Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- Documented at https://github.com/hfiref0x/NtCall64/blob/master/Source/NtCall64/ntos.h#L588... --- dlls/ntdll/tests/Makefile.in | 2 +- dlls/ntdll/tests/rtl.c | 64 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index ed15c51339..c7683c1522 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = ntdll.dll -IMPORTS = user32 advapi32 +IMPORTS = user32 advapi32 shlwapi
C_SRCS = \ atom.c \ diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 7a62670ea0..3588e00681 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -27,6 +27,7 @@ #include "in6addr.h" #include "inaddr.h" #include "ip2string.h" +#include "shlwapi.h"
#ifndef __WINE_WINTERNL_H
@@ -80,6 +81,7 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *); static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *); static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG); static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *); +static NTSTATUS (WINAPI *pLdrGetDllFullName)(HMODULE, PUNICODE_STRING); static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **); static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
@@ -120,6 +122,7 @@ static void InitFunctionPtrs(void) pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread"); pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules"); + pLdrGetDllFullName = (void *)GetProcAddress(hntdll, "LdrGetDllFullName"); pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification"); pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification"); } @@ -3483,6 +3486,66 @@ static void test_LdrRegisterDllNotification(void) pLdrUnregisterDllNotification(cookie); }
+static void test_LdrGetDllFullName(void) +{ + static const WCHAR ntdll_dll[] = {'n','t','d','l','l','.','d','l','l',0}; + static const WCHAR dot_exe[] = {'.','e','x','e',0}; + HMODULE ntdll = GetModuleHandleA("ntdll.dll"); + WCHAR ntdll_path[MAX_PATH], path_buffer[MAX_PATH]; + UNICODE_STRING path = {0, 0, path_buffer}; + WCHAR expected_terminator; + const WCHAR *extension; + NTSTATUS status; + + if (!pLdrGetDllFullName) + { + skip("LdrGetDllFullName not available\n"); + return; + } + + if (0) /* crashes on Windows */ + pLdrGetDllFullName(ntdll, NULL); + + memset(path_buffer, 0x23, sizeof(path_buffer)); + + status = pLdrGetDllFullName(ntdll, &path); + ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status); + ok(path.Length == 0, "Expected length 0, got %d\n", path.Length); + ok(path_buffer[0] == 0x2323, "Expected 0x2323, got 0x%x\n", path_buffer[0]); + + GetSystemDirectoryW(ntdll_path, ARRAY_SIZE(ntdll_path)); + path.MaximumLength = 5; /* odd numbers produce partially copied characters */ + + status = pLdrGetDllFullName(ntdll, &path); + ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status); + ok(path.Length == path.MaximumLength, + "Expected length %d, got %d\n", path.MaximumLength, path.Length); + expected_terminator = 0x2300 | (ntdll_path[path.MaximumLength / sizeof(WCHAR)] & 0xFF); + ok(path_buffer[path.MaximumLength / sizeof(WCHAR)] == expected_terminator, + "Expected 0x%x, got 0x%x\n", expected_terminator, path_buffer[path.MaximumLength / 2]); + path_buffer[path.MaximumLength / sizeof(WCHAR)] = 0; + ntdll_path[path.MaximumLength / sizeof(WCHAR)] = 0; + ok(lstrcmpW(path_buffer, ntdll_path) == 0, "Expected %s, got %s\n", + wine_dbgstr_w(ntdll_path), wine_dbgstr_w(path_buffer)); + + GetSystemDirectoryW(ntdll_path, ARRAY_SIZE(ntdll_path)); + PathAppendW(ntdll_path, ntdll_dll); + path.MaximumLength = sizeof(path_buffer); + + status = pLdrGetDllFullName(NULL, &path); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + extension = PathFindExtensionW(path_buffer); + ok(lstrcmpW(extension, dot_exe) == 0, "Expected %s, got %s\n", + wine_dbgstr_w(dot_exe), wine_dbgstr_w(extension)); + + status = pLdrGetDllFullName(ntdll, &path); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + ok(path.Length == lstrlenW(ntdll_path) * sizeof(WCHAR), "Expected length %d, got %d\n", + lstrlenW(ntdll_path) * sizeof(WCHAR), path.Length); + ok(lstrcmpiW(path_buffer, ntdll_path) == 0, "Expected %s, got %s\n", + wine_dbgstr_w(ntdll_path), wine_dbgstr_w(path_buffer)); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -3523,4 +3586,5 @@ START_TEST(rtl) test_LdrEnumerateLoadedModules(); test_RtlMakeSelfRelativeSD(); test_LdrRegisterDllNotification(); + test_LdrGetDllFullName(); }
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/loader.c | 25 +++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/tests/rtl.c | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 45d32399ad..63972f360f 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1713,6 +1713,31 @@ NTSTATUS WINAPI LdrEnumerateLoadedModules( void *unknown, LDRENUMPROC callback, return STATUS_SUCCESS; }
+/****************************************************************** + * LdrGetDllFullName (NTDLL.@) + */ +NTSTATUS WINAPI LdrGetDllFullName(HMODULE module, UNICODE_STRING *name) +{ + WINE_MODREF *wm; + + TRACE( "(%p, %p)\n", module, name ); + + if (!module) module = NtCurrentTeb()->Peb->ImageBaseAddress; + + RtlEnterCriticalSection( &loader_section ); + wm = get_modref( module ); + RtlLeaveCriticalSection( &loader_section ); + + if (!wm) return STATUS_DLL_NOT_FOUND; + + RtlCopyUnicodeString( name, &wm->ldr.FullDllName ); + + if (name->MaximumLength < wm->ldr.FullDllName.Length + sizeof(WCHAR)) + return STATUS_BUFFER_TOO_SMALL; + + return STATUS_SUCCESS; +} + /****************************************************************** * LdrRegisterDllNotification (NTDLL.@) */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 763d664a3b..ccdca4bd91 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -87,6 +87,7 @@ @ stdcall LdrFindResource_U(long ptr long ptr) @ stub LdrFlushAlternateResourceModules @ stdcall LdrGetDllDirectory(ptr) +@ stdcall LdrGetDllFullName(long ptr) @ stdcall LdrGetDllHandle(wstr long ptr ptr) # @ stub LdrGetDllHandleEx @ stdcall LdrGetDllPath(wstr long ptr ptr) diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 3588e00681..f3ed4100c1 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -3499,7 +3499,7 @@ static void test_LdrGetDllFullName(void)
if (!pLdrGetDllFullName) { - skip("LdrGetDllFullName not available\n"); + win_skip("LdrGetDllFullName not available\n"); return; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=73030
Your paranoid android.
=== debiant (32 bit Chinese:China report) ===
ntdll: om.c:2133: Test failed: got 87 om.c:2133: Test failed: got 87
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/loader.c | 2 ++ dlls/ntdll/tests/rtl.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 63972f360f..d1b71efc07 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1845,6 +1845,8 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, DWORD exp_size; NTSTATUS ret = STATUS_PROCEDURE_NOT_FOUND;
+ *address = NULL; + RtlEnterCriticalSection( &loader_section );
/* check if the module itself is invalid to return the proper error */ diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index f3ed4100c1..fb90de6785 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -82,6 +82,7 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG); static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *); static NTSTATUS (WINAPI *pLdrGetDllFullName)(HMODULE, PUNICODE_STRING); +static NTSTATUS (WINAPI *pLdrGetProcedureAddress)(HMODULE, PCANSI_STRING, WORD, void **); static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **); static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
@@ -123,6 +124,7 @@ static void InitFunctionPtrs(void) pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules"); pLdrGetDllFullName = (void *)GetProcAddress(hntdll, "LdrGetDllFullName"); + pLdrGetProcedureAddress = (void *)GetProcAddress(hntdll, "LdrGetProcedureAddress"); pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification"); pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification"); } @@ -3546,6 +3548,26 @@ static void test_LdrGetDllFullName(void) wine_dbgstr_w(ntdll_path), wine_dbgstr_w(path_buffer)); }
+static void test_LdrGetProcedureAddress(void) +{ + NTSTATUS status; + FARPROC fp; + + if (!pLdrGetProcedureAddress) + { + win_skip("LdrGetProcedureAddress not available\n"); + return; + } + + if (0) /* crashes on Windows */ + status = pLdrGetProcedureAddress(NULL, NULL, 0, NULL); + + fp = (FARPROC)0xdeadbeef; + status = pLdrGetProcedureAddress(NULL, NULL, 0, (void **)&fp); + ok(status == STATUS_DLL_NOT_FOUND, "Expected STATUS_DLL_NOT_FOUND, got %08x\n", status); + ok(!fp, "Expected NULL function pointer, got %p\n", fp); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -3587,4 +3609,5 @@ START_TEST(rtl) test_RtlMakeSelfRelativeSD(); test_LdrRegisterDllNotification(); test_LdrGetDllFullName(); + test_LdrGetProcedureAddress(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=73031
Your paranoid android.
=== wxppro (32 bit report) ===
ntdll: rtl.c:3567: Test failed: Expected STATUS_DLL_NOT_FOUND, got c000000d rtl.c:3568: Test failed: Expected NULL function pointer, got DEADBEEF
=== w2008s64 (32 bit report) ===
ntdll: rtl.c:3567: Test failed: Expected STATUS_DLL_NOT_FOUND, got c000000d rtl.c:3568: Test failed: Expected NULL function pointer, got DEADBEEF
=== w8 (32 bit report) ===
ntdll: rtl.c:3568: Test failed: Expected NULL function pointer, got DEADBEEF
=== w8adm (32 bit report) ===
ntdll: rtl.c:3568: Test failed: Expected NULL function pointer, got DEADBEEF
=== w2008s64 (64 bit report) ===
ntdll: rtl.c:3567: Test failed: Expected STATUS_DLL_NOT_FOUND, got c000000d rtl.c:3568: Test failed: Expected NULL function pointer, got 00000000DEADBEEF
=== w864 (64 bit report) ===
ntdll: rtl.c:3568: Test failed: Expected NULL function pointer, got 00000000DEADBEEF
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- This will help tremendously with debugging null pointer segfaults. --- dlls/ntdll/loader.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index d1b71efc07..2c37135105 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1865,6 +1865,17 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, }
RtlLeaveCriticalSection( &loader_section ); + + if (__WINE_GET_DEBUGGING_WARN( __wine_dbch___default ) && module && (name || ord) && !*address) + { + WCHAR path_buffer[MAX_PATH]; + UNICODE_STRING module_path = { 0, sizeof(path_buffer), path_buffer }; + path_buffer[0] = 0; + LdrGetDllFullName( module, &module_path ); + WARN( "function %s (ordinal %d) not found in module %s\n", + wine_dbgstr_a(name ? name->Buffer : NULL), ord, wine_dbgstr_w(path_buffer) ); + } + return ret; }
On 6/7/20 11:41 PM, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
This will help tremendously with debugging null pointer segfaults.
Seconded wholeheartedly. I've kept a similar patch in my local tree for quite a while.
Even worse, applications will detect that a function is missing but silently fail...
dlls/ntdll/loader.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index d1b71efc07..2c37135105 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1865,6 +1865,17 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, }
RtlLeaveCriticalSection( &loader_section );
- if (__WINE_GET_DEBUGGING_WARN( __wine_dbch___default ) && module && (name || ord) && !*address)
Why not just WARN_ON(module)?
Couldn't we just check for STATUS_PROCEDURE_NOT_FOUND? (I also wouldn't think it's worth checking that the parameters are valid.)
- {
WCHAR path_buffer[MAX_PATH];
UNICODE_STRING module_path = { 0, sizeof(path_buffer), path_buffer };
path_buffer[0] = 0;
LdrGetDllFullName( module, &module_path );
WARN( "function %s (ordinal %d) not found in module %s\n",
wine_dbgstr_a(name ? name->Buffer : NULL), ord, wine_dbgstr_w(path_buffer) );
As long as we're calling get_modref() in this function anyway, if we're concerned about printing the module name, I think it makes sense to just access the WINE_MODREF directly. That way you wouldn't have to possibly truncate the buffer (not that it probably matters).
- }
}return ret;
On Sun, Jun 7, 2020 at 11:17 PM Zebediah Figura z.figura12@gmail.com wrote:
On 6/7/20 11:41 PM, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
This will help tremendously with debugging null pointer segfaults.
Seconded wholeheartedly. I've kept a similar patch in my local tree for quite a while.
Even worse, applications will detect that a function is missing but silently fail...
Glad you approve!
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index d1b71efc07..2c37135105 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1865,6 +1865,17 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, }
RtlLeaveCriticalSection( &loader_section );
- if (__WINE_GET_DEBUGGING_WARN( __wine_dbch___default ) && module && (name || ord) && !*address)
Why not just WARN_ON(module)?
I didn't know that you could do that. Thanks for the tip!
Couldn't we just check for STATUS_PROCEDURE_NOT_FOUND? (I also wouldn't think it's worth checking that the parameters are valid.)
Yes, I realized after I sent v1 that the function should be checking ret instead of address. I put in some argument checks because I didn't want to see noise from this function when the failure is not a bug in Wine. Do you see any strong reason to drop the argument checks?
- {
WCHAR path_buffer[MAX_PATH];
UNICODE_STRING module_path = { 0, sizeof(path_buffer), path_buffer };
path_buffer[0] = 0;
LdrGetDllFullName( module, &module_path );
WARN( "function %s (ordinal %d) not found in module %s\n",
wine_dbgstr_a(name ? name->Buffer : NULL), ord, wine_dbgstr_w(path_buffer) );
As long as we're calling get_modref() in this function anyway, if we're concerned about printing the module name, I think it makes sense to just access the WINE_MODREF directly. That way you wouldn't have to possibly truncate the buffer (not that it probably matters).
You're right, I really didn't need to use LdrGetDllFullName. I will send a new patch that does not depend on it.
-Alex
On 6/8/20 5:59 PM, Alex Henrie wrote:
On Sun, Jun 7, 2020 at 11:17 PM Zebediah Figura z.figura12@gmail.com wrote:
On 6/7/20 11:41 PM, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
This will help tremendously with debugging null pointer segfaults.
Seconded wholeheartedly. I've kept a similar patch in my local tree for quite a while.
Even worse, applications will detect that a function is missing but silently fail...
Glad you approve!
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index d1b71efc07..2c37135105 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1865,6 +1865,17 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, }
RtlLeaveCriticalSection( &loader_section );
- if (__WINE_GET_DEBUGGING_WARN( __wine_dbch___default ) && module && (name || ord) && !*address)
Why not just WARN_ON(module)?
I didn't know that you could do that. Thanks for the tip!
Couldn't we just check for STATUS_PROCEDURE_NOT_FOUND? (I also wouldn't think it's worth checking that the parameters are valid.)
Yes, I realized after I sent v1 that the function should be checking ret instead of address. I put in some argument checks because I didn't want to see noise from this function when the failure is not a bug in Wine. Do you see any strong reason to drop the argument checks?
Mostly because I don't expect much of said noise, but I don't feel strongly about it.
- {
WCHAR path_buffer[MAX_PATH];
UNICODE_STRING module_path = { 0, sizeof(path_buffer), path_buffer };
path_buffer[0] = 0;
LdrGetDllFullName( module, &module_path );
WARN( "function %s (ordinal %d) not found in module %s\n",
wine_dbgstr_a(name ? name->Buffer : NULL), ord, wine_dbgstr_w(path_buffer) );
As long as we're calling get_modref() in this function anyway, if we're concerned about printing the module name, I think it makes sense to just access the WINE_MODREF directly. That way you wouldn't have to possibly truncate the buffer (not that it probably matters).
You're right, I really didn't need to use LdrGetDllFullName. I will send a new patch that does not depend on it.
-Alex
On 6/7/20 11:41 PM, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
Documented at https://github.com/hfiref0x/NtCall64/blob/master/Source/NtCall64/ntos.h#L588...
dlls/ntdll/tests/Makefile.in | 2 +- dlls/ntdll/tests/rtl.c | 64 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index ed15c51339..c7683c1522 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = ntdll.dll -IMPORTS = user32 advapi32 +IMPORTS = user32 advapi32 shlwapi
C_SRCS = \ atom.c \ diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 7a62670ea0..3588e00681 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -27,6 +27,7 @@ #include "in6addr.h" #include "inaddr.h" #include "ip2string.h" +#include "shlwapi.h"
#ifndef __WINE_WINTERNL_H
@@ -80,6 +81,7 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *); static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *); static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG); static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *); +static NTSTATUS (WINAPI *pLdrGetDllFullName)(HMODULE, PUNICODE_STRING); static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **); static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
@@ -120,6 +122,7 @@ static void InitFunctionPtrs(void) pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread"); pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules");
pLdrGetDllFullName = (void *)GetProcAddress(hntdll, "LdrGetDllFullName"); pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification"); pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification"); }
@@ -3483,6 +3486,66 @@ static void test_LdrRegisterDllNotification(void) pLdrUnregisterDllNotification(cookie); }
+static void test_LdrGetDllFullName(void) +{
- static const WCHAR ntdll_dll[] = {'n','t','d','l','l','.','d','l','l',0};
- static const WCHAR dot_exe[] = {'.','e','x','e',0};
These could be inline wide-string constants.
- HMODULE ntdll = GetModuleHandleA("ntdll.dll");
- WCHAR ntdll_path[MAX_PATH], path_buffer[MAX_PATH];
- UNICODE_STRING path = {0, 0, path_buffer};
- WCHAR expected_terminator;
- const WCHAR *extension;
- NTSTATUS status;
- if (!pLdrGetDllFullName)
- {
skip("LdrGetDllFullName not available\n");
return;
- }
- if (0) /* crashes on Windows */
pLdrGetDllFullName(ntdll, NULL);
- memset(path_buffer, 0x23, sizeof(path_buffer));
- status = pLdrGetDllFullName(ntdll, &path);
- ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status);
- ok(path.Length == 0, "Expected length 0, got %d\n", path.Length);
- ok(path_buffer[0] == 0x2323, "Expected 0x2323, got 0x%x\n", path_buffer[0]);
- GetSystemDirectoryW(ntdll_path, ARRAY_SIZE(ntdll_path));
- path.MaximumLength = 5; /* odd numbers produce partially copied characters */
- status = pLdrGetDllFullName(ntdll, &path);
- ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status);
- ok(path.Length == path.MaximumLength,
"Expected length %d, got %d\n", path.MaximumLength, path.Length);
- expected_terminator = 0x2300 | (ntdll_path[path.MaximumLength / sizeof(WCHAR)] & 0xFF);
- ok(path_buffer[path.MaximumLength / sizeof(WCHAR)] == expected_terminator,
"Expected 0x%x, got 0x%x\n", expected_terminator, path_buffer[path.MaximumLength / 2]);
- path_buffer[path.MaximumLength / sizeof(WCHAR)] = 0;
- ntdll_path[path.MaximumLength / sizeof(WCHAR)] = 0;
- ok(lstrcmpW(path_buffer, ntdll_path) == 0, "Expected %s, got %s\n",
wine_dbgstr_w(ntdll_path), wine_dbgstr_w(path_buffer));
Maybe it'd be simpler to do something like
memset(expect, 0x23, sizeof(expect)); memcpy(expect, ntdll_path, 5); ok(!memcmp(path_buffer, expect, sizeof(path_buffer)), ...);
Feels a bit easier to me; just a suggestion.
- GetSystemDirectoryW(ntdll_path, ARRAY_SIZE(ntdll_path));
- PathAppendW(ntdll_path, ntdll_dll);
- path.MaximumLength = sizeof(path_buffer);
- status = pLdrGetDllFullName(NULL, &path);
- ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
- extension = PathFindExtensionW(path_buffer);
- ok(lstrcmpW(extension, dot_exe) == 0, "Expected %s, got %s\n",
wine_dbgstr_w(dot_exe), wine_dbgstr_w(extension));
- status = pLdrGetDllFullName(ntdll, &path);
- ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
- ok(path.Length == lstrlenW(ntdll_path) * sizeof(WCHAR), "Expected length %d, got %d\n",
lstrlenW(ntdll_path) * sizeof(WCHAR), path.Length);
- ok(lstrcmpiW(path_buffer, ntdll_path) == 0, "Expected %s, got %s\n",
wine_dbgstr_w(ntdll_path), wine_dbgstr_w(path_buffer));
+}
- START_TEST(rtl) { InitFunctionPtrs();
@@ -3523,4 +3586,5 @@ START_TEST(rtl) test_LdrEnumerateLoadedModules(); test_RtlMakeSelfRelativeSD(); test_LdrRegisterDllNotification();
- test_LdrGetDllFullName(); }
Alex Henrie alexhenrie24@gmail.com wrote:
-IMPORTS = user32 advapi32 +IMPORTS = user32 advapi32 shlwapi
What is this for? If for PathAppendW() then it's exported from kernelbase.
On Sun, Jun 7, 2020 at 11:10 PM Dmitry Timoshkov dmitry@baikal.ru wrote:
Alex Henrie alexhenrie24@gmail.com wrote:
-IMPORTS = user32 advapi32 +IMPORTS = user32 advapi32 shlwapi
What is this for? If for PathAppendW() then it's exported from kernelbase.
I'm pretty sure that I can't import kernelbase because it's not present on Windows XP. So instead I'm importing PathAppendW's old home, shlwapi, which simply forwards to kernelbase on newer versions of Windows.
-Alex