Author: ion Date: Fri Feb 23 10:13:19 2007 New Revision: 25885
URL: http://svn.reactos.org/svn/reactos?rev=25885&view=rev Log: - Merge DbgUnLoadImageSymbols from KD branch. - Rename LdrUnloadModule to MmUnloadSystemImage and: - Use MmSystemLoadLock. - Take into consideration the import list. - Honour load count. - Unload symbols if really unloading the image. - Dereference and clear imports. - Do proper LdrEntry cleanup. - Stub MiDereferenceImports and MmCallDllInitialize. - Implement MiLocateExportName and MiClearImports. - We don't yet fully support reference counting imports...this is still TBD.
Modified: trunk/reactos/include/ndk/rtlfuncs.h trunk/reactos/lib/rtl/debug.c trunk/reactos/ntoskrnl/ex/sysinfo.c trunk/reactos/ntoskrnl/include/internal/ldr.h trunk/reactos/ntoskrnl/include/internal/mm.h trunk/reactos/ntoskrnl/io/iomgr/driver.c trunk/reactos/ntoskrnl/ldr/loader.c trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/include/ndk/rtlfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtlfuncs.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/rtlfuncs.h (original) +++ trunk/reactos/include/ndk/rtlfuncs.h Fri Feb 23 10:13:19 2007 @@ -2514,6 +2514,14 @@ IN ULONG ProcessId );
+VOID +NTAPI +DbgUnLoadImageSymbols( + IN PANSI_STRING Name, + IN PVOID Base, + IN ULONG_PTR ProcessId +); + // // Generic Table Functions //
Modified: trunk/reactos/lib/rtl/debug.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/debug.c?rev=25885&a... ============================================================================== --- trunk/reactos/lib/rtl/debug.c (original) +++ trunk/reactos/lib/rtl/debug.c Fri Feb 23 10:13:19 2007 @@ -348,4 +348,25 @@ DebugService2(Name, &SymbolInfo, BREAKPOINT_LOAD_SYMBOLS); return STATUS_SUCCESS; } + +/* + * @implemented + */ +VOID +NTAPI +DbgUnLoadImageSymbols(IN PANSI_STRING Name, + IN PVOID Base, + IN ULONG_PTR ProcessId) +{ + KD_SYMBOLS_INFO SymbolInfo; + + /* Setup the symbol data */ + SymbolInfo.BaseOfDll = Base; + SymbolInfo.ProcessId = (PVOID)ProcessId; + SymbolInfo.CheckSum = SymbolInfo.SizeOfImage = 0; + + /* Load the symbols */ + DebugService2(Name, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS); +} + /* EOF */
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ex/sysinfo.c (original) +++ trunk/reactos/ntoskrnl/ex/sysinfo.c Fri Feb 23 10:13:19 2007 @@ -1495,7 +1495,7 @@ if (!NtHeader) { /* Fail */ - LdrUnloadModule(ModuleObject); + MmUnloadSystemImage(ModuleObject); return STATUS_INVALID_IMAGE_FORMAT; }
@@ -1514,7 +1514,7 @@ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
/* Unload if we failed */ - if (!NT_SUCCESS(Status)) LdrUnloadModule(ModuleObject); + if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject); return Status; }
Modified: trunk/reactos/ntoskrnl/include/internal/ldr.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/l... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ldr.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ldr.h Fri Feb 23 10:13:19 2007 @@ -6,77 +6,6 @@ #define DRIVER_ROOT_NAME L"\Driver\" #define FILESYSTEM_ROOT_NAME L"\FileSystem\"
-extern ULONG_PTR LdrHalBase; - -NTSTATUS -NTAPI -LdrLoadInitialProcess( - PHANDLE ProcessHandle, - PHANDLE ThreadHandle -); - -VOID -NTAPI -LdrLoadAutoConfigDrivers(VOID); - -NTSTATUS -NTAPI -LdrpMapImage( - HANDLE ProcessHandle, - HANDLE SectionHandle, - PVOID *ImageBase -); - -NTSTATUS -NTAPI -LdrpLoadImage( - PUNICODE_STRING DriverName, - PVOID *ModuleBase, - PVOID *SectionPointer, - PVOID *EntryPoint, - PVOID *ExportDirectory -); - -NTSTATUS -NTAPI -LdrpUnloadImage(PVOID ModuleBase); - -NTSTATUS -NTAPI -LdrpLoadAndCallImage(PUNICODE_STRING DriverName); - -NTSTATUS -NTAPI -LdrpQueryModuleInformation( - PVOID Buffer, - ULONG Size, - PULONG ReqSize -); - -VOID -NTAPI -LdrInit1(VOID); - -VOID -NTAPI -LdrInitDebug( - PLOADER_MODULE Module, - PWCH Name -); - -NTSTATUS -NTAPI -MmLoadSystemImage(IN PUNICODE_STRING FileName, - IN PUNICODE_STRING NamePrefix OPTIONAL, - IN PUNICODE_STRING LoadedName OPTIONAL, - IN ULONG Flags, - OUT PVOID *ModuleObject, - OUT PVOID *ImageBaseAddress); - -NTSTATUS -NTAPI -LdrUnloadModule(PLDR_DATA_TABLE_ENTRY ModuleObject); - PLDR_DATA_TABLE_ENTRY NTAPI LdrGetModuleObject(PUNICODE_STRING ModuleName);
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/m... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/mm.h (original) +++ trunk/reactos/ntoskrnl/include/internal/mm.h Fri Feb 23 10:13:19 2007 @@ -332,16 +332,6 @@ BOOLEAN Dirty );
- -/* FUNCTIONS */ - -NTSTATUS -NTAPI -MmCheckSystemImage( - IN HANDLE ImageHandle, - IN BOOLEAN PurgeSection -); - /* aspace.c ******************************************************************/
VOID @@ -1429,6 +1419,8 @@ OUT PULONG ResultLength );
+/* sysldr.c ******************************************************************/ + VOID NTAPI MiReloadBootLoadedDrivers( @@ -1441,5 +1433,28 @@ IN PLOADER_PARAMETER_BLOCK LoaderBlock );
+NTSTATUS +NTAPI +MmLoadSystemImage( + IN PUNICODE_STRING FileName, + IN PUNICODE_STRING NamePrefix OPTIONAL, + IN PUNICODE_STRING LoadedName OPTIONAL, + IN ULONG Flags, + OUT PVOID *ModuleObject, + OUT PVOID *ImageBaseAddress +); + +NTSTATUS +NTAPI +MmUnloadSystemImage( + IN PVOID ImageHandle +); + +NTSTATUS +NTAPI +MmCheckSystemImage( + IN HANDLE ImageHandle, + IN BOOLEAN PurgeSection +);
#endif
Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/driver.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/driver.c Fri Feb 23 10:13:19 2007 @@ -1169,7 +1169,7 @@ (*DriverObject->DriverUnload)(DriverObject); ObDereferenceObject(DriverObject); ObDereferenceObject(DriverObject); - LdrUnloadModule(ModuleObject); + MmUnloadSystemImage(ModuleObject);
return STATUS_SUCCESS; } @@ -1750,7 +1750,7 @@ if (!NT_SUCCESS(Status)) { DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status); - LdrUnloadModule(ModuleObject); + MmUnloadSystemImage(ModuleObject); IopFreeDeviceNode(DeviceNode); goto ReleaseCapturedString; }
Modified: trunk/reactos/ntoskrnl/ldr/loader.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ldr/loader.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ldr/loader.c (original) +++ trunk/reactos/ntoskrnl/ldr/loader.c Fri Feb 23 10:13:19 2007 @@ -133,30 +133,4 @@ return(NULL); }
-// -// Used when unloading drivers -// -NTSTATUS -NTAPI -LdrUnloadModule ( PLDR_DATA_TABLE_ENTRY ModuleObject ) -{ - KIRQL Irql; - - /* Remove the module from the module list */ - KeAcquireSpinLock(&PsLoadedModuleSpinLock,&Irql); - RemoveEntryList(&ModuleObject->InLoadOrderLinks); - KeReleaseSpinLock(&PsLoadedModuleSpinLock, 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); -} - /* EOF */
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=25... ============================================================================== --- trunk/reactos/ntoskrnl/mm/sysldr.c (original) +++ trunk/reactos/ntoskrnl/mm/sysldr.c Fri Feb 23 10:13:19 2007 @@ -20,6 +20,135 @@ KMUTANT MmSystemLoadLock;
/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NTAPI +MiDereferenceImports(IN PLOAD_IMPORTS ImportList) +{ + /* Check if there's no imports or if we're a boot driver */ + if ((ImportList == (PVOID)-1) || (ImportList == (PVOID)-2)) + { + /* Then there's nothing to do */ + return STATUS_SUCCESS; + } + + /* Otherwise, FIXME */ + DPRINT1("Imports not dereferenced!\n"); + return STATUS_UNSUCCESSFUL; +} + +VOID +NTAPI +MiClearImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry) +{ + PAGED_CODE(); + + /* Check if there's no imports or we're a boot driver or only one entry */ + if ((LdrEntry->LoadedImports == (PVOID)-1) || + (LdrEntry->LoadedImports == (PVOID)-2) || + ((ULONG_PTR)LdrEntry->LoadedImports & 1)) + { + /* Nothing to do */ + return; + } + + /* Otherwise, free the import list */ + ExFreePool(LdrEntry->LoadedImports); +} + +PVOID +NTAPI +MiLocateExportName(IN PVOID DllBase, + IN PCHAR 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, (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]); + + /* Check if the function is actually a forwarder */ + if (((ULONG_PTR)Function > (ULONG_PTR)ExportDirectory) && + ((ULONG_PTR)Function < ((ULONG_PTR)ExportDirectory + ExportSize))) + { + /* It is, fail */ + return NULL; + } + + /* We found it */ + return Function; +} + +NTSTATUS +NTAPI +MmCallDllInitialize(IN PLDR_DATA_TABLE_ENTRY LdrEntry, + IN PLIST_ENTRY ListHead) +{ + PMM_DLL_INITIALIZE DllInit; + + /* Try to see if the image exports a DllInitialize routine */ + DllInit = (PMM_DLL_INITIALIZE)MiLocateExportName(LdrEntry->DllBase, + "DllInitialize"); + if (!DllInit) return STATUS_SUCCESS; + + /* FIXME: TODO */ + DPRINT1("DllInitialize not called!\n"); + return STATUS_UNSUCCESSFUL; +}
VOID NTAPI @@ -321,6 +450,92 @@
NTSTATUS NTAPI +MmUnloadSystemImage(IN PVOID ImageHandle) +{ + PLDR_DATA_TABLE_ENTRY LdrEntry = ImageHandle; + PVOID BaseAddress = LdrEntry->DllBase; + NTSTATUS Status; + ANSI_STRING TempName; + BOOLEAN HadEntry = FALSE; + + /* Acquire the loader lock */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(&MmSystemLoadLock, + WrVirtualMemory, + KernelMode, + FALSE, + NULL); + + /* Check if this driver was loaded at boot and didn't get imports parsed */ + if (LdrEntry->LoadedImports == (PVOID)-1) goto Done; + + /* We should still be alive */ + ASSERT(LdrEntry->LoadCount != 0); + LdrEntry->LoadCount--; + + /* Check if we're still loaded */ + if (LdrEntry->LoadCount) goto Done; + + /* We should cleanup... are symbols loaded */ + if (LdrEntry->Flags & LDRP_DEBUG_SYMBOLS_LOADED) + { + /* Create the ANSI name */ + Status = RtlUnicodeStringToAnsiString(&TempName, + &LdrEntry->BaseDllName, + TRUE); + if (NT_SUCCESS(Status)) + { + /* Unload the symbols */ + DbgUnLoadImageSymbols(&TempName, BaseAddress, -1); + RtlFreeAnsiString(&TempName); + } + } + + /* FIXME: Free the driver */ + //MmFreeSection(LdrEntry->DllBase); + + /* Check if we're linked in */ + if (LdrEntry->InLoadOrderLinks.Flink) + { + /* Remove us */ + MiProcessLoaderEntry(LdrEntry, FALSE); + HadEntry = TRUE; + } + + /* Dereference and clear the imports */ + MiDereferenceImports(LdrEntry->LoadedImports); + MiClearImports(LdrEntry); + + /* Check if the entry needs to go away */ + if (HadEntry) + { + /* Check if it had a name */ + if (LdrEntry->FullDllName.Buffer) + { + /* Free it */ + ExFreePool(LdrEntry->FullDllName.Buffer); + } + + /* Check if we had a section */ + if (LdrEntry->SectionPointer) + { + /* Dereference it */ + ObDereferenceObject(LdrEntry->SectionPointer); + } + + /* Free the entry */ + ExFreePool(LdrEntry); + } + + /* Release the system lock and return */ +Done: + KeReleaseMutant(&MmSystemLoadLock, 1, FALSE, FALSE); + KeLeaveCriticalRegion(); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI MiResolveImageReferences(IN PVOID ImageBase, IN PUNICODE_STRING ImageFileDirectory, IN PUNICODE_STRING NamePrefix OPTIONAL, @@ -406,8 +621,7 @@ if ((GdiLink) && (NormalLink)) { /* It's not, it's importing stuff it shouldn't be! */ - DPRINT1("Invalid driver!\n"); - //MiDereferenceImports(LoadedImports); + MiDereferenceImports(LoadedImports); if (LoadedImports) ExFreePool(LoadedImports); return STATUS_PROCEDURE_NOT_FOUND; } @@ -432,7 +646,7 @@ if (!NT_SUCCESS(Status)) { /* Failed */ - //MiDereferenceImports(LoadedImports); + MiDereferenceImports(LoadedImports); if (LoadedImports) ExFreePool(LoadedImports); return Status; } @@ -517,7 +731,6 @@ else { /* Fill out the information for the error */ - DPRINT1("Failed to import: %S\n", DllName.Buffer); *MissingDriver = DllName.Buffer; *(PULONG)MissingDriver |= 1; *MissingApi = NULL; @@ -539,7 +752,6 @@ ASSERT(DllBase = DllEntry->DllBase);
/* Call the initialization routines */ -#if 0 Status = MmCallDllInitialize(DllEntry, &PsLoadedModuleList); if (!NT_SUCCESS(Status)) { @@ -548,16 +760,14 @@ 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); + MiDereferenceImports(LoadedImports); if (LoadedImports) ExFreePool(LoadedImports); return Status; } @@ -590,8 +800,7 @@ if (!ExportDirectory) { /* Cleanup and return */ - DPRINT1("Invalid driver: %wZ\n", &LdrEntry->BaseDllName); - //MiDereferenceImports(LoadedImports); + MiDereferenceImports(LoadedImports); if (LoadedImports) ExFreePool(LoadedImports); return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND; } @@ -620,7 +829,7 @@ if (!NT_SUCCESS(Status)) { /* Cleanup and return */ - //MiDereferenceImports(LoadedImports); + MiDereferenceImports(LoadedImports); if (LoadedImports) ExFreePool(LoadedImports); return Status; }