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
;
183 /* FUNCTIONS *****************************************************************/
190 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
194 ULONGLONG ScaledIdle
;
196 Prcb
= KeGetCurrentPrcb();
198 ScaledIdle
= (ULONGLONG
)Prcb
->IdleThread
->KernelTime
* 100;
199 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
201 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
211 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
213 PULONG ProcessorNumber
)
217 Prcb
= KeGetCurrentPrcb();
219 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
220 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
221 *ProcessorNumber
= KeGetCurrentProcessorNumber();
229 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
231 /* Quick check to see if it exists at all */
232 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
234 /* Return our support for it */
235 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
243 ExVerifySuite(SUITE_TYPE SuiteType
)
245 if (SuiteType
== Personal
) return TRUE
;
251 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
252 OUT PWSTR ValueBuffer
,
253 IN ULONG ValueBufferLength
,
254 IN OUT PULONG ReturnLength OPTIONAL
)
257 UNICODE_STRING WName
;
261 UNICODE_STRING WValue
;
262 KPROCESSOR_MODE PreviousMode
;
266 /* Check if the call came from user mode */
267 PreviousMode
= ExGetPreviousMode();
268 if (PreviousMode
!= KernelMode
)
272 /* Probe the input and output buffers */
273 ProbeForRead(VariableName
, sizeof(UNICODE_STRING
), sizeof(ULONG
));
274 ProbeForWrite(ValueBuffer
, ValueBufferLength
, sizeof(WCHAR
));
275 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
277 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
279 /* Return the exception code */
280 _SEH2_YIELD(return _SEH2_GetExceptionCode());
285 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
286 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
, PreviousMode
))
288 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
289 return STATUS_PRIVILEGE_NOT_HELD
;
292 /* Copy the name to kernel space if necessary */
293 Status
= ProbeAndCaptureUnicodeString(&WName
, PreviousMode
, VariableName
);
294 if (!NT_SUCCESS(Status
)) return Status
;
296 /* Convert the name to ANSI and release the captured UNICODE string */
297 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
298 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
299 if (!NT_SUCCESS(Status
)) return Status
;
301 /* Allocate a buffer for the ANSI environment variable */
302 AnsiValueBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_ENVVAL_SIZE
, 'rvnE');
303 if (AnsiValueBuffer
== NULL
)
305 RtlFreeAnsiString(&AName
);
306 return STATUS_INSUFFICIENT_RESOURCES
;
309 /* Get the environment variable and free the ANSI name */
310 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
313 RtlFreeAnsiString(&AName
);
315 /* Check if we had success */
316 if (Result
== ESUCCESS
)
318 /* Copy the result back to the caller. */
321 /* Initialize ANSI string from the result */
322 RtlInitAnsiString(&AValue
, AnsiValueBuffer
);
324 /* Initialize a UNICODE string from the callers buffer */
325 RtlInitEmptyUnicodeString(&WValue
, ValueBuffer
, (USHORT
)ValueBufferLength
);
327 /* Convert the result to UNICODE */
328 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, FALSE
);
330 if (ReturnLength
!= NULL
)
331 *ReturnLength
= WValue
.Length
;
333 _SEH2_EXCEPT(ExSystemExceptionFilter())
335 Status
= _SEH2_GetExceptionCode();
341 Status
= STATUS_UNSUCCESSFUL
;
344 /* Free the allocated ANSI value buffer */
345 ExFreePoolWithTag(AnsiValueBuffer
, 'rvnE');
353 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
354 IN PUNICODE_STRING Value
)
356 UNICODE_STRING CapturedName
, CapturedValue
;
357 ANSI_STRING AName
, AValue
;
358 KPROCESSOR_MODE PreviousMode
;
363 PreviousMode
= ExGetPreviousMode();
366 * Copy the strings to kernel space if necessary
368 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
371 if (NT_SUCCESS(Status
))
373 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
376 if (NT_SUCCESS(Status
))
379 * according to ntinternals the SeSystemEnvironmentName privilege is required!
381 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
385 * convert the strings to ANSI
387 Status
= RtlUnicodeStringToAnsiString(&AName
,
390 if (NT_SUCCESS(Status
))
392 Status
= RtlUnicodeStringToAnsiString(&AValue
,
395 if (NT_SUCCESS(Status
))
397 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
400 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
406 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
407 Status
= STATUS_PRIVILEGE_NOT_HELD
;
410 ReleaseCapturedUnicodeString(&CapturedValue
,
414 ReleaseCapturedUnicodeString(&CapturedName
,
423 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
425 IN ULONG BufferLength
)
428 return STATUS_NOT_IMPLEMENTED
;
433 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
434 IN LPGUID VendorGuid
,
436 IN OUT PULONG ReturnLength
,
437 IN OUT PULONG Attributes
)
440 return STATUS_NOT_IMPLEMENTED
;
445 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
446 IN LPGUID VendorGuid
)
449 return STATUS_NOT_IMPLEMENTED
;
452 /* --- Query/Set System Information --- */
455 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
456 * so the stack is popped only in one place on x86 platform.
458 #define QSI_USE(n) QSI##n
460 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
462 #define SSI_USE(n) SSI##n
464 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
468 ExQueryPoolUsage(OUT PULONG PagedPoolPages
,
469 OUT PULONG NonPagedPoolPages
,
470 OUT PULONG PagedPoolAllocs
,
471 OUT PULONG PagedPoolFrees
,
472 OUT PULONG PagedPoolLookasideHits
,
473 OUT PULONG NonPagedPoolAllocs
,
474 OUT PULONG NonPagedPoolFrees
,
475 OUT PULONG NonPagedPoolLookasideHits
);
477 /* Class 0 - Basic Information */
478 QSI_DEF(SystemBasicInformation
)
480 PSYSTEM_BASIC_INFORMATION Sbi
481 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
483 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
485 /* Check user buffer's size */
486 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
488 return STATUS_INFO_LENGTH_MISMATCH
;
491 RtlZeroMemory(Sbi
, Size
);
493 Sbi
->TimerResolution
= KeMaximumIncrement
;
494 Sbi
->PageSize
= PAGE_SIZE
;
495 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
496 Sbi
->LowestPhysicalPageNumber
= (ULONG
)MmLowestPhysicalPage
;
497 Sbi
->HighestPhysicalPageNumber
= (ULONG
)MmHighestPhysicalPage
;
498 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
499 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
500 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
501 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
502 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
504 return STATUS_SUCCESS
;
507 /* Class 1 - Processor Information */
508 QSI_DEF(SystemProcessorInformation
)
510 PSYSTEM_PROCESSOR_INFORMATION Spi
511 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
513 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
515 /* Check user buffer's size */
516 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
518 return STATUS_INFO_LENGTH_MISMATCH
;
520 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
521 Spi
->ProcessorLevel
= KeProcessorLevel
;
522 Spi
->ProcessorRevision
= KeProcessorRevision
;
524 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
526 DPRINT("Arch %u Level %u Rev 0x%x\n", Spi
->ProcessorArchitecture
,
527 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
529 return STATUS_SUCCESS
;
532 /* Class 2 - Performance Information */
533 QSI_DEF(SystemPerformanceInformation
)
535 ULONG IdleUser
, IdleKernel
;
536 PSYSTEM_PERFORMANCE_INFORMATION Spi
537 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
539 PEPROCESS TheIdleProcess
;
541 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
543 /* Check user buffer's size */
544 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
546 return STATUS_INFO_LENGTH_MISMATCH
;
549 TheIdleProcess
= PsIdleProcess
;
551 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
552 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
553 Spi
->IoReadTransferCount
= IoReadTransferCount
;
554 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
555 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
556 Spi
->IoReadOperationCount
= IoReadOperationCount
;
557 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
558 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
560 Spi
->AvailablePages
= (ULONG
)MmAvailablePages
;
562 * Add up all the used "Committed" memory + pagefile.
563 * Not sure this is right. 8^\
565 Spi
->CommittedPages
= MiMemoryConsumers
[MC_SYSTEM
].PagesUsed
+
566 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
567 MiMemoryConsumers
[MC_USER
].PagesUsed
+
570 * Add up the full system total + pagefile.
571 * All this make Taskmgr happy but not sure it is the right numbers.
572 * This too, fixes some of GlobalMemoryStatusEx numbers.
574 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
576 Spi
->PeakCommitment
= 0; /* FIXME */
577 Spi
->PageFaultCount
= 0; /* FIXME */
578 Spi
->CopyOnWriteCount
= 0; /* FIXME */
579 Spi
->TransitionCount
= 0; /* FIXME */
580 Spi
->CacheTransitionCount
= 0; /* FIXME */
581 Spi
->DemandZeroCount
= 0; /* FIXME */
582 Spi
->PageReadCount
= 0; /* FIXME */
583 Spi
->PageReadIoCount
= 0; /* FIXME */
584 Spi
->CacheReadCount
= 0; /* FIXME */
585 Spi
->CacheIoCount
= 0; /* FIXME */
586 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
587 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
588 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
589 Spi
->MappedWriteIoCount
= 0; /* FIXME */
591 Spi
->PagedPoolPages
= 0;
592 Spi
->NonPagedPoolPages
= 0;
593 Spi
->PagedPoolAllocs
= 0;
594 Spi
->PagedPoolFrees
= 0;
595 Spi
->PagedPoolLookasideHits
= 0;
596 Spi
->NonPagedPoolAllocs
= 0;
597 Spi
->NonPagedPoolFrees
= 0;
598 Spi
->NonPagedPoolLookasideHits
= 0;
599 ExQueryPoolUsage(&Spi
->PagedPoolPages
,
600 &Spi
->NonPagedPoolPages
,
601 &Spi
->PagedPoolAllocs
,
602 &Spi
->PagedPoolFrees
,
603 &Spi
->PagedPoolLookasideHits
,
604 &Spi
->NonPagedPoolAllocs
,
605 &Spi
->NonPagedPoolFrees
,
606 &Spi
->NonPagedPoolLookasideHits
);
607 Spi
->FreeSystemPtes
= 0; /* FIXME */
609 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
611 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
612 Spi
->Spare3Count
= 0; /* FIXME */
614 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
615 Spi
->ResidentPagedPoolPage
= 0; /* FIXME */
617 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
618 Spi
->CcFastReadNoWait
= 0; /* FIXME */
619 Spi
->CcFastReadWait
= 0; /* FIXME */
620 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
621 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
623 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
624 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
625 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
626 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
628 Spi
->CcMapDataNoWait
= 0; /* FIXME */
629 Spi
->CcMapDataWait
= 0; /* FIXME */
630 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
631 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
633 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
634 Spi
->CcPinReadNoWait
= 0; /* FIXME */
635 Spi
->CcPinReadWait
= 0; /* FIXME */
636 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
637 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
638 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
639 Spi
->CcCopyReadWait
= 0; /* FIXME */
640 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
641 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
643 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
644 Spi
->CcMdlReadWait
= 0; /* FIXME */
645 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
646 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
647 Spi
->CcReadAheadIos
= 0; /* FIXME */
648 Spi
->CcLazyWriteIos
= 0; /* FIXME */
649 Spi
->CcLazyWritePages
= 0; /* FIXME */
650 Spi
->CcDataFlushes
= 0; /* FIXME */
651 Spi
->CcDataPages
= 0; /* FIXME */
652 Spi
->ContextSwitches
= 0; /* FIXME */
653 Spi
->FirstLevelTbFills
= 0; /* FIXME */
654 Spi
->SecondLevelTbFills
= 0; /* FIXME */
655 Spi
->SystemCalls
= 0; /* FIXME */
657 return STATUS_SUCCESS
;
660 /* Class 3 - Time Of Day Information */
661 QSI_DEF(SystemTimeOfDayInformation
)
663 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
664 LARGE_INTEGER CurrentTime
;
666 /* Set amount of written information to 0 */
669 /* Check user buffer's size */
670 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
672 return STATUS_INFO_LENGTH_MISMATCH
;
675 /* Get current time */
676 KeQuerySystemTime(&CurrentTime
);
678 /* Zero local buffer */
679 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
681 /* Fill local time structure */
682 Sti
.BootTime
= KeBootTime
;
683 Sti
.CurrentTime
= CurrentTime
;
684 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
685 Sti
.TimeZoneId
= ExpTimeZoneId
;
688 /* Copy as much as requested by caller */
689 RtlCopyMemory(Buffer
, &Sti
, Size
);
691 /* Set amount of information we copied */
694 return STATUS_SUCCESS
;
697 /* Class 4 - Path Information */
698 QSI_DEF(SystemPathInformation
)
700 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
701 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
703 return STATUS_BREAKPOINT
;
706 /* Class 5 - Process Information */
707 QSI_DEF(SystemProcessInformation
)
709 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
710 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
711 PEPROCESS Process
= NULL
, SystemProcess
;
712 PETHREAD CurrentThread
;
713 ANSI_STRING ImageName
;
715 USHORT ImageNameMaximumLength
; // image name len in bytes
716 USHORT ImageNameLength
;
717 PLIST_ENTRY CurrentEntry
;
718 ULONG TotalSize
= 0, ThreadsCount
;
719 ULONG TotalUser
, TotalKernel
;
721 NTSTATUS Status
= STATUS_SUCCESS
;
722 PUNICODE_STRING ProcessImageName
;
724 BOOLEAN Overflow
= FALSE
;
728 /* scan the process list */
730 PSYSTEM_PROCESS_INFORMATION Spi
731 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
733 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
735 /* Check for overflow */
736 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
741 /* Zero user's buffer */
742 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
744 SystemProcess
= PsIdleProcess
;
745 Process
= SystemProcess
;
746 Current
= (PUCHAR
) Spi
;
750 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
752 if ((Process
->ProcessExiting
) &&
753 (Process
->Pcb
.Header
.SignalState
) &&
754 !(Process
->ActiveThreads
) &&
755 (IsListEmpty(&Process
->Pcb
.ThreadListHead
)))
757 DPRINT1("Process %p (%s:%p) is a zombie\n",
758 Process
, Process
->ImageFileName
, Process
->UniqueProcessId
);
760 ImageNameMaximumLength
= 0;
765 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
766 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
769 CurrentEntry
= CurrentEntry
->Flink
;
772 // size of the structure for every process
773 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
775 Status
= SeLocateProcessImageName(Process
, &ProcessImageName
);
777 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
779 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
780 /* Loop the file name*/
781 while (szSrc
> ProcessImageName
->Buffer
)
783 /* Make sure this isn't a backslash */
784 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
791 ImageNameLength
+= sizeof(WCHAR
);
795 if (!ImageNameLength
&& Process
!= PsIdleProcess
)
797 ImageNameLength
= (USHORT
)strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
800 /* Round up the image name length as NT does */
801 if (ImageNameLength
> 0)
802 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
804 ImageNameMaximumLength
= 0;
806 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
808 /* Check for overflow */
809 if (TotalSize
> Size
)
814 /* Fill system information */
817 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginnnig of the next structure
818 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
819 SpiCurrent
->CreateTime
= Process
->CreateTime
;
820 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
821 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
822 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
824 /* Copy name to the end of the struct */
825 if(Process
!= PsIdleProcess
)
829 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
831 /* Release the memory allocated by SeLocateProcessImageName */
832 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
836 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
837 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
842 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
845 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
846 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
847 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
848 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
849 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
850 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
851 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
852 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
853 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
854 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
855 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
856 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
857 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
858 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
859 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
860 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
861 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
863 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
864 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
866 CurrentThread
= (PETHREAD
)CONTAINING_RECORD(CurrentEntry
, KTHREAD
,
869 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
870 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
871 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
872 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
873 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
874 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
875 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
876 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
877 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
878 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
879 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
882 CurrentEntry
= CurrentEntry
->Flink
;
885 /* Query total user/kernel times of a process */
886 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
887 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
888 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
891 /* Handle idle process entry */
893 if (Process
== PsIdleProcess
) Process
= NULL
;
895 Process
= PsGetNextProcess(Process
);
897 if ((Process
== SystemProcess
) || (Process
== NULL
))
900 SpiCurrent
->NextEntryOffset
= 0;
904 Current
+= CurrentSize
+ ImageNameMaximumLength
;
905 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
908 ObDereferenceObject(Process
);
909 Status
= STATUS_SUCCESS
;
911 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
914 ObDereferenceObject(Process
);
915 Status
= _SEH2_GetExceptionCode();
920 Status
= STATUS_INFO_LENGTH_MISMATCH
;
922 *ReqSize
= TotalSize
;
926 /* Class 6 - Call Count Information */
927 QSI_DEF(SystemCallCountInformation
)
930 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
931 return STATUS_NOT_IMPLEMENTED
;
934 /* Class 7 - Device Information */
935 QSI_DEF(SystemDeviceInformation
)
937 PSYSTEM_DEVICE_INFORMATION Sdi
938 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
939 PCONFIGURATION_INFORMATION ConfigInfo
;
941 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
943 /* Check user buffer's size */
944 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
946 return STATUS_INFO_LENGTH_MISMATCH
;
949 ConfigInfo
= IoGetConfigurationInformation();
951 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
952 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
953 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
954 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
955 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
956 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
958 return STATUS_SUCCESS
;
961 /* Class 8 - Processor Performance Information */
962 QSI_DEF(SystemProcessorPerformanceInformation
)
964 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
965 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
971 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
973 /* Check user buffer's size */
976 return STATUS_INFO_LENGTH_MISMATCH
;
979 for (i
= 0; i
< KeNumberProcessors
; i
++)
981 /* Get the PRCB on this processor */
982 Prcb
= KiProcessorBlock
[i
];
984 /* Calculate total user and kernel times */
985 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
986 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
987 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
988 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
989 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
990 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
991 Spi
->InterruptCount
= Prcb
->InterruptCount
;
995 return STATUS_SUCCESS
;
998 /* Class 9 - Flags Information */
999 QSI_DEF(SystemFlagsInformation
)
1001 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1003 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
1004 return (STATUS_INFO_LENGTH_MISMATCH
);
1006 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
1007 return STATUS_SUCCESS
;
1010 SSI_DEF(SystemFlagsInformation
)
1012 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
1014 return STATUS_INFO_LENGTH_MISMATCH
;
1016 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
1017 return STATUS_SUCCESS
;
1020 /* Class 10 - Call Time Information */
1021 QSI_DEF(SystemCallTimeInformation
)
1024 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
1025 return STATUS_NOT_IMPLEMENTED
;
1028 /* Class 11 - Module Information */
1029 QSI_DEF(SystemModuleInformation
)
1033 /* Acquire system module list lock */
1034 KeEnterCriticalRegion();
1035 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource
, TRUE
);
1037 /* Call the generic handler with the system module list */
1038 Status
= ExpQueryModuleInformation(&PsLoadedModuleList
,
1039 &MmLoadedUserImageList
,
1040 (PRTL_PROCESS_MODULES
)Buffer
,
1044 /* Release list lock and return status */
1045 ExReleaseResourceLite(&PsLoadedModuleResource
);
1046 KeLeaveCriticalRegion();
1050 /* Class 12 - Locks Information */
1051 QSI_DEF(SystemLocksInformation
)
1054 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1055 return STATUS_NOT_IMPLEMENTED
;
1058 /* Class 13 - Stack Trace Information */
1059 QSI_DEF(SystemStackTraceInformation
)
1062 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1063 return STATUS_NOT_IMPLEMENTED
;
1066 /* Class 14 - Paged Pool Information */
1067 QSI_DEF(SystemPagedPoolInformation
)
1070 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1071 return STATUS_NOT_IMPLEMENTED
;
1074 /* Class 15 - Non Paged Pool Information */
1075 QSI_DEF(SystemNonPagedPoolInformation
)
1078 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1079 return STATUS_NOT_IMPLEMENTED
;
1083 /* Class 16 - Handle Information */
1084 QSI_DEF(SystemHandleInformation
)
1086 PEPROCESS pr
, syspr
;
1087 ULONG curSize
, i
= 0;
1090 PSYSTEM_HANDLE_INFORMATION Shi
=
1091 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1093 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1095 if (Size
< sizeof(SYSTEM_HANDLE_INFORMATION
))
1097 *ReqSize
= sizeof(SYSTEM_HANDLE_INFORMATION
);
1098 return STATUS_INFO_LENGTH_MISMATCH
;
1101 DPRINT("SystemHandleInformation 1\n");
1103 /* First Calc Size from Count. */
1104 syspr
= PsGetNextProcess(NULL
);
1109 hCount
= hCount
+ ObGetProcessHandleCount(pr
);
1110 pr
= PsGetNextProcess(pr
);
1112 if ((pr
== syspr
) || (pr
== NULL
)) break;
1114 while ((pr
!= syspr
) && (pr
!= NULL
));
1118 ObDereferenceObject(pr
);
1121 DPRINT("SystemHandleInformation 2\n");
1123 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
) +
1124 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1125 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
)));
1127 Shi
->NumberOfHandles
= hCount
;
1132 return (STATUS_INFO_LENGTH_MISMATCH
);
1135 DPRINT("SystemHandleInformation 3\n");
1137 /* Now get Handles from all processs. */
1138 syspr
= PsGetNextProcess(NULL
);
1143 int Count
= 0, HandleCount
;
1145 HandleCount
= ObGetProcessHandleCount(pr
);
1147 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1149 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG_PTR
)pr
->UniqueProcessId
;
1154 pr
= PsGetNextProcess(pr
);
1156 if ((pr
== syspr
) || (pr
== NULL
)) break;
1158 while ((pr
!= syspr
) && (pr
!= NULL
));
1160 if(pr
!= NULL
) ObDereferenceObject(pr
);
1162 DPRINT("SystemHandleInformation 4\n");
1163 return STATUS_SUCCESS
;
1167 SSI_DEF(SystemHandleInformation)
1170 return STATUS_SUCCESS;
1174 /* Class 17 - Information */
1175 QSI_DEF(SystemObjectInformation
)
1178 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1179 return STATUS_NOT_IMPLEMENTED
;
1182 /* Class 18 - Information */
1183 QSI_DEF(SystemPageFileInformation
)
1185 UNICODE_STRING FileName
; /* FIXME */
1186 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1188 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1190 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1191 return STATUS_INFO_LENGTH_MISMATCH
;
1194 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1197 Spfi
->NextEntryOffset
= 0;
1199 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1200 Spfi
->TotalInUse
= MiUsedSwapPages
;
1201 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1202 Spfi
->PageFileName
= FileName
;
1203 return STATUS_SUCCESS
;
1206 /* Class 19 - Vdm Instemul Information */
1207 QSI_DEF(SystemVdmInstemulInformation
)
1210 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1211 return STATUS_NOT_IMPLEMENTED
;
1214 /* Class 20 - Vdm Bop Information */
1215 QSI_DEF(SystemVdmBopInformation
)
1218 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1219 return STATUS_NOT_IMPLEMENTED
;
1222 /* Class 21 - File Cache Information */
1223 QSI_DEF(SystemFileCacheInformation
)
1225 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1227 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1229 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1230 return STATUS_INFO_LENGTH_MISMATCH
;
1233 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1235 /* Return the Byte size not the page size. */
1237 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1239 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1240 /* Taskmgr multiplies this one by page size right away */
1241 Sci
->CurrentSizeIncludingTransitionInPages
=
1242 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1243 /* system working set and standby pages. */
1244 Sci
->PageFaultCount
= 0; /* FIXME */
1245 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1246 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1248 return STATUS_SUCCESS
;
1251 SSI_DEF(SystemFileCacheInformation
)
1253 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1255 return STATUS_INFO_LENGTH_MISMATCH
;
1258 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1259 return STATUS_NOT_IMPLEMENTED
;
1262 /* Class 22 - Pool Tag Information */
1263 QSI_DEF(SystemPoolTagInformation
)
1265 if (Size
< sizeof(SYSTEM_POOLTAG_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
1266 return ExGetPoolTagInfo(Buffer
, Size
, ReqSize
);
1269 /* Class 23 - Interrupt Information for all processors */
1270 QSI_DEF(SystemInterruptInformation
)
1275 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1277 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1279 return STATUS_INFO_LENGTH_MISMATCH
;
1282 ti
= KeQueryTimeIncrement();
1284 for (i
= 0; i
< KeNumberProcessors
; i
++)
1286 Prcb
= KiProcessorBlock
[i
];
1287 sii
->ContextSwitches
= KeGetContextSwitches(Prcb
);
1288 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1289 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1290 sii
->TimeIncrement
= ti
;
1291 sii
->DpcBypassCount
= 0;
1292 sii
->ApcBypassCount
= 0;
1296 return STATUS_SUCCESS
;
1299 /* Class 24 - DPC Behaviour Information */
1300 QSI_DEF(SystemDpcBehaviourInformation
)
1303 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1304 return STATUS_NOT_IMPLEMENTED
;
1307 SSI_DEF(SystemDpcBehaviourInformation
)
1310 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1311 return STATUS_NOT_IMPLEMENTED
;
1314 /* Class 25 - Full Memory Information */
1315 QSI_DEF(SystemFullMemoryInformation
)
1317 PULONG Spi
= (PULONG
) Buffer
;
1319 PEPROCESS TheIdleProcess
;
1321 *ReqSize
= sizeof(ULONG
);
1323 if (sizeof(ULONG
) != Size
)
1325 return STATUS_INFO_LENGTH_MISMATCH
;
1328 DPRINT("SystemFullMemoryInformation\n");
1330 TheIdleProcess
= PsIdleProcess
;
1332 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
1333 TheIdleProcess
->UniqueProcessId
,
1334 TheIdleProcess
->Pcb
.KernelTime
,
1338 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1340 return STATUS_SUCCESS
;
1343 /* Class 26 - Load Image */
1344 SSI_DEF(SystemLoadGdiDriverInformation
)
1346 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1347 UNICODE_STRING ImageName
;
1349 PVOID SectionPointer
;
1350 ULONG_PTR EntryPoint
;
1353 PIMAGE_NT_HEADERS NtHeader
;
1356 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1358 /* Incorrect buffer length, fail */
1359 return STATUS_INFO_LENGTH_MISMATCH
;
1362 /* Only kernel mode can call this function */
1363 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1365 /* Load the driver */
1366 ImageName
= DriverInfo
->DriverName
;
1367 Status
= MmLoadSystemImage(&ImageName
,
1373 if (!NT_SUCCESS(Status
)) return Status
;
1375 /* Return the export pointer */
1376 DriverInfo
->ExportSectionPointer
=
1377 RtlImageDirectoryEntryToData(ImageBase
,
1379 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1382 /* Get the entrypoint */
1383 NtHeader
= RtlImageNtHeader(ImageBase
);
1384 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1385 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1387 /* Save other data */
1388 DriverInfo
->ImageAddress
= ImageBase
;
1389 DriverInfo
->SectionPointer
= SectionPointer
;
1390 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1391 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1394 return STATUS_SUCCESS
;
1397 /* Class 27 - Unload Image */
1398 SSI_DEF(SystemUnloadGdiDriverInformation
)
1400 PVOID
*SectionPointer
= Buffer
;
1403 if (Size
!= sizeof(PVOID
))
1405 /* Incorrect length, fail */
1406 return STATUS_INFO_LENGTH_MISMATCH
;
1409 /* Only kernel mode can call this function */
1410 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1412 /* Unload the image */
1413 MmUnloadSystemImage(*SectionPointer
);
1414 return STATUS_SUCCESS
;
1417 /* Class 28 - Time Adjustment Information */
1418 QSI_DEF(SystemTimeAdjustmentInformation
)
1420 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1421 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1423 /* Check if enough storage was provided */
1424 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1426 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1427 return STATUS_INFO_LENGTH_MISMATCH
;
1430 /* Give time values to our caller */
1431 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1432 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1433 TimeInfo
->Enable
= !KiTimeAdjustmentEnabled
;
1435 return STATUS_SUCCESS
;
1438 SSI_DEF(SystemTimeAdjustmentInformation
)
1440 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1441 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
=
1442 (PSYSTEM_SET_TIME_ADJUST_INFORMATION
)Buffer
;
1444 /* Check size of a buffer, it must match our expectations */
1445 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1446 return STATUS_INFO_LENGTH_MISMATCH
;
1448 /* Check who is calling */
1449 if (PreviousMode
!= KernelMode
)
1451 /* Check access rights */
1452 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1454 return STATUS_PRIVILEGE_NOT_HELD
;
1458 /* FIXME: behaviour suggests the member be named 'Disable' */
1459 if (TimeInfo
->Enable
)
1461 /* Disable time adjustment and set default value */
1462 KiTimeAdjustmentEnabled
= FALSE
;
1463 KeTimeAdjustment
= KeMaximumIncrement
;
1467 /* Check if a valid time adjustment value is given */
1468 if (TimeInfo
->TimeAdjustment
== 0) return STATUS_INVALID_PARAMETER_2
;
1470 /* Enable time adjustment and set the adjustment value */
1471 KiTimeAdjustmentEnabled
= TRUE
;
1472 KeTimeAdjustment
= TimeInfo
->TimeAdjustment
;
1475 return STATUS_SUCCESS
;
1478 /* Class 29 - Summary Memory Information */
1479 QSI_DEF(SystemSummaryMemoryInformation
)
1482 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1483 return STATUS_NOT_IMPLEMENTED
;
1486 /* Class 30 - Next Event Id Information */
1487 QSI_DEF(SystemNextEventIdInformation
)
1490 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1491 return STATUS_NOT_IMPLEMENTED
;
1494 /* Class 31 - Event Ids Information */
1495 QSI_DEF(SystemEventIdsInformation
)
1498 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1499 return STATUS_NOT_IMPLEMENTED
;
1502 /* Class 32 - Crash Dump Information */
1503 QSI_DEF(SystemCrashDumpInformation
)
1506 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1507 return STATUS_NOT_IMPLEMENTED
;
1510 /* Class 33 - Exception Information */
1511 QSI_DEF(SystemExceptionInformation
)
1513 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation
=
1514 (PSYSTEM_EXCEPTION_INFORMATION
)Buffer
;
1516 ULONG AlignmentFixupCount
= 0, ExceptionDispatchCount
= 0;
1517 ULONG FloatingEmulationCount
= 0, ByteWordEmulationCount
= 0;
1520 /* Check size of a buffer, it must match our expectations */
1521 if (sizeof(SYSTEM_EXCEPTION_INFORMATION
) != Size
)
1522 return STATUS_INFO_LENGTH_MISMATCH
;
1524 /* Sum up exception count information from all processors */
1525 for (i
= 0; i
< KeNumberProcessors
; i
++)
1527 Prcb
= KiProcessorBlock
[i
];
1530 AlignmentFixupCount
+= Prcb
->KeAlignmentFixupCount
;
1531 ExceptionDispatchCount
+= Prcb
->KeExceptionDispatchCount
;
1532 FloatingEmulationCount
+= Prcb
->KeFloatingEmulationCount
;
1536 /* Save information in user's buffer */
1537 ExceptionInformation
->AlignmentFixupCount
= AlignmentFixupCount
;
1538 ExceptionInformation
->ExceptionDispatchCount
= ExceptionDispatchCount
;
1539 ExceptionInformation
->FloatingEmulationCount
= FloatingEmulationCount
;
1540 ExceptionInformation
->ByteWordEmulationCount
= ByteWordEmulationCount
;
1542 return STATUS_SUCCESS
;
1545 /* Class 34 - Crash Dump State Information */
1546 QSI_DEF(SystemCrashDumpStateInformation
)
1549 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1550 return STATUS_NOT_IMPLEMENTED
;
1553 /* Class 35 - Kernel Debugger Information */
1554 QSI_DEF(SystemKernelDebuggerInformation
)
1556 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1558 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1559 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1561 return STATUS_INFO_LENGTH_MISMATCH
;
1564 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1565 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1567 return STATUS_SUCCESS
;
1570 /* Class 36 - Context Switch Information */
1571 QSI_DEF(SystemContextSwitchInformation
)
1573 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation
=
1574 (PSYSTEM_CONTEXT_SWITCH_INFORMATION
)Buffer
;
1575 ULONG ContextSwitches
;
1579 /* Check size of a buffer, it must match our expectations */
1580 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION
) != Size
)
1581 return STATUS_INFO_LENGTH_MISMATCH
;
1583 /* Calculate total value of context switches across all processors */
1584 ContextSwitches
= 0;
1585 for (i
= 0; i
< KeNumberProcessors
; i
++)
1587 Prcb
= KiProcessorBlock
[i
];
1590 ContextSwitches
+= KeGetContextSwitches(Prcb
);
1594 ContextSwitchInformation
->ContextSwitches
= ContextSwitches
;
1597 ContextSwitchInformation
->FindAny
= 0;
1598 ContextSwitchInformation
->FindLast
= 0;
1599 ContextSwitchInformation
->FindIdeal
= 0;
1600 ContextSwitchInformation
->IdleAny
= 0;
1601 ContextSwitchInformation
->IdleCurrent
= 0;
1602 ContextSwitchInformation
->IdleLast
= 0;
1603 ContextSwitchInformation
->IdleIdeal
= 0;
1604 ContextSwitchInformation
->PreemptAny
= 0;
1605 ContextSwitchInformation
->PreemptCurrent
= 0;
1606 ContextSwitchInformation
->PreemptLast
= 0;
1607 ContextSwitchInformation
->SwitchToIdle
= 0;
1609 return STATUS_SUCCESS
;
1612 /* Class 37 - Registry Quota Information */
1613 QSI_DEF(SystemRegistryQuotaInformation
)
1615 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1617 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1618 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1620 return STATUS_INFO_LENGTH_MISMATCH
;
1623 DPRINT1("Faking max registry size of 32 MB\n");
1624 srqi
->RegistryQuotaAllowed
= 0x2000000;
1625 srqi
->RegistryQuotaUsed
= 0x200000;
1626 srqi
->PagedPoolSize
= 0x200000;
1628 return STATUS_SUCCESS
;
1631 SSI_DEF(SystemRegistryQuotaInformation
)
1634 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1635 return STATUS_NOT_IMPLEMENTED
;
1638 /* Class 38 - Load And Call Image */
1639 SSI_DEF(SystemExtendServiceTableInformation
)
1641 UNICODE_STRING ImageName
;
1642 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1643 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1645 PIMAGE_NT_HEADERS NtHeader
;
1646 DRIVER_OBJECT Win32k
;
1647 PDRIVER_INITIALIZE DriverInit
;
1649 ULONG_PTR EntryPoint
;
1651 /* Validate the size */
1652 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1654 /* Check who is calling */
1655 if (PreviousMode
!= KernelMode
)
1657 static const UNICODE_STRING Win32kName
=
1658 RTL_CONSTANT_STRING(L
"\\SystemRoot\\System32\\win32k.sys");
1660 /* Make sure we can load drivers */
1661 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1663 /* FIXME: We can't, fail */
1664 return STATUS_PRIVILEGE_NOT_HELD
;
1669 /* Probe and copy the unicode string */
1670 ProbeForRead(Buffer
, sizeof(ImageName
), 1);
1671 ImageName
= *(PUNICODE_STRING
)Buffer
;
1673 /* Probe the string buffer */
1674 ProbeForRead(ImageName
.Buffer
, ImageName
.Length
, sizeof(WCHAR
));
1676 /* Check if we have the correct name (nothing else is allowed!) */
1677 if (!RtlEqualUnicodeString(&ImageName
, &Win32kName
, FALSE
))
1679 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD
);
1682 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1684 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1688 /* Recursively call the function, so that we are from kernel mode */
1689 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1691 sizeof(Win32kName
));
1694 /* Load the image */
1695 Status
= MmLoadSystemImage((PUNICODE_STRING
)Buffer
,
1699 (PVOID
)&ModuleObject
,
1702 if (!NT_SUCCESS(Status
)) return Status
;
1704 /* Get the headers */
1705 NtHeader
= RtlImageNtHeader(ImageBase
);
1709 MmUnloadSystemImage(ModuleObject
);
1710 return STATUS_INVALID_IMAGE_FORMAT
;
1713 /* Get the entrypoint */
1714 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1715 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1716 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1718 /* Create a dummy device */
1719 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1720 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1721 Win32k
.DriverStart
= ImageBase
;
1724 Status
= (DriverInit
)(&Win32k
, NULL
);
1725 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1727 /* Unload if we failed */
1728 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1732 /* Class 39 - Priority Separation */
1733 SSI_DEF(SystemPrioritySeperation
)
1736 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1737 return STATUS_NOT_IMPLEMENTED
;
1740 /* Class 40 - Plug Play Bus Information */
1741 QSI_DEF(SystemPlugPlayBusInformation
)
1744 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1745 return STATUS_NOT_IMPLEMENTED
;
1748 /* Class 41 - Dock Information */
1749 QSI_DEF(SystemDockInformation
)
1752 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1753 return STATUS_NOT_IMPLEMENTED
;
1756 /* Class 42 - Power Information */
1757 QSI_DEF(SystemPowerInformation
)
1760 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1761 return STATUS_NOT_IMPLEMENTED
;
1764 /* Class 43 - Processor Speed Information */
1765 QSI_DEF(SystemProcessorSpeedInformation
)
1768 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1769 return STATUS_NOT_IMPLEMENTED
;
1772 /* Class 44 - Current Time Zone Information */
1773 QSI_DEF(SystemCurrentTimeZoneInformation
)
1775 *ReqSize
= sizeof(TIME_ZONE_INFORMATION
);
1777 if (sizeof(TIME_ZONE_INFORMATION
) != Size
)
1779 return STATUS_INFO_LENGTH_MISMATCH
;
1782 /* Copy the time zone information struct */
1785 sizeof(TIME_ZONE_INFORMATION
));
1787 return STATUS_SUCCESS
;
1791 SSI_DEF(SystemCurrentTimeZoneInformation
)
1793 /* Check user buffer's size */
1794 if (Size
< sizeof(TIME_ZONE_INFORMATION
))
1796 return STATUS_INFO_LENGTH_MISMATCH
;
1799 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1803 /* Class 45 - Lookaside Information */
1804 QSI_DEF(SystemLookasideInformation
)
1807 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1808 return STATUS_NOT_IMPLEMENTED
;
1812 /* Class 46 - Set time slip event */
1813 SSI_DEF(SystemSetTimeSlipEvent
)
1816 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1817 return STATUS_NOT_IMPLEMENTED
;
1822 MmSessionCreate(OUT PULONG SessionId
);
1826 MmSessionDelete(IN ULONG SessionId
);
1828 /* Class 47 - Create a new session (TSE) */
1829 SSI_DEF(SystemCreateSession
)
1832 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1835 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
1837 if (PreviousMode
!= KernelMode
)
1839 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1841 return STATUS_PRIVILEGE_NOT_HELD
;
1845 Status
= MmSessionCreate(&SessionId
);
1846 if (NT_SUCCESS(Status
)) *(PULONG
)Buffer
= SessionId
;
1852 /* Class 48 - Delete an existing session (TSE) */
1853 SSI_DEF(SystemDeleteSession
)
1856 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1858 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
1860 if (PreviousMode
!= KernelMode
)
1862 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1864 return STATUS_PRIVILEGE_NOT_HELD
;
1868 SessionId
= *(PULONG
)Buffer
;
1870 return MmSessionDelete(SessionId
);
1874 /* Class 49 - UNKNOWN */
1875 QSI_DEF(SystemInvalidInfoClass4
)
1878 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1879 return STATUS_NOT_IMPLEMENTED
;
1883 /* Class 50 - System range start address */
1884 QSI_DEF(SystemRangeStartInformation
)
1886 /* Check user buffer's size */
1887 if (Size
!= sizeof(ULONG_PTR
)) return STATUS_INFO_LENGTH_MISMATCH
;
1889 *(PULONG_PTR
)Buffer
= (ULONG_PTR
)MmSystemRangeStart
;
1891 if (ReqSize
) *ReqSize
= sizeof(ULONG_PTR
);
1893 return STATUS_SUCCESS
;
1896 /* Class 51 - Driver verifier information */
1897 QSI_DEF(SystemVerifierInformation
)
1900 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1901 return STATUS_NOT_IMPLEMENTED
;
1905 SSI_DEF(SystemVerifierInformation
)
1908 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1909 return STATUS_NOT_IMPLEMENTED
;
1913 /* Class 52 - Add a driver verifier */
1914 SSI_DEF(SystemAddVerifier
)
1917 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1918 return STATUS_NOT_IMPLEMENTED
;
1922 /* Class 53 - A session's processes */
1923 QSI_DEF(SystemSessionProcessesInformation
)
1926 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1927 return STATUS_NOT_IMPLEMENTED
;
1931 /* Query/Set Calls Table */
1935 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1936 NTSTATUS (* Set
) (PVOID
,ULONG
);
1943 // XX unknown behaviour
1945 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1946 #define SI_QX(n) {QSI_USE(n),NULL}
1947 #define SI_XS(n) {NULL,SSI_USE(n)}
1948 #define SI_XX(n) {NULL,NULL}
1954 SI_QX(SystemBasicInformation
),
1955 SI_QX(SystemProcessorInformation
),
1956 SI_QX(SystemPerformanceInformation
),
1957 SI_QX(SystemTimeOfDayInformation
),
1958 SI_QX(SystemPathInformation
), /* should be SI_XX */
1959 SI_QX(SystemProcessInformation
), // aka SystemProcessesAndThreadsInformation
1960 SI_QX(SystemCallCountInformation
), // aka SystemCallCounts
1961 SI_QX(SystemDeviceInformation
), // aka SystemConfigurationInformation
1962 SI_QX(SystemProcessorPerformanceInformation
), // aka SystemProcessorTimes
1963 SI_QS(SystemFlagsInformation
), // aka SystemGlobalFlag
1964 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1965 SI_QX(SystemModuleInformation
),
1966 SI_QX(SystemLocksInformation
), // aka SystemLockInformation
1967 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1968 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1969 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1970 SI_QX(SystemHandleInformation
),
1971 SI_QX(SystemObjectInformation
),
1972 SI_QX(SystemPageFileInformation
), // aka SystemPagefileInformation
1973 SI_QX(SystemVdmInstemulInformation
), // aka SystemInstructionEmulationCounts
1974 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1975 SI_QS(SystemFileCacheInformation
), // aka SystemCacheInformation
1976 SI_QX(SystemPoolTagInformation
),
1977 SI_QX(SystemInterruptInformation
), // aka SystemProcessorStatistics
1978 SI_QS(SystemDpcBehaviourInformation
), // aka SystemDpcInformation
1979 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1980 SI_XS(SystemLoadGdiDriverInformation
), // correct: SystemLoadImage
1981 SI_XS(SystemUnloadGdiDriverInformation
), // correct: SystemUnloadImage
1982 SI_QS(SystemTimeAdjustmentInformation
), // aka SystemTimeAdjustment
1983 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1984 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1985 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */ // SystemPerformanceTraceInformation
1986 SI_QX(SystemCrashDumpInformation
),
1987 SI_QX(SystemExceptionInformation
),
1988 SI_QX(SystemCrashDumpStateInformation
),
1989 SI_QX(SystemKernelDebuggerInformation
),
1990 SI_QX(SystemContextSwitchInformation
),
1991 SI_QS(SystemRegistryQuotaInformation
),
1992 SI_XS(SystemExtendServiceTableInformation
), // correct: SystemLoadAndCallImage
1993 SI_XS(SystemPrioritySeperation
),
1994 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1995 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1996 SI_QX(SystemPowerInformation
), /* it should be SI_XX */ // SystemPowerInformationNative? SystemInvalidInfoClass2
1997 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1998 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */ // aka SystemTimeZoneInformation
1999 SI_QX(SystemLookasideInformation
),
2000 SI_XS(SystemSetTimeSlipEvent
),
2001 SI_XS(SystemCreateSession
),
2002 SI_XS(SystemDeleteSession
),
2003 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */ // SystemSessionInformation?
2004 SI_QX(SystemRangeStartInformation
),
2005 SI_QS(SystemVerifierInformation
),
2006 SI_XS(SystemAddVerifier
),
2007 SI_QX(SystemSessionProcessesInformation
)
2010 C_ASSERT(SystemBasicInformation
== 0);
2011 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
2012 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
2018 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2019 OUT PVOID SystemInformation
,
2021 OUT PULONG UnsafeResultLength
)
2023 KPROCESSOR_MODE PreviousMode
;
2024 ULONG ResultLength
= 0;
2025 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
2029 PreviousMode
= ExGetPreviousMode();
2033 if (PreviousMode
!= KernelMode
)
2035 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
2036 ProbeForWrite(SystemInformation
, Length
, 1);
2037 if (UnsafeResultLength
!= NULL
)
2038 ProbeForWriteUlong(UnsafeResultLength
);
2041 if (UnsafeResultLength
)
2042 *UnsafeResultLength
= 0;
2045 * Check if the request is valid.
2047 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2049 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2052 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
2055 * Hand the request to a subhandler.
2057 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
2061 /* Save the result length to the caller */
2062 if (UnsafeResultLength
)
2063 *UnsafeResultLength
= ResultLength
;
2066 _SEH2_EXCEPT(ExSystemExceptionFilter())
2068 FStatus
= _SEH2_GetExceptionCode();
2078 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2079 IN PVOID SystemInformation
,
2080 IN ULONG SystemInformationLength
)
2085 * If called from user mode, check
2086 * possible unsafe arguments.
2089 if (KernelMode
!= KeGetPreviousMode())
2093 // SystemInformation,
2103 * Check the request is valid.
2105 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
2106 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
2108 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
2111 * Hand the request to a subhandler.
2113 return CallQS
[SystemInformationClass
].Set(SystemInformation
,
2114 SystemInformationLength
);
2118 return STATUS_INVALID_INFO_CLASS
;
2123 NtFlushInstructionCache(IN HANDLE ProcessHandle
,
2124 IN PVOID BaseAddress
,
2125 IN ULONG NumberOfBytesToFlush
)
2129 #if defined(_M_IX86) || defined(_M_AMD64)
2131 #elif defined(_M_PPC)
2132 __asm__
__volatile__("tlbsync");
2133 #elif defined(_M_MIPS)
2134 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2136 #elif defined(_M_ARM)
2137 __asm__
__volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
2139 #error Unknown architecture
2141 return STATUS_SUCCESS
;
2146 NtGetCurrentProcessorNumber(VOID
)
2148 /* Just return the CPU */
2149 return KeGetCurrentProcessorNumber();
2155 #undef ExGetPreviousMode
2158 ExGetPreviousMode (VOID
)
2160 return KeGetPreviousMode();