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 FAST_MUTEX ExpEnvironmentLock
;
21 ERESOURCE ExpFirmwareTableResource
;
22 LIST_ENTRY ExpFirmwareTableProviderListHead
;
26 ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount
,
27 IN PLDR_DATA_TABLE_ENTRY LdrEntry
,
28 OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
)
32 ANSI_STRING ModuleName
;
35 ModuleInfo
->MappedBase
= NULL
;
36 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
37 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
38 ModuleInfo
->Flags
= LdrEntry
->Flags
;
39 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
40 ModuleInfo
->LoadOrderIndex
= (USHORT
)ModuleCount
;
41 ModuleInfo
->InitOrderIndex
= 0;
44 RtlInitEmptyAnsiString(&ModuleName
,
45 ModuleInfo
->FullPathName
,
46 sizeof(ModuleInfo
->FullPathName
));
49 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
50 &LdrEntry
->FullDllName
,
52 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
54 /* Calculate offset to name */
55 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
56 while ((p
> ModuleName
.Buffer
) && (*--p
))
58 /* Check if we found the separator */
59 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
61 /* We did, break out */
68 ModuleInfo
->OffsetToFileName
= (USHORT
)(p
- ModuleName
.Buffer
);
72 /* Return empty name */
73 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
74 ModuleInfo
->OffsetToFileName
= 0;
82 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
83 IN PLIST_ENTRY UserModeList
,
84 OUT PRTL_PROCESS_MODULES Modules
,
86 OUT PULONG ReturnLength
)
88 NTSTATUS Status
= STATUS_SUCCESS
;
90 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
91 PLDR_DATA_TABLE_ENTRY LdrEntry
;
92 ULONG ModuleCount
= 0;
93 PLIST_ENTRY NextEntry
;
96 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
97 ModuleInfo
= &Modules
->Modules
[0];
99 /* Loop the kernel list */
100 NextEntry
= KernelModeList
->Flink
;
101 while (NextEntry
!= KernelModeList
)
104 LdrEntry
= CONTAINING_RECORD(NextEntry
,
105 LDR_DATA_TABLE_ENTRY
,
108 /* Update size and check if we can manage one more entry */
109 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
110 if (Length
>= RequiredLength
)
112 Status
= ExpConvertLdrModuleToRtlModule(ModuleCount
,
116 /* Go to the next module */
122 Status
= STATUS_INFO_LENGTH_MISMATCH
;
125 /* Update count and move to next entry */
127 NextEntry
= NextEntry
->Flink
;
130 /* Check if caller also wanted user modules */
133 NextEntry
= UserModeList
->Flink
;
134 while (NextEntry
!= UserModeList
)
137 LdrEntry
= CONTAINING_RECORD(NextEntry
,
138 LDR_DATA_TABLE_ENTRY
,
141 /* Update size and check if we can manage one more entry */
142 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
143 if (Length
>= RequiredLength
)
145 Status
= ExpConvertLdrModuleToRtlModule(ModuleCount
,
149 /* Go to the next module */
155 Status
= STATUS_INFO_LENGTH_MISMATCH
;
158 /* Update count and move to next entry */
160 NextEntry
= NextEntry
->Flink
;
164 /* Update return length */
165 if (ReturnLength
) *ReturnLength
= RequiredLength
;
167 /* Validate the length again */
168 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
170 /* Set the final count */
171 Modules
->NumberOfModules
= ModuleCount
;
175 /* Otherwise, we failed */
176 Status
= STATUS_INFO_LENGTH_MISMATCH
;
185 ExUnlockUserBuffer(PMDL Mdl
)
188 ExFreePoolWithTag(Mdl
, TAG_MDL
);
196 KPROCESSOR_MODE AccessMode
,
197 LOCK_OPERATION Operation
,
198 PVOID
*MappedSystemVa
,
204 *MappedSystemVa
= NULL
;
207 /* Allocate an MDL for the buffer */
208 Mdl
= IoAllocateMdl(BaseAddress
, Length
, FALSE
, TRUE
, NULL
);
211 return STATUS_INSUFFICIENT_RESOURCES
;
214 /* Enter SEH for probing */
217 MmProbeAndLockPages(Mdl
, AccessMode
, Operation
);
219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
221 ExFreePoolWithTag(Mdl
, TAG_MDL
);
222 return _SEH2_GetExceptionCode();
226 /* Return the safe kernel mode buffer */
227 *MappedSystemVa
= MmGetSystemAddressForMdlSafe(Mdl
, NormalPagePriority
);
228 if (*MappedSystemVa
== NULL
)
230 ExUnlockUserBuffer(Mdl
);
231 return STATUS_INSUFFICIENT_RESOURCES
;
236 return STATUS_SUCCESS
;
239 /* FUNCTIONS *****************************************************************/
246 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
250 ULONGLONG ScaledIdle
;
252 Prcb
= KeGetCurrentPrcb();
254 ScaledIdle
= (ULONGLONG
)Prcb
->IdleThread
->KernelTime
* 100;
255 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
257 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
267 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
269 PULONG ProcessorNumber
)
273 Prcb
= KeGetCurrentPrcb();
275 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
276 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
277 *ProcessorNumber
= KeGetCurrentProcessorNumber();
285 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
287 /* Quick check to see if it exists at all */
288 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
290 /* Return our support for it */
291 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
299 ExVerifySuite(SUITE_TYPE SuiteType
)
301 if (SuiteType
== Personal
) return TRUE
;
307 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
308 OUT PWSTR ValueBuffer
,
309 IN ULONG ValueBufferLength
,
310 IN OUT PULONG ReturnLength OPTIONAL
)
313 UNICODE_STRING WName
;
317 UNICODE_STRING WValue
;
318 KPROCESSOR_MODE PreviousMode
;
322 /* Check if the call came from user mode */
323 PreviousMode
= ExGetPreviousMode();
324 if (PreviousMode
!= KernelMode
)
328 /* Probe the input and output buffers */
329 ProbeForRead(VariableName
, sizeof(UNICODE_STRING
), sizeof(ULONG
));
330 ProbeForWrite(ValueBuffer
, ValueBufferLength
, sizeof(WCHAR
));
331 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
335 /* Return the exception code */
336 _SEH2_YIELD(return _SEH2_GetExceptionCode());
341 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
342 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
, PreviousMode
))
344 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
345 return STATUS_PRIVILEGE_NOT_HELD
;
348 /* Copy the name to kernel space if necessary */
349 Status
= ProbeAndCaptureUnicodeString(&WName
, PreviousMode
, VariableName
);
350 if (!NT_SUCCESS(Status
)) return Status
;
352 /* Convert the name to ANSI and release the captured UNICODE string */
353 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
354 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
355 if (!NT_SUCCESS(Status
)) return Status
;
357 /* Allocate a buffer for the ANSI environment variable */
358 AnsiValueBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_ENVVAL_SIZE
, 'rvnE');
359 if (AnsiValueBuffer
== NULL
)
361 RtlFreeAnsiString(&AName
);
362 return STATUS_INSUFFICIENT_RESOURCES
;
365 /* Get the environment variable and free the ANSI name */
366 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
369 RtlFreeAnsiString(&AName
);
371 /* Check if we had success */
372 if (Result
== ESUCCESS
)
374 /* Copy the result back to the caller. */
377 /* Initialize ANSI string from the result */
378 RtlInitAnsiString(&AValue
, AnsiValueBuffer
);
380 /* Initialize a UNICODE string from the callers buffer */
381 RtlInitEmptyUnicodeString(&WValue
, ValueBuffer
, (USHORT
)ValueBufferLength
);
383 /* Convert the result to UNICODE */
384 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, FALSE
);
386 if (ReturnLength
!= NULL
)
387 *ReturnLength
= WValue
.Length
;
389 _SEH2_EXCEPT(ExSystemExceptionFilter())
391 Status
= _SEH2_GetExceptionCode();
397 Status
= STATUS_UNSUCCESSFUL
;
400 /* Free the allocated ANSI value buffer */
401 ExFreePoolWithTag(AnsiValueBuffer
, 'rvnE');
409 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
410 IN PUNICODE_STRING Value
)
412 UNICODE_STRING CapturedName
, CapturedValue
;
413 ANSI_STRING AName
, AValue
;
414 KPROCESSOR_MODE PreviousMode
;
419 PreviousMode
= ExGetPreviousMode();
422 * Copy the strings to kernel space if necessary
424 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
427 if (NT_SUCCESS(Status
))
429 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
432 if (NT_SUCCESS(Status
))
435 * according to ntinternals the SeSystemEnvironmentName privilege is required!
437 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
441 * convert the strings to ANSI
443 Status
= RtlUnicodeStringToAnsiString(&AName
,
446 if (NT_SUCCESS(Status
))
448 Status
= RtlUnicodeStringToAnsiString(&AValue
,
451 if (NT_SUCCESS(Status
))
453 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
456 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
462 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
463 Status
= STATUS_PRIVILEGE_NOT_HELD
;
466 ReleaseCapturedUnicodeString(&CapturedValue
,
470 ReleaseCapturedUnicodeString(&CapturedName
,
479 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
481 IN ULONG BufferLength
)
484 return STATUS_NOT_IMPLEMENTED
;
489 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
490 IN LPGUID VendorGuid
,
492 IN OUT PULONG ReturnLength
,
493 IN OUT PULONG Attributes
)
496 return STATUS_NOT_IMPLEMENTED
;
501 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
502 IN LPGUID VendorGuid
)
505 return STATUS_NOT_IMPLEMENTED
;
508 /* --- Query/Set System Information --- */
511 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
512 * so the stack is popped only in one place on x86 platform.
514 #define QSI_USE(n) QSI##n
516 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
518 #define SSI_USE(n) SSI##n
520 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
524 ExQueryPoolUsage(OUT PULONG PagedPoolPages
,
525 OUT PULONG NonPagedPoolPages
,
526 OUT PULONG PagedPoolAllocs
,
527 OUT PULONG PagedPoolFrees
,
528 OUT PULONG PagedPoolLookasideHits
,
529 OUT PULONG NonPagedPoolAllocs
,
530 OUT PULONG NonPagedPoolFrees
,
531 OUT PULONG NonPagedPoolLookasideHits
);
533 /* Class 0 - Basic Information */
534 QSI_DEF(SystemBasicInformation
)
536 PSYSTEM_BASIC_INFORMATION Sbi
537 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
539 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
541 /* Check user buffer's size */
542 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
544 return STATUS_INFO_LENGTH_MISMATCH
;
547 RtlZeroMemory(Sbi
, Size
);
549 Sbi
->TimerResolution
= KeMaximumIncrement
;
550 Sbi
->PageSize
= PAGE_SIZE
;
551 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
552 Sbi
->LowestPhysicalPageNumber
= (ULONG
)MmLowestPhysicalPage
;
553 Sbi
->HighestPhysicalPageNumber
= (ULONG
)MmHighestPhysicalPage
;
554 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
555 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
556 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
557 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
558 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
560 return STATUS_SUCCESS
;
563 /* Class 1 - Processor Information */
564 QSI_DEF(SystemProcessorInformation
)
566 PSYSTEM_PROCESSOR_INFORMATION Spi
567 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
569 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
571 /* Check user buffer's size */
572 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
574 return STATUS_INFO_LENGTH_MISMATCH
;
576 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
577 Spi
->ProcessorLevel
= KeProcessorLevel
;
578 Spi
->ProcessorRevision
= KeProcessorRevision
;
580 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
582 DPRINT("Arch %u Level %u Rev 0x%x\n", Spi
->ProcessorArchitecture
,
583 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
585 return STATUS_SUCCESS
;
588 /* Class 2 - Performance Information */
589 QSI_DEF(SystemPerformanceInformation
)
591 ULONG IdleUser
, IdleKernel
;
592 PSYSTEM_PERFORMANCE_INFORMATION Spi
593 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
595 PEPROCESS TheIdleProcess
;
597 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
599 /* Check user buffer's size */
600 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
602 return STATUS_INFO_LENGTH_MISMATCH
;
605 TheIdleProcess
= PsIdleProcess
;
607 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
608 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
609 Spi
->IoReadTransferCount
= IoReadTransferCount
;
610 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
611 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
612 Spi
->IoReadOperationCount
= IoReadOperationCount
;
613 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
614 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
616 Spi
->AvailablePages
= (ULONG
)MmAvailablePages
;
618 * Add up all the used "Committed" memory + pagefile.
619 * Not sure this is right. 8^\
621 Spi
->CommittedPages
= MiMemoryConsumers
[MC_SYSTEM
].PagesUsed
+
622 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
623 MiMemoryConsumers
[MC_USER
].PagesUsed
+
626 * Add up the full system total + pagefile.
627 * All this make Taskmgr happy but not sure it is the right numbers.
628 * This too, fixes some of GlobalMemoryStatusEx numbers.
630 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
632 Spi
->PeakCommitment
= 0; /* FIXME */
633 Spi
->PageFaultCount
= 0; /* FIXME */
634 Spi
->CopyOnWriteCount
= 0; /* FIXME */
635 Spi
->TransitionCount
= 0; /* FIXME */
636 Spi
->CacheTransitionCount
= 0; /* FIXME */
637 Spi
->DemandZeroCount
= 0; /* FIXME */
638 Spi
->PageReadCount
= 0; /* FIXME */
639 Spi
->PageReadIoCount
= 0; /* FIXME */
640 Spi
->CacheReadCount
= 0; /* FIXME */
641 Spi
->CacheIoCount
= 0; /* FIXME */
642 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
643 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
644 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
645 Spi
->MappedWriteIoCount
= 0; /* FIXME */
647 Spi
->PagedPoolPages
= 0;
648 Spi
->NonPagedPoolPages
= 0;
649 Spi
->PagedPoolAllocs
= 0;
650 Spi
->PagedPoolFrees
= 0;
651 Spi
->PagedPoolLookasideHits
= 0;
652 Spi
->NonPagedPoolAllocs
= 0;
653 Spi
->NonPagedPoolFrees
= 0;
654 Spi
->NonPagedPoolLookasideHits
= 0;
655 ExQueryPoolUsage(&Spi
->PagedPoolPages
,
656 &Spi
->NonPagedPoolPages
,
657 &Spi
->PagedPoolAllocs
,
658 &Spi
->PagedPoolFrees
,
659 &Spi
->PagedPoolLookasideHits
,
660 &Spi
->NonPagedPoolAllocs
,
661 &Spi
->NonPagedPoolFrees
,
662 &Spi
->NonPagedPoolLookasideHits
);
663 Spi
->FreeSystemPtes
= 0; /* FIXME */
665 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
667 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
668 Spi
->Spare3Count
= 0; /* FIXME */
670 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
671 Spi
->ResidentPagedPoolPage
= 0; /* FIXME */
673 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
674 Spi
->CcFastReadNoWait
= 0; /* FIXME */
675 Spi
->CcFastReadWait
= 0; /* FIXME */
676 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
677 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
679 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
680 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
681 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
682 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
684 Spi
->CcMapDataNoWait
= 0; /* FIXME */
685 Spi
->CcMapDataWait
= 0; /* FIXME */
686 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
687 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
689 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
690 Spi
->CcPinReadNoWait
= 0; /* FIXME */
691 Spi
->CcPinReadWait
= 0; /* FIXME */
692 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
693 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
694 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
695 Spi
->CcCopyReadWait
= 0; /* FIXME */
696 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
697 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
699 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
700 Spi
->CcMdlReadWait
= 0; /* FIXME */
701 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
702 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
703 Spi
->CcReadAheadIos
= 0; /* FIXME */
704 Spi
->CcLazyWriteIos
= 0; /* FIXME */
705 Spi
->CcLazyWritePages
= 0; /* FIXME */
706 Spi
->CcDataFlushes
= 0; /* FIXME */
707 Spi
->CcDataPages
= 0; /* FIXME */
708 Spi
->ContextSwitches
= 0; /* FIXME */
709 Spi
->FirstLevelTbFills
= 0; /* FIXME */
710 Spi
->SecondLevelTbFills
= 0; /* FIXME */
711 Spi
->SystemCalls
= 0; /* FIXME */
713 return STATUS_SUCCESS
;
716 /* Class 3 - Time Of Day Information */
717 QSI_DEF(SystemTimeOfDayInformation
)
719 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
720 LARGE_INTEGER CurrentTime
;
722 /* Set amount of written information to 0 */
725 /* Check user buffer's size */
726 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
728 return STATUS_INFO_LENGTH_MISMATCH
;
731 /* Get current time */
732 KeQuerySystemTime(&CurrentTime
);
734 /* Zero local buffer */
735 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
737 /* Fill local time structure */
738 Sti
.BootTime
= KeBootTime
;
739 Sti
.CurrentTime
= CurrentTime
;
740 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
741 Sti
.TimeZoneId
= ExpTimeZoneId
;
744 /* Copy as much as requested by caller */
745 RtlCopyMemory(Buffer
, &Sti
, Size
);
747 /* Set amount of information we copied */
750 return STATUS_SUCCESS
;
753 /* Class 4 - Path Information */
754 QSI_DEF(SystemPathInformation
)
756 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
757 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
759 return STATUS_BREAKPOINT
;
762 /* Class 5 - Process Information */
763 QSI_DEF(SystemProcessInformation
)
765 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
766 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
767 PEPROCESS Process
= NULL
, SystemProcess
;
768 PETHREAD CurrentThread
;
769 ANSI_STRING ImageName
;
771 USHORT ImageNameMaximumLength
; // image name length in bytes
772 USHORT ImageNameLength
;
773 PLIST_ENTRY CurrentEntry
;
774 ULONG TotalSize
= 0, ThreadsCount
;
775 ULONG TotalUser
, TotalKernel
;
777 NTSTATUS Status
= STATUS_SUCCESS
;
778 PUNICODE_STRING TempProcessImageName
;
779 _SEH2_VOLATILE PUNICODE_STRING ProcessImageName
= NULL
;
781 BOOLEAN Overflow
= FALSE
;
785 /* scan the process list */
787 PSYSTEM_PROCESS_INFORMATION Spi
788 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
790 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
792 /* Check for overflow */
793 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
798 /* Zero user's buffer */
799 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
801 SystemProcess
= PsIdleProcess
;
802 Process
= SystemProcess
;
803 Current
= (PUCHAR
) Spi
;
807 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
809 if ((Process
->ProcessExiting
) &&
810 (Process
->Pcb
.Header
.SignalState
) &&
811 !(Process
->ActiveThreads
) &&
812 (IsListEmpty(&Process
->Pcb
.ThreadListHead
)))
814 DPRINT1("Process %p (%s:%p) is a zombie\n",
815 Process
, Process
->ImageFileName
, Process
->UniqueProcessId
);
817 ImageNameMaximumLength
= 0;
822 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
823 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
826 CurrentEntry
= CurrentEntry
->Flink
;
829 // size of the structure for every process
830 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
832 Status
= SeLocateProcessImageName(Process
, &TempProcessImageName
);
833 ProcessImageName
= TempProcessImageName
;
835 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
837 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
838 /* Loop the file name*/
839 while (szSrc
> ProcessImageName
->Buffer
)
841 /* Make sure this isn't a backslash */
842 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
849 ImageNameLength
+= sizeof(WCHAR
);
853 if (!ImageNameLength
&& Process
!= PsIdleProcess
)
855 ImageNameLength
= (USHORT
)strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
858 /* Round up the image name length as NT does */
859 if (ImageNameLength
> 0)
860 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
862 ImageNameMaximumLength
= 0;
864 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
866 /* Check for overflow */
867 if (TotalSize
> Size
)
872 /* Fill system information */
875 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginning of the next structure
876 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
877 SpiCurrent
->CreateTime
= Process
->CreateTime
;
878 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
879 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
880 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
882 /* Copy name to the end of the struct */
883 if(Process
!= PsIdleProcess
)
887 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
891 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
892 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
897 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
900 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
901 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
902 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
903 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
904 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
905 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
906 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
907 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
908 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
909 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
910 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
911 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
912 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
913 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
914 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
915 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
916 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
918 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
919 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
921 CurrentThread
= CONTAINING_RECORD(CurrentEntry
, ETHREAD
, Tcb
.ThreadListEntry
);
923 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
924 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
925 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
926 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
927 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
928 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
929 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
930 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
931 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
932 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
933 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
936 CurrentEntry
= CurrentEntry
->Flink
;
939 /* Query total user/kernel times of a process */
940 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
941 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
942 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
945 if (ProcessImageName
)
947 /* Release the memory allocated by SeLocateProcessImageName */
948 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
949 ProcessImageName
= NULL
;
952 /* Handle idle process entry */
954 if (Process
== PsIdleProcess
) Process
= NULL
;
956 Process
= PsGetNextProcess(Process
);
958 if ((Process
== SystemProcess
) || (Process
== NULL
))
961 SpiCurrent
->NextEntryOffset
= 0;
965 Current
+= CurrentSize
+ ImageNameMaximumLength
;
966 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
969 ObDereferenceObject(Process
);
970 Status
= STATUS_SUCCESS
;
972 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
975 ObDereferenceObject(Process
);
976 if (ProcessImageName
)
978 /* Release the memory allocated by SeLocateProcessImageName */
979 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
982 Status
= _SEH2_GetExceptionCode();
987 Status
= STATUS_INFO_LENGTH_MISMATCH
;
989 *ReqSize
= TotalSize
;
993 /* Class 6 - Call Count Information */
994 QSI_DEF(SystemCallCountInformation
)
997 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
998 return STATUS_NOT_IMPLEMENTED
;
1001 /* Class 7 - Device Information */
1002 QSI_DEF(SystemDeviceInformation
)
1004 PSYSTEM_DEVICE_INFORMATION Sdi
1005 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
1006 PCONFIGURATION_INFORMATION ConfigInfo
;
1008 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
1010 /* Check user buffer's size */
1011 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
1013 return STATUS_INFO_LENGTH_MISMATCH
;
1016 ConfigInfo
= IoGetConfigurationInformation();
1018 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
1019 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
1020 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
1021 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
1022 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
1023 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
1025 return STATUS_SUCCESS
;
1028 /* Class 8 - Processor Performance Information */
1029 QSI_DEF(SystemProcessorPerformanceInformation
)
1031 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
1032 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
1038 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
1040 /* Check user buffer's size */
1041 if (Size
< *ReqSize
)
1043 return STATUS_INFO_LENGTH_MISMATCH
;
1046 for (i
= 0; i
< KeNumberProcessors
; i
++)
1048 /* Get the PRCB on this processor */
1049 Prcb
= KiProcessorBlock
[i
];
1051 /* Calculate total user and kernel times */
1052 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
1053 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
1054 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
1055 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
1056 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
1057 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
1058 Spi
->InterruptCount
= Prcb
->InterruptCount
;
1062 return STATUS_SUCCESS
;
1065 /* Class 9 - Flags Information */
1066 QSI_DEF(SystemFlagsInformation
)
1068 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1070 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
1071 return (STATUS_INFO_LENGTH_MISMATCH
);
1073 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
1074 return STATUS_SUCCESS
;
1077 SSI_DEF(SystemFlagsInformation
)
1079 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1081 return STATUS_INFO_LENGTH_MISMATCH
;
1084 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, ExGetPreviousMode()))
1086 return STATUS_ACCESS_DENIED
;
1089 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
1090 return STATUS_SUCCESS
;
1093 /* Class 10 - Call Time Information */
1094 QSI_DEF(SystemCallTimeInformation
)
1097 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
1098 return STATUS_NOT_IMPLEMENTED
;
1101 /* Class 11 - Module Information */
1102 QSI_DEF(SystemModuleInformation
)
1106 /* Acquire system module list lock */
1107 KeEnterCriticalRegion();
1108 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource
, TRUE
);
1110 /* Call the generic handler with the system module list */
1111 Status
= ExpQueryModuleInformation(&PsLoadedModuleList
,
1112 &MmLoadedUserImageList
,
1113 (PRTL_PROCESS_MODULES
)Buffer
,
1117 /* Release list lock and return status */
1118 ExReleaseResourceLite(&PsLoadedModuleResource
);
1119 KeLeaveCriticalRegion();
1123 /* Class 12 - Locks Information */
1124 QSI_DEF(SystemLocksInformation
)
1127 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1128 return STATUS_NOT_IMPLEMENTED
;
1131 /* Class 13 - Stack Trace Information */
1132 QSI_DEF(SystemStackTraceInformation
)
1135 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1136 return STATUS_NOT_IMPLEMENTED
;
1139 /* Class 14 - Paged Pool Information */
1140 QSI_DEF(SystemPagedPoolInformation
)
1143 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1144 return STATUS_NOT_IMPLEMENTED
;
1147 /* Class 15 - Non Paged Pool Information */
1148 QSI_DEF(SystemNonPagedPoolInformation
)
1151 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1152 return STATUS_NOT_IMPLEMENTED
;
1156 /* Class 16 - Handle Information */
1157 QSI_DEF(SystemHandleInformation
)
1159 PEPROCESS pr
, syspr
;
1160 ULONG curSize
, i
= 0;
1163 PSYSTEM_HANDLE_INFORMATION Shi
=
1164 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1166 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1168 if (Size
< sizeof(SYSTEM_HANDLE_INFORMATION
))
1170 *ReqSize
= sizeof(SYSTEM_HANDLE_INFORMATION
);
1171 return STATUS_INFO_LENGTH_MISMATCH
;
1174 DPRINT("SystemHandleInformation 1\n");
1176 /* First Calc Size from Count. */
1177 syspr
= PsGetNextProcess(NULL
);
1182 hCount
= hCount
+ ObGetProcessHandleCount(pr
);
1183 pr
= PsGetNextProcess(pr
);
1185 if ((pr
== syspr
) || (pr
== NULL
)) break;
1187 while ((pr
!= syspr
) && (pr
!= NULL
));
1191 ObDereferenceObject(pr
);
1194 DPRINT("SystemHandleInformation 2\n");
1196 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
) +
1197 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1198 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
)));
1200 Shi
->NumberOfHandles
= hCount
;
1205 return (STATUS_INFO_LENGTH_MISMATCH
);
1208 DPRINT("SystemHandleInformation 3\n");
1210 /* Now get Handles from all processes. */
1211 syspr
= PsGetNextProcess(NULL
);
1216 int Count
= 0, HandleCount
;
1218 HandleCount
= ObGetProcessHandleCount(pr
);
1220 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1222 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG_PTR
)pr
->UniqueProcessId
;
1227 pr
= PsGetNextProcess(pr
);
1229 if ((pr
== syspr
) || (pr
== NULL
)) break;
1231 while ((pr
!= syspr
) && (pr
!= NULL
));
1233 if(pr
!= NULL
) ObDereferenceObject(pr
);
1235 DPRINT("SystemHandleInformation 4\n");
1236 return STATUS_SUCCESS
;
1240 SSI_DEF(SystemHandleInformation)
1243 return STATUS_SUCCESS;
1247 /* Class 17 - Information */
1248 QSI_DEF(SystemObjectInformation
)
1251 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1252 return STATUS_NOT_IMPLEMENTED
;
1255 /* Class 18 - Information */
1256 QSI_DEF(SystemPageFileInformation
)
1258 UNICODE_STRING FileName
; /* FIXME */
1259 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1261 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1263 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1264 return STATUS_INFO_LENGTH_MISMATCH
;
1267 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1270 Spfi
->NextEntryOffset
= 0;
1272 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1273 Spfi
->TotalInUse
= MiUsedSwapPages
;
1274 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1275 Spfi
->PageFileName
= FileName
;
1276 return STATUS_SUCCESS
;
1279 /* Class 19 - Vdm Instemul Information */
1280 QSI_DEF(SystemVdmInstemulInformation
)
1283 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1284 return STATUS_NOT_IMPLEMENTED
;
1287 /* Class 20 - Vdm Bop Information */
1288 QSI_DEF(SystemVdmBopInformation
)
1291 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1292 return STATUS_NOT_IMPLEMENTED
;
1295 /* Class 21 - File Cache Information */
1296 QSI_DEF(SystemFileCacheInformation
)
1298 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1300 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1302 if (Size
< *ReqSize
)
1304 return STATUS_INFO_LENGTH_MISMATCH
;
1307 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1309 /* Return the Byte size not the page size. */
1311 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1313 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1314 /* Taskmgr multiplies this one by page size right away */
1315 Sci
->CurrentSizeIncludingTransitionInPages
=
1316 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1317 /* system working set and standby pages. */
1318 Sci
->PageFaultCount
= 0; /* FIXME */
1319 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1320 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1322 return STATUS_SUCCESS
;
1325 SSI_DEF(SystemFileCacheInformation
)
1327 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1329 return STATUS_INFO_LENGTH_MISMATCH
;
1332 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1333 return STATUS_NOT_IMPLEMENTED
;
1336 /* Class 22 - Pool Tag Information */
1337 QSI_DEF(SystemPoolTagInformation
)
1339 if (Size
< sizeof(SYSTEM_POOLTAG_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
1340 return ExGetPoolTagInfo(Buffer
, Size
, ReqSize
);
1343 /* Class 23 - Interrupt Information for all processors */
1344 QSI_DEF(SystemInterruptInformation
)
1349 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1351 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1353 return STATUS_INFO_LENGTH_MISMATCH
;
1356 ti
= KeQueryTimeIncrement();
1358 for (i
= 0; i
< KeNumberProcessors
; i
++)
1360 Prcb
= KiProcessorBlock
[i
];
1361 sii
->ContextSwitches
= KeGetContextSwitches(Prcb
);
1362 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1363 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1364 sii
->TimeIncrement
= ti
;
1365 sii
->DpcBypassCount
= 0;
1366 sii
->ApcBypassCount
= 0;
1370 return STATUS_SUCCESS
;
1373 /* Class 24 - DPC Behaviour Information */
1374 QSI_DEF(SystemDpcBehaviourInformation
)
1377 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1378 return STATUS_NOT_IMPLEMENTED
;
1381 SSI_DEF(SystemDpcBehaviourInformation
)
1384 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1385 return STATUS_NOT_IMPLEMENTED
;
1388 /* Class 25 - Full Memory Information */
1389 QSI_DEF(SystemFullMemoryInformation
)
1391 PULONG Spi
= (PULONG
) Buffer
;
1393 PEPROCESS TheIdleProcess
;
1395 *ReqSize
= sizeof(ULONG
);
1397 if (sizeof(ULONG
) != Size
)
1399 return STATUS_INFO_LENGTH_MISMATCH
;
1402 DPRINT("SystemFullMemoryInformation\n");
1404 TheIdleProcess
= PsIdleProcess
;
1406 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
1407 TheIdleProcess
->UniqueProcessId
,
1408 TheIdleProcess
->Pcb
.KernelTime
,
1412 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1414 return STATUS_SUCCESS
;
1417 /* Class 26 - Load Image */
1418 SSI_DEF(SystemLoadGdiDriverInformation
)
1420 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1421 UNICODE_STRING ImageName
;
1423 PVOID SectionPointer
;
1424 ULONG_PTR EntryPoint
;
1427 PIMAGE_NT_HEADERS NtHeader
;
1430 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1432 /* Incorrect buffer length, fail */
1433 return STATUS_INFO_LENGTH_MISMATCH
;
1436 /* Only kernel mode can call this function */
1437 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1439 /* Load the driver */
1440 ImageName
= DriverInfo
->DriverName
;
1441 Status
= MmLoadSystemImage(&ImageName
,
1447 if (!NT_SUCCESS(Status
)) return Status
;
1449 /* Return the export pointer */
1450 DriverInfo
->ExportSectionPointer
=
1451 RtlImageDirectoryEntryToData(ImageBase
,
1453 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1456 /* Get the entrypoint */
1457 NtHeader
= RtlImageNtHeader(ImageBase
);
1458 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1459 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1461 /* Save other data */
1462 DriverInfo
->ImageAddress
= ImageBase
;
1463 DriverInfo
->SectionPointer
= SectionPointer
;
1464 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1465 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1468 return STATUS_SUCCESS
;
1471 /* Class 27 - Unload Image */
1472 SSI_DEF(SystemUnloadGdiDriverInformation
)
1474 PVOID
*SectionPointer
= Buffer
;
1477 if (Size
!= sizeof(PVOID
))
1479 /* Incorrect length, fail */
1480 return STATUS_INFO_LENGTH_MISMATCH
;
1483 /* Only kernel mode can call this function */
1484 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1486 /* Unload the image */
1487 MmUnloadSystemImage(*SectionPointer
);
1488 return STATUS_SUCCESS
;
1491 /* Class 28 - Time Adjustment Information */
1492 QSI_DEF(SystemTimeAdjustmentInformation
)
1494 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1495 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1497 /* Check if enough storage was provided */
1498 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1500 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1501 return STATUS_INFO_LENGTH_MISMATCH
;
1504 /* Give time values to our caller */
1505 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1506 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1507 TimeInfo
->Enable
= !KiTimeAdjustmentEnabled
;
1509 return STATUS_SUCCESS
;
1512 SSI_DEF(SystemTimeAdjustmentInformation
)
1514 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1515 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
=
1516 (PSYSTEM_SET_TIME_ADJUST_INFORMATION
)Buffer
;
1518 /* Check size of a buffer, it must match our expectations */
1519 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1520 return STATUS_INFO_LENGTH_MISMATCH
;
1522 /* Check who is calling */
1523 if (PreviousMode
!= KernelMode
)
1525 /* Check access rights */
1526 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1528 return STATUS_PRIVILEGE_NOT_HELD
;
1532 /* FIXME: behaviour suggests the member be named 'Disable' */
1533 if (TimeInfo
->Enable
)
1535 /* Disable time adjustment and set default value */
1536 KiTimeAdjustmentEnabled
= FALSE
;
1537 KeTimeAdjustment
= KeMaximumIncrement
;
1541 /* Check if a valid time adjustment value is given */
1542 if (TimeInfo
->TimeAdjustment
== 0) return STATUS_INVALID_PARAMETER_2
;
1544 /* Enable time adjustment and set the adjustment value */
1545 KiTimeAdjustmentEnabled
= TRUE
;
1546 KeTimeAdjustment
= TimeInfo
->TimeAdjustment
;
1549 return STATUS_SUCCESS
;
1552 /* Class 29 - Summary Memory Information */
1553 QSI_DEF(SystemSummaryMemoryInformation
)
1556 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1557 return STATUS_NOT_IMPLEMENTED
;
1560 /* Class 30 - Next Event Id Information */
1561 QSI_DEF(SystemNextEventIdInformation
)
1564 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1565 return STATUS_NOT_IMPLEMENTED
;
1569 QSI_DEF(SystemPerformanceTraceInformation
)
1572 DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n");
1573 return STATUS_NOT_IMPLEMENTED
;
1576 /* Class 32 - Crash Dump Information */
1577 QSI_DEF(SystemCrashDumpInformation
)
1580 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1581 return STATUS_NOT_IMPLEMENTED
;
1584 /* Class 33 - Exception Information */
1585 QSI_DEF(SystemExceptionInformation
)
1587 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation
=
1588 (PSYSTEM_EXCEPTION_INFORMATION
)Buffer
;
1590 ULONG AlignmentFixupCount
= 0, ExceptionDispatchCount
= 0;
1591 ULONG FloatingEmulationCount
= 0, ByteWordEmulationCount
= 0;
1594 /* Check size of a buffer, it must match our expectations */
1595 if (sizeof(SYSTEM_EXCEPTION_INFORMATION
) != Size
)
1596 return STATUS_INFO_LENGTH_MISMATCH
;
1598 /* Sum up exception count information from all processors */
1599 for (i
= 0; i
< KeNumberProcessors
; i
++)
1601 Prcb
= KiProcessorBlock
[i
];
1604 AlignmentFixupCount
+= Prcb
->KeAlignmentFixupCount
;
1605 ExceptionDispatchCount
+= Prcb
->KeExceptionDispatchCount
;
1607 FloatingEmulationCount
+= Prcb
->KeFloatingEmulationCount
;
1612 /* Save information in user's buffer */
1613 ExceptionInformation
->AlignmentFixupCount
= AlignmentFixupCount
;
1614 ExceptionInformation
->ExceptionDispatchCount
= ExceptionDispatchCount
;
1615 ExceptionInformation
->FloatingEmulationCount
= FloatingEmulationCount
;
1616 ExceptionInformation
->ByteWordEmulationCount
= ByteWordEmulationCount
;
1618 return STATUS_SUCCESS
;
1621 /* Class 34 - Crash Dump State Information */
1622 QSI_DEF(SystemCrashDumpStateInformation
)
1625 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1626 return STATUS_NOT_IMPLEMENTED
;
1629 /* Class 35 - Kernel Debugger Information */
1630 QSI_DEF(SystemKernelDebuggerInformation
)
1632 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1634 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1635 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1637 return STATUS_INFO_LENGTH_MISMATCH
;
1640 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1641 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1643 return STATUS_SUCCESS
;
1646 /* Class 36 - Context Switch Information */
1647 QSI_DEF(SystemContextSwitchInformation
)
1649 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation
=
1650 (PSYSTEM_CONTEXT_SWITCH_INFORMATION
)Buffer
;
1651 ULONG ContextSwitches
;
1655 /* Check size of a buffer, it must match our expectations */
1656 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION
) != Size
)
1657 return STATUS_INFO_LENGTH_MISMATCH
;
1659 /* Calculate total value of context switches across all processors */
1660 ContextSwitches
= 0;
1661 for (i
= 0; i
< KeNumberProcessors
; i
++)
1663 Prcb
= KiProcessorBlock
[i
];
1666 ContextSwitches
+= KeGetContextSwitches(Prcb
);
1670 ContextSwitchInformation
->ContextSwitches
= ContextSwitches
;
1673 ContextSwitchInformation
->FindAny
= 0;
1674 ContextSwitchInformation
->FindLast
= 0;
1675 ContextSwitchInformation
->FindIdeal
= 0;
1676 ContextSwitchInformation
->IdleAny
= 0;
1677 ContextSwitchInformation
->IdleCurrent
= 0;
1678 ContextSwitchInformation
->IdleLast
= 0;
1679 ContextSwitchInformation
->IdleIdeal
= 0;
1680 ContextSwitchInformation
->PreemptAny
= 0;
1681 ContextSwitchInformation
->PreemptCurrent
= 0;
1682 ContextSwitchInformation
->PreemptLast
= 0;
1683 ContextSwitchInformation
->SwitchToIdle
= 0;
1685 return STATUS_SUCCESS
;
1688 /* Class 37 - Registry Quota Information */
1689 QSI_DEF(SystemRegistryQuotaInformation
)
1691 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1693 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1694 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1696 return STATUS_INFO_LENGTH_MISMATCH
;
1699 DPRINT1("Faking max registry size of 32 MB\n");
1700 srqi
->RegistryQuotaAllowed
= 0x2000000;
1701 srqi
->RegistryQuotaUsed
= 0x200000;
1702 srqi
->PagedPoolSize
= 0x200000;
1704 return STATUS_SUCCESS
;
1707 SSI_DEF(SystemRegistryQuotaInformation
)
1710 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1711 return STATUS_NOT_IMPLEMENTED
;
1714 /* Class 38 - Load And Call Image */
1715 SSI_DEF(SystemExtendServiceTableInformation
)
1717 UNICODE_STRING ImageName
;
1718 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1719 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1721 PIMAGE_NT_HEADERS NtHeader
;
1722 DRIVER_OBJECT Win32k
;
1723 PDRIVER_INITIALIZE DriverInit
;
1725 ULONG_PTR EntryPoint
;
1727 /* Validate the size */
1728 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1730 /* Check who is calling */
1731 if (PreviousMode
!= KernelMode
)
1733 static const UNICODE_STRING Win32kName
=
1734 RTL_CONSTANT_STRING(L
"\\SystemRoot\\System32\\win32k.sys");
1736 /* Make sure we can load drivers */
1737 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1739 /* FIXME: We can't, fail */
1740 return STATUS_PRIVILEGE_NOT_HELD
;
1745 /* Probe and copy the unicode string */
1746 ProbeForRead(Buffer
, sizeof(ImageName
), 1);
1747 ImageName
= *(PUNICODE_STRING
)Buffer
;
1749 /* Probe the string buffer */
1750 ProbeForRead(ImageName
.Buffer
, ImageName
.Length
, sizeof(WCHAR
));
1752 /* Check if we have the correct name (nothing else is allowed!) */
1753 if (!RtlEqualUnicodeString(&ImageName
, &Win32kName
, FALSE
))
1755 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD
);
1758 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1760 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1764 /* Recursively call the function, so that we are from kernel mode */
1765 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1767 sizeof(Win32kName
));
1770 /* Load the image */
1771 Status
= MmLoadSystemImage((PUNICODE_STRING
)Buffer
,
1775 (PVOID
)&ModuleObject
,
1778 if (!NT_SUCCESS(Status
)) return Status
;
1780 /* Get the headers */
1781 NtHeader
= RtlImageNtHeader(ImageBase
);
1785 MmUnloadSystemImage(ModuleObject
);
1786 return STATUS_INVALID_IMAGE_FORMAT
;
1789 /* Get the entrypoint */
1790 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1791 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1792 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1794 /* Create a dummy device */
1795 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1796 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1797 Win32k
.DriverStart
= ImageBase
;
1800 Status
= (DriverInit
)(&Win32k
, NULL
);
1801 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1803 /* Unload if we failed */
1804 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1808 /* Class 39 - Priority Separation */
1809 SSI_DEF(SystemPrioritySeperation
)
1811 /* Check if the size is correct */
1812 if (Size
!= sizeof(ULONG
))
1814 return STATUS_INFO_LENGTH_MISMATCH
;
1817 /* We need the TCB privilege */
1818 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, ExGetPreviousMode()))
1820 return STATUS_PRIVILEGE_NOT_HELD
;
1823 /* Modify the quantum table */
1824 PsChangeQuantumTable(TRUE
, *(PULONG
)Buffer
);
1826 return STATUS_SUCCESS
;
1830 QSI_DEF(SystemVerifierAddDriverInformation
)
1833 DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n");
1834 return STATUS_NOT_IMPLEMENTED
;
1838 QSI_DEF(SystemVerifierRemoveDriverInformation
)
1841 DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n");
1842 return STATUS_NOT_IMPLEMENTED
;
1845 /* Class 42 - Power Information */
1846 QSI_DEF(SystemProcessorIdleInformation
)
1848 *ReqSize
= sizeof(PROCESSOR_POWER_INFORMATION
) * KeNumberProcessors
;
1850 if (sizeof(PROCESSOR_POWER_INFORMATION
) * KeNumberProcessors
> Size
)
1852 return STATUS_INFO_LENGTH_MISMATCH
;
1856 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1857 return STATUS_NOT_IMPLEMENTED
;
1861 QSI_DEF(SystemLegacyDriverInformation
)
1864 DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n");
1865 return STATUS_NOT_IMPLEMENTED
;
1868 /* Class 44 - Current Time Zone Information */
1869 QSI_DEF(SystemCurrentTimeZoneInformation
)
1871 *ReqSize
= sizeof(TIME_ZONE_INFORMATION
);
1873 if (sizeof(TIME_ZONE_INFORMATION
) != Size
)
1875 return STATUS_INFO_LENGTH_MISMATCH
;
1878 /* Copy the time zone information struct */
1881 sizeof(TIME_ZONE_INFORMATION
));
1883 return STATUS_SUCCESS
;
1887 SSI_DEF(SystemCurrentTimeZoneInformation
)
1889 /* Check user buffer's size */
1890 if (Size
< sizeof(TIME_ZONE_INFORMATION
))
1892 return STATUS_INFO_LENGTH_MISMATCH
;
1895 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1900 ExpCopyLookasideInformation(
1901 PSYSTEM_LOOKASIDE_INFORMATION
*InfoPointer
,
1902 PULONG RemainingPointer
,
1903 PLIST_ENTRY ListHead
,
1904 BOOLEAN ListUsesMisses
)
1907 PSYSTEM_LOOKASIDE_INFORMATION Info
;
1908 PGENERAL_LOOKASIDE LookasideList
;
1909 PLIST_ENTRY ListEntry
;
1912 /* Get info pointer and remaining count of free array element */
1913 Info
= *InfoPointer
;
1914 Remaining
= *RemainingPointer
;
1916 /* Loop as long as we have lookaside lists and free array elements */
1917 for (ListEntry
= ListHead
->Flink
;
1918 (ListEntry
!= ListHead
) && (Remaining
> 0);
1919 ListEntry
= ListEntry
->Flink
, Remaining
--)
1921 LookasideList
= CONTAINING_RECORD(ListEntry
, GENERAL_LOOKASIDE
, ListEntry
);
1923 /* Fill the next array element */
1924 Info
->CurrentDepth
= LookasideList
->Depth
;
1925 Info
->MaximumDepth
= LookasideList
->MaximumDepth
;
1926 Info
->TotalAllocates
= LookasideList
->TotalAllocates
;
1927 Info
->TotalFrees
= LookasideList
->TotalFrees
;
1928 Info
->Type
= LookasideList
->Type
;
1929 Info
->Tag
= LookasideList
->Tag
;
1930 Info
->Size
= LookasideList
->Size
;
1932 /* Check how the lists track misses/hits */
1936 Info
->AllocateMisses
= LookasideList
->AllocateMisses
;
1937 Info
->FreeMisses
= LookasideList
->FreeMisses
;
1941 /* Calculate misses */
1942 Info
->AllocateMisses
= LookasideList
->TotalAllocates
1943 - LookasideList
->AllocateHits
;
1944 Info
->FreeMisses
= LookasideList
->TotalFrees
1945 - LookasideList
->FreeHits
;
1949 /* Return the updated pointer and remaining count */
1950 *InfoPointer
= Info
;
1951 *RemainingPointer
= Remaining
;
1954 /* Class 45 - Lookaside Information */
1955 QSI_DEF(SystemLookasideInformation
)
1957 KPROCESSOR_MODE PreviousMode
;
1958 PSYSTEM_LOOKASIDE_INFORMATION Info
;
1960 ULONG MaxCount
, Remaining
;
1964 /* First we need to lock down the memory, since we are going to access it
1966 PreviousMode
= ExGetPreviousMode();
1967 Status
= ExLockUserBuffer(Buffer
,
1973 if (!NT_SUCCESS(Status
))
1975 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status
);
1979 /* Calculate how many items we can store */
1980 Remaining
= MaxCount
= Size
/ sizeof(SYSTEM_LOOKASIDE_INFORMATION
);
1986 /* Copy info from pool lookaside lists */
1987 ExpCopyLookasideInformation(&Info
,
1989 &ExPoolLookasideListHead
,
1996 /* Copy info from system lookaside lists */
1997 ExpCopyLookasideInformation(&Info
,
1999 &ExSystemLookasideListHead
,
2006 /* Acquire spinlock for ExpNonPagedLookasideListHead */
2007 KeAcquireSpinLock(&ExpNonPagedLookasideListLock
, &OldIrql
);
2009 /* Copy info from non-paged lookaside lists */
2010 ExpCopyLookasideInformation(&Info
,
2012 &ExpNonPagedLookasideListHead
,
2015 /* Release spinlock for ExpNonPagedLookasideListHead */
2016 KeReleaseSpinLock(&ExpNonPagedLookasideListLock
, OldIrql
);
2023 /* Acquire spinlock for ExpPagedLookasideListHead */
2024 KeAcquireSpinLock(&ExpPagedLookasideListLock
, &OldIrql
);
2026 /* Copy info from paged lookaside lists */
2027 ExpCopyLookasideInformation(&Info
,
2029 &ExpPagedLookasideListHead
,
2032 /* Release spinlock for ExpPagedLookasideListHead */
2033 KeReleaseSpinLock(&ExpPagedLookasideListLock
, OldIrql
);
2037 /* Release the locked user buffer */
2038 ExUnlockUserBuffer(Mdl
);
2040 /* Return the size of the actually written data */
2041 *ReqSize
= (MaxCount
- Remaining
) * sizeof(SYSTEM_LOOKASIDE_INFORMATION
);
2042 return STATUS_SUCCESS
;
2046 /* Class 46 - Set time slip event */
2047 SSI_DEF(SystemTimeSlipNotification
)
2050 DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n");
2051 return STATUS_NOT_IMPLEMENTED
;
2056 MmSessionCreate(OUT PULONG SessionId
);
2060 MmSessionDelete(IN ULONG SessionId
);
2062 /* Class 47 - Create a new session (TSE) */
2063 SSI_DEF(SystemSessionCreate
)
2066 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2069 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
2071 if (PreviousMode
!= KernelMode
)
2073 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
2075 return STATUS_PRIVILEGE_NOT_HELD
;
2078 ProbeForWriteUlong(Buffer
);
2081 Status
= MmSessionCreate(&SessionId
);
2082 if (NT_SUCCESS(Status
)) *(PULONG
)Buffer
= SessionId
;
2088 /* Class 48 - Delete an existing session (TSE) */
2089 SSI_DEF(SystemSessionDetach
)
2092 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
2094 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
2096 if (PreviousMode
!= KernelMode
)
2098 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
2100 return STATUS_PRIVILEGE_NOT_HELD
;
2104 SessionId
= *(PULONG
)Buffer
;
2106 return MmSessionDelete(SessionId
);
2110 /* Class 49 - UNKNOWN */
2111 QSI_DEF(SystemSessionInformation
)
2114 DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n");
2115 return STATUS_NOT_IMPLEMENTED
;
2119 /* Class 50 - System range start address */
2120 QSI_DEF(SystemRangeStartInformation
)
2122 /* Check user buffer's size */
2123 if (Size
!= sizeof(ULONG_PTR
)) return STATUS_INFO_LENGTH_MISMATCH
;
2125 *(PULONG_PTR
)Buffer
= (ULONG_PTR
)MmSystemRangeStart
;
2127 if (ReqSize
) *ReqSize
= sizeof(ULONG_PTR
);
2129 return STATUS_SUCCESS
;
2132 /* Class 51 - Driver verifier information */
2133 QSI_DEF(SystemVerifierInformation
)
2136 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
2137 return STATUS_NOT_IMPLEMENTED
;
2141 SSI_DEF(SystemVerifierInformation
)
2144 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
2145 return STATUS_NOT_IMPLEMENTED
;
2150 SSI_DEF(SystemVerifierThunkExtend
)
2153 DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n");
2154 return STATUS_NOT_IMPLEMENTED
;
2158 /* Class 53 - A session's processes */
2159 QSI_DEF(SystemSessionProcessesInformation
)
2162 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
2163 return STATUS_NOT_IMPLEMENTED
;
2167 /* Class 54 - Load & map in system space */
2168 SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation
)
2171 DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n");
2172 return STATUS_NOT_IMPLEMENTED
;
2176 /* Class 55 - NUMA processor information */
2177 QSI_DEF(SystemNumaProcessorMap
)
2179 ULONG MaxEntries
, Node
;
2180 PSYSTEM_NUMA_INFORMATION NumaInformation
= (PSYSTEM_NUMA_INFORMATION
)Buffer
;
2182 /* Validate input size */
2183 if (Size
< sizeof(ULONG
))
2185 return STATUS_INFO_LENGTH_MISMATCH
;
2188 /* Return highest node */
2189 NumaInformation
->HighestNodeNumber
= KeNumberNodes
- 1;
2191 /* Compute how much entries we will be able to put in output structure */
2192 MaxEntries
= (Size
- FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
)) / sizeof(ULONGLONG
);
2193 /* Make sure we don't overflow KeNodeBlock */
2194 if (MaxEntries
> KeNumberNodes
)
2196 MaxEntries
= KeNumberNodes
;
2199 /* If we have entries to write, and room for it */
2200 if (Size
>= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
) &&
2203 /* Already set size we return */
2204 *ReqSize
= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, ActiveProcessorsAffinityMask
) +
2205 MaxEntries
* sizeof(ULONGLONG
);
2207 /* For each node, return processor mask */
2208 for (Node
= 0; Node
< MaxEntries
; ++Node
)
2210 NumaInformation
->ActiveProcessorsAffinityMask
[Node
] = KeNodeBlock
[Node
]->ProcessorMask
;
2215 /* We only returned highest node number */
2216 *ReqSize
= sizeof(ULONG
);
2219 return STATUS_SUCCESS
;
2223 /* Class 56 - Prefetcher information */
2224 QSI_DEF(SystemPrefetcherInformation
)
2227 DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n");
2228 return STATUS_NOT_IMPLEMENTED
;
2232 /* Class 57 - Extended process information */
2233 QSI_DEF(SystemExtendedProcessInformation
)
2236 DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n");
2237 return STATUS_NOT_IMPLEMENTED
;
2241 /* Class 58 - Recommended shared ata alignment */
2242 QSI_DEF(SystemRecommendedSharedDataAlignment
)
2245 DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n");
2246 return STATUS_NOT_IMPLEMENTED
;
2250 /* Class 60 - NUMA memory information */
2251 QSI_DEF(SystemNumaAvailableMemory
)
2253 ULONG MaxEntries
, Node
;
2254 PSYSTEM_NUMA_INFORMATION NumaInformation
= (PSYSTEM_NUMA_INFORMATION
)Buffer
;
2256 /* Validate input size */
2257 if (Size
< sizeof(ULONG
))
2259 return STATUS_INFO_LENGTH_MISMATCH
;
2262 /* Return highest node */
2263 NumaInformation
->HighestNodeNumber
= KeNumberNodes
- 1;
2265 /* Compute how much entries we will be able to put in output structure */
2266 MaxEntries
= (Size
- FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
)) / sizeof(ULONGLONG
);
2267 /* Make sure we don't overflow KeNodeBlock */
2268 if (MaxEntries
> KeNumberNodes
)
2270 MaxEntries
= KeNumberNodes
;
2273 /* If we have entries to write, and room for it */
2274 if (Size
>= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
) &&
2277 /* Already set size we return */
2278 *ReqSize
= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION
, AvailableMemory
) +
2279 MaxEntries
* sizeof(ULONGLONG
);
2281 /* If we have a single entry (us), directly return MM information */
2282 if (MaxEntries
== 1)
2284 NumaInformation
->AvailableMemory
[0] = MmAvailablePages
<< PAGE_SHIFT
;
2288 /* Otherwise, for each node, return available bytes */
2289 for (Node
= 0; Node
< MaxEntries
; ++Node
)
2291 NumaInformation
->AvailableMemory
[Node
] = (KeNodeBlock
[Node
]->FreeCount
[0] + KeNodeBlock
[Node
]->FreeCount
[1]) << PAGE_SHIFT
;
2297 /* We only returned highest node number */
2298 *ReqSize
= sizeof(ULONG
);
2301 return STATUS_SUCCESS
;
2305 /* Query/Set Calls Table */
2309 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
2310 NTSTATUS (* Set
) (PVOID
,ULONG
);
2317 // XX unknown behaviour
2319 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
2320 #define SI_QX(n) {QSI_USE(n),NULL}
2321 #define SI_XS(n) {NULL,SSI_USE(n)}
2322 #define SI_XX(n) {NULL,NULL}
2328 SI_QX(SystemBasicInformation
),
2329 SI_QX(SystemProcessorInformation
),
2330 SI_QX(SystemPerformanceInformation
),
2331 SI_QX(SystemTimeOfDayInformation
),
2332 SI_QX(SystemPathInformation
), /* should be SI_XX */
2333 SI_QX(SystemProcessInformation
),
2334 SI_QX(SystemCallCountInformation
),
2335 SI_QX(SystemDeviceInformation
),
2336 SI_QX(SystemProcessorPerformanceInformation
),
2337 SI_QS(SystemFlagsInformation
),
2338 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
2339 SI_QX(SystemModuleInformation
),
2340 SI_QX(SystemLocksInformation
),
2341 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
2342 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
2343 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
2344 SI_QX(SystemHandleInformation
),
2345 SI_QX(SystemObjectInformation
),
2346 SI_QX(SystemPageFileInformation
),
2347 SI_QX(SystemVdmInstemulInformation
),
2348 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
2349 SI_QS(SystemFileCacheInformation
),
2350 SI_QX(SystemPoolTagInformation
),
2351 SI_QX(SystemInterruptInformation
),
2352 SI_QS(SystemDpcBehaviourInformation
),
2353 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
2354 SI_XS(SystemLoadGdiDriverInformation
),
2355 SI_XS(SystemUnloadGdiDriverInformation
),
2356 SI_QS(SystemTimeAdjustmentInformation
),
2357 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
2358 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
2359 SI_QX(SystemPerformanceTraceInformation
), /* it should be SI_XX */
2360 SI_QX(SystemCrashDumpInformation
),
2361 SI_QX(SystemExceptionInformation
),
2362 SI_QX(SystemCrashDumpStateInformation
),
2363 SI_QX(SystemKernelDebuggerInformation
),
2364 SI_QX(SystemContextSwitchInformation
),
2365 SI_QS(SystemRegistryQuotaInformation
),
2366 SI_XS(SystemExtendServiceTableInformation
),
2367 SI_XS(SystemPrioritySeperation
),
2368 SI_QX(SystemVerifierAddDriverInformation
), /* it should be SI_XX */
2369 SI_QX(SystemVerifierRemoveDriverInformation
), /* it should be SI_XX */
2370 SI_QX(SystemProcessorIdleInformation
), /* it should be SI_XX */
2371 SI_QX(SystemLegacyDriverInformation
), /* it should be SI_XX */
2372 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
2373 SI_QX(SystemLookasideInformation
),
2374 SI_XS(SystemTimeSlipNotification
),
2375 SI_XS(SystemSessionCreate
),
2376 SI_XS(SystemSessionDetach
),
2377 SI_QX(SystemSessionInformation
), /* it should be SI_XX */
2378 SI_QX(SystemRangeStartInformation
),
2379 SI_QS(SystemVerifierInformation
),
2380 SI_XS(SystemVerifierThunkExtend
),
2381 SI_QX(SystemSessionProcessesInformation
),
2382 SI_XS(SystemLoadGdiDriverInSystemSpaceInformation
),
2383 SI_QX(SystemNumaProcessorMap
),
2384 SI_QX(SystemPrefetcherInformation
),
2385 SI_QX(SystemExtendedProcessInformation
),
2386 SI_QX(SystemRecommendedSharedDataAlignment
),
2387 SI_XX(SystemComPlusPackage
),
2388 SI_QX(SystemNumaAvailableMemory
)
2391 C_ASSERT(SystemBasicInformation
== 0);
2392 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
2393 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
2399 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2400 OUT PVOID SystemInformation
,
2402 OUT PULONG UnsafeResultLength
)
2404 KPROCESSOR_MODE PreviousMode
;
2405 ULONG ResultLength
= 0;
2406 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
2410 PreviousMode
= ExGetPreviousMode();
2414 if (PreviousMode
!= KernelMode
)
2416 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
2417 ProbeForWrite(SystemInformation
, Length
, 1);
2418 if (UnsafeResultLength
!= NULL
)
2419 ProbeForWriteUlong(UnsafeResultLength
);
2422 if (UnsafeResultLength
)
2423 *UnsafeResultLength
= 0;
2426 * Check if the request is valid.
2428 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2430 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2433 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
2436 * Hand the request to a subhandler.
2438 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
2442 /* Save the result length to the caller */
2443 if (NT_SUCCESS(FStatus
) && UnsafeResultLength
)
2444 *UnsafeResultLength
= ResultLength
;
2447 _SEH2_EXCEPT(ExSystemExceptionFilter())
2449 FStatus
= _SEH2_GetExceptionCode();
2459 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2460 IN PVOID SystemInformation
,
2461 IN ULONG SystemInformationLength
)
2463 NTSTATUS Status
= STATUS_INVALID_INFO_CLASS
;
2464 KPROCESSOR_MODE PreviousMode
;
2468 PreviousMode
= ExGetPreviousMode();
2473 * If called from user mode, check
2474 * possible unsafe arguments.
2476 if (PreviousMode
!= KernelMode
)
2478 ProbeForRead(SystemInformation
, SystemInformationLength
, sizeof(ULONG
));
2482 * Check the request is valid.
2484 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
2485 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
2487 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
2490 * Hand the request to a subhandler.
2492 Status
= CallQS
[SystemInformationClass
].Set(SystemInformation
,
2493 SystemInformationLength
);
2497 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2499 Status
= _SEH2_GetExceptionCode();
2508 NtFlushInstructionCache(
2509 _In_ HANDLE ProcessHandle
,
2510 _In_opt_ PVOID BaseAddress
,
2511 _In_ ULONG FlushSize
)
2513 KAPC_STATE ApcState
;
2518 /* Is a base address given? */
2519 if (BaseAddress
!= NULL
)
2521 /* If the requested size is 0, there is nothing to do */
2524 return STATUS_SUCCESS
;
2527 /* Is this a user mode call? */
2528 if (KeGetPreviousMode() != KernelMode
)
2530 /* Make sure the base address is in user space */
2531 if (BaseAddress
> MmHighestUserAddress
)
2533 DPRINT1("Invalid BaseAddress 0x%p\n", BaseAddress
);
2534 return STATUS_ACCESS_VIOLATION
;
2539 /* Is another process requested? */
2540 if (ProcessHandle
!= NtCurrentProcess())
2542 /* Reference the process */
2543 Status
= ObReferenceObjectByHandle(ProcessHandle
,
2546 KeGetPreviousMode(),
2549 if (!NT_SUCCESS(Status
))
2551 DPRINT1("Failed to reference the process %p\n", ProcessHandle
);
2555 /* Attach to the process */
2556 KeStackAttachProcess(Process
, &ApcState
);
2559 /* FIXME: don't flush everything if a range is requested */
2560 #if defined(_M_IX86) || defined(_M_AMD64)
2562 #elif defined(_M_PPC)
2563 __asm__
__volatile__("tlbsync");
2564 #elif defined(_M_MIPS)
2565 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2567 #elif defined(_M_ARM)
2568 _MoveToCoprocessor(0, CP15_ICIALLU
);
2570 #error Unknown architecture
2573 /* Check if we attached */
2574 if (ProcessHandle
!= NtCurrentProcess())
2576 /* Detach from the process */
2577 KeUnstackDetachProcess(&ApcState
);
2580 return STATUS_SUCCESS
;
2585 NtGetCurrentProcessorNumber(VOID
)
2587 /* Just return the CPU */
2588 return KeGetCurrentProcessorNumber();
2594 #undef ExGetPreviousMode
2597 ExGetPreviousMode (VOID
)
2599 return KeGetPreviousMode();