94ab5b8ba3df08b69ec8a877df5d184a66e49697
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/sysinfo.c
5 * PURPOSE: System information functions
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Aleksey Bragin (aleksey@reactos.org)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 VOID MmPrintMemoryStatistic(VOID);
18
19 FAST_MUTEX ExpEnvironmentLock;
20 ERESOURCE ExpFirmwareTableResource;
21 LIST_ENTRY ExpFirmwareTableProviderListHead;
22
23 NTSTATUS
24 NTAPI
25 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
26 IN PLIST_ENTRY UserModeList,
27 OUT PRTL_PROCESS_MODULES Modules,
28 IN ULONG Length,
29 OUT PULONG ReturnLength)
30 {
31 NTSTATUS Status = STATUS_SUCCESS;
32 ULONG RequiredLength;
33 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
34 PLDR_DATA_TABLE_ENTRY LdrEntry;
35 ANSI_STRING ModuleName;
36 ULONG ModuleCount = 0;
37 PLIST_ENTRY NextEntry;
38 PCHAR p;
39
40 /* Setup defaults */
41 RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules);
42 ModuleInfo = &Modules->Modules[0];
43
44 /* Loop the kernel list */
45 NextEntry = KernelModeList->Flink;
46 while (NextEntry != KernelModeList)
47 {
48 /* Get the entry */
49 LdrEntry = CONTAINING_RECORD(NextEntry,
50 LDR_DATA_TABLE_ENTRY,
51 InLoadOrderLinks);
52
53 /* Update size and check if we can manage one more entry */
54 RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
55 if (Length >= RequiredLength)
56 {
57 /* Fill it out */
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;
65
66 /* Setup name */
67 RtlInitEmptyAnsiString(&ModuleName,
68 ModuleInfo->FullPathName,
69 sizeof(ModuleInfo->FullPathName));
70
71 /* Convert it */
72 Status = RtlUnicodeStringToAnsiString(&ModuleName,
73 &LdrEntry->FullDllName,
74 FALSE);
75 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
76 {
77 /* Calculate offset to name */
78 p = ModuleName.Buffer + ModuleName.Length;
79 while ((p > ModuleName.Buffer) && (*--p))
80 {
81 /* Check if we found the separator */
82 if (*p == OBJ_NAME_PATH_SEPARATOR)
83 {
84 /* We did, break out */
85 p++;
86 break;
87 }
88 }
89
90 /* Set the offset */
91 ModuleInfo->OffsetToFileName = p - ModuleName.Buffer;
92 }
93 else
94 {
95 /* Return empty name */
96 ModuleInfo->FullPathName[0] = ANSI_NULL;
97 ModuleInfo->OffsetToFileName = 0;
98 }
99
100 /* Go to the next module */
101 ModuleInfo++;
102 }
103 else
104 {
105 /* Set error code */
106 Status = STATUS_INFO_LENGTH_MISMATCH;
107 }
108
109 /* Update count and move to next entry */
110 ModuleCount++;
111 NextEntry = NextEntry->Flink;
112 }
113
114 /* Check if caller also wanted user modules */
115 if (UserModeList)
116 {
117 /* FIXME: TODO */
118 DPRINT1("User-mode list not yet supported in ReactOS!\n");
119 }
120
121 /* Update return length */
122 if (ReturnLength) *ReturnLength = RequiredLength;
123
124 /* Validate the length again */
125 if (Length >= FIELD_OFFSET(RTL_PROCESS_MODULES, Modules))
126 {
127 /* Set the final count */
128 Modules->NumberOfModules = ModuleCount;
129 }
130 else
131 {
132 /* Otherwise, we failed */
133 Status = STATUS_INFO_LENGTH_MISMATCH;
134 }
135
136 /* Done */
137 return Status;
138 }
139
140 /* FUNCTIONS *****************************************************************/
141
142 /*
143 * @implemented
144 */
145 VOID
146 NTAPI
147 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage)
148 {
149 PKPRCB Prcb;
150 ULONG TotalTime;
151 ULONGLONG ScaledIdle;
152
153 Prcb = KeGetCurrentPrcb();
154
155 ScaledIdle = Prcb->IdleThread->KernelTime * 100;
156 TotalTime = Prcb->KernelTime + Prcb->UserTime;
157 if (TotalTime != 0)
158 *CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime));
159 else
160 *CpuUsage = 0;
161 }
162
163 /*
164 * @implemented
165 */
166 VOID
167 NTAPI
168 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime,
169 PULONG TotalCpuTime,
170 PULONG ProcessorNumber)
171 {
172 PKPRCB Prcb;
173
174 Prcb = KeGetCurrentPrcb();
175
176 *ThreadKernelTime = Prcb->KernelTime + Prcb->UserTime;
177 *TotalCpuTime = Prcb->CurrentThread->KernelTime;
178 *ProcessorNumber = KeGetCurrentProcessorNumber();
179 }
180
181 /*
182 * @implemented
183 */
184 BOOLEAN
185 NTAPI
186 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
187 {
188 /* Quick check to see if it exists at all */
189 if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
190
191 /* Return our support for it */
192 return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
193 }
194
195 /*
196 * @implemented
197 */
198 BOOLEAN
199 NTAPI
200 ExVerifySuite(SUITE_TYPE SuiteType)
201 {
202 if (SuiteType == Personal) return TRUE;
203 return FALSE;
204 }
205
206 NTSTATUS
207 NTAPI
208 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName,
209 OUT PWSTR ValueBuffer,
210 IN ULONG ValueBufferLength,
211 IN OUT PULONG ReturnLength OPTIONAL)
212 {
213 ANSI_STRING AName;
214 UNICODE_STRING WName;
215 ARC_STATUS Result;
216 PCH Value;
217 ANSI_STRING AValue;
218 UNICODE_STRING WValue;
219 KPROCESSOR_MODE PreviousMode;
220 NTSTATUS Status;
221 PAGED_CODE();
222
223 PreviousMode = ExGetPreviousMode();
224
225 if (PreviousMode != KernelMode)
226 {
227 _SEH2_TRY
228 {
229 ProbeForRead(VariableName,
230 sizeof(UNICODE_STRING),
231 sizeof(ULONG));
232
233 ProbeForWrite(ValueBuffer,
234 ValueBufferLength,
235 sizeof(WCHAR));
236
237 if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength);
238 }
239 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
240 {
241 /* Return the exception code */
242 _SEH2_YIELD(return _SEH2_GetExceptionCode());
243 }
244 _SEH2_END;
245 }
246
247 /*
248 * Copy the name to kernel space if necessary and convert it to ANSI.
249 */
250 Status = ProbeAndCaptureUnicodeString(&WName,
251 PreviousMode,
252 VariableName);
253 if (NT_SUCCESS(Status))
254 {
255 /*
256 * according to ntinternals the SeSystemEnvironmentName privilege is required!
257 */
258 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
259 PreviousMode))
260 {
261 ReleaseCapturedUnicodeString(&WName, PreviousMode);
262 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
263 return STATUS_PRIVILEGE_NOT_HELD;
264 }
265
266 /*
267 * convert the value name to ansi
268 */
269 Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
270 ReleaseCapturedUnicodeString(&WName, PreviousMode);
271
272 if (!NT_SUCCESS(Status)) return Status;
273
274 /*
275 * Create a temporary buffer for the value
276 */
277 Value = ExAllocatePool(NonPagedPool, ValueBufferLength);
278 if (Value == NULL)
279 {
280 RtlFreeAnsiString(&AName);
281 return STATUS_INSUFFICIENT_RESOURCES;
282 }
283
284 /*
285 * Get the environment variable
286 */
287 Result = HalGetEnvironmentVariable(AName.Buffer,
288 (USHORT)ValueBufferLength,
289 Value);
290 if (!Result)
291 {
292 RtlFreeAnsiString(&AName);
293 ExFreePool(Value);
294 return STATUS_UNSUCCESSFUL;
295 }
296
297 /*
298 * Convert the result to UNICODE, protect with SEH in case the value buffer
299 * isn't NULL-terminated!
300 */
301 _SEH2_TRY
302 {
303 RtlInitAnsiString(&AValue, Value);
304 Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
305 }
306 _SEH2_EXCEPT(ExSystemExceptionFilter())
307 {
308 Status = _SEH2_GetExceptionCode();
309 }
310 _SEH2_END;
311
312 if (NT_SUCCESS(Status))
313 {
314 /*
315 * Copy the result back to the caller.
316 */
317 _SEH2_TRY
318 {
319 RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
320 ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
321 if (ReturnLength != NULL)
322 {
323 *ReturnLength = WValue.Length + sizeof(WCHAR);
324 }
325
326 Status = STATUS_SUCCESS;
327 }
328 _SEH2_EXCEPT(ExSystemExceptionFilter())
329 {
330 Status = _SEH2_GetExceptionCode();
331 }
332 _SEH2_END;
333 }
334
335 /*
336 * Cleanup allocated resources.
337 */
338 RtlFreeAnsiString(&AName);
339 ExFreePool(Value);
340 }
341
342 return Status;
343 }
344
345
346 NTSTATUS
347 NTAPI
348 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName,
349 IN PUNICODE_STRING Value)
350 {
351 UNICODE_STRING CapturedName, CapturedValue;
352 ANSI_STRING AName, AValue;
353 KPROCESSOR_MODE PreviousMode;
354 NTSTATUS Status;
355
356 PAGED_CODE();
357
358 PreviousMode = ExGetPreviousMode();
359
360 /*
361 * Copy the strings to kernel space if necessary
362 */
363 Status = ProbeAndCaptureUnicodeString(&CapturedName,
364 PreviousMode,
365 VariableName);
366 if (NT_SUCCESS(Status))
367 {
368 Status = ProbeAndCaptureUnicodeString(&CapturedValue,
369 PreviousMode,
370 Value);
371 if (NT_SUCCESS(Status))
372 {
373 /*
374 * according to ntinternals the SeSystemEnvironmentName privilege is required!
375 */
376 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
377 PreviousMode))
378 {
379 /*
380 * convert the strings to ANSI
381 */
382 Status = RtlUnicodeStringToAnsiString(&AName,
383 &CapturedName,
384 TRUE);
385 if (NT_SUCCESS(Status))
386 {
387 Status = RtlUnicodeStringToAnsiString(&AValue,
388 &CapturedValue,
389 TRUE);
390 if (NT_SUCCESS(Status))
391 {
392 ARC_STATUS Result = HalSetEnvironmentVariable(AName.Buffer,
393 AValue.Buffer);
394
395 Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
396 }
397 }
398 }
399 else
400 {
401 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
402 Status = STATUS_PRIVILEGE_NOT_HELD;
403 }
404
405 ReleaseCapturedUnicodeString(&CapturedValue,
406 PreviousMode);
407 }
408
409 ReleaseCapturedUnicodeString(&CapturedName,
410 PreviousMode);
411 }
412
413 return Status;
414 }
415
416 NTSTATUS
417 NTAPI
418 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass,
419 IN PVOID Buffer,
420 IN ULONG BufferLength)
421 {
422 UNIMPLEMENTED;
423 return STATUS_NOT_IMPLEMENTED;
424 }
425
426 NTSTATUS
427 NTAPI
428 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
429 IN LPGUID VendorGuid,
430 IN PVOID Value,
431 IN OUT PULONG ReturnLength,
432 IN OUT PULONG Attributes)
433 {
434 UNIMPLEMENTED;
435 return STATUS_NOT_IMPLEMENTED;
436 }
437
438 NTSTATUS
439 NTAPI
440 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
441 IN LPGUID VendorGuid)
442 {
443 UNIMPLEMENTED;
444 return STATUS_NOT_IMPLEMENTED;
445 }
446
447 /* --- Query/Set System Information --- */
448
449 /*
450 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
451 * so the stack is popped only in one place on x86 platform.
452 */
453 #define QSI_USE(n) QSI##n
454 #define QSI_DEF(n) \
455 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
456
457 #define SSI_USE(n) SSI##n
458 #define SSI_DEF(n) \
459 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
460
461
462 /* Class 0 - Basic Information */
463 QSI_DEF(SystemBasicInformation)
464 {
465 PSYSTEM_BASIC_INFORMATION Sbi
466 = (PSYSTEM_BASIC_INFORMATION) Buffer;
467
468 *ReqSize = sizeof(SYSTEM_BASIC_INFORMATION);
469
470 /* Check user buffer's size */
471 if (Size != sizeof(SYSTEM_BASIC_INFORMATION))
472 {
473 return STATUS_INFO_LENGTH_MISMATCH;
474 }
475
476 RtlZeroMemory(Sbi, Size);
477 Sbi->Reserved = 0;
478 Sbi->TimerResolution = KeMaximumIncrement;
479 Sbi->PageSize = PAGE_SIZE;
480 Sbi->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
481 Sbi->LowestPhysicalPageNumber = MmLowestPhysicalPage;
482 Sbi->HighestPhysicalPageNumber = MmHighestPhysicalPage;
483 Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
484 Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
485 Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
486 Sbi->ActiveProcessorsAffinityMask = KeActiveProcessors;
487 Sbi->NumberOfProcessors = KeNumberProcessors;
488
489 return STATUS_SUCCESS;
490 }
491
492 /* Class 1 - Processor Information */
493 QSI_DEF(SystemProcessorInformation)
494 {
495 PSYSTEM_PROCESSOR_INFORMATION Spi
496 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
497 PKPRCB Prcb;
498
499 *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION);
500
501 /* Check user buffer's size */
502 if (Size < sizeof(SYSTEM_PROCESSOR_INFORMATION))
503 {
504 return STATUS_INFO_LENGTH_MISMATCH;
505 }
506 Prcb = KeGetCurrentPrcb();
507 Spi->ProcessorArchitecture = KeProcessorArchitecture;
508 Spi->ProcessorLevel = KeProcessorLevel;
509 Spi->ProcessorRevision = KeProcessorRevision;
510 Spi->Reserved = 0;
511 Spi->ProcessorFeatureBits = KeFeatureBits;
512
513 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
514 Spi->ProcessorLevel, Spi->ProcessorRevision);
515
516 return STATUS_SUCCESS;
517 }
518
519 /* Class 2 - Performance Information */
520 QSI_DEF(SystemPerformanceInformation)
521 {
522 ULONG IdleUser, IdleKernel;
523 PSYSTEM_PERFORMANCE_INFORMATION Spi
524 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
525
526 PEPROCESS TheIdleProcess;
527
528 *ReqSize = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
529
530 /* Check user buffer's size */
531 if (Size < sizeof(SYSTEM_PERFORMANCE_INFORMATION))
532 {
533 return STATUS_INFO_LENGTH_MISMATCH;
534 }
535
536 TheIdleProcess = PsIdleProcess;
537
538 IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
539 Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
540 Spi->IoReadTransferCount = IoReadTransferCount;
541 Spi->IoWriteTransferCount = IoWriteTransferCount;
542 Spi->IoOtherTransferCount = IoOtherTransferCount;
543 Spi->IoReadOperationCount = IoReadOperationCount;
544 Spi->IoWriteOperationCount = IoWriteOperationCount;
545 Spi->IoOtherOperationCount = IoOtherOperationCount;
546
547 Spi->AvailablePages = MmAvailablePages;
548 /*
549 * Add up all the used "Committed" memory + pagefile.
550 * Not sure this is right. 8^\
551 */
552 Spi->CommittedPages = MiMemoryConsumers[MC_PPOOL].PagesUsed +
553 MiMemoryConsumers[MC_NPPOOL].PagesUsed +
554 MiMemoryConsumers[MC_CACHE].PagesUsed +
555 MiMemoryConsumers[MC_USER].PagesUsed +
556 MiUsedSwapPages;
557 /*
558 * Add up the full system total + pagefile.
559 * All this make Taskmgr happy but not sure it is the right numbers.
560 * This too, fixes some of GlobalMemoryStatusEx numbers.
561 */
562 Spi->CommitLimit = MmNumberOfPhysicalPages + MiFreeSwapPages + MiUsedSwapPages;
563
564 Spi->PeakCommitment = 0; /* FIXME */
565 Spi->PageFaultCount = 0; /* FIXME */
566 Spi->CopyOnWriteCount = 0; /* FIXME */
567 Spi->TransitionCount = 0; /* FIXME */
568 Spi->CacheTransitionCount = 0; /* FIXME */
569 Spi->DemandZeroCount = 0; /* FIXME */
570 Spi->PageReadCount = 0; /* FIXME */
571 Spi->PageReadIoCount = 0; /* FIXME */
572 Spi->CacheReadCount = 0; /* FIXME */
573 Spi->CacheIoCount = 0; /* FIXME */
574 Spi->DirtyPagesWriteCount = 0; /* FIXME */
575 Spi->DirtyWriteIoCount = 0; /* FIXME */
576 Spi->MappedPagesWriteCount = 0; /* FIXME */
577 Spi->MappedWriteIoCount = 0; /* FIXME */
578
579 Spi->PagedPoolPages = MiMemoryConsumers[MC_PPOOL].PagesUsed;
580 Spi->PagedPoolAllocs = 0; /* FIXME */
581 Spi->PagedPoolFrees = 0; /* FIXME */
582 Spi->NonPagedPoolPages = MiMemoryConsumers[MC_NPPOOL].PagesUsed;
583 Spi->NonPagedPoolAllocs = 0; /* FIXME */
584 Spi->NonPagedPoolFrees = 0; /* FIXME */
585
586 Spi->FreeSystemPtes = 0; /* FIXME */
587
588 Spi->ResidentSystemCodePage = 0; /* FIXME */
589
590 Spi->TotalSystemDriverPages = 0; /* FIXME */
591 Spi->TotalSystemCodePages = 0; /* FIXME */
592 Spi->NonPagedPoolLookasideHits = 0; /* FIXME */
593 Spi->PagedPoolLookasideHits = 0; /* FIXME */
594 Spi->Spare3Count = 0; /* FIXME */
595
596 Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
597 Spi->ResidentPagedPoolPage = MmPagedPoolSize; /* FIXME */
598
599 Spi->ResidentSystemDriverPage = 0; /* FIXME */
600 Spi->CcFastReadNoWait = 0; /* FIXME */
601 Spi->CcFastReadWait = 0; /* FIXME */
602 Spi->CcFastReadResourceMiss = 0; /* FIXME */
603 Spi->CcFastReadNotPossible = 0; /* FIXME */
604
605 Spi->CcFastMdlReadNoWait = 0; /* FIXME */
606 Spi->CcFastMdlReadWait = 0; /* FIXME */
607 Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
608 Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
609
610 Spi->CcMapDataNoWait = 0; /* FIXME */
611 Spi->CcMapDataWait = 0; /* FIXME */
612 Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
613 Spi->CcMapDataWaitMiss = 0; /* FIXME */
614
615 Spi->CcPinMappedDataCount = 0; /* FIXME */
616 Spi->CcPinReadNoWait = 0; /* FIXME */
617 Spi->CcPinReadWait = 0; /* FIXME */
618 Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
619 Spi->CcPinReadWaitMiss = 0; /* FIXME */
620 Spi->CcCopyReadNoWait = 0; /* FIXME */
621 Spi->CcCopyReadWait = 0; /* FIXME */
622 Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
623 Spi->CcCopyReadWaitMiss = 0; /* FIXME */
624
625 Spi->CcMdlReadNoWait = 0; /* FIXME */
626 Spi->CcMdlReadWait = 0; /* FIXME */
627 Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
628 Spi->CcMdlReadWaitMiss = 0; /* FIXME */
629 Spi->CcReadAheadIos = 0; /* FIXME */
630 Spi->CcLazyWriteIos = 0; /* FIXME */
631 Spi->CcLazyWritePages = 0; /* FIXME */
632 Spi->CcDataFlushes = 0; /* FIXME */
633 Spi->CcDataPages = 0; /* FIXME */
634 Spi->ContextSwitches = 0; /* FIXME */
635 Spi->FirstLevelTbFills = 0; /* FIXME */
636 Spi->SecondLevelTbFills = 0; /* FIXME */
637 Spi->SystemCalls = 0; /* FIXME */
638
639 return STATUS_SUCCESS;
640 }
641
642 /* Class 3 - Time Of Day Information */
643 QSI_DEF(SystemTimeOfDayInformation)
644 {
645 SYSTEM_TIMEOFDAY_INFORMATION Sti;
646 LARGE_INTEGER CurrentTime;
647
648 /* Set amount of written information to 0 */
649 *ReqSize = 0;
650
651 /* Check user buffer's size */
652 if (Size > sizeof(SYSTEM_TIMEOFDAY_INFORMATION))
653 {
654 return STATUS_INFO_LENGTH_MISMATCH;
655 }
656
657 /* Get current time */
658 KeQuerySystemTime(&CurrentTime);
659
660 /* Zero local buffer */
661 RtlZeroMemory(&Sti, sizeof(SYSTEM_TIMEOFDAY_INFORMATION));
662
663 /* Fill local time structure */
664 Sti.BootTime= KeBootTime;
665 Sti.CurrentTime = CurrentTime;
666 Sti.TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
667 Sti.TimeZoneId = ExpTimeZoneId;
668 Sti.Reserved = 0;
669
670 /* Copy as much as requested by caller */
671 RtlCopyMemory(Buffer, &Sti, Size);
672
673 /* Set amount of information we copied */
674 *ReqSize = Size;
675
676 return STATUS_SUCCESS;
677 }
678
679 /* Class 4 - Path Information */
680 QSI_DEF(SystemPathInformation)
681 {
682 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
683 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
684
685 return STATUS_BREAKPOINT;
686 }
687
688 /* Class 5 - Process Information */
689 QSI_DEF(SystemProcessInformation)
690 {
691 PSYSTEM_PROCESS_INFORMATION SpiCurrent;
692 PSYSTEM_THREAD_INFORMATION ThreadInfo;
693 PEPROCESS Process = NULL, SystemProcess;
694 PETHREAD CurrentThread;
695 ANSI_STRING ImageName;
696 ULONG CurrentSize;
697 USHORT ImageNameMaximumLength; // image name len in bytes
698 USHORT ImageNameLength;
699 PLIST_ENTRY CurrentEntry;
700 ULONG TotalSize = 0, ThreadsCount;
701 ULONG TotalUser, TotalKernel;
702 PUCHAR Current;
703 NTSTATUS Status = STATUS_SUCCESS;
704 PUNICODE_STRING ProcessImageName;
705 PWCHAR szSrc;
706 BOOLEAN Overflow = FALSE;
707
708 _SEH2_TRY
709 {
710 /* scan the process list */
711
712 PSYSTEM_PROCESS_INFORMATION Spi
713 = (PSYSTEM_PROCESS_INFORMATION) Buffer;
714
715 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
716
717 /* Check for overflow */
718 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
719 Overflow = TRUE;
720
721 /* Zero user's buffer */
722 if (!Overflow) RtlZeroMemory(Spi, Size);
723
724 SystemProcess = PsIdleProcess;
725 Process = SystemProcess;
726 Current = (PUCHAR) Spi;
727
728 do
729 {
730 SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
731
732 ThreadsCount = 0;
733 CurrentEntry = Process->ThreadListHead.Flink;
734 while (CurrentEntry != &Process->ThreadListHead)
735 {
736 ThreadsCount++;
737 CurrentEntry = CurrentEntry->Flink;
738 }
739
740 // size of the structure for every process
741 CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
742 ImageNameLength = 0;
743 Status = SeLocateProcessImageName(Process, &ProcessImageName);
744 szSrc = NULL;
745 if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0))
746 {
747 szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length);
748 /* Loop the file name*/
749 while (szSrc > ProcessImageName->Buffer)
750 {
751 /* Make sure this isn't a backslash */
752 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
753 {
754 szSrc++;
755 break;
756 }
757 else
758 {
759 ImageNameLength += sizeof(WCHAR);
760 }
761 }
762 }
763 if (!ImageNameLength && Process != PsIdleProcess && Process->ImageFileName)
764 {
765 ImageNameLength = strlen(Process->ImageFileName) * sizeof(WCHAR);
766 }
767
768 /* Round up the image name length as NT does */
769 if (ImageNameLength > 0)
770 ImageNameMaximumLength = ROUND_UP(ImageNameLength + sizeof(WCHAR), 8);
771 else
772 ImageNameMaximumLength = 0;
773
774 TotalSize += CurrentSize + ImageNameMaximumLength;
775
776 /* Check for overflow */
777 if (TotalSize > Size)
778 Overflow = TRUE;
779
780 /* Fill system information */
781 if (!Overflow)
782 {
783 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginnnig of the next structure
784 SpiCurrent->NumberOfThreads = ThreadsCount;
785 SpiCurrent->CreateTime = Process->CreateTime;
786 SpiCurrent->ImageName.Length = ImageNameLength;
787 SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength;
788 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
789
790 /* Copy name to the end of the struct */
791 if(Process != PsIdleProcess)
792 {
793 if (szSrc)
794 {
795 RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
796
797 /* Release the memory allocated by SeLocateProcessImageName */
798 ExFreePool(ProcessImageName);
799 }
800 else if (Process->ImageFileName)
801 {
802 RtlInitAnsiString(&ImageName, Process->ImageFileName);
803 RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
804 }
805 }
806 else
807 {
808 RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
809 }
810
811 SpiCurrent->BasePriority = Process->Pcb.BasePriority;
812 SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
813 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId;
814 SpiCurrent->HandleCount = ObGetProcessHandleCount(Process);
815 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
816 SpiCurrent->VirtualSize = Process->VirtualSize;
817 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
818 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
819 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
820 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
821 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[0];
822 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
823 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
824 SpiCurrent->PagefileUsage = Process->QuotaUsage[2];
825 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[2];
826 SpiCurrent->PrivatePageCount = Process->CommitCharge;
827 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
828
829 CurrentEntry = Process->ThreadListHead.Flink;
830 while (CurrentEntry != &Process->ThreadListHead)
831 {
832 CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
833 ThreadListEntry);
834
835 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
836 ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
837 ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart;
838 ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
839 ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress;
840 ThreadInfo->ClientId = CurrentThread->Cid;
841 ThreadInfo->Priority = CurrentThread->Tcb.Priority;
842 ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
843 ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches;
844 ThreadInfo->ThreadState = CurrentThread->Tcb.State;
845 ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
846
847 ThreadInfo++;
848 CurrentEntry = CurrentEntry->Flink;
849 }
850
851 /* Query total user/kernel times of a process */
852 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser);
853 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
854 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
855 }
856
857 /* Handle idle process entry */
858 if (Process == PsIdleProcess) Process = NULL;
859
860 Process = PsGetNextProcess(Process);
861 ThreadsCount = 0;
862 if ((Process == SystemProcess) || (Process == NULL))
863 {
864 if (!Overflow)
865 SpiCurrent->NextEntryOffset = 0;
866 break;
867 }
868 else
869 Current += CurrentSize + ImageNameMaximumLength;
870 } while ((Process != SystemProcess) && (Process != NULL));
871
872 if(Process != NULL)
873 ObDereferenceObject(Process);
874 Status = STATUS_SUCCESS;
875 }
876 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
877 {
878 if(Process != NULL)
879 ObDereferenceObject(Process);
880 Status = _SEH2_GetExceptionCode();
881 }
882 _SEH2_END
883
884 if (Overflow)
885 Status = STATUS_INFO_LENGTH_MISMATCH;
886
887 *ReqSize = TotalSize;
888 return Status;
889 }
890
891 /* Class 6 - Call Count Information */
892 QSI_DEF(SystemCallCountInformation)
893 {
894 /* FIXME */
895 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
896 return STATUS_NOT_IMPLEMENTED;
897 }
898
899 /* Class 7 - Device Information */
900 QSI_DEF(SystemDeviceInformation)
901 {
902 PSYSTEM_DEVICE_INFORMATION Sdi
903 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
904 PCONFIGURATION_INFORMATION ConfigInfo;
905
906 *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION);
907
908 /* Check user buffer's size */
909 if (Size < sizeof(SYSTEM_DEVICE_INFORMATION))
910 {
911 return STATUS_INFO_LENGTH_MISMATCH;
912 }
913
914 ConfigInfo = IoGetConfigurationInformation();
915
916 Sdi->NumberOfDisks = ConfigInfo->DiskCount;
917 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
918 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
919 Sdi->NumberOfTapes = ConfigInfo->TapeCount;
920 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
921 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
922
923 return STATUS_SUCCESS;
924 }
925
926 /* Class 8 - Processor Performance Information */
927 QSI_DEF(SystemProcessorPerformanceInformation)
928 {
929 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
930 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
931
932 LONG i;
933 ULONG TotalTime;
934 LARGE_INTEGER CurrentTime;
935 PKPRCB Prcb;
936
937 *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
938
939 /* Check user buffer's size */
940 if (Size < *ReqSize)
941 {
942 return STATUS_INFO_LENGTH_MISMATCH;
943 }
944
945 CurrentTime.QuadPart = KeQueryInterruptTime();
946 for (i = 0; i < KeNumberProcessors; i++)
947 {
948 /* Get the PRCB on this processor */
949 Prcb = KiProcessorBlock[i];
950
951 /* Calculate total user and kernel times */
952 TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime;
953 Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement);
954 Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement);
955 Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement);
956 Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement);
957 Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement);
958 Spi->InterruptCount = Prcb->InterruptCount;
959 Spi++;
960 }
961
962 return STATUS_SUCCESS;
963 }
964
965 /* Class 9 - Flags Information */
966 QSI_DEF(SystemFlagsInformation)
967 {
968 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
969 {
970 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
971 return (STATUS_INFO_LENGTH_MISMATCH);
972 }
973 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
974 return STATUS_SUCCESS;
975 }
976
977 SSI_DEF(SystemFlagsInformation)
978 {
979 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
980 {
981 return STATUS_INFO_LENGTH_MISMATCH;
982 }
983 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
984 return STATUS_SUCCESS;
985 }
986
987 /* Class 10 - Call Time Information */
988 QSI_DEF(SystemCallTimeInformation)
989 {
990 /* FIXME */
991 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
992 return STATUS_NOT_IMPLEMENTED;
993 }
994
995 /* Class 11 - Module Information */
996 QSI_DEF(SystemModuleInformation)
997 {
998 NTSTATUS Status;
999
1000 /* Acquire system module list lock */
1001 KeEnterCriticalRegion();
1002 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
1003
1004 /* Call the generic handler with the system module list */
1005 Status = ExpQueryModuleInformation(&PsLoadedModuleList,
1006 &MmLoadedUserImageList,
1007 (PRTL_PROCESS_MODULES)Buffer,
1008 Size,
1009 ReqSize);
1010
1011 /* Release list lock and return status */
1012 ExReleaseResourceLite(&PsLoadedModuleResource);
1013 KeLeaveCriticalRegion();
1014 return Status;
1015 }
1016
1017 /* Class 12 - Locks Information */
1018 QSI_DEF(SystemLocksInformation)
1019 {
1020 /* FIXME */
1021 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1022 return STATUS_NOT_IMPLEMENTED;
1023 }
1024
1025 /* Class 13 - Stack Trace Information */
1026 QSI_DEF(SystemStackTraceInformation)
1027 {
1028 /* FIXME */
1029 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1030 return STATUS_NOT_IMPLEMENTED;
1031 }
1032
1033 /* Class 14 - Paged Pool Information */
1034 QSI_DEF(SystemPagedPoolInformation)
1035 {
1036 /* FIXME */
1037 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1038 return STATUS_NOT_IMPLEMENTED;
1039 }
1040
1041 /* Class 15 - Non Paged Pool Information */
1042 QSI_DEF(SystemNonPagedPoolInformation)
1043 {
1044 /* FIXME */
1045 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1046 return STATUS_NOT_IMPLEMENTED;
1047 }
1048
1049
1050 /* Class 16 - Handle Information */
1051 QSI_DEF(SystemHandleInformation)
1052 {
1053 PEPROCESS pr, syspr;
1054 ULONG curSize, i = 0;
1055 ULONG hCount = 0;
1056
1057 PSYSTEM_HANDLE_INFORMATION Shi =
1058 (PSYSTEM_HANDLE_INFORMATION) Buffer;
1059
1060 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1061
1062 if (Size < sizeof(SYSTEM_HANDLE_INFORMATION))
1063 {
1064 *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
1065 return STATUS_INFO_LENGTH_MISMATCH;
1066 }
1067
1068 DPRINT("SystemHandleInformation 1\n");
1069
1070 /* First Calc Size from Count. */
1071 syspr = PsGetNextProcess(NULL);
1072 pr = syspr;
1073
1074 do
1075 {
1076 hCount = hCount + ObGetProcessHandleCount(pr);
1077 pr = PsGetNextProcess(pr);
1078
1079 if ((pr == syspr) || (pr == NULL)) break;
1080 }
1081 while ((pr != syspr) && (pr != NULL));
1082
1083 if(pr != NULL)
1084 {
1085 ObDereferenceObject(pr);
1086 }
1087
1088 DPRINT("SystemHandleInformation 2\n");
1089
1090 curSize = sizeof(SYSTEM_HANDLE_INFORMATION) +
1091 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) -
1092 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)));
1093
1094 Shi->NumberOfHandles = hCount;
1095
1096 if (curSize > Size)
1097 {
1098 *ReqSize = curSize;
1099 return (STATUS_INFO_LENGTH_MISMATCH);
1100 }
1101
1102 DPRINT("SystemHandleInformation 3\n");
1103
1104 /* Now get Handles from all processs. */
1105 syspr = PsGetNextProcess(NULL);
1106 pr = syspr;
1107
1108 do
1109 {
1110 int Count = 0, HandleCount;
1111
1112 HandleCount = ObGetProcessHandleCount(pr);
1113
1114 for (Count = 0; HandleCount > 0 ; HandleCount--)
1115 {
1116 Shi->Handles[i].UniqueProcessId = (USHORT)(ULONG)pr->UniqueProcessId;
1117 Count++;
1118 i++;
1119 }
1120
1121 pr = PsGetNextProcess(pr);
1122
1123 if ((pr == syspr) || (pr == NULL)) break;
1124 }
1125 while ((pr != syspr) && (pr != NULL));
1126
1127 if(pr != NULL) ObDereferenceObject(pr);
1128
1129 DPRINT("SystemHandleInformation 4\n");
1130 return STATUS_SUCCESS;
1131
1132 }
1133 /*
1134 SSI_DEF(SystemHandleInformation)
1135 {
1136
1137 return STATUS_SUCCESS;
1138 }
1139 */
1140
1141 /* Class 17 - Information */
1142 QSI_DEF(SystemObjectInformation)
1143 {
1144 /* FIXME */
1145 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1146 return STATUS_NOT_IMPLEMENTED;
1147 }
1148
1149 /* Class 18 - Information */
1150 QSI_DEF(SystemPageFileInformation)
1151 {
1152 UNICODE_STRING FileName; /* FIXME */
1153 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
1154
1155 if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION))
1156 {
1157 * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION);
1158 return STATUS_INFO_LENGTH_MISMATCH;
1159 }
1160
1161 RtlInitUnicodeString(&FileName, NULL); /* FIXME */
1162
1163 /* FIXME */
1164 Spfi->NextEntryOffset = 0;
1165
1166 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
1167 Spfi->TotalInUse = MiUsedSwapPages;
1168 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
1169 Spfi->PageFileName = FileName;
1170 return STATUS_SUCCESS;
1171 }
1172
1173 /* Class 19 - Vdm Instemul Information */
1174 QSI_DEF(SystemVdmInstemulInformation)
1175 {
1176 /* FIXME */
1177 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1178 return STATUS_NOT_IMPLEMENTED;
1179 }
1180
1181 /* Class 20 - Vdm Bop Information */
1182 QSI_DEF(SystemVdmBopInformation)
1183 {
1184 /* FIXME */
1185 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1186 return STATUS_NOT_IMPLEMENTED;
1187 }
1188
1189 /* Class 21 - File Cache Information */
1190 QSI_DEF(SystemFileCacheInformation)
1191 {
1192 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
1193
1194 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1195 {
1196 *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
1197 return STATUS_INFO_LENGTH_MISMATCH;
1198 }
1199
1200 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION));
1201
1202 /* Return the Byte size not the page size. */
1203 Sci->CurrentSize =
1204 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
1205 Sci->PeakSize =
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 */
1214
1215 return STATUS_SUCCESS;
1216 }
1217
1218 SSI_DEF(SystemFileCacheInformation)
1219 {
1220 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1221 {
1222 return STATUS_INFO_LENGTH_MISMATCH;
1223 }
1224 /* FIXME */
1225 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1226 return STATUS_NOT_IMPLEMENTED;
1227 }
1228
1229 /* Class 22 - Pool Tag Information */
1230 QSI_DEF(SystemPoolTagInformation)
1231 {
1232 /* FIXME */
1233 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1234 return STATUS_NOT_IMPLEMENTED;
1235 }
1236
1237 /* Class 23 - Interrupt Information for all processors */
1238 QSI_DEF(SystemInterruptInformation)
1239 {
1240 PKPRCB Prcb;
1241 PKPCR Pcr;
1242 LONG i;
1243 ULONG ti;
1244 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1245
1246 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1247 {
1248 return STATUS_INFO_LENGTH_MISMATCH;
1249 }
1250
1251 ti = KeQueryTimeIncrement();
1252
1253 for (i = 0; i < KeNumberProcessors; i++)
1254 {
1255 Prcb = KiProcessorBlock[i];
1256 Pcr = (PKPCR)CONTAINING_RECORD(Prcb, KIPCR, PrcbData);
1257 #ifdef _M_ARM // This code should probably be done differently
1258 sii->ContextSwitches = Pcr->ContextSwitches;
1259 #else
1260 sii->ContextSwitches = ((PKIPCR)Pcr)->ContextSwitches;
1261 #endif
1262 sii->DpcCount = Prcb->DpcData[0].DpcCount;
1263 sii->DpcRate = Prcb->DpcRequestRate;
1264 sii->TimeIncrement = ti;
1265 sii->DpcBypassCount = 0;
1266 sii->ApcBypassCount = 0;
1267 sii++;
1268 }
1269
1270 return STATUS_SUCCESS;
1271 }
1272
1273 /* Class 24 - DPC Behaviour Information */
1274 QSI_DEF(SystemDpcBehaviourInformation)
1275 {
1276 /* FIXME */
1277 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1278 return STATUS_NOT_IMPLEMENTED;
1279 }
1280
1281 SSI_DEF(SystemDpcBehaviourInformation)
1282 {
1283 /* FIXME */
1284 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1285 return STATUS_NOT_IMPLEMENTED;
1286 }
1287
1288 /* Class 25 - Full Memory Information */
1289 QSI_DEF(SystemFullMemoryInformation)
1290 {
1291 PULONG Spi = (PULONG) Buffer;
1292
1293 PEPROCESS TheIdleProcess;
1294
1295 *ReqSize = sizeof(ULONG);
1296
1297 if (sizeof(ULONG) != Size)
1298 {
1299 return STATUS_INFO_LENGTH_MISMATCH;
1300 }
1301
1302 DPRINT("SystemFullMemoryInformation\n");
1303
1304 TheIdleProcess = PsIdleProcess;
1305
1306 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1307 TheIdleProcess->UniqueProcessId,
1308 TheIdleProcess->Pcb.KernelTime,
1309 MiFreeSwapPages,
1310 MiUsedSwapPages);
1311
1312 #ifndef NDEBUG
1313 MmPrintMemoryStatistic();
1314 #endif
1315
1316 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1317
1318 return STATUS_SUCCESS;
1319 }
1320
1321 /* Class 26 - Load Image */
1322 SSI_DEF(SystemLoadGdiDriverInformation)
1323 {
1324 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1325 UNICODE_STRING ImageName;
1326 PVOID ImageBase;
1327 PVOID SectionPointer;
1328 ULONG_PTR EntryPoint;
1329 NTSTATUS Status;
1330 ULONG DirSize;
1331 PIMAGE_NT_HEADERS NtHeader;
1332
1333 /* Validate size */
1334 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1335 {
1336 /* Incorrect buffer length, fail */
1337 return STATUS_INFO_LENGTH_MISMATCH;
1338 }
1339
1340 /* Only kernel mode can call this function */
1341 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1342
1343 /* Load the driver */
1344 ImageName = DriverInfo->DriverName;
1345 Status = MmLoadSystemImage(&ImageName,
1346 NULL,
1347 NULL,
1348 0,
1349 &SectionPointer,
1350 &ImageBase);
1351 if (!NT_SUCCESS(Status)) return Status;
1352
1353 /* Return the export pointer */
1354 DriverInfo->ExportSectionPointer =
1355 RtlImageDirectoryEntryToData(ImageBase,
1356 TRUE,
1357 IMAGE_DIRECTORY_ENTRY_EXPORT,
1358 &DirSize);
1359
1360 /* Get the entrypoint */
1361 NtHeader = RtlImageNtHeader(ImageBase);
1362 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1363 EntryPoint += (ULONG_PTR)ImageBase;
1364
1365 /* Save other data */
1366 DriverInfo->ImageAddress = ImageBase;
1367 DriverInfo->SectionPointer = SectionPointer;
1368 DriverInfo->EntryPoint = (PVOID)EntryPoint;
1369 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1370
1371 /* All is good */
1372 return STATUS_SUCCESS;
1373 }
1374
1375 /* Class 27 - Unload Image */
1376 SSI_DEF(SystemUnloadGdiDriverInformation)
1377 {
1378 PVOID SectionPointer = Buffer;
1379
1380 /* Validate size */
1381 if (Size != sizeof(PVOID))
1382 {
1383 /* Incorrect length, fail */
1384 return STATUS_INFO_LENGTH_MISMATCH;
1385 }
1386
1387 /* Only kernel mode can call this function */
1388 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1389
1390 /* Unload the image */
1391 MmUnloadSystemImage(SectionPointer);
1392 return STATUS_SUCCESS;
1393 }
1394
1395 /* Class 28 - Time Adjustment Information */
1396 QSI_DEF(SystemTimeAdjustmentInformation)
1397 {
1398 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo =
1399 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer;
1400
1401 /* Check if enough storage was provided */
1402 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size)
1403 {
1404 * ReqSize = sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION);
1405 return STATUS_INFO_LENGTH_MISMATCH;
1406 }
1407
1408 /* Give time values to our caller */
1409 TimeInfo->TimeIncrement = KeMaximumIncrement;
1410 TimeInfo->TimeAdjustment = KeTimeAdjustment;
1411 TimeInfo->Enable = TRUE;
1412
1413 return STATUS_SUCCESS;
1414 }
1415
1416 SSI_DEF(SystemTimeAdjustmentInformation)
1417 {
1418 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1419 /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1420 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
1421
1422 /* Check size of a buffer, it must match our expectations */
1423 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
1424 return STATUS_INFO_LENGTH_MISMATCH;
1425
1426 /* Check who is calling */
1427 if (PreviousMode != KernelMode)
1428 {
1429 /* Check access rights */
1430 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode))
1431 {
1432 return STATUS_PRIVILEGE_NOT_HELD;
1433 }
1434 }
1435
1436 /* TODO: Set time adjustment information */
1437 DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
1438 return STATUS_NOT_IMPLEMENTED;
1439 }
1440
1441 /* Class 29 - Summary Memory Information */
1442 QSI_DEF(SystemSummaryMemoryInformation)
1443 {
1444 /* FIXME */
1445 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1446 return STATUS_NOT_IMPLEMENTED;
1447 }
1448
1449 /* Class 30 - Next Event Id Information */
1450 QSI_DEF(SystemNextEventIdInformation)
1451 {
1452 /* FIXME */
1453 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1454 return STATUS_NOT_IMPLEMENTED;
1455 }
1456
1457 /* Class 31 - Event Ids Information */
1458 QSI_DEF(SystemEventIdsInformation)
1459 {
1460 /* FIXME */
1461 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1462 return STATUS_NOT_IMPLEMENTED;
1463 }
1464
1465 /* Class 32 - Crash Dump Information */
1466 QSI_DEF(SystemCrashDumpInformation)
1467 {
1468 /* FIXME */
1469 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1470 return STATUS_NOT_IMPLEMENTED;
1471 }
1472
1473 /* Class 33 - Exception Information */
1474 QSI_DEF(SystemExceptionInformation)
1475 {
1476 /* FIXME */
1477 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1478 return STATUS_NOT_IMPLEMENTED;
1479 }
1480
1481 /* Class 34 - Crash Dump State Information */
1482 QSI_DEF(SystemCrashDumpStateInformation)
1483 {
1484 /* FIXME */
1485 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1486 return STATUS_NOT_IMPLEMENTED;
1487 }
1488
1489 /* Class 35 - Kernel Debugger Information */
1490 QSI_DEF(SystemKernelDebuggerInformation)
1491 {
1492 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1493
1494 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1495 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1496 {
1497 return STATUS_INFO_LENGTH_MISMATCH;
1498 }
1499
1500 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1501 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1502
1503 return STATUS_SUCCESS;
1504 }
1505
1506 /* Class 36 - Context Switch Information */
1507 QSI_DEF(SystemContextSwitchInformation)
1508 {
1509 /* FIXME */
1510 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1511 return STATUS_NOT_IMPLEMENTED;
1512 }
1513
1514 /* Class 37 - Registry Quota Information */
1515 QSI_DEF(SystemRegistryQuotaInformation)
1516 {
1517 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1518
1519 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1520 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1521 {
1522 return STATUS_INFO_LENGTH_MISMATCH;
1523 }
1524
1525 DPRINT1("Faking max registry size of 32 MB\n");
1526 srqi->RegistryQuotaAllowed = 0x2000000;
1527 srqi->RegistryQuotaUsed = 0x200000;
1528 srqi->PagedPoolSize = 0x200000;
1529
1530 return STATUS_SUCCESS;
1531 }
1532
1533 SSI_DEF(SystemRegistryQuotaInformation)
1534 {
1535 /* FIXME */
1536 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1537 return STATUS_NOT_IMPLEMENTED;
1538 }
1539
1540 /* Class 38 - Load And Call Image */
1541 SSI_DEF(SystemExtendServiceTableInformation)
1542 {
1543 UNICODE_STRING ImageName;
1544 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1545 PLDR_DATA_TABLE_ENTRY ModuleObject;
1546 NTSTATUS Status;
1547 PIMAGE_NT_HEADERS NtHeader;
1548 DRIVER_OBJECT Win32k;
1549 PDRIVER_INITIALIZE DriverInit;
1550 PVOID ImageBase;
1551 ULONG_PTR EntryPoint;
1552
1553 /* Validate the size */
1554 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1555
1556 /* Check who is calling */
1557 if (PreviousMode != KernelMode)
1558 {
1559 /* Make sure we can load drivers */
1560 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1561 {
1562 /* FIXME: We can't, fail */
1563 //return STATUS_PRIVILEGE_NOT_HELD;
1564 }
1565 }
1566
1567 /* Probe and capture the driver name */
1568 ProbeAndCaptureUnicodeString(&ImageName, PreviousMode, Buffer);
1569
1570 /* Load the image */
1571 Status = MmLoadSystemImage(&ImageName,
1572 NULL,
1573 NULL,
1574 0,
1575 (PVOID)&ModuleObject,
1576 &ImageBase);
1577
1578 /* Release String */
1579 ReleaseCapturedUnicodeString(&ImageName, PreviousMode);
1580
1581 if (!NT_SUCCESS(Status)) return Status;
1582
1583 /* Get the headers */
1584 NtHeader = RtlImageNtHeader(ImageBase);
1585 if (!NtHeader)
1586 {
1587 /* Fail */
1588 MmUnloadSystemImage(ModuleObject);
1589 return STATUS_INVALID_IMAGE_FORMAT;
1590 }
1591
1592 /* Get the entrypoint */
1593 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1594 EntryPoint += (ULONG_PTR)ImageBase;
1595 DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1596
1597 /* Create a dummy device */
1598 RtlZeroMemory(&Win32k, sizeof(Win32k));
1599 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1600 Win32k.DriverStart = ImageBase;
1601
1602 /* Call it */
1603 Status = (DriverInit)(&Win32k, NULL);
1604 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1605
1606 /* Unload if we failed */
1607 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
1608 return Status;
1609 }
1610
1611 /* Class 39 - Priority Separation */
1612 SSI_DEF(SystemPrioritySeperation)
1613 {
1614 /* FIXME */
1615 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1616 return STATUS_NOT_IMPLEMENTED;
1617 }
1618
1619 /* Class 40 - Plug Play Bus Information */
1620 QSI_DEF(SystemPlugPlayBusInformation)
1621 {
1622 /* FIXME */
1623 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1624 return STATUS_NOT_IMPLEMENTED;
1625 }
1626
1627 /* Class 41 - Dock Information */
1628 QSI_DEF(SystemDockInformation)
1629 {
1630 /* FIXME */
1631 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1632 return STATUS_NOT_IMPLEMENTED;
1633 }
1634
1635 /* Class 42 - Power Information */
1636 QSI_DEF(SystemPowerInformation)
1637 {
1638 /* FIXME */
1639 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1640 return STATUS_NOT_IMPLEMENTED;
1641 }
1642
1643 /* Class 43 - Processor Speed Information */
1644 QSI_DEF(SystemProcessorSpeedInformation)
1645 {
1646 /* FIXME */
1647 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1648 return STATUS_NOT_IMPLEMENTED;
1649 }
1650
1651 /* Class 44 - Current Time Zone Information */
1652 QSI_DEF(SystemCurrentTimeZoneInformation)
1653 {
1654 *ReqSize = sizeof(TIME_ZONE_INFORMATION);
1655
1656 if (sizeof(TIME_ZONE_INFORMATION) != Size)
1657 {
1658 return STATUS_INFO_LENGTH_MISMATCH;
1659 }
1660
1661 /* Copy the time zone information struct */
1662 memcpy(Buffer,
1663 &ExpTimeZoneInfo,
1664 sizeof(TIME_ZONE_INFORMATION));
1665
1666 return STATUS_SUCCESS;
1667 }
1668
1669
1670 SSI_DEF(SystemCurrentTimeZoneInformation)
1671 {
1672 /* Check user buffer's size */
1673 if (Size < sizeof(TIME_ZONE_INFORMATION))
1674 {
1675 return STATUS_INFO_LENGTH_MISMATCH;
1676 }
1677
1678 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1679 }
1680
1681
1682 /* Class 45 - Lookaside Information */
1683 QSI_DEF(SystemLookasideInformation)
1684 {
1685 /* FIXME */
1686 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1687 return STATUS_NOT_IMPLEMENTED;
1688 }
1689
1690
1691 /* Class 46 - Set time slip event */
1692 SSI_DEF(SystemSetTimeSlipEvent)
1693 {
1694 /* FIXME */
1695 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1696 return STATUS_NOT_IMPLEMENTED;
1697 }
1698
1699
1700 /* Class 47 - Create a new session (TSE) */
1701 SSI_DEF(SystemCreateSession)
1702 {
1703 /* FIXME */
1704 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1705 return STATUS_NOT_IMPLEMENTED;
1706 }
1707
1708
1709 /* Class 48 - Delete an existing session (TSE) */
1710 SSI_DEF(SystemDeleteSession)
1711 {
1712 /* FIXME */
1713 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1714 return STATUS_NOT_IMPLEMENTED;
1715 }
1716
1717
1718 /* Class 49 - UNKNOWN */
1719 QSI_DEF(SystemInvalidInfoClass4)
1720 {
1721 /* FIXME */
1722 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1723 return STATUS_NOT_IMPLEMENTED;
1724 }
1725
1726
1727 /* Class 50 - System range start address */
1728 QSI_DEF(SystemRangeStartInformation)
1729 {
1730 /* FIXME */
1731 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1732 return STATUS_NOT_IMPLEMENTED;
1733 }
1734
1735
1736 /* Class 51 - Driver verifier information */
1737 QSI_DEF(SystemVerifierInformation)
1738 {
1739 /* FIXME */
1740 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1741 return STATUS_NOT_IMPLEMENTED;
1742 }
1743
1744
1745 SSI_DEF(SystemVerifierInformation)
1746 {
1747 /* FIXME */
1748 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1749 return STATUS_NOT_IMPLEMENTED;
1750 }
1751
1752
1753 /* Class 52 - Add a driver verifier */
1754 SSI_DEF(SystemAddVerifier)
1755 {
1756 /* FIXME */
1757 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1758 return STATUS_NOT_IMPLEMENTED;
1759 }
1760
1761
1762 /* Class 53 - A session's processes */
1763 QSI_DEF(SystemSessionProcessesInformation)
1764 {
1765 /* FIXME */
1766 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1767 return STATUS_NOT_IMPLEMENTED;
1768 }
1769
1770
1771 /* Query/Set Calls Table */
1772 typedef
1773 struct _QSSI_CALLS
1774 {
1775 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1776 NTSTATUS (* Set) (PVOID,ULONG);
1777
1778 } QSSI_CALLS;
1779
1780 // QS Query & Set
1781 // QX Query
1782 // XS Set
1783 // XX unknown behaviour
1784 //
1785 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1786 #define SI_QX(n) {QSI_USE(n),NULL}
1787 #define SI_XS(n) {NULL,SSI_USE(n)}
1788 #define SI_XX(n) {NULL,NULL}
1789
1790 static
1791 QSSI_CALLS
1792 CallQS [] =
1793 {
1794 SI_QX(SystemBasicInformation),
1795 SI_QX(SystemProcessorInformation),
1796 SI_QX(SystemPerformanceInformation),
1797 SI_QX(SystemTimeOfDayInformation),
1798 SI_QX(SystemPathInformation), /* should be SI_XX */
1799 SI_QX(SystemProcessInformation),
1800 SI_QX(SystemCallCountInformation),
1801 SI_QX(SystemDeviceInformation),
1802 SI_QX(SystemProcessorPerformanceInformation),
1803 SI_QS(SystemFlagsInformation),
1804 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1805 SI_QX(SystemModuleInformation),
1806 SI_QX(SystemLocksInformation),
1807 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1808 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1809 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1810 SI_QX(SystemHandleInformation),
1811 SI_QX(SystemObjectInformation),
1812 SI_QX(SystemPageFileInformation),
1813 SI_QX(SystemVdmInstemulInformation),
1814 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1815 SI_QS(SystemFileCacheInformation),
1816 SI_QX(SystemPoolTagInformation),
1817 SI_QX(SystemInterruptInformation),
1818 SI_QS(SystemDpcBehaviourInformation),
1819 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1820 SI_XS(SystemLoadGdiDriverInformation),
1821 SI_XS(SystemUnloadGdiDriverInformation),
1822 SI_QS(SystemTimeAdjustmentInformation),
1823 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1824 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1825 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1826 SI_QX(SystemCrashDumpInformation),
1827 SI_QX(SystemExceptionInformation),
1828 SI_QX(SystemCrashDumpStateInformation),
1829 SI_QX(SystemKernelDebuggerInformation),
1830 SI_QX(SystemContextSwitchInformation),
1831 SI_QS(SystemRegistryQuotaInformation),
1832 SI_XS(SystemExtendServiceTableInformation),
1833 SI_XS(SystemPrioritySeperation),
1834 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1835 SI_QX(SystemDockInformation), /* it should be SI_XX */
1836 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1837 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1838 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1839 SI_QX(SystemLookasideInformation),
1840 SI_XS(SystemSetTimeSlipEvent),
1841 SI_XS(SystemCreateSession),
1842 SI_XS(SystemDeleteSession),
1843 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1844 SI_QX(SystemRangeStartInformation),
1845 SI_QS(SystemVerifierInformation),
1846 SI_XS(SystemAddVerifier),
1847 SI_QX(SystemSessionProcessesInformation)
1848 };
1849
1850 C_ASSERT(SystemBasicInformation == 0);
1851 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1852 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1853
1854 /*
1855 * @implemented
1856 */
1857 NTSTATUS NTAPI
1858 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1859 OUT PVOID SystemInformation,
1860 IN ULONG Length,
1861 OUT PULONG UnsafeResultLength)
1862 {
1863 KPROCESSOR_MODE PreviousMode;
1864 ULONG ResultLength;
1865 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1866
1867 PAGED_CODE();
1868
1869 PreviousMode = ExGetPreviousMode();
1870
1871 _SEH2_TRY
1872 {
1873 if (PreviousMode != KernelMode)
1874 {
1875 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1876 ProbeForWrite(SystemInformation, Length, 1);
1877 if (UnsafeResultLength != NULL)
1878 ProbeForWriteUlong(UnsafeResultLength);
1879 }
1880
1881 /*
1882 * Check the request is valid.
1883 */
1884 if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
1885 {
1886 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
1887 }
1888
1889 if (NULL != CallQS [SystemInformationClass].Query)
1890 {
1891 /*
1892 * Hand the request to a subhandler.
1893 */
1894 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1895 Length,
1896 &ResultLength);
1897 if (UnsafeResultLength != NULL)
1898 {
1899 if (PreviousMode != KernelMode)
1900 {
1901 *UnsafeResultLength = ResultLength;
1902 }
1903 else
1904 {
1905 *UnsafeResultLength = ResultLength;
1906 }
1907 }
1908 }
1909 }
1910 _SEH2_EXCEPT(ExSystemExceptionFilter())
1911 {
1912 FStatus = _SEH2_GetExceptionCode();
1913 }
1914 _SEH2_END;
1915
1916 return FStatus;
1917 }
1918
1919
1920 NTSTATUS
1921 NTAPI
1922 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1923 IN PVOID SystemInformation,
1924 IN ULONG SystemInformationLength)
1925 {
1926 PAGED_CODE();
1927
1928 /*
1929 * If called from user mode, check
1930 * possible unsafe arguments.
1931 */
1932 #if 0
1933 if (KernelMode != KeGetPreviousMode())
1934 {
1935 // Check arguments
1936 //ProbeForWrite(
1937 // SystemInformation,
1938 // Length
1939 // );
1940 //ProbeForWrite(
1941 // ResultLength,
1942 // sizeof (ULONG)
1943 // );
1944 }
1945 #endif
1946 /*
1947 * Check the request is valid.
1948 */
1949 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
1950 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
1951 {
1952 if (NULL != CallQS [SystemInformationClass].Set)
1953 {
1954 /*
1955 * Hand the request to a subhandler.
1956 */
1957 return CallQS [SystemInformationClass].Set(SystemInformation,
1958 SystemInformationLength);
1959 }
1960 }
1961
1962 return STATUS_INVALID_INFO_CLASS;
1963 }
1964
1965 NTSTATUS
1966 NTAPI
1967 NtFlushInstructionCache(IN HANDLE ProcessHandle,
1968 IN PVOID BaseAddress,
1969 IN ULONG NumberOfBytesToFlush)
1970 {
1971 PAGED_CODE();
1972
1973 #if defined(_M_IX86)
1974 __wbinvd();
1975 #elif defined(_M_PPC)
1976 __asm__ __volatile__("tlbsync");
1977 #elif defined(_M_MIPS)
1978 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1979 for (;;);
1980 #elif defined(_M_ARM)
1981 __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
1982 #else
1983 #error Unknown architecture
1984 #endif
1985 return STATUS_SUCCESS;
1986 }
1987
1988 ULONG
1989 NTAPI
1990 NtGetCurrentProcessorNumber(VOID)
1991 {
1992 /* Just return the CPU */
1993 return KeGetCurrentProcessorNumber();
1994 }
1995
1996 /*
1997 * @implemented
1998 */
1999 #undef ExGetPreviousMode
2000 KPROCESSOR_MODE
2001 NTAPI
2002 ExGetPreviousMode (VOID)
2003 {
2004 return KeGetPreviousMode();
2005 }