diff --git a/reactos/include/ddk/ntifs.h b/reactos/include/ddk/ntifs.h index 9cc7e7874e2..7acf7d6dd0a 100644 --- a/reactos/include/ddk/ntifs.h +++ b/reactos/include/ddk/ntifs.h @@ -3813,6 +3813,14 @@ RtlAllocateHeap ( IN ULONG Size ); +NTSYSAPI +NTSTATUS +NTAPI +RtlAppendStringToString( + PSTRING Destination, + const STRING *Source +); + NTSYSAPI USHORT NTAPI diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index 850733ad6ac..0131a0af187 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -248,6 +248,8 @@ typedef struct _ADAPTER_OBJECT *PADAPTER_OBJECT; #define MAXIMUM_SUSPEND_COUNT MAXCHAR +#define MAXIMUM_FILENAME_LENGTH 256 + #define FILE_SUPERSEDED 0x00000000 #define FILE_OPENED 0x00000001 #define FILE_CREATED 0x00000002 diff --git a/reactos/include/ndk/ldrtypes.h b/reactos/include/ndk/ldrtypes.h index c1a742affe7..f4447d67957 100644 --- a/reactos/include/ndk/ldrtypes.h +++ b/reactos/include/ndk/ldrtypes.h @@ -118,6 +118,15 @@ typedef struct _LDR_DATA_TABLE_ENTRY PVOID PatchInformation; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; +// +// Loaded Imports Reference Counting in Kernel +// +typedef struct _LOAD_IMPORTS +{ + SIZE_T Count; + PLDR_DATA_TABLE_ENTRY Entry[1]; +} LOAD_IMPORTS, *PLOAD_IMPORTS; + // // Loader Resource Information // diff --git a/reactos/include/psdk/winnt.h b/reactos/include/psdk/winnt.h index 885a17602f8..ca07265a98f 100644 --- a/reactos/include/psdk/winnt.h +++ b/reactos/include/psdk/winnt.h @@ -3119,21 +3119,21 @@ typedef struct _IMAGE_IMPORT_BY_NAME { } IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; typedef struct _IMAGE_THUNK_DATA { union { - PBYTE ForwarderString; - PDWORD Function; + ULONG ForwarderString; + ULONG Function; DWORD Ordinal; - PIMAGE_IMPORT_BY_NAME AddressOfData; + ULONG AddressOfData; } u1; } IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA; typedef struct _IMAGE_IMPORT_DESCRIPTOR { _ANONYMOUS_UNION union { DWORD Characteristics; - PIMAGE_THUNK_DATA OriginalFirstThunk; + ULONG OriginalFirstThunk; } DUMMYUNIONNAME; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; - PIMAGE_THUNK_DATA FirstThunk; + ULONG FirstThunk; } IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR { DWORD TimeDateStamp; diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index 2c4978b0f4b..ab6f5da2f75 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -952,8 +952,8 @@ QSI_DEF(SystemCallTimeInformation) /* Class 11 - Module Information */ QSI_DEF(SystemModuleInformation) { - extern LIST_ENTRY ModuleListHead; - return ExpQueryModuleInformation(&ModuleListHead, + extern LIST_ENTRY PsLoadedModuleList; + return ExpQueryModuleInformation(&PsLoadedModuleList, NULL, (PRTL_PROCESS_MODULES)Buffer, Size, diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 79c7f7a9936..2a73841267b 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -384,7 +384,7 @@ extern GENERIC_MAPPING PspJobMapping; extern POBJECT_TYPE PsJobType; extern LARGE_INTEGER ShortPsLockDelay; extern UNICODE_STRING PsNtDllPathName; -extern LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY]; +extern LIST_ENTRY PsLoadedModuleList; // // Inlined Functions diff --git a/reactos/ntoskrnl/kdbg/kdb_symbols.c b/reactos/ntoskrnl/kdbg/kdb_symbols.c index 75d4701611b..3b96b9630d7 100644 --- a/reactos/ntoskrnl/kdbg/kdb_symbols.c +++ b/reactos/ntoskrnl/kdbg/kdb_symbols.c @@ -107,13 +107,12 @@ KdbpSymFindModule(IN PVOID Address OPTIONAL, { PLIST_ENTRY current_entry; PLDR_DATA_TABLE_ENTRY current; - extern LIST_ENTRY ModuleListHead; INT Count = 0; INT Length; - current_entry = ModuleListHead.Flink; + current_entry = PsLoadedModuleList.Flink; - while (current_entry != &ModuleListHead) + while (current_entry != &PsLoadedModuleList) { current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index bd51f6c86d3..5f9fb21544f 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -37,15 +37,15 @@ KiRosPrintAddress(PVOID address) { PLIST_ENTRY current_entry; PLDR_DATA_TABLE_ENTRY current; - extern LIST_ENTRY ModuleListHead; + extern LIST_ENTRY PsLoadedModuleList; ULONG_PTR RelativeAddress; ULONG i = 0; do { - current_entry = ModuleListHead.Flink; + current_entry = PsLoadedModuleList.Flink; - while (current_entry != &ModuleListHead) + while (current_entry != &PsLoadedModuleList) { current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, @@ -267,13 +267,13 @@ KiPcToFileHeader(IN PVOID Eip, PVOID ImageBase, EipBase = NULL; PLDR_DATA_TABLE_ENTRY Entry; PLIST_ENTRY ListHead, NextEntry; - extern LIST_ENTRY ModuleListHead; + extern LIST_ENTRY PsLoadedModuleList; /* Assume no */ *InKernel = FALSE; /* Set list pointers and make sure it's valid */ - ListHead = &ModuleListHead; + ListHead = &PsLoadedModuleList; NextEntry = ListHead->Flink; if (NextEntry) { diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index b5dc048b375..5e505472273 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -20,44 +20,21 @@ /* GLOBALS *******************************************************************/ -LIST_ENTRY ModuleListHead; +LIST_ENTRY PsLoadedModuleList; KSPIN_LOCK ModuleListLock; LDR_DATA_TABLE_ENTRY NtoskrnlModuleObject; LDR_DATA_TABLE_ENTRY HalModuleObject; /* FUNCTIONS *****************************************************************/ -static PVOID -LdrPEGetExportByName ( - PVOID BaseAddress, - PUCHAR SymbolName, - USHORT Hint ); - -static VOID -LdrpBuildModuleBaseName ( - PUNICODE_STRING BaseName, - PUNICODE_STRING FullName ) -{ - PWCHAR p; - - DPRINT("LdrpBuildModuleBaseName()\n"); - DPRINT("FullName %wZ\n", FullName); - - p = wcsrchr(FullName->Buffer, L'\\'); - if (p == NULL) - { - p = FullName->Buffer; - } - else - { - p++; - } - - DPRINT("p %S\n", p); - - RtlInitUnicodeString(BaseName, p); -} - +NTSTATUS +NTAPI +MiResolveImageReferences(IN PVOID ImageBase, + IN PUNICODE_STRING ImageFileDirectory, + IN PUNICODE_STRING NamePrefix OPTIONAL, + OUT PCHAR *MissingApi, + OUT PWCHAR *MissingDriver, + OUT PLOAD_IMPORTS *LoadImports); static LONG LdrpCompareModuleNames ( @@ -128,380 +105,128 @@ LdrpCompareModuleNames ( return(0); } -#ifndef PATH_MAX -#define PATH_MAX 260 -#endif - -static NTSTATUS -LdrPEGetOrLoadModule ( - PWCHAR ModuleName, - PCHAR ImportedName, - PLDR_DATA_TABLE_ENTRY* ImportedModule) +VOID +INIT_FUNCTION +NTAPI +LdrInit1(VOID) { - UNICODE_STRING DriverName; - UNICODE_STRING NameString; - WCHAR NameBuffer[PATH_MAX]; - NTSTATUS Status = STATUS_SUCCESS; + PLDR_DATA_TABLE_ENTRY HalModuleObject, NtoskrnlModuleObject, LdrEntry; - RtlCreateUnicodeStringFromAsciiz (&DriverName, ImportedName); - DPRINT("Import module: %wZ\n", &DriverName); + /* Initialize the module list and spinlock */ + InitializeListHead(&PsLoadedModuleList); + KeInitializeSpinLock(&ModuleListLock); - *ImportedModule = LdrGetModuleObject(&DriverName); - if (*ImportedModule == NULL) - { - PWCHAR PathEnd; - ULONG PathLength; + /* Get the NTOSKRNL Entry from the loader */ + LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - PathEnd = wcsrchr(ModuleName, L'\\'); - if (NULL != PathEnd) - { - PathLength = (PathEnd - ModuleName + 1) * sizeof(WCHAR); - RtlCopyMemory(NameBuffer, ModuleName, PathLength); - RtlCopyMemory(NameBuffer + (PathLength / sizeof(WCHAR)), DriverName.Buffer, DriverName.Length); - NameString.Buffer = NameBuffer; - NameString.MaximumLength = NameString.Length = (USHORT)PathLength + DriverName.Length; + /* Initialize ModuleObject for NTOSKRNL */ + NtoskrnlModuleObject = ExAllocatePoolWithTag(PagedPool, + sizeof(LDR_DATA_TABLE_ENTRY), + TAG('M', 'm', 'L', 'd')); + NtoskrnlModuleObject->DllBase = LdrEntry->DllBase; + RtlInitUnicodeString(&NtoskrnlModuleObject->FullDllName, KERNEL_MODULE_NAME); + NtoskrnlModuleObject->BaseDllName = NtoskrnlModuleObject->FullDllName; + NtoskrnlModuleObject->EntryPoint = LdrEntry->EntryPoint; + NtoskrnlModuleObject->SizeOfImage = LdrEntry->SizeOfImage; - /* NULL-terminate */ - NameString.MaximumLength += sizeof(WCHAR); - NameBuffer[NameString.Length / sizeof(WCHAR)] = 0; + /* Insert it into the list */ + InsertTailList(&PsLoadedModuleList, &NtoskrnlModuleObject->InLoadOrderLinks); - Status = LdrLoadModule(&NameString, ImportedModule); - } - else - { - DPRINT("Module '%wZ' not loaded yet\n", &DriverName); - wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\"); - wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR)); - RtlInitUnicodeString(&NameString, NameBuffer); - Status = LdrLoadModule(&NameString, ImportedModule); - } - if (!NT_SUCCESS(Status)) - { - wcscpy(NameBuffer, L"\\SystemRoot\\system32\\"); - wcsncat(NameBuffer, DriverName.Buffer, DriverName.Length / sizeof(WCHAR)); - RtlInitUnicodeString(&NameString, NameBuffer); - Status = LdrLoadModule(&NameString, ImportedModule); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Unknown import module: %wZ (Status %lx)\n", &DriverName, Status); - } - } - } - RtlFreeUnicodeString(&DriverName); - return Status; + /* Get the HAL Entry from the loader */ + LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + + /* Initialize ModuleObject for HAL */ + HalModuleObject = ExAllocatePoolWithTag(PagedPool, + sizeof(LDR_DATA_TABLE_ENTRY), + TAG('M', 'm', 'L', 'd')); + HalModuleObject->DllBase = LdrEntry->DllBase; + RtlInitUnicodeString(&HalModuleObject->FullDllName, HAL_MODULE_NAME); + HalModuleObject->BaseDllName = HalModuleObject->FullDllName; + HalModuleObject->EntryPoint = LdrEntry->EntryPoint; + HalModuleObject->SizeOfImage = LdrEntry->SizeOfImage; + + /* Insert it into the list */ + InsertTailList(&PsLoadedModuleList, &HalModuleObject->InLoadOrderLinks); + + /* Hook for KDB on initialization of the loader. */ + KDB_LOADERINIT_HOOK(NtoskrnlModuleObject, HalModuleObject); } -static PVOID -LdrPEFixupForward ( PCHAR ForwardName ) +// +// 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 ) { - CHAR NameBuffer[128]; - UNICODE_STRING ModuleName; - PCHAR p; - PLDR_DATA_TABLE_ENTRY ModuleObject; + PLDR_DATA_TABLE_ENTRY Module; + PLIST_ENTRY Entry; + KIRQL Irql; - DPRINT("LdrPEFixupForward (%s)\n", ForwardName); + DPRINT("LdrGetModuleObject(%wZ) called\n", ModuleName); - strcpy(NameBuffer, ForwardName); - p = strchr(NameBuffer, '.'); - if (p == NULL) + KeAcquireSpinLock(&ModuleListLock,&Irql); + + Entry = PsLoadedModuleList.Flink; + while (Entry != &PsLoadedModuleList) { - return NULL; + 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(&ModuleListLock, Irql); + return(Module); + } + + Entry = Entry->Flink; } - *p = 0; + KeReleaseSpinLock(&ModuleListLock, Irql); - DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1); + DPRINT("Could not find module '%wZ'\n", ModuleName); - RtlCreateUnicodeStringFromAsciiz(&ModuleName, - NameBuffer); - ModuleObject = LdrGetModuleObject(&ModuleName); - RtlFreeUnicodeString(&ModuleName); - - DPRINT("ModuleObject: %p\n", ModuleObject); - - if (ModuleObject == NULL) - { - DPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer); - return NULL; - } - return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff); + return(NULL); } -static PVOID -LdrPEGetExportByOrdinal ( - PVOID BaseAddress, - ULONG Ordinal ) -{ - PIMAGE_EXPORT_DIRECTORY ExportDir; - ULONG ExportDirSize; - PULONG * ExFunctions; - PVOID Function; - - ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData ( - BaseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportDirSize); - - ExFunctions = (PULONG *)RVA(BaseAddress, - ExportDir->AddressOfFunctions); - DPRINT("LdrPEGetExportByOrdinal(Ordinal %d) = %x\n", - Ordinal, - RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base])); - - Function = 0 != ExFunctions[Ordinal - ExportDir->Base] - ? RVA(BaseAddress, ExFunctions[Ordinal - ExportDir->Base] ) - : NULL; - - if (((ULONG_PTR)Function >= (ULONG_PTR)ExportDir) && - ((ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - } - - return Function; -} - -static PVOID -LdrPEGetExportByName ( - PVOID BaseAddress, - PUCHAR SymbolName, - USHORT Hint ) -{ - PIMAGE_EXPORT_DIRECTORY ExportDir; - PULONG * ExFunctions; - PULONG * ExNames; - USHORT * ExOrdinals; - PVOID ExName; - ULONG Ordinal; - PVOID Function; - LONG minn, maxn, mid, res; - ULONG ExportDirSize; - - DPRINT("LdrPEGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint); - - ExportDir = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportDirSize); - if (ExportDir == NULL) - { - DPRINT1("LdrPEGetExportByName(): no export directory!\n"); - return NULL; - } - - - /* The symbol names may be missing entirely */ - if (ExportDir->AddressOfNames == 0) - { - DPRINT("LdrPEGetExportByName(): symbol names missing entirely\n"); - return NULL; - } - - /* - * Get header pointers - */ - ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames); - ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); - ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions); - - /* - * Check the hint first - */ - if (Hint < ExportDir->NumberOfNames) - { - ExName = RVA(BaseAddress, ExNames[Hint]); - if (strcmp(ExName, (PCHAR)SymbolName) == 0) - { - Ordinal = ExOrdinals[Hint]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && - (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - if (Function == NULL) - { - DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); - } - return Function; - } - if (Function != NULL) - { - return Function; - } - } - } - - /* - * Binary search - */ - minn = 0; - maxn = ExportDir->NumberOfNames - 1; - while (minn <= maxn) - { - mid = (minn + maxn) / 2; - - ExName = RVA(BaseAddress, ExNames[mid]); - res = strcmp(ExName, (PCHAR)SymbolName); - if (res == 0) - { - Ordinal = ExOrdinals[mid]; - Function = RVA(BaseAddress, ExFunctions[Ordinal]); - if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir && - (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize) - { - DPRINT("Forward: %s\n", (PCHAR)Function); - Function = LdrPEFixupForward((PCHAR)Function); - if (Function == NULL) - { - DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); - } - return Function; - } - if (Function != NULL) - { - return Function; - } - } - else if (res > 0) - { - maxn = mid - 1; - } - else - { - minn = mid + 1; - } - } - - ExName = RVA(BaseAddress, ExNames[mid]); - DPRINT1("LdrPEGetExportByName(): failed to find %s\n",SymbolName); - return (PVOID)NULL; -} - -static NTSTATUS -LdrPEProcessImportDirectoryEntry( - PVOID DriverBase, - PLDR_DATA_TABLE_ENTRY ImportedModule, - PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory ) -{ - PVOID* ImportAddressList; - PULONG FunctionNameList; - ULONG Ordinal; - - if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0) - { - return STATUS_UNSUCCESSFUL; - } - - /* Get the import address list. */ - ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk); - - /* Get the list of functions to import. */ - if (ImportModuleDirectory->OriginalFirstThunk != 0) - { - FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk); - } - else - { - FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk); - } - - /* Walk through function list and fixup addresses. */ - while (*FunctionNameList != 0L) - { - if ((*FunctionNameList) & 0x80000000) - { - Ordinal = (*FunctionNameList) & 0x7fffffff; - *ImportAddressList = LdrPEGetExportByOrdinal(ImportedModule->DllBase, Ordinal); - if ((*ImportAddressList) == NULL) - { - DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName); - return STATUS_UNSUCCESSFUL; - } - } - else - { - IMAGE_IMPORT_BY_NAME *pe_name; - pe_name = RVA(DriverBase, *FunctionNameList); - *ImportAddressList = LdrPEGetExportByName(ImportedModule->DllBase, pe_name->Name, pe_name->Hint); - if ((*ImportAddressList) == NULL) - { - DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullDllName); - return STATUS_UNSUCCESSFUL; - } - } - ImportAddressList++; - FunctionNameList++; - } - return STATUS_SUCCESS; -} - -typedef struct _LOAD_IMPORTS -{ - SIZE_T Count; - PLDR_DATA_TABLE_ENTRY Entry[1]; -} LOAD_IMPORTS, *PLOAD_IMPORTS; - +// +// Used when unloading drivers +// NTSTATUS NTAPI -MiResolveImageReferences(IN PVOID ImageBase, - IN PUNICODE_STRING ImageFileDirectory, - IN PUNICODE_STRING NamePrefix OPTIONAL, - OUT PCHAR *MissingApi, - OUT PWCHAR *MissingDriver, - OUT PLOAD_IMPORTS *LoadImports) +LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject ) { - /* We don't do anything for now */ - return STATUS_SUCCESS; + KIRQL Irql; + + /* Remove the module from the module list */ + KeAcquireSpinLock(&ModuleListLock,&Irql); + RemoveEntryList(&ModuleObject->InLoadOrderLinks); + KeReleaseSpinLock(&ModuleListLock, Irql); + + /* Hook for KDB on unloading a driver. */ + KDB_UNLOADDRIVER_HOOK(ModuleObject); + + /* Free module section */ + // MmFreeSection(ModuleObject->DllBase); + + ExFreePool(ModuleObject->FullDllName.Buffer); + ExFreePool(ModuleObject); + + return(STATUS_SUCCESS); } -static NTSTATUS -LdrPEFixupImports (IN PVOID DllBase, - IN PWCHAR DllName) -{ - PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory; - PCHAR ImportedName; - PLDR_DATA_TABLE_ENTRY ImportedModule; - NTSTATUS Status; - ULONG Size; - - /* Process each import module */ - ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR) - RtlImageDirectoryEntryToData(DllBase, - TRUE, - IMAGE_DIRECTORY_ENTRY_IMPORT, - &Size); - DPRINT("Processeing import directory at %p\n", ImportModuleDirectory); - while (ImportModuleDirectory->Name) - { - /* Check to make sure that import lib is kernel */ - ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name; - - Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory); - if (!NT_SUCCESS(Status)) - { - while (TRUE); - return Status; - } - - ImportModuleDirectory++; - } - return STATUS_SUCCESS; -} - -static NTSTATUS -LdrPEProcessModule( - PVOID ModuleLoadBase, - PUNICODE_STRING FileName, - PLDR_DATA_TABLE_ENTRY *ModuleObject ) +// +// Used for images already loaded (boot drivers) +// +NTSTATUS +LdrProcessModule(PVOID ModuleLoadBase, + PUNICODE_STRING FileName, + PLDR_DATA_TABLE_ENTRY *ModuleObject) { unsigned int DriverSize, Idx; ULONG CurrentSize; @@ -641,7 +366,7 @@ LdrPEProcessModule( BaseLength *= sizeof(WCHAR); /* Setup the string */ - BaseName.Length = BaseLength; + BaseName.Length = (USHORT)BaseLength; BaseName.Buffer = p; } else @@ -698,7 +423,7 @@ LdrPEProcessModule( NtHeader->OptionalHeader.AddressOfEntryPoint); LdrEntry->SizeOfImage = DriverSize; LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum; - LdrEntry->SectionPointer = NULL; // FIXME + LdrEntry->SectionPointer = LdrEntry; /* Now write the DLL name */ LdrEntry->BaseDllName.Buffer = NameBuffer; @@ -737,7 +462,7 @@ LdrPEProcessModule( /* Insert the entry */ KeAcquireSpinLock(&ModuleListLock, &Irql); - InsertTailList(&ModuleListHead, &LdrEntry->InLoadOrderLinks); + InsertTailList(&PsLoadedModuleList, &LdrEntry->InLoadOrderLinks); KeReleaseSpinLock(&ModuleListLock, Irql); /* Resolve imports */ @@ -748,10 +473,6 @@ LdrPEProcessModule( &MissingApiName, &MissingDriverName, &LoadedImports); - - /* Resolve imports */ - Status = LdrPEFixupImports(LdrEntry->DllBase, - LdrEntry->FullDllName.Buffer); if (!NT_SUCCESS(Status)) { /* Fail */ @@ -765,145 +486,6 @@ LdrPEProcessModule( return STATUS_SUCCESS; } -VOID -INIT_FUNCTION -NTAPI -LdrInit1(VOID) -{ - PLDR_DATA_TABLE_ENTRY HalModuleObject, NtoskrnlModuleObject, LdrEntry; - - /* Initialize the module list and spinlock */ - InitializeListHead(&ModuleListHead); - KeInitializeSpinLock(&ModuleListLock); - - /* Get the NTOSKRNL Entry from the loader */ - LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - /* Initialize ModuleObject for NTOSKRNL */ - NtoskrnlModuleObject = ExAllocatePoolWithTag(PagedPool, - sizeof(LDR_DATA_TABLE_ENTRY), - TAG('M', 'm', 'L', 'd')); - NtoskrnlModuleObject->DllBase = LdrEntry->DllBase; - RtlInitUnicodeString(&NtoskrnlModuleObject->FullDllName, KERNEL_MODULE_NAME); - LdrpBuildModuleBaseName(&NtoskrnlModuleObject->BaseDllName, &NtoskrnlModuleObject->FullDllName); - NtoskrnlModuleObject->EntryPoint = LdrEntry->EntryPoint; - NtoskrnlModuleObject->SizeOfImage = LdrEntry->SizeOfImage; - - /* Insert it into the list */ - InsertTailList(&ModuleListHead, &NtoskrnlModuleObject->InLoadOrderLinks); - - /* Get the HAL Entry from the loader */ - LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - /* Initialize ModuleObject for HAL */ - HalModuleObject = ExAllocatePoolWithTag(PagedPool, - sizeof(LDR_DATA_TABLE_ENTRY), - TAG('M', 'm', 'L', 'd')); - HalModuleObject->DllBase = LdrEntry->DllBase; - RtlInitUnicodeString(&HalModuleObject->FullDllName, HAL_MODULE_NAME); - LdrpBuildModuleBaseName(&HalModuleObject->BaseDllName, &HalModuleObject->FullDllName); - HalModuleObject->EntryPoint = LdrEntry->EntryPoint; - HalModuleObject->SizeOfImage = LdrEntry->SizeOfImage; - - /* Insert it into the list */ - InsertTailList(&ModuleListHead, &HalModuleObject->InLoadOrderLinks); - - /* Hook for KDB on initialization of the loader. */ - KDB_LOADERINIT_HOOK(NtoskrnlModuleObject, HalModuleObject); -} - -// -// 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(&ModuleListLock,&Irql); - - Entry = ModuleListHead.Flink; - while (Entry != &ModuleListHead) - { - 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(&ModuleListLock, Irql); - return(Module); - } - - Entry = Entry->Flink; - } - - KeReleaseSpinLock(&ModuleListLock, Irql); - - DPRINT("Could not find module '%wZ'\n", ModuleName); - - return(NULL); -} - -// -// Used when unloading drivers -// -NTSTATUS -NTAPI -LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject ) -{ - KIRQL Irql; - - /* Remove the module from the module list */ - KeAcquireSpinLock(&ModuleListLock,&Irql); - RemoveEntryList(&ModuleObject->InLoadOrderLinks); - KeReleaseSpinLock(&ModuleListLock, Irql); - - /* Hook for KDB on unloading a driver. */ - KDB_UNLOADDRIVER_HOOK(ModuleObject); - - /* Free module section */ - // MmFreeSection(ModuleObject->DllBase); - - ExFreePool(ModuleObject->FullDllName.Buffer); - ExFreePool(ModuleObject); - - return(STATUS_SUCCESS); -} - -// -// Used for images already loaded (boot drivers) -// -NTSTATUS -LdrProcessModule( - PVOID ModuleLoadBase, - PUNICODE_STRING ModuleName, - PLDR_DATA_TABLE_ENTRY *ModuleObject ) -{ - PIMAGE_DOS_HEADER PEDosHeader; - - /* If MZ header exists */ - PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase; - if (PEDosHeader->e_magic == IMAGE_DOS_SIGNATURE && PEDosHeader->e_lfanew != 0L) - { - return LdrPEProcessModule(ModuleLoadBase, - ModuleName, - ModuleObject); - } - - DPRINT("Module wasn't PE\n"); - return STATUS_UNSUCCESSFUL; -} - // // Used by NtLoadDriver/IoMgr // diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index fb3f7707e5e..cd333002731 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -409,7 +409,7 @@ MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName) ANSI_STRING AnsiRoutineName; NTSTATUS Status; PLIST_ENTRY NextEntry; - extern LIST_ENTRY ModuleListHead; + extern LIST_ENTRY PsLoadedModuleList; PLDR_DATA_TABLE_ENTRY LdrEntry; BOOLEAN Found = FALSE; UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); @@ -422,8 +422,8 @@ MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName) if (!NT_SUCCESS(Status)) return NULL; /* Loop the loaded module list */ - NextEntry = ModuleListHead.Flink; - while (NextEntry != &ModuleListHead) + NextEntry = PsLoadedModuleList.Flink; + while (NextEntry != &PsLoadedModuleList) { /* Get the entry */ LdrEntry = CONTAINING_RECORD(NextEntry, diff --git a/reactos/ntoskrnl/mm/sysldr.c b/reactos/ntoskrnl/mm/sysldr.c new file mode 100644 index 00000000000..f8febbae2b7 --- /dev/null +++ b/reactos/ntoskrnl/mm/sysldr.c @@ -0,0 +1,586 @@ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/mm/sysldr.c +* PURPOSE: Contains the Kernel Loader (SYSLDR) for loading PE files. +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NTAPI +MiSnapThunk(IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA Name, + IN PIMAGE_THUNK_DATA Address, + IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, + IN ULONG ExportSize, + IN BOOLEAN SnapForwarder, + OUT PCHAR *MissingApi) +{ + BOOLEAN IsOrdinal; + USHORT Ordinal; + PULONG NameTable; + PUSHORT OrdinalTable; + PIMAGE_IMPORT_BY_NAME NameImport; + USHORT Hint; + ULONG Low = 0, Mid = 0, High; + LONG Ret; + NTSTATUS Status; + PCHAR MissingForwarder; + CHAR NameBuffer[MAXIMUM_FILENAME_LENGTH]; + PULONG ExportTable; + ANSI_STRING DllName; + UNICODE_STRING ForwarderName; + PLIST_ENTRY NextEntry; + PLDR_DATA_TABLE_ENTRY LdrEntry; + ULONG ForwardExportSize; + PIMAGE_EXPORT_DIRECTORY ForwardExportDirectory; + PIMAGE_IMPORT_BY_NAME ForwardName; + ULONG ForwardLength; + IMAGE_THUNK_DATA ForwardThunk; + PAGED_CODE(); + + /* Check if this is an ordinal */ + IsOrdinal = IMAGE_SNAP_BY_ORDINAL(Name->u1.Ordinal); + if ((IsOrdinal) && !(SnapForwarder)) + { + /* Get the ordinal number and set it as missing */ + Ordinal = (USHORT)(IMAGE_ORDINAL(Name->u1.Ordinal) - + ExportDirectory->Base); + *MissingApi = (PCHAR)(ULONG_PTR)Ordinal; + } + else + { + /* Get the VA if we don't have to snap */ + if (!SnapForwarder) Name->u1.AddressOfData += (ULONG_PTR)ImageBase; + NameImport = (PIMAGE_IMPORT_BY_NAME)Name->u1.AddressOfData; + + /* Copy the procedure name */ + strncpy(*MissingApi, + (PCHAR)&NameImport->Name[0], + MAXIMUM_FILENAME_LENGTH - 1); + + /* Setup name tables */ + DPRINT("Import name: %s\n", NameImport->Name); + NameTable = (PULONG)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfNames); + OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfNameOrdinals); + + /* Get the hint and check if it's valid */ + Hint = NameImport->Hint; + if ((Hint < ExportDirectory->NumberOfNames) && + !(strcmp(NameImport->Name, (PCHAR)DllBase + NameTable[Hint]))) + { + /* We have a match, get the ordinal number from here */ + Ordinal = OrdinalTable[Hint]; + } + else + { + /* Do a binary search */ + High = ExportDirectory->NumberOfNames - 1; + while (High >= Low) + { + /* Get new middle value */ + Mid = (Low + High) >> 1; + + /* Compare name */ + Ret = strcmp(NameImport->Name, (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 STATUS_DRIVER_ENTRYPOINT_NOT_FOUND; + + /* Otherwise, this is the ordinal */ + Ordinal = OrdinalTable[Mid]; + } + } + + /* Check if the ordinal is invalid */ + if (Ordinal >= ExportDirectory->NumberOfFunctions) + { + /* Fail */ + Status = STATUS_DRIVER_ORDINAL_NOT_FOUND; + } + else + { + /* In case the forwarder is missing */ + MissingForwarder = NameBuffer; + + /* Resolve the address and write it */ + ExportTable = (PULONG)((ULONG_PTR)DllBase + + ExportDirectory->AddressOfFunctions); + Address->u1.Function = (ULONG_PTR)DllBase + ExportTable[Ordinal]; + + /* Assume success from now on */ + Status = STATUS_SUCCESS; + + /* Check if the function is actually a forwarder */ + if ((Address->u1.Function > (ULONG_PTR)ExportDirectory) && + (Address->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize))) + { + /* Now assume failure in case the forwarder doesn't exist */ + Status = STATUS_DRIVER_ENTRYPOINT_NOT_FOUND; + + /* Build the forwarder name */ + DllName.Buffer = (PCHAR)Address->u1.Function; + DllName.Length = strchr(DllName.Buffer, '.') - + DllName.Buffer + + sizeof(ANSI_NULL); + DllName.MaximumLength = DllName.Length; + + /* Convert it */ + if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ForwarderName, + &DllName, + TRUE))) + { + /* We failed, just return an error */ + return Status; + } + + /* Loop the module list */ + NextEntry = PsLoadedModuleList.Flink; + while (NextEntry != &PsLoadedModuleList) + { + /* Get the loader entry */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + /* Check if it matches */ + if (RtlPrefixString((PSTRING)&ForwarderName, + (PSTRING)&LdrEntry->BaseDllName, + TRUE)) + { + /* Get the forwarder export directory */ + ForwardExportDirectory = + RtlImageDirectoryEntryToData(LdrEntry->DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ForwardExportSize); + if (!ForwardExportDirectory) break; + + /* Allocate a name entry */ + ForwardLength = strlen(DllName.Buffer + DllName.Length) + + sizeof(ANSI_NULL); + ForwardName = ExAllocatePoolWithTag(PagedPool, + sizeof(*ForwardName) + + ForwardLength, + TAG_LDR_WSTR); + if (!ForwardName) break; + + /* Copy the data */ + RtlCopyMemory(&ForwardName->Name[0], + DllName.Buffer + DllName.Length, + ForwardLength); + ForwardName->Hint = 0; + + /* Set the new address */ + *(PULONG)&ForwardThunk.u1.AddressOfData = (ULONG)ForwardName; + + /* Snap the forwarder */ + Status = MiSnapThunk(LdrEntry->DllBase, + ImageBase, + &ForwardThunk, + &ForwardThunk, + ForwardExportDirectory, + ForwardExportSize, + TRUE, + &MissingForwarder); + + /* Free the forwarder name and set the thunk */ + ExFreePool(ForwardName); + Address->u1 = ForwardThunk.u1; + break; + } + + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + } + + /* Free the name */ + RtlFreeUnicodeString(&ForwarderName); + } + } + + /* Return status */ + return Status; +} + +NTSTATUS +NTAPI +MiResolveImageReferences(IN PVOID ImageBase, + IN PUNICODE_STRING ImageFileDirectory, + IN PUNICODE_STRING NamePrefix OPTIONAL, + OUT PCHAR *MissingApi, + OUT PWCHAR *MissingDriver, + OUT PLOAD_IMPORTS *LoadImports) +{ + PCHAR MissingApiBuffer = *MissingApi, ImportName; + PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor, CurrentImport; + ULONG ImportSize, ImportCount = 0, LoadedImportsSize, ExportSize; + PLOAD_IMPORTS LoadedImports; + ULONG GdiLink, NormalLink, i; + BOOLEAN ReferenceNeeded, Loaded; + ANSI_STRING TempString; + UNICODE_STRING NameString, DllName; + PLDR_DATA_TABLE_ENTRY LdrEntry = NULL, DllEntry, ImportEntry = NULL; + PVOID ImportBase, DllBase; + PLIST_ENTRY NextEntry; + PIMAGE_EXPORT_DIRECTORY ExportDirectory; + NTSTATUS Status; + PIMAGE_THUNK_DATA OrigThunk, FirstThunk; + PAGED_CODE(); + DPRINT("%s - ImageBase: %p. ImageFileDirectory: %wZ\n", + __FUNCTION__, ImageBase, ImageFileDirectory); + + /* Assume no imports */ + *LoadImports = (PVOID)-2; + + /* Get the import descriptor */ + ImportDescriptor = RtlImageDirectoryEntryToData(ImageBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &ImportSize); + if (!ImportDescriptor) return STATUS_SUCCESS; + + /* Loop all imports to count them */ + for (CurrentImport = ImportDescriptor; + (CurrentImport->Name) && (CurrentImport->OriginalFirstThunk); + CurrentImport++) + { + /* One more */ + ImportCount++; + } + + /* Make sure we have non-zero imports */ + if (ImportCount) + { + /* Calculate and allocate the list we'll need */ + LoadedImportsSize = ImportCount * sizeof(PVOID) + sizeof(SIZE_T); + LoadedImports = ExAllocatePoolWithTag(PagedPool, + LoadedImportsSize, + TAG_LDR_WSTR); + if (LoadedImports) + { + /* Zero it and set the count */ + RtlZeroMemory(LoadedImports, LoadedImportsSize); + LoadedImports->Count = ImportCount; + } + } + else + { + /* No table */ + LoadedImports = NULL; + } + + /* Reset the import count and loop descriptors again */ + ImportCount = GdiLink = NormalLink = 0; + while ((ImportDescriptor->Name) && (ImportDescriptor->OriginalFirstThunk)) + { + /* Get the name */ + ImportName = (PCHAR)((ULONG_PTR)ImageBase + ImportDescriptor->Name); + + /* Check if this is a GDI driver */ + GdiLink = GdiLink | + !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)); + + /* We can also allow dxapi */ + NormalLink = NormalLink | + ((_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) && + (_strnicmp(ImportName, "dxapi", sizeof("dxapi") - 1))); + + /* Check if this is a valid GDI driver */ + if ((GdiLink) && (NormalLink)) + { + /* It's not, it's importing stuff it shouldn't be! */ + DPRINT1("Invalid driver!\n"); + //MiDereferenceImports(LoadedImports); + if (LoadedImports) ExFreePool(LoadedImports); + return STATUS_PROCEDURE_NOT_FOUND; + } + + /* Check if this is a "core" import, which doesn't get referenced */ + if (!(_strnicmp(ImportName, "ntoskrnl", sizeof("ntoskrnl") - 1)) || + !(_strnicmp(ImportName, "win32k", sizeof("win32k") - 1)) || + !(_strnicmp(ImportName, "hal", sizeof("hal") - 1))) + { + /* Don't reference this */ + ReferenceNeeded = FALSE; + } + else + { + /* Reference these modules */ + ReferenceNeeded = TRUE; + } + + /* Now setup a unicode string for the import */ + RtlInitAnsiString(&TempString, ImportName); + Status = RtlAnsiStringToUnicodeString(&NameString, &TempString, TRUE); + if (!NT_SUCCESS(Status)) + { + /* Failed */ + //MiDereferenceImports(LoadedImports); + if (LoadedImports) ExFreePool(LoadedImports); + return Status; + } + + /* We don't support name prefixes yet */ + if (NamePrefix) DPRINT1("Name Prefix not yet supported!\n"); + + /* Remember that we haven't loaded the import at this point */ +CheckDllState: + Loaded = FALSE; + ImportBase = NULL; + + /* Loop the driver list */ + NextEntry = PsLoadedModuleList.Flink; + while (NextEntry != &PsLoadedModuleList) + { + /* Get the loader entry and compare the name */ + LdrEntry = CONTAINING_RECORD(NextEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + if (RtlEqualUnicodeString(&NameString, + &LdrEntry->BaseDllName, + TRUE)) + { + /* Get the base address */ + ImportBase = LdrEntry->DllBase; + + /* Check if we haven't loaded yet, and we need references */ + if (!(Loaded) && (ReferenceNeeded)) + { + /* Make sure we're not already loading */ + if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)) + { + /* Increase the load count */ + LdrEntry->LoadCount++; + } + } + + /* Done, break out */ + break; + } + + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + } + + /* Check if we haven't loaded the import yet */ + if (!ImportBase) + { + /* Setup the import DLL name */ + DllName.MaximumLength = NameString.Length + + ImageFileDirectory->Length + + sizeof(UNICODE_NULL); + DllName.Buffer = ExAllocatePoolWithTag(NonPagedPool, + DllName.MaximumLength, + TAG_LDR_WSTR); + if (DllName.Buffer) + { + /* Setup the base length and copy it */ + DllName.Length = ImageFileDirectory->Length; + RtlCopyMemory(DllName.Buffer, + ImageFileDirectory->Buffer, + ImageFileDirectory->Length); + + /* Now add the import name and null-terminate it */ + RtlAppendStringToString((PSTRING)&DllName, + (PSTRING)&NameString); + DllName.Buffer[(DllName.MaximumLength - 1) / 2] = UNICODE_NULL; + + /* Load the image */ + Status = LdrLoadModule(&DllName, &DllEntry); + if (NT_SUCCESS(Status)) + { + /* We can free the DLL Name */ + ExFreePool(DllName.Buffer); + } + else + { + /* Fill out the information for the error */ + DPRINT1("Failed to import: %S\n", DllName.Buffer); + *MissingDriver = DllName.Buffer; + *(PULONG)MissingDriver |= 1; + *MissingApi = NULL; + } + } + else + { + /* We're out of resources */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + /* Check if we're OK until now */ + if (NT_SUCCESS(Status)) + { + /* We're now loaded */ + Loaded = TRUE; + + /* Get the base address and other information */ + DllBase = DllEntry->DllBase; + ASSERT(DllBase = DllEntry->DllBase); + + /* Call the initialization routines */ +#if 0 + Status = MmCallDllInitialize(DllEntry, &PsLoadedModuleList); + if (!NT_SUCCESS(Status)) + { + /* We failed, unload the image */ + MmUnloadSystemImage(DllEntry); + while (TRUE); + Loaded = FALSE; + } +#endif + } + + /* Check if we failed by here */ + if (!NT_SUCCESS(Status)) + { + /* Cleanup and return */ + DPRINT1("Failed loading import\n"); + RtlFreeUnicodeString(&NameString); + //MiDereferenceImports(LoadedImports); + if (LoadedImports) ExFreePool(LoadedImports); + return Status; + } + + /* Loop again to make sure that everything is OK */ + goto CheckDllState; + } + + /* Check if we're support to reference this import */ + if ((ReferenceNeeded) && (LoadedImports)) + { + /* Make sure we're not already loading */ + if (!(LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS)) + { + /* Add the entry */ + LoadedImports->Entry[ImportCount] = LdrEntry; + ImportCount++; + } + } + + /* Free the import name */ + RtlFreeUnicodeString(&NameString); + + /* Set the missing driver name and get the export directory */ + *MissingDriver = LdrEntry->BaseDllName.Buffer; + ExportDirectory = RtlImageDirectoryEntryToData(ImportBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + if (!ExportDirectory) + { + /* Cleanup and return */ + DPRINT1("Invalid driver: %wZ\n", &LdrEntry->BaseDllName); + //MiDereferenceImports(LoadedImports); + if (LoadedImports) ExFreePool(LoadedImports); + return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND; + } + + /* Make sure we have an IAT */ + if (ImportDescriptor->OriginalFirstThunk) + { + /* Get the first thunks */ + OrigThunk = (PVOID)((ULONG_PTR)ImageBase + + ImportDescriptor->OriginalFirstThunk); + FirstThunk = (PVOID)((ULONG_PTR)ImageBase + + ImportDescriptor->FirstThunk); + + /* Loop the IAT */ + while (OrigThunk->u1.AddressOfData) + { + /* Snap thunk */ + Status = MiSnapThunk(ImportBase, + ImageBase, + OrigThunk++, + FirstThunk++, + ExportDirectory, + ExportSize, + FALSE, + MissingApi); + if (!NT_SUCCESS(Status)) + { + /* Cleanup and return */ + //MiDereferenceImports(LoadedImports); + if (LoadedImports) ExFreePool(LoadedImports); + return Status; + } + + /* Reset the buffer */ + *MissingApi = MissingApiBuffer; + } + } + + /* Go to the next import */ + ImportDescriptor++; + } + + /* Check if we have an import list */ + if (LoadedImports) + { + /* Reset the count again, and loop entries*/ + ImportCount = 0; + for (i = 0; i < LoadedImports->Count; i++) + { + if (LoadedImports->Entry[i]) + { + /* Got an entry, OR it with 1 in case it's the single entry */ + ImportEntry = (PVOID)((ULONG_PTR)LoadedImports->Entry[i] | 1); + ImportCount++; + } + } + + /* Check if we had no imports */ + if (!ImportCount) + { + /* Free the list and set it to no imports */ + ExFreePool(LoadedImports); + LoadedImports = (PVOID)-2; + } + else if (ImportCount == 1) + { + /* Just one entry, we can free the table and only use our entry */ + ExFreePool(LoadedImports); + LoadedImports = (PLOAD_IMPORTS)ImportEntry; + } + else if (ImportCount != LoadedImports->Count) + { + /* FIXME: Can this happen? */ + DPRINT1("Unhandled scenario\n"); + while (TRUE); + } + + /* Return the list */ + *LoadImports = LoadedImports; + } + + /* Return success */ + return STATUS_SUCCESS; +} + diff --git a/reactos/ntoskrnl/mm/verifier.c b/reactos/ntoskrnl/mm/verifier.c index 8adcc9176fe..3c252ab4624 100644 --- a/reactos/ntoskrnl/mm/verifier.c +++ b/reactos/ntoskrnl/mm/verifier.c @@ -19,7 +19,7 @@ LIST_ENTRY MiVerifierDriverAddedThunkListHead; KMUTANT MmSystemLoadLock; ULONG MiActiveVerifierThunks; -extern LIST_ENTRY ModuleListHead; +extern LIST_ENTRY PsLoadedModuleList; /* PRIVATE FUNCTIONS *********************************************************/ @@ -32,7 +32,7 @@ MiLookupDataTableEntry(IN PVOID Address) PAGED_CODE(); /* Loop entries */ - NextEntry = ModuleListHead.Flink; + NextEntry = PsLoadedModuleList.Flink; do { /* Get the loader entry */ @@ -51,7 +51,7 @@ MiLookupDataTableEntry(IN PVOID Address) /* Move on */ NextEntry = NextEntry->Flink; - } while(NextEntry != &ModuleListHead); + } while(NextEntry != &PsLoadedModuleList); /* Return the entry */ return FoundEntry; diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 591bac5a370..60891077471 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -275,6 +275,7 @@ region.c rmap.c section.c + sysldr.c verifier.c virtual.c wset.c