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 = (USHORT)(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 *****************************************************************/
/*
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;
PETHREAD CurrentThread;
ANSI_STRING ImageName;
ULONG CurrentSize;
- USHORT ImageNameMaximumLength; // image name len in bytes
+ USHORT ImageNameMaximumLength; // image name length in bytes
USHORT ImageNameLength;
PLIST_ENTRY CurrentEntry;
ULONG TotalSize = 0, ThreadsCount;
ULONG TotalUser, TotalKernel;
PUCHAR Current;
NTSTATUS Status = STATUS_SUCCESS;
- PUNICODE_STRING ProcessImageName;
+ PUNICODE_STRING TempProcessImageName;
+ _SEH2_VOLATILE PUNICODE_STRING ProcessImageName = NULL;
PWCHAR szSrc;
BOOLEAN Overflow = FALSE;
!(Process->ActiveThreads) &&
(IsListEmpty(&Process->Pcb.ThreadListHead)))
{
- DPRINT1("Process %p (%s:%lx) is a zombie\n",
+ DPRINT1("Process %p (%s:%p) is a zombie\n",
Process, Process->ImageFileName, Process->UniqueProcessId);
CurrentSize = 0;
ImageNameMaximumLength = 0;
// size of the structure for every process
CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
ImageNameLength = 0;
- Status = SeLocateProcessImageName(Process, &ProcessImageName);
+ Status = SeLocateProcessImageName(Process, &TempProcessImageName);
+ ProcessImageName = TempProcessImageName;
szSrc = NULL;
if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0))
{
/* Fill system information */
if (!Overflow)
{
- SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginnnig of the next structure
+ SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginning of the next structure
SpiCurrent->NumberOfThreads = ThreadsCount;
SpiCurrent->CreateTime = Process->CreateTime;
SpiCurrent->ImageName.Length = ImageNameLength;
if (szSrc)
{
RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
-
- /* Release the memory allocated by SeLocateProcessImageName */
- ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
}
else
{
CurrentEntry = Process->Pcb.ThreadListHead.Flink;
while (CurrentEntry != &Process->Pcb.ThreadListHead)
{
- CurrentThread = (PETHREAD)CONTAINING_RECORD(CurrentEntry, KTHREAD,
- ThreadListEntry);
+ CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD, Tcb.ThreadListEntry);
ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
}
+ if (ProcessImageName)
+ {
+ /* Release the memory allocated by SeLocateProcessImageName */
+ ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
+ ProcessImageName = NULL;
+ }
+
/* Handle idle process entry */
Skip:
if (Process == PsIdleProcess) Process = NULL;
{
if(Process != NULL)
ObDereferenceObject(Process);
+ if (ProcessImageName)
+ {
+ /* Release the memory allocated by SeLocateProcessImageName */
+ ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
+ }
+
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
{
return STATUS_INFO_LENGTH_MISMATCH;
}
+
+ if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode()))
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
return STATUS_SUCCESS;
}
DPRINT("SystemHandleInformation 3\n");
- /* Now get Handles from all processs. */
+ /* Now get Handles from all processes. */
syspr = PsGetNextProcess(NULL);
pr = syspr;
{
SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
- if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
+ *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
+
+ if (Size < *ReqSize)
{
- *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
return STATUS_INFO_LENGTH_MISMATCH;
}
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,
/* 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;
}
return STATUS_NOT_IMPLEMENTED;
}
-/* Class 31 - Event Ids Information */
-QSI_DEF(SystemEventIdsInformation)
+/* Class 31 */
+QSI_DEF(SystemPerformanceTraceInformation)
{
/* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
+ DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
{
AlignmentFixupCount += Prcb->KeAlignmentFixupCount;
ExceptionDispatchCount += Prcb->KeExceptionDispatchCount;
+#ifndef _M_ARM
FloatingEmulationCount += Prcb->KeFloatingEmulationCount;
+#endif // _M_ARM
}
}
/* 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 */
/* Class 39 - Priority Separation */
SSI_DEF(SystemPrioritySeperation)
{
- /* FIXME */
- DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
+ /* Check if the size is correct */
+ if (Size != sizeof(ULONG))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* We need the TCB privilege */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, ExGetPreviousMode()))
+ {
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+
+ /* Modify the quantum table */
+ PsChangeQuantumTable(TRUE, *(PULONG)Buffer);
+
+ return STATUS_SUCCESS;
}
-/* Class 40 - Plug Play Bus Information */
-QSI_DEF(SystemPlugPlayBusInformation)
+/* Class 40 */
+QSI_DEF(SystemVerifierAddDriverInformation)
{
/* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
+ DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
-/* Class 41 - Dock Information */
-QSI_DEF(SystemDockInformation)
+/* Class 41 */
+QSI_DEF(SystemVerifierRemoveDriverInformation)
{
/* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
+ DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
/* Class 42 - Power Information */
-QSI_DEF(SystemPowerInformation)
+QSI_DEF(SystemProcessorIdleInformation)
{
+ *ReqSize = sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors;
+
+ if (sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors > Size)
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
/* FIXME */
DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
-/* Class 43 - Processor Speed Information */
-QSI_DEF(SystemProcessorSpeedInformation)
+/* Class 43 */
+QSI_DEF(SystemLegacyDriverInformation)
{
/* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
+ DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
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 */
+ KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
+
+ /* Copy info from non-paged lookaside lists */
+ ExpCopyLookasideInformation(&Info,
+ &Remaining,
+ &ExpNonPagedLookasideListHead,
+ TRUE);
+
+ /* Release spinlock for ExpNonPagedLookasideListHead */
+ KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+
+ if (Remaining == 0)
+ {
+ goto Leave;
+ }
+
+ /* Acquire spinlock for ExpPagedLookasideListHead */
+ KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
+
+ /* Copy info from paged lookaside lists */
+ ExpCopyLookasideInformation(&Info,
+ &Remaining,
+ &ExpPagedLookasideListHead,
+ TRUE);
+
+ /* Release spinlock for ExpPagedLookasideListHead */
+ KeReleaseSpinLock(&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;
}
/* Class 46 - Set time slip event */
-SSI_DEF(SystemSetTimeSlipEvent)
+SSI_DEF(SystemTimeSlipNotification)
{
/* FIXME */
- DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
+ DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
MmSessionDelete(IN ULONG SessionId);
/* Class 47 - Create a new session (TSE) */
-SSI_DEF(SystemCreateSession)
+SSI_DEF(SystemSessionCreate)
{
ULONG SessionId;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
{
return STATUS_PRIVILEGE_NOT_HELD;
}
+
+ ProbeForWriteUlong(Buffer);
}
Status = MmSessionCreate(&SessionId);
/* Class 48 - Delete an existing session (TSE) */
-SSI_DEF(SystemDeleteSession)
+SSI_DEF(SystemSessionDetach)
{
ULONG SessionId;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
/* Class 49 - UNKNOWN */
-QSI_DEF(SystemInvalidInfoClass4)
+QSI_DEF(SystemSessionInformation)
{
/* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
+ DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
}
-/* Class 52 - Add a driver verifier */
-SSI_DEF(SystemAddVerifier)
+/* Class 52 */
+SSI_DEF(SystemVerifierThunkExtend)
{
/* FIXME */
- DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
+ DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n");
return STATUS_NOT_IMPLEMENTED;
}
}
+/* Class 54 - Load & map in system space */
+SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation)
+{
+ /* FIXME */
+ DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 55 - NUMA processor information */
+QSI_DEF(SystemNumaProcessorMap)
+{
+ ULONG MaxEntries, Node;
+ PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer;
+
+ /* Validate input size */
+ if (Size < sizeof(ULONG))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Return highest node */
+ NumaInformation->HighestNodeNumber = KeNumberNodes - 1;
+
+ /* Compute how much entries we will be able to put in output structure */
+ MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask)) / sizeof(ULONGLONG);
+ /* Make sure we don't overflow KeNodeBlock */
+ if (MaxEntries > KeNumberNodes)
+ {
+ MaxEntries = KeNumberNodes;
+ }
+
+ /* If we have entries to write, and room for it */
+ if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) &&
+ MaxEntries != 0)
+ {
+ /* Already set size we return */
+ *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) +
+ MaxEntries * sizeof(ULONGLONG);
+
+ /* For each node, return processor mask */
+ for (Node = 0; Node < MaxEntries; ++Node)
+ {
+ NumaInformation->ActiveProcessorsAffinityMask[Node] = KeNodeBlock[Node]->ProcessorMask;
+ }
+ }
+ else
+ {
+ /* We only returned highest node number */
+ *ReqSize = sizeof(ULONG);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+/* Class 56 - Prefetcher information */
+QSI_DEF(SystemPrefetcherInformation)
+{
+ /* FIXME */
+ DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 57 - Extended process information */
+QSI_DEF(SystemExtendedProcessInformation)
+{
+ /* FIXME */
+ DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 58 - Recommended shared ata alignment */
+QSI_DEF(SystemRecommendedSharedDataAlignment)
+{
+ /* FIXME */
+ DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n");
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 60 - NUMA memory information */
+QSI_DEF(SystemNumaAvailableMemory)
+{
+ ULONG MaxEntries, Node;
+ PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer;
+
+ /* Validate input size */
+ if (Size < sizeof(ULONG))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Return highest node */
+ NumaInformation->HighestNodeNumber = KeNumberNodes - 1;
+
+ /* Compute how much entries we will be able to put in output structure */
+ MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory)) / sizeof(ULONGLONG);
+ /* Make sure we don't overflow KeNodeBlock */
+ if (MaxEntries > KeNumberNodes)
+ {
+ MaxEntries = KeNumberNodes;
+ }
+
+ /* If we have entries to write, and room for it */
+ if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) &&
+ MaxEntries != 0)
+ {
+ /* Already set size we return */
+ *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) +
+ MaxEntries * sizeof(ULONGLONG);
+
+ /* If we have a single entry (us), directly return MM information */
+ if (MaxEntries == 1)
+ {
+ NumaInformation->AvailableMemory[0] = MmAvailablePages << PAGE_SHIFT;
+ }
+ else
+ {
+ /* Otherwise, for each node, return available bytes */
+ for (Node = 0; Node < MaxEntries; ++Node)
+ {
+ NumaInformation->AvailableMemory[Node] = (KeNodeBlock[Node]->FreeCount[0] + KeNodeBlock[Node]->FreeCount[1]) << PAGE_SHIFT;
+ }
+ }
+ }
+ else
+ {
+ /* We only returned highest node number */
+ *ReqSize = sizeof(ULONG);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
/* Query/Set Calls Table */
typedef
struct _QSSI_CALLS
SI_QS(SystemTimeAdjustmentInformation),
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(SystemPerformanceTraceInformation), /* it should be SI_XX */
SI_QX(SystemCrashDumpInformation),
SI_QX(SystemExceptionInformation),
SI_QX(SystemCrashDumpStateInformation),
SI_QS(SystemRegistryQuotaInformation),
SI_XS(SystemExtendServiceTableInformation),
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(SystemProcessorSpeedInformation), /* it should be SI_XX */
+ SI_QX(SystemVerifierAddDriverInformation), /* it should be SI_XX */
+ SI_QX(SystemVerifierRemoveDriverInformation), /* it should be SI_XX */
+ SI_QX(SystemProcessorIdleInformation), /* it should be SI_XX */
+ SI_QX(SystemLegacyDriverInformation), /* it should be SI_XX */
SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
SI_QX(SystemLookasideInformation),
- SI_XS(SystemSetTimeSlipEvent),
- SI_XS(SystemCreateSession),
- SI_XS(SystemDeleteSession),
- SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
+ SI_XS(SystemTimeSlipNotification),
+ SI_XS(SystemSessionCreate),
+ SI_XS(SystemSessionDetach),
+ SI_QX(SystemSessionInformation), /* it should be SI_XX */
SI_QX(SystemRangeStartInformation),
SI_QS(SystemVerifierInformation),
- SI_XS(SystemAddVerifier),
- SI_QX(SystemSessionProcessesInformation)
+ SI_XS(SystemVerifierThunkExtend),
+ SI_QX(SystemSessionProcessesInformation),
+ SI_XS(SystemLoadGdiDriverInSystemSpaceInformation),
+ SI_QX(SystemNumaProcessorMap),
+ SI_QX(SystemPrefetcherInformation),
+ SI_QX(SystemExtendedProcessInformation),
+ SI_QX(SystemRecommendedSharedDataAlignment),
+ SI_XX(SystemComPlusPackage),
+ SI_QX(SystemNumaAvailableMemory)
};
C_ASSERT(SystemBasicInformation == 0);
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)
{
IN PVOID SystemInformation,
IN ULONG SystemInformationLength)
{
+ NTSTATUS Status = STATUS_INVALID_INFO_CLASS;
+ KPROCESSOR_MODE PreviousMode;
+
PAGED_CODE();
- /*
- * If called from user mode, check
- * possible unsafe arguments.
- */
-#if 0
- if (KernelMode != KeGetPreviousMode())
- {
- // Check arguments
- //ProbeForWrite(
- // SystemInformation,
- // Length
- // );
- //ProbeForWrite(
- // ResultLength,
- // sizeof (ULONG)
- // );
- }
-#endif
- /*
- * Check the request is valid.
- */
- if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
- (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
+ PreviousMode = ExGetPreviousMode();
+
+ _SEH2_TRY
{
- if (NULL != CallQS [SystemInformationClass].Set)
+ /*
+ * If called from user mode, check
+ * possible unsafe arguments.
+ */
+ if (PreviousMode != KernelMode)
{
- /*
- * Hand the request to a subhandler.
- */
- return CallQS [SystemInformationClass].Set(SystemInformation,
- SystemInformationLength);
+ ProbeForRead(SystemInformation, SystemInformationLength, sizeof(ULONG));
+ }
+
+ /*
+ * Check the request is valid.
+ */
+ if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
+ (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
+ {
+ if (NULL != CallQS [SystemInformationClass].Set)
+ {
+ /*
+ * Hand the request to a subhandler.
+ */
+ Status = CallQS [SystemInformationClass].Set(SystemInformation,
+ SystemInformationLength);
+ }
}
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
- return STATUS_INVALID_INFO_CLASS;
+ return Status;
}
NTSTATUS
NTAPI
-NtFlushInstructionCache(IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN ULONG NumberOfBytesToFlush)
+NtFlushInstructionCache(
+ _In_ HANDLE ProcessHandle,
+ _In_opt_ PVOID BaseAddress,
+ _In_ ULONG FlushSize)
{
+ KAPC_STATE ApcState;
+ PKPROCESS Process;
+ NTSTATUS Status;
PAGED_CODE();
+ /* Is a base address given? */
+ if (BaseAddress != NULL)
+ {
+ /* If the requested size is 0, there is nothing to do */
+ if (FlushSize == 0)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* Is this a user mode call? */
+ if (KeGetPreviousMode() != KernelMode)
+ {
+ /* Make sure the base address is in user space */
+ if (BaseAddress > MmHighestUserAddress)
+ {
+ DPRINT1("Invalid BaseAddress 0x%p\n", BaseAddress);
+ return STATUS_ACCESS_VIOLATION;
+ }
+ }
+ }
+
+ /* Is another process requested? */
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_WRITE,
+ PsProcessType,
+ KeGetPreviousMode(),
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reference the process %p\n", ProcessHandle);
+ return Status;
+ }
+
+ /* Attach to the process */
+ KeStackAttachProcess(Process, &ApcState);
+ }
+
+ /* FIXME: don't flush everything if a range is requested */
#if defined(_M_IX86) || defined(_M_AMD64)
__wbinvd();
#elif defined(_M_PPC)
__asm__ __volatile__("tlbsync");
#elif defined(_M_MIPS)
DPRINT1("NtFlushInstructionCache() is not implemented\n");
- for (;;);
+ DbgBreakPoint();
#elif defined(_M_ARM)
- __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
+ _MoveToCoprocessor(0, CP15_ICIALLU);
#else
#error Unknown architecture
#endif
+
+ /* Check if we attached */
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ /* Detach from the process */
+ KeUnstackDetachProcess(&ApcState);
+ }
+
return STATUS_SUCCESS;
}