-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/sysinfo.c
* PURPOSE: System information functions
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
- * Aleksey Bragin (aleksey@studiocerebral.com)
+ * Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
-#include <internal/debug.h>
-
-extern PEPROCESS PsIdleProcess;
-extern ULONG NtGlobalFlag; /* FIXME: it should go in a ddk/?.h */
-ULONGLONG STDCALL KeQueryInterruptTime(VOID);
+#include <debug.h>
VOID MmPrintMemoryStatistic(VOID);
ERESOURCE ExpFirmwareTableResource;
LIST_ENTRY ExpFirmwareTableProviderListHead;
+NTSTATUS
+NTAPI
+ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
+ IN PLIST_ENTRY UserModeList,
+ OUT PRTL_PROCESS_MODULES Modules,
+ IN ULONG Length,
+ OUT PULONG ReturnLength)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG RequiredLength;
+ PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ ANSI_STRING ModuleName;
+ ULONG ModuleCount = 0;
+ PLIST_ENTRY NextEntry;
+ PCHAR p;
+
+ /* Setup defaults */
+ RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules);
+ ModuleInfo = &Modules->Modules[0];
+
+ /* Loop the kernel list */
+ NextEntry = KernelModeList->Flink;
+ while (NextEntry != KernelModeList)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Update size and check if we can manage one more entry */
+ RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
+ if (Length >= RequiredLength)
+ {
+ /* Fill it out */
+ ModuleInfo->MappedBase = NULL;
+ ModuleInfo->ImageBase = LdrEntry->DllBase;
+ ModuleInfo->ImageSize = LdrEntry->SizeOfImage;
+ ModuleInfo->Flags = LdrEntry->Flags;
+ ModuleInfo->LoadCount = LdrEntry->LoadCount;
+ ModuleInfo->LoadOrderIndex = (USHORT)ModuleCount;
+ ModuleInfo->InitOrderIndex = 0;
+
+ /* Setup name */
+ RtlInitEmptyAnsiString(&ModuleName,
+ ModuleInfo->FullPathName,
+ sizeof(ModuleInfo->FullPathName));
+
+ /* Convert it */
+ Status = RtlUnicodeStringToAnsiString(&ModuleName,
+ &LdrEntry->FullDllName,
+ FALSE);
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+ {
+ /* Calculate offset to name */
+ p = ModuleName.Buffer + ModuleName.Length;
+ while ((p > ModuleName.Buffer) && (*--p))
+ {
+ /* Check if we found the separator */
+ if (*p == OBJ_NAME_PATH_SEPARATOR)
+ {
+ /* We did, break out */
+ p++;
+ break;
+ }
+ }
+
+ /* Set the offset */
+ ModuleInfo->OffsetToFileName = p - ModuleName.Buffer;
+ }
+ else
+ {
+ /* Return empty name */
+ ModuleInfo->FullPathName[0] = ANSI_NULL;
+ ModuleInfo->OffsetToFileName = 0;
+ }
+
+ /* Go to the next module */
+ ModuleInfo++;
+ }
+ else
+ {
+ /* Set error code */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Update count and move to next entry */
+ ModuleCount++;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Check if caller also wanted user modules */
+ if (UserModeList)
+ {
+ /* FIXME: TODO */
+ DPRINT1("User-mode list not yet supported in ReactOS!\n");
+ }
+
+ /* Update return length */
+ if (ReturnLength) *ReturnLength = RequiredLength;
+
+ /* Validate the length again */
+ if (Length >= FIELD_OFFSET(RTL_PROCESS_MODULES, Modules))
+ {
+ /* Set the final count */
+ Modules->NumberOfModules = ModuleCount;
+ }
+ else
+ {
+ /* Otherwise, we failed */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Done */
+ return Status;
+}
+
/* FUNCTIONS *****************************************************************/
/*
return KeGetPreviousMode();
}
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-ExEnumHandleTable (
- PULONG HandleTable,
- PVOID Callback,
- PVOID Param,
- PHANDLE Handle OPTIONAL
- )
-{
- UNIMPLEMENTED;
-}
-
/*
* @implemented
*/
VOID
-STDCALL
-ExGetCurrentProcessorCpuUsage (
- PULONG CpuUsage
- )
+NTAPI
+ExGetCurrentProcessorCpuUsage(PULONG CpuUsage)
{
PKPRCB Prcb;
ULONG TotalTime;
* @implemented
*/
VOID
-STDCALL
-ExGetCurrentProcessorCounts (
- PULONG ThreadKernelTime,
- PULONG TotalCpuTime,
- PULONG ProcessorNumber
- )
+NTAPI
+ExGetCurrentProcessorCounts(PULONG ThreadKernelTime,
+ PULONG TotalCpuTime,
+ PULONG ProcessorNumber)
{
PKPRCB Prcb;
* @implemented
*/
BOOLEAN
-STDCALL
+NTAPI
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
{
/* Quick check to see if it exists at all */
* @implemented
*/
BOOLEAN
-STDCALL
+NTAPI
ExVerifySuite(SUITE_TYPE SuiteType)
{
if (SuiteType == Personal) return TRUE;
return FALSE;
}
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
OUT PWSTR ValueBuffer,
IN ULONG ValueBufferLength,
{
ANSI_STRING AName;
UNICODE_STRING WName;
- BOOLEAN Result;
+ ARC_STATUS Result;
PCH Value;
ANSI_STRING AValue;
UNICODE_STRING WValue;
if(PreviousMode != KernelMode)
{
- _SEH_TRY
+ _SEH2_TRY
{
ProbeForRead(VariableName,
sizeof(UNICODE_STRING),
ProbeForWriteUlong(ReturnLength);
}
}
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if(!NT_SUCCESS(Status))
{
* Convert the result to UNICODE, protect with SEH in case the value buffer
* isn't NULL-terminated!
*/
- _SEH_TRY
+ _SEH2_TRY
{
RtlInitAnsiString(&AValue, Value);
Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
}
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
if(NT_SUCCESS(Status))
{
/*
* Copy the result back to the caller.
*/
- _SEH_TRY
+ _SEH2_TRY
{
RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
Status = STATUS_SUCCESS;
}
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
}
/*
}
-NTSTATUS STDCALL
+NTSTATUS NTAPI
NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName,
IN PUNICODE_STRING Value)
{
TRUE);
if(NT_SUCCESS(Status))
{
- BOOLEAN Result = HalSetEnvironmentVariable(AName.Buffer,
+ ARC_STATUS Result = HalSetEnvironmentVariable(AName.Buffer,
AValue.Buffer);
Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
{
return (STATUS_INFO_LENGTH_MISMATCH);
}
+ RtlZeroMemory(Sbi, Size);
Sbi->Reserved = 0;
Sbi->TimerResolution = KeMaximumIncrement;
Sbi->PageSize = PAGE_SIZE;
return (STATUS_INFO_LENGTH_MISMATCH);
}
Prcb = KeGetCurrentPrcb();
- Spi->ProcessorArchitecture = 0; /* Intel Processor */
- Spi->ProcessorLevel = Prcb->CpuType;
- Spi->ProcessorRevision = Prcb->CpuStep;
+ Spi->ProcessorArchitecture = KeProcessorArchitecture;
+ Spi->ProcessorLevel = KeProcessorLevel;
+ Spi->ProcessorRevision = KeProcessorRevision;
Spi->Reserved = 0;
- Spi->ProcessorFeatureBits = Prcb->FeatureBits;
+ Spi->ProcessorFeatureBits = KeFeatureBits;
DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
Spi->ProcessorLevel, Spi->ProcessorRevision);
/* Class 2 - Performance Information */
QSI_DEF(SystemPerformanceInformation)
{
+ ULONG IdleUser, IdleKernel;
PSYSTEM_PERFORMANCE_INFORMATION Spi
= (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
TheIdleProcess = PsIdleProcess;
- Spi->IdleProcessTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000LL;
-
+ IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
+ Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
Spi->IoReadTransferCount = IoReadTransferCount;
Spi->IoWriteTransferCount = IoWriteTransferCount;
Spi->IoOtherTransferCount = IoOtherTransferCount;
Spi->AvailablePages = MmStats.NrFreePages;
/*
- Add up all the used "Commitied" memory + pagefile.
+ Add up all the used "Committed" memory + pagefile.
Not sure this is right. 8^\
*/
Spi->CommittedPages = MiMemoryConsumers[MC_PPOOL].PagesUsed +
{
ULONG ovlSize = 0, nThreads;
PEPROCESS pr = NULL, syspr;
- unsigned char *pCur;
+ PUCHAR pCur;
+ ULONG TotalUser, TotalKernel;
NTSTATUS Status = STATUS_SUCCESS;
- _SEH_TRY
+ _SEH2_TRY
{
/* scan the process list */
if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
{
- return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
+ _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
}
+ RtlZeroMemory(Spi, Size);
- syspr = PsGetNextProcess(NULL);
+ syspr = PsIdleProcess;
pr = syspr;
pCur = (unsigned char *)Spi;
int inLen=32; // image name len in bytes
PLIST_ENTRY current_entry;
PETHREAD current;
- PSYSTEM_THREAD_INFORMATION ThreadInfo;
+ PSYSTEM_THREAD_INFORMATION ThreadInfo;
SpiCur = (PSYSTEM_PROCESS_INFORMATION)pCur;
*ReqSize = ovlSize;
ObDereferenceObject(pr);
- return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
+ _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
}
// fill system information
SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
SpiCur->NumberOfThreads = nThreads;
SpiCur->CreateTime = pr->CreateTime;
- SpiCur->UserTime.QuadPart = pr->Pcb.UserTime * 100000LL;
- SpiCur->KernelTime.QuadPart = pr->Pcb.KernelTime * 100000LL;
SpiCur->ImageName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
- SpiCur->ImageName.MaximumLength = inLen;
+ SpiCur->ImageName.MaximumLength = (USHORT)inLen;
SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
// copy name to the end of the struct
}
else
{
- RtlInitUnicodeString(&SpiCur->ImageName, NULL);
+ RtlInitUnicodeString(&SpiCur->ImageName, NULL);
}
SpiCur->BasePriority = pr->Pcb.BasePriority;
SpiCur->PagefileUsage = pr->QuotaUsage[2];
SpiCur->PeakPagefileUsage = pr->QuotaPeak[2];
SpiCur->PrivatePageCount = pr->CommitCharge;
- ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCur + 1);
+ ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCur + 1);
- current_entry = pr->ThreadListHead.Flink;
- while (current_entry != &pr->ThreadListHead)
+ current_entry = pr->ThreadListHead.Flink;
+ while (current_entry != &pr->ThreadListHead)
{
current = CONTAINING_RECORD(current_entry, ETHREAD,
ThreadListEntry);
-
- ThreadInfo->KernelTime.QuadPart = current->Tcb.KernelTime * 100000LL;
- ThreadInfo->UserTime.QuadPart = current->Tcb.UserTime * 100000LL;
-// SpiCur->TH[i].CreateTime = current->CreateTime;
+ ThreadInfo->KernelTime.QuadPart = UInt32x32To64(current->Tcb.KernelTime, KeMaximumIncrement);
+ ThreadInfo->UserTime.QuadPart = UInt32x32To64(current->Tcb.UserTime, KeMaximumIncrement);
+ ThreadInfo->CreateTime.QuadPart = current->CreateTime.QuadPart;
ThreadInfo->WaitTime = current->Tcb.WaitTime;
ThreadInfo->StartAddress = (PVOID) current->StartAddress;
ThreadInfo->ClientId = current->Cid;
ThreadInfo->ContextSwitches = current->Tcb.ContextSwitches;
ThreadInfo->ThreadState = current->Tcb.State;
ThreadInfo->WaitReason = current->Tcb.WaitReason;
+
ThreadInfo++;
current_entry = current_entry->Flink;
}
+ /* Query total user/kernel times of a process */
+ TotalKernel = KeQueryRuntimeProcess(&pr->Pcb, &TotalUser);
+ SpiCur->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
+ SpiCur->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
+
+ /* Handle idle process entry */
+ if (pr == PsIdleProcess) pr = NULL;
+
pr = PsGetNextProcess(pr);
nThreads = 0;
if ((pr == syspr) || (pr == NULL))
ObDereferenceObject(pr);
Status = STATUS_SUCCESS;
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
if(pr != NULL)
ObDereferenceObject(pr);
- Status = _SEH_GetExceptionCode();
+ Status = _SEH2_GetExceptionCode();
}
- _SEH_END
+ _SEH2_END
*ReqSize = ovlSize;
return Status;
/* Class 8 - Processor Performance Information */
QSI_DEF(SystemProcessorPerformanceInformation)
{
- PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
- = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
+ PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
+ = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
- LONG i;
- LARGE_INTEGER CurrentTime;
- PKPRCB Prcb;
+ LONG i;
+ ULONG TotalTime;
+ LARGE_INTEGER CurrentTime;
+ PKPRCB Prcb;
- *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
- /*
- * Check user buffer's size
- */
- if (Size < KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION))
- {
- return (STATUS_INFO_LENGTH_MISMATCH);
- }
+ *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
- CurrentTime.QuadPart = KeQueryInterruptTime();
- Prcb = ((PKPCR)KPCR_BASE)->Prcb;
- for (i = 0; i < KeNumberProcessors; i++)
- {
- Spi->IdleTime.QuadPart = (Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime) * 100000LL; // IdleTime
- Spi->KernelTime.QuadPart = Prcb->KernelTime * 100000LL; // KernelTime
- Spi->UserTime.QuadPart = Prcb->UserTime * 100000LL;
- Spi->DpcTime.QuadPart = Prcb->DpcTime * 100000LL;
- Spi->InterruptTime.QuadPart = Prcb->InterruptTime * 100000LL;
- Spi->InterruptCount = Prcb->InterruptCount; // Interrupt Count
- Spi++;
- Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
- }
+ /* Check user buffer's size */
+ if (Size < *ReqSize)
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
- return (STATUS_SUCCESS);
+ CurrentTime.QuadPart = KeQueryInterruptTime();
+ Prcb = KeGetPcr()->Prcb;
+ for (i = 0; i < KeNumberProcessors; i++)
+ {
+ /* Calculate total user and kernel times */
+ TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime;
+ Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement);
+ Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement);
+ Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement);
+ Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement);
+ Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement);
+ Spi->InterruptCount = Prcb->InterruptCount;
+ Spi++;
+ Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
+ }
+
+ return STATUS_SUCCESS;
}
/* Class 9 - Flags Information */
/* Class 11 - Module Information */
QSI_DEF(SystemModuleInformation)
{
- return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
+ extern LIST_ENTRY PsLoadedModuleList;
+ return ExpQueryModuleInformation(&PsLoadedModuleList,
+ NULL,
+ (PRTL_PROCESS_MODULES)Buffer,
+ Size,
+ ReqSize);
}
/* Class 12 - Locks Information */
for (Count = 0; HandleCount > 0 ; HandleCount--)
{
- Shi->Handles[i].UniqueProcessId = (ULONG)pr->UniqueProcessId;
+ Shi->Handles[i].UniqueProcessId = (USHORT)(ULONG_PTR)pr->UniqueProcessId;
Count++;
i++;
}
QSI_DEF(SystemInterruptInformation)
{
PKPRCB Prcb;
+ PKPCR Pcr;
LONG i;
ULONG ti;
PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
ti = KeQueryTimeIncrement();
- Prcb = ((PKPCR)KPCR_BASE)->Prcb;
for (i = 0; i < KeNumberProcessors; i++)
{
- //sii->ContextSwitches = Prcb->KeContextSwitches;
- sii->DpcCount = 0; /* FIXME */
- sii->DpcRate = 0; /* FIXME */
+ Prcb = KiProcessorBlock[i];
+#ifdef _M_AMD64
+ Pcr = CONTAINING_RECORD(Prcb, KPCR, CurrentPrcb);
+#else
+ Pcr = CONTAINING_RECORD(Prcb, KPCR, Prcb);
+#endif
+#ifdef _M_ARM // This code should probably be done differently
+ sii->ContextSwitches = Pcr->ContextSwitches;
+#else
+ sii->ContextSwitches = ((PKIPCR)Pcr)->ContextSwitches;
+#endif
+ sii->DpcCount = Prcb->DpcData[0].DpcCount;
+ sii->DpcRate = Prcb->DpcRequestRate;
sii->TimeIncrement = ti;
- sii->DpcBypassCount = 0; /* FIXME */
- sii->ApcBypassCount = 0; /* FIXME */
+ sii->DpcBypassCount = 0;
+ sii->ApcBypassCount = 0;
sii++;
- Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
}
return STATUS_SUCCESS;
}
/* Class 26 - Load Image */
-SSI_DEF(SystemLoadImage)
-{
- PSYSTEM_GDI_DRIVER_INFORMATION Sli = (PSYSTEM_GDI_DRIVER_INFORMATION)Buffer;
-
- if (sizeof(SYSTEM_GDI_DRIVER_INFORMATION) != Size)
+SSI_DEF(SystemLoadGdiDriverInformation)
+{
+ PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ UNICODE_STRING ImageName;
+ PVOID ImageBase;
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ ULONG_PTR EntryPoint;
+ NTSTATUS Status;
+ ULONG DirSize;
+ PIMAGE_NT_HEADERS NtHeader;
+
+ /* Validate size */
+ if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
{
- return(STATUS_INFO_LENGTH_MISMATCH);
+ /* Incorrect buffer length, fail */
+ return STATUS_INFO_LENGTH_MISMATCH;
}
- return(LdrpLoadImage(&Sli->DriverName,
- &Sli->ImageAddress,
- &Sli->SectionPointer,
- &Sli->EntryPoint,
- (PVOID)&Sli->ExportSectionPointer));
+ /* Only kernel-mode can call this function */
+ if (PreviousMode != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
+
+ /* Load the driver */
+ ImageName = DriverInfo->DriverName;
+ Status = MmLoadSystemImage(&ImageName,
+ NULL,
+ NULL,
+ 0,
+ (PVOID)&ModuleObject,
+ &ImageBase);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Return the export pointer */
+ DriverInfo->ExportSectionPointer =
+ RtlImageDirectoryEntryToData(ImageBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &DirSize);
+
+ /* Get the entrypoint */
+ NtHeader = RtlImageNtHeader(ImageBase);
+ EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
+ EntryPoint += (ULONG_PTR)ImageBase;
+
+ /* Save other data */
+ DriverInfo->ImageAddress = ImageBase;
+ DriverInfo->SectionPointer = NULL;
+ DriverInfo->EntryPoint = (PVOID)EntryPoint;
+ DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
+
+ /* All is good */
+ return STATUS_SUCCESS;
}
/* Class 27 - Unload Image */
-SSI_DEF(SystemUnloadImage)
+SSI_DEF(SystemUnloadGdiDriverInformation)
{
- PVOID Sui = (PVOID)Buffer;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ PLIST_ENTRY NextEntry;
+ PVOID BaseAddr = *((PVOID*)Buffer);
- if (sizeof(PVOID) != Size)
+ if(Size != sizeof(PVOID))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ if(KeGetPreviousMode() != KernelMode)
+ return STATUS_PRIVILEGE_NOT_HELD;
+
+ // Scan the module list
+ NextEntry = PsLoadedModuleList.Flink;
+ while(NextEntry != &PsLoadedModuleList)
{
- return(STATUS_INFO_LENGTH_MISMATCH);
+ 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;
}
- return(LdrpUnloadImage(Sui));
}
/* Class 28 - Time Adjustment Information */
}
/* Class 38 - Load And Call Image */
-SSI_DEF(SystemLoadAndCallImage)
-{
- PUNICODE_STRING Slci = (PUNICODE_STRING)Buffer;
+SSI_DEF(SystemExtendServiceTableInformation)
+{
+ UNICODE_STRING ImageName;
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ PLDR_DATA_TABLE_ENTRY ModuleObject;
+ NTSTATUS Status;
+ PIMAGE_NT_HEADERS NtHeader;
+ DRIVER_OBJECT Win32k;
+ PDRIVER_INITIALIZE DriverInit;
+ PVOID ImageBase;
+ ULONG_PTR EntryPoint;
+
+ /* Validate the size */
+ if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
+
+ /* Check who is calling */
+ if (PreviousMode != KernelMode)
+ {
+ /* Make sure we can load drivers */
+ if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
+ {
+ /* FIXME: We can't, fail */
+ //return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Probe and capture the driver name */
+ ProbeAndCaptureUnicodeString(&ImageName, UserMode, Buffer);
- if (sizeof(UNICODE_STRING) != Size)
+ /* Force kernel as previous mode */
+ return ZwSetSystemInformation(SystemExtendServiceTableInformation,
+ &ImageName,
+ sizeof(ImageName));
+ }
+
+ /* Just copy the string */
+ ImageName = *(PUNICODE_STRING)Buffer;
+
+ /* Load the image */
+ Status = MmLoadSystemImage(&ImageName,
+ NULL,
+ NULL,
+ 0,
+ (PVOID)&ModuleObject,
+ &ImageBase);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Get the headers */
+ NtHeader = RtlImageNtHeader(ImageBase);
+ if (!NtHeader)
{
- return(STATUS_INFO_LENGTH_MISMATCH);
+ /* Fail */
+ MmUnloadSystemImage(ModuleObject);
+ return STATUS_INVALID_IMAGE_FORMAT;
}
- return(LdrpLoadAndCallImage(Slci));
+ /* Get the entrypoint */
+ EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
+ EntryPoint += (ULONG_PTR)ImageBase;
+ DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
+
+ /* Create a dummy device */
+ RtlZeroMemory(&Win32k, sizeof(Win32k));
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+ Win32k.DriverStart = ImageBase;
+
+ /* Call it */
+ Status = (DriverInit)(&Win32k, NULL);
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ /* Unload if we failed */
+ if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
+ return Status;
}
/* Class 39 - Priority Separation */
SI_QX(SystemInterruptInformation),
SI_QS(SystemDpcBehaviourInformation),
SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
- SI_XS(SystemLoadImage),
- SI_XS(SystemUnloadImage),
+ SI_XS(SystemLoadGdiDriverInformation),
+ SI_XS(SystemUnloadGdiDriverInformation),
SI_QS(SystemTimeAdjustmentInformation),
SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
SI_QX(SystemKernelDebuggerInformation),
SI_QX(SystemContextSwitchInformation),
SI_QS(SystemRegistryQuotaInformation),
- SI_XS(SystemLoadAndCallImage),
+ SI_XS(SystemExtendServiceTableInformation),
SI_XS(SystemPrioritySeperation),
SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
SI_QX(SystemDockInformation), /* it should be SI_XX */
SI_QX(SystemSessionProcessesInformation)
};
+C_ASSERT(SystemBasicInformation == 0);
+#define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
+#define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG Length,
NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
PAGED_CODE();
-
+
PreviousMode = ExGetPreviousMode();
-
- _SEH_TRY
+
+ _SEH2_TRY
{
if (PreviousMode != KernelMode)
{
/* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
- ProbeForWrite(SystemInformation, Length, 1);
+ ProbeForWrite(SystemInformation, Length, 1);
if (UnsafeResultLength != NULL)
ProbeForWriteUlong(UnsafeResultLength);
}
- /* Clear user buffer. */
- RtlZeroMemory(SystemInformation, Length);
-
/*
* Check the request is valid.
*/
- if (SystemInformationClass >= MaxSystemInfoClass)
+ if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
{
- return (STATUS_INVALID_INFO_CLASS);
+ _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
}
if (NULL != CallQS [SystemInformationClass].Query)
{
if (PreviousMode != KernelMode)
{
- _SEH_TRY
- {
*UnsafeResultLength = ResultLength;
- }
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
- {
- FStatus = _SEH_GetExceptionCode();
- }
- _SEH_END;
}
else
{
}
}
}
- _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ _SEH2_EXCEPT(ExSystemExceptionFilter())
{
- FStatus = _SEH_GetExceptionCode();
+ FStatus = _SEH2_GetExceptionCode();
}
- _SEH_END;
+ _SEH2_END;
return (FStatus);
}
NTSTATUS
-STDCALL
+NTAPI
NtSetSystemInformation (
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN PVOID SystemInformation,
/*
* Check the request is valid.
*/
- if ( (SystemInformationClass >= SystemBasicInformation)
- && (SystemInformationClass < MaxSystemInfoClass)
+ if ( (SystemInformationClass >= MIN_SYSTEM_INFO_CLASS)
+ && (SystemInformationClass < MAX_SYSTEM_INFO_CLASS)
)
{
if (NULL != CallQS [SystemInformationClass].Set)
NTSTATUS
-STDCALL
+NTAPI
NtFlushInstructionCache (
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
{
PAGED_CODE();
+#if defined(_M_IX86)
__wbinvd();
+#elif defined(_M_PPC)
+ __asm__ __volatile__("tlbsync");
+#elif defined(_M_MIPS)
+ DPRINT1("NtFlushInstructionCache() is not implemented\n");
+ for (;;);
+#elif defined(_M_ARM)
+ __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
+#elif defined(_M_AMD64)
+ DPRINT1("NtFlushInstructionCache() is not implemented\n");
+ for (;;);
+#else
+#error Unknown architecture
+#endif
return STATUS_SUCCESS;
}
return KeGetCurrentProcessorNumber();
}
-/* EOF */
+/* EOF */
\ No newline at end of file