mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 06:05:48 +00:00
- Add missing synchronization for access to PsLoadedModuleList. Inserting and removing entries to the list was protected by a spinlock, but some places didn't acquire the lock before looping the list when searching for module information. For efficiency, use an executive resource for other access than inserting/removing entries so we can have shared locking in some common cases (spinlock stays so access can be synchronized with DPCs).
- Make SystemUnloadGdiDriverInformation take the opaque SectionPointer (which is really the Loader Entry) from the SYSTEM_GDI_DRIVER_INFORMATION structure returned in SystemLoadGdiDriverInformation so it doesn't need to loop the loaded module list to find it. - Fix EngLoad/UnloadImage to do this. Also make EngLoadImage return the pointer to the internal structure as the "handle" so EngUnloadImage doesn't need to loop the driver list to find it. The code is still extremely broken and needs a rewrite. - Remove some externs from related variables in the code -- we use something called "headers". svn path=/trunk/; revision=44119
This commit is contained in:
parent
14442c0a34
commit
141ef5cfc3
8 changed files with 72 additions and 97 deletions
|
@ -139,17 +139,6 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
#undef ExGetPreviousMode
|
||||
KPROCESSOR_MODE
|
||||
NTAPI
|
||||
ExGetPreviousMode (VOID)
|
||||
{
|
||||
return KeGetPreviousMode();
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -1006,12 +995,23 @@ QSI_DEF(SystemCallTimeInformation)
|
|||
/* Class 11 - Module Information */
|
||||
QSI_DEF(SystemModuleInformation)
|
||||
{
|
||||
extern LIST_ENTRY PsLoadedModuleList;
|
||||
return ExpQueryModuleInformation(&PsLoadedModuleList,
|
||||
NULL,
|
||||
(PRTL_PROCESS_MODULES)Buffer,
|
||||
Size,
|
||||
ReqSize);
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Acquire system module list lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
|
||||
|
||||
/* Call the generic handler with the system module list */
|
||||
Status = ExpQueryModuleInformation(&PsLoadedModuleList,
|
||||
&MmLoadedUserImageList,
|
||||
(PRTL_PROCESS_MODULES)Buffer,
|
||||
Size,
|
||||
ReqSize);
|
||||
|
||||
/* Release list lock and return status */
|
||||
ExReleaseResourceLite(&PsLoadedModuleResource);
|
||||
KeLeaveCriticalRegion();
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Class 12 - Locks Information */
|
||||
|
@ -1322,10 +1322,9 @@ QSI_DEF(SystemFullMemoryInformation)
|
|||
SSI_DEF(SystemLoadGdiDriverInformation)
|
||||
{
|
||||
PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
|
||||
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
||||
UNICODE_STRING ImageName;
|
||||
PVOID ImageBase;
|
||||
PLDR_DATA_TABLE_ENTRY ModuleObject;
|
||||
PVOID SectionPointer;
|
||||
ULONG_PTR EntryPoint;
|
||||
NTSTATUS Status;
|
||||
ULONG DirSize;
|
||||
|
@ -1338,8 +1337,8 @@ SSI_DEF(SystemLoadGdiDriverInformation)
|
|||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
/* Only kernel-mode can call this function */
|
||||
if (PreviousMode != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
|
||||
/* Only kernel mode can call this function */
|
||||
if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
|
||||
|
||||
/* Load the driver */
|
||||
ImageName = DriverInfo->DriverName;
|
||||
|
@ -1347,7 +1346,7 @@ SSI_DEF(SystemLoadGdiDriverInformation)
|
|||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
(PVOID)&ModuleObject,
|
||||
&SectionPointer,
|
||||
&ImageBase);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
|
@ -1365,7 +1364,7 @@ SSI_DEF(SystemLoadGdiDriverInformation)
|
|||
|
||||
/* Save other data */
|
||||
DriverInfo->ImageAddress = ImageBase;
|
||||
DriverInfo->SectionPointer = NULL;
|
||||
DriverInfo->SectionPointer = SectionPointer;
|
||||
DriverInfo->EntryPoint = (PVOID)EntryPoint;
|
||||
DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
|
||||
|
||||
|
@ -1376,44 +1375,21 @@ SSI_DEF(SystemLoadGdiDriverInformation)
|
|||
/* Class 27 - Unload Image */
|
||||
SSI_DEF(SystemUnloadGdiDriverInformation)
|
||||
{
|
||||
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PVOID BaseAddr = *((PVOID*)Buffer);
|
||||
PVOID SectionPointer = Buffer;
|
||||
|
||||
if(Size != sizeof(PVOID))
|
||||
/* Validate size */
|
||||
if (Size != sizeof(PVOID))
|
||||
{
|
||||
/* Incorrect length, fail */
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
if(KeGetPreviousMode() != KernelMode)
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
|
||||
// Scan the module list
|
||||
NextEntry = PsLoadedModuleList.Flink;
|
||||
while(NextEntry != &PsLoadedModuleList)
|
||||
{
|
||||
LdrEntry = CONTAINING_RECORD(NextEntry,
|
||||
LDR_DATA_TABLE_ENTRY,
|
||||
InLoadOrderLinks);
|
||||
|
||||
if (LdrEntry->DllBase == BaseAddr)
|
||||
{
|
||||
// Found it.
|
||||
break;
|
||||
}
|
||||
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
// Check if we found the image
|
||||
if(NextEntry != &PsLoadedModuleList)
|
||||
{
|
||||
return MmUnloadSystemImage(LdrEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Image 0x%x not found.\n", BaseAddr);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
/* Only kernel mode can call this function */
|
||||
if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
|
||||
|
||||
/* Unload the image */
|
||||
MmUnloadSystemImage(SectionPointer);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Class 28 - Time Adjustment Information */
|
||||
|
@ -1986,7 +1962,6 @@ NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
|||
return STATUS_INVALID_INFO_CLASS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtFlushInstructionCache(IN HANDLE ProcessHandle,
|
||||
|
@ -2018,4 +1993,13 @@ NtGetCurrentProcessorNumber(VOID)
|
|||
return KeGetCurrentProcessorNumber();
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
#undef ExGetPreviousMode
|
||||
KPROCESSOR_MODE
|
||||
NTAPI
|
||||
ExGetPreviousMode (VOID)
|
||||
{
|
||||
return KeGetPreviousMode();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ extern MEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptorOrg;
|
|||
|
||||
extern LIST_ENTRY MmLoadedUserImageList;
|
||||
|
||||
extern KMUTANT MmSystemLoadLock;
|
||||
|
||||
extern ULONG MmNumberOfPagingFiles;
|
||||
|
||||
extern PVOID MmUnloadedDrivers;
|
||||
|
|
|
@ -434,6 +434,8 @@ extern POBJECT_TYPE PsJobType;
|
|||
extern LARGE_INTEGER ShortPsLockDelay;
|
||||
extern UNICODE_STRING PsNtDllPathName;
|
||||
extern LIST_ENTRY PsLoadedModuleList;
|
||||
extern KSPIN_LOCK PsLoadedModuleSpinLock;
|
||||
extern ERESOURCE PsLoadedModuleResource;
|
||||
extern ULONG_PTR PsNtosImageBase;
|
||||
|
||||
//
|
||||
|
|
|
@ -692,8 +692,6 @@ MiResolveImageReferences(IN PVOID ImageBase,
|
|||
OUT PWCHAR *MissingDriver,
|
||||
OUT PLOAD_IMPORTS *LoadImports);
|
||||
|
||||
extern KSPIN_LOCK PsLoadedModuleSpinLock;
|
||||
|
||||
//
|
||||
// Used for images already loaded (boot drivers)
|
||||
//
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
MM_DRIVER_VERIFIER_DATA MmVerifierData;
|
||||
LIST_ENTRY MiVerifierDriverAddedThunkListHead;
|
||||
ULONG MiActiveVerifierThunks;
|
||||
extern KMUTANT MmSystemLoadLock;
|
||||
extern LIST_ENTRY PsLoadedModuleList;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ ULONG MmReadClusterSize;
|
|||
UCHAR MmDisablePagingExecutive = 1; // Forced to off
|
||||
PMMPTE MmSharedUserDataPte;
|
||||
PMMSUPPORT MmKernelAddressSpace;
|
||||
extern KMUTANT MmSystemLoadLock;
|
||||
BOOLEAN MiDbgEnableMdDump =
|
||||
#ifdef _ARM_
|
||||
TRUE;
|
||||
|
|
|
@ -30,6 +30,7 @@ sprintf_nt(IN PCHAR Buffer,
|
|||
LIST_ENTRY PsLoadedModuleList;
|
||||
LIST_ENTRY MmLoadedUserImageList;
|
||||
KSPIN_LOCK PsLoadedModuleSpinLock;
|
||||
ERESOURCE PsLoadedModuleResource;
|
||||
ULONG_PTR PsNtosImageBase;
|
||||
KMUTANT MmSystemLoadLock;
|
||||
|
||||
|
@ -438,15 +439,21 @@ MiProcessLoaderEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
|
|||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Acquire the lock */
|
||||
KeAcquireSpinLock(&PsLoadedModuleSpinLock, &OldIrql);
|
||||
/* Acquire module list lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
|
||||
|
||||
/* Acquire the spinlock too as we will insert or remove the entry */
|
||||
OldIrql = KeAcquireSpinLockRaiseToSynch(&PsLoadedModuleSpinLock);
|
||||
|
||||
/* Insert or remove from the list */
|
||||
Insert ? InsertTailList(&PsLoadedModuleList, &LdrEntry->InLoadOrderLinks) :
|
||||
RemoveEntryList(&LdrEntry->InLoadOrderLinks);
|
||||
|
||||
/* Release the lock */
|
||||
/* Release locks */
|
||||
KeReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
|
||||
ExReleaseResourceLite(&PsLoadedModuleResource);
|
||||
KeLeaveCriticalRegion();
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -1332,7 +1339,8 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
PLIST_ENTRY ListHead, NextEntry;
|
||||
ULONG EntrySize;
|
||||
|
||||
/* Setup the loaded module list and lock */
|
||||
/* Setup the loaded module list and locks */
|
||||
ExInitializeResourceLite(&PsLoadedModuleResource);
|
||||
KeInitializeSpinLock(&PsLoadedModuleSpinLock);
|
||||
InitializeListHead(&PsLoadedModuleList);
|
||||
|
||||
|
@ -2005,6 +2013,7 @@ MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
|
|||
|
||||
/* Lock the list */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&PsLoadedModuleResource, TRUE);
|
||||
|
||||
/* Loop the loaded module list */
|
||||
NextEntry = PsLoadedModuleList.Flink;
|
||||
|
@ -2046,6 +2055,7 @@ MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
|
|||
}
|
||||
|
||||
/* Release the lock */
|
||||
ExReleaseResourceLite(&PsLoadedModuleResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Free the string and return */
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
typedef struct _DRIVERS
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
HANDLE ImageHandle;
|
||||
PVOID SectionPointer;
|
||||
UNICODE_STRING DriverName;
|
||||
}DRIVERS, *PDRIVERS;
|
||||
|
||||
extern LIST_ENTRY GlobalDriverListHead;
|
||||
|
||||
|
||||
/*
|
||||
* Blatantly stolen from ldr/utils.c in ntdll. I can't link ntdll from
|
||||
* here, though.
|
||||
|
@ -199,8 +200,8 @@ HANDLE
|
|||
APIENTRY
|
||||
EngLoadImage (LPWSTR DriverName)
|
||||
{
|
||||
HANDLE hImageHandle = NULL;
|
||||
SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
|
||||
PDRIVERS DriverInfo = NULL;
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlInitUnicodeString(&GdiDriverInfo.DriverName, DriverName);
|
||||
|
@ -213,14 +214,14 @@ EngLoadImage (LPWSTR DriverName)
|
|||
{
|
||||
Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry);
|
||||
if( Current && (0 == RtlCompareUnicodeString(&GdiDriverInfo.DriverName, &Current->DriverName, FALSE)) ) {
|
||||
hImageHandle = Current->ImageHandle;
|
||||
DriverInfo = Current;
|
||||
break;
|
||||
}
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
};
|
||||
}
|
||||
|
||||
if( !hImageHandle )
|
||||
if( !DriverInfo )
|
||||
{
|
||||
/* the driver was not loaded before, so let's do that */
|
||||
Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation, &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
|
||||
|
@ -228,19 +229,17 @@ EngLoadImage (LPWSTR DriverName)
|
|||
DPRINT1("ZwSetSystemInformation failed with Status 0x%lx\n", Status);
|
||||
}
|
||||
else {
|
||||
PDRIVERS DriverInfo;
|
||||
hImageHandle = (HANDLE)GdiDriverInfo.ImageAddress;
|
||||
DriverInfo = ExAllocatePool(PagedPool, sizeof(DRIVERS));
|
||||
DriverInfo->DriverName.MaximumLength = GdiDriverInfo.DriverName.MaximumLength;
|
||||
DriverInfo->DriverName.Length = GdiDriverInfo.DriverName.Length;
|
||||
DriverInfo->DriverName.Buffer = ExAllocatePool(PagedPool, GdiDriverInfo.DriverName.MaximumLength);
|
||||
RtlCopyUnicodeString(&DriverInfo->DriverName, &GdiDriverInfo.DriverName);
|
||||
DriverInfo->ImageHandle = hImageHandle;
|
||||
DriverInfo->SectionPointer = GdiDriverInfo.SectionPointer;
|
||||
InsertHeadList(&GlobalDriverListHead, &DriverInfo->ListEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return hImageHandle;
|
||||
return DriverInfo;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -248,11 +247,12 @@ APIENTRY
|
|||
EngUnloadImage ( IN HANDLE hModule )
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PDRIVERS DriverInfo = (PDRIVERS)hModule;
|
||||
|
||||
DPRINT("hModule 0x%x\n", hModule);
|
||||
|
||||
Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
|
||||
&hModule, sizeof(HANDLE));
|
||||
DriverInfo->SectionPointer, sizeof(PVOID));
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -261,27 +261,9 @@ EngUnloadImage ( IN HANDLE hModule )
|
|||
}
|
||||
else
|
||||
{
|
||||
/* remove from the list */
|
||||
if( !IsListEmpty(&GlobalDriverListHead) )
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry = GlobalDriverListHead.Flink;
|
||||
PDRIVERS Current;
|
||||
/* probably the driver was already loaded, let's try to find it out */
|
||||
while( CurrentEntry != &GlobalDriverListHead )
|
||||
{
|
||||
Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry);
|
||||
|
||||
if( Current ) {
|
||||
if(Current->ImageHandle == hModule) {
|
||||
ExFreePool(Current->DriverName.Buffer);
|
||||
RemoveEntryList(&Current->ListEntry);
|
||||
ExFreePool(Current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
};
|
||||
}
|
||||
ExFreePool(DriverInfo->DriverName.Buffer);
|
||||
RemoveEntryList(&DriverInfo->ListEntry);
|
||||
ExFreePool(DriverInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue