ntdll: Implement LdrGetDllHandleEx() function.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b8d0118517
commit
cf0a828b02
|
@ -39,6 +39,9 @@ static BOOL (WINAPI *pK32GetModuleInformation)(HANDLE process, HMODULE module,
|
|||
|
||||
static NTSTATUS (WINAPI *pLdrGetDllDirectory)(UNICODE_STRING*);
|
||||
static NTSTATUS (WINAPI *pLdrSetDllDirectory)(UNICODE_STRING*);
|
||||
static NTSTATUS (WINAPI *pLdrGetDllHandle)( LPCWSTR load_path, ULONG flags, const UNICODE_STRING *name, HMODULE *base );
|
||||
static NTSTATUS (WINAPI *pLdrGetDllHandleEx)( ULONG flags, LPCWSTR load_path, ULONG *dll_characteristics,
|
||||
const UNICODE_STRING *name, HMODULE *base );
|
||||
|
||||
static BOOL is_unicode_enabled = TRUE;
|
||||
|
||||
|
@ -826,6 +829,8 @@ static void init_pointers(void)
|
|||
mod = GetModuleHandleA( "ntdll.dll" );
|
||||
MAKEFUNC(LdrGetDllDirectory);
|
||||
MAKEFUNC(LdrSetDllDirectory);
|
||||
MAKEFUNC(LdrGetDllHandle);
|
||||
MAKEFUNC(LdrGetDllHandleEx);
|
||||
#undef MAKEFUNC
|
||||
|
||||
/* before Windows 7 this was not exported in kernel32 */
|
||||
|
@ -1143,6 +1148,107 @@ static void test_SetDefaultDllDirectories(void)
|
|||
pSetDefaultDllDirectories( LOAD_LIBRARY_SEARCH_DEFAULT_DIRS );
|
||||
}
|
||||
|
||||
static void check_refcount( HMODULE mod, unsigned int refcount )
|
||||
{
|
||||
unsigned int i;
|
||||
BOOL ret;
|
||||
|
||||
for (i = 0; i < min( refcount, 10 ); ++i)
|
||||
{
|
||||
ret = FreeLibrary( mod );
|
||||
ok( ret || broken( refcount == ~0u && GetLastError() == ERROR_MOD_NOT_FOUND && i == 2 ) /* Win8 */,
|
||||
"Refcount test failed, i %u, error %u.\n", i, GetLastError() );
|
||||
if (!ret) return;
|
||||
}
|
||||
if (refcount != ~0u)
|
||||
{
|
||||
ret = FreeLibrary( mod );
|
||||
ok( !ret && GetLastError() == ERROR_MOD_NOT_FOUND, "Refcount test failed, ret %d, error %u.\n",
|
||||
ret, GetLastError() );
|
||||
}
|
||||
}
|
||||
|
||||
static void test_LdrGetDllHandleEx(void)
|
||||
{
|
||||
HMODULE mod, loaded_mod;
|
||||
UNICODE_STRING name;
|
||||
NTSTATUS status;
|
||||
unsigned int i;
|
||||
|
||||
if (!pLdrGetDllHandleEx)
|
||||
{
|
||||
win_skip( "LdrGetDllHandleEx is not available.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString( &name, L"unknown.dll" );
|
||||
status = pLdrGetDllHandleEx( 0, NULL, NULL, &name, &mod );
|
||||
ok( status == STATUS_DLL_NOT_FOUND, "Got unexpected status %#x.\n", status );
|
||||
|
||||
RtlInitUnicodeString( &name, L"authz.dll" );
|
||||
loaded_mod = LoadLibraryW( name.Buffer );
|
||||
ok( !!loaded_mod, "Failed to load module.\n" );
|
||||
status = pLdrGetDllHandleEx( 0, NULL, NULL, &name, &mod );
|
||||
ok( !status, "Got unexpected status %#x.\n", status );
|
||||
ok( mod == loaded_mod, "got %p\n", mod );
|
||||
winetest_push_context( "Flags 0" );
|
||||
check_refcount( loaded_mod, 2 );
|
||||
winetest_pop_context();
|
||||
|
||||
loaded_mod = LoadLibraryW( name.Buffer );
|
||||
ok( !!loaded_mod, "Failed to load module.\n" );
|
||||
status = pLdrGetDllHandleEx( LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, NULL,
|
||||
NULL, &name, &mod );
|
||||
ok( !status, "Got unexpected status %#x.\n", status );
|
||||
ok( mod == loaded_mod, "got %p\n", mod );
|
||||
winetest_push_context( "LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT" );
|
||||
check_refcount( loaded_mod, 1 );
|
||||
winetest_pop_context();
|
||||
|
||||
loaded_mod = LoadLibraryW( name.Buffer );
|
||||
ok( !!loaded_mod, "Failed to load module.\n" );
|
||||
status = pLdrGetDllHandle( NULL, ~0u, &name, &mod );
|
||||
ok( !status, "Got unexpected status %#x.\n", status );
|
||||
ok( mod == loaded_mod, "got %p\n", mod );
|
||||
winetest_push_context( "LdrGetDllHandle" );
|
||||
check_refcount( loaded_mod, 1 );
|
||||
winetest_pop_context();
|
||||
|
||||
loaded_mod = LoadLibraryW( name.Buffer );
|
||||
ok( !!loaded_mod, "Failed to load module.\n" );
|
||||
status = pLdrGetDllHandleEx( 4, NULL, NULL, (void *)&name, &mod );
|
||||
ok( !status, "Got unexpected status %#x.\n", status );
|
||||
ok( mod == loaded_mod, "got %p\n", mod );
|
||||
winetest_push_context( "Flag 4" );
|
||||
check_refcount( loaded_mod, 2 );
|
||||
winetest_pop_context();
|
||||
|
||||
for (i = 3; i < 32; ++i)
|
||||
{
|
||||
loaded_mod = LoadLibraryW( name.Buffer );
|
||||
ok( !!loaded_mod, "Failed to load module.\n" );
|
||||
status = pLdrGetDllHandleEx( 1 << i, NULL, NULL, &name, &mod );
|
||||
ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status );
|
||||
winetest_push_context( "Invalid flags, i %u", i );
|
||||
check_refcount( loaded_mod, 1 );
|
||||
winetest_pop_context();
|
||||
}
|
||||
|
||||
status = pLdrGetDllHandleEx( LDR_GET_DLL_HANDLE_EX_FLAG_PIN | LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
NULL, NULL, &name, &mod );
|
||||
ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status );
|
||||
|
||||
loaded_mod = LoadLibraryW( name.Buffer );
|
||||
ok( !!loaded_mod, "Failed to load module.\n" );
|
||||
status = pLdrGetDllHandleEx( LDR_GET_DLL_HANDLE_EX_FLAG_PIN, NULL,
|
||||
NULL, &name, &mod );
|
||||
ok( !status, "Got unexpected status %#x.\n", status );
|
||||
ok( mod == loaded_mod, "got %p\n", mod );
|
||||
winetest_push_context( "LDR_GET_DLL_HANDLE_EX_FLAG_PIN" );
|
||||
check_refcount( loaded_mod, ~0u );
|
||||
winetest_pop_context();
|
||||
}
|
||||
|
||||
START_TEST(module)
|
||||
{
|
||||
WCHAR filenameW[MAX_PATH];
|
||||
|
@ -1175,4 +1281,5 @@ START_TEST(module)
|
|||
testK32GetModuleInformation();
|
||||
test_AddDllDirectory();
|
||||
test_SetDefaultDllDirectories();
|
||||
test_LdrGetDllHandleEx();
|
||||
}
|
||||
|
|
|
@ -2996,16 +2996,33 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags,
|
|||
|
||||
|
||||
/******************************************************************
|
||||
* LdrGetDllHandle (NTDLL.@)
|
||||
* LdrGetDllHandleEx (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_STRING *name, HMODULE *base )
|
||||
NTSTATUS WINAPI LdrGetDllHandleEx( ULONG flags, LPCWSTR load_path, ULONG *dll_characteristics,
|
||||
const UNICODE_STRING *name, HMODULE *base )
|
||||
{
|
||||
NTSTATUS status;
|
||||
static const ULONG supported_flags = LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
|
||||
| LDR_GET_DLL_HANDLE_EX_FLAG_PIN;
|
||||
static const ULONG valid_flags = LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
|
||||
| LDR_GET_DLL_HANDLE_EX_FLAG_PIN | 4;
|
||||
SECTION_IMAGE_INFORMATION image_info;
|
||||
UNICODE_STRING nt_name;
|
||||
struct file_id id;
|
||||
NTSTATUS status;
|
||||
WINE_MODREF *wm;
|
||||
HANDLE mapping;
|
||||
SECTION_IMAGE_INFORMATION image_info;
|
||||
struct file_id id;
|
||||
|
||||
TRACE( "flag %#x, load_path %p, dll_characteristics %p, name %p, base %p.\n",
|
||||
flags, load_path, dll_characteristics, name, base );
|
||||
|
||||
if (flags & ~valid_flags) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if ((flags & (LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | LDR_GET_DLL_HANDLE_EX_FLAG_PIN))
|
||||
== (LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | LDR_GET_DLL_HANDLE_EX_FLAG_PIN))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (flags & ~supported_flags) FIXME( "Unsupported flags %#x.\n", flags );
|
||||
if (dll_characteristics) FIXME( "dll_characteristics unsupported.\n" );
|
||||
|
||||
RtlEnterCriticalSection( &loader_section );
|
||||
|
||||
|
@ -3019,12 +3036,29 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
|
|||
}
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (flags & LDR_GET_DLL_HANDLE_EX_FLAG_PIN)
|
||||
LdrAddRefDll( LDR_ADDREF_DLL_PIN, *base );
|
||||
else if (!(flags & LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))
|
||||
LdrAddRefDll( 0, *base );
|
||||
}
|
||||
|
||||
RtlLeaveCriticalSection( &loader_section );
|
||||
TRACE( "%s -> %p (load path %s)\n", debugstr_us(name), status ? NULL : *base, debugstr_w(load_path) );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* LdrGetDllHandle (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_STRING *name, HMODULE *base )
|
||||
{
|
||||
return LdrGetDllHandleEx( LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, load_path, NULL, name, base );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* LdrAddRefDll (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
@ stub LdrFlushAlternateResourceModules
|
||||
@ stdcall LdrGetDllDirectory(ptr)
|
||||
@ stdcall LdrGetDllHandle(wstr long ptr ptr)
|
||||
@ stdcall LdrGetDllHandleEx(long ptr ptr ptr ptr)
|
||||
# @ stub LdrGetDllHandleEx
|
||||
@ stdcall LdrGetDllPath(wstr long ptr ptr)
|
||||
@ stdcall LdrGetProcedureAddress(ptr ptr long ptr)
|
||||
|
|
|
@ -3380,6 +3380,10 @@ typedef void (CALLBACK *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG, LDR_DLL_NOTIFICAT
|
|||
/* flag for LdrAddRefDll */
|
||||
#define LDR_ADDREF_DLL_PIN 0x00000001
|
||||
|
||||
/* flags for LdrGetDllHandleEx */
|
||||
#define LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x00000001
|
||||
#define LDR_GET_DLL_HANDLE_EX_FLAG_PIN 0x00000002
|
||||
|
||||
#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
|
||||
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED 2
|
||||
|
||||
|
@ -3778,6 +3782,7 @@ NTSYSAPI NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE,const LDR_RESOURCE_
|
|||
NTSYSAPI NTSTATUS WINAPI LdrFindResource_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DATA_ENTRY**);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrGetDllDirectory(UNICODE_STRING*);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrGetDllHandleEx(ULONG, LPCWSTR, ULONG *, const UNICODE_STRING*, HMODULE*);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrGetDllPath(PCWSTR,ULONG,PWSTR*,PWSTR*);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, const ANSI_STRING*, ULONG, void**);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, const UNICODE_STRING*, HMODULE*);
|
||||
|
|
Loading…
Reference in New Issue