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 *****************************************************************/
17 /* The maximum size of an environment value (in bytes) */
18 #define MAX_ENVVAL_SIZE 1024
20 extern LIST_ENTRY HandleTableListHead
;
21 extern EX_PUSH_LOCK HandleTableListLock
;
23 FAST_MUTEX ExpEnvironmentLock
;
24 ERESOURCE ExpFirmwareTableResource
;
25 LIST_ENTRY ExpFirmwareTableProviderListHead
;
29 ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount
,
30 IN PLDR_DATA_TABLE_ENTRY LdrEntry
,
31 OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
)
35 ANSI_STRING ModuleName
;
38 ModuleInfo
->MappedBase
= NULL
;
39 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
40 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
41 ModuleInfo
->Flags
= LdrEntry
->Flags
;
42 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
43 ModuleInfo
->LoadOrderIndex
= (USHORT
)ModuleCount
;
44 ModuleInfo
->InitOrderIndex
= 0;
47 RtlInitEmptyAnsiString(&ModuleName
,
48 ModuleInfo
->FullPathName
,
49 sizeof(ModuleInfo
->FullPathName
));
52 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
53 &LdrEntry
->FullDllName
,
55 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
57 /* Calculate offset to name */
58 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
59 while ((p
> ModuleName
.Buffer
) && (*--p
))
61 /* Check if we found the separator */
62 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
64 /* We did, break out */
71 ModuleInfo
->OffsetToFileName
= (USHORT
)(p
- ModuleName
.Buffer
);
75 /* Return empty name */
76 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
77 ModuleInfo
->OffsetToFileName
= 0;
85 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
86 IN PLIST_ENTRY UserModeList
,
87 OUT PRTL_PROCESS_MODULES Modules
,
89 OUT PULONG ReturnLength
)
91 NTSTATUS Status
= STATUS_SUCCESS
;
93 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
94 PLDR_DATA_TABLE_ENTRY LdrEntry
;
95 ULONG ModuleCount
= 0;
96 PLIST_ENTRY NextEntry
;
99 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
100 ModuleInfo
= &Modules
->Modules
[0];
102 /* Loop the kernel list */
103 NextEntry
= KernelModeList
->Flink
;
104 while (NextEntry
!= KernelModeList
)
107 LdrEntry
= CONTAINING_RECORD(NextEntry
,
108 LDR_DATA_TABLE_ENTRY
,
111 /* Update size and check if we can manage one more entry */
112 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
113 if (Length
>= RequiredLength
)
115 Status
= ExpConvertLdrModuleToRtlModule(ModuleCount
,
119 /* Go to the next module */
125 Status
= STATUS_INFO_LENGTH_MISMATCH
;
128 /* Update count and move to next entry */
130 NextEntry
= NextEntry
->Flink
;
133 /* Check if caller also wanted user modules */
136 NextEntry
= UserModeList
->Flink
;
137 while (NextEntry
!= UserModeList
)
140 LdrEntry
= CONTAINING_RECORD(NextEntry
,
141 LDR_DATA_TABLE_ENTRY
,
144 /* Update size and check if we can manage one more entry */
145 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
146 if (Length
>= RequiredLength
)
148 Status
= ExpConvertLdrModuleToRtlModule(ModuleCount
,
152 /* Go to the next module */
158 Status
= STATUS_INFO_LENGTH_MISMATCH
;
161 /* Update count and move to next entry */
163 NextEntry
= NextEntry
->Flink
;
167 /* Update return length */
168 if (ReturnLength
) *ReturnLength
= RequiredLength
;
170 /* Validate the length again */
171 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
173 /* Set the final count */
174 Modules
->NumberOfModules
= ModuleCount
;
178 /* Otherwise, we failed */
179 Status
= STATUS_INFO_LENGTH_MISMATCH
;
188 ExUnlockUserBuffer(PMDL Mdl
)
191 ExFreePoolWithTag(Mdl
, TAG_MDL
);
199 KPROCESSOR_MODE AccessMode
,
200 LOCK_OPERATION Operation
,
201 PVOID
*MappedSystemVa
,
207 *MappedSystemVa
= NULL
;
210 /* Allocate an MDL for the buffer */
211 Mdl
= IoAllocateMdl(BaseAddress
, Length
, FALSE
, TRUE
, NULL
);
214 return STATUS_INSUFFICIENT_RESOURCES
;
217 /* Enter SEH for probing */
220 MmProbeAndLockPages(Mdl
, AccessMode
, Operation
);
222 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
224 ExFreePoolWithTag(Mdl
, TAG_MDL
);
225 _SEH2_YIELD(return _SEH2_GetExceptionCode());
229 /* Return the safe kernel mode buffer */
230 *MappedSystemVa
= MmGetSystemAddressForMdlSafe(Mdl
, NormalPagePriority
);
231 if (*MappedSystemVa
== NULL
)
233 ExUnlockUserBuffer(Mdl
);
234 return STATUS_INSUFFICIENT_RESOURCES
;
239 return STATUS_SUCCESS
;
242 /* FUNCTIONS *****************************************************************/
249 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
253 ULONGLONG ScaledIdle
;
255 Prcb
= KeGetCurrentPrcb();
257 ScaledIdle
= (ULONGLONG
)Prcb
->IdleThread
->KernelTime
* 100;
258 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
260 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
270 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
272 PULONG ProcessorNumber
)
276 Prcb
= KeGetCurrentPrcb();
278 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
279 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
280 *ProcessorNumber
= KeGetCurrentProcessorNumber();
288 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
290 /* Quick check to see if it exists at all */
291 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
293 /* Return our support for it */
294 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
302 ExVerifySuite(SUITE_TYPE SuiteType
)
304 if (SuiteType
== Personal
) return TRUE
;
310 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
311 OUT PWSTR ValueBuffer
,
312 IN ULONG ValueBufferLength
,
313 IN OUT PULONG ReturnLength OPTIONAL
)
316 UNICODE_STRING WName
;
320 UNICODE_STRING WValue
;
321 KPROCESSOR_MODE PreviousMode
;
325 /* Check if the call came from user mode */
326 PreviousMode
= ExGetPreviousMode();
327 if (PreviousMode
!= KernelMode
)
331 /* Probe the input and output buffers */
332 ProbeForRead(VariableName
, sizeof(UNICODE_STRING
), sizeof(ULONG
));
333 ProbeForWrite(ValueBuffer
, ValueBufferLength
, sizeof(WCHAR
));
334 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
336 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
338 /* Return the exception code */
339 _SEH2_YIELD(return _SEH2_GetExceptionCode());
344 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
345 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
, PreviousMode
))
347 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
348 return STATUS_PRIVILEGE_NOT_HELD
;
351 /* Copy the name to kernel space if necessary */
352 Status
= ProbeAndCaptureUnicodeString(&WName
, PreviousMode
, VariableName
);
353 if (!NT_SUCCESS(Status
)) return Status
;
355 /* Convert the name to ANSI and release the captured UNICODE string */
356 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
357 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
358 if (!NT_SUCCESS(Status
)) return Status
;
360 /* Allocate a buffer for the ANSI environment variable */
361 AnsiValueBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_ENVVAL_SIZE
, 'rvnE');
362 if (AnsiValueBuffer
== NULL
)
364 RtlFreeAnsiString(&AName
);
365 return STATUS_INSUFFICIENT_RESOURCES
;
368 /* Get the environment variable and free the ANSI name */
369 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
372 RtlFreeAnsiString(&AName
);
374 /* Check if we had success */
375 if (Result
== ESUCCESS
)
377 /* Copy the result back to the caller. */
380 /* Initialize ANSI string from the result */
381 RtlInitAnsiString(&AValue
, AnsiValueBuffer
);
383 /* Initialize a UNICODE string from the callers buffer */
384 RtlInitEmptyUnicodeString(&WValue
, ValueBuffer
, (USHORT
)ValueBufferLength
);
386 /* Convert the result to UNICODE */
387 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, FALSE
);
389 if (ReturnLength
!= NULL
)
390 *ReturnLength
= WValue
.Length
;
392 _SEH2_EXCEPT(ExSystemExceptionFilter())
394 Status
= _SEH2_GetExceptionCode();
400 Status
= STATUS_UNSUCCESSFUL
;
403 /* Free the allocated ANSI value buffer */
404 ExFreePoolWithTag(AnsiValueBuffer
, 'rvnE');
412 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
413 IN PUNICODE_STRING Value
)
415 UNICODE_STRING CapturedName
, CapturedValue
;
416 ANSI_STRING AName
, AValue
;
417 KPROCESSOR_MODE PreviousMode
;
422 PreviousMode
= ExGetPreviousMode();
425 * Copy the strings to kernel space if necessary
427 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
430 if (NT_SUCCESS(Status
))
432 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
435 if (NT_SUCCESS(Status
))
438 * according to ntinternals the SeSystemEnvironmentName privilege is required!
440 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
444 * convert the strings to ANSI
446 Status
= RtlUnicodeStringToAnsiString(&AName
,
449 if (NT_SUCCESS(Status
))
451 Status
= RtlUnicodeStringToAnsiString(&AValue
,
454 if (NT_SUCCESS(Status
))
456 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
459 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
465 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
466 Status
= STATUS_PRIVILEGE_NOT_HELD
;
469 ReleaseCapturedUnicodeString(&CapturedValue
,
473 ReleaseCapturedUnicodeString(&CapturedName
,
482 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
484 IN ULONG BufferLength
)
487 return STATUS_NOT_IMPLEMENTED
;
492 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
493 IN LPGUID VendorGuid
,
495 IN OUT PULONG ReturnLength
,
496 IN OUT PULONG Attributes
)
499 return STATUS_NOT_IMPLEMENTED
;
504 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
505 IN LPGUID VendorGuid
,
507 IN OUT PULONG ReturnLength
,
508 IN OUT PULONG Attributes
)
511 return STATUS_NOT_IMPLEMENTED
;
514 /* --- Query/Set System Information --- */
517 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
518 * so the stack is popped only in one place on x86 platform.
520 #define QSI_USE(n) QSI##n
522 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
524 #define SSI_USE(n) SSI##n
526 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
530 ExQueryPoolUsage(OUT PULONG PagedPoolPages
,
531 OUT PULONG NonPagedPoolPages
,
532 OUT PULONG PagedPoolAllocs
,
533 OUT PULONG PagedPoolFrees
,
534 OUT PULONG PagedPoolLookasideHits
,
535 OUT PULONG NonPagedPoolAllocs
,
536 OUT PULONG NonPagedPoolFrees
,
537 OUT PULONG NonPagedPoolLookasideHits
);
539 /* Class 0 - Basic Information */
540 QSI_DEF(SystemBasicInformation
)
542 PSYSTEM_BASIC_INFORMATION Sbi
543 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
545 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
547 /* Check user buffer's size */
548 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
550 return STATUS_INFO_LENGTH_MISMATCH
;
553 RtlZeroMemory(Sbi
, Size
);
555 Sbi
->TimerResolution
= KeMaximumIncrement
;
556 Sbi
->PageSize
= PAGE_SIZE
;
557 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
558 Sbi
->LowestPhysicalPageNumber
= (ULONG
)MmLowestPhysicalPage
;
559 Sbi
->HighestPhysicalPageNumber
= (ULONG
)MmHighestPhysicalPage
;
560 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
561 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
562 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
563 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
564 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
566 return STATUS_SUCCESS
;
569 /* Class 1 - Processor Information */
570 QSI_DEF(SystemProcessorInformation
)
572 PSYSTEM_PROCESSOR_INFORMATION Spi
573 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
575 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
577 /* Check user buffer's size */
578 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
580 return STATUS_INFO_LENGTH_MISMATCH
;
582 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
583 Spi
->ProcessorLevel
= KeProcessorLevel
;
584 Spi
->ProcessorRevision
= KeProcessorRevision
;
586 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
588 DPRINT("Arch %u Level %u Rev 0x%x\n", Spi
->ProcessorArchitecture
,
589 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
591 return STATUS_SUCCESS
;
594 /* Class 2 - Performance Information */
595 QSI_DEF(SystemPerformanceInformation
)
597 ULONG IdleUser
, IdleKernel
;
598 PSYSTEM_PERFORMANCE_INFORMATION Spi
599 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
601 PEPROCESS TheIdleProcess
;
603 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
605 /* Check user buffer's size */
606 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
608 return STATUS_INFO_LENGTH_MISMATCH
;
611 TheIdleProcess
= PsIdleProcess
;
613 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
614 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
615 Spi
->IoReadTransferCount
= IoReadTransferCount
;
616 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
617 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
618 Spi
->IoReadOperationCount
= IoReadOperationCount
;
619 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
620 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
622 Spi
->AvailablePages
= (ULONG
)MmAvailablePages
;
624 * Add up all the used "Committed" memory + pagefile.
625 * Not sure this is right. 8^\
627 Spi
->CommittedPages
= MiMemoryConsumers
[MC_SYSTEM
].PagesUsed
+
628 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
629 MiMemoryConsumers
[MC_USER
].PagesUsed
+
632 * Add up the full system total + pagefile.
633 * All this make Taskmgr happy but not sure it is the right numbers.
634 * This too, fixes some of GlobalMemoryStatusEx numbers.
636 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
638 Spi
->PeakCommitment
= 0; /* FIXME */
639 Spi
->PageFaultCount
= 0; /* FIXME */
640 Spi
->CopyOnWriteCount
= 0; /* FIXME */
641 Spi
->TransitionCount
= 0; /* FIXME */
642 Spi
->CacheTransitionCount
= 0; /* FIXME */
643 Spi
->DemandZeroCount
= 0; /* FIXME */
644 Spi
->PageReadCount
= 0; /* FIXME */
645 Spi
->PageReadIoCount
= 0; /* FIXME */
646 Spi
->CacheReadCount
= 0; /* FIXME */
647 Spi
->CacheIoCount
= 0; /* FIXME */
648 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
649 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
650 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
651 Spi
->MappedWriteIoCount
= 0; /* FIXME */
653 Spi
->PagedPoolPages
= 0;
654 Spi
->NonPagedPoolPages
= 0;
655 Spi
->PagedPoolAllocs
= 0;
656 Spi
->PagedPoolFrees
= 0;
657 Spi
->PagedPoolLookasideHits
= 0;
658 Spi
->NonPagedPoolAllocs
= 0;
659 Spi
->NonPagedPoolFrees
= 0;
660 Spi
->NonPagedPoolLookasideHits
= 0;
661 ExQueryPoolUsage(&Spi
->PagedPoolPages
,
662 &Spi
->NonPagedPoolPages
,
663 &Spi
->PagedPoolAllocs
,
664 &Spi
->PagedPoolFrees
,
665 &Spi
->PagedPoolLookasideHits
,
666 &Spi
->NonPagedPoolAllocs
,
667 &Spi
->NonPagedPoolFrees
,
668 &Spi
->NonPagedPoolLookasideHits
);
669 Spi
->FreeSystemPtes
= 0; /* FIXME */
671 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
673 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
674 Spi
->Spare3Count
= 0; /* FIXME */
676 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
677 Spi
->ResidentPagedPoolPage
= 0; /* FIXME */
679 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
680 Spi
->CcFastReadNoWait
= 0; /* FIXME */
681 Spi
->CcFastReadWait
= 0; /* FIXME */
682 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
683 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
685 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
686 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
687 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
688 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
690 Spi
->CcMapDataNoWait
= 0; /* FIXME */
691 Spi
->CcMapDataWait
= 0; /* FIXME */
692 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
693 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
695 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
696 Spi
->CcPinReadNoWait
= 0; /* FIXME */
697 Spi
->CcPinReadWait
= 0; /* FIXME */
698 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
699 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
700 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
701 Spi
->CcCopyReadWait
= 0; /* FIXME */
702 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
703 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
705 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
706 Spi
->CcMdlReadWait
= 0; /* FIXME */
707 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
708 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
709 Spi
->CcReadAheadIos
= 0; /* FIXME */
710 Spi
->CcLazyWriteIos
= 0; /* FIXME */
711 Spi
->CcLazyWritePages
= 0; /* FIXME */
712 Spi
->CcDataFlushes
= 0; /* FIXME */
713 Spi
->CcDataPages
= 0; /* FIXME */
714 Spi
->ContextSwitches
= 0; /* FIXME */
715 Spi
->FirstLevelTbFills
= 0; /* FIXME */
716 Spi
->SecondLevelTbFills
= 0; /* FIXME */
717 Spi
->SystemCalls
= 0; /* FIXME */
719 return STATUS_SUCCESS
;
722 /* Class 3 - Time Of Day Information */
723 QSI_DEF(SystemTimeOfDayInformation
)
725 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
726 LARGE_INTEGER CurrentTime
;
728 /* Set amount of written information to 0 */
731 /* Check user buffer's size */
732 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
734 return STATUS_INFO_LENGTH_MISMATCH
;
737 /* Get current time */
738 KeQuerySystemTime(&CurrentTime
);
740 /* Zero local buffer */
741 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
743 /* Fill local time structure */
744 Sti
.BootTime
= KeBootTime
;
745 Sti
.CurrentTime
= CurrentTime
;
746 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
747 Sti
.TimeZoneId
= ExpTimeZoneId
;
750 /* Copy as much as requested by caller */
751 RtlCopyMemory(Buffer
, &Sti
, Size
);
753 /* Set amount of information we copied */
756 return STATUS_SUCCESS
;
759 /* Class 4 - Path Information */
760 QSI_DEF(SystemPathInformation
)
762 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
763 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
765 return STATUS_BREAKPOINT
;
768 /* Class 5 - Process Information */
769 QSI_DEF(SystemProcessInformation
)
771 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
772 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
773 PEPROCESS Process
= NULL
, SystemProcess
;
774 PETHREAD CurrentThread
;
775 ANSI_STRING ImageName
;
777 USHORT ImageNameMaximumLength
; // image name length in bytes
778 USHORT ImageNameLength
;
779 PLIST_ENTRY CurrentEntry
;
780 ULONG TotalSize
= 0, ThreadsCount
;
781 ULONG TotalUser
, TotalKernel
;
783 NTSTATUS Status
= STATUS_SUCCESS
;
784 PUNICODE_STRING TempProcessImageName
;
785 _SEH2_VOLATILE PUNICODE_STRING ProcessImageName
= NULL
;
787 BOOLEAN Overflow
= FALSE
;
791 /* scan the process list */
793 PSYSTEM_PROCESS_INFORMATION Spi
794 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
796 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
798 /* Check for overflow */
799 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
804 /* Zero user's buffer */
805 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
807 SystemProcess
= PsIdleProcess
;
808 Process
= SystemProcess
;
809 Current
= (PUCHAR
) Spi
;
813 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
815 /* Lock the Process */
816 KeEnterCriticalRegion();
817 ExAcquirePushLockShared(&Process
->ProcessLock
);
819 if ((Process
->ProcessExiting
) &&
820 (Process
->Pcb
.Header
.SignalState
) &&
821 !(Process
->ActiveThreads
) &&
822 (IsListEmpty(&Process
->Pcb
.ThreadListHead
)))
824 DPRINT1("Process %p (%s:%p) is a zombie\n",
825 Process
, Process
->ImageFileName
, Process
->UniqueProcessId
);
827 ImageNameMaximumLength
= 0;
829 /* Unlock the Process */
830 ExReleasePushLockShared(&Process
->ProcessLock
);
831 KeLeaveCriticalRegion();
836 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
837 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
840 CurrentEntry
= CurrentEntry
->Flink
;
843 // size of the structure for every process
844 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
846 Status
= SeLocateProcessImageName(Process
, &TempProcessImageName
);
847 ProcessImageName
= TempProcessImageName
;
849 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
851 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
852 /* Loop the file name*/
853 while (szSrc
> ProcessImageName
->Buffer
)
855 /* Make sure this isn't a backslash */
856 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
863 ImageNameLength
+= sizeof(WCHAR
);
867 if (!ImageNameLength
&& Process
!= PsIdleProcess
)
869 ImageNameLength
= (USHORT
)strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
872 /* Round up the image name length as NT does */
873 if (ImageNameLength
> 0)
874 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
876 ImageNameMaximumLength
= 0;
878 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
880 /* Check for overflow */
881 if (TotalSize
> Size
)
886 /* Fill system information */
889 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginning of the next structure
890 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
891 SpiCurrent
->CreateTime
= Process
->CreateTime
;
892 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
893 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
894 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
896 /* Copy name to the end of the struct */
897 if(Process
!= PsIdleProcess
)
901 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
905 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
906 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
911 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
914 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
915 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
916 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
917 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
918 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
919 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
920 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
921 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
922 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
923 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
924 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
925 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
926 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
927 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
928 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
929 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
930 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
932 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
933 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
935 CurrentThread
= CONTAINING_RECORD(CurrentEntry
, ETHREAD
, Tcb
.ThreadListEntry
);
937 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
938 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
939 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
940 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
941 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
942 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
943 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
944 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
945 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
946 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
947 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
950 CurrentEntry
= CurrentEntry
->Flink
;
953 /* Query total user/kernel times of a process */
954 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
955 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
956 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
959 if (ProcessImageName
)
961 /* Release the memory allocated by SeLocateProcessImageName */
962 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
963 ProcessImageName
= NULL
;
966 /* Unlock the Process */
967 ExReleasePushLockShared(&Process
->ProcessLock
);
968 KeLeaveCriticalRegion();
970 /* Handle idle process entry */
972 if (Process
== PsIdleProcess
) Process
= NULL
;
974 Process
= PsGetNextProcess(Process
);
976 if ((Process
== SystemProcess
) || (Process
== NULL
))
979 SpiCurrent
->NextEntryOffset
= 0;
983 Current
+= CurrentSize
+ ImageNameMaximumLength
;
984 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
987 ObDereferenceObject(Process
);
988 Status
= STATUS_SUCCESS
;
990 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
993 ObDereferenceObject(Process
);
994 if (ProcessImageName
)
996 /* Release the memory allocated by SeLocateProcessImageName */
997 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
1000 Status
= _SEH2_GetExceptionCode();
1005 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1007 *ReqSize
= TotalSize
;
1011 /* Class 6 - Call Count Information */
1012 QSI_DEF(SystemCallCountInformation
)
1015 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
1016 return STATUS_NOT_IMPLEMENTED
;
1019 /* Class 7 - Device Information */
1020 QSI_DEF(SystemDeviceInformation
)
1022 PSYSTEM_DEVICE_INFORMATION Sdi
1023 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
1024 PCONFIGURATION_INFORMATION ConfigInfo
;
1026 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
1028 /* Check user buffer's size */
1029 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
1031 return STATUS_INFO_LENGTH_MISMATCH
;
1034 ConfigInfo
= IoGetConfigurationInformation();
1036 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
1037 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
1038 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
1039 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
1040 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
1041 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
1043 return STATUS_SUCCESS
;
1046 /* Class 8 - Processor Performance Information */
1047 QSI_DEF(SystemProcessorPerformanceInformation
)
1049 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
1050 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
1056 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
1058 /* Check user buffer's size */
1059 if (Size
< *ReqSize
)
1061 return STATUS_INFO_LENGTH_MISMATCH
;
1064 for (i
= 0; i
< KeNumberProcessors
; i
++)
1066 /* Get the PRCB on this processor */
1067 Prcb
= KiProcessorBlock
[i
];
1069 /* Calculate total user and kernel times */
1070 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
1071 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
1072 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
1073 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
1074 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
1075 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
1076 Spi
->InterruptCount
= Prcb
->InterruptCount
;
1080 return STATUS_SUCCESS
;
1083 /* Class 9 - Flags Information */
1084 QSI_DEF(SystemFlagsInformation
)
1086 #if (NTDDI_VERSION >= NTDDI_VISTA)
1087 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
1090 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1092 return STATUS_INFO_LENGTH_MISMATCH
;
1095 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
1096 #if (NTDDI_VERSION < NTDDI_VISTA)
1097 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
1100 return STATUS_SUCCESS
;
1103 SSI_DEF(SystemFlagsInformation
)
1105 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1107 return STATUS_INFO_LENGTH_MISMATCH
;
1110 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, ExGetPreviousMode()))
1112 return STATUS_ACCESS_DENIED
;
1115 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
1116 return STATUS_SUCCESS
;
1119 /* Class 10 - Call Time Information */
1120 QSI_DEF(SystemCallTimeInformation
)
1123 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
1124 return STATUS_NOT_IMPLEMENTED
;
1127 /* Class 11 - Module Information */
1128 QSI_DEF(SystemModuleInformation
)
1132 /* Acquire system module list lock */
1133 KeEnterCriticalRegion();
1134 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource
, TRUE
);
1136 /* Call the generic handler with the system module list */
1137 Status
= ExpQueryModuleInformation(&PsLoadedModuleList
,
1138 &MmLoadedUserImageList
,
1139 (PRTL_PROCESS_MODULES
)Buffer
,
1143 /* Release list lock and return status */
1144 ExReleaseResourceLite(&PsLoadedModuleResource
);
1145 KeLeaveCriticalRegion();
1149 /* Class 12 - Locks Information */
1150 QSI_DEF(SystemLocksInformation
)
1153 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1154 return STATUS_NOT_IMPLEMENTED
;
1157 /* Class 13 - Stack Trace Information */
1158 QSI_DEF(SystemStackTraceInformation
)
1161 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1162 return STATUS_NOT_IMPLEMENTED
;
1165 /* Class 14 - Paged Pool Information */
1166 QSI_DEF(SystemPagedPoolInformation
)
1169 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1170 return STATUS_NOT_IMPLEMENTED
;
1173 /* Class 15 - Non Paged Pool Information */
1174 QSI_DEF(SystemNonPagedPoolInformation
)
1177 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1178 return STATUS_NOT_IMPLEMENTED
;
1182 /* Class 16 - Handle Information */
1183 QSI_DEF(SystemHandleInformation
)
1185 PSYSTEM_HANDLE_INFORMATION HandleInformation
;
1186 PLIST_ENTRY NextTableEntry
;
1187 PHANDLE_TABLE HandleTable
;
1188 PHANDLE_TABLE_ENTRY HandleTableEntry
;
1195 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1197 /* Set initial required buffer size */
1198 *ReqSize
= FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION
, Handles
);
1200 /* Check user's buffer size */
1201 if (Size
< *ReqSize
)
1203 return STATUS_INFO_LENGTH_MISMATCH
;
1206 /* We need to lock down the memory */
1207 Status
= ExLockUserBuffer(Buffer
,
1209 ExGetPreviousMode(),
1211 (PVOID
*)&HandleInformation
,
1213 if (!NT_SUCCESS(Status
))
1215 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status
);
1219 /* Reset of count of handles */
1220 HandleInformation
->NumberOfHandles
= 0;
1222 /* Enter a critical region */
1223 KeEnterCriticalRegion();
1225 /* Acquire the handle table lock */
1226 ExAcquirePushLockShared(&HandleTableListLock
);
1228 /* Enumerate all system handles */
1229 for (NextTableEntry
= HandleTableListHead
.Flink
;
1230 NextTableEntry
!= &HandleTableListHead
;
1231 NextTableEntry
= NextTableEntry
->Flink
)
1233 /* Get current handle table */
1234 HandleTable
= CONTAINING_RECORD(NextTableEntry
, HANDLE_TABLE
, HandleTableList
);
1236 /* Set the initial value and loop the entries */
1238 while ((HandleTableEntry
= ExpLookupHandleTableEntry(HandleTable
, Handle
)))
1240 /* Validate the entry */
1241 if ((HandleTableEntry
->Object
) &&
1242 (HandleTableEntry
->NextFreeTableEntry
!= -2))
1244 /* Increase of count of handles */
1245 ++HandleInformation
->NumberOfHandles
;
1247 /* Lock the entry */
1248 if (ExpLockHandleTableEntry(HandleTable
, HandleTableEntry
))
1250 /* Increase required buffer size */
1251 *ReqSize
+= sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
);
1253 /* Check user's buffer size */
1254 if (*ReqSize
> Size
)
1256 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1260 POBJECT_HEADER ObjectHeader
= ObpGetHandleObject(HandleTableEntry
);
1262 /* Filling handle information */
1263 HandleInformation
->Handles
[Index
].UniqueProcessId
=
1264 (USHORT
)(ULONG_PTR
) HandleTable
->UniqueProcessId
;
1266 HandleInformation
->Handles
[Index
].CreatorBackTraceIndex
= 0;
1268 #if 0 /* FIXME!!! Type field currupted */
1269 HandleInformation
->Handles
[Index
].ObjectTypeIndex
=
1270 (UCHAR
) ObjectHeader
->Type
->Index
;
1272 HandleInformation
->Handles
[Index
].ObjectTypeIndex
= 0;
1275 HandleInformation
->Handles
[Index
].HandleAttributes
=
1276 HandleTableEntry
->ObAttributes
& OBJ_HANDLE_ATTRIBUTES
;
1278 HandleInformation
->Handles
[Index
].HandleValue
=
1279 (USHORT
)(ULONG_PTR
) Handle
.GenericHandleOverlay
;
1281 HandleInformation
->Handles
[Index
].Object
= &ObjectHeader
->Body
;
1283 HandleInformation
->Handles
[Index
].GrantedAccess
=
1284 HandleTableEntry
->GrantedAccess
;
1290 ExUnlockHandleTableEntry(HandleTable
, HandleTableEntry
);
1294 /* Go to the next entry */
1295 Handle
.Value
+= sizeof(HANDLE
);
1299 /* Release the lock */
1300 ExReleasePushLockShared(&HandleTableListLock
);
1302 /* Leave the critical region */
1303 KeLeaveCriticalRegion();
1305 /* Release the locked user buffer */
1306 ExUnlockUserBuffer(Mdl
);
1311 /* Class 17 - Information */
1312 QSI_DEF(SystemObjectInformation
)
1315 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1316 return STATUS_NOT_IMPLEMENTED
;
1319 /* Class 18 - Information */
1320 QSI_DEF(SystemPageFileInformation
)
1322 UNICODE_STRING FileName
; /* FIXME */
1323 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1325 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1327 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1328 return STATUS_INFO_LENGTH_MISMATCH
;
1331 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1334 Spfi
->NextEntryOffset
= 0;
1336 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1337 Spfi
->TotalInUse
= MiUsedSwapPages
;
1338 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1339 Spfi
->PageFileName
= FileName
;
1340 return STATUS_SUCCESS
;
1343 /* Class 19 - Vdm Instemul Information */
1344 QSI_DEF(SystemVdmInstemulInformation
)
1347 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1348 return STATUS_NOT_IMPLEMENTED
;
1351 /* Class 20 - Vdm Bop Information */
1352 QSI_DEF(SystemVdmBopInformation
)
1355 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1356 return STATUS_NOT_IMPLEMENTED
;
1359 /* Class 21 - File Cache Information */
1360 QSI_DEF(SystemFileCacheInformation
)
1362 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1364 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1366 if (Size
< *ReqSize
)
1368 return STATUS_INFO_LENGTH_MISMATCH
;
1371 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1373 /* Return the Byte size not the page size. */
1375 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1377 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1378 /* Taskmgr multiplies this one by page size right away */
1379 Sci
->CurrentSizeIncludingTransitionInPages
=
1380 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1381 /* system working set and standby pages. */
1382 Sci
->PageFaultCount
= 0; /* FIXME */
1383 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1384 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1386 return STATUS_SUCCESS
;
1389 SSI_DEF(SystemFileCacheInformation
)
1391 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1393 return STATUS_INFO_LENGTH_MISMATCH
;
1396 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1397 return STATUS_NOT_IMPLEMENTED
;
1400 /* Class 22 - Pool Tag Information */
1401 QSI_DEF(SystemPoolTagInformation
)
1403 if (Size
< sizeof(SYSTEM_POOLTAG_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
1404 return ExGetPoolTagInfo(Buffer
, Size
, ReqSize
);
1407 /* Class 23 - Interrupt Information for all processors */
1408 QSI_DEF(SystemInterruptInformation
)
1413 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1415 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1417 return STATUS_INFO_LENGTH_MISMATCH
;
1420 ti
= KeQueryTimeIncrement();
1422 for (i
= 0; i
< KeNumberProcessors
; i
++)
1424 Prcb
= KiProcessorBlock
[i
];
1425 sii
->ContextSwitches
= KeGetContextSwitches(Prcb
);
1426 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1427 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1428 sii
->TimeIncrement
= ti
;
1429 sii
->DpcBypassCount
= 0;
1430 sii
->ApcBypassCount
= 0;
1434 return STATUS_SUCCESS
;
1437 /* Class 24 - DPC Behaviour Information */
1438 QSI_DEF(SystemDpcBehaviourInformation
)
1441 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1442 return STATUS_NOT_IMPLEMENTED
;
1445 SSI_DEF(SystemDpcBehaviourInformation
)
1448 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1449 return STATUS_NOT_IMPLEMENTED
;
1452 /* Class 25 - Full Memory Information */
1453 QSI_DEF(SystemFullMemoryInformation
)
1455 PULONG Spi
= (PULONG
) Buffer
;
1457 PEPROCESS TheIdleProcess
;
1459 *ReqSize
= sizeof(ULONG
);
1461 if (sizeof(ULONG
) != Size
)
1463 return STATUS_INFO_LENGTH_MISMATCH
;
1466 DPRINT("SystemFullMemoryInformation\n");
1468 TheIdleProcess
= PsIdleProcess
;
1470 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
1471 TheIdleProcess
->UniqueProcessId
,
1472 TheIdleProcess
->Pcb
.KernelTime
,
1476 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1478 return STATUS_SUCCESS
;
1481 /* Class 26 - Load Image */
1482 SSI_DEF(SystemLoadGdiDriverInformation
)
1484 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1485 UNICODE_STRING ImageName
;
1487 PVOID SectionPointer
;
1488 ULONG_PTR EntryPoint
;
1491 PIMAGE_NT_HEADERS NtHeader
;
1494 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1496 /* Incorrect buffer length, fail */
1497 return STATUS_INFO_LENGTH_MISMATCH
;
1500 /* Only kernel mode can call this function */
1501 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1503 /* Load the driver */
1504 ImageName
= DriverInfo
->DriverName
;
1505 Status
= MmLoadSystemImage(&ImageName
,
1511 if (!NT_SUCCESS(Status
)) return Status
;
1513 /* Return the export pointer */
1514 DriverInfo
->ExportSectionPointer
=
1515 RtlImageDirectoryEntryToData(ImageBase
,
1517 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1520 /* Get the entrypoint */
1521 NtHeader
= RtlImageNtHeader(ImageBase
);
1522 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1523 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1525 /* Save other data */
1526 DriverInfo
->ImageAddress
= ImageBase
;
1527 DriverInfo
->SectionPointer
= SectionPointer
;
1528 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1529 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1532 return STATUS_SUCCESS
;
1535 /* Class 27 - Unload Image */
1536 SSI_DEF(SystemUnloadGdiDriverInformation
)
1538 PVOID
*SectionPointer
= Buffer
;
1541 if (Size
!= sizeof(PVOID
))
1543 /* Incorrect length, fail */
1544 return STATUS_INFO_LENGTH_MISMATCH
;
1547 /* Only kernel mode can call this function */
1548 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1550 /* Unload the image */
1551 MmUnloadSystemImage(*SectionPointer
);
1552 return STATUS_SUCCESS
;
1555 /* Class 28 - Time Adjustment Information */
1556 QSI_DEF(SystemTimeAdjustmentInformation
)
1558 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1559 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1561 /* Check if enough storage was provided */
1562 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1564 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1565 return STATUS_INFO_LENGTH_MISMATCH
;
1568 /* Give time values to our caller */
1569 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1570 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1571 TimeInfo
->Enable
= !KiTimeAdjustmentEnabled
;
1573 return STATUS_SUCCESS
;
1576 SSI_DEF(SystemTimeAdjustmentInformation
)
1578 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1579 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
=
1580 (PSYSTEM_SET_TIME_ADJUST_INFORMATION
)Buffer
;
1582 /* Check size of a buffer, it must match our expectations */
1583 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1584 return STATUS_INFO_LENGTH_MISMATCH
;
1586 /* Check who is calling */
1587 if (PreviousMode
!= KernelMode
)
1589 /* Check access rights */
1590 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1592 return STATUS_PRIVILEGE_NOT_HELD
;
1596 /* FIXME: behaviour suggests the member be named 'Disable' */
1597 if (TimeInfo
->Enable
)
1599 /* Disable time adjustment and set default value */
1600 KiTimeAdjustmentEnabled
= FALSE
;
1601 KeTimeAdjustment
= KeMaximumIncrement
;
1605 /* Check if a valid time adjustment value is given */
1606 if (TimeInfo
->TimeAdjustment
== 0) return STATUS_INVALID_PARAMETER_2
;
1608 /* Enable time adjustment and set the adjustment value */
1609 KiTimeAdjustmentEnabled
= TRUE
;
1610 KeTimeAdjustment
= TimeInfo
->TimeAdjustment
;
1613 return STATUS_SUCCESS
;
1616 /* Class 29 - Summary Memory Information */
1617 QSI_DEF(SystemSummaryMemoryInformation
)
1620 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1621 return STATUS_NOT_IMPLEMENTED
;
1624 /* Class 30 - Next Event Id Information */
1625 QSI_DEF(SystemNextEventIdInformation
)
1628 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1629 return STATUS_NOT_IMPLEMENTED
;
1633 QSI_DEF(SystemPerformanceTraceInformation
)
1636 DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n");
1637 return STATUS_NOT_IMPLEMENTED
;
1640 /* Class 32 - Crash Dump Information */
1641 QSI_DEF(SystemCrashDumpInformation
)
1644 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1645 return STATUS_NOT_IMPLEMENTED
;
1648 /* Class 33 - Exception Information */
1649 QSI_DEF(SystemExceptionInformation
)
1651 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation
=
1652 (PSYSTEM_EXCEPTION_INFORMATION
)Buffer
;
1654 ULONG AlignmentFixupCount
= 0, ExceptionDispatchCount
= 0;
1655 ULONG FloatingEmulationCount
= 0, ByteWordEmulationCount
= 0;
1658 /* Check size of a buffer, it must match our expectations */
1659 if (sizeof(SYSTEM_EXCEPTION_INFORMATION
) != Size
)
1660 return STATUS_INFO_LENGTH_MISMATCH
;
1662 /* Sum up exception count information from all processors */
1663 for (i
= 0; i
< KeNumberProcessors
; i
++)
1665 Prcb
= KiProcessorBlock
[i
];
1668 AlignmentFixupCount
+= Prcb
->KeAlignmentFixupCount
;
1669 ExceptionDispatchCount
+= Prcb
->KeExceptionDispatchCount
;
1671 FloatingEmulationCount
+= Prcb
->KeFloatingEmulationCount
;
1676 /* Save information in user's buffer */
1677 ExceptionInformation
->AlignmentFixupCount
= AlignmentFixupCount
;
1678 ExceptionInformation
->ExceptionDispatchCount
= ExceptionDispatchCount
;
1679 ExceptionInformation
->FloatingEmulationCount
= FloatingEmulationCount
;
1680 ExceptionInformation
->ByteWordEmulationCount
= ByteWordEmulationCount
;
1682 return STATUS_SUCCESS
;
1685 /* Class 34 - Crash Dump State Information */
1686 QSI_DEF(SystemCrashDumpStateInformation
)
1689 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1690 return STATUS_NOT_IMPLEMENTED
;
1693 /* Class 35 - Kernel Debugger Information */
1694 QSI_DEF(SystemKernelDebuggerInformation
)
1696 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1698 #if (NTDDI_VERSION >= NTDDI_VISTA)
1699 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1702 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1704 return STATUS_INFO_LENGTH_MISMATCH
;
1707 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1708 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1710 #if (NTDDI_VERSION < NTDDI_VISTA)
1711 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1714 return STATUS_SUCCESS
;
1717 /* Class 36 - Context Switch Information */
1718 QSI_DEF(SystemContextSwitchInformation
)
1720 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation
=
1721 (PSYSTEM_CONTEXT_SWITCH_INFORMATION
)Buffer
;
1722 ULONG ContextSwitches
;
1726 /* Check size of a buffer, it must match our expectations */
1727 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION
) != Size
)
1728 return STATUS_INFO_LENGTH_MISMATCH
;
1730 /* Calculate total value of context switches across all processors */
1731 ContextSwitches
= 0;
1732 for (i
= 0; i
< KeNumberProcessors
; i
++)
1734 Prcb
= KiProcessorBlock
[i
];
1737 ContextSwitches
+= KeGetContextSwitches(Prcb
);
1741 ContextSwitchInformation
->ContextSwitches
= ContextSwitches
;
1744 ContextSwitchInformation
->FindAny
= 0;
1745 ContextSwitchInformation
->FindLast
= 0;
1746 ContextSwitchInformation
->FindIdeal
= 0;
1747 ContextSwitchInformation
->IdleAny
= 0;
1748 ContextSwitchInformation
->IdleCurrent
= 0;
1749 ContextSwitchInformation
->IdleLast
= 0;
1750 ContextSwitchInformation
->IdleIdeal
= 0;
1751 ContextSwitchInformation
->PreemptAny
= 0;
1752 ContextSwitchInformation
->PreemptCurrent
= 0;
1753 ContextSwitchInformation
->PreemptLast
= 0;
1754 ContextSwitchInformation
->SwitchToIdle
= 0;
1756 return STATUS_SUCCESS
;
1759 /* Class 37 - Registry Quota Information */
1760 QSI_DEF(SystemRegistryQuotaInformation
)
1762 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1764 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1765 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1767 return STATUS_INFO_LENGTH_MISMATCH
;
1770 DPRINT1("Faking max registry size of 32 MB\n");
1771 srqi
->RegistryQuotaAllowed
= 0x2000000;
1772 srqi
->RegistryQuotaUsed
= 0x200000;
1773 srqi
->PagedPoolSize
= 0x200000;
1775 return STATUS_SUCCESS
;
1778 SSI_DEF(SystemRegistryQuotaInformation
)
1781 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1782 return STATUS_NOT_IMPLEMENTED
;
1785 /* Class 38 - Load And Call Image */
1786 SSI_DEF(SystemExtendServiceTableInformation
)
1788 UNICODE_STRING ImageName
;
1789 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1790 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1792 PIMAGE_NT_HEADERS NtHeader
;
1793 DRIVER_OBJECT Win32k
;
1794 PDRIVER_INITIALIZE DriverInit
;
1796 ULONG_PTR EntryPoint
;
1798 /* Validate the size */
1799 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1801 /* Check who is calling */
1802 if (PreviousMode
!= KernelMode
)
1804 static const UNICODE_STRING Win32kName
=
1805 RTL_CONSTANT_STRING(L
"\\SystemRoot\\System32\\win32k.sys");
1807 /* Make sure we can load drivers */
1808 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1810 /* FIXME: We can't, fail */
1811 return STATUS_PRIVILEGE_NOT_HELD
;
1816 /* Probe and copy the unicode string */
1817 ProbeForRead(Buffer
, sizeof(ImageName
), 1);
1818 ImageName
= *(PUNICODE_STRING
)Buffer
;
1820 /* Probe the string buffer */
1821 ProbeForRead(ImageName
.Buffer
, ImageName
.Length
, sizeof(WCHAR
));
1823 /* Check if we have the correct name (nothing else is allowed!) */
1824 if (!RtlEqualUnicodeString(&ImageName
, &Win32kName
, FALSE
))
1826 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD
);
1829 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1831 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1835 /* Recursively call the function, so that we are from kernel mode */
1836 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1838 sizeof(Win32kName
));
1841 /* Load the image */
1842 Status
= MmLoadSystemImage((PUNICODE_STRING
)Buffer
,
1846 (PVOID
)&ModuleObject
,
1849 if (!NT_SUCCESS(Status
)) return Status
;
1851 /* Get the headers */
1852 NtHeader
= RtlImageNtHeader(ImageBase
);
1856 MmUnloadSystemImage(ModuleObject
);
1857 return STATUS_INVALID_IMAGE_FORMAT
;
1860 /* Get the entrypoint */
1861 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1862 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1863 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1865 /* Create a dummy device */
1866 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1867 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1868 Win32k
.DriverStart
= ImageBase
;
1871 Status
= (DriverInit
)(&Win32k
, NULL
);
1872 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1874 /* Unload if we failed */
1875 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1879 /* Class 39 - Priority Separation */
1880 SSI_DEF(SystemPrioritySeperation
)
1882 /* Check if the size is correct */
1883 if (Size
!= sizeof(ULONG
))
1885 return STATUS_INFO_LENGTH_MISMATCH
;
1888 /* We need the TCB privilege */
1889 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, ExGetPreviousMode()))
1891 return STATUS_PRIVILEGE_NOT_HELD
;
1894 /* Modify the quantum table */
1895 PsChangeQuantumTable(TRUE
, *(PULONG
)Buffer
);
1897 return STATUS_SUCCESS
;
1901 QSI_DEF(SystemVerifierAddDriverInformation
)
1904 DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n");
1905 return STATUS_NOT_IMPLEMENTED
;
1909 QSI_DEF(SystemVerifierRemoveDriverInformation
)
1912 DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n");
1913 return STATUS_NOT_IMPLEMENTED
;
1916 /* Class 42 - Power Information */
1917 QSI_DEF(SystemProcessorIdleInformation
)
1919 *ReqSize
= sizeof(PROCESSOR_POWER_INFORMATION
) * KeNumberProcessors
;
1921 if (sizeof(PROCESSOR_POWER_INFORMATION
) * KeNumberProcessors
> Size
)
1923 return STATUS_INFO_LENGTH_MISMATCH
;
1927 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1928 return STATUS_NOT_IMPLEMENTED
;
1932 QSI_DEF(SystemLegacyDriverInformation
)
1935 DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n");
1936 return STATUS_NOT_IMPLEMENTED
;
1939 /* Class 44 - Current Time Zone Information */
1940 QSI_DEF(SystemCurrentTimeZoneInformation
)
1942 *ReqSize
= sizeof(TIME_ZONE_INFORMATION
);
1944 if (sizeof(TIME_ZONE_INFORMATION
) != Size
)
1946 return STATUS_INFO_LENGTH_MISMATCH
;
1949 /* Copy the time zone information struct */
1952 sizeof(TIME_ZONE_INFORMATION
));
1954 return STATUS_SUCCESS
;
1958 SSI_DEF(SystemCurrentTimeZoneInformation
)
1960 /* Check user buffer's size */
1961 if (Size
< sizeof(TIME_ZONE_INFORMATION
))
1963 return STATUS_INFO_LENGTH_MISMATCH
;
1966 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1971 ExpCopyLookasideInformation(
1972 PSYSTEM_LOOKASIDE_INFORMATION
*InfoPointer
,
1973 PULONG RemainingPointer
,
1974 PLIST_ENTRY ListHead
,
1975 BOOLEAN ListUsesMisses
)
1978 PSYSTEM_LOOKASIDE_INFORMATION Info
;
1979 PGENERAL_LOOKASIDE LookasideList
;
1980 PLIST_ENTRY ListEntry
;
1983 /* Get info pointer and remaining count of free array element */
1984 Info
= *InfoPointer
;
1985 Remaining
= *RemainingPointer
;
1987 /* Loop as long as we have lookaside lists and free array elements */
1988 for (ListEntry
= ListHead
->Flink
;
1989 (ListEntry
!= ListHead
) && (Remaining
> 0);
1990 ListEntry
= ListEntry
->Flink
, Remaining
--)
1992 LookasideList
= CONTAINING_RECORD(ListEntry
, GENERAL_LOOKASIDE
, ListEntry
);
1994 /* Fill the next array element */
1995 Info
->CurrentDepth
= LookasideList
->Depth
;
1996 Info
->MaximumDepth
= LookasideList
->MaximumDepth
;
1997 Info
->TotalAllocates
= LookasideList
->TotalAllocates
;
1998 Info
->TotalFrees
= LookasideList
->TotalFrees
;
1999 Info
->Type
= LookasideList
->Type
;
2000 Info
->Tag
= LookasideList
->Tag
;
2001 Info
->Size
= LookasideList
->Size
;
2003 /* Check how the lists track misses/hits */
2007 Info
->AllocateMisses
= LookasideList
->AllocateMisses
;
2008 Info
->FreeMisses
= LookasideList
->FreeMisses
;
2012 /* Calculate misses */
2013 Info
->AllocateMisses
= LookasideList
->TotalAllocates
2014 - LookasideList
->AllocateHits
;
2015 Info
->FreeMisses
= LookasideList
->TotalFrees
2016 - LookasideList
->FreeHits
;
2020 /* Return the updated pointer and remaining count */
2021 *InfoPointer
= Info
;
2022 *RemainingPointer
= Remaining
;
2025 /* Class 45 - Lookaside Information */
2026 QSI_DEF(SystemLookasideInformation
)
2028 KPROCESSOR_MODE PreviousMode
;
2029 PSYSTEM_LOOKASIDE_INFORMATION Info
;
2031 ULONG MaxCount
, Remaining
;
2035 /* First we need to lock down the memory, since we are going to access it
2037 PreviousMode
= ExGetPreviousMode();
2038 Status
= ExLockUserBuffer(Buffer
,
2044 if (!NT_SUCCESS(Status
))
2046 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status
);
2050 /* Calculate how many items we can store */
2051 Remaining
= MaxCount
= Size
/ sizeof(SYSTEM_LOOKASIDE_INFORMATION
);
2057 /* Copy info from pool lookaside lists */
2058 ExpCopyLookasideInformation(&Info
,
2060 &ExPoolLookasideListHead
,
2067 /* Copy info from system lookaside lists */
2068 ExpCopyLookasideInformation(&Info
,
2070 &ExSystemLookasideListHead
,
2077 /* Acquire spinlock for ExpNonPagedLookasideListHead */
2078 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
2080 /* Copy info from non-paged lookaside lists */
2081 ExpCopyLookasideInformation(&Info
,
2083 &ExpNonPagedLookasideListHead
,
2086 /* Release spinlock for ExpNonPagedLookasideListHead */
2087 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
2094 /* Acquire spinlock for ExpPagedLookasideListHead */
2095 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
2097 /* Copy info from paged lookaside lists */
2098 ExpCopyLookasideInformation(&Info
,
2100 &ExpPagedLookasideListHead
,
2103 /* Release spinlock for ExpPagedLookasideListHead */
2104 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
2108 /* Release the locked user buffer */
2109 ExUnlockUserBuffer(Mdl
);
2111 /* Return the size of the actually written data */
2112 *ReqSize
= (MaxCount
- Remaining
) * sizeof(SYSTEM_LOOKASIDE_INFORMATION
);
2113 return STATUS_SUCCESS
;
2117 /* Class 46 - Set time slip event */
2118 SSI_DEF(SystemTimeSlipNotification
)
2121 DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n");
2122 return STATUS_NOT_IMPLEMENTED
;
2127 MmSessionCreate(OUT PULONG SessionId
);
2131 MmSessionDelete(IN ULONG SessionId
);
2133 /* Class 47 - Create a new session (TSE) */
2134 SSI_DEF(SystemSessionCreate
)
2137 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2140 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
2142 if (PreviousMode
!= KernelMode
)
2144 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
2146 return STATUS_PRIVILEGE_NOT_HELD
;
2149 ProbeForWriteUlong(Buffer
);
2152 Status
= MmSessionCreate(&SessionId
);
2153 if (NT_SUCCESS(Status
)) *(PULONG
)Buffer
= SessionId
;
2159 /* Class 48 - Delete an existing session (TSE) */
2160 SSI_DEF(SystemSessionDetach
)
2163 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2165 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
2167 if (PreviousMode
!= KernelMode
)
2169 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
2171 return STATUS_PRIVILEGE_NOT_HELD
;
2175 SessionId
= *(PULONG
)Buffer
;
2177 return MmSessionDelete(SessionId
);
2181 /* Class 49 - UNKNOWN */
2182 QSI_DEF(SystemSessionInformation
)
2185 DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n");
2186 return STATUS_NOT_IMPLEMENTED
;
2190 /* Class 50 - System range start address */
2191 QSI_DEF(SystemRangeStartInformation
)
2193 /* Check user buffer's size */
2194 if (Size
!= sizeof(ULONG_PTR
)) return STATUS_INFO_LENGTH_MISMATCH
;
2196 *(PULONG_PTR
)Buffer
= (ULONG_PTR
)MmSystemRangeStart
;
2198 if (ReqSize
) *ReqSize
= sizeof(ULONG_PTR
);
2200 return STATUS_SUCCESS
;
2203 /* Class 51 - Driver verifier information */
2204 QSI_DEF(SystemVerifierInformation
)
2207 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
2208 return STATUS_NOT_IMPLEMENTED
;
2212 SSI_DEF(SystemVerifierInformation
)
2215 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
2216 return STATUS_NOT_IMPLEMENTED
;
2221 SSI_DEF(SystemVerifierThunkExtend
)
2224 DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n");
2225 return STATUS_NOT_IMPLEMENTED
;
2229 /* Class 53 - A session's processes */
2230 QSI_DEF(SystemSessionProcessesInformation
)
2233 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
2234 return STATUS_NOT_IMPLEMENTED
;
2238 /* Class 54 - Load & map in system space */
2239 SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation
)
2242 DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n");
2243 return STATUS_NOT_IMPLEMENTED
;
2247 /* Class 55 - NUMA processor information */
2248 QSI_DEF(SystemNumaProcessorMap
)
2250 ULONG MaxEntries
, Node
;
2251 PSYSTEM_NUMA_INFORMATION NumaInformation
= (PSYSTEM_NUMA_INFORMATION
)Buffer
;
2253 /* Validate input size */
2254 if (Size
< sizeof(ULONG
))
2256 return STATUS_INFO_LENGTH_MISMATCH
;
2259 /* Return highest node */
2260 NumaInformation
->HighestNodeNumber
= KeNumberNodes
- 1;
2262 /* Compute how much entries we will be able to put in output structure */
2263 MaxEntries
= (Size
- FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
)) / sizeof(ULONGLONG
);
2264 /* Make sure we don't overflow KeNodeBlock */
2265 if (MaxEntries
> KeNumberNodes
)
2267 MaxEntries
= KeNumberNodes
;
2270 /* If we have entries to write, and room for it */
2271 if (Size
>= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
) &&
2274 /* Already set size we return */
2275 *ReqSize
= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
) +
2276 MaxEntries
* sizeof(ULONGLONG
);
2278 /* For each node, return processor mask */
2279 for (Node
= 0; Node
< MaxEntries
; ++Node
)
2281 NumaInformation
->ActiveProcessorsAffinityMask
[Node
] = KeNodeBlock
[Node
]->ProcessorMask
;
2286 /* We only returned highest node number */
2287 *ReqSize
= sizeof(ULONG
);
2290 return STATUS_SUCCESS
;
2294 /* Class 56 - Prefetcher information */
2295 QSI_DEF(SystemPrefetcherInformation
)
2298 DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n");
2299 return STATUS_NOT_IMPLEMENTED
;
2303 /* Class 57 - Extended process information */
2304 QSI_DEF(SystemExtendedProcessInformation
)
2307 DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n");
2308 return STATUS_NOT_IMPLEMENTED
;
2312 /* Class 58 - Recommended shared ata alignment */
2313 QSI_DEF(SystemRecommendedSharedDataAlignment
)
2316 DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n");
2317 return STATUS_NOT_IMPLEMENTED
;
2321 /* Class 60 - NUMA memory information */
2322 QSI_DEF(SystemNumaAvailableMemory
)
2324 ULONG MaxEntries
, Node
;
2325 PSYSTEM_NUMA_INFORMATION NumaInformation
= (PSYSTEM_NUMA_INFORMATION
)Buffer
;
2327 /* Validate input size */
2328 if (Size
< sizeof(ULONG
))
2330 return STATUS_INFO_LENGTH_MISMATCH
;
2333 /* Return highest node */
2334 NumaInformation
->HighestNodeNumber
= KeNumberNodes
- 1;
2336 /* Compute how much entries we will be able to put in output structure */
2337 MaxEntries
= (Size
- FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
)) / sizeof(ULONGLONG
);
2338 /* Make sure we don't overflow KeNodeBlock */
2339 if (MaxEntries
> KeNumberNodes
)
2341 MaxEntries
= KeNumberNodes
;
2344 /* If we have entries to write, and room for it */
2345 if (Size
>= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
) &&
2348 /* Already set size we return */
2349 *ReqSize
= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
) +
2350 MaxEntries
* sizeof(ULONGLONG
);
2352 /* If we have a single entry (us), directly return MM information */
2353 if (MaxEntries
== 1)
2355 NumaInformation
->AvailableMemory
[0] = MmAvailablePages
<< PAGE_SHIFT
;
2359 /* Otherwise, for each node, return available bytes */
2360 for (Node
= 0; Node
< MaxEntries
; ++Node
)
2362 NumaInformation
->AvailableMemory
[Node
] = (KeNodeBlock
[Node
]->FreeCount
[0] + KeNodeBlock
[Node
]->FreeCount
[1]) << PAGE_SHIFT
;
2368 /* We only returned highest node number */
2369 *ReqSize
= sizeof(ULONG
);
2372 return STATUS_SUCCESS
;
2376 /* Query/Set Calls Table */
2380 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
2381 NTSTATUS (* Set
) (PVOID
,ULONG
);
2387 // XX unknown behaviour
2389 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
2390 #define SI_QX(n) {QSI_USE(n),NULL}
2391 #define SI_XS(n) {NULL,SSI_USE(n)}
2392 #define SI_XX(n) {NULL,NULL}
2398 SI_QX(SystemBasicInformation
),
2399 SI_QX(SystemProcessorInformation
),
2400 SI_QX(SystemPerformanceInformation
),
2401 SI_QX(SystemTimeOfDayInformation
),
2402 SI_QX(SystemPathInformation
), /* should be SI_XX */
2403 SI_QX(SystemProcessInformation
),
2404 SI_QX(SystemCallCountInformation
),
2405 SI_QX(SystemDeviceInformation
),
2406 SI_QX(SystemProcessorPerformanceInformation
),
2407 SI_QS(SystemFlagsInformation
),
2408 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
2409 SI_QX(SystemModuleInformation
),
2410 SI_QX(SystemLocksInformation
),
2411 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
2412 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
2413 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
2414 SI_QX(SystemHandleInformation
),
2415 SI_QX(SystemObjectInformation
),
2416 SI_QX(SystemPageFileInformation
),
2417 SI_QX(SystemVdmInstemulInformation
),
2418 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
2419 SI_QS(SystemFileCacheInformation
),
2420 SI_QX(SystemPoolTagInformation
),
2421 SI_QX(SystemInterruptInformation
),
2422 SI_QS(SystemDpcBehaviourInformation
),
2423 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
2424 SI_XS(SystemLoadGdiDriverInformation
),
2425 SI_XS(SystemUnloadGdiDriverInformation
),
2426 SI_QS(SystemTimeAdjustmentInformation
),
2427 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
2428 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
2429 SI_QX(SystemPerformanceTraceInformation
), /* it should be SI_XX */
2430 SI_QX(SystemCrashDumpInformation
),
2431 SI_QX(SystemExceptionInformation
),
2432 SI_QX(SystemCrashDumpStateInformation
),
2433 SI_QX(SystemKernelDebuggerInformation
),
2434 SI_QX(SystemContextSwitchInformation
),
2435 SI_QS(SystemRegistryQuotaInformation
),
2436 SI_XS(SystemExtendServiceTableInformation
),
2437 SI_XS(SystemPrioritySeperation
),
2438 SI_QX(SystemVerifierAddDriverInformation
), /* it should be SI_XX */
2439 SI_QX(SystemVerifierRemoveDriverInformation
), /* it should be SI_XX */
2440 SI_QX(SystemProcessorIdleInformation
), /* it should be SI_XX */
2441 SI_QX(SystemLegacyDriverInformation
), /* it should be SI_XX */
2442 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
2443 SI_QX(SystemLookasideInformation
),
2444 SI_XS(SystemTimeSlipNotification
),
2445 SI_XS(SystemSessionCreate
),
2446 SI_XS(SystemSessionDetach
),
2447 SI_QX(SystemSessionInformation
), /* it should be SI_XX */
2448 SI_QX(SystemRangeStartInformation
),
2449 SI_QS(SystemVerifierInformation
),
2450 SI_XS(SystemVerifierThunkExtend
),
2451 SI_QX(SystemSessionProcessesInformation
),
2452 SI_XS(SystemLoadGdiDriverInSystemSpaceInformation
),
2453 SI_QX(SystemNumaProcessorMap
),
2454 SI_QX(SystemPrefetcherInformation
),
2455 SI_QX(SystemExtendedProcessInformation
),
2456 SI_QX(SystemRecommendedSharedDataAlignment
),
2457 SI_XX(SystemComPlusPackage
),
2458 SI_QX(SystemNumaAvailableMemory
)
2461 C_ASSERT(SystemBasicInformation
== 0);
2462 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
2463 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
2469 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2470 OUT PVOID SystemInformation
,
2472 OUT PULONG UnsafeResultLength
)
2474 KPROCESSOR_MODE PreviousMode
;
2475 ULONG ResultLength
= 0;
2476 ULONG Alignment
= TYPE_ALIGNMENT(ULONG
);
2477 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
2481 PreviousMode
= ExGetPreviousMode();
2485 #if (NTDDI_VERSION >= NTDDI_VISTA)
2487 * Check if the request is valid.
2489 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2491 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2495 if (PreviousMode
!= KernelMode
)
2497 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
2498 if (SystemInformationClass
== SystemKernelDebuggerInformation
)
2499 Alignment
= TYPE_ALIGNMENT(BOOLEAN
);
2501 ProbeForWrite(SystemInformation
, Length
, Alignment
);
2502 if (UnsafeResultLength
!= NULL
)
2503 ProbeForWriteUlong(UnsafeResultLength
);
2506 if (UnsafeResultLength
)
2507 *UnsafeResultLength
= 0;
2509 #if (NTDDI_VERSION < NTDDI_VISTA)
2511 * Check if the request is valid.
2513 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2515 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2519 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
2522 * Hand the request to a subhandler.
2524 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
2528 /* Save the result length to the caller */
2529 if (UnsafeResultLength
)
2530 *UnsafeResultLength
= ResultLength
;
2533 _SEH2_EXCEPT(ExSystemExceptionFilter())
2535 FStatus
= _SEH2_GetExceptionCode();
2545 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2546 IN PVOID SystemInformation
,
2547 IN ULONG SystemInformationLength
)
2549 NTSTATUS Status
= STATUS_INVALID_INFO_CLASS
;
2550 KPROCESSOR_MODE PreviousMode
;
2554 PreviousMode
= ExGetPreviousMode();
2559 * If called from user mode, check
2560 * possible unsafe arguments.
2562 if (PreviousMode
!= KernelMode
)
2564 ProbeForRead(SystemInformation
, SystemInformationLength
, sizeof(ULONG
));
2568 * Check the request is valid.
2570 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
2571 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
2573 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
2576 * Hand the request to a subhandler.
2578 Status
= CallQS
[SystemInformationClass
].Set(SystemInformation
,
2579 SystemInformationLength
);
2583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2585 Status
= _SEH2_GetExceptionCode();
2594 NtGetCurrentProcessorNumber(VOID
)
2597 return KeGetCurrentProcessorNumber();
2600 #undef ExGetPreviousMode
2603 ExGetPreviousMode(VOID
)
2606 return KeGetPreviousMode();