From eafb8e1b84a5ee717d5b0e22686303494fc5ccd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Fri, 3 Feb 2017 00:05:10 +0100 Subject: ntdll: Implement LdrEnumerateLoadedModules. --- dlls/ntdll/loader.c | 31 +++++++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/tests/rtl.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index c0703f008a7..15acf0e197d 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1523,6 +1523,37 @@ NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod) return STATUS_NO_MORE_ENTRIES; } +typedef void (WINAPI LDR_ENUM_CALLBACK)(LDR_MODULE*, void*, BOOLEAN*); + +/****************************************************************** + * LdrEnumerateLoadedModules (NTDLL.@) + */ +NTSTATUS WINAPI LdrEnumerateLoadedModules(void *unknown, LDR_ENUM_CALLBACK *callback, void *context) +{ + PLIST_ENTRY mark, entry; + PLDR_MODULE mod; + BOOLEAN stop = FALSE; + + TRACE("(%p, %p, %p)\n", unknown, callback, context); + + if (unknown || !callback) + return STATUS_INVALID_PARAMETER; + + RtlEnterCriticalSection( &loader_section ); + + mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList; + for (entry = mark->Flink; entry != mark; entry = entry->Flink) + { + mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList); + callback(mod, context, &stop); + if (stop) break; + } + + RtlLeaveCriticalSection( &loader_section ); + + return STATUS_SUCCESS; +} + /****************************************************************** * LdrLockLoaderLock (NTDLL.@) * diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 81767ede7d7..9921b4cb1cc 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -63,7 +63,7 @@ # @ stub LdrDestroyOutOfProcessImage @ stdcall LdrDisableThreadCalloutsForDll(long) @ stub LdrEnumResources -# @ stub LdrEnumerateLoadedModules +@ stdcall LdrEnumerateLoadedModules(ptr ptr ptr) # @ stub LdrFindCreateProcessManifest @ stdcall LdrFindEntryForAddress(ptr ptr) @ stdcall LdrFindResourceDirectory_U(long ptr long ptr) diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index d96ced64cb0..cfff3f5ec49 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -111,6 +111,7 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *); static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *); static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG); static NTSTATUS (WINAPI *pRtlQueryPackageIdentity)(HANDLE, WCHAR*, SIZE_T*, WCHAR*, SIZE_T*, BOOLEAN*); +static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void*, void*, void*); static HMODULE hkernel32 = 0; static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); @@ -173,6 +174,7 @@ static void InitFunctionPtrs(void) pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread"); pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); pRtlQueryPackageIdentity = (void *)GetProcAddress(hntdll, "RtlQueryPackageIdentity"); + pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules"); } hkernel32 = LoadLibraryA("kernel32.dll"); ok(hkernel32 != 0, "LoadLibrary failed\n"); @@ -3230,6 +3232,57 @@ done: CoUninitialize(); } +static BOOL enum_abort = FALSE; +static BOOL ntdll_found = FALSE; +static int module_count = 0; + +void WINAPI ldr_enum_callback(LDR_MODULE *module, void *context, BOOLEAN *stop) +{ + static const WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0}; + ok(context == (void *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", context); + + module_count++; + + if (!lstrcmpiW(module->BaseDllName.Buffer, ntdllW)) + ntdll_found = TRUE; + + *stop = enum_abort; +} + +static void test_LdrEnumerateLoadedModules(void) +{ + NTSTATUS status; + + if (!pLdrEnumerateLoadedModules) + { + win_skip("LdrEnumerateLoadedModules not available\n"); + return; + } + + enum_abort = FALSE; + ntdll_found = FALSE; + module_count = 0; + status = pLdrEnumerateLoadedModules(NULL, ldr_enum_callback, (void *)0xdeadbeef); + ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status); + ok(ntdll_found, "Could not find ntdll!\n"); + ok(module_count > 1, "Expected more than one module, got %d\n", module_count); + + enum_abort = TRUE; + module_count = 0; + status = pLdrEnumerateLoadedModules(NULL, ldr_enum_callback, (void *)0xdeadbeef); + ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status); + ok(module_count == 1, "Expected exactly one module, got %d\n", module_count); + + status = pLdrEnumerateLoadedModules((void *)0x1, ldr_enum_callback, (void *)0xdeadbeef); + ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status); + + status = pLdrEnumerateLoadedModules((void *)0xdeadbeef, ldr_enum_callback, (void *)0xdeadbeef); + ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status); + + status = pLdrEnumerateLoadedModules(NULL, NULL, (void *)0xdeadbeef); + ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -3267,4 +3320,5 @@ START_TEST(rtl) test_RtlIsCriticalSectionLocked(); test_RtlInitializeCriticalSectionEx(); test_RtlQueryPackageIdentity(); + test_LdrEnumerateLoadedModules(); } -- 2.11.0