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 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
27 IN PLIST_ENTRY UserModeList
,
28 OUT PRTL_PROCESS_MODULES Modules
,
30 OUT PULONG ReturnLength
)
32 NTSTATUS Status
= STATUS_SUCCESS
;
34 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
35 PLDR_DATA_TABLE_ENTRY LdrEntry
;
36 ANSI_STRING ModuleName
;
37 ULONG ModuleCount
= 0;
38 PLIST_ENTRY NextEntry
;
42 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
43 ModuleInfo
= &Modules
->Modules
[0];
45 /* Loop the kernel list */
46 NextEntry
= KernelModeList
->Flink
;
47 while (NextEntry
!= KernelModeList
)
50 LdrEntry
= CONTAINING_RECORD(NextEntry
,
54 /* Update size and check if we can manage one more entry */
55 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
56 if (Length
>= RequiredLength
)
59 ModuleInfo
->MappedBase
= NULL
;
60 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
61 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
62 ModuleInfo
->Flags
= LdrEntry
->Flags
;
63 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
64 ModuleInfo
->LoadOrderIndex
= (USHORT
)ModuleCount
;
65 ModuleInfo
->InitOrderIndex
= 0;
68 RtlInitEmptyAnsiString(&ModuleName
,
69 ModuleInfo
->FullPathName
,
70 sizeof(ModuleInfo
->FullPathName
));
73 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
74 &LdrEntry
->FullDllName
,
76 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
78 /* Calculate offset to name */
79 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
80 while ((p
> ModuleName
.Buffer
) && (*--p
))
82 /* Check if we found the separator */
83 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
85 /* We did, break out */
92 ModuleInfo
->OffsetToFileName
= (USHORT
)(p
- ModuleName
.Buffer
);
96 /* Return empty name */
97 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
98 ModuleInfo
->OffsetToFileName
= 0;
101 /* Go to the next module */
107 Status
= STATUS_INFO_LENGTH_MISMATCH
;
110 /* Update count and move to next entry */
112 NextEntry
= NextEntry
->Flink
;
115 /* Check if caller also wanted user modules */
119 DPRINT1("User-mode list not yet supported in ReactOS!\n");
122 /* Update return length */
123 if (ReturnLength
) *ReturnLength
= RequiredLength
;
125 /* Validate the length again */
126 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
128 /* Set the final count */
129 Modules
->NumberOfModules
= ModuleCount
;
133 /* Otherwise, we failed */
134 Status
= STATUS_INFO_LENGTH_MISMATCH
;
141 /* FUNCTIONS *****************************************************************/
148 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
152 ULONGLONG ScaledIdle
;
154 Prcb
= KeGetCurrentPrcb();
156 ScaledIdle
= (ULONGLONG
)Prcb
->IdleThread
->KernelTime
* 100;
157 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
159 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
169 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
171 PULONG ProcessorNumber
)
175 Prcb
= KeGetCurrentPrcb();
177 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
178 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
179 *ProcessorNumber
= KeGetCurrentProcessorNumber();
187 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
189 /* Quick check to see if it exists at all */
190 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
192 /* Return our support for it */
193 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
201 ExVerifySuite(SUITE_TYPE SuiteType
)
203 if (SuiteType
== Personal
) return TRUE
;
209 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
210 OUT PWSTR ValueBuffer
,
211 IN ULONG ValueBufferLength
,
212 IN OUT PULONG ReturnLength OPTIONAL
)
215 UNICODE_STRING WName
;
219 UNICODE_STRING WValue
;
220 KPROCESSOR_MODE PreviousMode
;
224 /* Check if the call came from user mode */
225 PreviousMode
= ExGetPreviousMode();
226 if (PreviousMode
!= KernelMode
)
230 /* Probe the input and output buffers */
231 ProbeForRead(VariableName
, sizeof(UNICODE_STRING
), sizeof(ULONG
));
232 ProbeForWrite(ValueBuffer
, ValueBufferLength
, sizeof(WCHAR
));
233 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
237 /* Return the exception code */
238 _SEH2_YIELD(return _SEH2_GetExceptionCode());
243 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
244 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
, PreviousMode
))
246 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
247 return STATUS_PRIVILEGE_NOT_HELD
;
250 /* Copy the name to kernel space if necessary */
251 Status
= ProbeAndCaptureUnicodeString(&WName
, PreviousMode
, VariableName
);
252 if (!NT_SUCCESS(Status
)) return Status
;
254 /* Convert the name to ANSI and release the captured UNICODE string */
255 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
256 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
257 if (!NT_SUCCESS(Status
)) return Status
;
259 /* Allocate a buffer for the ANSI environment variable */
260 AnsiValueBuffer
= ExAllocatePoolWithTag(NonPagedPool
, MAX_ENVVAL_SIZE
, 'rvnE');
261 if (AnsiValueBuffer
== NULL
)
263 RtlFreeAnsiString(&AName
);
264 return STATUS_INSUFFICIENT_RESOURCES
;
267 /* Get the environment variable and free the ANSI name */
268 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
271 RtlFreeAnsiString(&AName
);
273 /* Check if we had success */
274 if (Result
== ESUCCESS
)
276 /* Copy the result back to the caller. */
279 /* Initialize ANSI string from the result */
280 RtlInitAnsiString(&AValue
, AnsiValueBuffer
);
282 /* Initialize a UNICODE string from the callers buffer */
283 RtlInitEmptyUnicodeString(&WValue
, ValueBuffer
, (USHORT
)ValueBufferLength
);
285 /* Convert the result to UNICODE */
286 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, FALSE
);
288 if (ReturnLength
!= NULL
)
289 *ReturnLength
= WValue
.Length
;
291 _SEH2_EXCEPT(ExSystemExceptionFilter())
293 Status
= _SEH2_GetExceptionCode();
299 Status
= STATUS_UNSUCCESSFUL
;
302 /* Free the allocated ANSI value buffer */
303 ExFreePoolWithTag(AnsiValueBuffer
, 'rvnE');
311 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
312 IN PUNICODE_STRING Value
)
314 UNICODE_STRING CapturedName
, CapturedValue
;
315 ANSI_STRING AName
, AValue
;
316 KPROCESSOR_MODE PreviousMode
;
321 PreviousMode
= ExGetPreviousMode();
324 * Copy the strings to kernel space if necessary
326 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
329 if (NT_SUCCESS(Status
))
331 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
334 if (NT_SUCCESS(Status
))
337 * according to ntinternals the SeSystemEnvironmentName privilege is required!
339 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
343 * convert the strings to ANSI
345 Status
= RtlUnicodeStringToAnsiString(&AName
,
348 if (NT_SUCCESS(Status
))
350 Status
= RtlUnicodeStringToAnsiString(&AValue
,
353 if (NT_SUCCESS(Status
))
355 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
358 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
364 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
365 Status
= STATUS_PRIVILEGE_NOT_HELD
;
368 ReleaseCapturedUnicodeString(&CapturedValue
,
372 ReleaseCapturedUnicodeString(&CapturedName
,
381 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
383 IN ULONG BufferLength
)
386 return STATUS_NOT_IMPLEMENTED
;
391 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
392 IN LPGUID VendorGuid
,
394 IN OUT PULONG ReturnLength
,
395 IN OUT PULONG Attributes
)
398 return STATUS_NOT_IMPLEMENTED
;
403 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
404 IN LPGUID VendorGuid
)
407 return STATUS_NOT_IMPLEMENTED
;
410 /* --- Query/Set System Information --- */
413 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
414 * so the stack is popped only in one place on x86 platform.
416 #define QSI_USE(n) QSI##n
418 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
420 #define SSI_USE(n) SSI##n
422 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
426 ExQueryPoolUsage(OUT PULONG PagedPoolPages
,
427 OUT PULONG NonPagedPoolPages
,
428 OUT PULONG PagedPoolAllocs
,
429 OUT PULONG PagedPoolFrees
,
430 OUT PULONG PagedPoolLookasideHits
,
431 OUT PULONG NonPagedPoolAllocs
,
432 OUT PULONG NonPagedPoolFrees
,
433 OUT PULONG NonPagedPoolLookasideHits
);
435 /* Class 0 - Basic Information */
436 QSI_DEF(SystemBasicInformation
)
438 PSYSTEM_BASIC_INFORMATION Sbi
439 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
441 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
443 /* Check user buffer's size */
444 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
446 return STATUS_INFO_LENGTH_MISMATCH
;
449 RtlZeroMemory(Sbi
, Size
);
451 Sbi
->TimerResolution
= KeMaximumIncrement
;
452 Sbi
->PageSize
= PAGE_SIZE
;
453 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
454 Sbi
->LowestPhysicalPageNumber
= (ULONG
)MmLowestPhysicalPage
;
455 Sbi
->HighestPhysicalPageNumber
= (ULONG
)MmHighestPhysicalPage
;
456 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
457 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
458 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
459 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
460 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
462 return STATUS_SUCCESS
;
465 /* Class 1 - Processor Information */
466 QSI_DEF(SystemProcessorInformation
)
468 PSYSTEM_PROCESSOR_INFORMATION Spi
469 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
471 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
473 /* Check user buffer's size */
474 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
476 return STATUS_INFO_LENGTH_MISMATCH
;
478 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
479 Spi
->ProcessorLevel
= KeProcessorLevel
;
480 Spi
->ProcessorRevision
= KeProcessorRevision
;
482 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
484 DPRINT("Arch %u Level %u Rev 0x%x\n", Spi
->ProcessorArchitecture
,
485 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
487 return STATUS_SUCCESS
;
490 /* Class 2 - Performance Information */
491 QSI_DEF(SystemPerformanceInformation
)
493 ULONG IdleUser
, IdleKernel
;
494 PSYSTEM_PERFORMANCE_INFORMATION Spi
495 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
497 PEPROCESS TheIdleProcess
;
499 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
501 /* Check user buffer's size */
502 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
504 return STATUS_INFO_LENGTH_MISMATCH
;
507 TheIdleProcess
= PsIdleProcess
;
509 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
510 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
511 Spi
->IoReadTransferCount
= IoReadTransferCount
;
512 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
513 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
514 Spi
->IoReadOperationCount
= IoReadOperationCount
;
515 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
516 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
518 Spi
->AvailablePages
= (ULONG
)MmAvailablePages
;
520 * Add up all the used "Committed" memory + pagefile.
521 * Not sure this is right. 8^\
523 Spi
->CommittedPages
= MiMemoryConsumers
[MC_SYSTEM
].PagesUsed
+
524 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
525 MiMemoryConsumers
[MC_USER
].PagesUsed
+
528 * Add up the full system total + pagefile.
529 * All this make Taskmgr happy but not sure it is the right numbers.
530 * This too, fixes some of GlobalMemoryStatusEx numbers.
532 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
534 Spi
->PeakCommitment
= 0; /* FIXME */
535 Spi
->PageFaultCount
= 0; /* FIXME */
536 Spi
->CopyOnWriteCount
= 0; /* FIXME */
537 Spi
->TransitionCount
= 0; /* FIXME */
538 Spi
->CacheTransitionCount
= 0; /* FIXME */
539 Spi
->DemandZeroCount
= 0; /* FIXME */
540 Spi
->PageReadCount
= 0; /* FIXME */
541 Spi
->PageReadIoCount
= 0; /* FIXME */
542 Spi
->CacheReadCount
= 0; /* FIXME */
543 Spi
->CacheIoCount
= 0; /* FIXME */
544 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
545 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
546 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
547 Spi
->MappedWriteIoCount
= 0; /* FIXME */
549 Spi
->PagedPoolPages
= 0;
550 Spi
->NonPagedPoolPages
= 0;
551 Spi
->PagedPoolAllocs
= 0;
552 Spi
->PagedPoolFrees
= 0;
553 Spi
->PagedPoolLookasideHits
= 0;
554 Spi
->NonPagedPoolAllocs
= 0;
555 Spi
->NonPagedPoolFrees
= 0;
556 Spi
->NonPagedPoolLookasideHits
= 0;
557 ExQueryPoolUsage(&Spi
->PagedPoolPages
,
558 &Spi
->NonPagedPoolPages
,
559 &Spi
->PagedPoolAllocs
,
560 &Spi
->PagedPoolFrees
,
561 &Spi
->PagedPoolLookasideHits
,
562 &Spi
->NonPagedPoolAllocs
,
563 &Spi
->NonPagedPoolFrees
,
564 &Spi
->NonPagedPoolLookasideHits
);
565 Spi
->FreeSystemPtes
= 0; /* FIXME */
567 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
569 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
570 Spi
->Spare3Count
= 0; /* FIXME */
572 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
573 Spi
->ResidentPagedPoolPage
= 0; /* FIXME */
575 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
576 Spi
->CcFastReadNoWait
= 0; /* FIXME */
577 Spi
->CcFastReadWait
= 0; /* FIXME */
578 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
579 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
581 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
582 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
583 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
584 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
586 Spi
->CcMapDataNoWait
= 0; /* FIXME */
587 Spi
->CcMapDataWait
= 0; /* FIXME */
588 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
589 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
591 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
592 Spi
->CcPinReadNoWait
= 0; /* FIXME */
593 Spi
->CcPinReadWait
= 0; /* FIXME */
594 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
595 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
596 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
597 Spi
->CcCopyReadWait
= 0; /* FIXME */
598 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
599 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
601 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
602 Spi
->CcMdlReadWait
= 0; /* FIXME */
603 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
604 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
605 Spi
->CcReadAheadIos
= 0; /* FIXME */
606 Spi
->CcLazyWriteIos
= 0; /* FIXME */
607 Spi
->CcLazyWritePages
= 0; /* FIXME */
608 Spi
->CcDataFlushes
= 0; /* FIXME */
609 Spi
->CcDataPages
= 0; /* FIXME */
610 Spi
->ContextSwitches
= 0; /* FIXME */
611 Spi
->FirstLevelTbFills
= 0; /* FIXME */
612 Spi
->SecondLevelTbFills
= 0; /* FIXME */
613 Spi
->SystemCalls
= 0; /* FIXME */
615 return STATUS_SUCCESS
;
618 /* Class 3 - Time Of Day Information */
619 QSI_DEF(SystemTimeOfDayInformation
)
621 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
622 LARGE_INTEGER CurrentTime
;
624 /* Set amount of written information to 0 */
627 /* Check user buffer's size */
628 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
630 return STATUS_INFO_LENGTH_MISMATCH
;
633 /* Get current time */
634 KeQuerySystemTime(&CurrentTime
);
636 /* Zero local buffer */
637 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
639 /* Fill local time structure */
640 Sti
.BootTime
= KeBootTime
;
641 Sti
.CurrentTime
= CurrentTime
;
642 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
643 Sti
.TimeZoneId
= ExpTimeZoneId
;
646 /* Copy as much as requested by caller */
647 RtlCopyMemory(Buffer
, &Sti
, Size
);
649 /* Set amount of information we copied */
652 return STATUS_SUCCESS
;
655 /* Class 4 - Path Information */
656 QSI_DEF(SystemPathInformation
)
658 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
659 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
661 return STATUS_BREAKPOINT
;
664 /* Class 5 - Process Information */
665 QSI_DEF(SystemProcessInformation
)
667 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
668 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
669 PEPROCESS Process
= NULL
, SystemProcess
;
670 PETHREAD CurrentThread
;
671 ANSI_STRING ImageName
;
673 USHORT ImageNameMaximumLength
; // image name len in bytes
674 USHORT ImageNameLength
;
675 PLIST_ENTRY CurrentEntry
;
676 ULONG TotalSize
= 0, ThreadsCount
;
677 ULONG TotalUser
, TotalKernel
;
679 NTSTATUS Status
= STATUS_SUCCESS
;
680 PUNICODE_STRING ProcessImageName
;
682 BOOLEAN Overflow
= FALSE
;
686 /* scan the process list */
688 PSYSTEM_PROCESS_INFORMATION Spi
689 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
691 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
693 /* Check for overflow */
694 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
699 /* Zero user's buffer */
700 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
702 SystemProcess
= PsIdleProcess
;
703 Process
= SystemProcess
;
704 Current
= (PUCHAR
) Spi
;
708 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
710 if ((Process
->ProcessExiting
) &&
711 (Process
->Pcb
.Header
.SignalState
) &&
712 !(Process
->ActiveThreads
) &&
713 (IsListEmpty(&Process
->Pcb
.ThreadListHead
)))
715 DPRINT1("Process %p (%s:%p) is a zombie\n",
716 Process
, Process
->ImageFileName
, Process
->UniqueProcessId
);
718 ImageNameMaximumLength
= 0;
723 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
724 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
727 CurrentEntry
= CurrentEntry
->Flink
;
730 // size of the structure for every process
731 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
733 Status
= SeLocateProcessImageName(Process
, &ProcessImageName
);
735 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
737 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
738 /* Loop the file name*/
739 while (szSrc
> ProcessImageName
->Buffer
)
741 /* Make sure this isn't a backslash */
742 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
749 ImageNameLength
+= sizeof(WCHAR
);
753 if (!ImageNameLength
&& Process
!= PsIdleProcess
)
755 ImageNameLength
= (USHORT
)strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
758 /* Round up the image name length as NT does */
759 if (ImageNameLength
> 0)
760 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
762 ImageNameMaximumLength
= 0;
764 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
766 /* Check for overflow */
767 if (TotalSize
> Size
)
772 /* Fill system information */
775 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginnnig of the next structure
776 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
777 SpiCurrent
->CreateTime
= Process
->CreateTime
;
778 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
779 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
780 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
782 /* Copy name to the end of the struct */
783 if(Process
!= PsIdleProcess
)
787 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
789 /* Release the memory allocated by SeLocateProcessImageName */
790 ExFreePoolWithTag(ProcessImageName
, TAG_SEPA
);
794 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
795 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
800 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
803 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
804 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
805 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
806 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
807 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
808 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
809 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
810 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
811 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
812 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
813 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
814 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
815 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
816 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
817 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
818 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
819 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
821 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
822 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
824 CurrentThread
= (PETHREAD
)CONTAINING_RECORD(CurrentEntry
, KTHREAD
,
827 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
828 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
829 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
830 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
831 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
832 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
833 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
834 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
835 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
836 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
837 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
840 CurrentEntry
= CurrentEntry
->Flink
;
843 /* Query total user/kernel times of a process */
844 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
845 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
846 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
849 /* Handle idle process entry */
851 if (Process
== PsIdleProcess
) Process
= NULL
;
853 Process
= PsGetNextProcess(Process
);
855 if ((Process
== SystemProcess
) || (Process
== NULL
))
858 SpiCurrent
->NextEntryOffset
= 0;
862 Current
+= CurrentSize
+ ImageNameMaximumLength
;
863 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
866 ObDereferenceObject(Process
);
867 Status
= STATUS_SUCCESS
;
869 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
872 ObDereferenceObject(Process
);
873 Status
= _SEH2_GetExceptionCode();
878 Status
= STATUS_INFO_LENGTH_MISMATCH
;
880 *ReqSize
= TotalSize
;
884 /* Class 6 - Call Count Information */
885 QSI_DEF(SystemCallCountInformation
)
888 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
889 return STATUS_NOT_IMPLEMENTED
;
892 /* Class 7 - Device Information */
893 QSI_DEF(SystemDeviceInformation
)
895 PSYSTEM_DEVICE_INFORMATION Sdi
896 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
897 PCONFIGURATION_INFORMATION ConfigInfo
;
899 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
901 /* Check user buffer's size */
902 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
904 return STATUS_INFO_LENGTH_MISMATCH
;
907 ConfigInfo
= IoGetConfigurationInformation();
909 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
910 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
911 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
912 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
913 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
914 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
916 return STATUS_SUCCESS
;
919 /* Class 8 - Processor Performance Information */
920 QSI_DEF(SystemProcessorPerformanceInformation
)
922 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
923 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
929 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
931 /* Check user buffer's size */
934 return STATUS_INFO_LENGTH_MISMATCH
;
937 for (i
= 0; i
< KeNumberProcessors
; i
++)
939 /* Get the PRCB on this processor */
940 Prcb
= KiProcessorBlock
[i
];
942 /* Calculate total user and kernel times */
943 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
944 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
945 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
946 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
947 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
948 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
949 Spi
->InterruptCount
= Prcb
->InterruptCount
;
953 return STATUS_SUCCESS
;
956 /* Class 9 - Flags Information */
957 QSI_DEF(SystemFlagsInformation
)
959 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
961 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
962 return (STATUS_INFO_LENGTH_MISMATCH
);
964 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
965 return STATUS_SUCCESS
;
968 SSI_DEF(SystemFlagsInformation
)
970 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
972 return STATUS_INFO_LENGTH_MISMATCH
;
974 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
975 return STATUS_SUCCESS
;
978 /* Class 10 - Call Time Information */
979 QSI_DEF(SystemCallTimeInformation
)
982 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
983 return STATUS_NOT_IMPLEMENTED
;
986 /* Class 11 - Module Information */
987 QSI_DEF(SystemModuleInformation
)
991 /* Acquire system module list lock */
992 KeEnterCriticalRegion();
993 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource
, TRUE
);
995 /* Call the generic handler with the system module list */
996 Status
= ExpQueryModuleInformation(&PsLoadedModuleList
,
997 &MmLoadedUserImageList
,
998 (PRTL_PROCESS_MODULES
)Buffer
,
1002 /* Release list lock and return status */
1003 ExReleaseResourceLite(&PsLoadedModuleResource
);
1004 KeLeaveCriticalRegion();
1008 /* Class 12 - Locks Information */
1009 QSI_DEF(SystemLocksInformation
)
1012 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1013 return STATUS_NOT_IMPLEMENTED
;
1016 /* Class 13 - Stack Trace Information */
1017 QSI_DEF(SystemStackTraceInformation
)
1020 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1021 return STATUS_NOT_IMPLEMENTED
;
1024 /* Class 14 - Paged Pool Information */
1025 QSI_DEF(SystemPagedPoolInformation
)
1028 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1029 return STATUS_NOT_IMPLEMENTED
;
1032 /* Class 15 - Non Paged Pool Information */
1033 QSI_DEF(SystemNonPagedPoolInformation
)
1036 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1037 return STATUS_NOT_IMPLEMENTED
;
1041 /* Class 16 - Handle Information */
1042 QSI_DEF(SystemHandleInformation
)
1044 PEPROCESS pr
, syspr
;
1045 ULONG curSize
, i
= 0;
1048 PSYSTEM_HANDLE_INFORMATION Shi
=
1049 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1051 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1053 if (Size
< sizeof(SYSTEM_HANDLE_INFORMATION
))
1055 *ReqSize
= sizeof(SYSTEM_HANDLE_INFORMATION
);
1056 return STATUS_INFO_LENGTH_MISMATCH
;
1059 DPRINT("SystemHandleInformation 1\n");
1061 /* First Calc Size from Count. */
1062 syspr
= PsGetNextProcess(NULL
);
1067 hCount
= hCount
+ ObGetProcessHandleCount(pr
);
1068 pr
= PsGetNextProcess(pr
);
1070 if ((pr
== syspr
) || (pr
== NULL
)) break;
1072 while ((pr
!= syspr
) && (pr
!= NULL
));
1076 ObDereferenceObject(pr
);
1079 DPRINT("SystemHandleInformation 2\n");
1081 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
) +
1082 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1083 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
)));
1085 Shi
->NumberOfHandles
= hCount
;
1090 return (STATUS_INFO_LENGTH_MISMATCH
);
1093 DPRINT("SystemHandleInformation 3\n");
1095 /* Now get Handles from all processs. */
1096 syspr
= PsGetNextProcess(NULL
);
1101 int Count
= 0, HandleCount
;
1103 HandleCount
= ObGetProcessHandleCount(pr
);
1105 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1107 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG_PTR
)pr
->UniqueProcessId
;
1112 pr
= PsGetNextProcess(pr
);
1114 if ((pr
== syspr
) || (pr
== NULL
)) break;
1116 while ((pr
!= syspr
) && (pr
!= NULL
));
1118 if(pr
!= NULL
) ObDereferenceObject(pr
);
1120 DPRINT("SystemHandleInformation 4\n");
1121 return STATUS_SUCCESS
;
1125 SSI_DEF(SystemHandleInformation)
1128 return STATUS_SUCCESS;
1132 /* Class 17 - Information */
1133 QSI_DEF(SystemObjectInformation
)
1136 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1137 return STATUS_NOT_IMPLEMENTED
;
1140 /* Class 18 - Information */
1141 QSI_DEF(SystemPageFileInformation
)
1143 UNICODE_STRING FileName
; /* FIXME */
1144 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1146 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1148 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1149 return STATUS_INFO_LENGTH_MISMATCH
;
1152 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1155 Spfi
->NextEntryOffset
= 0;
1157 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1158 Spfi
->TotalInUse
= MiUsedSwapPages
;
1159 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1160 Spfi
->PageFileName
= FileName
;
1161 return STATUS_SUCCESS
;
1164 /* Class 19 - Vdm Instemul Information */
1165 QSI_DEF(SystemVdmInstemulInformation
)
1168 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1169 return STATUS_NOT_IMPLEMENTED
;
1172 /* Class 20 - Vdm Bop Information */
1173 QSI_DEF(SystemVdmBopInformation
)
1176 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1177 return STATUS_NOT_IMPLEMENTED
;
1180 /* Class 21 - File Cache Information */
1181 QSI_DEF(SystemFileCacheInformation
)
1183 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1185 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1187 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1188 return STATUS_INFO_LENGTH_MISMATCH
;
1191 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1193 /* Return the Byte size not the page size. */
1195 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1197 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1198 /* Taskmgr multiplies this one by page size right away */
1199 Sci
->CurrentSizeIncludingTransitionInPages
=
1200 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1201 /* system working set and standby pages. */
1202 Sci
->PageFaultCount
= 0; /* FIXME */
1203 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1204 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1206 return STATUS_SUCCESS
;
1209 SSI_DEF(SystemFileCacheInformation
)
1211 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1213 return STATUS_INFO_LENGTH_MISMATCH
;
1216 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1217 return STATUS_NOT_IMPLEMENTED
;
1220 /* Class 22 - Pool Tag Information */
1221 QSI_DEF(SystemPoolTagInformation
)
1223 if (Size
< sizeof(SYSTEM_POOLTAG_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
1224 return ExGetPoolTagInfo(Buffer
, Size
, ReqSize
);
1227 /* Class 23 - Interrupt Information for all processors */
1228 QSI_DEF(SystemInterruptInformation
)
1233 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1235 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1237 return STATUS_INFO_LENGTH_MISMATCH
;
1240 ti
= KeQueryTimeIncrement();
1242 for (i
= 0; i
< KeNumberProcessors
; i
++)
1244 Prcb
= KiProcessorBlock
[i
];
1245 sii
->ContextSwitches
= KeGetContextSwitches(Prcb
);
1246 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1247 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1248 sii
->TimeIncrement
= ti
;
1249 sii
->DpcBypassCount
= 0;
1250 sii
->ApcBypassCount
= 0;
1254 return STATUS_SUCCESS
;
1257 /* Class 24 - DPC Behaviour Information */
1258 QSI_DEF(SystemDpcBehaviourInformation
)
1261 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1262 return STATUS_NOT_IMPLEMENTED
;
1265 SSI_DEF(SystemDpcBehaviourInformation
)
1268 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1269 return STATUS_NOT_IMPLEMENTED
;
1272 /* Class 25 - Full Memory Information */
1273 QSI_DEF(SystemFullMemoryInformation
)
1275 PULONG Spi
= (PULONG
) Buffer
;
1277 PEPROCESS TheIdleProcess
;
1279 *ReqSize
= sizeof(ULONG
);
1281 if (sizeof(ULONG
) != Size
)
1283 return STATUS_INFO_LENGTH_MISMATCH
;
1286 DPRINT("SystemFullMemoryInformation\n");
1288 TheIdleProcess
= PsIdleProcess
;
1290 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
1291 TheIdleProcess
->UniqueProcessId
,
1292 TheIdleProcess
->Pcb
.KernelTime
,
1296 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1298 return STATUS_SUCCESS
;
1301 /* Class 26 - Load Image */
1302 SSI_DEF(SystemLoadGdiDriverInformation
)
1304 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1305 UNICODE_STRING ImageName
;
1307 PVOID SectionPointer
;
1308 ULONG_PTR EntryPoint
;
1311 PIMAGE_NT_HEADERS NtHeader
;
1314 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1316 /* Incorrect buffer length, fail */
1317 return STATUS_INFO_LENGTH_MISMATCH
;
1320 /* Only kernel mode can call this function */
1321 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1323 /* Load the driver */
1324 ImageName
= DriverInfo
->DriverName
;
1325 Status
= MmLoadSystemImage(&ImageName
,
1331 if (!NT_SUCCESS(Status
)) return Status
;
1333 /* Return the export pointer */
1334 DriverInfo
->ExportSectionPointer
=
1335 RtlImageDirectoryEntryToData(ImageBase
,
1337 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1340 /* Get the entrypoint */
1341 NtHeader
= RtlImageNtHeader(ImageBase
);
1342 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1343 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1345 /* Save other data */
1346 DriverInfo
->ImageAddress
= ImageBase
;
1347 DriverInfo
->SectionPointer
= SectionPointer
;
1348 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1349 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1352 return STATUS_SUCCESS
;
1355 /* Class 27 - Unload Image */
1356 SSI_DEF(SystemUnloadGdiDriverInformation
)
1358 PVOID SectionPointer
= Buffer
;
1361 if (Size
!= sizeof(PVOID
))
1363 /* Incorrect length, fail */
1364 return STATUS_INFO_LENGTH_MISMATCH
;
1367 /* Only kernel mode can call this function */
1368 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1370 /* Unload the image */
1371 MmUnloadSystemImage(SectionPointer
);
1372 return STATUS_SUCCESS
;
1375 /* Class 28 - Time Adjustment Information */
1376 QSI_DEF(SystemTimeAdjustmentInformation
)
1378 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1379 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1381 /* Check if enough storage was provided */
1382 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1384 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1385 return STATUS_INFO_LENGTH_MISMATCH
;
1388 /* Give time values to our caller */
1389 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1390 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1391 TimeInfo
->Enable
= !KiTimeAdjustmentEnabled
;
1393 return STATUS_SUCCESS
;
1396 SSI_DEF(SystemTimeAdjustmentInformation
)
1398 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1399 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
=
1400 (PSYSTEM_SET_TIME_ADJUST_INFORMATION
)Buffer
;
1402 /* Check size of a buffer, it must match our expectations */
1403 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1404 return STATUS_INFO_LENGTH_MISMATCH
;
1406 /* Check who is calling */
1407 if (PreviousMode
!= KernelMode
)
1409 /* Check access rights */
1410 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1412 return STATUS_PRIVILEGE_NOT_HELD
;
1416 /* FIXME: behaviour suggests the member be named 'Disable' */
1417 if (TimeInfo
->Enable
)
1419 /* Disable time adjustment and set default value */
1420 KiTimeAdjustmentEnabled
= FALSE
;
1421 KeTimeAdjustment
= KeMaximumIncrement
;
1425 /* Check if a valid time adjustment value is given */
1426 if (TimeInfo
->TimeAdjustment
== 0) return STATUS_INVALID_PARAMETER_2
;
1428 /* Enable time adjustment and set the adjustment value */
1429 KiTimeAdjustmentEnabled
= TRUE
;
1430 KeTimeAdjustment
= TimeInfo
->TimeAdjustment
;
1433 return STATUS_SUCCESS
;
1436 /* Class 29 - Summary Memory Information */
1437 QSI_DEF(SystemSummaryMemoryInformation
)
1440 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1441 return STATUS_NOT_IMPLEMENTED
;
1444 /* Class 30 - Next Event Id Information */
1445 QSI_DEF(SystemNextEventIdInformation
)
1448 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1449 return STATUS_NOT_IMPLEMENTED
;
1452 /* Class 31 - Event Ids Information */
1453 QSI_DEF(SystemEventIdsInformation
)
1456 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1457 return STATUS_NOT_IMPLEMENTED
;
1460 /* Class 32 - Crash Dump Information */
1461 QSI_DEF(SystemCrashDumpInformation
)
1464 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1465 return STATUS_NOT_IMPLEMENTED
;
1468 /* Class 33 - Exception Information */
1469 QSI_DEF(SystemExceptionInformation
)
1471 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation
=
1472 (PSYSTEM_EXCEPTION_INFORMATION
)Buffer
;
1474 ULONG AlignmentFixupCount
= 0, ExceptionDispatchCount
= 0;
1475 ULONG FloatingEmulationCount
= 0, ByteWordEmulationCount
= 0;
1478 /* Check size of a buffer, it must match our expectations */
1479 if (sizeof(SYSTEM_EXCEPTION_INFORMATION
) != Size
)
1480 return STATUS_INFO_LENGTH_MISMATCH
;
1482 /* Sum up exception count information from all processors */
1483 for (i
= 0; i
< KeNumberProcessors
; i
++)
1485 Prcb
= KiProcessorBlock
[i
];
1488 AlignmentFixupCount
+= Prcb
->KeAlignmentFixupCount
;
1489 ExceptionDispatchCount
+= Prcb
->KeExceptionDispatchCount
;
1490 FloatingEmulationCount
+= Prcb
->KeFloatingEmulationCount
;
1494 /* Save information in user's buffer */
1495 ExceptionInformation
->AlignmentFixupCount
= AlignmentFixupCount
;
1496 ExceptionInformation
->ExceptionDispatchCount
= ExceptionDispatchCount
;
1497 ExceptionInformation
->FloatingEmulationCount
= FloatingEmulationCount
;
1498 ExceptionInformation
->ByteWordEmulationCount
= ByteWordEmulationCount
;
1500 return STATUS_SUCCESS
;
1503 /* Class 34 - Crash Dump State Information */
1504 QSI_DEF(SystemCrashDumpStateInformation
)
1507 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1508 return STATUS_NOT_IMPLEMENTED
;
1511 /* Class 35 - Kernel Debugger Information */
1512 QSI_DEF(SystemKernelDebuggerInformation
)
1514 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1516 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1517 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1519 return STATUS_INFO_LENGTH_MISMATCH
;
1522 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1523 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1525 return STATUS_SUCCESS
;
1528 /* Class 36 - Context Switch Information */
1529 QSI_DEF(SystemContextSwitchInformation
)
1531 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation
=
1532 (PSYSTEM_CONTEXT_SWITCH_INFORMATION
)Buffer
;
1533 ULONG ContextSwitches
;
1537 /* Check size of a buffer, it must match our expectations */
1538 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION
) != Size
)
1539 return STATUS_INFO_LENGTH_MISMATCH
;
1541 /* Calculate total value of context switches across all processors */
1542 ContextSwitches
= 0;
1543 for (i
= 0; i
< KeNumberProcessors
; i
++)
1545 Prcb
= KiProcessorBlock
[i
];
1548 ContextSwitches
+= KeGetContextSwitches(Prcb
);
1552 ContextSwitchInformation
->ContextSwitches
= ContextSwitches
;
1555 ContextSwitchInformation
->FindAny
= 0;
1556 ContextSwitchInformation
->FindLast
= 0;
1557 ContextSwitchInformation
->FindIdeal
= 0;
1558 ContextSwitchInformation
->IdleAny
= 0;
1559 ContextSwitchInformation
->IdleCurrent
= 0;
1560 ContextSwitchInformation
->IdleLast
= 0;
1561 ContextSwitchInformation
->IdleIdeal
= 0;
1562 ContextSwitchInformation
->PreemptAny
= 0;
1563 ContextSwitchInformation
->PreemptCurrent
= 0;
1564 ContextSwitchInformation
->PreemptLast
= 0;
1565 ContextSwitchInformation
->SwitchToIdle
= 0;
1567 return STATUS_SUCCESS
;
1570 /* Class 37 - Registry Quota Information */
1571 QSI_DEF(SystemRegistryQuotaInformation
)
1573 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1575 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1576 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1578 return STATUS_INFO_LENGTH_MISMATCH
;
1581 DPRINT1("Faking max registry size of 32 MB\n");
1582 srqi
->RegistryQuotaAllowed
= 0x2000000;
1583 srqi
->RegistryQuotaUsed
= 0x200000;
1584 srqi
->PagedPoolSize
= 0x200000;
1586 return STATUS_SUCCESS
;
1589 SSI_DEF(SystemRegistryQuotaInformation
)
1592 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1593 return STATUS_NOT_IMPLEMENTED
;
1596 /* Class 38 - Load And Call Image */
1597 SSI_DEF(SystemExtendServiceTableInformation
)
1599 UNICODE_STRING ImageName
;
1600 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1601 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1603 PIMAGE_NT_HEADERS NtHeader
;
1604 DRIVER_OBJECT Win32k
;
1605 PDRIVER_INITIALIZE DriverInit
;
1607 ULONG_PTR EntryPoint
;
1609 /* Validate the size */
1610 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1612 /* Check who is calling */
1613 if (PreviousMode
!= KernelMode
)
1615 static const UNICODE_STRING Win32kName
=
1616 RTL_CONSTANT_STRING(L
"\\SystemRoot\\System32\\win32k.sys");
1618 /* Make sure we can load drivers */
1619 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1621 /* FIXME: We can't, fail */
1622 return STATUS_PRIVILEGE_NOT_HELD
;
1627 /* Probe and copy the unicode string */
1628 ProbeForRead(Buffer
, sizeof(ImageName
), 1);
1629 ImageName
= *(PUNICODE_STRING
)Buffer
;
1631 /* Probe the string buffer */
1632 ProbeForRead(ImageName
.Buffer
, ImageName
.Length
, sizeof(WCHAR
));
1634 /* Check if we have the correct name (nothing else is allowed!) */
1635 if (!RtlEqualUnicodeString(&ImageName
, &Win32kName
, FALSE
))
1637 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD
);
1640 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1642 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1646 /* Recursively call the function, so that we are from kernel mode */
1647 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1649 sizeof(Win32kName
));
1652 /* Load the image */
1653 Status
= MmLoadSystemImage((PUNICODE_STRING
)Buffer
,
1657 (PVOID
)&ModuleObject
,
1660 if (!NT_SUCCESS(Status
)) return Status
;
1662 /* Get the headers */
1663 NtHeader
= RtlImageNtHeader(ImageBase
);
1667 MmUnloadSystemImage(ModuleObject
);
1668 return STATUS_INVALID_IMAGE_FORMAT
;
1671 /* Get the entrypoint */
1672 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1673 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1674 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1676 /* Create a dummy device */
1677 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1678 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1679 Win32k
.DriverStart
= ImageBase
;
1682 Status
= (DriverInit
)(&Win32k
, NULL
);
1683 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1684 __debugbreak();__debugbreak();
1685 /* Unload if we failed */
1686 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1690 /* Class 39 - Priority Separation */
1691 SSI_DEF(SystemPrioritySeperation
)
1694 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1695 return STATUS_NOT_IMPLEMENTED
;
1698 /* Class 40 - Plug Play Bus Information */
1699 QSI_DEF(SystemPlugPlayBusInformation
)
1702 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1703 return STATUS_NOT_IMPLEMENTED
;
1706 /* Class 41 - Dock Information */
1707 QSI_DEF(SystemDockInformation
)
1710 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1711 return STATUS_NOT_IMPLEMENTED
;
1714 /* Class 42 - Power Information */
1715 QSI_DEF(SystemPowerInformation
)
1718 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1719 return STATUS_NOT_IMPLEMENTED
;
1722 /* Class 43 - Processor Speed Information */
1723 QSI_DEF(SystemProcessorSpeedInformation
)
1726 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1727 return STATUS_NOT_IMPLEMENTED
;
1730 /* Class 44 - Current Time Zone Information */
1731 QSI_DEF(SystemCurrentTimeZoneInformation
)
1733 *ReqSize
= sizeof(TIME_ZONE_INFORMATION
);
1735 if (sizeof(TIME_ZONE_INFORMATION
) != Size
)
1737 return STATUS_INFO_LENGTH_MISMATCH
;
1740 /* Copy the time zone information struct */
1743 sizeof(TIME_ZONE_INFORMATION
));
1745 return STATUS_SUCCESS
;
1749 SSI_DEF(SystemCurrentTimeZoneInformation
)
1751 /* Check user buffer's size */
1752 if (Size
< sizeof(TIME_ZONE_INFORMATION
))
1754 return STATUS_INFO_LENGTH_MISMATCH
;
1757 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1761 /* Class 45 - Lookaside Information */
1762 QSI_DEF(SystemLookasideInformation
)
1765 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1766 return STATUS_NOT_IMPLEMENTED
;
1770 /* Class 46 - Set time slip event */
1771 SSI_DEF(SystemSetTimeSlipEvent
)
1774 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1775 return STATUS_NOT_IMPLEMENTED
;
1780 MmSessionCreate(OUT PULONG SessionId
);
1784 MmSessionDelete(IN ULONG SessionId
);
1786 /* Class 47 - Create a new session (TSE) */
1787 SSI_DEF(SystemCreateSession
)
1790 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1793 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
1795 if (PreviousMode
!= KernelMode
)
1797 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1799 return STATUS_PRIVILEGE_NOT_HELD
;
1803 Status
= MmSessionCreate(&SessionId
);
1804 if (NT_SUCCESS(Status
)) *(PULONG
)Buffer
= SessionId
;
1810 /* Class 48 - Delete an existing session (TSE) */
1811 SSI_DEF(SystemDeleteSession
)
1814 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1816 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
1818 if (PreviousMode
!= KernelMode
)
1820 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1822 return STATUS_PRIVILEGE_NOT_HELD
;
1826 SessionId
= *(PULONG
)Buffer
;
1828 return MmSessionDelete(SessionId
);
1832 /* Class 49 - UNKNOWN */
1833 QSI_DEF(SystemInvalidInfoClass4
)
1836 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1837 return STATUS_NOT_IMPLEMENTED
;
1841 /* Class 50 - System range start address */
1842 QSI_DEF(SystemRangeStartInformation
)
1844 /* Check user buffer's size */
1845 if (Size
!= sizeof(ULONG_PTR
)) return STATUS_INFO_LENGTH_MISMATCH
;
1847 *(PULONG_PTR
)Buffer
= (ULONG_PTR
)MmSystemRangeStart
;
1849 if (ReqSize
) *ReqSize
= sizeof(ULONG_PTR
);
1851 return STATUS_SUCCESS
;
1854 /* Class 51 - Driver verifier information */
1855 QSI_DEF(SystemVerifierInformation
)
1858 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1859 return STATUS_NOT_IMPLEMENTED
;
1863 SSI_DEF(SystemVerifierInformation
)
1866 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1867 return STATUS_NOT_IMPLEMENTED
;
1871 /* Class 52 - Add a driver verifier */
1872 SSI_DEF(SystemAddVerifier
)
1875 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1876 return STATUS_NOT_IMPLEMENTED
;
1880 /* Class 53 - A session's processes */
1881 QSI_DEF(SystemSessionProcessesInformation
)
1884 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1885 return STATUS_NOT_IMPLEMENTED
;
1889 /* Query/Set Calls Table */
1893 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1894 NTSTATUS (* Set
) (PVOID
,ULONG
);
1901 // XX unknown behaviour
1903 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1904 #define SI_QX(n) {QSI_USE(n),NULL}
1905 #define SI_XS(n) {NULL,SSI_USE(n)}
1906 #define SI_XX(n) {NULL,NULL}
1912 SI_QX(SystemBasicInformation
),
1913 SI_QX(SystemProcessorInformation
),
1914 SI_QX(SystemPerformanceInformation
),
1915 SI_QX(SystemTimeOfDayInformation
),
1916 SI_QX(SystemPathInformation
), /* should be SI_XX */
1917 SI_QX(SystemProcessInformation
),
1918 SI_QX(SystemCallCountInformation
),
1919 SI_QX(SystemDeviceInformation
),
1920 SI_QX(SystemProcessorPerformanceInformation
),
1921 SI_QS(SystemFlagsInformation
),
1922 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1923 SI_QX(SystemModuleInformation
),
1924 SI_QX(SystemLocksInformation
),
1925 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1926 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1927 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1928 SI_QX(SystemHandleInformation
),
1929 SI_QX(SystemObjectInformation
),
1930 SI_QX(SystemPageFileInformation
),
1931 SI_QX(SystemVdmInstemulInformation
),
1932 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1933 SI_QS(SystemFileCacheInformation
),
1934 SI_QX(SystemPoolTagInformation
),
1935 SI_QX(SystemInterruptInformation
),
1936 SI_QS(SystemDpcBehaviourInformation
),
1937 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1938 SI_XS(SystemLoadGdiDriverInformation
),
1939 SI_XS(SystemUnloadGdiDriverInformation
),
1940 SI_QS(SystemTimeAdjustmentInformation
),
1941 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1942 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1943 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */
1944 SI_QX(SystemCrashDumpInformation
),
1945 SI_QX(SystemExceptionInformation
),
1946 SI_QX(SystemCrashDumpStateInformation
),
1947 SI_QX(SystemKernelDebuggerInformation
),
1948 SI_QX(SystemContextSwitchInformation
),
1949 SI_QS(SystemRegistryQuotaInformation
),
1950 SI_XS(SystemExtendServiceTableInformation
),
1951 SI_XS(SystemPrioritySeperation
),
1952 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1953 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1954 SI_QX(SystemPowerInformation
), /* it should be SI_XX */
1955 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1956 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
1957 SI_QX(SystemLookasideInformation
),
1958 SI_XS(SystemSetTimeSlipEvent
),
1959 SI_XS(SystemCreateSession
),
1960 SI_XS(SystemDeleteSession
),
1961 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */
1962 SI_QX(SystemRangeStartInformation
),
1963 SI_QS(SystemVerifierInformation
),
1964 SI_XS(SystemAddVerifier
),
1965 SI_QX(SystemSessionProcessesInformation
)
1968 C_ASSERT(SystemBasicInformation
== 0);
1969 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1970 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1976 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1977 OUT PVOID SystemInformation
,
1979 OUT PULONG UnsafeResultLength
)
1981 KPROCESSOR_MODE PreviousMode
;
1983 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
1987 PreviousMode
= ExGetPreviousMode();
1991 if (PreviousMode
!= KernelMode
)
1993 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1994 ProbeForWrite(SystemInformation
, Length
, 1);
1995 if (UnsafeResultLength
!= NULL
)
1996 ProbeForWriteUlong(UnsafeResultLength
);
2000 * Check the request is valid.
2002 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
2004 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
2007 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
2010 * Hand the request to a subhandler.
2012 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
2016 /* Save the result length to the caller */
2017 if (UnsafeResultLength
)
2018 *UnsafeResultLength
= ResultLength
;
2021 _SEH2_EXCEPT(ExSystemExceptionFilter())
2023 FStatus
= _SEH2_GetExceptionCode();
2033 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2034 IN PVOID SystemInformation
,
2035 IN ULONG SystemInformationLength
)
2040 * If called from user mode, check
2041 * possible unsafe arguments.
2044 if (KernelMode
!= KeGetPreviousMode())
2048 // SystemInformation,
2058 * Check the request is valid.
2060 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
2061 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
2063 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
2066 * Hand the request to a subhandler.
2068 return CallQS
[SystemInformationClass
].Set(SystemInformation
,
2069 SystemInformationLength
);
2073 return STATUS_INVALID_INFO_CLASS
;
2078 NtFlushInstructionCache(IN HANDLE ProcessHandle
,
2079 IN PVOID BaseAddress
,
2080 IN ULONG NumberOfBytesToFlush
)
2084 #if defined(_M_IX86) || defined(_M_AMD64)
2086 #elif defined(_M_PPC)
2087 __asm__
__volatile__("tlbsync");
2088 #elif defined(_M_MIPS)
2089 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2091 #elif defined(_M_ARM)
2092 __asm__
__volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
2094 #error Unknown architecture
2096 return STATUS_SUCCESS
;
2101 NtGetCurrentProcessorNumber(VOID
)
2103 /* Just return the CPU */
2104 return KeGetCurrentProcessorNumber();
2110 #undef ExGetPreviousMode
2113 ExGetPreviousMode (VOID
)
2115 return KeGetPreviousMode();