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 FAST_MUTEX ExpEnvironmentLock
;
18 ERESOURCE ExpFirmwareTableResource
;
19 LIST_ENTRY ExpFirmwareTableProviderListHead
;
23 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList
,
24 IN PLIST_ENTRY UserModeList
,
25 OUT PRTL_PROCESS_MODULES Modules
,
27 OUT PULONG ReturnLength
)
29 NTSTATUS Status
= STATUS_SUCCESS
;
31 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo
;
32 PLDR_DATA_TABLE_ENTRY LdrEntry
;
33 ANSI_STRING ModuleName
;
34 ULONG ModuleCount
= 0;
35 PLIST_ENTRY NextEntry
;
39 RequiredLength
= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
);
40 ModuleInfo
= &Modules
->Modules
[0];
42 /* Loop the kernel list */
43 NextEntry
= KernelModeList
->Flink
;
44 while (NextEntry
!= KernelModeList
)
47 LdrEntry
= CONTAINING_RECORD(NextEntry
,
51 /* Update size and check if we can manage one more entry */
52 RequiredLength
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
53 if (Length
>= RequiredLength
)
56 ModuleInfo
->MappedBase
= NULL
;
57 ModuleInfo
->ImageBase
= LdrEntry
->DllBase
;
58 ModuleInfo
->ImageSize
= LdrEntry
->SizeOfImage
;
59 ModuleInfo
->Flags
= LdrEntry
->Flags
;
60 ModuleInfo
->LoadCount
= LdrEntry
->LoadCount
;
61 ModuleInfo
->LoadOrderIndex
= (USHORT
)ModuleCount
;
62 ModuleInfo
->InitOrderIndex
= 0;
65 RtlInitEmptyAnsiString(&ModuleName
,
66 ModuleInfo
->FullPathName
,
67 sizeof(ModuleInfo
->FullPathName
));
70 Status
= RtlUnicodeStringToAnsiString(&ModuleName
,
71 &LdrEntry
->FullDllName
,
73 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
75 /* Calculate offset to name */
76 p
= ModuleName
.Buffer
+ ModuleName
.Length
;
77 while ((p
> ModuleName
.Buffer
) && (*--p
))
79 /* Check if we found the separator */
80 if (*p
== OBJ_NAME_PATH_SEPARATOR
)
82 /* We did, break out */
89 ModuleInfo
->OffsetToFileName
= (USHORT
)(p
- ModuleName
.Buffer
);
93 /* Return empty name */
94 ModuleInfo
->FullPathName
[0] = ANSI_NULL
;
95 ModuleInfo
->OffsetToFileName
= 0;
98 /* Go to the next module */
104 Status
= STATUS_INFO_LENGTH_MISMATCH
;
107 /* Update count and move to next entry */
109 NextEntry
= NextEntry
->Flink
;
112 /* Check if caller also wanted user modules */
116 DPRINT1("User-mode list not yet supported in ReactOS!\n");
119 /* Update return length */
120 if (ReturnLength
) *ReturnLength
= RequiredLength
;
122 /* Validate the length again */
123 if (Length
>= FIELD_OFFSET(RTL_PROCESS_MODULES
, Modules
))
125 /* Set the final count */
126 Modules
->NumberOfModules
= ModuleCount
;
130 /* Otherwise, we failed */
131 Status
= STATUS_INFO_LENGTH_MISMATCH
;
138 /* FUNCTIONS *****************************************************************/
145 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage
)
149 ULONGLONG ScaledIdle
;
151 Prcb
= KeGetCurrentPrcb();
153 ScaledIdle
= (ULONGLONG
)Prcb
->IdleThread
->KernelTime
* 100;
154 TotalTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
156 *CpuUsage
= (ULONG
)(100 - (ScaledIdle
/ TotalTime
));
166 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime
,
168 PULONG ProcessorNumber
)
172 Prcb
= KeGetCurrentPrcb();
174 *ThreadKernelTime
= Prcb
->KernelTime
+ Prcb
->UserTime
;
175 *TotalCpuTime
= Prcb
->CurrentThread
->KernelTime
;
176 *ProcessorNumber
= KeGetCurrentProcessorNumber();
184 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature
)
186 /* Quick check to see if it exists at all */
187 if (ProcessorFeature
>= PROCESSOR_FEATURE_MAX
) return(FALSE
);
189 /* Return our support for it */
190 return(SharedUserData
->ProcessorFeatures
[ProcessorFeature
]);
198 ExVerifySuite(SUITE_TYPE SuiteType
)
200 if (SuiteType
== Personal
) return TRUE
;
206 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
207 OUT PWSTR ValueBuffer
,
208 IN ULONG ValueBufferLength
,
209 IN OUT PULONG ReturnLength OPTIONAL
)
212 UNICODE_STRING WName
;
216 UNICODE_STRING WValue
;
217 KPROCESSOR_MODE PreviousMode
;
221 /* Check if the call came from user mode */
222 PreviousMode
= ExGetPreviousMode();
223 if (PreviousMode
!= KernelMode
)
227 /* Probe the input and output buffers */
228 ProbeForRead(VariableName
, sizeof(UNICODE_STRING
), sizeof(ULONG
));
229 ProbeForWrite(ValueBuffer
, ValueBufferLength
, sizeof(WCHAR
));
230 if (ReturnLength
!= NULL
) ProbeForWriteUlong(ReturnLength
);
232 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
234 /* Return the exception code */
235 _SEH2_YIELD(return _SEH2_GetExceptionCode());
240 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
241 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
, PreviousMode
))
243 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
244 return STATUS_PRIVILEGE_NOT_HELD
;
247 /* Copy the name to kernel space if necessary */
248 Status
= ProbeAndCaptureUnicodeString(&WName
, PreviousMode
, VariableName
);
249 if (!NT_SUCCESS(Status
))
254 /* Convert the name to ANSI and release the captured UNICODE string */
255 Status
= RtlUnicodeStringToAnsiString(&AName
, &WName
, TRUE
);
256 ReleaseCapturedUnicodeString(&WName
, PreviousMode
);
257 if (!NT_SUCCESS(Status
)) return Status
;
259 /* Allocate a buffer for the ANSI environment variable */
260 AnsiValueBuffer
= ExAllocatePoolWithTag(NonPagedPool
, ValueBufferLength
, 'pmeT');
261 if (AnsiValueBuffer
== NULL
)
263 RtlFreeAnsiString(&AName
);
264 return STATUS_INSUFFICIENT_RESOURCES
;
267 /* Get the environment variable and free the ANSI name */
268 Result
= HalGetEnvironmentVariable(AName
.Buffer
,
269 (USHORT
)ValueBufferLength
,
271 RtlFreeAnsiString(&AName
);
273 /* Check if we had success */
274 if (Result
== ESUCCESS
)
276 /* Copy the result back to the caller. */
279 /* Initialize ANSI string from the result */
280 RtlInitAnsiString(&AValue
, AnsiValueBuffer
);
282 /* Initialize a UNICODE string from the callers buffer */
283 RtlInitEmptyUnicodeString(&WValue
, ValueBuffer
, ValueBufferLength
);
285 /* Convert the result to UNICODE */
286 Status
= RtlAnsiStringToUnicodeString(&WValue
, &AValue
, FALSE
);
288 if (ReturnLength
!= NULL
)
290 *ReturnLength
= WValue
.Length
;
293 _SEH2_EXCEPT(ExSystemExceptionFilter())
295 Status
= _SEH2_GetExceptionCode();
301 Status
= STATUS_UNSUCCESSFUL
;
304 /* Free the allocated ANSI value buffer */
305 ExFreePoolWithTag(AnsiValueBuffer
, 'pmeT');
313 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName
,
314 IN PUNICODE_STRING Value
)
316 UNICODE_STRING CapturedName
, CapturedValue
;
317 ANSI_STRING AName
, AValue
;
318 KPROCESSOR_MODE PreviousMode
;
323 PreviousMode
= ExGetPreviousMode();
326 * Copy the strings to kernel space if necessary
328 Status
= ProbeAndCaptureUnicodeString(&CapturedName
,
331 if (NT_SUCCESS(Status
))
333 Status
= ProbeAndCaptureUnicodeString(&CapturedValue
,
336 if (NT_SUCCESS(Status
))
339 * according to ntinternals the SeSystemEnvironmentName privilege is required!
341 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege
,
345 * convert the strings to ANSI
347 Status
= RtlUnicodeStringToAnsiString(&AName
,
350 if (NT_SUCCESS(Status
))
352 Status
= RtlUnicodeStringToAnsiString(&AValue
,
355 if (NT_SUCCESS(Status
))
357 ARC_STATUS Result
= HalSetEnvironmentVariable(AName
.Buffer
,
360 Status
= (Result
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
366 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
367 Status
= STATUS_PRIVILEGE_NOT_HELD
;
370 ReleaseCapturedUnicodeString(&CapturedValue
,
374 ReleaseCapturedUnicodeString(&CapturedName
,
383 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass
,
385 IN ULONG BufferLength
)
388 return STATUS_NOT_IMPLEMENTED
;
393 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
394 IN LPGUID VendorGuid
,
396 IN OUT PULONG ReturnLength
,
397 IN OUT PULONG Attributes
)
400 return STATUS_NOT_IMPLEMENTED
;
405 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName
,
406 IN LPGUID VendorGuid
)
409 return STATUS_NOT_IMPLEMENTED
;
412 /* --- Query/Set System Information --- */
415 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
416 * so the stack is popped only in one place on x86 platform.
418 #define QSI_USE(n) QSI##n
420 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
422 #define SSI_USE(n) SSI##n
424 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
428 ExQueryPoolUsage(OUT PULONG PagedPoolPages
,
429 OUT PULONG NonPagedPoolPages
,
430 OUT PULONG PagedPoolAllocs
,
431 OUT PULONG PagedPoolFrees
,
432 OUT PULONG PagedPoolLookasideHits
,
433 OUT PULONG NonPagedPoolAllocs
,
434 OUT PULONG NonPagedPoolFrees
,
435 OUT PULONG NonPagedPoolLookasideHits
);
437 /* Class 0 - Basic Information */
438 QSI_DEF(SystemBasicInformation
)
440 PSYSTEM_BASIC_INFORMATION Sbi
441 = (PSYSTEM_BASIC_INFORMATION
) Buffer
;
443 *ReqSize
= sizeof(SYSTEM_BASIC_INFORMATION
);
445 /* Check user buffer's size */
446 if (Size
!= sizeof(SYSTEM_BASIC_INFORMATION
))
448 return STATUS_INFO_LENGTH_MISMATCH
;
451 RtlZeroMemory(Sbi
, Size
);
453 Sbi
->TimerResolution
= KeMaximumIncrement
;
454 Sbi
->PageSize
= PAGE_SIZE
;
455 Sbi
->NumberOfPhysicalPages
= MmNumberOfPhysicalPages
;
456 Sbi
->LowestPhysicalPageNumber
= (ULONG
)MmLowestPhysicalPage
;
457 Sbi
->HighestPhysicalPageNumber
= (ULONG
)MmHighestPhysicalPage
;
458 Sbi
->AllocationGranularity
= MM_VIRTMEM_GRANULARITY
; /* hard coded on Intel? */
459 Sbi
->MinimumUserModeAddress
= 0x10000; /* Top of 64k */
460 Sbi
->MaximumUserModeAddress
= (ULONG_PTR
)MmHighestUserAddress
;
461 Sbi
->ActiveProcessorsAffinityMask
= KeActiveProcessors
;
462 Sbi
->NumberOfProcessors
= KeNumberProcessors
;
464 return STATUS_SUCCESS
;
467 /* Class 1 - Processor Information */
468 QSI_DEF(SystemProcessorInformation
)
470 PSYSTEM_PROCESSOR_INFORMATION Spi
471 = (PSYSTEM_PROCESSOR_INFORMATION
) Buffer
;
473 *ReqSize
= sizeof(SYSTEM_PROCESSOR_INFORMATION
);
475 /* Check user buffer's size */
476 if (Size
< sizeof(SYSTEM_PROCESSOR_INFORMATION
))
478 return STATUS_INFO_LENGTH_MISMATCH
;
480 Spi
->ProcessorArchitecture
= KeProcessorArchitecture
;
481 Spi
->ProcessorLevel
= KeProcessorLevel
;
482 Spi
->ProcessorRevision
= KeProcessorRevision
;
484 Spi
->ProcessorFeatureBits
= KeFeatureBits
;
486 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi
->ProcessorArchitecture
,
487 Spi
->ProcessorLevel
, Spi
->ProcessorRevision
);
489 return STATUS_SUCCESS
;
492 /* Class 2 - Performance Information */
493 QSI_DEF(SystemPerformanceInformation
)
495 ULONG IdleUser
, IdleKernel
;
496 PSYSTEM_PERFORMANCE_INFORMATION Spi
497 = (PSYSTEM_PERFORMANCE_INFORMATION
) Buffer
;
499 PEPROCESS TheIdleProcess
;
501 *ReqSize
= sizeof(SYSTEM_PERFORMANCE_INFORMATION
);
503 /* Check user buffer's size */
504 if (Size
< sizeof(SYSTEM_PERFORMANCE_INFORMATION
))
506 return STATUS_INFO_LENGTH_MISMATCH
;
509 TheIdleProcess
= PsIdleProcess
;
511 IdleKernel
= KeQueryRuntimeProcess(&TheIdleProcess
->Pcb
, &IdleUser
);
512 Spi
->IdleProcessTime
.QuadPart
= UInt32x32To64(IdleKernel
, KeMaximumIncrement
);
513 Spi
->IoReadTransferCount
= IoReadTransferCount
;
514 Spi
->IoWriteTransferCount
= IoWriteTransferCount
;
515 Spi
->IoOtherTransferCount
= IoOtherTransferCount
;
516 Spi
->IoReadOperationCount
= IoReadOperationCount
;
517 Spi
->IoWriteOperationCount
= IoWriteOperationCount
;
518 Spi
->IoOtherOperationCount
= IoOtherOperationCount
;
520 Spi
->AvailablePages
= (ULONG
)MmAvailablePages
;
522 * Add up all the used "Committed" memory + pagefile.
523 * Not sure this is right. 8^\
525 Spi
->CommittedPages
= MiMemoryConsumers
[MC_SYSTEM
].PagesUsed
+
526 MiMemoryConsumers
[MC_CACHE
].PagesUsed
+
527 MiMemoryConsumers
[MC_USER
].PagesUsed
+
530 * Add up the full system total + pagefile.
531 * All this make Taskmgr happy but not sure it is the right numbers.
532 * This too, fixes some of GlobalMemoryStatusEx numbers.
534 Spi
->CommitLimit
= MmNumberOfPhysicalPages
+ MiFreeSwapPages
+ MiUsedSwapPages
;
536 Spi
->PeakCommitment
= 0; /* FIXME */
537 Spi
->PageFaultCount
= 0; /* FIXME */
538 Spi
->CopyOnWriteCount
= 0; /* FIXME */
539 Spi
->TransitionCount
= 0; /* FIXME */
540 Spi
->CacheTransitionCount
= 0; /* FIXME */
541 Spi
->DemandZeroCount
= 0; /* FIXME */
542 Spi
->PageReadCount
= 0; /* FIXME */
543 Spi
->PageReadIoCount
= 0; /* FIXME */
544 Spi
->CacheReadCount
= 0; /* FIXME */
545 Spi
->CacheIoCount
= 0; /* FIXME */
546 Spi
->DirtyPagesWriteCount
= 0; /* FIXME */
547 Spi
->DirtyWriteIoCount
= 0; /* FIXME */
548 Spi
->MappedPagesWriteCount
= 0; /* FIXME */
549 Spi
->MappedWriteIoCount
= 0; /* FIXME */
551 Spi
->PagedPoolPages
= 0;
552 Spi
->NonPagedPoolPages
= 0;
553 Spi
->PagedPoolAllocs
= 0;
554 Spi
->PagedPoolFrees
= 0;
555 Spi
->PagedPoolLookasideHits
= 0;
556 Spi
->NonPagedPoolAllocs
= 0;
557 Spi
->NonPagedPoolFrees
= 0;
558 Spi
->NonPagedPoolLookasideHits
= 0;
559 ExQueryPoolUsage(&Spi
->PagedPoolPages
,
560 &Spi
->NonPagedPoolPages
,
561 &Spi
->PagedPoolAllocs
,
562 &Spi
->PagedPoolFrees
,
563 &Spi
->PagedPoolLookasideHits
,
564 &Spi
->NonPagedPoolAllocs
,
565 &Spi
->NonPagedPoolFrees
,
566 &Spi
->NonPagedPoolLookasideHits
);
567 Spi
->FreeSystemPtes
= 0; /* FIXME */
569 Spi
->ResidentSystemCodePage
= 0; /* FIXME */
571 Spi
->TotalSystemDriverPages
= 0; /* FIXME */
572 Spi
->Spare3Count
= 0; /* FIXME */
574 Spi
->ResidentSystemCachePage
= MiMemoryConsumers
[MC_CACHE
].PagesUsed
;
575 Spi
->ResidentPagedPoolPage
= 0; /* FIXME */
577 Spi
->ResidentSystemDriverPage
= 0; /* FIXME */
578 Spi
->CcFastReadNoWait
= 0; /* FIXME */
579 Spi
->CcFastReadWait
= 0; /* FIXME */
580 Spi
->CcFastReadResourceMiss
= 0; /* FIXME */
581 Spi
->CcFastReadNotPossible
= 0; /* FIXME */
583 Spi
->CcFastMdlReadNoWait
= 0; /* FIXME */
584 Spi
->CcFastMdlReadWait
= 0; /* FIXME */
585 Spi
->CcFastMdlReadResourceMiss
= 0; /* FIXME */
586 Spi
->CcFastMdlReadNotPossible
= 0; /* FIXME */
588 Spi
->CcMapDataNoWait
= 0; /* FIXME */
589 Spi
->CcMapDataWait
= 0; /* FIXME */
590 Spi
->CcMapDataNoWaitMiss
= 0; /* FIXME */
591 Spi
->CcMapDataWaitMiss
= 0; /* FIXME */
593 Spi
->CcPinMappedDataCount
= 0; /* FIXME */
594 Spi
->CcPinReadNoWait
= 0; /* FIXME */
595 Spi
->CcPinReadWait
= 0; /* FIXME */
596 Spi
->CcPinReadNoWaitMiss
= 0; /* FIXME */
597 Spi
->CcPinReadWaitMiss
= 0; /* FIXME */
598 Spi
->CcCopyReadNoWait
= 0; /* FIXME */
599 Spi
->CcCopyReadWait
= 0; /* FIXME */
600 Spi
->CcCopyReadNoWaitMiss
= 0; /* FIXME */
601 Spi
->CcCopyReadWaitMiss
= 0; /* FIXME */
603 Spi
->CcMdlReadNoWait
= 0; /* FIXME */
604 Spi
->CcMdlReadWait
= 0; /* FIXME */
605 Spi
->CcMdlReadNoWaitMiss
= 0; /* FIXME */
606 Spi
->CcMdlReadWaitMiss
= 0; /* FIXME */
607 Spi
->CcReadAheadIos
= 0; /* FIXME */
608 Spi
->CcLazyWriteIos
= 0; /* FIXME */
609 Spi
->CcLazyWritePages
= 0; /* FIXME */
610 Spi
->CcDataFlushes
= 0; /* FIXME */
611 Spi
->CcDataPages
= 0; /* FIXME */
612 Spi
->ContextSwitches
= 0; /* FIXME */
613 Spi
->FirstLevelTbFills
= 0; /* FIXME */
614 Spi
->SecondLevelTbFills
= 0; /* FIXME */
615 Spi
->SystemCalls
= 0; /* FIXME */
617 return STATUS_SUCCESS
;
620 /* Class 3 - Time Of Day Information */
621 QSI_DEF(SystemTimeOfDayInformation
)
623 SYSTEM_TIMEOFDAY_INFORMATION Sti
;
624 LARGE_INTEGER CurrentTime
;
626 /* Set amount of written information to 0 */
629 /* Check user buffer's size */
630 if (Size
> sizeof(SYSTEM_TIMEOFDAY_INFORMATION
))
632 return STATUS_INFO_LENGTH_MISMATCH
;
635 /* Get current time */
636 KeQuerySystemTime(&CurrentTime
);
638 /* Zero local buffer */
639 RtlZeroMemory(&Sti
, sizeof(SYSTEM_TIMEOFDAY_INFORMATION
));
641 /* Fill local time structure */
642 Sti
.BootTime
= KeBootTime
;
643 Sti
.CurrentTime
= CurrentTime
;
644 Sti
.TimeZoneBias
.QuadPart
= ExpTimeZoneBias
.QuadPart
;
645 Sti
.TimeZoneId
= ExpTimeZoneId
;
648 /* Copy as much as requested by caller */
649 RtlCopyMemory(Buffer
, &Sti
, Size
);
651 /* Set amount of information we copied */
654 return STATUS_SUCCESS
;
657 /* Class 4 - Path Information */
658 QSI_DEF(SystemPathInformation
)
660 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
661 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
663 return STATUS_BREAKPOINT
;
666 /* Class 5 - Process Information */
667 QSI_DEF(SystemProcessInformation
)
669 PSYSTEM_PROCESS_INFORMATION SpiCurrent
;
670 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
671 PEPROCESS Process
= NULL
, SystemProcess
;
672 PETHREAD CurrentThread
;
673 ANSI_STRING ImageName
;
675 USHORT ImageNameMaximumLength
; // image name len in bytes
676 USHORT ImageNameLength
;
677 PLIST_ENTRY CurrentEntry
;
678 ULONG TotalSize
= 0, ThreadsCount
;
679 ULONG TotalUser
, TotalKernel
;
681 NTSTATUS Status
= STATUS_SUCCESS
;
682 PUNICODE_STRING ProcessImageName
;
684 BOOLEAN Overflow
= FALSE
;
688 /* scan the process list */
690 PSYSTEM_PROCESS_INFORMATION Spi
691 = (PSYSTEM_PROCESS_INFORMATION
) Buffer
;
693 *ReqSize
= sizeof(SYSTEM_PROCESS_INFORMATION
);
695 /* Check for overflow */
696 if (Size
< sizeof(SYSTEM_PROCESS_INFORMATION
))
701 /* Zero user's buffer */
702 if (!Overflow
) RtlZeroMemory(Spi
, Size
);
704 SystemProcess
= PsIdleProcess
;
705 Process
= SystemProcess
;
706 Current
= (PUCHAR
) Spi
;
710 SpiCurrent
= (PSYSTEM_PROCESS_INFORMATION
) Current
;
712 if ((Process
->ProcessExiting
) &&
713 (Process
->Pcb
.Header
.SignalState
) &&
714 !(Process
->ActiveThreads
) &&
715 (IsListEmpty(&Process
->Pcb
.ThreadListHead
)))
717 DPRINT1("Process %p (%s:%lx) is a zombie\n",
718 Process
, Process
->ImageFileName
, Process
->UniqueProcessId
);
720 ImageNameMaximumLength
= 0;
725 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
726 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
729 CurrentEntry
= CurrentEntry
->Flink
;
732 // size of the structure for every process
733 CurrentSize
= sizeof(SYSTEM_PROCESS_INFORMATION
) + sizeof(SYSTEM_THREAD_INFORMATION
) * ThreadsCount
;
735 Status
= SeLocateProcessImageName(Process
, &ProcessImageName
);
737 if (NT_SUCCESS(Status
) && (ProcessImageName
->Length
> 0))
739 szSrc
= (PWCHAR
)((PCHAR
)ProcessImageName
->Buffer
+ ProcessImageName
->Length
);
740 /* Loop the file name*/
741 while (szSrc
> ProcessImageName
->Buffer
)
743 /* Make sure this isn't a backslash */
744 if (*--szSrc
== OBJ_NAME_PATH_SEPARATOR
)
751 ImageNameLength
+= sizeof(WCHAR
);
755 if (!ImageNameLength
&& Process
!= PsIdleProcess
)
757 ImageNameLength
= (USHORT
)strlen(Process
->ImageFileName
) * sizeof(WCHAR
);
760 /* Round up the image name length as NT does */
761 if (ImageNameLength
> 0)
762 ImageNameMaximumLength
= ROUND_UP(ImageNameLength
+ sizeof(WCHAR
), 8);
764 ImageNameMaximumLength
= 0;
766 TotalSize
+= CurrentSize
+ ImageNameMaximumLength
;
768 /* Check for overflow */
769 if (TotalSize
> Size
)
774 /* Fill system information */
777 SpiCurrent
->NextEntryOffset
= CurrentSize
+ ImageNameMaximumLength
; // relative offset to the beginnnig of the next structure
778 SpiCurrent
->NumberOfThreads
= ThreadsCount
;
779 SpiCurrent
->CreateTime
= Process
->CreateTime
;
780 SpiCurrent
->ImageName
.Length
= ImageNameLength
;
781 SpiCurrent
->ImageName
.MaximumLength
= ImageNameMaximumLength
;
782 SpiCurrent
->ImageName
.Buffer
= (void*)(Current
+ CurrentSize
);
784 /* Copy name to the end of the struct */
785 if(Process
!= PsIdleProcess
)
789 RtlCopyMemory(SpiCurrent
->ImageName
.Buffer
, szSrc
, SpiCurrent
->ImageName
.Length
);
791 /* Release the memory allocated by SeLocateProcessImageName */
792 ExFreePool(ProcessImageName
);
796 RtlInitAnsiString(&ImageName
, Process
->ImageFileName
);
797 RtlAnsiStringToUnicodeString(&SpiCurrent
->ImageName
, &ImageName
, FALSE
);
802 RtlInitUnicodeString(&SpiCurrent
->ImageName
, NULL
);
805 SpiCurrent
->BasePriority
= Process
->Pcb
.BasePriority
;
806 SpiCurrent
->UniqueProcessId
= Process
->UniqueProcessId
;
807 SpiCurrent
->InheritedFromUniqueProcessId
= Process
->InheritedFromUniqueProcessId
;
808 SpiCurrent
->HandleCount
= ObGetProcessHandleCount(Process
);
809 SpiCurrent
->PeakVirtualSize
= Process
->PeakVirtualSize
;
810 SpiCurrent
->VirtualSize
= Process
->VirtualSize
;
811 SpiCurrent
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
812 SpiCurrent
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
813 SpiCurrent
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
814 SpiCurrent
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
815 SpiCurrent
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
816 SpiCurrent
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
817 SpiCurrent
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
818 SpiCurrent
->PagefileUsage
= Process
->QuotaUsage
[2];
819 SpiCurrent
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
820 SpiCurrent
->PrivatePageCount
= Process
->CommitCharge
;
821 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(SpiCurrent
+ 1);
823 CurrentEntry
= Process
->Pcb
.ThreadListHead
.Flink
;
824 while (CurrentEntry
!= &Process
->Pcb
.ThreadListHead
)
826 CurrentThread
= (PETHREAD
)CONTAINING_RECORD(CurrentEntry
, KTHREAD
,
829 ThreadInfo
->KernelTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.KernelTime
, KeMaximumIncrement
);
830 ThreadInfo
->UserTime
.QuadPart
= UInt32x32To64(CurrentThread
->Tcb
.UserTime
, KeMaximumIncrement
);
831 ThreadInfo
->CreateTime
.QuadPart
= CurrentThread
->CreateTime
.QuadPart
;
832 ThreadInfo
->WaitTime
= CurrentThread
->Tcb
.WaitTime
;
833 ThreadInfo
->StartAddress
= (PVOID
) CurrentThread
->StartAddress
;
834 ThreadInfo
->ClientId
= CurrentThread
->Cid
;
835 ThreadInfo
->Priority
= CurrentThread
->Tcb
.Priority
;
836 ThreadInfo
->BasePriority
= CurrentThread
->Tcb
.BasePriority
;
837 ThreadInfo
->ContextSwitches
= CurrentThread
->Tcb
.ContextSwitches
;
838 ThreadInfo
->ThreadState
= CurrentThread
->Tcb
.State
;
839 ThreadInfo
->WaitReason
= CurrentThread
->Tcb
.WaitReason
;
842 CurrentEntry
= CurrentEntry
->Flink
;
845 /* Query total user/kernel times of a process */
846 TotalKernel
= KeQueryRuntimeProcess(&Process
->Pcb
, &TotalUser
);
847 SpiCurrent
->UserTime
.QuadPart
= UInt32x32To64(TotalUser
, KeMaximumIncrement
);
848 SpiCurrent
->KernelTime
.QuadPart
= UInt32x32To64(TotalKernel
, KeMaximumIncrement
);
851 /* Handle idle process entry */
853 if (Process
== PsIdleProcess
) Process
= NULL
;
855 Process
= PsGetNextProcess(Process
);
857 if ((Process
== SystemProcess
) || (Process
== NULL
))
860 SpiCurrent
->NextEntryOffset
= 0;
864 Current
+= CurrentSize
+ ImageNameMaximumLength
;
865 } while ((Process
!= SystemProcess
) && (Process
!= NULL
));
868 ObDereferenceObject(Process
);
869 Status
= STATUS_SUCCESS
;
871 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
874 ObDereferenceObject(Process
);
875 Status
= _SEH2_GetExceptionCode();
880 Status
= STATUS_INFO_LENGTH_MISMATCH
;
882 *ReqSize
= TotalSize
;
886 /* Class 6 - Call Count Information */
887 QSI_DEF(SystemCallCountInformation
)
890 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
891 return STATUS_NOT_IMPLEMENTED
;
894 /* Class 7 - Device Information */
895 QSI_DEF(SystemDeviceInformation
)
897 PSYSTEM_DEVICE_INFORMATION Sdi
898 = (PSYSTEM_DEVICE_INFORMATION
) Buffer
;
899 PCONFIGURATION_INFORMATION ConfigInfo
;
901 *ReqSize
= sizeof(SYSTEM_DEVICE_INFORMATION
);
903 /* Check user buffer's size */
904 if (Size
< sizeof(SYSTEM_DEVICE_INFORMATION
))
906 return STATUS_INFO_LENGTH_MISMATCH
;
909 ConfigInfo
= IoGetConfigurationInformation();
911 Sdi
->NumberOfDisks
= ConfigInfo
->DiskCount
;
912 Sdi
->NumberOfFloppies
= ConfigInfo
->FloppyCount
;
913 Sdi
->NumberOfCdRoms
= ConfigInfo
->CdRomCount
;
914 Sdi
->NumberOfTapes
= ConfigInfo
->TapeCount
;
915 Sdi
->NumberOfSerialPorts
= ConfigInfo
->SerialCount
;
916 Sdi
->NumberOfParallelPorts
= ConfigInfo
->ParallelCount
;
918 return STATUS_SUCCESS
;
921 /* Class 8 - Processor Performance Information */
922 QSI_DEF(SystemProcessorPerformanceInformation
)
924 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
925 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) Buffer
;
931 *ReqSize
= KeNumberProcessors
* sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
933 /* Check user buffer's size */
936 return STATUS_INFO_LENGTH_MISMATCH
;
939 for (i
= 0; i
< KeNumberProcessors
; i
++)
941 /* Get the PRCB on this processor */
942 Prcb
= KiProcessorBlock
[i
];
944 /* Calculate total user and kernel times */
945 TotalTime
= Prcb
->IdleThread
->KernelTime
+ Prcb
->IdleThread
->UserTime
;
946 Spi
->IdleTime
.QuadPart
= UInt32x32To64(TotalTime
, KeMaximumIncrement
);
947 Spi
->KernelTime
.QuadPart
= UInt32x32To64(Prcb
->KernelTime
, KeMaximumIncrement
);
948 Spi
->UserTime
.QuadPart
= UInt32x32To64(Prcb
->UserTime
, KeMaximumIncrement
);
949 Spi
->DpcTime
.QuadPart
= UInt32x32To64(Prcb
->DpcTime
, KeMaximumIncrement
);
950 Spi
->InterruptTime
.QuadPart
= UInt32x32To64(Prcb
->InterruptTime
, KeMaximumIncrement
);
951 Spi
->InterruptCount
= Prcb
->InterruptCount
;
955 return STATUS_SUCCESS
;
958 /* Class 9 - Flags Information */
959 QSI_DEF(SystemFlagsInformation
)
961 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
963 *ReqSize
= sizeof(SYSTEM_FLAGS_INFORMATION
);
964 return (STATUS_INFO_LENGTH_MISMATCH
);
966 ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
= NtGlobalFlag
;
967 return STATUS_SUCCESS
;
970 SSI_DEF(SystemFlagsInformation
)
972 if (sizeof(SYSTEM_FLAGS_INFORMATION
) != Size
)
974 return STATUS_INFO_LENGTH_MISMATCH
;
976 NtGlobalFlag
= ((PSYSTEM_FLAGS_INFORMATION
) Buffer
)->Flags
;
977 return STATUS_SUCCESS
;
980 /* Class 10 - Call Time Information */
981 QSI_DEF(SystemCallTimeInformation
)
984 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
985 return STATUS_NOT_IMPLEMENTED
;
988 /* Class 11 - Module Information */
989 QSI_DEF(SystemModuleInformation
)
993 /* Acquire system module list lock */
994 KeEnterCriticalRegion();
995 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource
, TRUE
);
997 /* Call the generic handler with the system module list */
998 Status
= ExpQueryModuleInformation(&PsLoadedModuleList
,
999 &MmLoadedUserImageList
,
1000 (PRTL_PROCESS_MODULES
)Buffer
,
1004 /* Release list lock and return status */
1005 ExReleaseResourceLite(&PsLoadedModuleResource
);
1006 KeLeaveCriticalRegion();
1010 /* Class 12 - Locks Information */
1011 QSI_DEF(SystemLocksInformation
)
1014 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1015 return STATUS_NOT_IMPLEMENTED
;
1018 /* Class 13 - Stack Trace Information */
1019 QSI_DEF(SystemStackTraceInformation
)
1022 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1023 return STATUS_NOT_IMPLEMENTED
;
1026 /* Class 14 - Paged Pool Information */
1027 QSI_DEF(SystemPagedPoolInformation
)
1030 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1031 return STATUS_NOT_IMPLEMENTED
;
1034 /* Class 15 - Non Paged Pool Information */
1035 QSI_DEF(SystemNonPagedPoolInformation
)
1038 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1039 return STATUS_NOT_IMPLEMENTED
;
1043 /* Class 16 - Handle Information */
1044 QSI_DEF(SystemHandleInformation
)
1046 PEPROCESS pr
, syspr
;
1047 ULONG curSize
, i
= 0;
1050 PSYSTEM_HANDLE_INFORMATION Shi
=
1051 (PSYSTEM_HANDLE_INFORMATION
) Buffer
;
1053 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1055 if (Size
< sizeof(SYSTEM_HANDLE_INFORMATION
))
1057 *ReqSize
= sizeof(SYSTEM_HANDLE_INFORMATION
);
1058 return STATUS_INFO_LENGTH_MISMATCH
;
1061 DPRINT("SystemHandleInformation 1\n");
1063 /* First Calc Size from Count. */
1064 syspr
= PsGetNextProcess(NULL
);
1069 hCount
= hCount
+ ObGetProcessHandleCount(pr
);
1070 pr
= PsGetNextProcess(pr
);
1072 if ((pr
== syspr
) || (pr
== NULL
)) break;
1074 while ((pr
!= syspr
) && (pr
!= NULL
));
1078 ObDereferenceObject(pr
);
1081 DPRINT("SystemHandleInformation 2\n");
1083 curSize
= sizeof(SYSTEM_HANDLE_INFORMATION
) +
1084 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
) * hCount
) -
1085 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO
)));
1087 Shi
->NumberOfHandles
= hCount
;
1092 return (STATUS_INFO_LENGTH_MISMATCH
);
1095 DPRINT("SystemHandleInformation 3\n");
1097 /* Now get Handles from all processs. */
1098 syspr
= PsGetNextProcess(NULL
);
1103 int Count
= 0, HandleCount
;
1105 HandleCount
= ObGetProcessHandleCount(pr
);
1107 for (Count
= 0; HandleCount
> 0 ; HandleCount
--)
1109 Shi
->Handles
[i
].UniqueProcessId
= (USHORT
)(ULONG_PTR
)pr
->UniqueProcessId
;
1114 pr
= PsGetNextProcess(pr
);
1116 if ((pr
== syspr
) || (pr
== NULL
)) break;
1118 while ((pr
!= syspr
) && (pr
!= NULL
));
1120 if(pr
!= NULL
) ObDereferenceObject(pr
);
1122 DPRINT("SystemHandleInformation 4\n");
1123 return STATUS_SUCCESS
;
1127 SSI_DEF(SystemHandleInformation)
1130 return STATUS_SUCCESS;
1134 /* Class 17 - Information */
1135 QSI_DEF(SystemObjectInformation
)
1138 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1139 return STATUS_NOT_IMPLEMENTED
;
1142 /* Class 18 - Information */
1143 QSI_DEF(SystemPageFileInformation
)
1145 UNICODE_STRING FileName
; /* FIXME */
1146 SYSTEM_PAGEFILE_INFORMATION
*Spfi
= (SYSTEM_PAGEFILE_INFORMATION
*) Buffer
;
1148 if (Size
< sizeof(SYSTEM_PAGEFILE_INFORMATION
))
1150 * ReqSize
= sizeof(SYSTEM_PAGEFILE_INFORMATION
);
1151 return STATUS_INFO_LENGTH_MISMATCH
;
1154 RtlInitUnicodeString(&FileName
, NULL
); /* FIXME */
1157 Spfi
->NextEntryOffset
= 0;
1159 Spfi
->TotalSize
= MiFreeSwapPages
+ MiUsedSwapPages
;
1160 Spfi
->TotalInUse
= MiUsedSwapPages
;
1161 Spfi
->PeakUsage
= MiUsedSwapPages
; /* FIXME */
1162 Spfi
->PageFileName
= FileName
;
1163 return STATUS_SUCCESS
;
1166 /* Class 19 - Vdm Instemul Information */
1167 QSI_DEF(SystemVdmInstemulInformation
)
1170 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1171 return STATUS_NOT_IMPLEMENTED
;
1174 /* Class 20 - Vdm Bop Information */
1175 QSI_DEF(SystemVdmBopInformation
)
1178 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1179 return STATUS_NOT_IMPLEMENTED
;
1182 /* Class 21 - File Cache Information */
1183 QSI_DEF(SystemFileCacheInformation
)
1185 SYSTEM_FILECACHE_INFORMATION
*Sci
= (SYSTEM_FILECACHE_INFORMATION
*) Buffer
;
1187 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1189 *ReqSize
= sizeof(SYSTEM_FILECACHE_INFORMATION
);
1190 return STATUS_INFO_LENGTH_MISMATCH
;
1193 RtlZeroMemory(Sci
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
1195 /* Return the Byte size not the page size. */
1197 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
;
1199 MiMemoryConsumers
[MC_CACHE
].PagesUsed
* PAGE_SIZE
; /* FIXME */
1200 /* Taskmgr multiplies this one by page size right away */
1201 Sci
->CurrentSizeIncludingTransitionInPages
=
1202 MiMemoryConsumers
[MC_CACHE
].PagesUsed
; /* FIXME: Should be */
1203 /* system working set and standby pages. */
1204 Sci
->PageFaultCount
= 0; /* FIXME */
1205 Sci
->MinimumWorkingSet
= 0; /* FIXME */
1206 Sci
->MaximumWorkingSet
= 0; /* FIXME */
1208 return STATUS_SUCCESS
;
1211 SSI_DEF(SystemFileCacheInformation
)
1213 if (Size
< sizeof(SYSTEM_FILECACHE_INFORMATION
))
1215 return STATUS_INFO_LENGTH_MISMATCH
;
1218 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1219 return STATUS_NOT_IMPLEMENTED
;
1222 /* Class 22 - Pool Tag Information */
1223 QSI_DEF(SystemPoolTagInformation
)
1225 if (Size
< sizeof(SYSTEM_POOLTAG_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
1226 return ExGetPoolTagInfo(Buffer
, Size
, ReqSize
);
1229 /* Class 23 - Interrupt Information for all processors */
1230 QSI_DEF(SystemInterruptInformation
)
1235 PSYSTEM_INTERRUPT_INFORMATION sii
= (PSYSTEM_INTERRUPT_INFORMATION
)Buffer
;
1237 if(Size
< KeNumberProcessors
* sizeof(SYSTEM_INTERRUPT_INFORMATION
))
1239 return STATUS_INFO_LENGTH_MISMATCH
;
1242 ti
= KeQueryTimeIncrement();
1244 for (i
= 0; i
< KeNumberProcessors
; i
++)
1246 Prcb
= KiProcessorBlock
[i
];
1247 sii
->ContextSwitches
= KeGetContextSwitches(Prcb
);
1248 sii
->DpcCount
= Prcb
->DpcData
[0].DpcCount
;
1249 sii
->DpcRate
= Prcb
->DpcRequestRate
;
1250 sii
->TimeIncrement
= ti
;
1251 sii
->DpcBypassCount
= 0;
1252 sii
->ApcBypassCount
= 0;
1256 return STATUS_SUCCESS
;
1259 /* Class 24 - DPC Behaviour Information */
1260 QSI_DEF(SystemDpcBehaviourInformation
)
1263 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1264 return STATUS_NOT_IMPLEMENTED
;
1267 SSI_DEF(SystemDpcBehaviourInformation
)
1270 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1271 return STATUS_NOT_IMPLEMENTED
;
1274 /* Class 25 - Full Memory Information */
1275 QSI_DEF(SystemFullMemoryInformation
)
1277 PULONG Spi
= (PULONG
) Buffer
;
1279 PEPROCESS TheIdleProcess
;
1281 *ReqSize
= sizeof(ULONG
);
1283 if (sizeof(ULONG
) != Size
)
1285 return STATUS_INFO_LENGTH_MISMATCH
;
1288 DPRINT("SystemFullMemoryInformation\n");
1290 TheIdleProcess
= PsIdleProcess
;
1292 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1293 TheIdleProcess
->UniqueProcessId
,
1294 TheIdleProcess
->Pcb
.KernelTime
,
1298 *Spi
= MiMemoryConsumers
[MC_USER
].PagesUsed
;
1300 return STATUS_SUCCESS
;
1303 /* Class 26 - Load Image */
1304 SSI_DEF(SystemLoadGdiDriverInformation
)
1306 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo
= (PVOID
)Buffer
;
1307 UNICODE_STRING ImageName
;
1309 PVOID SectionPointer
;
1310 ULONG_PTR EntryPoint
;
1313 PIMAGE_NT_HEADERS NtHeader
;
1316 if (Size
!= sizeof(SYSTEM_GDI_DRIVER_INFORMATION
))
1318 /* Incorrect buffer length, fail */
1319 return STATUS_INFO_LENGTH_MISMATCH
;
1322 /* Only kernel mode can call this function */
1323 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1325 /* Load the driver */
1326 ImageName
= DriverInfo
->DriverName
;
1327 Status
= MmLoadSystemImage(&ImageName
,
1333 if (!NT_SUCCESS(Status
)) return Status
;
1335 /* Return the export pointer */
1336 DriverInfo
->ExportSectionPointer
=
1337 RtlImageDirectoryEntryToData(ImageBase
,
1339 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1342 /* Get the entrypoint */
1343 NtHeader
= RtlImageNtHeader(ImageBase
);
1344 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1345 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1347 /* Save other data */
1348 DriverInfo
->ImageAddress
= ImageBase
;
1349 DriverInfo
->SectionPointer
= SectionPointer
;
1350 DriverInfo
->EntryPoint
= (PVOID
)EntryPoint
;
1351 DriverInfo
->ImageLength
= NtHeader
->OptionalHeader
.SizeOfImage
;
1354 return STATUS_SUCCESS
;
1357 /* Class 27 - Unload Image */
1358 SSI_DEF(SystemUnloadGdiDriverInformation
)
1360 PVOID SectionPointer
= Buffer
;
1363 if (Size
!= sizeof(PVOID
))
1365 /* Incorrect length, fail */
1366 return STATUS_INFO_LENGTH_MISMATCH
;
1369 /* Only kernel mode can call this function */
1370 if (ExGetPreviousMode() != KernelMode
) return STATUS_PRIVILEGE_NOT_HELD
;
1372 /* Unload the image */
1373 MmUnloadSystemImage(SectionPointer
);
1374 return STATUS_SUCCESS
;
1377 /* Class 28 - Time Adjustment Information */
1378 QSI_DEF(SystemTimeAdjustmentInformation
)
1380 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
=
1381 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION
)Buffer
;
1383 /* Check if enough storage was provided */
1384 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
) > Size
)
1386 * ReqSize
= sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION
);
1387 return STATUS_INFO_LENGTH_MISMATCH
;
1390 /* Give time values to our caller */
1391 TimeInfo
->TimeIncrement
= KeMaximumIncrement
;
1392 TimeInfo
->TimeAdjustment
= KeTimeAdjustment
;
1393 TimeInfo
->Enable
= !KiTimeAdjustmentEnabled
;
1395 return STATUS_SUCCESS
;
1398 SSI_DEF(SystemTimeAdjustmentInformation
)
1400 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1401 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
=
1402 (PSYSTEM_SET_TIME_ADJUST_INFORMATION
)Buffer
;
1404 /* Check size of a buffer, it must match our expectations */
1405 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION
) != Size
)
1406 return STATUS_INFO_LENGTH_MISMATCH
;
1408 /* Check who is calling */
1409 if (PreviousMode
!= KernelMode
)
1411 /* Check access rights */
1412 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege
, PreviousMode
))
1414 return STATUS_PRIVILEGE_NOT_HELD
;
1418 /* FIXME: behaviour suggests the member be named 'Disable' */
1419 if (TimeInfo
->Enable
)
1421 /* Disable time adjustment and set default value */
1422 KiTimeAdjustmentEnabled
= FALSE
;
1423 KeTimeAdjustment
= KeMaximumIncrement
;
1427 /* Check if a valid time adjustment value is given */
1428 if (TimeInfo
->TimeAdjustment
== 0) return STATUS_INVALID_PARAMETER_2
;
1430 /* Enable time adjustment and set the adjustment value */
1431 KiTimeAdjustmentEnabled
= TRUE
;
1432 KeTimeAdjustment
= TimeInfo
->TimeAdjustment
;
1435 return STATUS_SUCCESS
;
1438 /* Class 29 - Summary Memory Information */
1439 QSI_DEF(SystemSummaryMemoryInformation
)
1442 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1443 return STATUS_NOT_IMPLEMENTED
;
1446 /* Class 30 - Next Event Id Information */
1447 QSI_DEF(SystemNextEventIdInformation
)
1450 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1451 return STATUS_NOT_IMPLEMENTED
;
1454 /* Class 31 - Event Ids Information */
1455 QSI_DEF(SystemEventIdsInformation
)
1458 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1459 return STATUS_NOT_IMPLEMENTED
;
1462 /* Class 32 - Crash Dump Information */
1463 QSI_DEF(SystemCrashDumpInformation
)
1466 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1467 return STATUS_NOT_IMPLEMENTED
;
1470 /* Class 33 - Exception Information */
1471 QSI_DEF(SystemExceptionInformation
)
1473 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation
=
1474 (PSYSTEM_EXCEPTION_INFORMATION
)Buffer
;
1476 ULONG AlignmentFixupCount
= 0, ExceptionDispatchCount
= 0;
1477 ULONG FloatingEmulationCount
= 0, ByteWordEmulationCount
= 0;
1480 /* Check size of a buffer, it must match our expectations */
1481 if (sizeof(SYSTEM_EXCEPTION_INFORMATION
) != Size
)
1482 return STATUS_INFO_LENGTH_MISMATCH
;
1484 /* Sum up exception count information from all processors */
1485 for (i
= 0; i
< KeNumberProcessors
; i
++)
1487 Prcb
= KiProcessorBlock
[i
];
1490 AlignmentFixupCount
+= Prcb
->KeAlignmentFixupCount
;
1491 ExceptionDispatchCount
+= Prcb
->KeExceptionDispatchCount
;
1492 FloatingEmulationCount
+= Prcb
->KeFloatingEmulationCount
;
1496 /* Save information in user's buffer */
1497 ExceptionInformation
->AlignmentFixupCount
= AlignmentFixupCount
;
1498 ExceptionInformation
->ExceptionDispatchCount
= ExceptionDispatchCount
;
1499 ExceptionInformation
->FloatingEmulationCount
= FloatingEmulationCount
;
1500 ExceptionInformation
->ByteWordEmulationCount
= ByteWordEmulationCount
;
1502 return STATUS_SUCCESS
;
1505 /* Class 34 - Crash Dump State Information */
1506 QSI_DEF(SystemCrashDumpStateInformation
)
1509 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1510 return STATUS_NOT_IMPLEMENTED
;
1513 /* Class 35 - Kernel Debugger Information */
1514 QSI_DEF(SystemKernelDebuggerInformation
)
1516 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
= (PSYSTEM_KERNEL_DEBUGGER_INFORMATION
) Buffer
;
1518 *ReqSize
= sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
);
1519 if (Size
< sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION
))
1521 return STATUS_INFO_LENGTH_MISMATCH
;
1524 skdi
->KernelDebuggerEnabled
= KD_DEBUGGER_ENABLED
;
1525 skdi
->KernelDebuggerNotPresent
= KD_DEBUGGER_NOT_PRESENT
;
1527 return STATUS_SUCCESS
;
1530 /* Class 36 - Context Switch Information */
1531 QSI_DEF(SystemContextSwitchInformation
)
1533 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation
=
1534 (PSYSTEM_CONTEXT_SWITCH_INFORMATION
)Buffer
;
1535 ULONG ContextSwitches
;
1539 /* Check size of a buffer, it must match our expectations */
1540 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION
) != Size
)
1541 return STATUS_INFO_LENGTH_MISMATCH
;
1543 /* Calculate total value of context switches across all processors */
1544 ContextSwitches
= 0;
1545 for (i
= 0; i
< KeNumberProcessors
; i
++)
1547 Prcb
= KiProcessorBlock
[i
];
1550 ContextSwitches
+= KeGetContextSwitches(Prcb
);
1554 ContextSwitchInformation
->ContextSwitches
= ContextSwitches
;
1557 ContextSwitchInformation
->FindAny
= 0;
1558 ContextSwitchInformation
->FindLast
= 0;
1559 ContextSwitchInformation
->FindIdeal
= 0;
1560 ContextSwitchInformation
->IdleAny
= 0;
1561 ContextSwitchInformation
->IdleCurrent
= 0;
1562 ContextSwitchInformation
->IdleLast
= 0;
1563 ContextSwitchInformation
->IdleIdeal
= 0;
1564 ContextSwitchInformation
->PreemptAny
= 0;
1565 ContextSwitchInformation
->PreemptCurrent
= 0;
1566 ContextSwitchInformation
->PreemptLast
= 0;
1567 ContextSwitchInformation
->SwitchToIdle
= 0;
1569 return STATUS_SUCCESS
;
1572 /* Class 37 - Registry Quota Information */
1573 QSI_DEF(SystemRegistryQuotaInformation
)
1575 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi
= (PSYSTEM_REGISTRY_QUOTA_INFORMATION
) Buffer
;
1577 *ReqSize
= sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
);
1578 if (Size
< sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION
))
1580 return STATUS_INFO_LENGTH_MISMATCH
;
1583 DPRINT1("Faking max registry size of 32 MB\n");
1584 srqi
->RegistryQuotaAllowed
= 0x2000000;
1585 srqi
->RegistryQuotaUsed
= 0x200000;
1586 srqi
->PagedPoolSize
= 0x200000;
1588 return STATUS_SUCCESS
;
1591 SSI_DEF(SystemRegistryQuotaInformation
)
1594 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1595 return STATUS_NOT_IMPLEMENTED
;
1598 /* Class 38 - Load And Call Image */
1599 SSI_DEF(SystemExtendServiceTableInformation
)
1601 UNICODE_STRING ImageName
;
1602 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1603 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1605 PIMAGE_NT_HEADERS NtHeader
;
1606 DRIVER_OBJECT Win32k
;
1607 PDRIVER_INITIALIZE DriverInit
;
1609 ULONG_PTR EntryPoint
;
1611 /* Validate the size */
1612 if (Size
!= sizeof(UNICODE_STRING
)) return STATUS_INFO_LENGTH_MISMATCH
;
1614 /* Check who is calling */
1615 if (PreviousMode
!= KernelMode
)
1617 /* Make sure we can load drivers */
1618 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, UserMode
))
1620 /* FIXME: We can't, fail */
1621 //return STATUS_PRIVILEGE_NOT_HELD;
1625 /* Probe and capture the driver name */
1626 ProbeAndCaptureUnicodeString(&ImageName
, PreviousMode
, Buffer
);
1628 /* Load the image */
1629 Status
= MmLoadSystemImage(&ImageName
,
1633 (PVOID
)&ModuleObject
,
1636 /* Release String */
1637 ReleaseCapturedUnicodeString(&ImageName
, PreviousMode
);
1639 if (!NT_SUCCESS(Status
)) return Status
;
1641 /* Get the headers */
1642 NtHeader
= RtlImageNtHeader(ImageBase
);
1646 MmUnloadSystemImage(ModuleObject
);
1647 return STATUS_INVALID_IMAGE_FORMAT
;
1650 /* Get the entrypoint */
1651 EntryPoint
= NtHeader
->OptionalHeader
.AddressOfEntryPoint
;
1652 EntryPoint
+= (ULONG_PTR
)ImageBase
;
1653 DriverInit
= (PDRIVER_INITIALIZE
)EntryPoint
;
1655 /* Create a dummy device */
1656 RtlZeroMemory(&Win32k
, sizeof(Win32k
));
1657 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1658 Win32k
.DriverStart
= ImageBase
;
1661 Status
= (DriverInit
)(&Win32k
, NULL
);
1662 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
1664 /* Unload if we failed */
1665 if (!NT_SUCCESS(Status
)) MmUnloadSystemImage(ModuleObject
);
1669 /* Class 39 - Priority Separation */
1670 SSI_DEF(SystemPrioritySeperation
)
1673 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1674 return STATUS_NOT_IMPLEMENTED
;
1677 /* Class 40 - Plug Play Bus Information */
1678 QSI_DEF(SystemPlugPlayBusInformation
)
1681 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1682 return STATUS_NOT_IMPLEMENTED
;
1685 /* Class 41 - Dock Information */
1686 QSI_DEF(SystemDockInformation
)
1689 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1690 return STATUS_NOT_IMPLEMENTED
;
1693 /* Class 42 - Power Information */
1694 QSI_DEF(SystemPowerInformation
)
1697 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1698 return STATUS_NOT_IMPLEMENTED
;
1701 /* Class 43 - Processor Speed Information */
1702 QSI_DEF(SystemProcessorSpeedInformation
)
1705 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1706 return STATUS_NOT_IMPLEMENTED
;
1709 /* Class 44 - Current Time Zone Information */
1710 QSI_DEF(SystemCurrentTimeZoneInformation
)
1712 *ReqSize
= sizeof(TIME_ZONE_INFORMATION
);
1714 if (sizeof(TIME_ZONE_INFORMATION
) != Size
)
1716 return STATUS_INFO_LENGTH_MISMATCH
;
1719 /* Copy the time zone information struct */
1722 sizeof(TIME_ZONE_INFORMATION
));
1724 return STATUS_SUCCESS
;
1728 SSI_DEF(SystemCurrentTimeZoneInformation
)
1730 /* Check user buffer's size */
1731 if (Size
< sizeof(TIME_ZONE_INFORMATION
))
1733 return STATUS_INFO_LENGTH_MISMATCH
;
1736 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION
)Buffer
);
1740 /* Class 45 - Lookaside Information */
1741 QSI_DEF(SystemLookasideInformation
)
1744 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1745 return STATUS_NOT_IMPLEMENTED
;
1749 /* Class 46 - Set time slip event */
1750 SSI_DEF(SystemSetTimeSlipEvent
)
1753 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1754 return STATUS_NOT_IMPLEMENTED
;
1759 MmSessionCreate(OUT PULONG SessionId
);
1763 MmSessionDelete(IN ULONG SessionId
);
1765 /* Class 47 - Create a new session (TSE) */
1766 SSI_DEF(SystemCreateSession
)
1769 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1772 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
1774 if (PreviousMode
!= KernelMode
)
1776 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1778 return STATUS_PRIVILEGE_NOT_HELD
;
1782 Status
= MmSessionCreate(&SessionId
);
1783 if (NT_SUCCESS(Status
)) *(PULONG
)Buffer
= SessionId
;
1789 /* Class 48 - Delete an existing session (TSE) */
1790 SSI_DEF(SystemDeleteSession
)
1793 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1795 if (Size
!= sizeof(ULONG
)) return STATUS_INFO_LENGTH_MISMATCH
;
1797 if (PreviousMode
!= KernelMode
)
1799 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege
, PreviousMode
))
1801 return STATUS_PRIVILEGE_NOT_HELD
;
1805 SessionId
= *(PULONG
)Buffer
;
1807 return MmSessionDelete(SessionId
);
1811 /* Class 49 - UNKNOWN */
1812 QSI_DEF(SystemInvalidInfoClass4
)
1815 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1816 return STATUS_NOT_IMPLEMENTED
;
1820 /* Class 50 - System range start address */
1821 QSI_DEF(SystemRangeStartInformation
)
1823 /* Check user buffer's size */
1824 if (Size
!= sizeof(ULONG_PTR
)) return STATUS_INFO_LENGTH_MISMATCH
;
1826 *(PULONG_PTR
)Buffer
= (ULONG_PTR
)MmSystemRangeStart
;
1828 if (ReqSize
) *ReqSize
= sizeof(ULONG_PTR
);
1830 return STATUS_SUCCESS
;
1833 /* Class 51 - Driver verifier information */
1834 QSI_DEF(SystemVerifierInformation
)
1837 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1838 return STATUS_NOT_IMPLEMENTED
;
1842 SSI_DEF(SystemVerifierInformation
)
1845 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1846 return STATUS_NOT_IMPLEMENTED
;
1850 /* Class 52 - Add a driver verifier */
1851 SSI_DEF(SystemAddVerifier
)
1854 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1855 return STATUS_NOT_IMPLEMENTED
;
1859 /* Class 53 - A session's processes */
1860 QSI_DEF(SystemSessionProcessesInformation
)
1863 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1864 return STATUS_NOT_IMPLEMENTED
;
1868 /* Query/Set Calls Table */
1872 NTSTATUS (* Query
) (PVOID
,ULONG
,PULONG
);
1873 NTSTATUS (* Set
) (PVOID
,ULONG
);
1880 // XX unknown behaviour
1882 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1883 #define SI_QX(n) {QSI_USE(n),NULL}
1884 #define SI_XS(n) {NULL,SSI_USE(n)}
1885 #define SI_XX(n) {NULL,NULL}
1891 SI_QX(SystemBasicInformation
),
1892 SI_QX(SystemProcessorInformation
),
1893 SI_QX(SystemPerformanceInformation
),
1894 SI_QX(SystemTimeOfDayInformation
),
1895 SI_QX(SystemPathInformation
), /* should be SI_XX */
1896 SI_QX(SystemProcessInformation
),
1897 SI_QX(SystemCallCountInformation
),
1898 SI_QX(SystemDeviceInformation
),
1899 SI_QX(SystemProcessorPerformanceInformation
),
1900 SI_QS(SystemFlagsInformation
),
1901 SI_QX(SystemCallTimeInformation
), /* should be SI_XX */
1902 SI_QX(SystemModuleInformation
),
1903 SI_QX(SystemLocksInformation
),
1904 SI_QX(SystemStackTraceInformation
), /* should be SI_XX */
1905 SI_QX(SystemPagedPoolInformation
), /* should be SI_XX */
1906 SI_QX(SystemNonPagedPoolInformation
), /* should be SI_XX */
1907 SI_QX(SystemHandleInformation
),
1908 SI_QX(SystemObjectInformation
),
1909 SI_QX(SystemPageFileInformation
),
1910 SI_QX(SystemVdmInstemulInformation
),
1911 SI_QX(SystemVdmBopInformation
), /* it should be SI_XX */
1912 SI_QS(SystemFileCacheInformation
),
1913 SI_QX(SystemPoolTagInformation
),
1914 SI_QX(SystemInterruptInformation
),
1915 SI_QS(SystemDpcBehaviourInformation
),
1916 SI_QX(SystemFullMemoryInformation
), /* it should be SI_XX */
1917 SI_XS(SystemLoadGdiDriverInformation
),
1918 SI_XS(SystemUnloadGdiDriverInformation
),
1919 SI_QS(SystemTimeAdjustmentInformation
),
1920 SI_QX(SystemSummaryMemoryInformation
), /* it should be SI_XX */
1921 SI_QX(SystemNextEventIdInformation
), /* it should be SI_XX */
1922 SI_QX(SystemEventIdsInformation
), /* it should be SI_XX */
1923 SI_QX(SystemCrashDumpInformation
),
1924 SI_QX(SystemExceptionInformation
),
1925 SI_QX(SystemCrashDumpStateInformation
),
1926 SI_QX(SystemKernelDebuggerInformation
),
1927 SI_QX(SystemContextSwitchInformation
),
1928 SI_QS(SystemRegistryQuotaInformation
),
1929 SI_XS(SystemExtendServiceTableInformation
),
1930 SI_XS(SystemPrioritySeperation
),
1931 SI_QX(SystemPlugPlayBusInformation
), /* it should be SI_XX */
1932 SI_QX(SystemDockInformation
), /* it should be SI_XX */
1933 SI_QX(SystemPowerInformation
), /* it should be SI_XX */
1934 SI_QX(SystemProcessorSpeedInformation
), /* it should be SI_XX */
1935 SI_QS(SystemCurrentTimeZoneInformation
), /* it should be SI_QX */
1936 SI_QX(SystemLookasideInformation
),
1937 SI_XS(SystemSetTimeSlipEvent
),
1938 SI_XS(SystemCreateSession
),
1939 SI_XS(SystemDeleteSession
),
1940 SI_QX(SystemInvalidInfoClass4
), /* it should be SI_XX */
1941 SI_QX(SystemRangeStartInformation
),
1942 SI_QS(SystemVerifierInformation
),
1943 SI_XS(SystemAddVerifier
),
1944 SI_QX(SystemSessionProcessesInformation
)
1947 C_ASSERT(SystemBasicInformation
== 0);
1948 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1949 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1955 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
1956 OUT PVOID SystemInformation
,
1958 OUT PULONG UnsafeResultLength
)
1960 KPROCESSOR_MODE PreviousMode
;
1962 NTSTATUS FStatus
= STATUS_NOT_IMPLEMENTED
;
1966 PreviousMode
= ExGetPreviousMode();
1970 if (PreviousMode
!= KernelMode
)
1972 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1973 ProbeForWrite(SystemInformation
, Length
, 1);
1974 if (UnsafeResultLength
!= NULL
)
1975 ProbeForWriteUlong(UnsafeResultLength
);
1979 * Check the request is valid.
1981 if (SystemInformationClass
>= MAX_SYSTEM_INFO_CLASS
)
1983 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS
);
1986 if (NULL
!= CallQS
[SystemInformationClass
].Query
)
1989 * Hand the request to a subhandler.
1991 FStatus
= CallQS
[SystemInformationClass
].Query(SystemInformation
,
1995 /* Save the result length to the caller */
1996 if (UnsafeResultLength
)
1997 *UnsafeResultLength
= ResultLength
;
2000 _SEH2_EXCEPT(ExSystemExceptionFilter())
2002 FStatus
= _SEH2_GetExceptionCode();
2012 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2013 IN PVOID SystemInformation
,
2014 IN ULONG SystemInformationLength
)
2019 * If called from user mode, check
2020 * possible unsafe arguments.
2023 if (KernelMode
!= KeGetPreviousMode())
2027 // SystemInformation,
2037 * Check the request is valid.
2039 if ((SystemInformationClass
>= MIN_SYSTEM_INFO_CLASS
) &&
2040 (SystemInformationClass
< MAX_SYSTEM_INFO_CLASS
))
2042 if (NULL
!= CallQS
[SystemInformationClass
].Set
)
2045 * Hand the request to a subhandler.
2047 return CallQS
[SystemInformationClass
].Set(SystemInformation
,
2048 SystemInformationLength
);
2052 return STATUS_INVALID_INFO_CLASS
;
2057 NtFlushInstructionCache(IN HANDLE ProcessHandle
,
2058 IN PVOID BaseAddress
,
2059 IN ULONG NumberOfBytesToFlush
)
2063 #if defined(_M_IX86) || defined(_M_AMD64)
2065 #elif defined(_M_PPC)
2066 __asm__
__volatile__("tlbsync");
2067 #elif defined(_M_MIPS)
2068 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2070 #elif defined(_M_ARM)
2071 __asm__
__volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
2073 #error Unknown architecture
2075 return STATUS_SUCCESS
;
2080 NtGetCurrentProcessorNumber(VOID
)
2082 /* Just return the CPU */
2083 return KeGetCurrentProcessorNumber();
2089 #undef ExGetPreviousMode
2092 ExGetPreviousMode (VOID
)
2094 return KeGetPreviousMode();