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
;
234 PreviousMode
= ExGetPreviousMode();
236 if (PreviousMode
!= KernelMode
)
240 ProbeForRead(VariableName
,
241 sizeof(UNICODE_STRING
),
244 ProbeForWrite(ValueBuffer
,
248 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
250 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
252 /* Return the exception code */
253 _SEH2_YIELD(return _SEH2_GetExceptionCode());
259 * Copy the name to kernel space if necessary and convert it to ANSI.
261 Status
= ProbeAndCaptureUnicodeString(&WName
,
264 if (NT_SUCCESS(Status
))
267 * according to ntinternals the SeSystemEnvironmentName privilege is required!
269 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
272 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
273 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
274 return STATUS_PRIVILEGE_NOT_HELD
;
278 * convert the value name to ansi
280 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
281 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
283 if (!NT_SUCCESS(Status
)) return Status
;
286 * Create a temporary buffer for the value
288 Value
= ExAllocatePool(NonPagedPool
, ValueBufferLength
);
291 RtlFreeAnsiString(&AName
);
292 return STATUS_INSUFFICIENT_RESOURCES
;
296 * Get the environment variable
298 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
299 (USHORT
)ValueBufferLength
,
303 RtlFreeAnsiString(&AName
);
305 return STATUS_UNSUCCESSFUL
;
309 * Convert the result to UNICODE, protect with SEH in case the value buffer
310 * isn't NULL-terminated!
314 RtlInitAnsiString(&AValue
, Value
);
315 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, TRUE
);
317 _SEH2_EXCEPT(ExSystemExceptionFilter())
319 Status
= _SEH2_GetExceptionCode();
323 if (NT_SUCCESS(Status
))
326 * Copy the result back to the caller.
330 RtlCopyMemory(ValueBuffer
, WValue
.Buffer
, WValue
.Length
);
331 ValueBuffer
[WValue
.Length
/ sizeof(WCHAR
)] = L
'\0';
332 if (ReturnLength
!= NULL
)
334 *ReturnLength
= WValue
.Length
+ sizeof(WCHAR
);
337 Status
= STATUS_SUCCESS
;
339 _SEH2_EXCEPT(ExSystemExceptionFilter())
341 Status
= _SEH2_GetExceptionCode();
347 * Cleanup allocated resources.
349 RtlFreeAnsiString(&AName
);
359 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
360 IN PUNICODE_STRING Value
)
362 UNICODE_STRING CapturedName
, CapturedValue
;
363 ANSI_STRING AName
, AValue
;
364 KPROCESSOR_MODE PreviousMode
;
369 PreviousMode
= ExGetPreviousMode();
372 * Copy the strings to kernel space if necessary
374 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
377 if (NT_SUCCESS(Status
))
379 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
382 if (NT_SUCCESS(Status
))
385 * according to ntinternals the SeSystemEnvironmentName privilege is required!
387 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
391 * convert the strings to ANSI
393 Status
= RtlUnicodeStringToAnsiString(&AName
,
396 if (NT_SUCCESS(Status
))
398 Status
= RtlUnicodeStringToAnsiString(&AValue
,
401 if (NT_SUCCESS(Status
))
403 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
406 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
412 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
413 Status
= STATUS_PRIVILEGE_NOT_HELD
;
416 ReleaseCapturedUnicodeString(&CapturedValue
,
420 ReleaseCapturedUnicodeString(&CapturedName
,
429 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
431 IN ULONG BufferLength
)
434 return STATUS_NOT_IMPLEMENTED
;
439 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
440 IN LPGUID VendorGuid
,
442 IN OUT PULONG ReturnLength
,
443 IN OUT PULONG Attributes
)
446 return STATUS_NOT_IMPLEMENTED
;
451 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
452 IN LPGUID VendorGuid
)
455 return STATUS_NOT_IMPLEMENTED
;
458 /* --- Query/Set System Information --- */
461 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
462 * so the stack is popped only in one place on x86 platform.
464 #define QSI_USE(n) QSI##n
466 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
468 #define SSI_USE(n) SSI##n
470 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
473 /* Class 0 - Basic Information */
474 QSI_DEF(SystemBasicInformation
)
476 PSYSTEM_BASIC_INFORMATION Sbi
477 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
479 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
481 /* Check user buffer's size */
482 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
484 return STATUS_INFO_LENGTH_MISMATCH
;
487 RtlZeroMemory(Sbi
, Size
);
489 Sbi
->TimerResolution
= KeMaximumIncrement
;
490 Sbi
->PageSize
= PAGE_SIZE
;
491 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
492 Sbi
->LowestPhysicalPageNumber
= MmLowestPhysicalPage
;
493 Sbi
->HighestPhysicalPageNumber
= MmHighestPhysicalPage
;
494 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
495 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
496 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
497 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
498 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
500 return STATUS_SUCCESS
;
503 /* Class 1 - Processor Information */
504 QSI_DEF(SystemProcessorInformation
)
506 PSYSTEM_PROCESSOR_INFORMATION Spi
507 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
510 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
512 /* Check user buffer's size */
513 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
515 return STATUS_INFO_LENGTH_MISMATCH
;
517 Prcb
= KeGetCurrentPrcb();
518 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
519 Spi
->ProcessorLevel
= KeProcessorLevel
;
520 Spi
->ProcessorRevision
= KeProcessorRevision
;
522 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
524 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi
->ProcessorArchitecture
,
525 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
527 return STATUS_SUCCESS
;
530 /* Class 2 - Performance Information */
531 QSI_DEF(SystemPerformanceInformation
)
533 ULONG IdleUser
, IdleKernel
;
534 PSYSTEM_PERFORMANCE_INFORMATION Spi
535 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
537 PEPROCESS TheIdleProcess
;
539 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
541 /* Check user buffer's size */
542 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
544 return STATUS_INFO_LENGTH_MISMATCH
;
547 TheIdleProcess
= PsIdleProcess
;
549 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
550 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
551 Spi
->IoReadTransferCount
= IoReadTransferCount
;
552 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
553 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
554 Spi
->IoReadOperationCount
= IoReadOperationCount
;
555 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
556 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
558 Spi
->AvailablePages
= MmAvailablePages
;
560 * Add up all the used "Committed" memory + pagefile.
561 * Not sure this is right. 8^\
563 Spi
->CommittedPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
+
564 MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
+
565 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
566 MiMemoryConsumers
[MC_USER
].PagesUsed
+
569 * Add up the full system total + pagefile.
570 * All this make Taskmgr happy but not sure it is the right numbers.
571 * This too, fixes some of GlobalMemoryStatusEx numbers.
573 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
575 Spi
->PeakCommitment
= 0; /* FIXME */
576 Spi
->PageFaultCount
= 0; /* FIXME */
577 Spi
->CopyOnWriteCount
= 0; /* FIXME */
578 Spi
->TransitionCount
= 0; /* FIXME */
579 Spi
->CacheTransitionCount
= 0; /* FIXME */
580 Spi
->DemandZeroCount
= 0; /* FIXME */
581 Spi
->PageReadCount
= 0; /* FIXME */
582 Spi
->PageReadIoCount
= 0; /* FIXME */
583 Spi
->CacheReadCount
= 0; /* FIXME */
584 Spi
->CacheIoCount
= 0; /* FIXME */
585 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
586 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
587 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
588 Spi
->MappedWriteIoCount
= 0; /* FIXME */
590 Spi
->PagedPoolPages
= MiMemoryConsumers
[MC_PPOOL
].PagesUsed
;
591 Spi
->PagedPoolAllocs
= 0; /* FIXME */
592 Spi
->PagedPoolFrees
= 0; /* FIXME */
593 Spi
->NonPagedPoolPages
= MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
;
594 Spi
->NonPagedPoolAllocs
= 0; /* FIXME */
595 Spi
->NonPagedPoolFrees
= 0; /* FIXME */
597 Spi
->FreeSystemPtes
= 0; /* FIXME */
599 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
601 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
602 Spi
->TotalSystemCodePages
= 0; /* FIXME */
603 Spi
->NonPagedPoolLookasideHits
= 0; /* FIXME */
604 Spi
->PagedPoolLookasideHits
= 0; /* FIXME */
605 Spi
->Spare3Count
= 0; /* FIXME */
607 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
608 Spi
->ResidentPagedPoolPage
= MmPagedPoolSize
; /* FIXME */
610 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
611 Spi
->CcFastReadNoWait
= 0; /* FIXME */
612 Spi
->CcFastReadWait
= 0; /* FIXME */
613 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
614 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
616 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
617 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
618 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
619 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
621 Spi
->CcMapDataNoWait
= 0; /* FIXME */
622 Spi
->CcMapDataWait
= 0; /* FIXME */
623 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
624 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
626 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
627 Spi
->CcPinReadNoWait
= 0; /* FIXME */
628 Spi
->CcPinReadWait
= 0; /* FIXME */
629 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
630 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
631 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
632 Spi
->CcCopyReadWait
= 0; /* FIXME */
633 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
634 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
636 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
637 Spi
->CcMdlReadWait
= 0; /* FIXME */
638 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
639 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
640 Spi
->CcReadAheadIos
= 0; /* FIXME */
641 Spi
->CcLazyWriteIos
= 0; /* FIXME */
642 Spi
->CcLazyWritePages
= 0; /* FIXME */
643 Spi
->CcDataFlushes
= 0; /* FIXME */
644 Spi
->CcDataPages
= 0; /* FIXME */
645 Spi
->ContextSwitches
= 0; /* FIXME */
646 Spi
->FirstLevelTbFills
= 0; /* FIXME */
647 Spi
->SecondLevelTbFills
= 0; /* FIXME */
648 Spi
->SystemCalls
= 0; /* FIXME */
650 return STATUS_SUCCESS
;
653 /* Class 3 - Time Of Day Information */
654 QSI_DEF(SystemTimeOfDayInformation
)
656 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
657 LARGE_INTEGER CurrentTime
;
659 /* Set amount of written information to 0 */
662 /* Check user buffer's size */
663 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
665 return STATUS_INFO_LENGTH_MISMATCH
;
668 /* Get current time */
669 KeQuerySystemTime(&CurrentTime
);
671 /* Zero local buffer */
672 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
674 /* Fill local time structure */
675 Sti
.BootTime
= KeBootTime
;
676 Sti
.CurrentTime
= CurrentTime
;
677 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
678 Sti
.TimeZoneId
= ExpTimeZoneId
;
681 /* Copy as much as requested by caller */
682 RtlCopyMemory(Buffer
, &Sti
, Size
);
684 /* Set amount of information we copied */
687 return STATUS_SUCCESS
;
690 /* Class 4 - Path Information */
691 QSI_DEF(SystemPathInformation
)
693 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
694 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
696 return STATUS_BREAKPOINT
;
699 /* Class 5 - Process Information */
700 QSI_DEF(SystemProcessInformation
)
702 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
703 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
704 PEPROCESS Process
= NULL
, SystemProcess
;
705 PETHREAD CurrentThread
;
706 ANSI_STRING ImageName
;
708 USHORT ImageNameMaximumLength
; // image name len in bytes
709 USHORT ImageNameLength
;
710 PLIST_ENTRY CurrentEntry
;
711 ULONG TotalSize
= 0, ThreadsCount
;
712 ULONG TotalUser
, TotalKernel
;
714 NTSTATUS Status
= STATUS_SUCCESS
;
715 PUNICODE_STRING ProcessImageName
;
717 BOOLEAN Overflow
= FALSE
;
721 /* scan the process list */
723 PSYSTEM_PROCESS_INFORMATION Spi
724 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
726 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
728 /* Check for overflow */
729 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
732 /* Zero user's buffer */
733 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
735 SystemProcess
= PsIdleProcess
;
736 Process
= SystemProcess
;
737 Current
= (PUCHAR
) Spi
;
741 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
744 CurrentEntry
= Process
->ThreadListHead
.Flink
;
745 while (CurrentEntry
!= &Process
->ThreadListHead
)
748 CurrentEntry
= CurrentEntry
->Flink
;
751 // size of the structure for every process
752 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
754 Status
= SeLocateProcessImageName(Process
, &ProcessImageName
);
756 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
758 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
759 /* Loop the file name*/
760 while (szSrc
> ProcessImageName
->Buffer
)
762 /* Make sure this isn't a backslash */
763 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
770 ImageNameLength
+= sizeof(WCHAR
);
774 if (!ImageNameLength
&& Process
!= PsIdleProcess
&& Process
->ImageFileName
)
776 ImageNameLength
= strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
779 /* Round up the image name length as NT does */
780 if (ImageNameLength
> 0)
781 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
783 ImageNameMaximumLength
= 0;
785 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
787 /* Check for overflow */
788 if (TotalSize
> Size
)
791 /* Fill system information */
794 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginnnig of the next structure
795 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
796 SpiCurrent
->CreateTime
= Process
->CreateTime
;
797 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
798 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
799 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
801 /* Copy name to the end of the struct */
802 if(Process
!= PsIdleProcess
)
806 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
808 /* Release the memory allocated by SeLocateProcessImageName */
809 ExFreePool(ProcessImageName
);
811 else if (Process
->ImageFileName
)
813 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
814 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
819 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
822 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
823 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
824 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
825 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
826 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
827 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
828 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
829 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
830 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
831 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
832 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
833 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
834 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
835 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
836 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
837 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
838 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
840 CurrentEntry
= Process
->ThreadListHead
.Flink
;
841 while (CurrentEntry
!= &Process
->ThreadListHead
)
843 CurrentThread
= CONTAINING_RECORD(CurrentEntry
, ETHREAD
,
846 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
847 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
848 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
849 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
850 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
851 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
852 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
853 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
854 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
855 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
856 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
859 CurrentEntry
= CurrentEntry
->Flink
;
862 /* Query total user/kernel times of a process */
863 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
864 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
865 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
868 /* Handle idle process entry */
869 if (Process
== PsIdleProcess
) Process
= NULL
;
871 Process
= PsGetNextProcess(Process
);
873 if ((Process
== SystemProcess
) || (Process
== NULL
))
876 SpiCurrent
->NextEntryOffset
= 0;
880 Current
+= CurrentSize
+ ImageNameMaximumLength
;
881 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
884 ObDereferenceObject(Process
);
885 Status
= STATUS_SUCCESS
;
887 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
890 ObDereferenceObject(Process
);
891 Status
= _SEH2_GetExceptionCode();
896 Status
= STATUS_INFO_LENGTH_MISMATCH
;
898 *ReqSize
= TotalSize
;
902 /* Class 6 - Call Count Information */
903 QSI_DEF(SystemCallCountInformation
)
906 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
907 return STATUS_NOT_IMPLEMENTED
;
910 /* Class 7 - Device Information */
911 QSI_DEF(SystemDeviceInformation
)
913 PSYSTEM_DEVICE_INFORMATION Sdi
914 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
915 PCONFIGURATION_INFORMATION ConfigInfo
;
917 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
919 /* Check user buffer's size */
920 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
922 return STATUS_INFO_LENGTH_MISMATCH
;
925 ConfigInfo
= IoGetConfigurationInformation();
927 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
928 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
929 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
930 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
931 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
932 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
934 return STATUS_SUCCESS
;
937 /* Class 8 - Processor Performance Information */
938 QSI_DEF(SystemProcessorPerformanceInformation
)
940 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
941 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
945 LARGE_INTEGER CurrentTime
;
948 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
950 /* Check user buffer's size */
953 return STATUS_INFO_LENGTH_MISMATCH
;
956 CurrentTime
.QuadPart
= KeQueryInterruptTime();
957 for (i
= 0; i
< KeNumberProcessors
; i
++)
959 /* Get the PRCB on this processor */
960 Prcb
= KiProcessorBlock
[i
];
962 /* Calculate total user and kernel times */
963 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
964 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
965 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
966 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
967 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
968 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
969 Spi
->InterruptCount
= Prcb
->InterruptCount
;
973 return STATUS_SUCCESS
;
976 /* Class 9 - Flags Information */
977 QSI_DEF(SystemFlagsInformation
)
979 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
981 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
982 return (STATUS_INFO_LENGTH_MISMATCH
);
984 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
985 return STATUS_SUCCESS
;
988 SSI_DEF(SystemFlagsInformation
)
990 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
992 return STATUS_INFO_LENGTH_MISMATCH
;
994 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
995 return STATUS_SUCCESS
;
998 /* Class 10 - Call Time Information */
999 QSI_DEF(SystemCallTimeInformation
)
1002 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
1003 return STATUS_NOT_IMPLEMENTED
;
1006 /* Class 11 - Module Information */
1007 QSI_DEF(SystemModuleInformation
)
1009 extern LIST_ENTRY PsLoadedModuleList
;
1010 return ExpQueryModuleInformation(&PsLoadedModuleList
,
1012 (PRTL_PROCESS_MODULES
)Buffer
,
1017 /* Class 12 - Locks Information */
1018 QSI_DEF(SystemLocksInformation
)
1021 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1022 return STATUS_NOT_IMPLEMENTED
;
1025 /* Class 13 - Stack Trace Information */
1026 QSI_DEF(SystemStackTraceInformation
)
1029 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1030 return STATUS_NOT_IMPLEMENTED
;
1033 /* Class 14 - Paged Pool Information */
1034 QSI_DEF(SystemPagedPoolInformation
)
1037 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1038 return STATUS_NOT_IMPLEMENTED
;
1041 /* Class 15 - Non Paged Pool Information */
1042 QSI_DEF(SystemNonPagedPoolInformation
)
1045 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1046 return STATUS_NOT_IMPLEMENTED
;
1050 /* Class 16 - Handle Information */
1051 QSI_DEF(SystemHandleInformation
)
1053 PEPROCESS pr
, syspr
;
1054 ULONG curSize
, i
= 0;
1057 PSYSTEM_HANDLE_INFORMATION Shi
=
1058 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1060 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1062 if (Size
< sizeof(SYSTEM_HANDLE_INFORMATION
))
1064 *ReqSize
= sizeof(SYSTEM_HANDLE_INFORMATION
);
1065 return STATUS_INFO_LENGTH_MISMATCH
;
1068 DPRINT("SystemHandleInformation 1\n");
1070 /* First Calc Size from Count. */
1071 syspr
= PsGetNextProcess(NULL
);
1076 hCount
= hCount
+ ObGetProcessHandleCount(pr
);
1077 pr
= PsGetNextProcess(pr
);
1079 if ((pr
== syspr
) || (pr
== NULL
)) break;
1081 while ((pr
!= syspr
) && (pr
!= NULL
));
1085 ObDereferenceObject(pr
);
1088 DPRINT("SystemHandleInformation 2\n");
1090 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
) +
1091 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1092 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
)));
1094 Shi
->NumberOfHandles
= hCount
;
1099 return (STATUS_INFO_LENGTH_MISMATCH
);
1102 DPRINT("SystemHandleInformation 3\n");
1104 /* Now get Handles from all processs. */
1105 syspr
= PsGetNextProcess(NULL
);
1110 int Count
= 0, HandleCount
;
1112 HandleCount
= ObGetProcessHandleCount(pr
);
1114 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1116 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG_PTR
)pr
->UniqueProcessId
;
1121 pr
= PsGetNextProcess(pr
);
1123 if ((pr
== syspr
) || (pr
== NULL
)) break;
1125 while ((pr
!= syspr
) && (pr
!= NULL
));
1127 if(pr
!= NULL
) ObDereferenceObject(pr
);
1129 DPRINT("SystemHandleInformation 4\n");
1130 return STATUS_SUCCESS
;
1134 SSI_DEF(SystemHandleInformation)
1137 return STATUS_SUCCESS;
1141 /* Class 17 - Information */
1142 QSI_DEF(SystemObjectInformation
)
1145 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1146 return STATUS_NOT_IMPLEMENTED
;
1149 /* Class 18 - Information */
1150 QSI_DEF(SystemPageFileInformation
)
1152 UNICODE_STRING FileName
; /* FIXME */
1153 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1155 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1157 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1158 return STATUS_INFO_LENGTH_MISMATCH
;
1161 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1164 Spfi
->NextEntryOffset
= 0;
1166 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1167 Spfi
->TotalInUse
= MiUsedSwapPages
;
1168 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1169 Spfi
->PageFileName
= FileName
;
1170 return STATUS_SUCCESS
;
1173 /* Class 19 - Vdm Instemul Information */
1174 QSI_DEF(SystemVdmInstemulInformation
)
1177 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1178 return STATUS_NOT_IMPLEMENTED
;
1181 /* Class 20 - Vdm Bop Information */
1182 QSI_DEF(SystemVdmBopInformation
)
1185 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1186 return STATUS_NOT_IMPLEMENTED
;
1189 /* Class 21 - File Cache Information */
1190 QSI_DEF(SystemFileCacheInformation
)
1192 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1194 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1196 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1197 return STATUS_INFO_LENGTH_MISMATCH
;
1200 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1202 /* Return the Byte size not the page size. */
1204 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1206 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1207 /* Taskmgr multiplies this one by page size right away */
1208 Sci
->CurrentSizeIncludingTransitionInPages
=
1209 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1210 /* system working set and standby pages. */
1211 Sci
->PageFaultCount
= 0; /* FIXME */
1212 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1213 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1215 return STATUS_SUCCESS
;
1218 SSI_DEF(SystemFileCacheInformation
)
1220 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1222 return STATUS_INFO_LENGTH_MISMATCH
;
1225 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1226 return STATUS_NOT_IMPLEMENTED
;
1229 /* Class 22 - Pool Tag Information */
1230 QSI_DEF(SystemPoolTagInformation
)
1233 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1234 return STATUS_NOT_IMPLEMENTED
;
1237 /* Class 23 - Interrupt Information for all processors */
1238 QSI_DEF(SystemInterruptInformation
)
1244 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1246 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1248 return STATUS_INFO_LENGTH_MISMATCH
;
1251 ti
= KeQueryTimeIncrement();
1253 for (i
= 0; i
< KeNumberProcessors
; i
++)
1255 Prcb
= KiProcessorBlock
[i
];
1257 Pcr
= CONTAINING_RECORD(Prcb
, KPCR
, CurrentPrcb
);
1259 Pcr
= CONTAINING_RECORD(Prcb
, KPCR
, Prcb
);
1261 #ifdef _M_ARM // This code should probably be done differently
1262 sii
->ContextSwitches
= Pcr
->ContextSwitches
;
1264 sii
->ContextSwitches
= ((PKIPCR
)Pcr
)->ContextSwitches
;
1266 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1267 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1268 sii
->TimeIncrement
= ti
;
1269 sii
->DpcBypassCount
= 0;
1270 sii
->ApcBypassCount
= 0;
1274 return STATUS_SUCCESS
;
1277 /* Class 24 - DPC Behaviour Information */
1278 QSI_DEF(SystemDpcBehaviourInformation
)
1281 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1282 return STATUS_NOT_IMPLEMENTED
;
1285 SSI_DEF(SystemDpcBehaviourInformation
)
1288 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1289 return STATUS_NOT_IMPLEMENTED
;
1292 /* Class 25 - Full Memory Information */
1293 QSI_DEF(SystemFullMemoryInformation
)
1295 PULONG Spi
= (PULONG
) Buffer
;
1297 PEPROCESS TheIdleProcess
;
1299 *ReqSize
= sizeof(ULONG
);
1301 if (sizeof(ULONG
) != Size
)
1303 return STATUS_INFO_LENGTH_MISMATCH
;
1306 DPRINT("SystemFullMemoryInformation\n");
1308 TheIdleProcess
= PsIdleProcess
;
1310 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1311 TheIdleProcess
->UniqueProcessId
,
1312 TheIdleProcess
->Pcb
.KernelTime
,
1317 MmPrintMemoryStatistic();
1320 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1322 return STATUS_SUCCESS
;
1325 /* Class 26 - Load Image */
1326 SSI_DEF(SystemLoadGdiDriverInformation
)
1328 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1329 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1330 UNICODE_STRING ImageName
;
1332 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1333 ULONG_PTR EntryPoint
;
1336 PIMAGE_NT_HEADERS NtHeader
;
1339 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1341 /* Incorrect buffer length, fail */
1342 return STATUS_INFO_LENGTH_MISMATCH
;
1345 /* Only kernel-mode can call this function */
1346 if (PreviousMode
!= KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1348 /* Load the driver */
1349 ImageName
= DriverInfo
->DriverName
;
1350 Status
= MmLoadSystemImage(&ImageName
,
1354 (PVOID
)&ModuleObject
,
1356 if (!NT_SUCCESS(Status
)) return Status
;
1358 /* Return the export pointer */
1359 DriverInfo
->ExportSectionPointer
=
1360 RtlImageDirectoryEntryToData(ImageBase
,
1362 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1365 /* Get the entrypoint */
1366 NtHeader
= RtlImageNtHeader(ImageBase
);
1367 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1368 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1370 /* Save other data */
1371 DriverInfo
->ImageAddress
= ImageBase
;
1372 DriverInfo
->SectionPointer
= NULL
;
1373 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1374 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1377 return STATUS_SUCCESS
;
1380 /* Class 27 - Unload Image */
1381 SSI_DEF(SystemUnloadGdiDriverInformation
)
1383 PLDR_DATA_TABLE_ENTRY LdrEntry
;
1384 PLIST_ENTRY NextEntry
;
1385 PVOID BaseAddr
= *((PVOID
*)Buffer
);
1387 if(Size
!= sizeof(PVOID
))
1388 return STATUS_INFO_LENGTH_MISMATCH
;
1390 if(KeGetPreviousMode() != KernelMode
)
1391 return STATUS_PRIVILEGE_NOT_HELD
;
1393 // Scan the module list
1394 NextEntry
= PsLoadedModuleList
.Flink
;
1395 while(NextEntry
!= &PsLoadedModuleList
)
1397 LdrEntry
= CONTAINING_RECORD(NextEntry
,
1398 LDR_DATA_TABLE_ENTRY
,
1401 if (LdrEntry
->DllBase
== BaseAddr
)
1407 NextEntry
= NextEntry
->Flink
;
1410 // Check if we found the image
1411 if(NextEntry
!= &PsLoadedModuleList
)
1413 return MmUnloadSystemImage(LdrEntry
);
1417 DPRINT1("Image 0x%x not found.\n", BaseAddr
);
1418 return STATUS_DLL_NOT_FOUND
;
1423 /* Class 28 - Time Adjustment Information */
1424 QSI_DEF(SystemTimeAdjustmentInformation
)
1426 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1427 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1429 /* Check if enough storage was provided */
1430 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1432 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1433 return STATUS_INFO_LENGTH_MISMATCH
;
1436 /* Give time values to our caller */
1437 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1438 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1439 TimeInfo
->Enable
= TRUE
;
1441 return STATUS_SUCCESS
;
1444 SSI_DEF(SystemTimeAdjustmentInformation
)
1446 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1447 /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1448 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
1450 /* Check size of a buffer, it must match our expectations */
1451 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1452 return STATUS_INFO_LENGTH_MISMATCH
;
1454 /* Check who is calling */
1455 if (PreviousMode
!= KernelMode
)
1457 /* Check access rights */
1458 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1460 return STATUS_PRIVILEGE_NOT_HELD
;
1464 /* TODO: Set time adjustment information */
1465 DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
1466 return STATUS_NOT_IMPLEMENTED
;
1469 /* Class 29 - Summary Memory Information */
1470 QSI_DEF(SystemSummaryMemoryInformation
)
1473 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1474 return STATUS_NOT_IMPLEMENTED
;
1477 /* Class 30 - Next Event Id Information */
1478 QSI_DEF(SystemNextEventIdInformation
)
1481 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1482 return STATUS_NOT_IMPLEMENTED
;
1485 /* Class 31 - Event Ids Information */
1486 QSI_DEF(SystemEventIdsInformation
)
1489 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1490 return STATUS_NOT_IMPLEMENTED
;
1493 /* Class 32 - Crash Dump Information */
1494 QSI_DEF(SystemCrashDumpInformation
)
1497 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1498 return STATUS_NOT_IMPLEMENTED
;
1501 /* Class 33 - Exception Information */
1502 QSI_DEF(SystemExceptionInformation
)
1505 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1506 return STATUS_NOT_IMPLEMENTED
;
1509 /* Class 34 - Crash Dump State Information */
1510 QSI_DEF(SystemCrashDumpStateInformation
)
1513 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1514 return STATUS_NOT_IMPLEMENTED
;
1517 /* Class 35 - Kernel Debugger Information */
1518 QSI_DEF(SystemKernelDebuggerInformation
)
1520 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1522 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1523 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1525 return STATUS_INFO_LENGTH_MISMATCH
;
1528 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1529 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1531 return STATUS_SUCCESS
;
1534 /* Class 36 - Context Switch Information */
1535 QSI_DEF(SystemContextSwitchInformation
)
1538 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1539 return STATUS_NOT_IMPLEMENTED
;
1542 /* Class 37 - Registry Quota Information */
1543 QSI_DEF(SystemRegistryQuotaInformation
)
1545 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1547 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1548 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1550 return STATUS_INFO_LENGTH_MISMATCH
;
1553 DPRINT1("Faking max registry size of 32 MB\n");
1554 srqi
->RegistryQuotaAllowed
= 0x2000000;
1555 srqi
->RegistryQuotaUsed
= 0x200000;
1556 srqi
->PagedPoolSize
= 0x200000;
1558 return STATUS_SUCCESS
;
1561 SSI_DEF(SystemRegistryQuotaInformation
)
1564 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1565 return STATUS_NOT_IMPLEMENTED
;
1568 /* Class 38 - Load And Call Image */
1569 SSI_DEF(SystemExtendServiceTableInformation
)
1571 UNICODE_STRING ImageName
;
1572 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1573 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1575 PIMAGE_NT_HEADERS NtHeader
;
1576 DRIVER_OBJECT Win32k
;
1577 PDRIVER_INITIALIZE DriverInit
;
1579 ULONG_PTR EntryPoint
;
1581 /* Validate the size */
1582 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1584 /* Check who is calling */
1585 if (PreviousMode
!= KernelMode
)
1587 /* Make sure we can load drivers */
1588 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1590 /* FIXME: We can't, fail */
1591 //return STATUS_PRIVILEGE_NOT_HELD;
1595 /* Probe and capture the driver name */
1596 ProbeAndCaptureUnicodeString(&ImageName
, PreviousMode
, Buffer
);
1598 /* Load the image */
1599 Status
= MmLoadSystemImage(&ImageName
,
1603 (PVOID
)&ModuleObject
,
1606 /* Release String */
1607 ReleaseCapturedUnicodeString(&ImageName
, PreviousMode
);
1609 if (!NT_SUCCESS(Status
)) return Status
;
1611 /* Get the headers */
1612 NtHeader
= RtlImageNtHeader(ImageBase
);
1616 MmUnloadSystemImage(ModuleObject
);
1617 return STATUS_INVALID_IMAGE_FORMAT
;
1620 /* Get the entrypoint */
1621 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1622 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1623 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1625 /* Create a dummy device */
1626 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1627 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1628 Win32k
.DriverStart
= ImageBase
;
1631 Status
= (DriverInit
)(&Win32k
, NULL
);
1632 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1634 /* Unload if we failed */
1635 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1639 /* Class 39 - Priority Separation */
1640 SSI_DEF(SystemPrioritySeperation
)
1643 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1644 return STATUS_NOT_IMPLEMENTED
;
1647 /* Class 40 - Plug Play Bus Information */
1648 QSI_DEF(SystemPlugPlayBusInformation
)
1651 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1652 return STATUS_NOT_IMPLEMENTED
;
1655 /* Class 41 - Dock Information */
1656 QSI_DEF(SystemDockInformation
)
1659 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1660 return STATUS_NOT_IMPLEMENTED
;
1663 /* Class 42 - Power Information */
1664 QSI_DEF(SystemPowerInformation
)
1667 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1668 return STATUS_NOT_IMPLEMENTED
;
1671 /* Class 43 - Processor Speed Information */
1672 QSI_DEF(SystemProcessorSpeedInformation
)
1675 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1676 return STATUS_NOT_IMPLEMENTED
;
1679 /* Class 44 - Current Time Zone Information */
1680 QSI_DEF(SystemCurrentTimeZoneInformation
)
1682 *ReqSize
= sizeof(TIME_ZONE_INFORMATION
);
1684 if (sizeof(TIME_ZONE_INFORMATION
) != Size
)
1686 return STATUS_INFO_LENGTH_MISMATCH
;
1689 /* Copy the time zone information struct */
1692 sizeof(TIME_ZONE_INFORMATION
));
1694 return STATUS_SUCCESS
;
1698 SSI_DEF(SystemCurrentTimeZoneInformation
)
1700 /* Check user buffer's size */
1701 if (Size
< sizeof(TIME_ZONE_INFORMATION
))
1703 return STATUS_INFO_LENGTH_MISMATCH
;
1706 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1710 /* Class 45 - Lookaside Information */
1711 QSI_DEF(SystemLookasideInformation
)
1714 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1715 return STATUS_NOT_IMPLEMENTED
;
1719 /* Class 46 - Set time slip event */
1720 SSI_DEF(SystemSetTimeSlipEvent
)
1723 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1724 return STATUS_NOT_IMPLEMENTED
;
1728 /* Class 47 - Create a new session (TSE) */
1729 SSI_DEF(SystemCreateSession
)
1732 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1733 return STATUS_NOT_IMPLEMENTED
;
1737 /* Class 48 - Delete an existing session (TSE) */
1738 SSI_DEF(SystemDeleteSession
)
1741 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1742 return STATUS_NOT_IMPLEMENTED
;
1746 /* Class 49 - UNKNOWN */
1747 QSI_DEF(SystemInvalidInfoClass4
)
1750 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1751 return STATUS_NOT_IMPLEMENTED
;
1755 /* Class 50 - System range start address */
1756 QSI_DEF(SystemRangeStartInformation
)
1759 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1760 return STATUS_NOT_IMPLEMENTED
;
1764 /* Class 51 - Driver verifier information */
1765 QSI_DEF(SystemVerifierInformation
)
1768 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1769 return STATUS_NOT_IMPLEMENTED
;
1773 SSI_DEF(SystemVerifierInformation
)
1776 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1777 return STATUS_NOT_IMPLEMENTED
;
1781 /* Class 52 - Add a driver verifier */
1782 SSI_DEF(SystemAddVerifier
)
1785 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1786 return STATUS_NOT_IMPLEMENTED
;
1790 /* Class 53 - A session's processes */
1791 QSI_DEF(SystemSessionProcessesInformation
)
1794 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1795 return STATUS_NOT_IMPLEMENTED
;
1799 /* Query/Set Calls Table */
1803 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1804 NTSTATUS (* Set
) (PVOID
,ULONG
);
1811 // XX unknown behaviour
1813 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1814 #define SI_QX(n) {QSI_USE(n),NULL}
1815 #define SI_XS(n) {NULL,SSI_USE(n)}
1816 #define SI_XX(n) {NULL,NULL}
1822 SI_QX(SystemBasicInformation
),
1823 SI_QX(SystemProcessorInformation
),
1824 SI_QX(SystemPerformanceInformation
),
1825 SI_QX(SystemTimeOfDayInformation
),
1826 SI_QX(SystemPathInformation
), /* should be SI_XX */
1827 SI_QX(SystemProcessInformation
),
1828 SI_QX(SystemCallCountInformation
),
1829 SI_QX(SystemDeviceInformation
),
1830 SI_QX(SystemProcessorPerformanceInformation
),
1831 SI_QS(SystemFlagsInformation
),
1832 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1833 SI_QX(SystemModuleInformation
),
1834 SI_QX(SystemLocksInformation
),
1835 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1836 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1837 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1838 SI_QX(SystemHandleInformation
),
1839 SI_QX(SystemObjectInformation
),
1840 SI_QX(SystemPageFileInformation
),
1841 SI_QX(SystemVdmInstemulInformation
),
1842 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1843 SI_QS(SystemFileCacheInformation
),
1844 SI_QX(SystemPoolTagInformation
),
1845 SI_QX(SystemInterruptInformation
),
1846 SI_QS(SystemDpcBehaviourInformation
),
1847 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1848 SI_XS(SystemLoadGdiDriverInformation
),
1849 SI_XS(SystemUnloadGdiDriverInformation
),
1850 SI_QS(SystemTimeAdjustmentInformation
),
1851 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1852 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1853 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */
1854 SI_QX(SystemCrashDumpInformation
),
1855 SI_QX(SystemExceptionInformation
),
1856 SI_QX(SystemCrashDumpStateInformation
),
1857 SI_QX(SystemKernelDebuggerInformation
),
1858 SI_QX(SystemContextSwitchInformation
),
1859 SI_QS(SystemRegistryQuotaInformation
),
1860 SI_XS(SystemExtendServiceTableInformation
),
1861 SI_XS(SystemPrioritySeperation
),
1862 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1863 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1864 SI_QX(SystemPowerInformation
), /* it should be SI_XX */
1865 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1866 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
1867 SI_QX(SystemLookasideInformation
),
1868 SI_XS(SystemSetTimeSlipEvent
),
1869 SI_XS(SystemCreateSession
),
1870 SI_XS(SystemDeleteSession
),
1871 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */
1872 SI_QX(SystemRangeStartInformation
),
1873 SI_QS(SystemVerifierInformation
),
1874 SI_XS(SystemAddVerifier
),
1875 SI_QX(SystemSessionProcessesInformation
)
1878 C_ASSERT(SystemBasicInformation
== 0);
1879 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1880 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1886 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1887 OUT PVOID SystemInformation
,
1889 OUT PULONG UnsafeResultLength
)
1891 KPROCESSOR_MODE PreviousMode
;
1893 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
1897 PreviousMode
= ExGetPreviousMode();
1901 if (PreviousMode
!= KernelMode
)
1903 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1904 ProbeForWrite(SystemInformation
, Length
, 1);
1905 if (UnsafeResultLength
!= NULL
)
1906 ProbeForWriteUlong(UnsafeResultLength
);
1910 * Check the request is valid.
1912 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
1914 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
1917 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
1920 * Hand the request to a subhandler.
1922 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
1925 if (UnsafeResultLength
!= NULL
)
1927 if (PreviousMode
!= KernelMode
)
1929 *UnsafeResultLength
= ResultLength
;
1933 *UnsafeResultLength
= ResultLength
;
1938 _SEH2_EXCEPT(ExSystemExceptionFilter())
1940 FStatus
= _SEH2_GetExceptionCode();
1950 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1951 IN PVOID SystemInformation
,
1952 IN ULONG SystemInformationLength
)
1957 * If called from user mode, check
1958 * possible unsafe arguments.
1961 if (KernelMode
!= KeGetPreviousMode())
1965 // SystemInformation,
1975 * Check the request is valid.
1977 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
1978 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
1980 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
1983 * Hand the request to a subhandler.
1985 return CallQS
[SystemInformationClass
].Set(SystemInformation
,
1986 SystemInformationLength
);
1990 return STATUS_INVALID_INFO_CLASS
;
1996 NtFlushInstructionCache(IN HANDLE ProcessHandle
,
1997 IN PVOID BaseAddress
,
1998 IN ULONG NumberOfBytesToFlush
)
2002 #if defined(_M_IX86) || defined(_M_AMD64)
2004 #elif defined(_M_PPC)
2005 __asm__
__volatile__("tlbsync");
2006 #elif defined(_M_MIPS)
2007 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2009 #elif defined(_M_ARM)
2010 __asm__
__volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
2012 #error Unknown architecture
2014 return STATUS_SUCCESS
;
2019 NtGetCurrentProcessorNumber(VOID
)
2021 /* Just return the CPU */
2022 return KeGetCurrentProcessorNumber();