#define NDEBUG
#include <debug.h>
-VOID MmPrintMemoryStatistic(VOID);
+/* The maximum size of an environment value (in bytes) */
+#define MAX_ENVVAL_SIZE 1024
FAST_MUTEX ExpEnvironmentLock;
ERESOURCE ExpFirmwareTableResource;
LIST_ENTRY ExpFirmwareTableProviderListHead;
+FORCEINLINE
+NTSTATUS
+ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount,
+ IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo)
+{
+ PCHAR p;
+ NTSTATUS Status;
+ ANSI_STRING ModuleName;
+
+ /* 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 = (USHORT)(p - ModuleName.Buffer);
+ }
+ else
+ {
+ /* Return empty name */
+ ModuleInfo->FullPathName[0] = ANSI_NULL;
+ ModuleInfo->OffsetToFileName = 0;
+ }
+
+ return Status;
+}
+
NTSTATUS
NTAPI
ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
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);
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;
- }
+ Status = ExpConvertLdrModuleToRtlModule(ModuleCount,
+ LdrEntry,
+ ModuleInfo);
/* Go to the next module */
ModuleInfo++;
/* Check if caller also wanted user modules */
if (UserModeList)
{
- /* FIXME: TODO */
- DPRINT1("User-mode list not yet supported in ReactOS!\n");
+ NextEntry = UserModeList->Flink;
+ while (NextEntry != UserModeList)
+ {
+ /* 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)
+ {
+ Status = ExpConvertLdrModuleToRtlModule(ModuleCount,
+ LdrEntry,
+ ModuleInfo);
+
+ /* 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;
+ }
}
/* Update return length */
return Status;
}
+VOID
+NTAPI
+ExUnlockUserBuffer(PMDL Mdl)
+{
+ MmUnlockPages(Mdl);
+ ExFreePoolWithTag(Mdl, TAG_MDL);
+}
+
+NTSTATUS
+NTAPI
+ExLockUserBuffer(
+ PVOID BaseAddress,
+ ULONG Length,
+ KPROCESSOR_MODE AccessMode,
+ LOCK_OPERATION Operation,
+ PVOID *MappedSystemVa,
+ PMDL *OutMdl)
+{
+ PMDL Mdl;
+ PAGED_CODE();
+
+ *MappedSystemVa = NULL;
+ *OutMdl = NULL;
+
+ /* Allocate an MDL for the buffer */
+ Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, TRUE, NULL);
+ if (Mdl == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Enter SEH for probing */
+ _SEH2_TRY
+ {
+ MmProbeAndLockPages(Mdl, AccessMode, Operation);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ExFreePoolWithTag(Mdl, TAG_MDL);
+ return _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Return the safe kernel mode buffer */
+ *MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+ if (*MappedSystemVa == NULL)
+ {
+ ExUnlockUserBuffer(Mdl);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Return the MDL */
+ *OutMdl = Mdl;
+ return STATUS_SUCCESS;
+}
+
/* FUNCTIONS *****************************************************************/
/*
Prcb = KeGetCurrentPrcb();
- ScaledIdle = Prcb->IdleThread->KernelTime * 100;
+ ScaledIdle = (ULONGLONG)Prcb->IdleThread->KernelTime * 100;
TotalTime = Prcb->KernelTime + Prcb->UserTime;
if (TotalTime != 0)
*CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime));
ANSI_STRING AName;
UNICODE_STRING WName;
ARC_STATUS Result;
- PCH Value;
+ PCH AnsiValueBuffer;
ANSI_STRING AValue;
UNICODE_STRING WValue;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PAGED_CODE();
+ /* Check if the call came from user mode */
PreviousMode = ExGetPreviousMode();
-
if (PreviousMode != KernelMode)
{
_SEH2_TRY
{
- ProbeForRead(VariableName,
- sizeof(UNICODE_STRING),
- sizeof(ULONG));
-
- ProbeForWrite(ValueBuffer,
- ValueBufferLength,
- sizeof(WCHAR));
-
+ /* Probe the input and output buffers */
+ ProbeForRead(VariableName, sizeof(UNICODE_STRING), sizeof(ULONG));
+ ProbeForWrite(ValueBuffer, ValueBufferLength, sizeof(WCHAR));
if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
_SEH2_END;
}
- /*
- * Copy the name to kernel space if necessary and convert it to ANSI.
- */
- Status = ProbeAndCaptureUnicodeString(&WName,
- PreviousMode,
- VariableName);
- if (NT_SUCCESS(Status))
+ /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
+ if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, PreviousMode))
{
- /*
- * according to ntinternals the SeSystemEnvironmentName privilege is required!
- */
- if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
- PreviousMode))
- {
- ReleaseCapturedUnicodeString(&WName, PreviousMode);
- DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
- return STATUS_PRIVILEGE_NOT_HELD;
- }
+ DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
- /*
- * convert the value name to ansi
- */
- Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
- ReleaseCapturedUnicodeString(&WName, PreviousMode);
+ /* Copy the name to kernel space if necessary */
+ Status = ProbeAndCaptureUnicodeString(&WName, PreviousMode, VariableName);
+ if (!NT_SUCCESS(Status)) return Status;
- if (!NT_SUCCESS(Status)) return Status;
+ /* Convert the name to ANSI and release the captured UNICODE string */
+ Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
+ ReleaseCapturedUnicodeString(&WName, PreviousMode);
+ if (!NT_SUCCESS(Status)) return Status;
- /*
- * Create a temporary buffer for the value
- */
- Value = ExAllocatePool(NonPagedPool, ValueBufferLength);
- if (Value == NULL)
- {
- RtlFreeAnsiString(&AName);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ /* Allocate a buffer for the ANSI environment variable */
+ AnsiValueBuffer = ExAllocatePoolWithTag(NonPagedPool, MAX_ENVVAL_SIZE, 'rvnE');
+ if (AnsiValueBuffer == NULL)
+ {
+ RtlFreeAnsiString(&AName);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- /*
- * Get the environment variable
- */
- Result = HalGetEnvironmentVariable(AName.Buffer,
- (USHORT)ValueBufferLength,
- Value);
- if (!Result)
- {
- RtlFreeAnsiString(&AName);
- ExFreePool(Value);
- return STATUS_UNSUCCESSFUL;
- }
+ /* Get the environment variable and free the ANSI name */
+ Result = HalGetEnvironmentVariable(AName.Buffer,
+ MAX_ENVVAL_SIZE,
+ AnsiValueBuffer);
+ RtlFreeAnsiString(&AName);
- /*
- * Convert the result to UNICODE, protect with SEH in case the value buffer
- * isn't NULL-terminated!
- */
+ /* Check if we had success */
+ if (Result == ESUCCESS)
+ {
+ /* Copy the result back to the caller. */
_SEH2_TRY
{
- RtlInitAnsiString(&AValue, Value);
- Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
+ /* Initialize ANSI string from the result */
+ RtlInitAnsiString(&AValue, AnsiValueBuffer);
+
+ /* Initialize a UNICODE string from the callers buffer */
+ RtlInitEmptyUnicodeString(&WValue, ValueBuffer, (USHORT)ValueBufferLength);
+
+ /* Convert the result to UNICODE */
+ Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, FALSE);
+
+ if (ReturnLength != NULL)
+ *ReturnLength = WValue.Length;
}
_SEH2_EXCEPT(ExSystemExceptionFilter())
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
-
- if (NT_SUCCESS(Status))
- {
- /*
- * Copy the result back to the caller.
- */
- _SEH2_TRY
- {
- RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
- ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
- if (ReturnLength != NULL)
- {
- *ReturnLength = WValue.Length + sizeof(WCHAR);
- }
-
- Status = STATUS_SUCCESS;
- }
- _SEH2_EXCEPT(ExSystemExceptionFilter())
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- }
-
- /*
- * Cleanup allocated resources.
- */
- RtlFreeAnsiString(&AName);
- ExFreePool(Value);
+ }
+ else
+ {
+ Status = STATUS_UNSUCCESSFUL;
}
+ /* Free the allocated ANSI value buffer */
+ ExFreePoolWithTag(AnsiValueBuffer, 'rvnE');
+
return Status;
}
#define SSI_DEF(n) \
static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
+VOID
+NTAPI
+ExQueryPoolUsage(OUT PULONG PagedPoolPages,
+ OUT PULONG NonPagedPoolPages,
+ OUT PULONG PagedPoolAllocs,
+ OUT PULONG PagedPoolFrees,
+ OUT PULONG PagedPoolLookasideHits,
+ OUT PULONG NonPagedPoolAllocs,
+ OUT PULONG NonPagedPoolFrees,
+ OUT PULONG NonPagedPoolLookasideHits);
/* Class 0 - Basic Information */
QSI_DEF(SystemBasicInformation)
Sbi->TimerResolution = KeMaximumIncrement;
Sbi->PageSize = PAGE_SIZE;
Sbi->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
- Sbi->LowestPhysicalPageNumber = MmLowestPhysicalPage;
- Sbi->HighestPhysicalPageNumber = MmHighestPhysicalPage;
+ Sbi->LowestPhysicalPageNumber = (ULONG)MmLowestPhysicalPage;
+ Sbi->HighestPhysicalPageNumber = (ULONG)MmHighestPhysicalPage;
Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
Spi->Reserved = 0;
Spi->ProcessorFeatureBits = KeFeatureBits;
- DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
+ DPRINT("Arch %u Level %u Rev 0x%x\n", Spi->ProcessorArchitecture,
Spi->ProcessorLevel, Spi->ProcessorRevision);
return STATUS_SUCCESS;
Spi->IoWriteOperationCount = IoWriteOperationCount;
Spi->IoOtherOperationCount = IoOtherOperationCount;
- Spi->AvailablePages = MmAvailablePages;
+ Spi->AvailablePages = (ULONG)MmAvailablePages;
/*
* Add up all the used "Committed" memory + pagefile.
* Not sure this is right. 8^\
Spi->MappedPagesWriteCount = 0; /* FIXME */
Spi->MappedWriteIoCount = 0; /* FIXME */
- Spi->PagedPoolPages = 0; /* FIXME */
- Spi->PagedPoolAllocs = 0; /* FIXME */
- Spi->PagedPoolFrees = 0; /* FIXME */
- Spi->NonPagedPoolPages = 0; /* FIXME */
- Spi->NonPagedPoolAllocs = 0; /* FIXME */
- Spi->NonPagedPoolFrees = 0; /* FIXME */
-
+ Spi->PagedPoolPages = 0;
+ Spi->NonPagedPoolPages = 0;
+ Spi->PagedPoolAllocs = 0;
+ Spi->PagedPoolFrees = 0;
+ Spi->PagedPoolLookasideHits = 0;
+ Spi->NonPagedPoolAllocs = 0;
+ Spi->NonPagedPoolFrees = 0;
+ Spi->NonPagedPoolLookasideHits = 0;
+ ExQueryPoolUsage(&Spi->PagedPoolPages,
+ &Spi->NonPagedPoolPages,
+ &Spi->PagedPoolAllocs,
+ &Spi->PagedPoolFrees,
+ &Spi->PagedPoolLookasideHits,
+ &Spi->NonPagedPoolAllocs,
+ &Spi->NonPagedPoolFrees,
+ &Spi->NonPagedPoolLookasideHits);
Spi->FreeSystemPtes = 0; /* FIXME */
Spi->ResidentSystemCodePage = 0; /* FIXME */
Spi->TotalSystemDriverPages = 0; /* FIXME */
- Spi->TotalSystemCodePages = 0; /* FIXME */
- Spi->NonPagedPoolLookasideHits = 0; /* FIXME */
- Spi->PagedPoolLookasideHits = 0; /* FIXME */
Spi->Spare3Count = 0; /* FIXME */
Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
/* Check for overflow */
if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
+ {
Overflow = TRUE;
+ }
/* Zero user's buffer */
if (!Overflow) RtlZeroMemory(Spi, Size);
{
SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
+ if ((Process->ProcessExiting) &&
+ (Process->Pcb.Header.SignalState) &&
+ !(Process->ActiveThreads) &&
+ (IsListEmpty(&Process->Pcb.ThreadListHead)))
+ {
+ DPRINT1("Process %p (%s:%p) is a zombie\n",
+ Process, Process->ImageFileName, Process->UniqueProcessId);
+ CurrentSize = 0;
+ ImageNameMaximumLength = 0;
+ goto Skip;
+ }
+
ThreadsCount = 0;
- CurrentEntry = Process->ThreadListHead.Flink;
- while (CurrentEntry != &Process->ThreadListHead)
+ CurrentEntry = Process->Pcb.ThreadListHead.Flink;
+ while (CurrentEntry != &Process->Pcb.ThreadListHead)
{
ThreadsCount++;
CurrentEntry = CurrentEntry->Flink;
}
}
}
- if (!ImageNameLength && Process != PsIdleProcess && Process->ImageFileName)
+ if (!ImageNameLength && Process != PsIdleProcess)
{
- ImageNameLength = strlen(Process->ImageFileName) * sizeof(WCHAR);
+ ImageNameLength = (USHORT)strlen(Process->ImageFileName) * sizeof(WCHAR);
}
/* Round up the image name length as NT does */
/* Check for overflow */
if (TotalSize > Size)
+ {
Overflow = TRUE;
+ }
/* Fill system information */
if (!Overflow)
RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
/* Release the memory allocated by SeLocateProcessImageName */
- ExFreePool(ProcessImageName);
+ ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
}
- else if (Process->ImageFileName)
+ else
{
RtlInitAnsiString(&ImageName, Process->ImageFileName);
RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
SpiCurrent->PrivatePageCount = Process->CommitCharge;
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
- CurrentEntry = Process->ThreadListHead.Flink;
- while (CurrentEntry != &Process->ThreadListHead)
+ CurrentEntry = Process->Pcb.ThreadListHead.Flink;
+ while (CurrentEntry != &Process->Pcb.ThreadListHead)
{
- CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
+ CurrentThread = (PETHREAD)CONTAINING_RECORD(CurrentEntry, KTHREAD,
ThreadListEntry);
ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
}
/* Handle idle process entry */
+Skip:
if (Process == PsIdleProcess) Process = NULL;
Process = PsGetNextProcess(Process);
/* Class 22 - Pool Tag Information */
QSI_DEF(SystemPoolTagInformation)
{
- /* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
+ if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
+ return ExGetPoolTagInfo(Buffer, Size, ReqSize);
}
/* Class 23 - Interrupt Information for all processors */
TheIdleProcess = PsIdleProcess;
- DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
+ DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
TheIdleProcess->UniqueProcessId,
TheIdleProcess->Pcb.KernelTime,
MiFreeSwapPages,
MiUsedSwapPages);
-#ifndef NDEBUG
- MmPrintMemoryStatistic();
-#endif
-
*Spi = MiMemoryConsumers[MC_USER].PagesUsed;
return STATUS_SUCCESS;
/* Class 27 - Unload Image */
SSI_DEF(SystemUnloadGdiDriverInformation)
{
- PVOID SectionPointer = Buffer;
+ PVOID *SectionPointer = Buffer;
/* Validate size */
if (Size != sizeof(PVOID))
if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
/* Unload the image */
- MmUnloadSystemImage(SectionPointer);
+ MmUnloadSystemImage(*SectionPointer);
return STATUS_SUCCESS;
}
/* Give time values to our caller */
TimeInfo->TimeIncrement = KeMaximumIncrement;
TimeInfo->TimeAdjustment = KeTimeAdjustment;
- TimeInfo->Enable = TRUE;
+ TimeInfo->Enable = !KiTimeAdjustmentEnabled;
return STATUS_SUCCESS;
}
SSI_DEF(SystemTimeAdjustmentInformation)
{
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
- /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
- (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
+ PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
+ (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;
/* Check size of a buffer, it must match our expectations */
if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
}
}
- /* TODO: Set time adjustment information */
- DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
- return STATUS_NOT_IMPLEMENTED;
+ /* FIXME: behaviour suggests the member be named 'Disable' */
+ if (TimeInfo->Enable)
+ {
+ /* Disable time adjustment and set default value */
+ KiTimeAdjustmentEnabled = FALSE;
+ KeTimeAdjustment = KeMaximumIncrement;
+ }
+ else
+ {
+ /* Check if a valid time adjustment value is given */
+ if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2;
+
+ /* Enable time adjustment and set the adjustment value */
+ KiTimeAdjustmentEnabled = TRUE;
+ KeTimeAdjustment = TimeInfo->TimeAdjustment;
+ }
+
+ return STATUS_SUCCESS;
}
/* Class 29 - Summary Memory Information */
/* Check who is calling */
if (PreviousMode != KernelMode)
{
+ static const UNICODE_STRING Win32kName =
+ RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\win32k.sys");
+
/* Make sure we can load drivers */
if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
{
/* FIXME: We can't, fail */
- //return STATUS_PRIVILEGE_NOT_HELD;
+ return STATUS_PRIVILEGE_NOT_HELD;
}
- }
- /* Probe and capture the driver name */
- ProbeAndCaptureUnicodeString(&ImageName, PreviousMode, Buffer);
+ _SEH2_TRY
+ {
+ /* Probe and copy the unicode string */
+ ProbeForRead(Buffer, sizeof(ImageName), 1);
+ ImageName = *(PUNICODE_STRING)Buffer;
+
+ /* Probe the string buffer */
+ ProbeForRead(ImageName.Buffer, ImageName.Length, sizeof(WCHAR));
+
+ /* Check if we have the correct name (nothing else is allowed!) */
+ if (!RtlEqualUnicodeString(&ImageName, &Win32kName, FALSE))
+ {
+ _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ /* Recursively call the function, so that we are from kernel mode */
+ return ZwSetSystemInformation(SystemExtendServiceTableInformation,
+ (PVOID)&Win32kName,
+ sizeof(Win32kName));
+ }
/* Load the image */
- Status = MmLoadSystemImage(&ImageName,
+ Status = MmLoadSystemImage((PUNICODE_STRING)Buffer,
NULL,
NULL,
0,
(PVOID)&ModuleObject,
&ImageBase);
- /* Release String */
- ReleaseCapturedUnicodeString(&ImageName, PreviousMode);
-
if (!NT_SUCCESS(Status)) return Status;
/* Get the headers */
return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
}
+static
+VOID
+ExpCopyLookasideInformation(
+ PSYSTEM_LOOKASIDE_INFORMATION *InfoPointer,
+ PULONG RemainingPointer,
+ PLIST_ENTRY ListHead,
+ BOOLEAN ListUsesMisses)
+
+{
+ PSYSTEM_LOOKASIDE_INFORMATION Info;
+ PGENERAL_LOOKASIDE LookasideList;
+ PLIST_ENTRY ListEntry;
+ ULONG Remaining;
+
+ /* Get info pointer and remaining count of free array element */
+ Info = *InfoPointer;
+ Remaining = *RemainingPointer;
+
+ /* Loop as long as we have lookaside lists and free array elements */
+ for (ListEntry = ListHead->Flink;
+ (ListEntry != ListHead) && (Remaining > 0);
+ ListEntry = ListEntry->Flink, Remaining--)
+ {
+ LookasideList = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry);
+
+ /* Fill the next array element */
+ Info->CurrentDepth = LookasideList->Depth;
+ Info->MaximumDepth = LookasideList->MaximumDepth;
+ Info->TotalAllocates = LookasideList->TotalAllocates;
+ Info->TotalFrees = LookasideList->TotalFrees;
+ Info->Type = LookasideList->Type;
+ Info->Tag = LookasideList->Tag;
+ Info->Size = LookasideList->Size;
+
+ /* Check how the lists track misses/hits */
+ if (ListUsesMisses)
+ {
+ /* Copy misses */
+ Info->AllocateMisses = LookasideList->AllocateMisses;
+ Info->FreeMisses = LookasideList->FreeMisses;
+ }
+ else
+ {
+ /* Calculate misses */
+ Info->AllocateMisses = LookasideList->TotalAllocates
+ - LookasideList->AllocateHits;
+ Info->FreeMisses = LookasideList->TotalFrees
+ - LookasideList->FreeHits;
+ }
+ }
+
+ /* Return the updated pointer and remaining count */
+ *InfoPointer = Info;
+ *RemainingPointer = Remaining;
+}
/* Class 45 - Lookaside Information */
QSI_DEF(SystemLookasideInformation)
{
- /* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
+ KPROCESSOR_MODE PreviousMode;
+ PSYSTEM_LOOKASIDE_INFORMATION Info;
+ PMDL Mdl;
+ ULONG MaxCount, Remaining;
+ KIRQL OldIrql;
+ NTSTATUS Status;
+
+ /* First we need to lock down the memory, since we are going to access it
+ at high IRQL */
+ PreviousMode = ExGetPreviousMode();
+ Status = ExLockUserBuffer(Buffer,
+ Size,
+ PreviousMode,
+ IoWriteAccess,
+ (PVOID*)&Info,
+ &Mdl);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
+ return Status;
+ }
+
+ /* Calculate how many items we can store */
+ Remaining = MaxCount = Size / sizeof(SYSTEM_LOOKASIDE_INFORMATION);
+ if (Remaining == 0)
+ {
+ goto Leave;
+ }
+
+ /* Copy info from pool lookaside lists */
+ ExpCopyLookasideInformation(&Info,
+ &Remaining,
+ &ExPoolLookasideListHead,
+ FALSE);
+ if (Remaining == 0)
+ {
+ goto Leave;
+ }
+
+ /* Copy info from system lookaside lists */
+ ExpCopyLookasideInformation(&Info,
+ &Remaining,
+ &ExSystemLookasideListHead,
+ TRUE);
+ if (Remaining == 0)
+ {
+ goto Leave;
+ }
+
+ /* Acquire spinlock for ExpNonPagedLookasideListHead */
+ OldIrql = KfAcquireSpinLock(&ExpNonPagedLookasideListLock);
+
+ /* Copy info from non-paged lookaside lists */
+ ExpCopyLookasideInformation(&Info,
+ &Remaining,
+ &ExpNonPagedLookasideListHead,
+ TRUE);
+
+ /* Release spinlock for ExpNonPagedLookasideListHead */
+ KfReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+
+ if (Remaining == 0)
+ {
+ goto Leave;
+ }
+
+ /* Acquire spinlock for ExpPagedLookasideListHead */
+ OldIrql = KfAcquireSpinLock(&ExpPagedLookasideListLock);
+
+ /* Copy info from paged lookaside lists */
+ ExpCopyLookasideInformation(&Info,
+ &Remaining,
+ &ExpPagedLookasideListHead,
+ TRUE);
+
+ /* Release spinlock for ExpPagedLookasideListHead */
+ KfReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
+
+Leave:
+
+ /* Release the locked user buffer */
+ ExUnlockUserBuffer(Mdl);
+
+ /* Return the size of the actually written data */
+ *ReqSize = (MaxCount - Remaining) * sizeof(SYSTEM_LOOKASIDE_INFORMATION);
+ return STATUS_SUCCESS;
}
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS
+NTAPI
+MmSessionCreate(OUT PULONG SessionId);
+
+NTSTATUS
+NTAPI
+MmSessionDelete(IN ULONG SessionId);
/* Class 47 - Create a new session (TSE) */
SSI_DEF(SystemCreateSession)
{
- /* FIXME */
- DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
+ ULONG SessionId;
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+ NTSTATUS Status;
+
+ if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
+
+ if (PreviousMode != KernelMode)
+ {
+ if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
+ {
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+ }
+
+ Status = MmSessionCreate(&SessionId);
+ if (NT_SUCCESS(Status)) *(PULONG)Buffer = SessionId;
+
+ return Status;
}
/* Class 48 - Delete an existing session (TSE) */
SSI_DEF(SystemDeleteSession)
{
- /* FIXME */
- DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
+ ULONG SessionId;
+ KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+
+ if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
+
+ if (PreviousMode != KernelMode)
+ {
+ if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
+ {
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+ }
+
+ SessionId = *(PULONG)Buffer;
+
+ return MmSessionDelete(SessionId);
}
/* Class 50 - System range start address */
QSI_DEF(SystemRangeStartInformation)
{
- /* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
-}
+ /* Check user buffer's size */
+ if (Size != sizeof(ULONG_PTR)) return STATUS_INFO_LENGTH_MISMATCH;
+
+ *(PULONG_PTR)Buffer = (ULONG_PTR)MmSystemRangeStart;
+
+ if (ReqSize) *ReqSize = sizeof(ULONG_PTR);
+ return STATUS_SUCCESS;
+}
/* Class 51 - Driver verifier information */
QSI_DEF(SystemVerifierInformation)
SI_QX(SystemPerformanceInformation),
SI_QX(SystemTimeOfDayInformation),
SI_QX(SystemPathInformation), /* should be SI_XX */
- SI_QX(SystemProcessInformation),
- SI_QX(SystemCallCountInformation),
- SI_QX(SystemDeviceInformation),
- SI_QX(SystemProcessorPerformanceInformation),
- SI_QS(SystemFlagsInformation),
+ SI_QX(SystemProcessInformation), // aka SystemProcessesAndThreadsInformation
+ SI_QX(SystemCallCountInformation), // aka SystemCallCounts
+ SI_QX(SystemDeviceInformation), // aka SystemConfigurationInformation
+ SI_QX(SystemProcessorPerformanceInformation), // aka SystemProcessorTimes
+ SI_QS(SystemFlagsInformation), // aka SystemGlobalFlag
SI_QX(SystemCallTimeInformation), /* should be SI_XX */
SI_QX(SystemModuleInformation),
- SI_QX(SystemLocksInformation),
+ SI_QX(SystemLocksInformation), // aka SystemLockInformation
SI_QX(SystemStackTraceInformation), /* should be SI_XX */
SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
SI_QX(SystemHandleInformation),
SI_QX(SystemObjectInformation),
- SI_QX(SystemPageFileInformation),
- SI_QX(SystemVdmInstemulInformation),
+ SI_QX(SystemPageFileInformation), // aka SystemPagefileInformation
+ SI_QX(SystemVdmInstemulInformation), // aka SystemInstructionEmulationCounts
SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
- SI_QS(SystemFileCacheInformation),
+ SI_QS(SystemFileCacheInformation), // aka SystemCacheInformation
SI_QX(SystemPoolTagInformation),
- SI_QX(SystemInterruptInformation),
- SI_QS(SystemDpcBehaviourInformation),
+ SI_QX(SystemInterruptInformation), // aka SystemProcessorStatistics
+ SI_QS(SystemDpcBehaviourInformation), // aka SystemDpcInformation
SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
- SI_XS(SystemLoadGdiDriverInformation),
- SI_XS(SystemUnloadGdiDriverInformation),
- SI_QS(SystemTimeAdjustmentInformation),
+ SI_XS(SystemLoadGdiDriverInformation), // correct: SystemLoadImage
+ SI_XS(SystemUnloadGdiDriverInformation), // correct: SystemUnloadImage
+ SI_QS(SystemTimeAdjustmentInformation), // aka SystemTimeAdjustment
SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
- SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
+ SI_QX(SystemEventIdsInformation), /* it should be SI_XX */ // SystemPerformanceTraceInformation
SI_QX(SystemCrashDumpInformation),
SI_QX(SystemExceptionInformation),
SI_QX(SystemCrashDumpStateInformation),
SI_QX(SystemKernelDebuggerInformation),
SI_QX(SystemContextSwitchInformation),
SI_QS(SystemRegistryQuotaInformation),
- SI_XS(SystemExtendServiceTableInformation),
+ SI_XS(SystemExtendServiceTableInformation), // correct: SystemLoadAndCallImage
SI_XS(SystemPrioritySeperation),
SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
SI_QX(SystemDockInformation), /* it should be SI_XX */
- SI_QX(SystemPowerInformation), /* it should be SI_XX */
+ SI_QX(SystemPowerInformation), /* it should be SI_XX */ // SystemPowerInformationNative? SystemInvalidInfoClass2
SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
- SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
+ SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */ // aka SystemTimeZoneInformation
SI_QX(SystemLookasideInformation),
SI_XS(SystemSetTimeSlipEvent),
SI_XS(SystemCreateSession),
SI_XS(SystemDeleteSession),
- SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
+ SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */ // SystemSessionInformation?
SI_QX(SystemRangeStartInformation),
SI_QS(SystemVerifierInformation),
SI_XS(SystemAddVerifier),
OUT PULONG UnsafeResultLength)
{
KPROCESSOR_MODE PreviousMode;
- ULONG ResultLength;
+ ULONG ResultLength = 0;
NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
PAGED_CODE();
ProbeForWriteUlong(UnsafeResultLength);
}
+ if (UnsafeResultLength)
+ *UnsafeResultLength = 0;
+
/*
- * Check the request is valid.
+ * Check if the request is valid.
*/
if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
{
FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
Length,
&ResultLength);
- if (UnsafeResultLength != NULL)
- {
- if (PreviousMode != KernelMode)
- {
- *UnsafeResultLength = ResultLength;
- }
- else
- {
- *UnsafeResultLength = ResultLength;
- }
- }
+
+ /* Save the result length to the caller */
+ if (UnsafeResultLength)
+ *UnsafeResultLength = ResultLength;
}
}
_SEH2_EXCEPT(ExSystemExceptionFilter())