2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/sysinfo.c
5 * PURPOSE: System information functions
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Aleksey Bragin (aleksey@reactos.org)
11 /* INCLUDES *****************************************************************/
19 /* The maximum size of an environment value (in bytes) */
20 #define MAX_ENVVAL_SIZE 1024
22 #define SIG_ACPI 0x41435049
23 #define SIG_FIRM 0x4649524D
24 #define SIG_RSMB 0x52534D42
26 extern LIST_ENTRY HandleTableListHead
;
27 extern EX_PUSH_LOCK HandleTableListLock
;
29 FAST_MUTEX ExpEnvironmentLock
;
30 ERESOURCE ExpFirmwareTableResource
;
31 LIST_ENTRY ExpFirmwareTableProviderListHead
;
35 ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount
,
36 IN PLDR_DATA_TABLE_ENTRY LdrEntry
,
37 OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
)
41 ANSI_STRING ModuleName
;
44 ModuleInfo
->MappedBase
= NULL
;
45 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
46 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
47 ModuleInfo
->Flags
= LdrEntry
->Flags
;
48 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
49 ModuleInfo
->LoadOrderIndex
= (USHORT
)ModuleCount
;
50 ModuleInfo
->InitOrderIndex
= 0;
53 RtlInitEmptyAnsiString(&ModuleName
,
54 ModuleInfo
->FullPathName
,
55 sizeof(ModuleInfo
->FullPathName
));
58 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
59 &LdrEntry
->FullDllName
,
61 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
63 /* Calculate offset to name */
64 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
65 while ((p
> ModuleName
.Buffer
) && (*--p
))
67 /* Check if we found the separator */
68 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
70 /* We did, break out */
77 ModuleInfo
->OffsetToFileName
= (USHORT
)(p
- ModuleName
.Buffer
);
81 /* Return empty name */
82 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
83 ModuleInfo
->OffsetToFileName
= 0;
91 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
92 IN PLIST_ENTRY UserModeList
,
93 OUT PRTL_PROCESS_MODULES Modules
,
95 OUT PULONG ReturnLength
)
97 NTSTATUS Status
= STATUS_SUCCESS
;
99 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
100 PLDR_DATA_TABLE_ENTRY LdrEntry
;
101 ULONG ModuleCount
= 0;
102 PLIST_ENTRY NextEntry
;
105 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
106 ModuleInfo
= &Modules
->Modules
[0];
108 /* Loop the kernel list */
109 NextEntry
= KernelModeList
->Flink
;
110 while (NextEntry
!= KernelModeList
)
113 LdrEntry
= CONTAINING_RECORD(NextEntry
,
114 LDR_DATA_TABLE_ENTRY
,
117 /* Update size and check if we can manage one more entry */
118 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
119 if (Length
>= RequiredLength
)
121 Status
= ExpConvertLdrModuleToRtlModule(ModuleCount
,
125 /* Go to the next module */
131 Status
= STATUS_INFO_LENGTH_MISMATCH
;
134 /* Update count and move to next entry */
136 NextEntry
= NextEntry
->Flink
;
139 /* Check if caller also wanted user modules */
142 NextEntry
= UserModeList
->Flink
;
143 while (NextEntry
!= UserModeList
)
146 LdrEntry
= CONTAINING_RECORD(NextEntry
,
147 LDR_DATA_TABLE_ENTRY
,
150 /* Update size and check if we can manage one more entry */
151 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
152 if (Length
>= RequiredLength
)
154 Status
= ExpConvertLdrModuleToRtlModule(ModuleCount
,
158 /* Go to the next module */
164 Status
= STATUS_INFO_LENGTH_MISMATCH
;
167 /* Update count and move to next entry */
169 NextEntry
= NextEntry
->Flink
;
173 /* Update return length */
174 if (ReturnLength
) *ReturnLength
= RequiredLength
;
176 /* Validate the length again */
177 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
179 /* Set the final count */
180 Modules
->NumberOfModules
= ModuleCount
;
184 /* Otherwise, we failed */
185 Status
= STATUS_INFO_LENGTH_MISMATCH
;
194 ExUnlockUserBuffer(PMDL Mdl
)
197 ExFreePoolWithTag(Mdl
, TAG_MDL
);
205 KPROCESSOR_MODE AccessMode
,
206 LOCK_OPERATION Operation
,
207 PVOID
*MappedSystemVa
,
213 *MappedSystemVa
= NULL
;
216 /* Allocate an MDL for the buffer */
217 Mdl
= IoAllocateMdl(BaseAddress
, Length
, FALSE
, TRUE
, NULL
);
220 return STATUS_INSUFFICIENT_RESOURCES
;
223 /* Enter SEH for probing */
226 MmProbeAndLockPages(Mdl
, AccessMode
, Operation
);
228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
230 ExFreePoolWithTag(Mdl
, TAG_MDL
);
231 _SEH2_YIELD(return _SEH2_GetExceptionCode());
235 /* Return the safe kernel mode buffer */
236 *MappedSystemVa
= MmGetSystemAddressForMdlSafe(Mdl
, NormalPagePriority
);
237 if (*MappedSystemVa
== NULL
)
239 ExUnlockUserBuffer(Mdl
);
240 return STATUS_INSUFFICIENT_RESOURCES
;
245 return STATUS_SUCCESS
;
250 ExpGetRawSMBiosTable(
251 _Out_opt_ PVOID Buffer
,
252 _Out_ ULONG
* OutSize
,
253 _In_ ULONG BufferSize
)
256 PVOID DataBlockObject
;
257 PWNODE_ALL_DATA AllData
;
260 ASSERT(OutSize
!= NULL
);
263 /* Open the data block object for the SMBIOS table */
264 Status
= IoWMIOpenBlock(&MSSmBios_RawSMBiosTables_GUID
,
267 if (!NT_SUCCESS(Status
))
269 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status
);
273 /* Query the required buffer size */
275 Status
= IoWMIQueryAllData(DataBlockObject
, &WMIBufSize
, NULL
);
276 if (!NT_SUCCESS(Status
))
278 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status
);
282 AllData
= ExAllocatePoolWithTag(PagedPool
, WMIBufSize
, 'itfS');
285 DPRINT1("Failed to allocate %lu bytes for SMBIOS tables\n", WMIBufSize
);
286 return STATUS_INSUFFICIENT_RESOURCES
;
289 /* Query the buffer data */
290 Status
= IoWMIQueryAllData(DataBlockObject
, &WMIBufSize
, AllData
);
291 if (!NT_SUCCESS(Status
))
293 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status
);
294 ExFreePoolWithTag(AllData
, 'itfS');
298 Status
= STATUS_SUCCESS
;
299 *OutSize
= AllData
->FixedInstanceSize
;
302 if (BufferSize
>= *OutSize
)
304 RtlMoveMemory(Buffer
, AllData
+ 1, *OutSize
);
308 Status
= STATUS_BUFFER_TOO_SMALL
;
312 /* Free the buffer */
313 ExFreePoolWithTag(AllData
, 'itfS');
317 /* FUNCTIONS *****************************************************************/
324 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
328 ULONGLONG ScaledIdle
;
330 Prcb
= KeGetCurrentPrcb();
332 ScaledIdle
= (ULONGLONG
)Prcb
->IdleThread
->KernelTime
* 100;
333 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
335 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
345 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
347 PULONG ProcessorNumber
)
351 Prcb
= KeGetCurrentPrcb();
353 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
354 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
355 *ProcessorNumber
= KeGetCurrentProcessorNumber();
363 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
365 /* Quick check to see if it exists at all */
366 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
368 /* Return our support for it */
369 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
377 ExVerifySuite(SUITE_TYPE SuiteType
)
379 if (SuiteType
== Personal
) return TRUE
;
385 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
386 OUT PWSTR ValueBuffer
,
387 IN ULONG ValueBufferLength
,
388 IN OUT PULONG ReturnLength OPTIONAL
)
391 UNICODE_STRING WName
;
395 UNICODE_STRING WValue
;
396 KPROCESSOR_MODE PreviousMode
;
400 /* Check if the call came from user mode */
401 PreviousMode
= ExGetPreviousMode();
402 if (PreviousMode
!= KernelMode
)
406 /* Probe the input and output buffers */
407 ProbeForRead(VariableName
, sizeof(UNICODE_STRING
), sizeof(ULONG
));
408 ProbeForWrite(ValueBuffer
, ValueBufferLength
, sizeof(WCHAR
));
409 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
411 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
413 /* Return the exception code */
414 _SEH2_YIELD(return _SEH2_GetExceptionCode());
419 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
420 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
, PreviousMode
))
422 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
423 return STATUS_PRIVILEGE_NOT_HELD
;
426 /* Copy the name to kernel space if necessary */
427 Status
= ProbeAndCaptureUnicodeString(&WName
, PreviousMode
, VariableName
);
428 if (!NT_SUCCESS(Status
)) return Status
;
430 /* Convert the name to ANSI and release the captured UNICODE string */
431 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
432 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
433 if (!NT_SUCCESS(Status
)) return Status
;
435 /* Allocate a buffer for the ANSI environment variable */
436 AnsiValueBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_ENVVAL_SIZE
, 'rvnE');
437 if (AnsiValueBuffer
== NULL
)
439 RtlFreeAnsiString(&AName
);
440 return STATUS_INSUFFICIENT_RESOURCES
;
443 /* Get the environment variable and free the ANSI name */
444 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
447 RtlFreeAnsiString(&AName
);
449 /* Check if we had success */
450 if (Result
== ESUCCESS
)
452 /* Copy the result back to the caller. */
455 /* Initialize ANSI string from the result */
456 RtlInitAnsiString(&AValue
, AnsiValueBuffer
);
458 /* Initialize a UNICODE string from the callers buffer */
459 RtlInitEmptyUnicodeString(&WValue
, ValueBuffer
, (USHORT
)ValueBufferLength
);
461 /* Convert the result to UNICODE */
462 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, FALSE
);
464 if (ReturnLength
!= NULL
)
465 *ReturnLength
= WValue
.Length
;
467 _SEH2_EXCEPT(ExSystemExceptionFilter())
469 Status
= _SEH2_GetExceptionCode();
475 Status
= STATUS_UNSUCCESSFUL
;
478 /* Free the allocated ANSI value buffer */
479 ExFreePoolWithTag(AnsiValueBuffer
, 'rvnE');
487 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
488 IN PUNICODE_STRING Value
)
490 UNICODE_STRING CapturedName
, CapturedValue
;
491 ANSI_STRING AName
, AValue
;
492 KPROCESSOR_MODE PreviousMode
;
497 PreviousMode
= ExGetPreviousMode();
500 * Copy the strings to kernel space if necessary
502 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
505 if (NT_SUCCESS(Status
))
507 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
510 if (NT_SUCCESS(Status
))
513 * according to ntinternals the SeSystemEnvironmentName privilege is required!
515 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
519 * convert the strings to ANSI
521 Status
= RtlUnicodeStringToAnsiString(&AName
,
524 if (NT_SUCCESS(Status
))
526 Status
= RtlUnicodeStringToAnsiString(&AValue
,
529 if (NT_SUCCESS(Status
))
531 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
534 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
540 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
541 Status
= STATUS_PRIVILEGE_NOT_HELD
;
544 ReleaseCapturedUnicodeString(&CapturedValue
,
548 ReleaseCapturedUnicodeString(&CapturedName
,
557 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
559 IN ULONG BufferLength
)
562 return STATUS_NOT_IMPLEMENTED
;
567 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
568 IN LPGUID VendorGuid
,
570 IN OUT PULONG ReturnLength
,
571 IN OUT PULONG Attributes
)
574 return STATUS_NOT_IMPLEMENTED
;
579 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
580 IN LPGUID VendorGuid
,
582 IN OUT PULONG ReturnLength
,
583 IN OUT PULONG Attributes
)
586 return STATUS_NOT_IMPLEMENTED
;
589 /* --- Query/Set System Information --- */
592 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
593 * so the stack is popped only in one place on x86 platform.
595 #define QSI_USE(n) QSI##n
597 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
599 #define SSI_USE(n) SSI##n
601 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
605 ExQueryPoolUsage(OUT PULONG PagedPoolPages
,
606 OUT PULONG NonPagedPoolPages
,
607 OUT PULONG PagedPoolAllocs
,
608 OUT PULONG PagedPoolFrees
,
609 OUT PULONG PagedPoolLookasideHits
,
610 OUT PULONG NonPagedPoolAllocs
,
611 OUT PULONG NonPagedPoolFrees
,
612 OUT PULONG NonPagedPoolLookasideHits
);
614 /* Class 0 - Basic Information */
615 QSI_DEF(SystemBasicInformation
)
617 PSYSTEM_BASIC_INFORMATION Sbi
618 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
620 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
622 /* Check user buffer's size */
623 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
625 return STATUS_INFO_LENGTH_MISMATCH
;
628 RtlZeroMemory(Sbi
, Size
);
630 Sbi
->TimerResolution
= KeMaximumIncrement
;
631 Sbi
->PageSize
= PAGE_SIZE
;
632 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
633 Sbi
->LowestPhysicalPageNumber
= (ULONG
)MmLowestPhysicalPage
;
634 Sbi
->HighestPhysicalPageNumber
= (ULONG
)MmHighestPhysicalPage
;
635 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
636 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
637 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
638 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
639 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
641 return STATUS_SUCCESS
;
644 /* Class 1 - Processor Information */
645 QSI_DEF(SystemProcessorInformation
)
647 PSYSTEM_PROCESSOR_INFORMATION Spi
648 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
650 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
652 /* Check user buffer's size */
653 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
655 return STATUS_INFO_LENGTH_MISMATCH
;
657 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
658 Spi
->ProcessorLevel
= KeProcessorLevel
;
659 Spi
->ProcessorRevision
= KeProcessorRevision
;
661 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
663 DPRINT("Arch %u Level %u Rev 0x%x\n", Spi
->ProcessorArchitecture
,
664 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
666 return STATUS_SUCCESS
;
669 /* Class 2 - Performance Information */
670 QSI_DEF(SystemPerformanceInformation
)
672 ULONG IdleUser
, IdleKernel
;
673 PSYSTEM_PERFORMANCE_INFORMATION Spi
674 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
676 PEPROCESS TheIdleProcess
;
678 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
680 /* Check user buffer's size */
681 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
683 return STATUS_INFO_LENGTH_MISMATCH
;
686 TheIdleProcess
= PsIdleProcess
;
688 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
689 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
690 Spi
->IoReadTransferCount
= IoReadTransferCount
;
691 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
692 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
693 Spi
->IoReadOperationCount
= IoReadOperationCount
;
694 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
695 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
697 Spi
->AvailablePages
= (ULONG
)MmAvailablePages
;
699 * Add up all the used "Committed" memory + pagefile.
700 * Not sure this is right. 8^\
702 Spi
->CommittedPages
= MiMemoryConsumers
[MC_SYSTEM
].PagesUsed
+
703 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
704 MiMemoryConsumers
[MC_USER
].PagesUsed
+
707 * Add up the full system total + pagefile.
708 * All this make Taskmgr happy but not sure it is the right numbers.
709 * This too, fixes some of GlobalMemoryStatusEx numbers.
711 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
713 Spi
->PeakCommitment
= 0; /* FIXME */
714 Spi
->PageFaultCount
= 0; /* FIXME */
715 Spi
->CopyOnWriteCount
= 0; /* FIXME */
716 Spi
->TransitionCount
= 0; /* FIXME */
717 Spi
->CacheTransitionCount
= 0; /* FIXME */
718 Spi
->DemandZeroCount
= 0; /* FIXME */
719 Spi
->PageReadCount
= 0; /* FIXME */
720 Spi
->PageReadIoCount
= 0; /* FIXME */
721 Spi
->CacheReadCount
= 0; /* FIXME */
722 Spi
->CacheIoCount
= 0; /* FIXME */
723 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
724 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
725 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
726 Spi
->MappedWriteIoCount
= 0; /* FIXME */
728 Spi
->PagedPoolPages
= 0;
729 Spi
->NonPagedPoolPages
= 0;
730 Spi
->PagedPoolAllocs
= 0;
731 Spi
->PagedPoolFrees
= 0;
732 Spi
->PagedPoolLookasideHits
= 0;
733 Spi
->NonPagedPoolAllocs
= 0;
734 Spi
->NonPagedPoolFrees
= 0;
735 Spi
->NonPagedPoolLookasideHits
= 0;
736 ExQueryPoolUsage(&Spi
->PagedPoolPages
,
737 &Spi
->NonPagedPoolPages
,
738 &Spi
->PagedPoolAllocs
,
739 &Spi
->PagedPoolFrees
,
740 &Spi
->PagedPoolLookasideHits
,
741 &Spi
->NonPagedPoolAllocs
,
742 &Spi
->NonPagedPoolFrees
,
743 &Spi
->NonPagedPoolLookasideHits
);
744 Spi
->FreeSystemPtes
= 0; /* FIXME */
746 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
748 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
749 Spi
->Spare3Count
= 0; /* FIXME */
751 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
752 Spi
->ResidentPagedPoolPage
= 0; /* FIXME */
754 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
755 Spi
->CcFastReadNoWait
= 0; /* FIXME */
756 Spi
->CcFastReadWait
= 0; /* FIXME */
757 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
758 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
760 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
761 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
762 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
763 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
765 Spi
->CcMapDataNoWait
= CcMapDataNoWait
;
766 Spi
->CcMapDataWait
= CcMapDataWait
;
767 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
768 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
770 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
771 Spi
->CcPinReadNoWait
= CcPinReadNoWait
;
772 Spi
->CcPinReadWait
= CcPinReadWait
;
773 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
774 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
775 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
776 Spi
->CcCopyReadWait
= 0; /* FIXME */
777 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
778 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
780 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
781 Spi
->CcMdlReadWait
= 0; /* FIXME */
782 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
783 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
784 Spi
->CcReadAheadIos
= 0; /* FIXME */
785 Spi
->CcLazyWriteIos
= CcLazyWriteIos
;
786 Spi
->CcLazyWritePages
= CcLazyWritePages
;
787 Spi
->CcDataFlushes
= CcDataFlushes
;
788 Spi
->CcDataPages
= CcDataPages
;
789 Spi
->ContextSwitches
= 0; /* FIXME */
790 Spi
->FirstLevelTbFills
= 0; /* FIXME */
791 Spi
->SecondLevelTbFills
= 0; /* FIXME */
792 Spi
->SystemCalls
= 0; /* FIXME */
794 return STATUS_SUCCESS
;
797 /* Class 3 - Time Of Day Information */
798 QSI_DEF(SystemTimeOfDayInformation
)
800 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
801 LARGE_INTEGER CurrentTime
;
803 /* Set amount of written information to 0 */
806 /* Check user buffer's size */
807 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
809 return STATUS_INFO_LENGTH_MISMATCH
;
812 /* Get current time */
813 KeQuerySystemTime(&CurrentTime
);
815 /* Zero local buffer */
816 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
818 /* Fill local time structure */
819 Sti
.BootTime
= KeBootTime
;
820 Sti
.CurrentTime
= CurrentTime
;
821 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
822 Sti
.TimeZoneId
= ExpTimeZoneId
;
825 /* Copy as much as requested by caller */
826 RtlCopyMemory(Buffer
, &Sti
, Size
);
828 /* Set amount of information we copied */
831 return STATUS_SUCCESS
;
834 /* Class 4 - Path Information */
835 QSI_DEF(SystemPathInformation
)
837 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
838 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
840 return STATUS_BREAKPOINT
;
843 /* Class 5 - Process Information */
844 QSI_DEF(SystemProcessInformation
)
846 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
847 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
848 PEPROCESS Process
= NULL
, SystemProcess
;
849 PETHREAD CurrentThread
;
850 ANSI_STRING ImageName
;
852 USHORT ImageNameMaximumLength
; // image name length in bytes
853 USHORT ImageNameLength
;
854 PLIST_ENTRY CurrentEntry
;
855 ULONG TotalSize
= 0, ThreadsCount
;
856 ULONG TotalUser
, TotalKernel
;
858 NTSTATUS Status
= STATUS_SUCCESS
;
859 PUNICODE_STRING TempProcessImageName
;
860 _SEH2_VOLATILE PUNICODE_STRING ProcessImageName
= NULL
;
862 BOOLEAN Overflow
= FALSE
;
866 /* scan the process list */
868 PSYSTEM_PROCESS_INFORMATION Spi
869 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
871 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
873 /* Check for overflow */
874 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
879 /* Zero user's buffer */
880 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
882 SystemProcess
= PsIdleProcess
;
883 Process
= SystemProcess
;
884 Current
= (PUCHAR
) Spi
;
888 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
890 /* Lock the Process */
891 KeEnterCriticalRegion();
892 ExAcquirePushLockShared(&Process
->ProcessLock
);
894 if ((Process
->ProcessExiting
) &&
895 (Process
->Pcb
.Header
.SignalState
) &&
896 !(Process
->ActiveThreads
) &&
897 (IsListEmpty(&Process
->Pcb
.ThreadListHead
)))
899 DPRINT1("Process %p (%s:%p) is a zombie\n",
900 Process
, Process
->ImageFileName
, Process
->UniqueProcessId
);
902 ImageNameMaximumLength
= 0;
904 /* Unlock the Process */
905 ExReleasePushLockShared(&Process
->ProcessLock
);
906 KeLeaveCriticalRegion();
911 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
912 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
915 CurrentEntry
= CurrentEntry
->Flink
;
918 // size of the structure for every process
919 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
921 Status
= SeLocateProcessImageName(Process
, &TempProcessImageName
);
922 ProcessImageName
= TempProcessImageName
;
924 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
926 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
927 /* Loop the file name*/
928 while (szSrc
> ProcessImageName
->Buffer
)
930 /* Make sure this isn't a backslash */
931 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
938 ImageNameLength
+= sizeof(WCHAR
);
942 if (!ImageNameLength
&& Process
!= PsIdleProcess
)
944 ImageNameLength
= (USHORT
)strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
947 /* Round up the image name length as NT does */
948 if (ImageNameLength
> 0)
949 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
951 ImageNameMaximumLength
= 0;
953 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
955 /* Check for overflow */
956 if (TotalSize
> Size
)
961 /* Fill system information */
964 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginning of the next structure
965 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
966 SpiCurrent
->CreateTime
= Process
->CreateTime
;
967 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
968 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
969 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
971 /* Copy name to the end of the struct */
972 if(Process
!= PsIdleProcess
)
976 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
980 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
981 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
986 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
989 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
990 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
991 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
992 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
993 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
994 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
995 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
996 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
997 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
998 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
999 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
1000 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
1001 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
1002 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
1003 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
1004 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
1005 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
1007 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
1008 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
1010 CurrentThread
= CONTAINING_RECORD(CurrentEntry
, ETHREAD
, Tcb
.ThreadListEntry
);
1012 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
1013 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
1014 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
1015 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
1016 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
1017 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
1018 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
1019 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
1020 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
1021 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
1022 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
1025 CurrentEntry
= CurrentEntry
->Flink
;
1028 /* Query total user/kernel times of a process */
1029 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
1030 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
1031 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
1034 if (ProcessImageName
)
1036 /* Release the memory allocated by SeLocateProcessImageName */
1037 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
1038 ProcessImageName
= NULL
;
1041 /* Unlock the Process */
1042 ExReleasePushLockShared(&Process
->ProcessLock
);
1043 KeLeaveCriticalRegion();
1045 /* Handle idle process entry */
1047 if (Process
== PsIdleProcess
) Process
= NULL
;
1049 Process
= PsGetNextProcess(Process
);
1051 if ((Process
== SystemProcess
) || (Process
== NULL
))
1054 SpiCurrent
->NextEntryOffset
= 0;
1058 Current
+= CurrentSize
+ ImageNameMaximumLength
;
1059 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
1062 ObDereferenceObject(Process
);
1063 Status
= STATUS_SUCCESS
;
1065 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1068 ObDereferenceObject(Process
);
1069 if (ProcessImageName
)
1071 /* Release the memory allocated by SeLocateProcessImageName */
1072 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
1075 Status
= _SEH2_GetExceptionCode();
1080 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1082 *ReqSize
= TotalSize
;
1086 /* Class 6 - Call Count Information */
1087 QSI_DEF(SystemCallCountInformation
)
1090 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
1091 return STATUS_NOT_IMPLEMENTED
;
1094 /* Class 7 - Device Information */
1095 QSI_DEF(SystemDeviceInformation
)
1097 PSYSTEM_DEVICE_INFORMATION Sdi
1098 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
1099 PCONFIGURATION_INFORMATION ConfigInfo
;
1101 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
1103 /* Check user buffer's size */
1104 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
1106 return STATUS_INFO_LENGTH_MISMATCH
;
1109 ConfigInfo
= IoGetConfigurationInformation();
1111 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
1112 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
1113 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
1114 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
1115 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
1116 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
1118 return STATUS_SUCCESS
;
1121 /* Class 8 - Processor Performance Information */
1122 QSI_DEF(SystemProcessorPerformanceInformation
)
1124 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
1125 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
1131 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
1133 /* Check user buffer's size */
1134 if (Size
< *ReqSize
)
1136 return STATUS_INFO_LENGTH_MISMATCH
;
1139 for (i
= 0; i
< KeNumberProcessors
; i
++)
1141 /* Get the PRCB on this processor */
1142 Prcb
= KiProcessorBlock
[i
];
1144 /* Calculate total user and kernel times */
1145 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
1146 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
1147 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
1148 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
1149 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
1150 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
1151 Spi
->InterruptCount
= Prcb
->InterruptCount
;
1155 return STATUS_SUCCESS
;
1158 /* Class 9 - Flags Information */
1159 QSI_DEF(SystemFlagsInformation
)
1161 #if (NTDDI_VERSION >= NTDDI_VISTA)
1162 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
1165 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1167 return STATUS_INFO_LENGTH_MISMATCH
;
1170 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
1171 #if (NTDDI_VERSION < NTDDI_VISTA)
1172 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
1175 return STATUS_SUCCESS
;
1178 SSI_DEF(SystemFlagsInformation
)
1180 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1182 return STATUS_INFO_LENGTH_MISMATCH
;
1185 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, ExGetPreviousMode()))
1187 return STATUS_ACCESS_DENIED
;
1190 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
1191 return STATUS_SUCCESS
;
1194 /* Class 10 - Call Time Information */
1195 QSI_DEF(SystemCallTimeInformation
)
1198 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
1199 return STATUS_NOT_IMPLEMENTED
;
1202 /* Class 11 - Module Information */
1203 QSI_DEF(SystemModuleInformation
)
1207 /* Acquire system module list lock */
1208 KeEnterCriticalRegion();
1209 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource
, TRUE
);
1211 /* Call the generic handler with the system module list */
1212 Status
= ExpQueryModuleInformation(&PsLoadedModuleList
,
1213 &MmLoadedUserImageList
,
1214 (PRTL_PROCESS_MODULES
)Buffer
,
1218 /* Release list lock and return status */
1219 ExReleaseResourceLite(&PsLoadedModuleResource
);
1220 KeLeaveCriticalRegion();
1224 /* Class 12 - Locks Information */
1225 QSI_DEF(SystemLocksInformation
)
1228 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1229 return STATUS_NOT_IMPLEMENTED
;
1232 /* Class 13 - Stack Trace Information */
1233 QSI_DEF(SystemStackTraceInformation
)
1236 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1237 return STATUS_NOT_IMPLEMENTED
;
1240 /* Class 14 - Paged Pool Information */
1241 QSI_DEF(SystemPagedPoolInformation
)
1244 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1245 return STATUS_NOT_IMPLEMENTED
;
1248 /* Class 15 - Non Paged Pool Information */
1249 QSI_DEF(SystemNonPagedPoolInformation
)
1252 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1253 return STATUS_NOT_IMPLEMENTED
;
1257 /* Class 16 - Handle Information */
1258 QSI_DEF(SystemHandleInformation
)
1260 PSYSTEM_HANDLE_INFORMATION HandleInformation
;
1261 PLIST_ENTRY NextTableEntry
;
1262 PHANDLE_TABLE HandleTable
;
1263 PHANDLE_TABLE_ENTRY HandleTableEntry
;
1270 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1272 /* Set initial required buffer size */
1273 *ReqSize
= FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION
, Handles
);
1275 /* Check user's buffer size */
1276 if (Size
< *ReqSize
)
1278 return STATUS_INFO_LENGTH_MISMATCH
;
1281 /* We need to lock down the memory */
1282 Status
= ExLockUserBuffer(Buffer
,
1284 ExGetPreviousMode(),
1286 (PVOID
*)&HandleInformation
,
1288 if (!NT_SUCCESS(Status
))
1290 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status
);
1294 /* Reset of count of handles */
1295 HandleInformation
->NumberOfHandles
= 0;
1297 /* Enter a critical region */
1298 KeEnterCriticalRegion();
1300 /* Acquire the handle table lock */
1301 ExAcquirePushLockShared(&HandleTableListLock
);
1303 /* Enumerate all system handles */
1304 for (NextTableEntry
= HandleTableListHead
.Flink
;
1305 NextTableEntry
!= &HandleTableListHead
;
1306 NextTableEntry
= NextTableEntry
->Flink
)
1308 /* Get current handle table */
1309 HandleTable
= CONTAINING_RECORD(NextTableEntry
, HANDLE_TABLE
, HandleTableList
);
1311 /* Set the initial value and loop the entries */
1313 while ((HandleTableEntry
= ExpLookupHandleTableEntry(HandleTable
, Handle
)))
1315 /* Validate the entry */
1316 if ((HandleTableEntry
->Object
) &&
1317 (HandleTableEntry
->NextFreeTableEntry
!= -2))
1319 /* Increase of count of handles */
1320 ++HandleInformation
->NumberOfHandles
;
1322 /* Lock the entry */
1323 if (ExpLockHandleTableEntry(HandleTable
, HandleTableEntry
))
1325 /* Increase required buffer size */
1326 *ReqSize
+= sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
);
1328 /* Check user's buffer size */
1329 if (*ReqSize
> Size
)
1331 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1335 POBJECT_HEADER ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
1337 /* Filling handle information */
1338 HandleInformation
->Handles
[Index
].UniqueProcessId
=
1339 (USHORT
)(ULONG_PTR
) HandleTable
->UniqueProcessId
;
1341 HandleInformation
->Handles
[Index
].CreatorBackTraceIndex
= 0;
1343 #if 0 /* FIXME!!! Type field currupted */
1344 HandleInformation
->Handles
[Index
].ObjectTypeIndex
=
1345 (UCHAR
) ObjectHeader
->Type
->Index
;
1347 HandleInformation
->Handles
[Index
].ObjectTypeIndex
= 0;
1350 HandleInformation
->Handles
[Index
].HandleAttributes
=
1351 HandleTableEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
;
1353 HandleInformation
->Handles
[Index
].HandleValue
=
1354 (USHORT
)(ULONG_PTR
) Handle
.GenericHandleOverlay
;
1356 HandleInformation
->Handles
[Index
].Object
= &ObjectHeader
->Body
;
1358 HandleInformation
->Handles
[Index
].GrantedAccess
=
1359 HandleTableEntry
->GrantedAccess
;
1365 ExUnlockHandleTableEntry(HandleTable
, HandleTableEntry
);
1369 /* Go to the next entry */
1370 Handle
.Value
+= sizeof(HANDLE
);
1374 /* Release the lock */
1375 ExReleasePushLockShared(&HandleTableListLock
);
1377 /* Leave the critical region */
1378 KeLeaveCriticalRegion();
1380 /* Release the locked user buffer */
1381 ExUnlockUserBuffer(Mdl
);
1386 /* Class 17 - Information */
1387 QSI_DEF(SystemObjectInformation
)
1390 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1391 return STATUS_NOT_IMPLEMENTED
;
1394 /* Class 18 - Information */
1395 QSI_DEF(SystemPageFileInformation
)
1397 UNICODE_STRING FileName
; /* FIXME */
1398 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1400 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1402 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1403 return STATUS_INFO_LENGTH_MISMATCH
;
1406 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1409 Spfi
->NextEntryOffset
= 0;
1411 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1412 Spfi
->TotalInUse
= MiUsedSwapPages
;
1413 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1414 Spfi
->PageFileName
= FileName
;
1415 return STATUS_SUCCESS
;
1418 /* Class 19 - Vdm Instemul Information */
1419 QSI_DEF(SystemVdmInstemulInformation
)
1422 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1423 return STATUS_NOT_IMPLEMENTED
;
1426 /* Class 20 - Vdm Bop Information */
1427 QSI_DEF(SystemVdmBopInformation
)
1430 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1431 return STATUS_NOT_IMPLEMENTED
;
1434 /* Class 21 - File Cache Information */
1435 QSI_DEF(SystemFileCacheInformation
)
1437 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1439 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1441 if (Size
< *ReqSize
)
1443 return STATUS_INFO_LENGTH_MISMATCH
;
1446 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1448 /* Return the Byte size not the page size. */
1450 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1452 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1453 /* Taskmgr multiplies this one by page size right away */
1454 Sci
->CurrentSizeIncludingTransitionInPages
=
1455 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1456 /* system working set and standby pages. */
1457 Sci
->PageFaultCount
= 0; /* FIXME */
1458 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1459 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1461 return STATUS_SUCCESS
;
1464 SSI_DEF(SystemFileCacheInformation
)
1466 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1468 return STATUS_INFO_LENGTH_MISMATCH
;
1471 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1472 return STATUS_NOT_IMPLEMENTED
;
1475 /* Class 22 - Pool Tag Information */
1476 QSI_DEF(SystemPoolTagInformation
)
1478 if (Size
< sizeof(SYSTEM_POOLTAG_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
1479 return ExGetPoolTagInfo(Buffer
, Size
, ReqSize
);
1482 /* Class 23 - Interrupt Information for all processors */
1483 QSI_DEF(SystemInterruptInformation
)
1488 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1490 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1492 return STATUS_INFO_LENGTH_MISMATCH
;
1495 ti
= KeQueryTimeIncrement();
1497 for (i
= 0; i
< KeNumberProcessors
; i
++)
1499 Prcb
= KiProcessorBlock
[i
];
1500 sii
->ContextSwitches
= KeGetContextSwitches(Prcb
);
1501 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1502 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1503 sii
->TimeIncrement
= ti
;
1504 sii
->DpcBypassCount
= 0;
1505 sii
->ApcBypassCount
= 0;
1509 return STATUS_SUCCESS
;
1512 /* Class 24 - DPC Behaviour Information */
1513 QSI_DEF(SystemDpcBehaviourInformation
)
1516 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1517 return STATUS_NOT_IMPLEMENTED
;
1520 SSI_DEF(SystemDpcBehaviourInformation
)
1523 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1524 return STATUS_NOT_IMPLEMENTED
;
1527 /* Class 25 - Full Memory Information */
1528 QSI_DEF(SystemFullMemoryInformation
)
1530 PULONG Spi
= (PULONG
) Buffer
;
1532 PEPROCESS TheIdleProcess
;
1534 *ReqSize
= sizeof(ULONG
);
1536 if (sizeof(ULONG
) != Size
)
1538 return STATUS_INFO_LENGTH_MISMATCH
;
1541 DPRINT("SystemFullMemoryInformation\n");
1543 TheIdleProcess
= PsIdleProcess
;
1545 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
1546 TheIdleProcess
->UniqueProcessId
,
1547 TheIdleProcess
->Pcb
.KernelTime
,
1551 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1553 return STATUS_SUCCESS
;
1556 /* Class 26 - Load Image */
1557 SSI_DEF(SystemLoadGdiDriverInformation
)
1559 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1560 UNICODE_STRING ImageName
;
1562 PVOID SectionPointer
;
1563 ULONG_PTR EntryPoint
;
1566 PIMAGE_NT_HEADERS NtHeader
;
1569 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1571 /* Incorrect buffer length, fail */
1572 return STATUS_INFO_LENGTH_MISMATCH
;
1575 /* Only kernel mode can call this function */
1576 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1578 /* Load the driver */
1579 ImageName
= DriverInfo
->DriverName
;
1580 Status
= MmLoadSystemImage(&ImageName
,
1586 if (!NT_SUCCESS(Status
)) return Status
;
1588 /* Return the export pointer */
1589 DriverInfo
->ExportSectionPointer
=
1590 RtlImageDirectoryEntryToData(ImageBase
,
1592 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1595 /* Get the entrypoint */
1596 NtHeader
= RtlImageNtHeader(ImageBase
);
1597 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1598 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1600 /* Save other data */
1601 DriverInfo
->ImageAddress
= ImageBase
;
1602 DriverInfo
->SectionPointer
= SectionPointer
;
1603 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1604 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1607 return STATUS_SUCCESS
;
1610 /* Class 27 - Unload Image */
1611 SSI_DEF(SystemUnloadGdiDriverInformation
)
1613 PVOID
*SectionPointer
= Buffer
;
1616 if (Size
!= sizeof(PVOID
))
1618 /* Incorrect length, fail */
1619 return STATUS_INFO_LENGTH_MISMATCH
;
1622 /* Only kernel mode can call this function */
1623 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1625 /* Unload the image */
1626 MmUnloadSystemImage(*SectionPointer
);
1627 return STATUS_SUCCESS
;
1630 /* Class 28 - Time Adjustment Information */
1631 QSI_DEF(SystemTimeAdjustmentInformation
)
1633 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1634 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1636 /* Check if enough storage was provided */
1637 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1639 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1640 return STATUS_INFO_LENGTH_MISMATCH
;
1643 /* Give time values to our caller */
1644 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1645 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1646 TimeInfo
->Enable
= !KiTimeAdjustmentEnabled
;
1648 return STATUS_SUCCESS
;
1651 SSI_DEF(SystemTimeAdjustmentInformation
)
1653 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1654 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
=
1655 (PSYSTEM_SET_TIME_ADJUST_INFORMATION
)Buffer
;
1657 /* Check size of a buffer, it must match our expectations */
1658 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1659 return STATUS_INFO_LENGTH_MISMATCH
;
1661 /* Check who is calling */
1662 if (PreviousMode
!= KernelMode
)
1664 /* Check access rights */
1665 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1667 return STATUS_PRIVILEGE_NOT_HELD
;
1671 /* FIXME: behaviour suggests the member be named 'Disable' */
1672 if (TimeInfo
->Enable
)
1674 /* Disable time adjustment and set default value */
1675 KiTimeAdjustmentEnabled
= FALSE
;
1676 KeTimeAdjustment
= KeMaximumIncrement
;
1680 /* Check if a valid time adjustment value is given */
1681 if (TimeInfo
->TimeAdjustment
== 0) return STATUS_INVALID_PARAMETER_2
;
1683 /* Enable time adjustment and set the adjustment value */
1684 KiTimeAdjustmentEnabled
= TRUE
;
1685 KeTimeAdjustment
= TimeInfo
->TimeAdjustment
;
1688 return STATUS_SUCCESS
;
1691 /* Class 29 - Summary Memory Information */
1692 QSI_DEF(SystemSummaryMemoryInformation
)
1695 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1696 return STATUS_NOT_IMPLEMENTED
;
1699 /* Class 30 - Next Event Id Information */
1700 QSI_DEF(SystemNextEventIdInformation
)
1703 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1704 return STATUS_NOT_IMPLEMENTED
;
1708 QSI_DEF(SystemPerformanceTraceInformation
)
1711 DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n");
1712 return STATUS_NOT_IMPLEMENTED
;
1715 /* Class 32 - Crash Dump Information */
1716 QSI_DEF(SystemCrashDumpInformation
)
1719 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1720 return STATUS_NOT_IMPLEMENTED
;
1723 /* Class 33 - Exception Information */
1724 QSI_DEF(SystemExceptionInformation
)
1726 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation
=
1727 (PSYSTEM_EXCEPTION_INFORMATION
)Buffer
;
1729 ULONG AlignmentFixupCount
= 0, ExceptionDispatchCount
= 0;
1730 ULONG FloatingEmulationCount
= 0, ByteWordEmulationCount
= 0;
1733 /* Check size of a buffer, it must match our expectations */
1734 if (sizeof(SYSTEM_EXCEPTION_INFORMATION
) != Size
)
1735 return STATUS_INFO_LENGTH_MISMATCH
;
1737 /* Sum up exception count information from all processors */
1738 for (i
= 0; i
< KeNumberProcessors
; i
++)
1740 Prcb
= KiProcessorBlock
[i
];
1743 AlignmentFixupCount
+= Prcb
->KeAlignmentFixupCount
;
1744 ExceptionDispatchCount
+= Prcb
->KeExceptionDispatchCount
;
1746 FloatingEmulationCount
+= Prcb
->KeFloatingEmulationCount
;
1751 /* Save information in user's buffer */
1752 ExceptionInformation
->AlignmentFixupCount
= AlignmentFixupCount
;
1753 ExceptionInformation
->ExceptionDispatchCount
= ExceptionDispatchCount
;
1754 ExceptionInformation
->FloatingEmulationCount
= FloatingEmulationCount
;
1755 ExceptionInformation
->ByteWordEmulationCount
= ByteWordEmulationCount
;
1757 return STATUS_SUCCESS
;
1760 /* Class 34 - Crash Dump State Information */
1761 QSI_DEF(SystemCrashDumpStateInformation
)
1764 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1765 return STATUS_NOT_IMPLEMENTED
;
1768 /* Class 35 - Kernel Debugger Information */
1769 QSI_DEF(SystemKernelDebuggerInformation
)
1771 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1773 #if (NTDDI_VERSION >= NTDDI_VISTA)
1774 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1777 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1779 return STATUS_INFO_LENGTH_MISMATCH
;
1782 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1783 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1785 #if (NTDDI_VERSION < NTDDI_VISTA)
1786 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1789 return STATUS_SUCCESS
;
1792 /* Class 36 - Context Switch Information */
1793 QSI_DEF(SystemContextSwitchInformation
)
1795 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation
=
1796 (PSYSTEM_CONTEXT_SWITCH_INFORMATION
)Buffer
;
1797 ULONG ContextSwitches
;
1801 /* Check size of a buffer, it must match our expectations */
1802 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION
) != Size
)
1803 return STATUS_INFO_LENGTH_MISMATCH
;
1805 /* Calculate total value of context switches across all processors */
1806 ContextSwitches
= 0;
1807 for (i
= 0; i
< KeNumberProcessors
; i
++)
1809 Prcb
= KiProcessorBlock
[i
];
1812 ContextSwitches
+= KeGetContextSwitches(Prcb
);
1816 ContextSwitchInformation
->ContextSwitches
= ContextSwitches
;
1819 ContextSwitchInformation
->FindAny
= 0;
1820 ContextSwitchInformation
->FindLast
= 0;
1821 ContextSwitchInformation
->FindIdeal
= 0;
1822 ContextSwitchInformation
->IdleAny
= 0;
1823 ContextSwitchInformation
->IdleCurrent
= 0;
1824 ContextSwitchInformation
->IdleLast
= 0;
1825 ContextSwitchInformation
->IdleIdeal
= 0;
1826 ContextSwitchInformation
->PreemptAny
= 0;
1827 ContextSwitchInformation
->PreemptCurrent
= 0;
1828 ContextSwitchInformation
->PreemptLast
= 0;
1829 ContextSwitchInformation
->SwitchToIdle
= 0;
1831 return STATUS_SUCCESS
;
1834 /* Class 37 - Registry Quota Information */
1835 QSI_DEF(SystemRegistryQuotaInformation
)
1837 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1839 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1840 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1842 return STATUS_INFO_LENGTH_MISMATCH
;
1845 DPRINT1("Faking max registry size of 32 MB\n");
1846 srqi
->RegistryQuotaAllowed
= 0x2000000;
1847 srqi
->RegistryQuotaUsed
= 0x200000;
1848 srqi
->PagedPoolSize
= 0x200000;
1850 return STATUS_SUCCESS
;
1853 SSI_DEF(SystemRegistryQuotaInformation
)
1856 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1857 return STATUS_NOT_IMPLEMENTED
;
1860 /* Class 38 - Load And Call Image */
1861 SSI_DEF(SystemExtendServiceTableInformation
)
1863 UNICODE_STRING ImageName
;
1864 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1865 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1867 PIMAGE_NT_HEADERS NtHeader
;
1868 DRIVER_OBJECT Win32k
;
1869 PDRIVER_INITIALIZE DriverInit
;
1871 ULONG_PTR EntryPoint
;
1873 /* Validate the size */
1874 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1876 /* Check who is calling */
1877 if (PreviousMode
!= KernelMode
)
1879 static const UNICODE_STRING Win32kName
=
1880 RTL_CONSTANT_STRING(L
"\\SystemRoot\\System32\\win32k.sys");
1882 /* Make sure we can load drivers */
1883 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1885 /* FIXME: We can't, fail */
1886 return STATUS_PRIVILEGE_NOT_HELD
;
1891 /* Probe and copy the unicode string */
1892 ProbeForRead(Buffer
, sizeof(ImageName
), 1);
1893 ImageName
= *(PUNICODE_STRING
)Buffer
;
1895 /* Probe the string buffer */
1896 ProbeForRead(ImageName
.Buffer
, ImageName
.Length
, sizeof(WCHAR
));
1898 /* Check if we have the correct name (nothing else is allowed!) */
1899 if (!RtlEqualUnicodeString(&ImageName
, &Win32kName
, FALSE
))
1901 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD
);
1904 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1906 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1910 /* Recursively call the function, so that we are from kernel mode */
1911 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1913 sizeof(Win32kName
));
1916 /* Load the image */
1917 Status
= MmLoadSystemImage((PUNICODE_STRING
)Buffer
,
1921 (PVOID
)&ModuleObject
,
1924 if (!NT_SUCCESS(Status
)) return Status
;
1926 /* Get the headers */
1927 NtHeader
= RtlImageNtHeader(ImageBase
);
1931 MmUnloadSystemImage(ModuleObject
);
1932 return STATUS_INVALID_IMAGE_FORMAT
;
1935 /* Get the entrypoint */
1936 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1937 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1938 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1940 /* Create a dummy device */
1941 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1942 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1943 Win32k
.DriverStart
= ImageBase
;
1946 Status
= (DriverInit
)(&Win32k
, NULL
);
1947 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1949 /* Unload if we failed */
1950 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1954 /* Class 39 - Priority Separation */
1955 SSI_DEF(SystemPrioritySeperation
)
1957 /* Check if the size is correct */
1958 if (Size
!= sizeof(ULONG
))
1960 return STATUS_INFO_LENGTH_MISMATCH
;
1963 /* We need the TCB privilege */
1964 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, ExGetPreviousMode()))
1966 return STATUS_PRIVILEGE_NOT_HELD
;
1969 /* Modify the quantum table */
1970 PsChangeQuantumTable(TRUE
, *(PULONG
)Buffer
);
1972 return STATUS_SUCCESS
;
1976 QSI_DEF(SystemVerifierAddDriverInformation
)
1979 DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n");
1980 return STATUS_NOT_IMPLEMENTED
;
1984 QSI_DEF(SystemVerifierRemoveDriverInformation
)
1987 DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n");
1988 return STATUS_NOT_IMPLEMENTED
;
1991 /* Class 42 - Power Information */
1992 QSI_DEF(SystemProcessorIdleInformation
)
1994 *ReqSize
= sizeof(PROCESSOR_POWER_INFORMATION
) * KeNumberProcessors
;
1996 if (sizeof(PROCESSOR_POWER_INFORMATION
) * KeNumberProcessors
> Size
)
1998 return STATUS_INFO_LENGTH_MISMATCH
;
2002 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
2003 return STATUS_NOT_IMPLEMENTED
;
2007 QSI_DEF(SystemLegacyDriverInformation
)
2010 DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n");
2011 return STATUS_NOT_IMPLEMENTED
;
2014 /* Class 44 - Current Time Zone Information */
2015 QSI_DEF(SystemCurrentTimeZoneInformation
)
2017 *ReqSize
= sizeof(RTL_TIME_ZONE_INFORMATION
);
2019 if (sizeof(RTL_TIME_ZONE_INFORMATION
) != Size
)
2021 return STATUS_INFO_LENGTH_MISMATCH
;
2024 /* Copy the time zone information struct */
2027 sizeof(RTL_TIME_ZONE_INFORMATION
));
2029 return STATUS_SUCCESS
;
2033 SSI_DEF(SystemCurrentTimeZoneInformation
)
2035 /* Check user buffer's size */
2036 if (Size
< sizeof(RTL_TIME_ZONE_INFORMATION
))
2038 return STATUS_INFO_LENGTH_MISMATCH
;
2041 return ExpSetTimeZoneInformation((PRTL_TIME_ZONE_INFORMATION
)Buffer
);
2046 ExpCopyLookasideInformation(
2047 PSYSTEM_LOOKASIDE_INFORMATION
*InfoPointer
,
2048 PULONG RemainingPointer
,
2049 PLIST_ENTRY ListHead
,
2050 BOOLEAN ListUsesMisses
)
2053 PSYSTEM_LOOKASIDE_INFORMATION Info
;
2054 PGENERAL_LOOKASIDE LookasideList
;
2055 PLIST_ENTRY ListEntry
;
2058 /* Get info pointer and remaining count of free array element */
2059 Info
= *InfoPointer
;
2060 Remaining
= *RemainingPointer
;
2062 /* Loop as long as we have lookaside lists and free array elements */
2063 for (ListEntry
= ListHead
->Flink
;
2064 (ListEntry
!= ListHead
) && (Remaining
> 0);
2065 ListEntry
= ListEntry
->Flink
, Remaining
--)
2067 LookasideList
= CONTAINING_RECORD(ListEntry
, GENERAL_LOOKASIDE
, ListEntry
);
2069 /* Fill the next array element */
2070 Info
->CurrentDepth
= LookasideList
->Depth
;
2071 Info
->MaximumDepth
= LookasideList
->MaximumDepth
;
2072 Info
->TotalAllocates
= LookasideList
->TotalAllocates
;
2073 Info
->TotalFrees
= LookasideList
->TotalFrees
;
2074 Info
->Type
= LookasideList
->Type
;
2075 Info
->Tag
= LookasideList
->Tag
;
2076 Info
->Size
= LookasideList
->Size
;
2078 /* Check how the lists track misses/hits */
2082 Info
->AllocateMisses
= LookasideList
->AllocateMisses
;
2083 Info
->FreeMisses
= LookasideList
->FreeMisses
;
2087 /* Calculate misses */
2088 Info
->AllocateMisses
= LookasideList
->TotalAllocates
2089 - LookasideList
->AllocateHits
;
2090 Info
->FreeMisses
= LookasideList
->TotalFrees
2091 - LookasideList
->FreeHits
;
2095 /* Return the updated pointer and remaining count */
2096 *InfoPointer
= Info
;
2097 *RemainingPointer
= Remaining
;
2100 /* Class 45 - Lookaside Information */
2101 QSI_DEF(SystemLookasideInformation
)
2103 KPROCESSOR_MODE PreviousMode
;
2104 PSYSTEM_LOOKASIDE_INFORMATION Info
;
2106 ULONG MaxCount
, Remaining
;
2110 /* First we need to lock down the memory, since we are going to access it
2112 PreviousMode
= ExGetPreviousMode();
2113 Status
= ExLockUserBuffer(Buffer
,
2119 if (!NT_SUCCESS(Status
))
2121 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status
);
2125 /* Calculate how many items we can store */
2126 Remaining
= MaxCount
= Size
/ sizeof(SYSTEM_LOOKASIDE_INFORMATION
);
2132 /* Copy info from pool lookaside lists */
2133 ExpCopyLookasideInformation(&Info
,
2135 &ExPoolLookasideListHead
,
2142 /* Copy info from system lookaside lists */
2143 ExpCopyLookasideInformation(&Info
,
2145 &ExSystemLookasideListHead
,
2152 /* Acquire spinlock for ExpNonPagedLookasideListHead */
2153 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
2155 /* Copy info from non-paged lookaside lists */
2156 ExpCopyLookasideInformation(&Info
,
2158 &ExpNonPagedLookasideListHead
,
2161 /* Release spinlock for ExpNonPagedLookasideListHead */
2162 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
2169 /* Acquire spinlock for ExpPagedLookasideListHead */
2170 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
2172 /* Copy info from paged lookaside lists */
2173 ExpCopyLookasideInformation(&Info
,
2175 &ExpPagedLookasideListHead
,
2178 /* Release spinlock for ExpPagedLookasideListHead */
2179 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
2183 /* Release the locked user buffer */
2184 ExUnlockUserBuffer(Mdl
);
2186 /* Return the size of the actually written data */
2187 *ReqSize
= (MaxCount
- Remaining
) * sizeof(SYSTEM_LOOKASIDE_INFORMATION
);
2188 return STATUS_SUCCESS
;
2192 /* Class 46 - Set time slip event */
2193 SSI_DEF(SystemTimeSlipNotification
)
2196 DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n");
2197 return STATUS_NOT_IMPLEMENTED
;
2202 MmSessionCreate(OUT PULONG SessionId
);
2206 MmSessionDelete(IN ULONG SessionId
);
2208 /* Class 47 - Create a new session (TSE) */
2209 SSI_DEF(SystemSessionCreate
)
2212 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2215 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
2217 if (PreviousMode
!= KernelMode
)
2219 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
2221 return STATUS_PRIVILEGE_NOT_HELD
;
2224 ProbeForWriteUlong(Buffer
);
2227 Status
= MmSessionCreate(&SessionId
);
2228 if (NT_SUCCESS(Status
)) *(PULONG
)Buffer
= SessionId
;
2234 /* Class 48 - Delete an existing session (TSE) */
2235 SSI_DEF(SystemSessionDetach
)
2238 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2240 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
2242 if (PreviousMode
!= KernelMode
)
2244 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
2246 return STATUS_PRIVILEGE_NOT_HELD
;
2250 SessionId
= *(PULONG
)Buffer
;
2252 return MmSessionDelete(SessionId
);
2256 /* Class 49 - UNKNOWN */
2257 QSI_DEF(SystemSessionInformation
)
2260 DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n");
2261 return STATUS_NOT_IMPLEMENTED
;
2265 /* Class 50 - System range start address */
2266 QSI_DEF(SystemRangeStartInformation
)
2268 /* Check user buffer's size */
2269 if (Size
!= sizeof(ULONG_PTR
)) return STATUS_INFO_LENGTH_MISMATCH
;
2271 *(PULONG_PTR
)Buffer
= (ULONG_PTR
)MmSystemRangeStart
;
2273 if (ReqSize
) *ReqSize
= sizeof(ULONG_PTR
);
2275 return STATUS_SUCCESS
;
2278 /* Class 51 - Driver verifier information */
2279 QSI_DEF(SystemVerifierInformation
)
2282 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
2283 return STATUS_NOT_IMPLEMENTED
;
2287 SSI_DEF(SystemVerifierInformation
)
2290 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
2291 return STATUS_NOT_IMPLEMENTED
;
2296 SSI_DEF(SystemVerifierThunkExtend
)
2299 DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n");
2300 return STATUS_NOT_IMPLEMENTED
;
2304 /* Class 53 - A session's processes */
2305 QSI_DEF(SystemSessionProcessesInformation
)
2308 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
2309 return STATUS_NOT_IMPLEMENTED
;
2313 /* Class 54 - Load & map in system space */
2314 SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation
)
2317 DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n");
2318 return STATUS_NOT_IMPLEMENTED
;
2322 /* Class 55 - NUMA processor information */
2323 QSI_DEF(SystemNumaProcessorMap
)
2325 ULONG MaxEntries
, Node
;
2326 PSYSTEM_NUMA_INFORMATION NumaInformation
= (PSYSTEM_NUMA_INFORMATION
)Buffer
;
2328 /* Validate input size */
2329 if (Size
< sizeof(ULONG
))
2331 return STATUS_INFO_LENGTH_MISMATCH
;
2334 /* Return highest node */
2335 NumaInformation
->HighestNodeNumber
= KeNumberNodes
- 1;
2337 /* Compute how much entries we will be able to put in output structure */
2338 MaxEntries
= (Size
- FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
)) / sizeof(ULONGLONG
);
2339 /* Make sure we don't overflow KeNodeBlock */
2340 if (MaxEntries
> KeNumberNodes
)
2342 MaxEntries
= KeNumberNodes
;
2345 /* If we have entries to write, and room for it */
2346 if (Size
>= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
) &&
2349 /* Already set size we return */
2350 *ReqSize
= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
) +
2351 MaxEntries
* sizeof(ULONGLONG
);
2353 /* For each node, return processor mask */
2354 for (Node
= 0; Node
< MaxEntries
; ++Node
)
2356 NumaInformation
->ActiveProcessorsAffinityMask
[Node
] = KeNodeBlock
[Node
]->ProcessorMask
;
2361 /* We only returned highest node number */
2362 *ReqSize
= sizeof(ULONG
);
2365 return STATUS_SUCCESS
;
2369 /* Class 56 - Prefetcher information */
2370 QSI_DEF(SystemPrefetcherInformation
)
2373 DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n");
2374 return STATUS_NOT_IMPLEMENTED
;
2378 /* Class 57 - Extended process information */
2379 QSI_DEF(SystemExtendedProcessInformation
)
2382 DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n");
2383 return STATUS_NOT_IMPLEMENTED
;
2387 /* Class 58 - Recommended shared ata alignment */
2388 QSI_DEF(SystemRecommendedSharedDataAlignment
)
2391 DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n");
2392 return STATUS_NOT_IMPLEMENTED
;
2396 /* Class 60 - NUMA memory information */
2397 QSI_DEF(SystemNumaAvailableMemory
)
2399 ULONG MaxEntries
, Node
;
2400 PSYSTEM_NUMA_INFORMATION NumaInformation
= (PSYSTEM_NUMA_INFORMATION
)Buffer
;
2402 /* Validate input size */
2403 if (Size
< sizeof(ULONG
))
2405 return STATUS_INFO_LENGTH_MISMATCH
;
2408 /* Return highest node */
2409 NumaInformation
->HighestNodeNumber
= KeNumberNodes
- 1;
2411 /* Compute how much entries we will be able to put in output structure */
2412 MaxEntries
= (Size
- FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
)) / sizeof(ULONGLONG
);
2413 /* Make sure we don't overflow KeNodeBlock */
2414 if (MaxEntries
> KeNumberNodes
)
2416 MaxEntries
= KeNumberNodes
;
2419 /* If we have entries to write, and room for it */
2420 if (Size
>= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
) &&
2423 /* Already set size we return */
2424 *ReqSize
= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
) +
2425 MaxEntries
* sizeof(ULONGLONG
);
2427 /* If we have a single entry (us), directly return MM information */
2428 if (MaxEntries
== 1)
2430 NumaInformation
->AvailableMemory
[0] = MmAvailablePages
<< PAGE_SHIFT
;
2434 /* Otherwise, for each node, return available bytes */
2435 for (Node
= 0; Node
< MaxEntries
; ++Node
)
2437 NumaInformation
->AvailableMemory
[Node
] = (KeNodeBlock
[Node
]->FreeCount
[0] + KeNodeBlock
[Node
]->FreeCount
[1]) << PAGE_SHIFT
;
2443 /* We only returned highest node number */
2444 *ReqSize
= sizeof(ULONG
);
2447 return STATUS_SUCCESS
;
2450 /* Class 64 - Extended handle information */
2451 QSI_DEF(SystemExtendedHandleInformation
)
2453 PSYSTEM_HANDLE_INFORMATION_EX HandleInformation
;
2454 PLIST_ENTRY NextTableEntry
;
2455 PHANDLE_TABLE HandleTable
;
2456 PHANDLE_TABLE_ENTRY HandleTableEntry
;
2463 DPRINT("NtQuerySystemInformation - SystemExtendedHandleInformation\n");
2465 /* Set initial required buffer size */
2466 *ReqSize
= FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX
, Handle
);
2468 /* Check user's buffer size */
2469 if (Size
< *ReqSize
)
2471 return STATUS_INFO_LENGTH_MISMATCH
;
2474 /* We need to lock down the memory */
2475 Status
= ExLockUserBuffer(Buffer
,
2477 ExGetPreviousMode(),
2479 (PVOID
*)&HandleInformation
,
2481 if (!NT_SUCCESS(Status
))
2483 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status
);
2487 /* Reset of count of handles */
2488 HandleInformation
->Count
= 0;
2490 /* Enter a critical region */
2491 KeEnterCriticalRegion();
2493 /* Acquire the handle table lock */
2494 ExAcquirePushLockShared(&HandleTableListLock
);
2496 /* Enumerate all system handles */
2497 for (NextTableEntry
= HandleTableListHead
.Flink
;
2498 NextTableEntry
!= &HandleTableListHead
;
2499 NextTableEntry
= NextTableEntry
->Flink
)
2501 /* Get current handle table */
2502 HandleTable
= CONTAINING_RECORD(NextTableEntry
, HANDLE_TABLE
, HandleTableList
);
2504 /* Set the initial value and loop the entries */
2506 while ((HandleTableEntry
= ExpLookupHandleTableEntry(HandleTable
, Handle
)))
2508 /* Validate the entry */
2509 if ((HandleTableEntry
->Object
) &&
2510 (HandleTableEntry
->NextFreeTableEntry
!= -2))
2512 /* Increase of count of handles */
2513 ++HandleInformation
->Count
;
2515 /* Lock the entry */
2516 if (ExpLockHandleTableEntry(HandleTable
, HandleTableEntry
))
2518 /* Increase required buffer size */
2519 *ReqSize
+= sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
);
2521 /* Check user's buffer size */
2522 if (*ReqSize
> Size
)
2524 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2528 POBJECT_HEADER ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
2530 /* Filling handle information */
2531 HandleInformation
->Handle
[Index
].UniqueProcessId
=
2532 (USHORT
)(ULONG_PTR
) HandleTable
->UniqueProcessId
;
2534 HandleInformation
->Handle
[Index
].CreatorBackTraceIndex
= 0;
2536 #if 0 /* FIXME!!! Type field currupted */
2537 HandleInformation
->Handles
[Index
].ObjectTypeIndex
=
2538 (UCHAR
) ObjectHeader
->Type
->Index
;
2540 HandleInformation
->Handle
[Index
].ObjectTypeIndex
= 0;
2543 HandleInformation
->Handle
[Index
].HandleAttributes
=
2544 HandleTableEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
;
2546 HandleInformation
->Handle
[Index
].HandleValue
=
2547 (USHORT
)(ULONG_PTR
) Handle
.GenericHandleOverlay
;
2549 HandleInformation
->Handle
[Index
].Object
= &ObjectHeader
->Body
;
2551 HandleInformation
->Handle
[Index
].GrantedAccess
=
2552 HandleTableEntry
->GrantedAccess
;
2554 HandleInformation
->Handle
[Index
].Reserved
= 0;
2560 ExUnlockHandleTableEntry(HandleTable
, HandleTableEntry
);
2564 /* Go to the next entry */
2565 Handle
.Value
+= sizeof(HANDLE
);
2569 /* Release the lock */
2570 ExReleasePushLockShared(&HandleTableListLock
);
2572 /* Leave the critical region */
2573 KeLeaveCriticalRegion();
2575 /* Release the locked user buffer */
2576 ExUnlockUserBuffer(Mdl
);
2581 /* Class 76 - System firmware table information */
2582 QSI_DEF(SystemFirmwareTableInformation
)
2584 PSYSTEM_FIRMWARE_TABLE_INFORMATION SysFirmwareInfo
= (PSYSTEM_FIRMWARE_TABLE_INFORMATION
)Buffer
;
2585 NTSTATUS Status
= STATUS_SUCCESS
;
2588 ULONG TableCount
= 0;
2590 DPRINT("NtQuerySystemInformation - SystemFirmwareTableInformation\n");
2592 /* Set initial required buffer size */
2593 *ReqSize
= FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
2595 /* Check user's buffer size */
2596 if (Size
< *ReqSize
)
2598 return STATUS_INFO_LENGTH_MISMATCH
;
2601 InputBufSize
= SysFirmwareInfo
->TableBufferLength
;
2602 switch (SysFirmwareInfo
->ProviderSignature
)
2605 * ExpFirmwareTableResource and ExpFirmwareTableProviderListHead
2606 * variables should be used there somehow...
2610 /* FIXME: Not implemented yet */
2611 DPRINT1("ACPI provider not implemented\n");
2612 Status
= STATUS_NOT_IMPLEMENTED
;
2617 /* FIXME: Not implemented yet */
2618 DPRINT1("FIRM provider not implemented\n");
2619 Status
= STATUS_NOT_IMPLEMENTED
;
2624 Status
= ExpGetRawSMBiosTable(NULL
, &DataSize
, 0);
2628 if (SysFirmwareInfo
->Action
== SystemFirmwareTable_Enumerate
)
2630 DataSize
= TableCount
* sizeof(ULONG
);
2631 if (DataSize
<= InputBufSize
)
2633 *(ULONG
*)SysFirmwareInfo
->TableBuffer
= 0;
2636 else if (SysFirmwareInfo
->Action
== SystemFirmwareTable_Get
2637 && DataSize
<= InputBufSize
)
2639 Status
= ExpGetRawSMBiosTable(SysFirmwareInfo
->TableBuffer
, &DataSize
, InputBufSize
);
2641 SysFirmwareInfo
->TableBufferLength
= DataSize
;
2647 DPRINT1("SystemFirmwareTableInformation: Unsupported provider (0x%x)\n",
2648 SysFirmwareInfo
->ProviderSignature
);
2649 Status
= STATUS_ILLEGAL_FUNCTION
;
2653 if (NT_SUCCESS(Status
))
2655 switch (SysFirmwareInfo
->Action
)
2657 case SystemFirmwareTable_Enumerate
:
2658 case SystemFirmwareTable_Get
:
2660 if (SysFirmwareInfo
->TableBufferLength
> InputBufSize
)
2662 Status
= STATUS_BUFFER_TOO_SMALL
;
2668 DPRINT1("SystemFirmwareTableInformation: Unsupported action (0x%x)\n",
2669 SysFirmwareInfo
->Action
);
2670 Status
= STATUS_ILLEGAL_FUNCTION
;
2676 SysFirmwareInfo
->TableBufferLength
= 0;
2681 /* Query/Set Calls Table */
2685 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
2686 NTSTATUS (* Set
) (PVOID
,ULONG
);
2692 // XX unknown behaviour
2694 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
2695 #define SI_QX(n) {QSI_USE(n),NULL}
2696 #define SI_XS(n) {NULL,SSI_USE(n)}
2697 #define SI_XX(n) {NULL,NULL}
2703 SI_QX(SystemBasicInformation
),
2704 SI_QX(SystemProcessorInformation
),
2705 SI_QX(SystemPerformanceInformation
),
2706 SI_QX(SystemTimeOfDayInformation
),
2707 SI_QX(SystemPathInformation
), /* should be SI_XX */
2708 SI_QX(SystemProcessInformation
),
2709 SI_QX(SystemCallCountInformation
),
2710 SI_QX(SystemDeviceInformation
),
2711 SI_QX(SystemProcessorPerformanceInformation
),
2712 SI_QS(SystemFlagsInformation
),
2713 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
2714 SI_QX(SystemModuleInformation
),
2715 SI_QX(SystemLocksInformation
),
2716 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
2717 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
2718 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
2719 SI_QX(SystemHandleInformation
),
2720 SI_QX(SystemObjectInformation
),
2721 SI_QX(SystemPageFileInformation
),
2722 SI_QX(SystemVdmInstemulInformation
),
2723 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
2724 SI_QS(SystemFileCacheInformation
),
2725 SI_QX(SystemPoolTagInformation
),
2726 SI_QX(SystemInterruptInformation
),
2727 SI_QS(SystemDpcBehaviourInformation
),
2728 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
2729 SI_XS(SystemLoadGdiDriverInformation
),
2730 SI_XS(SystemUnloadGdiDriverInformation
),
2731 SI_QS(SystemTimeAdjustmentInformation
),
2732 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
2733 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
2734 SI_QX(SystemPerformanceTraceInformation
), /* it should be SI_XX */
2735 SI_QX(SystemCrashDumpInformation
),
2736 SI_QX(SystemExceptionInformation
),
2737 SI_QX(SystemCrashDumpStateInformation
),
2738 SI_QX(SystemKernelDebuggerInformation
),
2739 SI_QX(SystemContextSwitchInformation
),
2740 SI_QS(SystemRegistryQuotaInformation
),
2741 SI_XS(SystemExtendServiceTableInformation
),
2742 SI_XS(SystemPrioritySeperation
),
2743 SI_QX(SystemVerifierAddDriverInformation
), /* it should be SI_XX */
2744 SI_QX(SystemVerifierRemoveDriverInformation
), /* it should be SI_XX */
2745 SI_QX(SystemProcessorIdleInformation
), /* it should be SI_XX */
2746 SI_QX(SystemLegacyDriverInformation
), /* it should be SI_XX */
2747 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
2748 SI_QX(SystemLookasideInformation
),
2749 SI_XS(SystemTimeSlipNotification
),
2750 SI_XS(SystemSessionCreate
),
2751 SI_XS(SystemSessionDetach
),
2752 SI_QX(SystemSessionInformation
), /* it should be SI_XX */
2753 SI_QX(SystemRangeStartInformation
),
2754 SI_QS(SystemVerifierInformation
),
2755 SI_XS(SystemVerifierThunkExtend
),
2756 SI_QX(SystemSessionProcessesInformation
),
2757 SI_XS(SystemLoadGdiDriverInSystemSpaceInformation
),
2758 SI_QX(SystemNumaProcessorMap
),
2759 SI_QX(SystemPrefetcherInformation
),
2760 SI_QX(SystemExtendedProcessInformation
),
2761 SI_QX(SystemRecommendedSharedDataAlignment
),
2762 SI_XX(SystemComPlusPackage
),
2763 SI_QX(SystemNumaAvailableMemory
),
2764 SI_XX(SystemProcessorPowerInformation
), /* FIXME: not implemented */
2765 SI_XX(SystemEmulationBasicInformation
), /* FIXME: not implemented */
2766 SI_XX(SystemEmulationProcessorInformation
), /* FIXME: not implemented */
2767 SI_QX(SystemExtendedHandleInformation
),
2768 SI_XX(SystemLostDelayedWriteInformation
), /* FIXME: not implemented */
2769 SI_XX(SystemBigPoolInformation
), /* FIXME: not implemented */
2770 SI_XX(SystemSessionPoolTagInformation
), /* FIXME: not implemented */
2771 SI_XX(SystemSessionMappedViewInformation
), /* FIXME: not implemented */
2772 SI_XX(SystemHotpatchInformation
), /* FIXME: not implemented */
2773 SI_XX(SystemObjectSecurityMode
), /* FIXME: not implemented */
2774 SI_XX(SystemWatchdogTimerHandler
), /* FIXME: not implemented */
2775 SI_XX(SystemWatchdogTimerInformation
), /* FIXME: not implemented */
2776 SI_XX(SystemLogicalProcessorInformation
), /* FIXME: not implemented */
2777 SI_XX(SystemWow64SharedInformation
), /* FIXME: not implemented */
2778 SI_XX(SystemRegisterFirmwareTableInformationHandler
), /* FIXME: not implemented */
2779 SI_QX(SystemFirmwareTableInformation
),
2782 C_ASSERT(SystemBasicInformation
== 0);
2783 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
2784 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
2792 NtQuerySystemInformation(
2793 _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2794 _Out_writes_bytes_to_opt_(SystemInformationLength
, *ReturnLength
) PVOID SystemInformation
,
2796 _Out_opt_ PULONG UnsafeResultLength
)
2798 KPROCESSOR_MODE PreviousMode
;
2799 ULONG ResultLength
= 0;
2800 ULONG Alignment
= TYPE_ALIGNMENT(ULONG
);
2801 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
2805 PreviousMode
= ExGetPreviousMode();
2809 #if (NTDDI_VERSION >= NTDDI_VISTA)
2811 * Check if the request is valid.
2813 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2815 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2819 if (PreviousMode
!= KernelMode
)
2821 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
2822 if (SystemInformationClass
== SystemKernelDebuggerInformation
)
2823 Alignment
= TYPE_ALIGNMENT(BOOLEAN
);
2825 ProbeForWrite(SystemInformation
, Length
, Alignment
);
2826 if (UnsafeResultLength
!= NULL
)
2827 ProbeForWriteUlong(UnsafeResultLength
);
2830 if (UnsafeResultLength
)
2831 *UnsafeResultLength
= 0;
2833 #if (NTDDI_VERSION < NTDDI_VISTA)
2835 * Check if the request is valid.
2837 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2839 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2843 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
2846 * Hand the request to a subhandler.
2848 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
2852 /* Save the result length to the caller */
2853 if (UnsafeResultLength
)
2854 *UnsafeResultLength
= ResultLength
;
2857 _SEH2_EXCEPT(ExSystemExceptionFilter())
2859 FStatus
= _SEH2_GetExceptionCode();
2869 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2870 IN PVOID SystemInformation
,
2871 IN ULONG SystemInformationLength
)
2873 NTSTATUS Status
= STATUS_INVALID_INFO_CLASS
;
2874 KPROCESSOR_MODE PreviousMode
;
2878 PreviousMode
= ExGetPreviousMode();
2883 * If called from user mode, check
2884 * possible unsafe arguments.
2886 if (PreviousMode
!= KernelMode
)
2888 ProbeForRead(SystemInformation
, SystemInformationLength
, sizeof(ULONG
));
2892 * Check the request is valid.
2894 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
2895 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
2897 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
2900 * Hand the request to a subhandler.
2902 Status
= CallQS
[SystemInformationClass
].Set(SystemInformation
,
2903 SystemInformationLength
);
2907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2909 Status
= _SEH2_GetExceptionCode();
2918 NtGetCurrentProcessorNumber(VOID
)
2921 return KeGetCurrentProcessorNumber();
2924 #undef ExGetPreviousMode
2927 ExGetPreviousMode(VOID
)
2930 return KeGetPreviousMode();