3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/sysinfo.c
6 * PURPOSE: System information functions
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Aleksey Bragin (aleksey@studiocerebral.com)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 extern PEPROCESS PsIdleProcess
;
19 extern ULONG NtGlobalFlag
; /* FIXME: it should go in a ddk/?.h */
20 ULONGLONG STDCALL
KeQueryInterruptTime(VOID
);
22 VOID
MmPrintMemoryStatistic(VOID
);
24 FAST_MUTEX ExpEnvironmentLock
;
25 ERESOURCE ExpFirmwareTableResource
;
26 LIST_ENTRY ExpFirmwareTableProviderListHead
;
30 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
31 IN PLIST_ENTRY UserModeList
,
32 OUT PRTL_PROCESS_MODULES Modules
,
34 OUT PULONG ReturnLength
)
36 NTSTATUS Status
= STATUS_SUCCESS
;
38 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
39 PLDR_DATA_TABLE_ENTRY LdrEntry
;
40 ANSI_STRING ModuleName
;
41 ULONG ModuleCount
= 0;
42 PLIST_ENTRY NextEntry
;
46 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
47 ModuleInfo
= &Modules
->Modules
[0];
49 /* Loop the kernel list */
50 NextEntry
= KernelModeList
->Flink
;
51 while (NextEntry
!= KernelModeList
)
54 LdrEntry
= CONTAINING_RECORD(NextEntry
,
58 /* Update size and check if we can manage one more entry */
59 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
60 if (Length
>= RequiredLength
)
63 ModuleInfo
->MappedBase
= NULL
;
64 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
65 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
66 ModuleInfo
->Flags
= LdrEntry
->Flags
;
67 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
68 ModuleInfo
->LoadOrderIndex
= ModuleCount
;
69 ModuleInfo
->InitOrderIndex
= 0;
72 RtlInitEmptyAnsiString(&ModuleName
,
73 ModuleInfo
->FullPathName
,
74 sizeof(ModuleInfo
->FullPathName
));
77 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
78 &LdrEntry
->FullDllName
,
80 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
82 /* Calculate offset to name */
83 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
84 while ((p
> ModuleName
.Buffer
) && (*--p
))
86 /* Check if we found the separator */
87 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
89 /* We did, break out */
96 ModuleInfo
->OffsetToFileName
= p
- ModuleName
.Buffer
;
100 /* Return empty name */
101 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
102 ModuleInfo
->OffsetToFileName
= 0;
105 /* Go to the next module */
111 Status
= STATUS_INFO_LENGTH_MISMATCH
;
114 /* Update count and move to next entry */
116 NextEntry
= NextEntry
->Flink
;
119 /* Check if caller also wanted user modules */
123 DPRINT1("User-mode list not yet supported in ReactOS!\n");
126 /* Update return length */
127 if (ReturnLength
) *ReturnLength
= RequiredLength
;
129 /* Validate the length again */
130 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
132 /* Set the final count */
133 Modules
->NumberOfModules
= ModuleCount
;
137 /* Otherwise, we failed */
138 Status
= STATUS_INFO_LENGTH_MISMATCH
;
145 /* FUNCTIONS *****************************************************************/
150 #undef ExGetPreviousMode
153 ExGetPreviousMode (VOID
)
155 return KeGetPreviousMode();
163 ExGetCurrentProcessorCpuUsage (
169 ULONGLONG ScaledIdle
;
171 Prcb
= KeGetCurrentPrcb();
173 ScaledIdle
= Prcb
->IdleThread
->KernelTime
* 100;
174 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
176 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
186 ExGetCurrentProcessorCounts (
187 PULONG ThreadKernelTime
,
189 PULONG ProcessorNumber
194 Prcb
= KeGetCurrentPrcb();
196 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
197 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
198 *ProcessorNumber
= KeGetCurrentProcessorNumber();
206 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
208 /* Quick check to see if it exists at all */
209 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
211 /* Return our support for it */
212 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
220 ExVerifySuite(SUITE_TYPE SuiteType
)
222 if (SuiteType
== Personal
) return TRUE
;
227 NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName
,
228 OUT PWSTR ValueBuffer
,
229 IN ULONG ValueBufferLength
,
230 IN OUT PULONG ReturnLength OPTIONAL
)
233 UNICODE_STRING WName
;
237 UNICODE_STRING WValue
;
238 KPROCESSOR_MODE PreviousMode
;
239 NTSTATUS Status
= STATUS_SUCCESS
;
243 PreviousMode
= ExGetPreviousMode();
245 if(PreviousMode
!= KernelMode
)
249 ProbeForRead(VariableName
,
250 sizeof(UNICODE_STRING
),
252 ProbeForWrite(ValueBuffer
,
255 if(ReturnLength
!= NULL
)
257 ProbeForWriteUlong(ReturnLength
);
260 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
262 Status
= _SEH_GetExceptionCode();
266 if(!NT_SUCCESS(Status
))
273 * Copy the name to kernel space if necessary and convert it to ANSI.
275 Status
= ProbeAndCaptureUnicodeString(&WName
,
278 if(NT_SUCCESS(Status
))
281 * according to ntinternals the SeSystemEnvironmentName privilege is required!
283 if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
286 ReleaseCapturedUnicodeString(&WName
,
288 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
289 return STATUS_PRIVILEGE_NOT_HELD
;
293 * convert the value name to ansi
295 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
296 ReleaseCapturedUnicodeString(&WName
,
298 if(!NT_SUCCESS(Status
))
304 * Create a temporary buffer for the value
306 Value
= ExAllocatePool(NonPagedPool
, ValueBufferLength
);
309 RtlFreeAnsiString(&AName
);
310 return STATUS_INSUFFICIENT_RESOURCES
;
314 * Get the environment variable
316 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
317 (USHORT
)ValueBufferLength
,
321 RtlFreeAnsiString(&AName
);
323 return STATUS_UNSUCCESSFUL
;
327 * Convert the result to UNICODE, protect with SEH in case the value buffer
328 * isn't NULL-terminated!
332 RtlInitAnsiString(&AValue
, Value
);
333 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, TRUE
);
335 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
337 Status
= _SEH_GetExceptionCode();
341 if(NT_SUCCESS(Status
))
344 * Copy the result back to the caller.
348 RtlCopyMemory(ValueBuffer
, WValue
.Buffer
, WValue
.Length
);
349 ValueBuffer
[WValue
.Length
/ sizeof(WCHAR
)] = L
'\0';
350 if(ReturnLength
!= NULL
)
352 *ReturnLength
= WValue
.Length
+ sizeof(WCHAR
);
355 Status
= STATUS_SUCCESS
;
357 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
359 Status
= _SEH_GetExceptionCode();
365 * Cleanup allocated resources.
367 RtlFreeAnsiString(&AName
);
376 NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName
,
377 IN PUNICODE_STRING Value
)
379 UNICODE_STRING CapturedName
, CapturedValue
;
380 ANSI_STRING AName
, AValue
;
381 KPROCESSOR_MODE PreviousMode
;
386 PreviousMode
= ExGetPreviousMode();
389 * Copy the strings to kernel space if necessary
391 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
394 if(NT_SUCCESS(Status
))
396 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
399 if(NT_SUCCESS(Status
))
402 * according to ntinternals the SeSystemEnvironmentName privilege is required!
404 if(SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
408 * convert the strings to ANSI
410 Status
= RtlUnicodeStringToAnsiString(&AName
,
413 if(NT_SUCCESS(Status
))
415 Status
= RtlUnicodeStringToAnsiString(&AValue
,
418 if(NT_SUCCESS(Status
))
420 BOOLEAN Result
= HalSetEnvironmentVariable(AName
.Buffer
,
423 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
429 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
430 Status
= STATUS_PRIVILEGE_NOT_HELD
;
433 ReleaseCapturedUnicodeString(&CapturedValue
,
437 ReleaseCapturedUnicodeString(&CapturedName
,
446 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
448 IN ULONG BufferLength
)
451 return STATUS_NOT_IMPLEMENTED
;
456 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
457 IN LPGUID VendorGuid
,
459 IN OUT PULONG ReturnLength
,
460 IN OUT PULONG Attributes
)
463 return STATUS_NOT_IMPLEMENTED
;
468 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
469 IN LPGUID VendorGuid
)
472 return STATUS_NOT_IMPLEMENTED
;
475 /* --- Query/Set System Information --- */
478 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
479 * so the stack is popped only in one place on x86 platform.
481 #define QSI_USE(n) QSI##n
483 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
485 #define SSI_USE(n) SSI##n
487 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
490 /* Class 0 - Basic Information */
491 QSI_DEF(SystemBasicInformation
)
493 PSYSTEM_BASIC_INFORMATION Sbi
494 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
496 *ReqSize
= sizeof (SYSTEM_BASIC_INFORMATION
);
498 * Check user buffer's size
500 if (Size
!= sizeof (SYSTEM_BASIC_INFORMATION
))
502 return (STATUS_INFO_LENGTH_MISMATCH
);
505 Sbi
->TimerResolution
= KeMaximumIncrement
;
506 Sbi
->PageSize
= PAGE_SIZE
;
507 Sbi
->NumberOfPhysicalPages
= MmStats
.NrTotalPages
;
508 Sbi
->LowestPhysicalPageNumber
= 0; /* FIXME */
509 Sbi
->HighestPhysicalPageNumber
= MmStats
.NrTotalPages
; /* FIXME */
510 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
511 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
512 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
513 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
514 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
515 return (STATUS_SUCCESS
);
518 /* Class 1 - Processor Information */
519 QSI_DEF(SystemProcessorInformation
)
521 PSYSTEM_PROCESSOR_INFORMATION Spi
522 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
524 *ReqSize
= sizeof (SYSTEM_PROCESSOR_INFORMATION
);
526 * Check user buffer's size
528 if (Size
< sizeof (SYSTEM_PROCESSOR_INFORMATION
))
530 return (STATUS_INFO_LENGTH_MISMATCH
);
532 Prcb
= KeGetCurrentPrcb();
533 Spi
->ProcessorArchitecture
= 0; /* Intel Processor */
534 Spi
->ProcessorLevel
= Prcb
->CpuType
;
535 Spi
->ProcessorRevision
= Prcb
->CpuStep
;
537 Spi
->ProcessorFeatureBits
= Prcb
->FeatureBits
;
539 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi
->ProcessorArchitecture
,
540 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
542 return (STATUS_SUCCESS
);
545 /* Class 2 - Performance Information */
546 QSI_DEF(SystemPerformanceInformation
)
548 PSYSTEM_PERFORMANCE_INFORMATION Spi
549 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
551 PEPROCESS TheIdleProcess
;
553 *ReqSize
= sizeof (SYSTEM_PERFORMANCE_INFORMATION
);
555 * Check user buffer's size
557 if (Size
< sizeof (SYSTEM_PERFORMANCE_INFORMATION
))
559 return (STATUS_INFO_LENGTH_MISMATCH
);
562 TheIdleProcess
= PsIdleProcess
;
564 Spi
->IdleProcessTime
.QuadPart
= TheIdleProcess
->Pcb
.KernelTime
* 100000LL;
566 Spi
->IoReadTransferCount
= IoReadTransferCount
;
567 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
568 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
569 Spi
->IoReadOperationCount
= IoReadOperationCount
;
570 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
571 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
573 Spi
->AvailablePages
= MmStats
.NrFreePages
;
575 Add up all the used "Commitied" memory + pagefile.
576 Not sure this is right. 8^\
578 Spi
->CommittedPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
+
579 MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
+
580 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
581 MiMemoryConsumers
[MC_USER
].PagesUsed
+
584 Add up the full system total + pagefile.
585 All this make Taskmgr happy but not sure it is the right numbers.
586 This too, fixes some of GlobalMemoryStatusEx numbers.
588 Spi
->CommitLimit
= MmStats
.NrTotalPages
+ MiFreeSwapPages
+
591 Spi
->PeakCommitment
= 0; /* FIXME */
592 Spi
->PageFaultCount
= 0; /* FIXME */
593 Spi
->CopyOnWriteCount
= 0; /* FIXME */
594 Spi
->TransitionCount
= 0; /* FIXME */
595 Spi
->CacheTransitionCount
= 0; /* FIXME */
596 Spi
->DemandZeroCount
= 0; /* FIXME */
597 Spi
->PageReadCount
= 0; /* FIXME */
598 Spi
->PageReadIoCount
= 0; /* FIXME */
599 Spi
->CacheReadCount
= 0; /* FIXME */
600 Spi
->CacheIoCount
= 0; /* FIXME */
601 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
602 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
603 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
604 Spi
->MappedWriteIoCount
= 0; /* FIXME */
606 Spi
->PagedPoolPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
;
607 Spi
->PagedPoolAllocs
= 0; /* FIXME */
608 Spi
->PagedPoolFrees
= 0; /* FIXME */
609 Spi
->NonPagedPoolPages
= MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
;
610 Spi
->NonPagedPoolAllocs
= 0; /* FIXME */
611 Spi
->NonPagedPoolFrees
= 0; /* FIXME */
613 Spi
->FreeSystemPtes
= 0; /* FIXME */
615 Spi
->ResidentSystemCodePage
= MmStats
.NrSystemPages
; /* FIXME */
617 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
618 Spi
->TotalSystemCodePages
= 0; /* FIXME */
619 Spi
->NonPagedPoolLookasideHits
= 0; /* FIXME */
620 Spi
->PagedPoolLookasideHits
= 0; /* FIXME */
621 Spi
->Spare3Count
= 0; /* FIXME */
623 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
624 Spi
->ResidentPagedPoolPage
= MmPagedPoolSize
; /* FIXME */
626 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
627 Spi
->CcFastReadNoWait
= 0; /* FIXME */
628 Spi
->CcFastReadWait
= 0; /* FIXME */
629 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
630 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
632 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
633 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
634 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
635 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
637 Spi
->CcMapDataNoWait
= 0; /* FIXME */
638 Spi
->CcMapDataWait
= 0; /* FIXME */
639 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
640 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
642 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
643 Spi
->CcPinReadNoWait
= 0; /* FIXME */
644 Spi
->CcPinReadWait
= 0; /* FIXME */
645 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
646 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
647 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
648 Spi
->CcCopyReadWait
= 0; /* FIXME */
649 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
650 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
652 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
653 Spi
->CcMdlReadWait
= 0; /* FIXME */
654 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
655 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
656 Spi
->CcReadAheadIos
= 0; /* FIXME */
657 Spi
->CcLazyWriteIos
= 0; /* FIXME */
658 Spi
->CcLazyWritePages
= 0; /* FIXME */
659 Spi
->CcDataFlushes
= 0; /* FIXME */
660 Spi
->CcDataPages
= 0; /* FIXME */
661 Spi
->ContextSwitches
= 0; /* FIXME */
662 Spi
->FirstLevelTbFills
= 0; /* FIXME */
663 Spi
->SecondLevelTbFills
= 0; /* FIXME */
664 Spi
->SystemCalls
= 0; /* FIXME */
666 return (STATUS_SUCCESS
);
669 /* Class 3 - Time Of Day Information */
670 QSI_DEF(SystemTimeOfDayInformation
)
672 PSYSTEM_TIMEOFDAY_INFORMATION Sti
;
673 LARGE_INTEGER CurrentTime
;
675 Sti
= (PSYSTEM_TIMEOFDAY_INFORMATION
)Buffer
;
676 *ReqSize
= sizeof (SYSTEM_TIMEOFDAY_INFORMATION
);
678 /* Check user buffer's size */
679 if (Size
!= sizeof (SYSTEM_TIMEOFDAY_INFORMATION
))
681 return STATUS_INFO_LENGTH_MISMATCH
;
684 KeQuerySystemTime(&CurrentTime
);
686 Sti
->BootTime
= KeBootTime
;
687 Sti
->CurrentTime
= CurrentTime
;
688 Sti
->TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
689 Sti
->TimeZoneId
= ExpTimeZoneId
;
692 return STATUS_SUCCESS
;
695 /* Class 4 - Path Information */
696 QSI_DEF(SystemPathInformation
)
698 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
699 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
701 return (STATUS_BREAKPOINT
);
704 /* Class 5 - Process Information */
705 QSI_DEF(SystemProcessInformation
)
707 ULONG ovlSize
= 0, nThreads
;
708 PEPROCESS pr
= NULL
, syspr
;
710 NTSTATUS Status
= STATUS_SUCCESS
;
714 /* scan the process list */
716 PSYSTEM_PROCESS_INFORMATION Spi
717 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
719 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
721 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
723 return (STATUS_INFO_LENGTH_MISMATCH
); // in case buffer size is too small
726 syspr
= PsGetNextProcess(NULL
);
728 pCur
= (unsigned char *)Spi
;
732 PSYSTEM_PROCESS_INFORMATION SpiCur
;
735 int inLen
=32; // image name len in bytes
736 PLIST_ENTRY current_entry
;
738 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
740 SpiCur
= (PSYSTEM_PROCESS_INFORMATION
)pCur
;
743 current_entry
= pr
->ThreadListHead
.Flink
;
744 while (current_entry
!= &pr
->ThreadListHead
)
747 current_entry
= current_entry
->Flink
;
750 // size of the structure for every process
751 curSize
= sizeof(SYSTEM_PROCESS_INFORMATION
)+sizeof(SYSTEM_THREAD_INFORMATION
)*nThreads
;
752 ovlSize
+= curSize
+inLen
;
757 ObDereferenceObject(pr
);
759 return (STATUS_INFO_LENGTH_MISMATCH
); // in case buffer size is too small
762 // fill system information
763 SpiCur
->NextEntryOffset
= curSize
+inLen
; // relative offset to the beginnnig of the next structure
764 SpiCur
->NumberOfThreads
= nThreads
;
765 SpiCur
->CreateTime
= pr
->CreateTime
;
766 SpiCur
->UserTime
.QuadPart
= pr
->Pcb
.UserTime
* 100000LL;
767 SpiCur
->KernelTime
.QuadPart
= pr
->Pcb
.KernelTime
* 100000LL;
768 SpiCur
->ImageName
.Length
= strlen(pr
->ImageFileName
) * sizeof(WCHAR
);
769 SpiCur
->ImageName
.MaximumLength
= inLen
;
770 SpiCur
->ImageName
.Buffer
= (void*)(pCur
+curSize
);
772 // copy name to the end of the struct
773 if(pr
!= PsIdleProcess
)
775 RtlInitAnsiString(&imgName
, pr
->ImageFileName
);
776 RtlAnsiStringToUnicodeString(&SpiCur
->ImageName
, &imgName
, FALSE
);
780 RtlInitUnicodeString(&SpiCur
->ImageName
, NULL
);
783 SpiCur
->BasePriority
= pr
->Pcb
.BasePriority
;
784 SpiCur
->UniqueProcessId
= pr
->UniqueProcessId
;
785 SpiCur
->InheritedFromUniqueProcessId
= pr
->InheritedFromUniqueProcessId
;
786 SpiCur
->HandleCount
= (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
787 SpiCur
->PeakVirtualSize
= pr
->PeakVirtualSize
;
788 SpiCur
->VirtualSize
= pr
->VirtualSize
;
789 SpiCur
->PageFaultCount
= pr
->Vm
.PageFaultCount
;
790 SpiCur
->PeakWorkingSetSize
= pr
->Vm
.PeakWorkingSetSize
;
791 SpiCur
->WorkingSetSize
= pr
->Vm
.WorkingSetSize
;
792 SpiCur
->QuotaPeakPagedPoolUsage
= pr
->QuotaPeak
[0];
793 SpiCur
->QuotaPagedPoolUsage
= pr
->QuotaUsage
[0];
794 SpiCur
->QuotaPeakNonPagedPoolUsage
= pr
->QuotaPeak
[1];
795 SpiCur
->QuotaNonPagedPoolUsage
= pr
->QuotaUsage
[1];
796 SpiCur
->PagefileUsage
= pr
->QuotaUsage
[2];
797 SpiCur
->PeakPagefileUsage
= pr
->QuotaPeak
[2];
798 SpiCur
->PrivatePageCount
= pr
->CommitCharge
;
799 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCur
+ 1);
801 current_entry
= pr
->ThreadListHead
.Flink
;
802 while (current_entry
!= &pr
->ThreadListHead
)
804 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
808 ThreadInfo
->KernelTime
.QuadPart
= current
->Tcb
.KernelTime
* 100000LL;
809 ThreadInfo
->UserTime
.QuadPart
= current
->Tcb
.UserTime
* 100000LL;
810 // SpiCur->TH[i].CreateTime = current->CreateTime;
811 ThreadInfo
->WaitTime
= current
->Tcb
.WaitTime
;
812 ThreadInfo
->StartAddress
= (PVOID
) current
->StartAddress
;
813 ThreadInfo
->ClientId
= current
->Cid
;
814 ThreadInfo
->Priority
= current
->Tcb
.Priority
;
815 ThreadInfo
->BasePriority
= current
->Tcb
.BasePriority
;
816 ThreadInfo
->ContextSwitches
= current
->Tcb
.ContextSwitches
;
817 ThreadInfo
->ThreadState
= current
->Tcb
.State
;
818 ThreadInfo
->WaitReason
= current
->Tcb
.WaitReason
;
820 current_entry
= current_entry
->Flink
;
823 pr
= PsGetNextProcess(pr
);
825 if ((pr
== syspr
) || (pr
== NULL
))
827 SpiCur
->NextEntryOffset
= 0;
831 pCur
= pCur
+ curSize
+ inLen
;
832 } while ((pr
!= syspr
) && (pr
!= NULL
));
835 ObDereferenceObject(pr
);
836 Status
= STATUS_SUCCESS
;
841 ObDereferenceObject(pr
);
842 Status
= _SEH_GetExceptionCode();
850 /* Class 6 - Call Count Information */
851 QSI_DEF(SystemCallCountInformation
)
854 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
855 return (STATUS_NOT_IMPLEMENTED
);
858 /* Class 7 - Device Information */
859 QSI_DEF(SystemDeviceInformation
)
861 PSYSTEM_DEVICE_INFORMATION Sdi
862 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
863 PCONFIGURATION_INFORMATION ConfigInfo
;
865 *ReqSize
= sizeof (SYSTEM_DEVICE_INFORMATION
);
867 * Check user buffer's size
869 if (Size
< sizeof (SYSTEM_DEVICE_INFORMATION
))
871 return (STATUS_INFO_LENGTH_MISMATCH
);
874 ConfigInfo
= IoGetConfigurationInformation ();
876 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
877 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
878 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
879 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
880 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
881 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
883 return (STATUS_SUCCESS
);
886 /* Class 8 - Processor Performance Information */
887 QSI_DEF(SystemProcessorPerformanceInformation
)
889 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
890 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
893 LARGE_INTEGER CurrentTime
;
896 *ReqSize
= KeNumberProcessors
* sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
898 * Check user buffer's size
900 if (Size
< KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
))
902 return (STATUS_INFO_LENGTH_MISMATCH
);
905 CurrentTime
.QuadPart
= KeQueryInterruptTime();
906 Prcb
= ((PKPCR
)KPCR_BASE
)->Prcb
;
907 for (i
= 0; i
< KeNumberProcessors
; i
++)
909 Spi
->IdleTime
.QuadPart
= (Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
) * 100000LL; // IdleTime
910 Spi
->KernelTime
.QuadPart
= Prcb
->KernelTime
* 100000LL; // KernelTime
911 Spi
->UserTime
.QuadPart
= Prcb
->UserTime
* 100000LL;
912 Spi
->DpcTime
.QuadPart
= Prcb
->DpcTime
* 100000LL;
913 Spi
->InterruptTime
.QuadPart
= Prcb
->InterruptTime
* 100000LL;
914 Spi
->InterruptCount
= Prcb
->InterruptCount
; // Interrupt Count
916 Prcb
= (PKPRCB
)((ULONG_PTR
)Prcb
+ PAGE_SIZE
);
919 return (STATUS_SUCCESS
);
922 /* Class 9 - Flags Information */
923 QSI_DEF(SystemFlagsInformation
)
925 if (sizeof (SYSTEM_FLAGS_INFORMATION
) != Size
)
927 * ReqSize
= sizeof (SYSTEM_FLAGS_INFORMATION
);
928 return (STATUS_INFO_LENGTH_MISMATCH
);
930 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
931 return (STATUS_SUCCESS
);
934 SSI_DEF(SystemFlagsInformation
)
936 if (sizeof (SYSTEM_FLAGS_INFORMATION
) != Size
)
938 return (STATUS_INFO_LENGTH_MISMATCH
);
940 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
941 return (STATUS_SUCCESS
);
944 /* Class 10 - Call Time Information */
945 QSI_DEF(SystemCallTimeInformation
)
948 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
949 return (STATUS_NOT_IMPLEMENTED
);
952 /* Class 11 - Module Information */
953 QSI_DEF(SystemModuleInformation
)
955 extern LIST_ENTRY PsLoadedModuleList
;
956 return ExpQueryModuleInformation(&PsLoadedModuleList
,
958 (PRTL_PROCESS_MODULES
)Buffer
,
963 /* Class 12 - Locks Information */
964 QSI_DEF(SystemLocksInformation
)
967 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
968 return (STATUS_NOT_IMPLEMENTED
);
971 /* Class 13 - Stack Trace Information */
972 QSI_DEF(SystemStackTraceInformation
)
975 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
976 return (STATUS_NOT_IMPLEMENTED
);
979 /* Class 14 - Paged Pool Information */
980 QSI_DEF(SystemPagedPoolInformation
)
983 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
984 return (STATUS_NOT_IMPLEMENTED
);
987 /* Class 15 - Non Paged Pool Information */
988 QSI_DEF(SystemNonPagedPoolInformation
)
991 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
992 return (STATUS_NOT_IMPLEMENTED
);
996 /* Class 16 - Handle Information */
997 QSI_DEF(SystemHandleInformation
)
1000 ULONG curSize
, i
= 0;
1003 PSYSTEM_HANDLE_INFORMATION Shi
=
1004 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1006 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1008 if (Size
< sizeof (SYSTEM_HANDLE_INFORMATION
))
1010 * ReqSize
= sizeof (SYSTEM_HANDLE_INFORMATION
);
1011 return (STATUS_INFO_LENGTH_MISMATCH
);
1014 DPRINT("SystemHandleInformation 1\n");
1016 /* First Calc Size from Count. */
1017 syspr
= PsGetNextProcess(NULL
);
1022 hCount
= hCount
+ (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
1023 pr
= PsGetNextProcess(pr
);
1025 if ((pr
== syspr
) || (pr
== NULL
))
1027 } while ((pr
!= syspr
) && (pr
!= NULL
));
1031 ObDereferenceObject(pr
);
1034 DPRINT("SystemHandleInformation 2\n");
1036 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
)+
1037 ( (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1038 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) ));
1040 Shi
->NumberOfHandles
= hCount
;
1045 return (STATUS_INFO_LENGTH_MISMATCH
);
1048 DPRINT("SystemHandleInformation 3\n");
1050 /* Now get Handles from all processs. */
1051 syspr
= PsGetNextProcess(NULL
);
1056 int Count
= 0, HandleCount
;
1058 HandleCount
= (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
1060 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1062 Shi
->Handles
[i
].UniqueProcessId
= (ULONG
)pr
->UniqueProcessId
;
1067 pr
= PsGetNextProcess(pr
);
1069 if ((pr
== syspr
) || (pr
== NULL
))
1071 } while ((pr
!= syspr
) && (pr
!= NULL
));
1075 ObDereferenceObject(pr
);
1078 DPRINT("SystemHandleInformation 4\n");
1079 return (STATUS_SUCCESS
);
1083 SSI_DEF(SystemHandleInformation)
1086 return (STATUS_SUCCESS);
1090 /* Class 17 - Information */
1091 QSI_DEF(SystemObjectInformation
)
1094 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1095 return (STATUS_NOT_IMPLEMENTED
);
1098 /* Class 18 - Information */
1099 QSI_DEF(SystemPageFileInformation
)
1101 UNICODE_STRING FileName
; /* FIXME */
1102 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1104 if (Size
< sizeof (SYSTEM_PAGEFILE_INFORMATION
))
1106 * ReqSize
= sizeof (SYSTEM_PAGEFILE_INFORMATION
);
1107 return (STATUS_INFO_LENGTH_MISMATCH
);
1110 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1113 Spfi
->NextEntryOffset
= 0;
1115 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1116 Spfi
->TotalInUse
= MiUsedSwapPages
;
1117 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1118 Spfi
->PageFileName
= FileName
;
1119 return (STATUS_SUCCESS
);
1122 /* Class 19 - Vdm Instemul Information */
1123 QSI_DEF(SystemVdmInstemulInformation
)
1126 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1127 return (STATUS_NOT_IMPLEMENTED
);
1130 /* Class 20 - Vdm Bop Information */
1131 QSI_DEF(SystemVdmBopInformation
)
1134 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1135 return (STATUS_NOT_IMPLEMENTED
);
1138 /* Class 21 - File Cache Information */
1139 QSI_DEF(SystemFileCacheInformation
)
1141 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1143 if (Size
< sizeof (SYSTEM_FILECACHE_INFORMATION
))
1145 * ReqSize
= sizeof (SYSTEM_FILECACHE_INFORMATION
);
1146 return (STATUS_INFO_LENGTH_MISMATCH
);
1149 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1151 /* Return the Byte size not the page size. */
1153 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1155 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1157 Sci
->PageFaultCount
= 0; /* FIXME */
1158 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1159 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1161 return (STATUS_SUCCESS
);
1164 SSI_DEF(SystemFileCacheInformation
)
1166 if (Size
< sizeof (SYSTEM_FILECACHE_INFORMATION
))
1168 return (STATUS_INFO_LENGTH_MISMATCH
);
1171 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1172 return (STATUS_NOT_IMPLEMENTED
);
1175 /* Class 22 - Pool Tag Information */
1176 QSI_DEF(SystemPoolTagInformation
)
1179 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1180 return (STATUS_NOT_IMPLEMENTED
);
1183 /* Class 23 - Interrupt Information for all processors */
1184 QSI_DEF(SystemInterruptInformation
)
1189 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1191 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1193 return (STATUS_INFO_LENGTH_MISMATCH
);
1196 ti
= KeQueryTimeIncrement();
1198 Prcb
= ((PKPCR
)KPCR_BASE
)->Prcb
;
1199 for (i
= 0; i
< KeNumberProcessors
; i
++)
1201 //sii->ContextSwitches = Prcb->KeContextSwitches;
1202 sii
->DpcCount
= 0; /* FIXME */
1203 sii
->DpcRate
= 0; /* FIXME */
1204 sii
->TimeIncrement
= ti
;
1205 sii
->DpcBypassCount
= 0; /* FIXME */
1206 sii
->ApcBypassCount
= 0; /* FIXME */
1208 Prcb
= (PKPRCB
)((ULONG_PTR
)Prcb
+ PAGE_SIZE
);
1211 return STATUS_SUCCESS
;
1214 /* Class 24 - DPC Behaviour Information */
1215 QSI_DEF(SystemDpcBehaviourInformation
)
1218 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1219 return (STATUS_NOT_IMPLEMENTED
);
1222 SSI_DEF(SystemDpcBehaviourInformation
)
1225 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1226 return (STATUS_NOT_IMPLEMENTED
);
1229 /* Class 25 - Full Memory Information */
1230 QSI_DEF(SystemFullMemoryInformation
)
1232 PULONG Spi
= (PULONG
) Buffer
;
1234 PEPROCESS TheIdleProcess
;
1236 * ReqSize
= sizeof (ULONG
);
1238 if (sizeof (ULONG
) != Size
)
1240 return (STATUS_INFO_LENGTH_MISMATCH
);
1242 DPRINT("SystemFullMemoryInformation\n");
1244 TheIdleProcess
= PsIdleProcess
;
1246 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1247 TheIdleProcess
->UniqueProcessId
,
1248 TheIdleProcess
->Pcb
.KernelTime
,
1253 MmPrintMemoryStatistic();
1256 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1258 return (STATUS_SUCCESS
);
1261 /* Class 26 - Load Image */
1262 SSI_DEF(SystemLoadGdiDriverInformation
)
1264 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1265 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1266 UNICODE_STRING ImageName
;
1268 ULONG_PTR EntryPoint
;
1270 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1272 PIMAGE_NT_HEADERS NtHeader
;
1275 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1277 /* Incorrect buffer length, fail */
1278 return STATUS_INFO_LENGTH_MISMATCH
;
1281 /* Only kernel-mode can call this function */
1282 if (PreviousMode
!= KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1284 /* Load the driver */
1285 ImageName
= DriverInfo
->DriverName
;
1286 Status
= LdrLoadModule(&ImageName
, &ModuleObject
);
1287 if (!NT_SUCCESS(Status
)) return Status
;
1289 /* Return the export pointer */
1290 ImageBase
= ModuleObject
->DllBase
;
1291 DriverInfo
->ExportSectionPointer
=
1292 RtlImageDirectoryEntryToData(ImageBase
,
1294 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1297 /* Get the entrypoint */
1298 NtHeader
= RtlImageNtHeader(ImageBase
);
1299 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1300 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1302 /* Save other data */
1303 DriverInfo
->ImageAddress
= ImageBase
;
1304 DriverInfo
->SectionPointer
= NULL
;
1305 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1306 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1309 return STATUS_SUCCESS
;
1312 /* Class 27 - Unload Image */
1313 SSI_DEF(SystemUnloadGdiDriverInformation
)
1316 if (Size
!= sizeof(PVOID
)) return STATUS_INFO_LENGTH_MISMATCH
;
1317 return STATUS_NOT_IMPLEMENTED
;
1320 /* Class 28 - Time Adjustment Information */
1321 QSI_DEF(SystemTimeAdjustmentInformation
)
1323 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
) > Size
)
1325 * ReqSize
= sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
);
1326 return (STATUS_INFO_LENGTH_MISMATCH
);
1329 DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1330 return (STATUS_NOT_IMPLEMENTED
);
1333 SSI_DEF(SystemTimeAdjustmentInformation
)
1335 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
) > Size
)
1337 return (STATUS_INFO_LENGTH_MISMATCH
);
1340 DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1341 return (STATUS_NOT_IMPLEMENTED
);
1344 /* Class 29 - Summary Memory Information */
1345 QSI_DEF(SystemSummaryMemoryInformation
)
1348 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1349 return (STATUS_NOT_IMPLEMENTED
);
1352 /* Class 30 - Next Event Id Information */
1353 QSI_DEF(SystemNextEventIdInformation
)
1356 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1357 return (STATUS_NOT_IMPLEMENTED
);
1360 /* Class 31 - Event Ids Information */
1361 QSI_DEF(SystemEventIdsInformation
)
1364 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1365 return (STATUS_NOT_IMPLEMENTED
);
1368 /* Class 32 - Crash Dump Information */
1369 QSI_DEF(SystemCrashDumpInformation
)
1372 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1373 return (STATUS_NOT_IMPLEMENTED
);
1376 /* Class 33 - Exception Information */
1377 QSI_DEF(SystemExceptionInformation
)
1380 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1381 return (STATUS_NOT_IMPLEMENTED
);
1384 /* Class 34 - Crash Dump State Information */
1385 QSI_DEF(SystemCrashDumpStateInformation
)
1388 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1389 return (STATUS_NOT_IMPLEMENTED
);
1392 /* Class 35 - Kernel Debugger Information */
1393 QSI_DEF(SystemKernelDebuggerInformation
)
1395 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1397 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1398 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1400 return STATUS_INFO_LENGTH_MISMATCH
;
1403 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1404 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1406 return STATUS_SUCCESS
;
1409 /* Class 36 - Context Switch Information */
1410 QSI_DEF(SystemContextSwitchInformation
)
1413 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1414 return (STATUS_NOT_IMPLEMENTED
);
1417 /* Class 37 - Registry Quota Information */
1418 QSI_DEF(SystemRegistryQuotaInformation
)
1420 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1422 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1423 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1425 return STATUS_INFO_LENGTH_MISMATCH
;
1428 DPRINT1("Faking max registry size of 32 MB\n");
1429 srqi
->RegistryQuotaAllowed
= 0x2000000;
1430 srqi
->RegistryQuotaUsed
= 0x200000;
1431 srqi
->PagedPoolSize
= 0x200000;
1433 return STATUS_SUCCESS
;
1436 SSI_DEF(SystemRegistryQuotaInformation
)
1439 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1440 return (STATUS_NOT_IMPLEMENTED
);
1443 /* Class 38 - Load And Call Image */
1444 SSI_DEF(SystemExtendServiceTableInformation
)
1446 UNICODE_STRING ImageName
;
1447 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1448 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1450 PIMAGE_NT_HEADERS NtHeader
;
1451 DRIVER_OBJECT Win32k
;
1452 PDRIVER_INITIALIZE DriverInit
;
1454 ULONG_PTR EntryPoint
;
1456 /* Validate the size */
1457 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1459 /* Check who is calling */
1460 if (PreviousMode
!= KernelMode
)
1462 /* Make sure we can load drivers */
1463 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1465 /* FIXME: We can't, fail */
1466 //return STATUS_PRIVILEGE_NOT_HELD;
1469 /* Probe and capture the driver name */
1470 ProbeAndCaptureUnicodeString(&ImageName
, UserMode
, Buffer
);
1472 /* Force kernel as previous mode */
1473 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1478 /* Just copy the string */
1479 ImageName
= *(PUNICODE_STRING
)Buffer
;
1481 /* Load the image */
1482 Status
= LdrLoadModule(&ImageName
, &ModuleObject
);
1483 if (!NT_SUCCESS(Status
)) return Status
;
1485 /* Get the headers */
1486 ImageBase
= ModuleObject
->DllBase
;
1487 NtHeader
= RtlImageNtHeader(ImageBase
);
1491 LdrUnloadModule(ModuleObject
);
1492 return STATUS_INVALID_IMAGE_FORMAT
;
1495 /* Get the entrypoint */
1496 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1497 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1498 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1500 /* Create a dummy device */
1501 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1502 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1503 Win32k
.DriverStart
= ImageBase
;
1506 Status
= (DriverInit
)(&Win32k
, NULL
);
1507 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1509 /* Unload if we failed */
1510 if (!NT_SUCCESS(Status
)) LdrUnloadModule(ModuleObject
);
1514 /* Class 39 - Priority Separation */
1515 SSI_DEF(SystemPrioritySeperation
)
1518 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1519 return (STATUS_NOT_IMPLEMENTED
);
1522 /* Class 40 - Plug Play Bus Information */
1523 QSI_DEF(SystemPlugPlayBusInformation
)
1526 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1527 return (STATUS_NOT_IMPLEMENTED
);
1530 /* Class 41 - Dock Information */
1531 QSI_DEF(SystemDockInformation
)
1534 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1535 return (STATUS_NOT_IMPLEMENTED
);
1538 /* Class 42 - Power Information */
1539 QSI_DEF(SystemPowerInformation
)
1542 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1543 return (STATUS_NOT_IMPLEMENTED
);
1546 /* Class 43 - Processor Speed Information */
1547 QSI_DEF(SystemProcessorSpeedInformation
)
1550 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1551 return (STATUS_NOT_IMPLEMENTED
);
1554 /* Class 44 - Current Time Zone Information */
1555 QSI_DEF(SystemCurrentTimeZoneInformation
)
1557 * ReqSize
= sizeof (TIME_ZONE_INFORMATION
);
1559 if (sizeof (TIME_ZONE_INFORMATION
) != Size
)
1561 return STATUS_INFO_LENGTH_MISMATCH
;
1564 /* Copy the time zone information struct */
1567 sizeof(TIME_ZONE_INFORMATION
));
1569 return STATUS_SUCCESS
;
1573 SSI_DEF(SystemCurrentTimeZoneInformation
)
1575 /* Check user buffer's size */
1576 if (Size
< sizeof (TIME_ZONE_INFORMATION
))
1578 return STATUS_INFO_LENGTH_MISMATCH
;
1581 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1585 /* Class 45 - Lookaside Information */
1586 QSI_DEF(SystemLookasideInformation
)
1589 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1590 return (STATUS_NOT_IMPLEMENTED
);
1594 /* Class 46 - Set time slip event */
1595 SSI_DEF(SystemSetTimeSlipEvent
)
1598 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1599 return (STATUS_NOT_IMPLEMENTED
);
1603 /* Class 47 - Create a new session (TSE) */
1604 SSI_DEF(SystemCreateSession
)
1607 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1608 return (STATUS_NOT_IMPLEMENTED
);
1612 /* Class 48 - Delete an existing session (TSE) */
1613 SSI_DEF(SystemDeleteSession
)
1616 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1617 return (STATUS_NOT_IMPLEMENTED
);
1621 /* Class 49 - UNKNOWN */
1622 QSI_DEF(SystemInvalidInfoClass4
)
1625 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1626 return (STATUS_NOT_IMPLEMENTED
);
1630 /* Class 50 - System range start address */
1631 QSI_DEF(SystemRangeStartInformation
)
1634 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1635 return (STATUS_NOT_IMPLEMENTED
);
1639 /* Class 51 - Driver verifier information */
1640 QSI_DEF(SystemVerifierInformation
)
1643 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1644 return (STATUS_NOT_IMPLEMENTED
);
1648 SSI_DEF(SystemVerifierInformation
)
1651 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1652 return (STATUS_NOT_IMPLEMENTED
);
1656 /* Class 52 - Add a driver verifier */
1657 SSI_DEF(SystemAddVerifier
)
1660 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1661 return (STATUS_NOT_IMPLEMENTED
);
1665 /* Class 53 - A session's processes */
1666 QSI_DEF(SystemSessionProcessesInformation
)
1669 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1670 return (STATUS_NOT_IMPLEMENTED
);
1674 /* Query/Set Calls Table */
1678 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1679 NTSTATUS (* Set
) (PVOID
,ULONG
);
1686 // XX unknown behaviour
1688 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1689 #define SI_QX(n) {QSI_USE(n),NULL}
1690 #define SI_XS(n) {NULL,SSI_USE(n)}
1691 #define SI_XX(n) {NULL,NULL}
1697 SI_QX(SystemBasicInformation
),
1698 SI_QX(SystemProcessorInformation
),
1699 SI_QX(SystemPerformanceInformation
),
1700 SI_QX(SystemTimeOfDayInformation
),
1701 SI_QX(SystemPathInformation
), /* should be SI_XX */
1702 SI_QX(SystemProcessInformation
),
1703 SI_QX(SystemCallCountInformation
),
1704 SI_QX(SystemDeviceInformation
),
1705 SI_QX(SystemProcessorPerformanceInformation
),
1706 SI_QS(SystemFlagsInformation
),
1707 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1708 SI_QX(SystemModuleInformation
),
1709 SI_QX(SystemLocksInformation
),
1710 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1711 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1712 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1713 SI_QX(SystemHandleInformation
),
1714 SI_QX(SystemObjectInformation
),
1715 SI_QX(SystemPageFileInformation
),
1716 SI_QX(SystemVdmInstemulInformation
),
1717 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1718 SI_QS(SystemFileCacheInformation
),
1719 SI_QX(SystemPoolTagInformation
),
1720 SI_QX(SystemInterruptInformation
),
1721 SI_QS(SystemDpcBehaviourInformation
),
1722 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1723 SI_XS(SystemLoadGdiDriverInformation
),
1724 SI_XS(SystemUnloadGdiDriverInformation
),
1725 SI_QS(SystemTimeAdjustmentInformation
),
1726 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1727 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1728 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */
1729 SI_QX(SystemCrashDumpInformation
),
1730 SI_QX(SystemExceptionInformation
),
1731 SI_QX(SystemCrashDumpStateInformation
),
1732 SI_QX(SystemKernelDebuggerInformation
),
1733 SI_QX(SystemContextSwitchInformation
),
1734 SI_QS(SystemRegistryQuotaInformation
),
1735 SI_XS(SystemExtendServiceTableInformation
),
1736 SI_XS(SystemPrioritySeperation
),
1737 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1738 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1739 SI_QX(SystemPowerInformation
), /* it should be SI_XX */
1740 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1741 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
1742 SI_QX(SystemLookasideInformation
),
1743 SI_XS(SystemSetTimeSlipEvent
),
1744 SI_XS(SystemCreateSession
),
1745 SI_XS(SystemDeleteSession
),
1746 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */
1747 SI_QX(SystemRangeStartInformation
),
1748 SI_QS(SystemVerifierInformation
),
1749 SI_XS(SystemAddVerifier
),
1750 SI_QX(SystemSessionProcessesInformation
)
1758 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1759 OUT PVOID SystemInformation
,
1761 OUT PULONG UnsafeResultLength
)
1763 KPROCESSOR_MODE PreviousMode
;
1765 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
1769 PreviousMode
= ExGetPreviousMode();
1773 if (PreviousMode
!= KernelMode
)
1775 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1776 ProbeForWrite(SystemInformation
, Length
, 1);
1777 if (UnsafeResultLength
!= NULL
)
1778 ProbeForWriteUlong(UnsafeResultLength
);
1781 /* Clear user buffer. */
1782 RtlZeroMemory(SystemInformation
, Length
);
1785 * Check the request is valid.
1787 if (SystemInformationClass
>= MaxSystemInfoClass
)
1789 return (STATUS_INVALID_INFO_CLASS
);
1792 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
1795 * Hand the request to a subhandler.
1797 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
1800 if (UnsafeResultLength
!= NULL
)
1802 if (PreviousMode
!= KernelMode
)
1806 *UnsafeResultLength
= ResultLength
;
1808 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
1810 FStatus
= _SEH_GetExceptionCode();
1816 *UnsafeResultLength
= ResultLength
;
1821 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
1823 FStatus
= _SEH_GetExceptionCode();
1833 NtSetSystemInformation (
1834 IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1835 IN PVOID SystemInformation
,
1836 IN ULONG SystemInformationLength
1842 * If called from user mode, check
1843 * possible unsafe arguments.
1846 if (KernelMode
!= KeGetPreviousMode())
1850 // SystemInformation,
1860 * Check the request is valid.
1862 if ( (SystemInformationClass
>= SystemBasicInformation
)
1863 && (SystemInformationClass
< MaxSystemInfoClass
)
1866 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
1869 * Hand the request to a subhandler.
1871 return CallQS
[SystemInformationClass
].Set (
1873 SystemInformationLength
1877 return (STATUS_INVALID_INFO_CLASS
);
1883 NtFlushInstructionCache (
1884 IN HANDLE ProcessHandle
,
1885 IN PVOID BaseAddress
,
1886 IN ULONG NumberOfBytesToFlush
1892 return STATUS_SUCCESS
;
1897 NtGetCurrentProcessorNumber(VOID
)
1899 /* Just return the CPU */
1900 return KeGetCurrentProcessorNumber();