From 8648ea02e1c8be4c8496eca4157c61bd4adfbf40 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Fri, 23 Feb 2007 07:56:01 +0000 Subject: [PATCH] - Get rid of LdrGetModuleObject, since MmLoadSystemImage will now return the existing module object in case it has already been loaded, get rid of LdrGetProcedureAddress, it doesn't belong in the kernel. Move MmGetSystemRoutineAddress from mm.c to sysldr.c and rewrite it to use MiFindExportedRoutineByName instead. - Remove /ldr ntoskrnl directory, since this module is finally gone. - Make PsInit code search for ntdll lookups using LookupEntryPoint internal function, instead of LdrGetProcedureAddress. Same code but done with recursion instead, and internal to this module (remove ANSI_STRINGs since we don't need them anymore). svn path=/trunk/; revision=25886 --- reactos/ntoskrnl/include/internal/ldr.h | 4 - reactos/ntoskrnl/io/iomgr/driver.c | 59 ++-------- reactos/ntoskrnl/kdbg/kdb_symbols.c | 2 +- reactos/ntoskrnl/ldr/loader.c | 136 ---------------------- reactos/ntoskrnl/ldr/rtl.c | 107 ----------------- reactos/ntoskrnl/mm/mm.c | 64 ----------- reactos/ntoskrnl/mm/pagefile.c | 14 ++- reactos/ntoskrnl/mm/sysldr.c | 145 ++++++++++++++++++++++++ reactos/ntoskrnl/ntoskrnl.rbuild | 4 - reactos/ntoskrnl/ps/psmgr.c | 123 ++++++++++++++++---- 10 files changed, 269 insertions(+), 389 deletions(-) delete mode 100644 reactos/ntoskrnl/ldr/loader.c delete mode 100644 reactos/ntoskrnl/ldr/rtl.c diff --git a/reactos/ntoskrnl/include/internal/ldr.h b/reactos/ntoskrnl/include/internal/ldr.h index 882bc2dea22..98988135237 100644 --- a/reactos/ntoskrnl/include/internal/ldr.h +++ b/reactos/ntoskrnl/include/internal/ldr.h @@ -6,8 +6,4 @@ #define DRIVER_ROOT_NAME L"\\Driver\\" #define FILESYSTEM_ROOT_NAME L"\\FileSystem\\" -PLDR_DATA_TABLE_ENTRY -NTAPI -LdrGetModuleObject(PUNICODE_STRING ModuleName); - #endif /* __INCLUDE_INTERNAL_LDR_H */ diff --git a/reactos/ntoskrnl/io/iomgr/driver.c b/reactos/ntoskrnl/io/iomgr/driver.c index 74c3c6a413a..055a7cf0f1c 100644 --- a/reactos/ntoskrnl/io/iomgr/driver.c +++ b/reactos/ntoskrnl/io/iomgr/driver.c @@ -435,34 +435,20 @@ IopLoadServiceModule( return Status; } - /* - * Load the module. - */ - - *ModuleObject = LdrGetModuleObject(&ServiceImagePath); - - if (*ModuleObject == NULL) - { /* * Case for disabled drivers */ - if (ServiceStart >= 4) - { - /* FIXME: Check if it is the right status code */ - Status = STATUS_PLUGPLAY_NO_DEVICE; - } - else - { - DPRINT("Loading module\n"); - Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, NULL); - } - } - else - { - DPRINT("Module already loaded\n"); - Status = STATUS_IMAGE_ALREADY_LOADED; - } + if (ServiceStart >= 4) + { + /* FIXME: Check if it is the right status code */ + Status = STATUS_PLUGPLAY_NO_DEVICE; + } + else + { + DPRINT("Loading module\n"); + Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, NULL); + } ExFreePool(ServiceImagePath.Buffer); @@ -1062,7 +1048,6 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) UNICODE_STRING ServiceName; UNICODE_STRING ObjectName; PDRIVER_OBJECT DriverObject; - PLDR_DATA_TABLE_ENTRY ModuleObject; NTSTATUS Status; LPWSTR Start; @@ -1145,16 +1130,6 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) return Status; } - /* - * ... and check if it's loaded - */ - - ModuleObject = LdrGetModuleObject(&ImagePath); - if (ModuleObject == NULL) - { - return STATUS_UNSUCCESSFUL; - } - /* * Free the service path */ @@ -1169,7 +1144,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) (*DriverObject->DriverUnload)(DriverObject); ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject); - MmUnloadSystemImage(ModuleObject); + MmUnloadSystemImage(DriverObject->DriverSection); return STATUS_SUCCESS; } @@ -1692,18 +1667,6 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) DPRINT("FullImagePath: '%wZ'\n", &ImagePath); DPRINT("Type: %lx\n", Type); - /* - * See, if the driver module isn't already loaded - */ - - ModuleObject = LdrGetModuleObject(&ImagePath); - if (ModuleObject != NULL) - { - DPRINT("Image already loaded\n"); - Status = STATUS_IMAGE_ALREADY_LOADED; - goto ReleaseCapturedString; - } - /* * Create device node */ diff --git a/reactos/ntoskrnl/kdbg/kdb_symbols.c b/reactos/ntoskrnl/kdbg/kdb_symbols.c index 3b96b9630d7..b57fed0a405 100644 --- a/reactos/ntoskrnl/kdbg/kdb_symbols.c +++ b/reactos/ntoskrnl/kdbg/kdb_symbols.c @@ -608,7 +608,7 @@ KdbSymProcessBootSymbols(IN PUNICODE_STRING FileName) IsRaw = FALSE; } - ModuleObject = LdrGetModuleObject(ModuleName); + ModuleObject = NULL; if (ModuleObject != NULL) { diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c deleted file mode 100644 index 8eb33e45da5..00000000000 --- a/reactos/ntoskrnl/ldr/loader.c +++ /dev/null @@ -1,136 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ldr/loader.c - * PURPOSE: Loaders for PE executables - * - * PROGRAMMERS: Jean Michault - * Rex Jolliff (rex@lvcablemodem.com) - * Jason Filby (jasonfilby@yahoo.com) - * Casper S. Hornstrup (chorns@users.sourceforge.net) - */ - - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -static LONG -LdrpCompareModuleNames ( - IN PUNICODE_STRING String1, - IN PUNICODE_STRING String2 ) -{ - ULONG len1, len2, i; - PWCHAR s1, s2, p; - WCHAR c1, c2; - - if (String1 && String2) - { - /* Search String1 for last path component */ - len1 = String1->Length / sizeof(WCHAR); - s1 = String1->Buffer; - for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++) - { - if (*p == L'\\') - { - if (i == String1->Length - sizeof(WCHAR)) - { - s1 = NULL; - len1 = 0; - } - else - { - s1 = p + 1; - len1 = (String1->Length - i) / sizeof(WCHAR); - } - } - } - - /* Search String2 for last path component */ - len2 = String2->Length / sizeof(WCHAR); - s2 = String2->Buffer; - for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++) - { - if (*p == L'\\') - { - if (i == String2->Length - sizeof(WCHAR)) - { - s2 = NULL; - len2 = 0; - } - else - { - s2 = p + 1; - len2 = (String2->Length - i) / sizeof(WCHAR); - } - } - } - - /* Compare last path components */ - if (s1 && s2) - { - while (1) - { - c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0; - c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0; - if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0)) - return(0); - if (!c1 || !c2 || c1 != c2) - return(c1 - c2); - } - } - } - - return(0); -} - -extern KSPIN_LOCK PsLoadedModuleSpinLock; - -// -// Used for checking if a module is already in the module list. -// Used during loading/unloading drivers. -// -PLDR_DATA_TABLE_ENTRY -NTAPI -LdrGetModuleObject ( PUNICODE_STRING ModuleName ) -{ - PLDR_DATA_TABLE_ENTRY Module; - PLIST_ENTRY Entry; - KIRQL Irql; - - DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName); - - KeAcquireSpinLock(&PsLoadedModuleSpinLock,&Irql); - - Entry = PsLoadedModuleList.Flink; - while (Entry != &PsLoadedModuleList) - { - Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - DPRINT("Comparing %wZ and %wZ\n", - &Module->BaseDllName, - ModuleName); - - if (!LdrpCompareModuleNames(&Module->BaseDllName, ModuleName)) - { - DPRINT("Module %wZ\n", &Module->BaseDllName); - KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql); - return(Module); - } - - Entry = Entry->Flink; - } - - KeReleaseSpinLock(&PsLoadedModuleSpinLock, Irql); - - DPRINT("Could not find module '%wZ'\n", ModuleName); - - return(NULL); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/ldr/rtl.c b/reactos/ntoskrnl/ldr/rtl.c deleted file mode 100644 index 8e8ff37d5db..00000000000 --- a/reactos/ntoskrnl/ldr/rtl.c +++ /dev/null @@ -1,107 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ldr/rtl.c - * PURPOSE: Loader utilities - * - * PROGRAMMERS: Jean Michault - * Rex Jolliff (rex@lvcablemodem.com) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -NTSTATUS STDCALL -LdrGetProcedureAddress (IN PVOID BaseAddress, - IN PANSI_STRING Name, - IN ULONG Ordinal, - OUT PVOID *ProcedureAddress) -{ - PIMAGE_EXPORT_DIRECTORY ExportDir; - ULONG ExportDirSize = 0; - PUSHORT OrdinalPtr; - PULONG NamePtr; - PCHAR CurrentNamePtr; - PULONG AddressPtr; - - if (ProcedureAddress == NULL) - return STATUS_INVALID_PARAMETER; - - /* get the pointer to the export directory */ - ExportDir = RtlImageDirectoryEntryToData(BaseAddress, TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportDirSize); - - if (ExportDir == NULL || ExportDirSize == 0) - return STATUS_INVALID_PARAMETER; - - AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions); - - if (Name && Name->Length) - { - LONG minn, maxn, mid, res; - - /* Search for export by name */ - - /* - * NOTE: Exports are always sorted and so we can apply binary search. - * Also the function names are _case sensitive_, so respect that. - * -- Filip Navara, August 1st, 2005 - */ - - /* - * I don't know who wrote this code but it's not working. - * Test case: KiFastSystemCall and KiFastSystemCallRet in ntdll. - * Former can't be found even though it's exported. - */ - - OrdinalPtr = (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); - NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames); - - minn = 0; maxn = ExportDir->NumberOfNames - 1; - while (minn <= maxn) - { - mid = (minn + maxn) / 2; - CurrentNamePtr = (PCHAR)RVA(BaseAddress, NamePtr[mid]); - res = strcmp(CurrentNamePtr, Name->Buffer); - if (res == 0) - { - /* - * Check if the beginning of the name matched, but it's still - * not the whole name. - */ - *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]); - return STATUS_SUCCESS; - } - if (res > 0) - maxn = mid - 1; - else - minn = mid + 1; - } - - CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name); - } - else - { - /* Search for export by ordinal */ - - Ordinal &= 0x0000FFFF; - if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) - { - *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[Ordinal - ExportDir->Base]); - return STATUS_SUCCESS; - } - - CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal); - } - - return STATUS_PROCEDURE_NOT_FOUND; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index cd333002731..0711646f4fd 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -398,70 +398,6 @@ MmSetAddressRangeModified ( return (FALSE); } -/* - * @implemented - */ -PVOID -NTAPI -MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName) -{ - PVOID ProcAddress; - ANSI_STRING AnsiRoutineName; - NTSTATUS Status; - PLIST_ENTRY NextEntry; - extern LIST_ENTRY PsLoadedModuleList; - PLDR_DATA_TABLE_ENTRY LdrEntry; - BOOLEAN Found = FALSE; - UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); - UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll"); - - /* Convert routine to ansi name */ - Status = RtlUnicodeStringToAnsiString(&AnsiRoutineName, - SystemRoutineName, - TRUE); - if (!NT_SUCCESS(Status)) return NULL; - - /* Loop the loaded module list */ - NextEntry = PsLoadedModuleList.Flink; - while (NextEntry != &PsLoadedModuleList) - { - /* Get the entry */ - LdrEntry = CONTAINING_RECORD(NextEntry, - LDR_DATA_TABLE_ENTRY, - InLoadOrderLinks); - - /* Check if it's the kernel or HAL */ - if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE)) - { - /* Found it */ - Found = TRUE; - } - else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE)) - { - /* Found it */ - Found = TRUE; - } - - /* Check if we found a valid binary */ - if (Found) - { - /* Find the procedure name */ - Status = LdrGetProcedureAddress(LdrEntry->DllBase, - &AnsiRoutineName, - 0, - &ProcAddress); - break; - } - - /* Keep looping */ - NextEntry = NextEntry->Flink; - } - - /* Free the string and return */ - RtlFreeAnsiString(&AnsiRoutineName); - return (NT_SUCCESS(Status) ? ProcAddress : NULL); -} - NTSTATUS NTAPI NtGetWriteWatch(IN HANDLE ProcessHandle, diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index 3b5fed1dc03..15c60ed000c 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -35,6 +35,10 @@ #pragma alloc_text(INIT, MmInitPagingFile) #endif +PVOID +NTAPI +MiFindExportedRoutineByName(IN PVOID DllBase, + IN PANSI_STRING ExportName); /* TYPES *********************************************************************/ @@ -694,7 +698,7 @@ MmInitializeCrashDump(HANDLE PageFileHandle, ULONG PageFileNum) UNICODE_STRING DiskDumpName = RTL_CONSTANT_STRING(L"DiskDump"); ANSI_STRING ProcName; PIO_STACK_LOCATION StackPtr; - PLDR_DATA_TABLE_ENTRY ModuleObject; + PLDR_DATA_TABLE_ENTRY ModuleObject = NULL; Status = ZwFsControlFile(PageFileHandle, 0, @@ -767,16 +771,14 @@ MmInitializeCrashDump(HANDLE PageFileHandle, ULONG PageFileNum) } /* Load the diskdump driver. */ - ModuleObject = LdrGetModuleObject(&DiskDumpName); + Status = MmLoadSystemImage(&DiskDumpName, NULL, NULL, 0, (PVOID)&ModuleObject, NULL); if (ModuleObject == NULL) { return(STATUS_OBJECT_NAME_NOT_FOUND); } RtlInitAnsiString(&ProcName, "DiskDumpFunctions"); - Status = LdrGetProcedureAddress(ModuleObject->DllBase, - &ProcName, - 0, - (PVOID*)&MmCoreDumpFunctions); + MmCoreDumpFunctions = MiFindExportedRoutineByName(ModuleObject->DllBase, + &ProcName); if (!NT_SUCCESS(Status)) { ObDereferenceObject(PageFile); diff --git a/reactos/ntoskrnl/mm/sysldr.c b/reactos/ntoskrnl/mm/sysldr.c index d6c2de723f0..cb4660e4bad 100644 --- a/reactos/ntoskrnl/mm/sysldr.c +++ b/reactos/ntoskrnl/mm/sysldr.c @@ -56,6 +56,77 @@ MiClearImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry) ExFreePool(LdrEntry->LoadedImports); } +PVOID +NTAPI +MiFindExportedRoutineByName(IN PVOID DllBase, + IN PANSI_STRING ExportName) +{ + PULONG NameTable; + PUSHORT OrdinalTable; + PIMAGE_EXPORT_DIRECTORY ExportDirectory; + LONG Low = 0, Mid = 0, High, Ret; + USHORT Ordinal; + PVOID Function; + ULONG ExportSize; + PULONG ExportTable; + PAGED_CODE(); + + /* Get the export directory */ + ExportDirectory = RtlImageDirectoryEntryToData(DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + if (!ExportDirectory) return NULL; + + /* Setup name tables */ + NameTable = (PULONG)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfNames); + OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfNameOrdinals); + + /* Do a binary search */ + High = ExportDirectory->NumberOfNames - 1; + while (High >= Low) + { + /* Get new middle value */ + Mid = (Low + High) >> 1; + + /* Compare name */ + Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]); + if (Ret < 0) + { + /* Update high */ + High = Mid - 1; + } + else if (Ret > 0) + { + /* Update low */ + Low = Mid + 1; + } + else + { + /* We got it */ + break; + } + } + + /* Check if we couldn't find it */ + if (High < Low) return NULL; + + /* Otherwise, this is the ordinal */ + Ordinal = OrdinalTable[Mid]; + + /* Resolve the address and write it */ + ExportTable = (PULONG)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfFunctions); + Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]); + + /* We found it! */ + ASSERT((Function > (PVOID)ExportDirectory) && + (Function < (PVOID)((ULONG_PTR)ExportDirectory + ExportSize))); + return Function; +} + PVOID NTAPI MiLocateExportName(IN PVOID DllBase, @@ -1712,3 +1783,77 @@ Quickie: return Status; } +/* + * @implemented + */ +PVOID +NTAPI +MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName) +{ + PVOID ProcAddress = NULL; + ANSI_STRING AnsiRoutineName; + NTSTATUS Status; + PLIST_ENTRY NextEntry; + extern LIST_ENTRY PsLoadedModuleList; + PLDR_DATA_TABLE_ENTRY LdrEntry; + BOOLEAN Found = FALSE; + UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); + UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll"); + ULONG Modules = 0; + + /* Convert routine to ansi name */ + Status = RtlUnicodeStringToAnsiString(&AnsiRoutineName, + SystemRoutineName, + TRUE); + if (!NT_SUCCESS(Status)) return NULL; + + /* Lock the list */ + KeEnterCriticalRegion(); + + /* Loop the loaded module list */ + NextEntry = PsLoadedModuleList.Flink; + while (NextEntry != &PsLoadedModuleList) + { + /* Get the entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* Check if it's the kernel or HAL */ + if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE)) + { + /* Found it */ + Found = TRUE; + Modules++; + } + else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE)) + { + /* Found it */ + Found = TRUE; + Modules++; + } + + /* Check if we found a valid binary */ + if (Found) + { + /* Find the procedure name */ + ProcAddress = MiFindExportedRoutineByName(LdrEntry->DllBase, + &AnsiRoutineName); + + /* Break out if we found it or if we already tried both modules */ + if (ProcAddress) break; + if (Modules == 2) break; + } + + /* Keep looping */ + NextEntry = NextEntry->Flink; + } + + /* Release the lock */ + KeLeaveCriticalRegion(); + + /* Free the string and return */ + RtlFreeAnsiString(&AnsiRoutineName); + return ProcAddress; +} + diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 60891077471..fa8309aca10 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -227,10 +227,6 @@ kdio.c kdmain.c - - loader.c - rtl.c - close.c complete.c diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index 7567844784a..50c8ac6ef81 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -38,15 +38,6 @@ PVOID PspSystemDllBase; PVOID PspSystemDllSection; PVOID PspSystemDllEntryPoint; -ANSI_STRING ThunkName = RTL_CONSTANT_STRING("LdrInitializeThunk"); -ANSI_STRING ApcName = RTL_CONSTANT_STRING("KiUserApcDispatcher"); -ANSI_STRING ExceptName = RTL_CONSTANT_STRING("KiUserExceptionDispatcher"); -ANSI_STRING CallbackName = RTL_CONSTANT_STRING("KiUserCallbackDispatcher"); -ANSI_STRING RaiseName = RTL_CONSTANT_STRING("KiRaiseUserExceptionDispatcher"); -ANSI_STRING FastName = RTL_CONSTANT_STRING("KiFastSystemCall"); -ANSI_STRING FastReturnName = RTL_CONSTANT_STRING("KiFastSystemCallRet"); -ANSI_STRING InterruptName = RTL_CONSTANT_STRING("KiIntSystemCall"); - UNICODE_STRING PsNtDllPathName = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntdll.dll"); @@ -67,13 +58,106 @@ BOOLEAN PspDoingGiveBacks; /* PRIVATE FUNCTIONS *********************************************************/ +ULONG +NTAPI +NameToOrdinal(IN PCHAR Name, + IN PVOID DllBase, + IN ULONG NumberOfNames, + IN PULONG NameTable, + IN PUSHORT OrdinalTable) +{ + ULONG Mid; + LONG Ret; + + /* Fail if no names */ + if (!NumberOfNames) return -1; + + /* Do binary search */ + Mid = NumberOfNames >> 1; + Ret = strcmp(Name, (PCHAR)((ULONG_PTR)DllBase + NameTable[Mid])); + + /* Check if we found it */ + if (!Ret) return OrdinalTable[Mid]; + + /* We didn't. Check if we only had one name to check */ + if (NumberOfNames == 1) return -1; + + /* Check if we should look up or down */ + if (Ret < 0) + { + /* Loop down */ + NumberOfNames = Mid; + } + else + { + /* Look up, update tables */ + NameTable = &NameTable[Mid + 1]; + OrdinalTable = &OrdinalTable[Mid + 1]; + NumberOfNames -= (Mid - 1); + } + + /* Call us recursively */ + return NameToOrdinal(Name, DllBase, NumberOfNames, NameTable, OrdinalTable); +} + NTSTATUS NTAPI -PspLookupSystemDllEntryPoint(IN PANSI_STRING Name, +LookupEntryPoint(IN PVOID DllBase, + IN PCHAR Name, + OUT PVOID *EntryPoint) +{ + PULONG NameTable; + PUSHORT OrdinalTable; + PIMAGE_EXPORT_DIRECTORY ExportDirectory; + ULONG ExportSize; + CHAR Buffer[64]; + USHORT Ordinal; + PULONG ExportTable; + + /* Get the export directory */ + ExportDirectory = RtlImageDirectoryEntryToData(DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + + /* Validate the name and copy it */ + if (strlen(Name) > sizeof(Buffer) - 2) return STATUS_INVALID_PARAMETER; + strcpy(Buffer, Name); + + /* Setup name tables */ + NameTable = (PULONG)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfNames); + OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfNameOrdinals); + + /* Get the ordinal */ + Ordinal = NameToOrdinal(Buffer, + DllBase, + ExportDirectory->NumberOfNames, + NameTable, + OrdinalTable); + + /* Make sure the ordinal is valid */ + if (Ordinal >= ExportDirectory->NumberOfFunctions) + { + /* It's not, fail */ + return STATUS_PROCEDURE_NOT_FOUND; + } + + /* Resolve the address and write it */ + ExportTable = (PULONG)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfFunctions); + *EntryPoint = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +PspLookupSystemDllEntryPoint(IN PCHAR Name, IN PVOID *EntryPoint) { /* Call the LDR Routine */ - return LdrGetProcedureAddress(PspSystemDllBase, Name, 0, EntryPoint); + return LookupEntryPoint(PspSystemDllBase, Name, EntryPoint); } NTSTATUS @@ -83,22 +167,22 @@ PspLookupKernelUserEntryPoints(VOID) NTSTATUS Status; /* Get user-mode APC trampoline */ - Status = PspLookupSystemDllEntryPoint(&ApcName, + Status = PspLookupSystemDllEntryPoint("KiUserApcDispatcher", &KeUserApcDispatcher); if (!NT_SUCCESS(Status)) return Status; /* Get user-mode exception dispatcher */ - Status = PspLookupSystemDllEntryPoint(&ExceptName, + Status = PspLookupSystemDllEntryPoint("KiUserExceptionDispatcher", &KeUserExceptionDispatcher); if (!NT_SUCCESS(Status)) return Status; /* Get user-mode callback dispatcher */ - Status = PspLookupSystemDllEntryPoint(&CallbackName, + Status = PspLookupSystemDllEntryPoint("KiUserCallbackDispatcher", &KeUserCallbackDispatcher); if (!NT_SUCCESS(Status)) return Status; /* Get user-mode exception raise trampoline */ - Status = PspLookupSystemDllEntryPoint(&RaiseName, + Status = PspLookupSystemDllEntryPoint("KiRaiseUserExceptionDispatcher", &KeRaiseUserExceptionDispatcher); if (!NT_SUCCESS(Status)) return Status; @@ -106,20 +190,20 @@ PspLookupKernelUserEntryPoints(VOID) if (KeFeatureBits & KF_FAST_SYSCALL) { /* Get user-mode sysenter stub */ - Status = PspLookupSystemDllEntryPoint(&FastName, + Status = PspLookupSystemDllEntryPoint("KiFastSystemCall", (PVOID)&SharedUserData-> SystemCall); if (!NT_SUCCESS(Status)) return Status; /* Get user-mode sysenter return stub */ - Status = PspLookupSystemDllEntryPoint(&FastReturnName, + Status = PspLookupSystemDllEntryPoint("KiFastSystemCallRet", (PVOID)&SharedUserData-> SystemCallReturn); } else { /* Get the user-mode interrupt stub */ - Status = PspLookupSystemDllEntryPoint(&InterruptName, + Status = PspLookupSystemDllEntryPoint("KiIntSystemCall", (PVOID)&SharedUserData-> SystemCall); } @@ -250,7 +334,8 @@ PspInitializeSystemDll(VOID) NTSTATUS Status; /* Get user-mode startup thunk */ - Status = PspLookupSystemDllEntryPoint(&ThunkName, &PspSystemDllEntryPoint); + Status = PspLookupSystemDllEntryPoint("LdrInitializeThunk", + &PspSystemDllEntryPoint); if (!NT_SUCCESS(Status)) { /* Failed, bugcheck */