From f1c20bd8484df2a458bdbf2a8e900df0c84d6aa0 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Thu, 12 Jan 2006 04:31:37 +0000 Subject: [PATCH] implemented GetModuleHandleExA/W(), LdrAddRefDll() and RtlPcToFileHeader() (untested) svn path=/trunk/; revision=20802 --- reactos/include/ndk/ldrtypes.h | 5 ++ reactos/include/ndk/umfuncs.h | 15 ++++ reactos/lib/kernel32/misc/ldr.c | 123 ++++++++++++++++++++++++++++++ reactos/lib/kernel32/misc/stubs.c | 34 --------- reactos/lib/ntdll/def/ntdll.def | 3 +- reactos/lib/ntdll/ldr/utils.c | 85 ++++++++++++++++++++- 6 files changed, 228 insertions(+), 37 deletions(-) diff --git a/reactos/include/ndk/ldrtypes.h b/reactos/include/ndk/ldrtypes.h index 17fde0939c6..9d60d20cc6e 100644 --- a/reactos/include/ndk/ldrtypes.h +++ b/reactos/include/ndk/ldrtypes.h @@ -106,4 +106,9 @@ typedef struct _LDR_RESOURCE_INFO ULONG Language; } LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO; +// +// LdrAddRef Flags +// +#define LDR_PIN_MODULE 0x00000001 + #endif diff --git a/reactos/include/ndk/umfuncs.h b/reactos/include/ndk/umfuncs.h index eaea78351eb..477c75f6835 100644 --- a/reactos/include/ndk/umfuncs.h +++ b/reactos/include/ndk/umfuncs.h @@ -161,6 +161,14 @@ DbgUiIssueRemoteBreakin( // // Loader Functions // + +NTSTATUS +NTAPI +LdrAddRefDll( + IN ULONG Flags, + IN PVOID BaseAddress +); + NTSTATUS NTAPI LdrDisableThreadCalloutsForDll( @@ -210,6 +218,13 @@ LdrLoadDll( OUT PVOID *BaseAddress OPTIONAL ); +PVOID +NTAPI +RtlPcToFileHeader( + IN PVOID PcValue, + PVOID* BaseOfImage +); + PIMAGE_BASE_RELOCATION NTAPI LdrProcessRelocationBlock( diff --git a/reactos/lib/kernel32/misc/ldr.c b/reactos/lib/kernel32/misc/ldr.c index 671321d321f..c8dcf3ee847 100644 --- a/reactos/lib/kernel32/misc/ldr.c +++ b/reactos/lib/kernel32/misc/ldr.c @@ -480,6 +480,129 @@ GetModuleHandleW (LPCWSTR lpModuleName) } +/* + * @implemented + */ +BOOL +STDCALL +GetModuleHandleExW(IN DWORD dwFlags, + IN LPCWSTR lpModuleName OPTIONAL, + OUT HMODULE* phModule) +{ + HMODULE hModule; + NTSTATUS Status; + BOOL Ret = FALSE; + + if (phModule == NULL || + ((dwFlags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) == + (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (lpModuleName == NULL) + { + hModule = NtCurrentPeb()->ImageBaseAddress; + } + else + { + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) + { + hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpModuleName, + (PVOID*)&hModule); + if (hModule == NULL) + { + SetLastErrorByStatus(STATUS_DLL_NOT_FOUND); + } + } + else + { + hModule = GetModuleHandleW(lpModuleName); + } + } + + if (hModule != NULL) + { + if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) + { + Status = LdrAddRefDll((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0, + hModule); + + if (NT_SUCCESS(Status)) + { + Ret = TRUE; + } + else + { + SetLastErrorByStatus(Status); + hModule = NULL; + } + } + else + Ret = TRUE; + } + + *phModule = hModule; + return Ret; +} + +/* + * @implemented + */ +BOOL +STDCALL +GetModuleHandleExA(IN DWORD dwFlags, + IN LPCSTR lpModuleName OPTIONAL, + OUT HMODULE* phModule) +{ + UNICODE_STRING UnicodeName; + ANSI_STRING ModuleName; + LPCWSTR lpModuleNameW; + NTSTATUS Status; + BOOL Ret; + + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) + { + lpModuleNameW = (LPCWSTR)lpModuleName; + } + else + { + RtlInitAnsiString(&ModuleName, + (LPSTR)lpModuleName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + Status = RtlAnsiStringToUnicodeString(&UnicodeName, + &ModuleName, + TRUE); + else + Status = RtlOemStringToUnicodeString(&UnicodeName, + &ModuleName, + TRUE); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + lpModuleNameW = UnicodeName.Buffer; + } + + Ret = GetModuleHandleExW(dwFlags, + lpModuleNameW, + phModule); + + if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) + { + RtlFreeUnicodeString(&UnicodeName); + } + + return Ret; +} + + /* * @implemented */ diff --git a/reactos/lib/kernel32/misc/stubs.c b/reactos/lib/kernel32/misc/stubs.c index 360bc512dcf..ba17227f322 100644 --- a/reactos/lib/kernel32/misc/stubs.c +++ b/reactos/lib/kernel32/misc/stubs.c @@ -1087,23 +1087,6 @@ GetFirmwareEnvironmentVariableW( return 0; } - - -/* - * @unimplemented - */ -BOOL -STDCALL -GetModuleHandleExW( - DWORD dwFlags, - LPCWSTR lpModuleName, - HMODULE* phModule - ) -{ - STUB; - return 0; -} - /* * @unimplemented */ @@ -1286,23 +1269,6 @@ GetFirmwareEnvironmentVariableA( return 0; } - - -/* - * @unimplemented - */ -BOOL -STDCALL -GetModuleHandleExA( - DWORD dwFlags, - LPCSTR lpModuleName, - HMODULE* phModule - ) -{ - STUB; - return 0; -} - /* * @unimplemented */ diff --git a/reactos/lib/ntdll/def/ntdll.def b/reactos/lib/ntdll/def/ntdll.def index 8b042ea0bd7..ef3b141a8bb 100644 --- a/reactos/lib/ntdll/def/ntdll.def +++ b/reactos/lib/ntdll/def/ntdll.def @@ -35,6 +35,7 @@ KiUserApcDispatcher@16 KiUserCallbackDispatcher@12 KiUserExceptionDispatcher@8 LdrAccessResource@16 +LdrAddRefDll@8 LdrDisableThreadCalloutsForDll@4 LdrEnumResources@20 LdrFindEntryForAddress@8 @@ -576,7 +577,7 @@ RtlOemStringToUnicodeSize@4=RtlxOemStringToUnicodeSize@4 RtlOemStringToUnicodeString@12 RtlOemToUnicodeN@20 RtlOpenCurrentUser@8 -;RtlPcToFileHeader +RtlPcToFileHeader@8 RtlPinAtomInAtomTable@8 RtlPrefixString@12 RtlPrefixUnicodeString@12 diff --git a/reactos/lib/ntdll/ldr/utils.c b/reactos/lib/ntdll/ldr/utils.c index 76cabd31c33..f0ece8e6775 100644 --- a/reactos/lib/ntdll/ldr/utils.c +++ b/reactos/lib/ntdll/ldr/utils.c @@ -2135,7 +2135,7 @@ LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module, { /* ?????????????????? */ } - else if (LoadCount == 1) + else if (!(Module->Flags & LDRP_STATIC_LINK) && LoadCount == 1) { BoundImportDescriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR) RtlImageDirectoryEntryToData(Module->DllBase, @@ -2207,7 +2207,11 @@ LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module, if (Unload) { - LdrpDetachProcess(FALSE); + if (!(Module->Flags & LDRP_STATIC_LINK)) + { + LdrpDetachProcess(FALSE); + } + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); } return STATUS_SUCCESS; @@ -2316,6 +2320,83 @@ LdrGetDllHandle(IN PWSTR DllPath OPTIONAL, return STATUS_DLL_NOT_FOUND; } +/* + * @implemented + */ +NTSTATUS NTAPI +LdrAddRefDll(IN ULONG Flags, + IN PVOID BaseAddress) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_DATA_TABLE_ENTRY Module; + NTSTATUS Status; + + if (Flags & ~(LDR_PIN_MODULE)) + { + return STATUS_INVALID_PARAMETER; + } + + Status = STATUS_DLL_NOT_FOUND; + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList); + + if (Module->DllBase == BaseAddress) + { + if (Flags & LDR_PIN_MODULE) + { + Module->Flags |= LDRP_STATIC_LINK; + } + else + { + LdrpIncrementLoadCount(Module, + FALSE); + } + Status = STATUS_SUCCESS; + break; + } + Entry = Entry->Flink; + } + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); + return Status; +} + +/* + * @implemented + */ +PVOID NTAPI +RtlPcToFileHeader(IN PVOID PcValue, + PVOID* BaseOfImage) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_DATA_TABLE_ENTRY Module; + PVOID ImageBase = NULL; + + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList); + + if ((ULONG_PTR)PcValue >= (ULONG_PTR)Module->DllBase && + (ULONG_PTR)PcValue < (ULONG_PTR)Module->DllBase + Module->SizeOfImage) + { + ImageBase = Module->DllBase; + break; + } + Entry = Entry->Flink; + } + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); + + *BaseOfImage = ImageBase; + return ImageBase; +} /* * @implemented