Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
a014f413
Commit
a014f413
authored
Sep 21, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add support for loading a Unix helper library from builtin dlls.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
6d7037c9
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
224 additions
and
11 deletions
+224
-11
loader.c
dlls/ntdll/loader.c
+28
-3
ntdll.spec
dlls/ntdll/ntdll.spec
+3
-0
loader.c
dlls/ntdll/unix/loader.c
+131
-5
unixlib.h
dlls/ntdll/unixlib.h
+2
-2
Makefile.in
dlls/winecrt0/Makefile.in
+2
-1
unix_lib.c
dlls/winecrt0/unix_lib.c
+55
-0
winternl.h
include/winternl.h
+3
-0
No files found.
dlls/ntdll/loader.c
View file @
a014f413
...
...
@@ -128,6 +128,7 @@ typedef struct _wine_modref
{
LDR_DATA_TABLE_ENTRY
ldr
;
struct
file_id
id
;
void
*
unix_entry
;
int
alloc_deps
;
int
nDeps
;
struct
_wine_modref
**
deps
;
...
...
@@ -2356,7 +2357,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
{
const
WCHAR
*
name
,
*
p
;
NTSTATUS
status
;
void
*
module
=
NULL
;
void
*
module
=
NULL
,
*
unix_entry
=
NULL
;
SECTION_IMAGE_INFORMATION
image_info
;
/* Fix the name in case we have a full path and extension */
...
...
@@ -2368,7 +2369,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
if
(
!
module_ptr
)
module_ptr
=
&
module
;
status
=
unix_funcs
->
load_builtin_dll
(
name
,
module_ptr
,
&
image_info
);
status
=
unix_funcs
->
load_builtin_dll
(
name
,
module_ptr
,
&
unix_entry
,
&
image_info
);
if
(
status
)
return
status
;
if
((
*
pwm
=
get_modref
(
*
module_ptr
)))
/* already loaded */
...
...
@@ -2383,7 +2384,8 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
TRACE
(
"loading %s from %s
\n
"
,
debugstr_w
(
name
),
debugstr_us
(
nt_name
)
);
status
=
build_module
(
load_path
,
nt_name
,
module_ptr
,
&
image_info
,
NULL
,
flags
,
pwm
);
if
(
status
&&
*
module_ptr
)
unix_funcs
->
unload_builtin_dll
(
*
module_ptr
);
if
(
!
status
)
(
*
pwm
)
->
unix_entry
=
unix_entry
;
else
if
(
*
module_ptr
)
unix_funcs
->
unload_builtin_dll
(
*
module_ptr
);
return
status
;
}
...
...
@@ -2755,6 +2757,29 @@ done:
return
nts
;
}
/***********************************************************************
* __wine_init_unix_lib
*/
NTSTATUS
__cdecl
__wine_init_unix_lib
(
HMODULE
module
,
DWORD
reason
,
const
void
*
ptr_in
,
void
*
ptr_out
)
{
WINE_MODREF
*
wm
;
NTSTATUS
ret
=
STATUS_DLL_NOT_FOUND
;
RtlEnterCriticalSection
(
&
loader_section
);
if
((
wm
=
get_modref
(
module
)))
{
NTSTATUS
(
CDECL
*
init_func
)(
HMODULE
,
DWORD
,
const
void
*
,
void
*
)
=
wm
->
unix_entry
;
if
(
init_func
)
ret
=
init_func
(
module
,
reason
,
ptr_in
,
ptr_out
);
}
else
ret
=
STATUS_INVALID_HANDLE
;
RtlLeaveCriticalSection
(
&
loader_section
);
return
ret
;
}
/******************************************************************
* LdrLoadDll (NTDLL.@)
*/
...
...
dlls/ntdll/ntdll.spec
View file @
a014f413
...
...
@@ -1597,7 +1597,10 @@
@ cdecl -syscall wine_server_release_fd(long long)
@ cdecl -syscall wine_server_send_fd(long)
@ cdecl -syscall __wine_make_process_system()
# Unix interface
@ cdecl __wine_set_unix_funcs(long ptr)
@ cdecl __wine_init_unix_lib(long long ptr ptr)
@ extern __wine_syscall_dispatcher
@ extern -arch=i386 __wine_ldt_copy
...
...
dlls/ntdll/unix/loader.c
View file @
a014f413
...
...
@@ -123,6 +123,8 @@ const char *build_dir = NULL;
const
char
*
config_dir
=
NULL
;
const
char
**
dll_paths
=
NULL
;
const
char
*
user_name
=
NULL
;
static
HMODULE
ntdll_module
;
static
const
IMAGE_EXPORT_DIRECTORY
*
ntdll_exports
;
struct
file_id
{
...
...
@@ -136,6 +138,7 @@ struct builtin_module
struct
file_id
id
;
void
*
handle
;
void
*
module
;
void
*
unix_module
;
};
static
struct
list
builtin_modules
=
LIST_INIT
(
builtin_modules
);
...
...
@@ -146,6 +149,7 @@ static NTSTATUS add_builtin_module( void *module, void *handle, const struct sta
if
(
!
(
builtin
=
malloc
(
sizeof
(
*
builtin
)
)))
return
STATUS_NO_MEMORY
;
builtin
->
handle
=
handle
;
builtin
->
module
=
module
;
builtin
->
unix_module
=
NULL
;
if
(
st
)
{
builtin
->
id
.
dev
=
st
->
st_dev
;
...
...
@@ -782,11 +786,76 @@ static ULONG_PTR find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY
return
0
;
}
static
ULONG_PTR
find_pe_export
(
HMODULE
module
,
const
IMAGE_EXPORT_DIRECTORY
*
exports
,
const
IMAGE_IMPORT_BY_NAME
*
name
)
{
const
WORD
*
ordinals
=
(
const
WORD
*
)((
BYTE
*
)
module
+
exports
->
AddressOfNameOrdinals
);
const
DWORD
*
names
=
(
const
DWORD
*
)((
BYTE
*
)
module
+
exports
->
AddressOfNames
);
if
(
name
->
Hint
<
exports
->
NumberOfNames
)
{
char
*
ename
=
(
char
*
)
module
+
names
[
name
->
Hint
];
if
(
!
strcmp
(
ename
,
(
char
*
)
name
->
Name
))
return
find_ordinal_export
(
module
,
exports
,
ordinals
[
name
->
Hint
]
);
}
return
find_named_export
(
module
,
exports
,
(
char
*
)
name
->
Name
);
}
static
inline
void
*
get_rva
(
void
*
module
,
ULONG_PTR
addr
)
{
return
(
BYTE
*
)
module
+
addr
;
}
static
NTSTATUS
fixup_ntdll_imports
(
const
char
*
name
,
HMODULE
module
)
{
const
IMAGE_NT_HEADERS
*
nt
;
const
IMAGE_IMPORT_DESCRIPTOR
*
descr
;
const
IMAGE_THUNK_DATA
*
import_list
;
IMAGE_THUNK_DATA
*
thunk_list
;
nt
=
get_rva
(
module
,
((
IMAGE_DOS_HEADER
*
)
module
)
->
e_lfanew
);
descr
=
get_rva
(
module
,
nt
->
OptionalHeader
.
DataDirectory
[
IMAGE_FILE_IMPORT_DIRECTORY
].
VirtualAddress
);
for
(;
descr
->
Name
&&
descr
->
FirstThunk
;
descr
++
)
{
thunk_list
=
get_rva
(
module
,
descr
->
FirstThunk
);
/* ntdll must be the only import */
if
(
strcmp
(
get_rva
(
module
,
descr
->
Name
),
"ntdll.dll"
))
{
ERR
(
"module %s is importing %s
\n
"
,
debugstr_a
(
name
),
(
char
*
)
get_rva
(
module
,
descr
->
Name
));
return
STATUS_PROCEDURE_NOT_FOUND
;
}
if
(
descr
->
u
.
OriginalFirstThunk
)
import_list
=
get_rva
(
module
,
descr
->
u
.
OriginalFirstThunk
);
else
import_list
=
thunk_list
;
while
(
import_list
->
u1
.
Ordinal
)
{
if
(
IMAGE_SNAP_BY_ORDINAL
(
import_list
->
u1
.
Ordinal
))
{
int
ordinal
=
IMAGE_ORDINAL
(
import_list
->
u1
.
Ordinal
)
-
ntdll_exports
->
Base
;
thunk_list
->
u1
.
Function
=
find_ordinal_export
(
ntdll_module
,
ntdll_exports
,
ordinal
);
if
(
!
thunk_list
->
u1
.
Function
)
ERR
(
"%s: ntdll.%u not found
\n
"
,
debugstr_a
(
name
),
ordinal
);
}
else
/* import by name */
{
IMAGE_IMPORT_BY_NAME
*
pe_name
=
get_rva
(
module
,
import_list
->
u1
.
AddressOfData
);
thunk_list
->
u1
.
Function
=
find_pe_export
(
ntdll_module
,
ntdll_exports
,
pe_name
);
if
(
!
thunk_list
->
u1
.
Function
)
ERR
(
"%s: ntdll.%s not found
\n
"
,
debugstr_a
(
name
),
pe_name
->
Name
);
}
import_list
++
;
thunk_list
++
;
}
}
return
STATUS_SUCCESS
;
}
static
void
load_ntdll_functions
(
HMODULE
module
)
{
const
IMAGE_EXPORT_DIRECTORY
*
ntdll_exports
=
get_export_dir
(
module
);
void
**
ptr
;
ntdll_exports
=
get_export_dir
(
module
);
assert
(
ntdll_exports
);
#define GET_FUNC(name) \
...
...
@@ -927,6 +996,55 @@ already_loaded:
/***********************************************************************
* dlopen_unix_dll
*/
static
NTSTATUS
dlopen_unix_dll
(
void
*
module
,
const
char
*
name
,
void
**
unix_entry
)
{
struct
builtin_module
*
builtin
;
void
*
unix_module
,
*
handle
,
*
entry
;
const
IMAGE_NT_HEADERS
*
nt
;
NTSTATUS
status
=
STATUS_INVALID_IMAGE_FORMAT
;
handle
=
dlopen
(
name
,
RTLD_NOW
);
if
(
!
handle
)
return
STATUS_DLL_NOT_FOUND
;
if
(
!
(
nt
=
dlsym
(
handle
,
"__wine_spec_nt_header"
)))
goto
done
;
if
(
!
(
entry
=
dlsym
(
handle
,
"__wine_init_unix_lib"
)))
goto
done
;
unix_module
=
(
HMODULE
)((
nt
->
OptionalHeader
.
ImageBase
+
0xffff
)
&
~
0xffff
);
LIST_FOR_EACH_ENTRY
(
builtin
,
&
builtin_modules
,
struct
builtin_module
,
entry
)
{
if
(
builtin
->
module
==
module
)
{
if
(
builtin
->
unix_module
==
unix_module
)
/* already loaded */
{
status
=
STATUS_SUCCESS
;
goto
done
;
}
if
(
builtin
->
unix_module
)
{
ERR
(
"module %p already has a Unix module that's not %s
\n
"
,
module
,
debugstr_a
(
name
)
);
goto
done
;
}
if
((
status
=
map_so_dll
(
nt
,
unix_module
)))
goto
done
;
if
((
status
=
fixup_ntdll_imports
(
name
,
unix_module
)))
goto
done
;
builtin
->
unix_module
=
handle
;
*
unix_entry
=
entry
;
return
STATUS_SUCCESS
;
}
else
if
(
builtin
->
unix_module
==
unix_module
)
{
ERR
(
"%s already loaded for module %p
\n
"
,
debugstr_a
(
name
),
module
);
goto
done
;
}
}
ERR
(
"builtin module not found for %s
\n
"
,
debugstr_a
(
name
)
);
done:
dlclose
(
handle
);
return
status
;
}
/***********************************************************************
* load_so_dll
*/
static
NTSTATUS
CDECL
load_so_dll
(
UNICODE_STRING
*
nt_name
,
void
**
module
)
...
...
@@ -1136,11 +1254,11 @@ static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFO
/***********************************************************************
* load_builtin_dll
*/
static
NTSTATUS
CDECL
load_builtin_dll
(
const
WCHAR
*
name
,
void
**
module
,
static
NTSTATUS
CDECL
load_builtin_dll
(
const
WCHAR
*
name
,
void
**
module
,
void
**
unix_entry
,
SECTION_IMAGE_INFORMATION
*
image_info
)
{
unsigned
int
i
,
pos
,
len
,
namelen
,
maxlen
=
0
;
char
*
ptr
,
*
file
;
char
*
ptr
=
NULL
,
*
file
,
*
ext
=
NULL
;
NTSTATUS
status
=
STATUS_DLL_NOT_FOUND
;
BOOL
found_image
=
FALSE
;
...
...
@@ -1157,6 +1275,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module,
if
(
name
[
i
]
>
127
)
goto
done
;
file
[
pos
+
i
]
=
(
char
)
name
[
i
];
if
(
file
[
pos
+
i
]
>=
'A'
&&
file
[
pos
+
i
]
<=
'Z'
)
file
[
pos
+
i
]
+=
'a'
-
'A'
;
else
if
(
file
[
pos
+
i
]
==
'.'
)
ext
=
file
+
pos
+
i
;
}
file
[
--
pos
]
=
'/'
;
...
...
@@ -1166,7 +1285,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module,
ptr
=
file
+
pos
;
namelen
=
len
+
1
;
file
[
pos
+
len
+
1
]
=
0
;
if
(
namelen
>
4
&&
!
memcmp
(
ptr
+
namelen
-
4
,
".dll"
,
4
))
namelen
-=
4
;
if
(
ext
&&
!
strcmp
(
ext
,
".dll"
))
namelen
-=
4
;
ptr
=
prepend
(
ptr
,
ptr
,
namelen
);
ptr
=
prepend
(
ptr
,
"/dlls"
,
sizeof
(
"/dlls"
)
-
1
);
ptr
=
prepend
(
ptr
,
build_dir
,
strlen
(
build_dir
)
);
...
...
@@ -1177,7 +1296,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module,
ptr
=
file
+
pos
;
namelen
=
len
+
1
;
file
[
pos
+
len
+
1
]
=
0
;
if
(
namelen
>
4
&&
!
memcmp
(
ptr
+
namelen
-
4
,
".exe"
,
4
))
namelen
-=
4
;
if
(
ext
&&
!
strcmp
(
ext
,
".exe"
))
namelen
-=
4
;
ptr
=
prepend
(
ptr
,
ptr
,
namelen
);
ptr
=
prepend
(
ptr
,
"/programs"
,
sizeof
(
"/programs"
)
-
1
);
ptr
=
prepend
(
ptr
,
build_dir
,
strlen
(
build_dir
)
);
...
...
@@ -1198,6 +1317,11 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module,
WARN
(
"cannot find builtin library for %s
\n
"
,
debugstr_w
(
name
)
);
done:
if
(
!
status
&&
ext
)
{
strcpy
(
ext
,
".so"
);
dlopen_unix_dll
(
*
module
,
ptr
,
unix_entry
);
}
free
(
file
);
return
status
;
}
...
...
@@ -1215,6 +1339,7 @@ static NTSTATUS CDECL unload_builtin_dll( void *module )
if
(
builtin
->
module
!=
module
)
continue
;
list_remove
(
&
builtin
->
entry
);
if
(
builtin
->
handle
)
dlclose
(
builtin
->
handle
);
if
(
builtin
->
unix_module
)
dlclose
(
builtin
->
unix_module
);
free
(
builtin
);
return
STATUS_SUCCESS
;
}
...
...
@@ -1334,6 +1459,7 @@ static void load_ntdll(void)
if
(
status
)
fatal_error
(
"failed to load %s error %x
\n
"
,
name
,
status
);
free
(
name
);
load_ntdll_functions
(
module
);
ntdll_module
=
module
;
}
...
...
dlls/ntdll/unixlib.h
View file @
a014f413
...
...
@@ -27,7 +27,7 @@
struct
_DISPATCHER_CONTEXT
;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 10
4
#define NTDLL_UNIXLIB_VERSION 10
5
struct
unix_funcs
{
...
...
@@ -86,7 +86,7 @@ struct unix_funcs
/* loader functions */
NTSTATUS
(
CDECL
*
load_so_dll
)(
UNICODE_STRING
*
nt_name
,
void
**
module
);
NTSTATUS
(
CDECL
*
load_builtin_dll
)(
const
WCHAR
*
name
,
void
**
module
,
NTSTATUS
(
CDECL
*
load_builtin_dll
)(
const
WCHAR
*
name
,
void
**
module
,
void
**
unix_entry
,
SECTION_IMAGE_INFORMATION
*
image_info
);
NTSTATUS
(
CDECL
*
unload_builtin_dll
)(
void
*
module
);
void
(
CDECL
*
init_builtin_dll
)(
void
*
module
);
...
...
dlls/winecrt0/Makefile.in
View file @
a014f413
...
...
@@ -14,4 +14,5 @@ C_SRCS = \
exe_wmain.c
\
register.c
\
setjmp.c
\
stub.c
stub.c
\
unix_lib.c
dlls/winecrt0/unix_lib.c
0 → 100644
View file @
a014f413
/*
* Support for the Unix part of builtin dlls
*
* Copyright 2019 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef _WIN32
#include <stdarg.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
static
NTSTATUS
(
__cdecl
*
p__wine_init_unix_lib
)(
HMODULE
,
DWORD
,
const
void
*
,
void
*
);
static
void
load_func
(
void
**
func
,
const
char
*
name
,
void
*
def
)
{
if
(
!*
func
)
{
HMODULE
module
=
GetModuleHandleA
(
"ntdll.dll"
);
void
*
proc
=
GetProcAddress
(
module
,
name
);
InterlockedExchangePointer
(
func
,
proc
?
proc
:
def
);
}
}
#define LOAD_FUNC(name) load_func( (void **)&p ## name, #name, fallback ## name )
static
NTSTATUS
__cdecl
fallback__wine_init_unix_lib
(
HMODULE
module
,
DWORD
reason
,
const
void
*
ptr_in
,
void
*
ptr_out
)
{
return
STATUS_DLL_NOT_FOUND
;
}
NTSTATUS
__cdecl
__wine_init_unix_lib
(
HMODULE
module
,
DWORD
reason
,
const
void
*
ptr_in
,
void
*
ptr_out
)
{
LOAD_FUNC
(
__wine_init_unix_lib
);
return
p__wine_init_unix_lib
(
module
,
reason
,
ptr_in
,
ptr_out
);
}
#endif
/* _WIN32 */
include/winternl.h
View file @
a014f413
...
...
@@ -3756,6 +3756,9 @@ static inline PLIST_ENTRY RemoveTailList(PLIST_ENTRY le)
#ifdef __WINESRC__
/* Wine internal functions */
extern
NTSTATUS
CDECL
__wine_init_unix_lib
(
HMODULE
module
,
DWORD
reason
,
const
void
*
ptr_in
,
void
*
ptr_out
);
/* The thread information for 16-bit threads */
/* NtCurrentTeb()->SubSystemTib points to this */
typedef
struct
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment