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&…
==============================================================================
--- 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=…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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=…
==============================================================================
--- 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=2…
==============================================================================
--- 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;
}