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 VOID
MmPrintMemoryStatistic(VOID
);
19 FAST_MUTEX ExpEnvironmentLock
;
20 ERESOURCE ExpFirmwareTableResource
;
21 LIST_ENTRY ExpFirmwareTableProviderListHead
;
25 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
26 IN PLIST_ENTRY UserModeList
,
27 OUT PRTL_PROCESS_MODULES Modules
,
29 OUT PULONG ReturnLength
)
31 NTSTATUS Status
= STATUS_SUCCESS
;
33 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
34 PLDR_DATA_TABLE_ENTRY LdrEntry
;
35 ANSI_STRING ModuleName
;
36 ULONG ModuleCount
= 0;
37 PLIST_ENTRY NextEntry
;
41 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
42 ModuleInfo
= &Modules
->Modules
[0];
44 /* Loop the kernel list */
45 NextEntry
= KernelModeList
->Flink
;
46 while (NextEntry
!= KernelModeList
)
49 LdrEntry
= CONTAINING_RECORD(NextEntry
,
53 /* Update size and check if we can manage one more entry */
54 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
55 if (Length
>= RequiredLength
)
58 ModuleInfo
->MappedBase
= NULL
;
59 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
60 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
61 ModuleInfo
->Flags
= LdrEntry
->Flags
;
62 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
63 ModuleInfo
->LoadOrderIndex
= (USHORT
)ModuleCount
;
64 ModuleInfo
->InitOrderIndex
= 0;
67 RtlInitEmptyAnsiString(&ModuleName
,
68 ModuleInfo
->FullPathName
,
69 sizeof(ModuleInfo
->FullPathName
));
72 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
73 &LdrEntry
->FullDllName
,
75 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
77 /* Calculate offset to name */
78 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
79 while ((p
> ModuleName
.Buffer
) && (*--p
))
81 /* Check if we found the separator */
82 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
84 /* We did, break out */
91 ModuleInfo
->OffsetToFileName
= p
- ModuleName
.Buffer
;
95 /* Return empty name */
96 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
97 ModuleInfo
->OffsetToFileName
= 0;
100 /* Go to the next module */
106 Status
= STATUS_INFO_LENGTH_MISMATCH
;
109 /* Update count and move to next entry */
111 NextEntry
= NextEntry
->Flink
;
114 /* Check if caller also wanted user modules */
118 DPRINT1("User-mode list not yet supported in ReactOS!\n");
121 /* Update return length */
122 if (ReturnLength
) *ReturnLength
= RequiredLength
;
124 /* Validate the length again */
125 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
127 /* Set the final count */
128 Modules
->NumberOfModules
= ModuleCount
;
132 /* Otherwise, we failed */
133 Status
= STATUS_INFO_LENGTH_MISMATCH
;
140 /* FUNCTIONS *****************************************************************/
145 #undef ExGetPreviousMode
148 ExGetPreviousMode (VOID
)
150 return KeGetPreviousMode();
158 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
162 ULONGLONG ScaledIdle
;
164 Prcb
= KeGetCurrentPrcb();
166 ScaledIdle
= Prcb
->IdleThread
->KernelTime
* 100;
167 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
169 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
179 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
181 PULONG ProcessorNumber
)
185 Prcb
= KeGetCurrentPrcb();
187 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
188 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
189 *ProcessorNumber
= KeGetCurrentProcessorNumber();
197 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
199 /* Quick check to see if it exists at all */
200 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
202 /* Return our support for it */
203 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
211 ExVerifySuite(SUITE_TYPE SuiteType
)
213 if (SuiteType
== Personal
) return TRUE
;
219 NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName
,
220 OUT PWSTR ValueBuffer
,
221 IN ULONG ValueBufferLength
,
222 IN OUT PULONG ReturnLength OPTIONAL
)
225 UNICODE_STRING WName
;
229 UNICODE_STRING WValue
;
230 KPROCESSOR_MODE PreviousMode
;
231 NTSTATUS Status
= STATUS_SUCCESS
;
235 PreviousMode
= ExGetPreviousMode();
237 if(PreviousMode
!= KernelMode
)
241 ProbeForRead(VariableName
,
242 sizeof(UNICODE_STRING
),
244 ProbeForWrite(ValueBuffer
,
247 if(ReturnLength
!= NULL
)
249 ProbeForWriteUlong(ReturnLength
);
252 _SEH2_EXCEPT(ExSystemExceptionFilter())
254 Status
= _SEH2_GetExceptionCode();
258 if(!NT_SUCCESS(Status
))
265 * Copy the name to kernel space if necessary and convert it to ANSI.
267 Status
= ProbeAndCaptureUnicodeString(&WName
,
270 if(NT_SUCCESS(Status
))
273 * according to ntinternals the SeSystemEnvironmentName privilege is required!
275 if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
278 ReleaseCapturedUnicodeString(&WName
,
280 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
281 return STATUS_PRIVILEGE_NOT_HELD
;
285 * convert the value name to ansi
287 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
288 ReleaseCapturedUnicodeString(&WName
,
290 if(!NT_SUCCESS(Status
))
296 * Create a temporary buffer for the value
298 Value
= ExAllocatePool(NonPagedPool
, ValueBufferLength
);
301 RtlFreeAnsiString(&AName
);
302 return STATUS_INSUFFICIENT_RESOURCES
;
306 * Get the environment variable
308 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
309 (USHORT
)ValueBufferLength
,
313 RtlFreeAnsiString(&AName
);
315 return STATUS_UNSUCCESSFUL
;
319 * Convert the result to UNICODE, protect with SEH in case the value buffer
320 * isn't NULL-terminated!
324 RtlInitAnsiString(&AValue
, Value
);
325 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, TRUE
);
327 _SEH2_EXCEPT(ExSystemExceptionFilter())
329 Status
= _SEH2_GetExceptionCode();
333 if(NT_SUCCESS(Status
))
336 * Copy the result back to the caller.
340 RtlCopyMemory(ValueBuffer
, WValue
.Buffer
, WValue
.Length
);
341 ValueBuffer
[WValue
.Length
/ sizeof(WCHAR
)] = L
'\0';
342 if(ReturnLength
!= NULL
)
344 *ReturnLength
= WValue
.Length
+ sizeof(WCHAR
);
347 Status
= STATUS_SUCCESS
;
349 _SEH2_EXCEPT(ExSystemExceptionFilter())
351 Status
= _SEH2_GetExceptionCode();
357 * Cleanup allocated resources.
359 RtlFreeAnsiString(&AName
);
368 NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName
,
369 IN PUNICODE_STRING Value
)
371 UNICODE_STRING CapturedName
, CapturedValue
;
372 ANSI_STRING AName
, AValue
;
373 KPROCESSOR_MODE PreviousMode
;
378 PreviousMode
= ExGetPreviousMode();
381 * Copy the strings to kernel space if necessary
383 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
386 if(NT_SUCCESS(Status
))
388 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
391 if(NT_SUCCESS(Status
))
394 * according to ntinternals the SeSystemEnvironmentName privilege is required!
396 if(SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
400 * convert the strings to ANSI
402 Status
= RtlUnicodeStringToAnsiString(&AName
,
405 if(NT_SUCCESS(Status
))
407 Status
= RtlUnicodeStringToAnsiString(&AValue
,
410 if(NT_SUCCESS(Status
))
412 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
415 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
421 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
422 Status
= STATUS_PRIVILEGE_NOT_HELD
;
425 ReleaseCapturedUnicodeString(&CapturedValue
,
429 ReleaseCapturedUnicodeString(&CapturedName
,
438 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
440 IN ULONG BufferLength
)
443 return STATUS_NOT_IMPLEMENTED
;
448 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
449 IN LPGUID VendorGuid
,
451 IN OUT PULONG ReturnLength
,
452 IN OUT PULONG Attributes
)
455 return STATUS_NOT_IMPLEMENTED
;
460 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
461 IN LPGUID VendorGuid
)
464 return STATUS_NOT_IMPLEMENTED
;
467 /* --- Query/Set System Information --- */
470 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
471 * so the stack is popped only in one place on x86 platform.
473 #define QSI_USE(n) QSI##n
475 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
477 #define SSI_USE(n) SSI##n
479 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
482 /* Class 0 - Basic Information */
483 QSI_DEF(SystemBasicInformation
)
485 PSYSTEM_BASIC_INFORMATION Sbi
486 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
488 *ReqSize
= sizeof (SYSTEM_BASIC_INFORMATION
);
490 * Check user buffer's size
492 if (Size
!= sizeof (SYSTEM_BASIC_INFORMATION
))
494 return (STATUS_INFO_LENGTH_MISMATCH
);
496 RtlZeroMemory(Sbi
, Size
);
498 Sbi
->TimerResolution
= KeMaximumIncrement
;
499 Sbi
->PageSize
= PAGE_SIZE
;
500 Sbi
->NumberOfPhysicalPages
= MmStats
.NrTotalPages
;
501 Sbi
->LowestPhysicalPageNumber
= 0; /* FIXME */
502 Sbi
->HighestPhysicalPageNumber
= MmStats
.NrTotalPages
; /* FIXME */
503 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
504 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
505 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
506 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
507 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
508 return (STATUS_SUCCESS
);
511 /* Class 1 - Processor Information */
512 QSI_DEF(SystemProcessorInformation
)
514 PSYSTEM_PROCESSOR_INFORMATION Spi
515 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
517 *ReqSize
= sizeof (SYSTEM_PROCESSOR_INFORMATION
);
519 * Check user buffer's size
521 if (Size
< sizeof (SYSTEM_PROCESSOR_INFORMATION
))
523 return (STATUS_INFO_LENGTH_MISMATCH
);
525 Prcb
= KeGetCurrentPrcb();
526 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
527 Spi
->ProcessorLevel
= KeProcessorLevel
;
528 Spi
->ProcessorRevision
= KeProcessorRevision
;
530 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
532 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi
->ProcessorArchitecture
,
533 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
535 return (STATUS_SUCCESS
);
538 /* Class 2 - Performance Information */
539 QSI_DEF(SystemPerformanceInformation
)
541 ULONG IdleUser
, IdleKernel
;
542 PSYSTEM_PERFORMANCE_INFORMATION Spi
543 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
545 PEPROCESS TheIdleProcess
;
547 *ReqSize
= sizeof (SYSTEM_PERFORMANCE_INFORMATION
);
549 * Check user buffer's size
551 if (Size
< sizeof (SYSTEM_PERFORMANCE_INFORMATION
))
553 return (STATUS_INFO_LENGTH_MISMATCH
);
556 TheIdleProcess
= PsIdleProcess
;
558 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
559 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
560 Spi
->IoReadTransferCount
= IoReadTransferCount
;
561 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
562 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
563 Spi
->IoReadOperationCount
= IoReadOperationCount
;
564 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
565 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
567 Spi
->AvailablePages
= MmStats
.NrFreePages
;
569 Add up all the used "Committed" memory + pagefile.
570 Not sure this is right. 8^\
572 Spi
->CommittedPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
+
573 MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
+
574 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
575 MiMemoryConsumers
[MC_USER
].PagesUsed
+
578 Add up the full system total + pagefile.
579 All this make Taskmgr happy but not sure it is the right numbers.
580 This too, fixes some of GlobalMemoryStatusEx numbers.
582 Spi
->CommitLimit
= MmStats
.NrTotalPages
+ MiFreeSwapPages
+
585 Spi
->PeakCommitment
= 0; /* FIXME */
586 Spi
->PageFaultCount
= 0; /* FIXME */
587 Spi
->CopyOnWriteCount
= 0; /* FIXME */
588 Spi
->TransitionCount
= 0; /* FIXME */
589 Spi
->CacheTransitionCount
= 0; /* FIXME */
590 Spi
->DemandZeroCount
= 0; /* FIXME */
591 Spi
->PageReadCount
= 0; /* FIXME */
592 Spi
->PageReadIoCount
= 0; /* FIXME */
593 Spi
->CacheReadCount
= 0; /* FIXME */
594 Spi
->CacheIoCount
= 0; /* FIXME */
595 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
596 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
597 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
598 Spi
->MappedWriteIoCount
= 0; /* FIXME */
600 Spi
->PagedPoolPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
;
601 Spi
->PagedPoolAllocs
= 0; /* FIXME */
602 Spi
->PagedPoolFrees
= 0; /* FIXME */
603 Spi
->NonPagedPoolPages
= MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
;
604 Spi
->NonPagedPoolAllocs
= 0; /* FIXME */
605 Spi
->NonPagedPoolFrees
= 0; /* FIXME */
607 Spi
->FreeSystemPtes
= 0; /* FIXME */
609 Spi
->ResidentSystemCodePage
= MmStats
.NrSystemPages
; /* FIXME */
611 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
612 Spi
->TotalSystemCodePages
= 0; /* FIXME */
613 Spi
->NonPagedPoolLookasideHits
= 0; /* FIXME */
614 Spi
->PagedPoolLookasideHits
= 0; /* FIXME */
615 Spi
->Spare3Count
= 0; /* FIXME */
617 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
618 Spi
->ResidentPagedPoolPage
= MmPagedPoolSize
; /* FIXME */
620 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
621 Spi
->CcFastReadNoWait
= 0; /* FIXME */
622 Spi
->CcFastReadWait
= 0; /* FIXME */
623 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
624 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
626 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
627 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
628 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
629 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
631 Spi
->CcMapDataNoWait
= 0; /* FIXME */
632 Spi
->CcMapDataWait
= 0; /* FIXME */
633 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
634 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
636 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
637 Spi
->CcPinReadNoWait
= 0; /* FIXME */
638 Spi
->CcPinReadWait
= 0; /* FIXME */
639 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
640 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
641 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
642 Spi
->CcCopyReadWait
= 0; /* FIXME */
643 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
644 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
646 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
647 Spi
->CcMdlReadWait
= 0; /* FIXME */
648 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
649 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
650 Spi
->CcReadAheadIos
= 0; /* FIXME */
651 Spi
->CcLazyWriteIos
= 0; /* FIXME */
652 Spi
->CcLazyWritePages
= 0; /* FIXME */
653 Spi
->CcDataFlushes
= 0; /* FIXME */
654 Spi
->CcDataPages
= 0; /* FIXME */
655 Spi
->ContextSwitches
= 0; /* FIXME */
656 Spi
->FirstLevelTbFills
= 0; /* FIXME */
657 Spi
->SecondLevelTbFills
= 0; /* FIXME */
658 Spi
->SystemCalls
= 0; /* FIXME */
660 return (STATUS_SUCCESS
);
663 /* Class 3 - Time Of Day Information */
664 QSI_DEF(SystemTimeOfDayInformation
)
666 PSYSTEM_TIMEOFDAY_INFORMATION Sti
;
667 LARGE_INTEGER CurrentTime
;
669 Sti
= (PSYSTEM_TIMEOFDAY_INFORMATION
)Buffer
;
670 *ReqSize
= sizeof (SYSTEM_TIMEOFDAY_INFORMATION
);
672 /* Check user buffer's size */
673 if (Size
!= sizeof (SYSTEM_TIMEOFDAY_INFORMATION
))
675 return STATUS_INFO_LENGTH_MISMATCH
;
678 KeQuerySystemTime(&CurrentTime
);
680 Sti
->BootTime
= KeBootTime
;
681 Sti
->CurrentTime
= CurrentTime
;
682 Sti
->TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
683 Sti
->TimeZoneId
= ExpTimeZoneId
;
686 return STATUS_SUCCESS
;
689 /* Class 4 - Path Information */
690 QSI_DEF(SystemPathInformation
)
692 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
693 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
695 return (STATUS_BREAKPOINT
);
698 /* Class 5 - Process Information */
699 QSI_DEF(SystemProcessInformation
)
701 ULONG ovlSize
= 0, nThreads
;
702 PEPROCESS pr
= NULL
, syspr
;
704 ULONG TotalUser
, TotalKernel
;
705 NTSTATUS Status
= STATUS_SUCCESS
;
709 /* scan the process list */
711 PSYSTEM_PROCESS_INFORMATION Spi
712 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
714 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
716 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
718 _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH
); // in case buffer size is too small
720 RtlZeroMemory(Spi
, Size
);
722 syspr
= PsIdleProcess
;
724 pCur
= (unsigned char *)Spi
;
728 PSYSTEM_PROCESS_INFORMATION SpiCur
;
731 int inLen
=32; // image name len in bytes
732 PLIST_ENTRY current_entry
;
734 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
736 SpiCur
= (PSYSTEM_PROCESS_INFORMATION
)pCur
;
739 current_entry
= pr
->ThreadListHead
.Flink
;
740 while (current_entry
!= &pr
->ThreadListHead
)
743 current_entry
= current_entry
->Flink
;
746 // size of the structure for every process
747 curSize
= sizeof(SYSTEM_PROCESS_INFORMATION
)+sizeof(SYSTEM_THREAD_INFORMATION
)*nThreads
;
748 ovlSize
+= curSize
+inLen
;
753 ObDereferenceObject(pr
);
755 _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH
); // in case buffer size is too small
758 // fill system information
759 SpiCur
->NextEntryOffset
= curSize
+inLen
; // relative offset to the beginnnig of the next structure
760 SpiCur
->NumberOfThreads
= nThreads
;
761 SpiCur
->CreateTime
= pr
->CreateTime
;
762 SpiCur
->ImageName
.Length
= strlen(pr
->ImageFileName
) * sizeof(WCHAR
);
763 SpiCur
->ImageName
.MaximumLength
= (USHORT
)inLen
;
764 SpiCur
->ImageName
.Buffer
= (void*)(pCur
+curSize
);
766 // copy name to the end of the struct
767 if(pr
!= PsIdleProcess
)
769 RtlInitAnsiString(&imgName
, pr
->ImageFileName
);
770 RtlAnsiStringToUnicodeString(&SpiCur
->ImageName
, &imgName
, FALSE
);
774 RtlInitUnicodeString(&SpiCur
->ImageName
, NULL
);
777 SpiCur
->BasePriority
= pr
->Pcb
.BasePriority
;
778 SpiCur
->UniqueProcessId
= pr
->UniqueProcessId
;
779 SpiCur
->InheritedFromUniqueProcessId
= pr
->InheritedFromUniqueProcessId
;
780 SpiCur
->HandleCount
= (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
781 SpiCur
->PeakVirtualSize
= pr
->PeakVirtualSize
;
782 SpiCur
->VirtualSize
= pr
->VirtualSize
;
783 SpiCur
->PageFaultCount
= pr
->Vm
.PageFaultCount
;
784 SpiCur
->PeakWorkingSetSize
= pr
->Vm
.PeakWorkingSetSize
;
785 SpiCur
->WorkingSetSize
= pr
->Vm
.WorkingSetSize
;
786 SpiCur
->QuotaPeakPagedPoolUsage
= pr
->QuotaPeak
[0];
787 SpiCur
->QuotaPagedPoolUsage
= pr
->QuotaUsage
[0];
788 SpiCur
->QuotaPeakNonPagedPoolUsage
= pr
->QuotaPeak
[1];
789 SpiCur
->QuotaNonPagedPoolUsage
= pr
->QuotaUsage
[1];
790 SpiCur
->PagefileUsage
= pr
->QuotaUsage
[2];
791 SpiCur
->PeakPagefileUsage
= pr
->QuotaPeak
[2];
792 SpiCur
->PrivatePageCount
= pr
->CommitCharge
;
793 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCur
+ 1);
795 current_entry
= pr
->ThreadListHead
.Flink
;
796 while (current_entry
!= &pr
->ThreadListHead
)
798 current
= CONTAINING_RECORD(current_entry
, ETHREAD
,
801 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(current
->Tcb
.KernelTime
, KeMaximumIncrement
);
802 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(current
->Tcb
.UserTime
, KeMaximumIncrement
);
803 ThreadInfo
->CreateTime
.QuadPart
= current
->CreateTime
.QuadPart
;
804 ThreadInfo
->WaitTime
= current
->Tcb
.WaitTime
;
805 ThreadInfo
->StartAddress
= (PVOID
) current
->StartAddress
;
806 ThreadInfo
->ClientId
= current
->Cid
;
807 ThreadInfo
->Priority
= current
->Tcb
.Priority
;
808 ThreadInfo
->BasePriority
= current
->Tcb
.BasePriority
;
809 ThreadInfo
->ContextSwitches
= current
->Tcb
.ContextSwitches
;
810 ThreadInfo
->ThreadState
= current
->Tcb
.State
;
811 ThreadInfo
->WaitReason
= current
->Tcb
.WaitReason
;
814 current_entry
= current_entry
->Flink
;
817 /* Query total user/kernel times of a process */
818 TotalKernel
= KeQueryRuntimeProcess(&pr
->Pcb
, &TotalUser
);
819 SpiCur
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
820 SpiCur
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
822 /* Handle idle process entry */
823 if (pr
== PsIdleProcess
) pr
= NULL
;
825 pr
= PsGetNextProcess(pr
);
827 if ((pr
== syspr
) || (pr
== NULL
))
829 SpiCur
->NextEntryOffset
= 0;
833 pCur
= pCur
+ curSize
+ inLen
;
834 } while ((pr
!= syspr
) && (pr
!= NULL
));
837 ObDereferenceObject(pr
);
838 Status
= STATUS_SUCCESS
;
840 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
843 ObDereferenceObject(pr
);
844 Status
= _SEH2_GetExceptionCode();
852 /* Class 6 - Call Count Information */
853 QSI_DEF(SystemCallCountInformation
)
856 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
857 return (STATUS_NOT_IMPLEMENTED
);
860 /* Class 7 - Device Information */
861 QSI_DEF(SystemDeviceInformation
)
863 PSYSTEM_DEVICE_INFORMATION Sdi
864 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
865 PCONFIGURATION_INFORMATION ConfigInfo
;
867 *ReqSize
= sizeof (SYSTEM_DEVICE_INFORMATION
);
869 * Check user buffer's size
871 if (Size
< sizeof (SYSTEM_DEVICE_INFORMATION
))
873 return (STATUS_INFO_LENGTH_MISMATCH
);
876 ConfigInfo
= IoGetConfigurationInformation ();
878 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
879 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
880 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
881 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
882 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
883 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
885 return (STATUS_SUCCESS
);
888 /* Class 8 - Processor Performance Information */
889 QSI_DEF(SystemProcessorPerformanceInformation
)
891 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
892 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
896 LARGE_INTEGER CurrentTime
;
899 *ReqSize
= KeNumberProcessors
* sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
901 /* Check user buffer's size */
904 return STATUS_INFO_LENGTH_MISMATCH
;
907 CurrentTime
.QuadPart
= KeQueryInterruptTime();
908 Prcb
= KeGetPcr()->Prcb
;
909 for (i
= 0; i
< KeNumberProcessors
; i
++)
911 /* Calculate total user and kernel times */
912 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
913 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
914 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
915 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
916 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
917 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
918 Spi
->InterruptCount
= Prcb
->InterruptCount
;
920 Prcb
= (PKPRCB
)((ULONG_PTR
)Prcb
+ PAGE_SIZE
);
923 return STATUS_SUCCESS
;
926 /* Class 9 - Flags Information */
927 QSI_DEF(SystemFlagsInformation
)
929 if (sizeof (SYSTEM_FLAGS_INFORMATION
) != Size
)
931 * ReqSize
= sizeof (SYSTEM_FLAGS_INFORMATION
);
932 return (STATUS_INFO_LENGTH_MISMATCH
);
934 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
935 return (STATUS_SUCCESS
);
938 SSI_DEF(SystemFlagsInformation
)
940 if (sizeof (SYSTEM_FLAGS_INFORMATION
) != Size
)
942 return (STATUS_INFO_LENGTH_MISMATCH
);
944 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
945 return (STATUS_SUCCESS
);
948 /* Class 10 - Call Time Information */
949 QSI_DEF(SystemCallTimeInformation
)
952 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
953 return (STATUS_NOT_IMPLEMENTED
);
956 /* Class 11 - Module Information */
957 QSI_DEF(SystemModuleInformation
)
959 extern LIST_ENTRY PsLoadedModuleList
;
960 return ExpQueryModuleInformation(&PsLoadedModuleList
,
962 (PRTL_PROCESS_MODULES
)Buffer
,
967 /* Class 12 - Locks Information */
968 QSI_DEF(SystemLocksInformation
)
971 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
972 return (STATUS_NOT_IMPLEMENTED
);
975 /* Class 13 - Stack Trace Information */
976 QSI_DEF(SystemStackTraceInformation
)
979 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
980 return (STATUS_NOT_IMPLEMENTED
);
983 /* Class 14 - Paged Pool Information */
984 QSI_DEF(SystemPagedPoolInformation
)
987 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
988 return (STATUS_NOT_IMPLEMENTED
);
991 /* Class 15 - Non Paged Pool Information */
992 QSI_DEF(SystemNonPagedPoolInformation
)
995 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
996 return (STATUS_NOT_IMPLEMENTED
);
1000 /* Class 16 - Handle Information */
1001 QSI_DEF(SystemHandleInformation
)
1003 PEPROCESS pr
, syspr
;
1004 ULONG curSize
, i
= 0;
1007 PSYSTEM_HANDLE_INFORMATION Shi
=
1008 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1010 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1012 if (Size
< sizeof (SYSTEM_HANDLE_INFORMATION
))
1014 * ReqSize
= sizeof (SYSTEM_HANDLE_INFORMATION
);
1015 return (STATUS_INFO_LENGTH_MISMATCH
);
1018 DPRINT("SystemHandleInformation 1\n");
1020 /* First Calc Size from Count. */
1021 syspr
= PsGetNextProcess(NULL
);
1026 hCount
= hCount
+ (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
1027 pr
= PsGetNextProcess(pr
);
1029 if ((pr
== syspr
) || (pr
== NULL
))
1031 } while ((pr
!= syspr
) && (pr
!= NULL
));
1035 ObDereferenceObject(pr
);
1038 DPRINT("SystemHandleInformation 2\n");
1040 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
)+
1041 ( (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1042 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) ));
1044 Shi
->NumberOfHandles
= hCount
;
1049 return (STATUS_INFO_LENGTH_MISMATCH
);
1052 DPRINT("SystemHandleInformation 3\n");
1054 /* Now get Handles from all processs. */
1055 syspr
= PsGetNextProcess(NULL
);
1060 int Count
= 0, HandleCount
;
1062 HandleCount
= (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
1064 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1066 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG_PTR
)pr
->UniqueProcessId
;
1071 pr
= PsGetNextProcess(pr
);
1073 if ((pr
== syspr
) || (pr
== NULL
))
1075 } while ((pr
!= syspr
) && (pr
!= NULL
));
1079 ObDereferenceObject(pr
);
1082 DPRINT("SystemHandleInformation 4\n");
1083 return (STATUS_SUCCESS
);
1087 SSI_DEF(SystemHandleInformation)
1090 return (STATUS_SUCCESS);
1094 /* Class 17 - Information */
1095 QSI_DEF(SystemObjectInformation
)
1098 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1099 return (STATUS_NOT_IMPLEMENTED
);
1102 /* Class 18 - Information */
1103 QSI_DEF(SystemPageFileInformation
)
1105 UNICODE_STRING FileName
; /* FIXME */
1106 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1108 if (Size
< sizeof (SYSTEM_PAGEFILE_INFORMATION
))
1110 * ReqSize
= sizeof (SYSTEM_PAGEFILE_INFORMATION
);
1111 return (STATUS_INFO_LENGTH_MISMATCH
);
1114 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1117 Spfi
->NextEntryOffset
= 0;
1119 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1120 Spfi
->TotalInUse
= MiUsedSwapPages
;
1121 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1122 Spfi
->PageFileName
= FileName
;
1123 return (STATUS_SUCCESS
);
1126 /* Class 19 - Vdm Instemul Information */
1127 QSI_DEF(SystemVdmInstemulInformation
)
1130 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1131 return (STATUS_NOT_IMPLEMENTED
);
1134 /* Class 20 - Vdm Bop Information */
1135 QSI_DEF(SystemVdmBopInformation
)
1138 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1139 return (STATUS_NOT_IMPLEMENTED
);
1142 /* Class 21 - File Cache Information */
1143 QSI_DEF(SystemFileCacheInformation
)
1145 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1147 if (Size
< sizeof (SYSTEM_FILECACHE_INFORMATION
))
1149 * ReqSize
= sizeof (SYSTEM_FILECACHE_INFORMATION
);
1150 return (STATUS_INFO_LENGTH_MISMATCH
);
1153 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1155 /* Return the Byte size not the page size. */
1157 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1159 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1161 Sci
->PageFaultCount
= 0; /* FIXME */
1162 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1163 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1165 return (STATUS_SUCCESS
);
1168 SSI_DEF(SystemFileCacheInformation
)
1170 if (Size
< sizeof (SYSTEM_FILECACHE_INFORMATION
))
1172 return (STATUS_INFO_LENGTH_MISMATCH
);
1175 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1176 return (STATUS_NOT_IMPLEMENTED
);
1179 /* Class 22 - Pool Tag Information */
1180 QSI_DEF(SystemPoolTagInformation
)
1183 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1184 return (STATUS_NOT_IMPLEMENTED
);
1187 /* Class 23 - Interrupt Information for all processors */
1188 QSI_DEF(SystemInterruptInformation
)
1194 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1196 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1198 return (STATUS_INFO_LENGTH_MISMATCH
);
1201 ti
= KeQueryTimeIncrement();
1203 for (i
= 0; i
< KeNumberProcessors
; i
++)
1205 Prcb
= KiProcessorBlock
[i
];
1207 Pcr
= CONTAINING_RECORD(Prcb
, KPCR
, CurrentPrcb
);
1209 Pcr
= CONTAINING_RECORD(Prcb
, KPCR
, Prcb
);
1211 #ifdef _M_ARM // This code should probably be done differently
1212 sii
->ContextSwitches
= Pcr
->ContextSwitches
;
1214 sii
->ContextSwitches
= ((PKIPCR
)Pcr
)->ContextSwitches
;
1216 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1217 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1218 sii
->TimeIncrement
= ti
;
1219 sii
->DpcBypassCount
= 0;
1220 sii
->ApcBypassCount
= 0;
1224 return STATUS_SUCCESS
;
1227 /* Class 24 - DPC Behaviour Information */
1228 QSI_DEF(SystemDpcBehaviourInformation
)
1231 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1232 return (STATUS_NOT_IMPLEMENTED
);
1235 SSI_DEF(SystemDpcBehaviourInformation
)
1238 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1239 return (STATUS_NOT_IMPLEMENTED
);
1242 /* Class 25 - Full Memory Information */
1243 QSI_DEF(SystemFullMemoryInformation
)
1245 PULONG Spi
= (PULONG
) Buffer
;
1247 PEPROCESS TheIdleProcess
;
1249 * ReqSize
= sizeof (ULONG
);
1251 if (sizeof (ULONG
) != Size
)
1253 return (STATUS_INFO_LENGTH_MISMATCH
);
1255 DPRINT("SystemFullMemoryInformation\n");
1257 TheIdleProcess
= PsIdleProcess
;
1259 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1260 TheIdleProcess
->UniqueProcessId
,
1261 TheIdleProcess
->Pcb
.KernelTime
,
1266 MmPrintMemoryStatistic();
1269 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1271 return (STATUS_SUCCESS
);
1274 /* Class 26 - Load Image */
1275 SSI_DEF(SystemLoadGdiDriverInformation
)
1277 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1278 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1279 UNICODE_STRING ImageName
;
1281 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1282 ULONG_PTR EntryPoint
;
1285 PIMAGE_NT_HEADERS NtHeader
;
1288 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1290 /* Incorrect buffer length, fail */
1291 return STATUS_INFO_LENGTH_MISMATCH
;
1294 /* Only kernel-mode can call this function */
1295 if (PreviousMode
!= KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1297 /* Load the driver */
1298 ImageName
= DriverInfo
->DriverName
;
1299 Status
= MmLoadSystemImage(&ImageName
,
1303 (PVOID
)&ModuleObject
,
1305 if (!NT_SUCCESS(Status
)) return Status
;
1307 /* Return the export pointer */
1308 DriverInfo
->ExportSectionPointer
=
1309 RtlImageDirectoryEntryToData(ImageBase
,
1311 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1314 /* Get the entrypoint */
1315 NtHeader
= RtlImageNtHeader(ImageBase
);
1316 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1317 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1319 /* Save other data */
1320 DriverInfo
->ImageAddress
= ImageBase
;
1321 DriverInfo
->SectionPointer
= NULL
;
1322 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1323 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1326 return STATUS_SUCCESS
;
1329 /* Class 27 - Unload Image */
1330 SSI_DEF(SystemUnloadGdiDriverInformation
)
1332 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1333 PLIST_ENTRY NextEntry
;
1334 PVOID BaseAddr
= *((PVOID
*)Buffer
);
1336 if(Size
!= sizeof(PVOID
))
1337 return STATUS_INFO_LENGTH_MISMATCH
;
1339 if(KeGetPreviousMode() != KernelMode
)
1340 return STATUS_PRIVILEGE_NOT_HELD
;
1342 // Scan the module list
1343 NextEntry
= PsLoadedModuleList
.Flink
;
1344 while(NextEntry
!= &PsLoadedModuleList
)
1346 LdrEntry
= CONTAINING_RECORD(NextEntry
,
1347 LDR_DATA_TABLE_ENTRY
,
1350 if (LdrEntry
->DllBase
== BaseAddr
)
1356 NextEntry
= NextEntry
->Flink
;
1359 // Check if we found the image
1360 if(NextEntry
!= &PsLoadedModuleList
)
1362 return MmUnloadSystemImage(LdrEntry
);
1366 DPRINT1("Image 0x%x not found.\n", BaseAddr
);
1367 return STATUS_DLL_NOT_FOUND
;
1372 /* Class 28 - Time Adjustment Information */
1373 QSI_DEF(SystemTimeAdjustmentInformation
)
1375 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
) > Size
)
1377 * ReqSize
= sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
);
1378 return (STATUS_INFO_LENGTH_MISMATCH
);
1381 DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1382 return (STATUS_NOT_IMPLEMENTED
);
1385 SSI_DEF(SystemTimeAdjustmentInformation
)
1387 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
) > Size
)
1389 return (STATUS_INFO_LENGTH_MISMATCH
);
1392 DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1393 return (STATUS_NOT_IMPLEMENTED
);
1396 /* Class 29 - Summary Memory Information */
1397 QSI_DEF(SystemSummaryMemoryInformation
)
1400 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1401 return (STATUS_NOT_IMPLEMENTED
);
1404 /* Class 30 - Next Event Id Information */
1405 QSI_DEF(SystemNextEventIdInformation
)
1408 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1409 return (STATUS_NOT_IMPLEMENTED
);
1412 /* Class 31 - Event Ids Information */
1413 QSI_DEF(SystemEventIdsInformation
)
1416 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1417 return (STATUS_NOT_IMPLEMENTED
);
1420 /* Class 32 - Crash Dump Information */
1421 QSI_DEF(SystemCrashDumpInformation
)
1424 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1425 return (STATUS_NOT_IMPLEMENTED
);
1428 /* Class 33 - Exception Information */
1429 QSI_DEF(SystemExceptionInformation
)
1432 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1433 return (STATUS_NOT_IMPLEMENTED
);
1436 /* Class 34 - Crash Dump State Information */
1437 QSI_DEF(SystemCrashDumpStateInformation
)
1440 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1441 return (STATUS_NOT_IMPLEMENTED
);
1444 /* Class 35 - Kernel Debugger Information */
1445 QSI_DEF(SystemKernelDebuggerInformation
)
1447 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1449 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1450 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1452 return STATUS_INFO_LENGTH_MISMATCH
;
1455 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1456 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1458 return STATUS_SUCCESS
;
1461 /* Class 36 - Context Switch Information */
1462 QSI_DEF(SystemContextSwitchInformation
)
1465 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1466 return (STATUS_NOT_IMPLEMENTED
);
1469 /* Class 37 - Registry Quota Information */
1470 QSI_DEF(SystemRegistryQuotaInformation
)
1472 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1474 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1475 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1477 return STATUS_INFO_LENGTH_MISMATCH
;
1480 DPRINT1("Faking max registry size of 32 MB\n");
1481 srqi
->RegistryQuotaAllowed
= 0x2000000;
1482 srqi
->RegistryQuotaUsed
= 0x200000;
1483 srqi
->PagedPoolSize
= 0x200000;
1485 return STATUS_SUCCESS
;
1488 SSI_DEF(SystemRegistryQuotaInformation
)
1491 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1492 return (STATUS_NOT_IMPLEMENTED
);
1495 /* Class 38 - Load And Call Image */
1496 SSI_DEF(SystemExtendServiceTableInformation
)
1498 UNICODE_STRING ImageName
;
1499 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1500 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1502 PIMAGE_NT_HEADERS NtHeader
;
1503 DRIVER_OBJECT Win32k
;
1504 PDRIVER_INITIALIZE DriverInit
;
1506 ULONG_PTR EntryPoint
;
1508 /* Validate the size */
1509 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1511 /* Check who is calling */
1512 if (PreviousMode
!= KernelMode
)
1514 /* Make sure we can load drivers */
1515 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1517 /* FIXME: We can't, fail */
1518 //return STATUS_PRIVILEGE_NOT_HELD;
1521 /* Probe and capture the driver name */
1522 ProbeAndCaptureUnicodeString(&ImageName
, UserMode
, Buffer
);
1524 /* Force kernel as previous mode */
1525 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1530 /* Just copy the string */
1531 ImageName
= *(PUNICODE_STRING
)Buffer
;
1533 /* Load the image */
1534 Status
= MmLoadSystemImage(&ImageName
,
1538 (PVOID
)&ModuleObject
,
1540 if (!NT_SUCCESS(Status
)) return Status
;
1542 /* Get the headers */
1543 NtHeader
= RtlImageNtHeader(ImageBase
);
1547 MmUnloadSystemImage(ModuleObject
);
1548 return STATUS_INVALID_IMAGE_FORMAT
;
1551 /* Get the entrypoint */
1552 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1553 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1554 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1556 /* Create a dummy device */
1557 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1558 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1559 Win32k
.DriverStart
= ImageBase
;
1562 Status
= (DriverInit
)(&Win32k
, NULL
);
1563 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1565 /* Unload if we failed */
1566 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1570 /* Class 39 - Priority Separation */
1571 SSI_DEF(SystemPrioritySeperation
)
1574 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1575 return (STATUS_NOT_IMPLEMENTED
);
1578 /* Class 40 - Plug Play Bus Information */
1579 QSI_DEF(SystemPlugPlayBusInformation
)
1582 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1583 return (STATUS_NOT_IMPLEMENTED
);
1586 /* Class 41 - Dock Information */
1587 QSI_DEF(SystemDockInformation
)
1590 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1591 return (STATUS_NOT_IMPLEMENTED
);
1594 /* Class 42 - Power Information */
1595 QSI_DEF(SystemPowerInformation
)
1598 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1599 return (STATUS_NOT_IMPLEMENTED
);
1602 /* Class 43 - Processor Speed Information */
1603 QSI_DEF(SystemProcessorSpeedInformation
)
1606 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1607 return (STATUS_NOT_IMPLEMENTED
);
1610 /* Class 44 - Current Time Zone Information */
1611 QSI_DEF(SystemCurrentTimeZoneInformation
)
1613 * ReqSize
= sizeof (TIME_ZONE_INFORMATION
);
1615 if (sizeof (TIME_ZONE_INFORMATION
) != Size
)
1617 return STATUS_INFO_LENGTH_MISMATCH
;
1620 /* Copy the time zone information struct */
1623 sizeof(TIME_ZONE_INFORMATION
));
1625 return STATUS_SUCCESS
;
1629 SSI_DEF(SystemCurrentTimeZoneInformation
)
1631 /* Check user buffer's size */
1632 if (Size
< sizeof (TIME_ZONE_INFORMATION
))
1634 return STATUS_INFO_LENGTH_MISMATCH
;
1637 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1641 /* Class 45 - Lookaside Information */
1642 QSI_DEF(SystemLookasideInformation
)
1645 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1646 return (STATUS_NOT_IMPLEMENTED
);
1650 /* Class 46 - Set time slip event */
1651 SSI_DEF(SystemSetTimeSlipEvent
)
1654 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1655 return (STATUS_NOT_IMPLEMENTED
);
1659 /* Class 47 - Create a new session (TSE) */
1660 SSI_DEF(SystemCreateSession
)
1663 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1664 return (STATUS_NOT_IMPLEMENTED
);
1668 /* Class 48 - Delete an existing session (TSE) */
1669 SSI_DEF(SystemDeleteSession
)
1672 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1673 return (STATUS_NOT_IMPLEMENTED
);
1677 /* Class 49 - UNKNOWN */
1678 QSI_DEF(SystemInvalidInfoClass4
)
1681 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1682 return (STATUS_NOT_IMPLEMENTED
);
1686 /* Class 50 - System range start address */
1687 QSI_DEF(SystemRangeStartInformation
)
1690 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1691 return (STATUS_NOT_IMPLEMENTED
);
1695 /* Class 51 - Driver verifier information */
1696 QSI_DEF(SystemVerifierInformation
)
1699 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1700 return (STATUS_NOT_IMPLEMENTED
);
1704 SSI_DEF(SystemVerifierInformation
)
1707 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1708 return (STATUS_NOT_IMPLEMENTED
);
1712 /* Class 52 - Add a driver verifier */
1713 SSI_DEF(SystemAddVerifier
)
1716 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1717 return (STATUS_NOT_IMPLEMENTED
);
1721 /* Class 53 - A session's processes */
1722 QSI_DEF(SystemSessionProcessesInformation
)
1725 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1726 return (STATUS_NOT_IMPLEMENTED
);
1730 /* Query/Set Calls Table */
1734 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1735 NTSTATUS (* Set
) (PVOID
,ULONG
);
1742 // XX unknown behaviour
1744 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1745 #define SI_QX(n) {QSI_USE(n),NULL}
1746 #define SI_XS(n) {NULL,SSI_USE(n)}
1747 #define SI_XX(n) {NULL,NULL}
1753 SI_QX(SystemBasicInformation
),
1754 SI_QX(SystemProcessorInformation
),
1755 SI_QX(SystemPerformanceInformation
),
1756 SI_QX(SystemTimeOfDayInformation
),
1757 SI_QX(SystemPathInformation
), /* should be SI_XX */
1758 SI_QX(SystemProcessInformation
),
1759 SI_QX(SystemCallCountInformation
),
1760 SI_QX(SystemDeviceInformation
),
1761 SI_QX(SystemProcessorPerformanceInformation
),
1762 SI_QS(SystemFlagsInformation
),
1763 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1764 SI_QX(SystemModuleInformation
),
1765 SI_QX(SystemLocksInformation
),
1766 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1767 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1768 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1769 SI_QX(SystemHandleInformation
),
1770 SI_QX(SystemObjectInformation
),
1771 SI_QX(SystemPageFileInformation
),
1772 SI_QX(SystemVdmInstemulInformation
),
1773 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1774 SI_QS(SystemFileCacheInformation
),
1775 SI_QX(SystemPoolTagInformation
),
1776 SI_QX(SystemInterruptInformation
),
1777 SI_QS(SystemDpcBehaviourInformation
),
1778 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1779 SI_XS(SystemLoadGdiDriverInformation
),
1780 SI_XS(SystemUnloadGdiDriverInformation
),
1781 SI_QS(SystemTimeAdjustmentInformation
),
1782 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1783 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1784 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */
1785 SI_QX(SystemCrashDumpInformation
),
1786 SI_QX(SystemExceptionInformation
),
1787 SI_QX(SystemCrashDumpStateInformation
),
1788 SI_QX(SystemKernelDebuggerInformation
),
1789 SI_QX(SystemContextSwitchInformation
),
1790 SI_QS(SystemRegistryQuotaInformation
),
1791 SI_XS(SystemExtendServiceTableInformation
),
1792 SI_XS(SystemPrioritySeperation
),
1793 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1794 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1795 SI_QX(SystemPowerInformation
), /* it should be SI_XX */
1796 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1797 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
1798 SI_QX(SystemLookasideInformation
),
1799 SI_XS(SystemSetTimeSlipEvent
),
1800 SI_XS(SystemCreateSession
),
1801 SI_XS(SystemDeleteSession
),
1802 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */
1803 SI_QX(SystemRangeStartInformation
),
1804 SI_QS(SystemVerifierInformation
),
1805 SI_XS(SystemAddVerifier
),
1806 SI_QX(SystemSessionProcessesInformation
)
1809 C_ASSERT(SystemBasicInformation
== 0);
1810 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1811 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1817 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1818 OUT PVOID SystemInformation
,
1820 OUT PULONG UnsafeResultLength
)
1822 KPROCESSOR_MODE PreviousMode
;
1824 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
1828 PreviousMode
= ExGetPreviousMode();
1832 if (PreviousMode
!= KernelMode
)
1834 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1835 ProbeForWrite(SystemInformation
, Length
, 1);
1836 if (UnsafeResultLength
!= NULL
)
1837 ProbeForWriteUlong(UnsafeResultLength
);
1841 * Check the request is valid.
1843 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
1845 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
1848 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
1851 * Hand the request to a subhandler.
1853 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
1856 if (UnsafeResultLength
!= NULL
)
1858 if (PreviousMode
!= KernelMode
)
1860 *UnsafeResultLength
= ResultLength
;
1864 *UnsafeResultLength
= ResultLength
;
1869 _SEH2_EXCEPT(ExSystemExceptionFilter())
1871 FStatus
= _SEH2_GetExceptionCode();
1881 NtSetSystemInformation (
1882 IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1883 IN PVOID SystemInformation
,
1884 IN ULONG SystemInformationLength
1890 * If called from user mode, check
1891 * possible unsafe arguments.
1894 if (KernelMode
!= KeGetPreviousMode())
1898 // SystemInformation,
1908 * Check the request is valid.
1910 if ( (SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
)
1911 && (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
)
1914 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
1917 * Hand the request to a subhandler.
1919 return CallQS
[SystemInformationClass
].Set (
1921 SystemInformationLength
1925 return (STATUS_INVALID_INFO_CLASS
);
1931 NtFlushInstructionCache (
1932 IN HANDLE ProcessHandle
,
1933 IN PVOID BaseAddress
,
1934 IN ULONG NumberOfBytesToFlush
1939 #if defined(_M_IX86)
1941 #elif defined(_M_PPC)
1942 __asm__
__volatile__("tlbsync");
1943 #elif defined(_M_MIPS)
1944 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1946 #elif defined(_M_ARM)
1947 __asm__
__volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
1948 #elif defined(_M_AMD64)
1949 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1952 #error Unknown architecture
1954 return STATUS_SUCCESS
;
1959 NtGetCurrentProcessorNumber(VOID
)
1961 /* Just return the CPU */
1962 return KeGetCurrentProcessorNumber();