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 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
254 Status
= _SEH_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 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
329 Status
= _SEH_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 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
351 Status
= _SEH_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 PSYSTEM_PERFORMANCE_INFORMATION Spi
542 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
544 PEPROCESS TheIdleProcess
;
546 *ReqSize
= sizeof (SYSTEM_PERFORMANCE_INFORMATION
);
548 * Check user buffer's size
550 if (Size
< sizeof (SYSTEM_PERFORMANCE_INFORMATION
))
552 return (STATUS_INFO_LENGTH_MISMATCH
);
555 TheIdleProcess
= PsIdleProcess
;
557 Spi
->IdleProcessTime
.QuadPart
= TheIdleProcess
->Pcb
.KernelTime
* 100000LL;
559 Spi
->IoReadTransferCount
= IoReadTransferCount
;
560 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
561 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
562 Spi
->IoReadOperationCount
= IoReadOperationCount
;
563 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
564 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
566 Spi
->AvailablePages
= MmStats
.NrFreePages
;
568 Add up all the used "Committed" memory + pagefile.
569 Not sure this is right. 8^\
571 Spi
->CommittedPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
+
572 MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
+
573 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
574 MiMemoryConsumers
[MC_USER
].PagesUsed
+
577 Add up the full system total + pagefile.
578 All this make Taskmgr happy but not sure it is the right numbers.
579 This too, fixes some of GlobalMemoryStatusEx numbers.
581 Spi
->CommitLimit
= MmStats
.NrTotalPages
+ MiFreeSwapPages
+
584 Spi
->PeakCommitment
= 0; /* FIXME */
585 Spi
->PageFaultCount
= 0; /* FIXME */
586 Spi
->CopyOnWriteCount
= 0; /* FIXME */
587 Spi
->TransitionCount
= 0; /* FIXME */
588 Spi
->CacheTransitionCount
= 0; /* FIXME */
589 Spi
->DemandZeroCount
= 0; /* FIXME */
590 Spi
->PageReadCount
= 0; /* FIXME */
591 Spi
->PageReadIoCount
= 0; /* FIXME */
592 Spi
->CacheReadCount
= 0; /* FIXME */
593 Spi
->CacheIoCount
= 0; /* FIXME */
594 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
595 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
596 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
597 Spi
->MappedWriteIoCount
= 0; /* FIXME */
599 Spi
->PagedPoolPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
;
600 Spi
->PagedPoolAllocs
= 0; /* FIXME */
601 Spi
->PagedPoolFrees
= 0; /* FIXME */
602 Spi
->NonPagedPoolPages
= MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
;
603 Spi
->NonPagedPoolAllocs
= 0; /* FIXME */
604 Spi
->NonPagedPoolFrees
= 0; /* FIXME */
606 Spi
->FreeSystemPtes
= 0; /* FIXME */
608 Spi
->ResidentSystemCodePage
= MmStats
.NrSystemPages
; /* FIXME */
610 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
611 Spi
->TotalSystemCodePages
= 0; /* FIXME */
612 Spi
->NonPagedPoolLookasideHits
= 0; /* FIXME */
613 Spi
->PagedPoolLookasideHits
= 0; /* FIXME */
614 Spi
->Spare3Count
= 0; /* FIXME */
616 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
617 Spi
->ResidentPagedPoolPage
= MmPagedPoolSize
; /* FIXME */
619 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
620 Spi
->CcFastReadNoWait
= 0; /* FIXME */
621 Spi
->CcFastReadWait
= 0; /* FIXME */
622 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
623 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
625 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
626 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
627 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
628 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
630 Spi
->CcMapDataNoWait
= 0; /* FIXME */
631 Spi
->CcMapDataWait
= 0; /* FIXME */
632 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
633 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
635 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
636 Spi
->CcPinReadNoWait
= 0; /* FIXME */
637 Spi
->CcPinReadWait
= 0; /* FIXME */
638 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
639 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
640 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
641 Spi
->CcCopyReadWait
= 0; /* FIXME */
642 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
643 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
645 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
646 Spi
->CcMdlReadWait
= 0; /* FIXME */
647 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
648 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
649 Spi
->CcReadAheadIos
= 0; /* FIXME */
650 Spi
->CcLazyWriteIos
= 0; /* FIXME */
651 Spi
->CcLazyWritePages
= 0; /* FIXME */
652 Spi
->CcDataFlushes
= 0; /* FIXME */
653 Spi
->CcDataPages
= 0; /* FIXME */
654 Spi
->ContextSwitches
= 0; /* FIXME */
655 Spi
->FirstLevelTbFills
= 0; /* FIXME */
656 Spi
->SecondLevelTbFills
= 0; /* FIXME */
657 Spi
->SystemCalls
= 0; /* FIXME */
659 return (STATUS_SUCCESS
);
662 /* Class 3 - Time Of Day Information */
663 QSI_DEF(SystemTimeOfDayInformation
)
665 PSYSTEM_TIMEOFDAY_INFORMATION Sti
;
666 LARGE_INTEGER CurrentTime
;
668 Sti
= (PSYSTEM_TIMEOFDAY_INFORMATION
)Buffer
;
669 *ReqSize
= sizeof (SYSTEM_TIMEOFDAY_INFORMATION
);
671 /* Check user buffer's size */
672 if (Size
!= sizeof (SYSTEM_TIMEOFDAY_INFORMATION
))
674 return STATUS_INFO_LENGTH_MISMATCH
;
677 KeQuerySystemTime(&CurrentTime
);
679 Sti
->BootTime
= KeBootTime
;
680 Sti
->CurrentTime
= CurrentTime
;
681 Sti
->TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
682 Sti
->TimeZoneId
= ExpTimeZoneId
;
685 return STATUS_SUCCESS
;
688 /* Class 4 - Path Information */
689 QSI_DEF(SystemPathInformation
)
691 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
692 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
694 return (STATUS_BREAKPOINT
);
697 /* Class 5 - Process Information */
698 QSI_DEF(SystemProcessInformation
)
700 ULONG ovlSize
= 0, nThreads
;
701 PEPROCESS pr
= NULL
, syspr
;
703 NTSTATUS Status
= STATUS_SUCCESS
;
707 /* scan the process list */
709 PSYSTEM_PROCESS_INFORMATION Spi
710 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
712 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
714 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
716 _SEH_YIELD(return STATUS_INFO_LENGTH_MISMATCH
); // in case buffer size is too small
718 RtlZeroMemory(Spi
, Size
);
720 syspr
= PsIdleProcess
;
722 pCur
= (unsigned char *)Spi
;
726 PSYSTEM_PROCESS_INFORMATION SpiCur
;
729 int inLen
=32; // image name len in bytes
730 PLIST_ENTRY current_entry
;
732 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
734 SpiCur
= (PSYSTEM_PROCESS_INFORMATION
)pCur
;
737 current_entry
= pr
->ThreadListHead
.Flink
;
738 while (current_entry
!= &pr
->ThreadListHead
)
741 current_entry
= current_entry
->Flink
;
744 // size of the structure for every process
745 curSize
= sizeof(SYSTEM_PROCESS_INFORMATION
)+sizeof(SYSTEM_THREAD_INFORMATION
)*nThreads
;
746 ovlSize
+= curSize
+inLen
;
751 ObDereferenceObject(pr
);
753 _SEH_YIELD(return STATUS_INFO_LENGTH_MISMATCH
); // in case buffer size is too small
756 // fill system information
757 SpiCur
->NextEntryOffset
= curSize
+inLen
; // relative offset to the beginnnig of the next structure
758 SpiCur
->NumberOfThreads
= nThreads
;
759 SpiCur
->CreateTime
= pr
->CreateTime
;
760 SpiCur
->UserTime
.QuadPart
= pr
->Pcb
.UserTime
* 100000LL;
761 SpiCur
->KernelTime
.QuadPart
= pr
->Pcb
.KernelTime
* 100000LL;
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
= current
->Tcb
.KernelTime
* 100000LL;
802 ThreadInfo
->UserTime
.QuadPart
= current
->Tcb
.UserTime
* 100000LL;
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
;
813 current_entry
= current_entry
->Flink
;
816 /* Handle idle process entry */
817 if (pr
== PsIdleProcess
) pr
= NULL
;
819 pr
= PsGetNextProcess(pr
);
821 if ((pr
== syspr
) || (pr
== NULL
))
823 SpiCur
->NextEntryOffset
= 0;
827 pCur
= pCur
+ curSize
+ inLen
;
828 } while ((pr
!= syspr
) && (pr
!= NULL
));
831 ObDereferenceObject(pr
);
832 Status
= STATUS_SUCCESS
;
837 ObDereferenceObject(pr
);
838 Status
= _SEH_GetExceptionCode();
846 /* Class 6 - Call Count Information */
847 QSI_DEF(SystemCallCountInformation
)
850 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
851 return (STATUS_NOT_IMPLEMENTED
);
854 /* Class 7 - Device Information */
855 QSI_DEF(SystemDeviceInformation
)
857 PSYSTEM_DEVICE_INFORMATION Sdi
858 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
859 PCONFIGURATION_INFORMATION ConfigInfo
;
861 *ReqSize
= sizeof (SYSTEM_DEVICE_INFORMATION
);
863 * Check user buffer's size
865 if (Size
< sizeof (SYSTEM_DEVICE_INFORMATION
))
867 return (STATUS_INFO_LENGTH_MISMATCH
);
870 ConfigInfo
= IoGetConfigurationInformation ();
872 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
873 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
874 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
875 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
876 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
877 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
879 return (STATUS_SUCCESS
);
882 /* Class 8 - Processor Performance Information */
883 QSI_DEF(SystemProcessorPerformanceInformation
)
885 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
886 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
889 LARGE_INTEGER CurrentTime
;
892 *ReqSize
= KeNumberProcessors
* sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
894 * Check user buffer's size
896 if (Size
< KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
))
898 return (STATUS_INFO_LENGTH_MISMATCH
);
901 CurrentTime
.QuadPart
= KeQueryInterruptTime();
902 Prcb
= KeGetCurrentPrcb();
903 for (i
= 0; i
< KeNumberProcessors
; i
++)
905 Spi
->IdleTime
.QuadPart
= (Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
) * 100000LL;
906 Spi
->KernelTime
.QuadPart
= Prcb
->KernelTime
* 100000LL;
907 Spi
->UserTime
.QuadPart
= Prcb
->UserTime
* 100000LL;
908 Spi
->DpcTime
.QuadPart
= Prcb
->DpcTime
* 100000LL;
909 Spi
->InterruptTime
.QuadPart
= Prcb
->InterruptTime
* 100000LL;
910 Spi
->InterruptCount
= Prcb
->InterruptCount
;
912 Prcb
= (PKPRCB
)((ULONG_PTR
)Prcb
+ PAGE_SIZE
);
915 return (STATUS_SUCCESS
);
918 /* Class 9 - Flags Information */
919 QSI_DEF(SystemFlagsInformation
)
921 if (sizeof (SYSTEM_FLAGS_INFORMATION
) != Size
)
923 * ReqSize
= sizeof (SYSTEM_FLAGS_INFORMATION
);
924 return (STATUS_INFO_LENGTH_MISMATCH
);
926 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
927 return (STATUS_SUCCESS
);
930 SSI_DEF(SystemFlagsInformation
)
932 if (sizeof (SYSTEM_FLAGS_INFORMATION
) != Size
)
934 return (STATUS_INFO_LENGTH_MISMATCH
);
936 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
937 return (STATUS_SUCCESS
);
940 /* Class 10 - Call Time Information */
941 QSI_DEF(SystemCallTimeInformation
)
944 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
945 return (STATUS_NOT_IMPLEMENTED
);
948 /* Class 11 - Module Information */
949 QSI_DEF(SystemModuleInformation
)
951 extern LIST_ENTRY PsLoadedModuleList
;
952 return ExpQueryModuleInformation(&PsLoadedModuleList
,
954 (PRTL_PROCESS_MODULES
)Buffer
,
959 /* Class 12 - Locks Information */
960 QSI_DEF(SystemLocksInformation
)
963 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
964 return (STATUS_NOT_IMPLEMENTED
);
967 /* Class 13 - Stack Trace Information */
968 QSI_DEF(SystemStackTraceInformation
)
971 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
972 return (STATUS_NOT_IMPLEMENTED
);
975 /* Class 14 - Paged Pool Information */
976 QSI_DEF(SystemPagedPoolInformation
)
979 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
980 return (STATUS_NOT_IMPLEMENTED
);
983 /* Class 15 - Non Paged Pool Information */
984 QSI_DEF(SystemNonPagedPoolInformation
)
987 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
988 return (STATUS_NOT_IMPLEMENTED
);
992 /* Class 16 - Handle Information */
993 QSI_DEF(SystemHandleInformation
)
996 ULONG curSize
, i
= 0;
999 PSYSTEM_HANDLE_INFORMATION Shi
=
1000 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1002 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1004 if (Size
< sizeof (SYSTEM_HANDLE_INFORMATION
))
1006 * ReqSize
= sizeof (SYSTEM_HANDLE_INFORMATION
);
1007 return (STATUS_INFO_LENGTH_MISMATCH
);
1010 DPRINT("SystemHandleInformation 1\n");
1012 /* First Calc Size from Count. */
1013 syspr
= PsGetNextProcess(NULL
);
1018 hCount
= hCount
+ (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
1019 pr
= PsGetNextProcess(pr
);
1021 if ((pr
== syspr
) || (pr
== NULL
))
1023 } while ((pr
!= syspr
) && (pr
!= NULL
));
1027 ObDereferenceObject(pr
);
1030 DPRINT("SystemHandleInformation 2\n");
1032 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
)+
1033 ( (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1034 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) ));
1036 Shi
->NumberOfHandles
= hCount
;
1041 return (STATUS_INFO_LENGTH_MISMATCH
);
1044 DPRINT("SystemHandleInformation 3\n");
1046 /* Now get Handles from all processs. */
1047 syspr
= PsGetNextProcess(NULL
);
1052 int Count
= 0, HandleCount
;
1054 HandleCount
= (pr
->ObjectTable
? ObpGetHandleCountByHandleTable(pr
->ObjectTable
) : 0);
1056 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1058 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG
)pr
->UniqueProcessId
;
1063 pr
= PsGetNextProcess(pr
);
1065 if ((pr
== syspr
) || (pr
== NULL
))
1067 } while ((pr
!= syspr
) && (pr
!= NULL
));
1071 ObDereferenceObject(pr
);
1074 DPRINT("SystemHandleInformation 4\n");
1075 return (STATUS_SUCCESS
);
1079 SSI_DEF(SystemHandleInformation)
1082 return (STATUS_SUCCESS);
1086 /* Class 17 - Information */
1087 QSI_DEF(SystemObjectInformation
)
1090 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1091 return (STATUS_NOT_IMPLEMENTED
);
1094 /* Class 18 - Information */
1095 QSI_DEF(SystemPageFileInformation
)
1097 UNICODE_STRING FileName
; /* FIXME */
1098 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1100 if (Size
< sizeof (SYSTEM_PAGEFILE_INFORMATION
))
1102 * ReqSize
= sizeof (SYSTEM_PAGEFILE_INFORMATION
);
1103 return (STATUS_INFO_LENGTH_MISMATCH
);
1106 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1109 Spfi
->NextEntryOffset
= 0;
1111 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1112 Spfi
->TotalInUse
= MiUsedSwapPages
;
1113 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1114 Spfi
->PageFileName
= FileName
;
1115 return (STATUS_SUCCESS
);
1118 /* Class 19 - Vdm Instemul Information */
1119 QSI_DEF(SystemVdmInstemulInformation
)
1122 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1123 return (STATUS_NOT_IMPLEMENTED
);
1126 /* Class 20 - Vdm Bop Information */
1127 QSI_DEF(SystemVdmBopInformation
)
1130 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1131 return (STATUS_NOT_IMPLEMENTED
);
1134 /* Class 21 - File Cache Information */
1135 QSI_DEF(SystemFileCacheInformation
)
1137 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1139 if (Size
< sizeof (SYSTEM_FILECACHE_INFORMATION
))
1141 * ReqSize
= sizeof (SYSTEM_FILECACHE_INFORMATION
);
1142 return (STATUS_INFO_LENGTH_MISMATCH
);
1145 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1147 /* Return the Byte size not the page size. */
1149 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1151 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1153 Sci
->PageFaultCount
= 0; /* FIXME */
1154 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1155 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1157 return (STATUS_SUCCESS
);
1160 SSI_DEF(SystemFileCacheInformation
)
1162 if (Size
< sizeof (SYSTEM_FILECACHE_INFORMATION
))
1164 return (STATUS_INFO_LENGTH_MISMATCH
);
1167 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1168 return (STATUS_NOT_IMPLEMENTED
);
1171 /* Class 22 - Pool Tag Information */
1172 QSI_DEF(SystemPoolTagInformation
)
1175 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1176 return (STATUS_NOT_IMPLEMENTED
);
1179 /* Class 23 - Interrupt Information for all processors */
1180 QSI_DEF(SystemInterruptInformation
)
1186 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1188 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1190 return (STATUS_INFO_LENGTH_MISMATCH
);
1193 ti
= KeQueryTimeIncrement();
1195 for (i
= 0; i
< KeNumberProcessors
; i
++)
1197 Prcb
= KiProcessorBlock
[i
];
1199 Pcr
= CONTAINING_RECORD(Prcb
, KPCR
, CurrentPrcb
);
1201 Pcr
= CONTAINING_RECORD(Prcb
, KPCR
, Prcb
);
1203 #ifdef _M_ARM // This code should probably be done differently
1204 sii
->ContextSwitches
= Pcr
->ContextSwitches
;
1206 sii
->ContextSwitches
= ((PKIPCR
)Pcr
)->ContextSwitches
;
1208 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1209 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1210 sii
->TimeIncrement
= ti
;
1211 sii
->DpcBypassCount
= 0;
1212 sii
->ApcBypassCount
= 0;
1216 return STATUS_SUCCESS
;
1219 /* Class 24 - DPC Behaviour Information */
1220 QSI_DEF(SystemDpcBehaviourInformation
)
1223 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1224 return (STATUS_NOT_IMPLEMENTED
);
1227 SSI_DEF(SystemDpcBehaviourInformation
)
1230 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1231 return (STATUS_NOT_IMPLEMENTED
);
1234 /* Class 25 - Full Memory Information */
1235 QSI_DEF(SystemFullMemoryInformation
)
1237 PULONG Spi
= (PULONG
) Buffer
;
1239 PEPROCESS TheIdleProcess
;
1241 * ReqSize
= sizeof (ULONG
);
1243 if (sizeof (ULONG
) != Size
)
1245 return (STATUS_INFO_LENGTH_MISMATCH
);
1247 DPRINT("SystemFullMemoryInformation\n");
1249 TheIdleProcess
= PsIdleProcess
;
1251 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1252 TheIdleProcess
->UniqueProcessId
,
1253 TheIdleProcess
->Pcb
.KernelTime
,
1258 MmPrintMemoryStatistic();
1261 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1263 return (STATUS_SUCCESS
);
1266 /* Class 26 - Load Image */
1267 SSI_DEF(SystemLoadGdiDriverInformation
)
1269 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1270 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1271 UNICODE_STRING ImageName
;
1273 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1274 ULONG_PTR EntryPoint
;
1277 PIMAGE_NT_HEADERS NtHeader
;
1280 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1282 /* Incorrect buffer length, fail */
1283 return STATUS_INFO_LENGTH_MISMATCH
;
1286 /* Only kernel-mode can call this function */
1287 if (PreviousMode
!= KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1289 /* Load the driver */
1290 ImageName
= DriverInfo
->DriverName
;
1291 Status
= MmLoadSystemImage(&ImageName
,
1295 (PVOID
)&ModuleObject
,
1297 if (!NT_SUCCESS(Status
)) return Status
;
1299 /* Return the export pointer */
1300 DriverInfo
->ExportSectionPointer
=
1301 RtlImageDirectoryEntryToData(ImageBase
,
1303 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1306 /* Get the entrypoint */
1307 NtHeader
= RtlImageNtHeader(ImageBase
);
1308 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1309 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1311 /* Save other data */
1312 DriverInfo
->ImageAddress
= ImageBase
;
1313 DriverInfo
->SectionPointer
= NULL
;
1314 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1315 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1318 return STATUS_SUCCESS
;
1321 /* Class 27 - Unload Image */
1322 SSI_DEF(SystemUnloadGdiDriverInformation
)
1324 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1325 PLIST_ENTRY NextEntry
;
1326 PVOID BaseAddr
= *((PVOID
*)Buffer
);
1328 if(Size
!= sizeof(PVOID
))
1329 return STATUS_INFO_LENGTH_MISMATCH
;
1331 if(KeGetPreviousMode() != KernelMode
)
1332 return STATUS_PRIVILEGE_NOT_HELD
;
1334 // Scan the module list
1335 NextEntry
= PsLoadedModuleList
.Flink
;
1336 while(NextEntry
!= &PsLoadedModuleList
)
1338 LdrEntry
= CONTAINING_RECORD(NextEntry
,
1339 LDR_DATA_TABLE_ENTRY
,
1342 if (LdrEntry
->DllBase
== BaseAddr
)
1348 NextEntry
= NextEntry
->Flink
;
1351 // Check if we found the image
1352 if(NextEntry
!= &PsLoadedModuleList
)
1354 return MmUnloadSystemImage(LdrEntry
);
1358 DPRINT1("Image 0x%x not found.\n", BaseAddr
);
1359 return STATUS_DLL_NOT_FOUND
;
1364 /* Class 28 - Time Adjustment Information */
1365 QSI_DEF(SystemTimeAdjustmentInformation
)
1367 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
) > Size
)
1369 * ReqSize
= sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
);
1370 return (STATUS_INFO_LENGTH_MISMATCH
);
1373 DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1374 return (STATUS_NOT_IMPLEMENTED
);
1377 SSI_DEF(SystemTimeAdjustmentInformation
)
1379 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION
) > Size
)
1381 return (STATUS_INFO_LENGTH_MISMATCH
);
1384 DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1385 return (STATUS_NOT_IMPLEMENTED
);
1388 /* Class 29 - Summary Memory Information */
1389 QSI_DEF(SystemSummaryMemoryInformation
)
1392 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1393 return (STATUS_NOT_IMPLEMENTED
);
1396 /* Class 30 - Next Event Id Information */
1397 QSI_DEF(SystemNextEventIdInformation
)
1400 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1401 return (STATUS_NOT_IMPLEMENTED
);
1404 /* Class 31 - Event Ids Information */
1405 QSI_DEF(SystemEventIdsInformation
)
1408 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1409 return (STATUS_NOT_IMPLEMENTED
);
1412 /* Class 32 - Crash Dump Information */
1413 QSI_DEF(SystemCrashDumpInformation
)
1416 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1417 return (STATUS_NOT_IMPLEMENTED
);
1420 /* Class 33 - Exception Information */
1421 QSI_DEF(SystemExceptionInformation
)
1424 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1425 return (STATUS_NOT_IMPLEMENTED
);
1428 /* Class 34 - Crash Dump State Information */
1429 QSI_DEF(SystemCrashDumpStateInformation
)
1432 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1433 return (STATUS_NOT_IMPLEMENTED
);
1436 /* Class 35 - Kernel Debugger Information */
1437 QSI_DEF(SystemKernelDebuggerInformation
)
1439 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1441 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1442 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1444 return STATUS_INFO_LENGTH_MISMATCH
;
1447 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1448 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1450 return STATUS_SUCCESS
;
1453 /* Class 36 - Context Switch Information */
1454 QSI_DEF(SystemContextSwitchInformation
)
1457 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1458 return (STATUS_NOT_IMPLEMENTED
);
1461 /* Class 37 - Registry Quota Information */
1462 QSI_DEF(SystemRegistryQuotaInformation
)
1464 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1466 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1467 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1469 return STATUS_INFO_LENGTH_MISMATCH
;
1472 DPRINT1("Faking max registry size of 32 MB\n");
1473 srqi
->RegistryQuotaAllowed
= 0x2000000;
1474 srqi
->RegistryQuotaUsed
= 0x200000;
1475 srqi
->PagedPoolSize
= 0x200000;
1477 return STATUS_SUCCESS
;
1480 SSI_DEF(SystemRegistryQuotaInformation
)
1483 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1484 return (STATUS_NOT_IMPLEMENTED
);
1487 /* Class 38 - Load And Call Image */
1488 SSI_DEF(SystemExtendServiceTableInformation
)
1490 UNICODE_STRING ImageName
;
1491 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1492 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1494 PIMAGE_NT_HEADERS NtHeader
;
1495 DRIVER_OBJECT Win32k
;
1496 PDRIVER_INITIALIZE DriverInit
;
1498 ULONG_PTR EntryPoint
;
1500 /* Validate the size */
1501 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1503 /* Check who is calling */
1504 if (PreviousMode
!= KernelMode
)
1506 /* Make sure we can load drivers */
1507 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1509 /* FIXME: We can't, fail */
1510 //return STATUS_PRIVILEGE_NOT_HELD;
1513 /* Probe and capture the driver name */
1514 ProbeAndCaptureUnicodeString(&ImageName
, UserMode
, Buffer
);
1516 /* Force kernel as previous mode */
1517 return ZwSetSystemInformation(SystemExtendServiceTableInformation
,
1522 /* Just copy the string */
1523 ImageName
= *(PUNICODE_STRING
)Buffer
;
1525 /* Load the image */
1526 Status
= MmLoadSystemImage(&ImageName
,
1530 (PVOID
)&ModuleObject
,
1532 if (!NT_SUCCESS(Status
)) return Status
;
1534 /* Get the headers */
1535 NtHeader
= RtlImageNtHeader(ImageBase
);
1539 MmUnloadSystemImage(ModuleObject
);
1540 return STATUS_INVALID_IMAGE_FORMAT
;
1543 /* Get the entrypoint */
1544 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1545 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1546 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1548 /* Create a dummy device */
1549 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1550 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1551 Win32k
.DriverStart
= ImageBase
;
1554 Status
= (DriverInit
)(&Win32k
, NULL
);
1555 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1557 /* Unload if we failed */
1558 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1562 /* Class 39 - Priority Separation */
1563 SSI_DEF(SystemPrioritySeperation
)
1566 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1567 return (STATUS_NOT_IMPLEMENTED
);
1570 /* Class 40 - Plug Play Bus Information */
1571 QSI_DEF(SystemPlugPlayBusInformation
)
1574 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1575 return (STATUS_NOT_IMPLEMENTED
);
1578 /* Class 41 - Dock Information */
1579 QSI_DEF(SystemDockInformation
)
1582 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1583 return (STATUS_NOT_IMPLEMENTED
);
1586 /* Class 42 - Power Information */
1587 QSI_DEF(SystemPowerInformation
)
1590 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1591 return (STATUS_NOT_IMPLEMENTED
);
1594 /* Class 43 - Processor Speed Information */
1595 QSI_DEF(SystemProcessorSpeedInformation
)
1598 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1599 return (STATUS_NOT_IMPLEMENTED
);
1602 /* Class 44 - Current Time Zone Information */
1603 QSI_DEF(SystemCurrentTimeZoneInformation
)
1605 * ReqSize
= sizeof (TIME_ZONE_INFORMATION
);
1607 if (sizeof (TIME_ZONE_INFORMATION
) != Size
)
1609 return STATUS_INFO_LENGTH_MISMATCH
;
1612 /* Copy the time zone information struct */
1615 sizeof(TIME_ZONE_INFORMATION
));
1617 return STATUS_SUCCESS
;
1621 SSI_DEF(SystemCurrentTimeZoneInformation
)
1623 /* Check user buffer's size */
1624 if (Size
< sizeof (TIME_ZONE_INFORMATION
))
1626 return STATUS_INFO_LENGTH_MISMATCH
;
1629 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1633 /* Class 45 - Lookaside Information */
1634 QSI_DEF(SystemLookasideInformation
)
1637 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1638 return (STATUS_NOT_IMPLEMENTED
);
1642 /* Class 46 - Set time slip event */
1643 SSI_DEF(SystemSetTimeSlipEvent
)
1646 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1647 return (STATUS_NOT_IMPLEMENTED
);
1651 /* Class 47 - Create a new session (TSE) */
1652 SSI_DEF(SystemCreateSession
)
1655 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1656 return (STATUS_NOT_IMPLEMENTED
);
1660 /* Class 48 - Delete an existing session (TSE) */
1661 SSI_DEF(SystemDeleteSession
)
1664 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1665 return (STATUS_NOT_IMPLEMENTED
);
1669 /* Class 49 - UNKNOWN */
1670 QSI_DEF(SystemInvalidInfoClass4
)
1673 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1674 return (STATUS_NOT_IMPLEMENTED
);
1678 /* Class 50 - System range start address */
1679 QSI_DEF(SystemRangeStartInformation
)
1682 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1683 return (STATUS_NOT_IMPLEMENTED
);
1687 /* Class 51 - Driver verifier information */
1688 QSI_DEF(SystemVerifierInformation
)
1691 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1692 return (STATUS_NOT_IMPLEMENTED
);
1696 SSI_DEF(SystemVerifierInformation
)
1699 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1700 return (STATUS_NOT_IMPLEMENTED
);
1704 /* Class 52 - Add a driver verifier */
1705 SSI_DEF(SystemAddVerifier
)
1708 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1709 return (STATUS_NOT_IMPLEMENTED
);
1713 /* Class 53 - A session's processes */
1714 QSI_DEF(SystemSessionProcessesInformation
)
1717 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1718 return (STATUS_NOT_IMPLEMENTED
);
1722 /* Query/Set Calls Table */
1726 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1727 NTSTATUS (* Set
) (PVOID
,ULONG
);
1734 // XX unknown behaviour
1736 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1737 #define SI_QX(n) {QSI_USE(n),NULL}
1738 #define SI_XS(n) {NULL,SSI_USE(n)}
1739 #define SI_XX(n) {NULL,NULL}
1745 SI_QX(SystemBasicInformation
),
1746 SI_QX(SystemProcessorInformation
),
1747 SI_QX(SystemPerformanceInformation
),
1748 SI_QX(SystemTimeOfDayInformation
),
1749 SI_QX(SystemPathInformation
), /* should be SI_XX */
1750 SI_QX(SystemProcessInformation
),
1751 SI_QX(SystemCallCountInformation
),
1752 SI_QX(SystemDeviceInformation
),
1753 SI_QX(SystemProcessorPerformanceInformation
),
1754 SI_QS(SystemFlagsInformation
),
1755 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1756 SI_QX(SystemModuleInformation
),
1757 SI_QX(SystemLocksInformation
),
1758 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1759 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1760 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1761 SI_QX(SystemHandleInformation
),
1762 SI_QX(SystemObjectInformation
),
1763 SI_QX(SystemPageFileInformation
),
1764 SI_QX(SystemVdmInstemulInformation
),
1765 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1766 SI_QS(SystemFileCacheInformation
),
1767 SI_QX(SystemPoolTagInformation
),
1768 SI_QX(SystemInterruptInformation
),
1769 SI_QS(SystemDpcBehaviourInformation
),
1770 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1771 SI_XS(SystemLoadGdiDriverInformation
),
1772 SI_XS(SystemUnloadGdiDriverInformation
),
1773 SI_QS(SystemTimeAdjustmentInformation
),
1774 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1775 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1776 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */
1777 SI_QX(SystemCrashDumpInformation
),
1778 SI_QX(SystemExceptionInformation
),
1779 SI_QX(SystemCrashDumpStateInformation
),
1780 SI_QX(SystemKernelDebuggerInformation
),
1781 SI_QX(SystemContextSwitchInformation
),
1782 SI_QS(SystemRegistryQuotaInformation
),
1783 SI_XS(SystemExtendServiceTableInformation
),
1784 SI_XS(SystemPrioritySeperation
),
1785 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1786 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1787 SI_QX(SystemPowerInformation
), /* it should be SI_XX */
1788 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1789 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
1790 SI_QX(SystemLookasideInformation
),
1791 SI_XS(SystemSetTimeSlipEvent
),
1792 SI_XS(SystemCreateSession
),
1793 SI_XS(SystemDeleteSession
),
1794 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */
1795 SI_QX(SystemRangeStartInformation
),
1796 SI_QS(SystemVerifierInformation
),
1797 SI_XS(SystemAddVerifier
),
1798 SI_QX(SystemSessionProcessesInformation
)
1806 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1807 OUT PVOID SystemInformation
,
1809 OUT PULONG UnsafeResultLength
)
1811 KPROCESSOR_MODE PreviousMode
;
1813 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
1817 PreviousMode
= ExGetPreviousMode();
1821 if (PreviousMode
!= KernelMode
)
1823 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1824 ProbeForWrite(SystemInformation
, Length
, 1);
1825 if (UnsafeResultLength
!= NULL
)
1826 ProbeForWriteUlong(UnsafeResultLength
);
1830 * Check the request is valid.
1832 if (SystemInformationClass
>= MaxSystemInfoClass
)
1834 _SEH_YIELD(return STATUS_INVALID_INFO_CLASS
);
1837 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
1840 * Hand the request to a subhandler.
1842 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
1845 if (UnsafeResultLength
!= NULL
)
1847 if (PreviousMode
!= KernelMode
)
1849 *UnsafeResultLength
= ResultLength
;
1853 *UnsafeResultLength
= ResultLength
;
1858 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
1860 FStatus
= _SEH_GetExceptionCode();
1870 NtSetSystemInformation (
1871 IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1872 IN PVOID SystemInformation
,
1873 IN ULONG SystemInformationLength
1879 * If called from user mode, check
1880 * possible unsafe arguments.
1883 if (KernelMode
!= KeGetPreviousMode())
1887 // SystemInformation,
1897 * Check the request is valid.
1899 if ( (SystemInformationClass
>= SystemBasicInformation
)
1900 && (SystemInformationClass
< MaxSystemInfoClass
)
1903 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
1906 * Hand the request to a subhandler.
1908 return CallQS
[SystemInformationClass
].Set (
1910 SystemInformationLength
1914 return (STATUS_INVALID_INFO_CLASS
);
1920 NtFlushInstructionCache (
1921 IN HANDLE ProcessHandle
,
1922 IN PVOID BaseAddress
,
1923 IN ULONG NumberOfBytesToFlush
1928 #if defined(_M_IX86)
1930 #elif defined(_M_PPC)
1931 __asm__
__volatile__("tlbsync");
1932 #elif defined(_M_MIPS)
1933 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1935 #elif defined(_M_ARM)
1936 __asm__
__volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
1937 #elif defined(_M_AMD64)
1938 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1941 #error Unknown architecture
1943 return STATUS_SUCCESS
;
1948 NtGetCurrentProcessorNumber(VOID
)
1950 /* Just return the CPU */
1951 return KeGetCurrentProcessorNumber();