sync with trunk (r49238)
[reactos.git] / 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
498 *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION);
499
500 /* Check user buffer's size */
501 if (Size < sizeof(SYSTEM_PROCESSOR_INFORMATION))
502 {
503 return STATUS_INFO_LENGTH_MISMATCH;
504 }
505 Spi->ProcessorArchitecture = KeProcessorArchitecture;
506 Spi->ProcessorLevel = KeProcessorLevel;
507 Spi->ProcessorRevision = KeProcessorRevision;
508 Spi->Reserved = 0;
509 Spi->ProcessorFeatureBits = KeFeatureBits;
510
511 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
512 Spi->ProcessorLevel, Spi->ProcessorRevision);
513
514 return STATUS_SUCCESS;
515 }
516
517 /* Class 2 - Performance Information */
518 QSI_DEF(SystemPerformanceInformation)
519 {
520 ULONG IdleUser, IdleKernel;
521 PSYSTEM_PERFORMANCE_INFORMATION Spi
522 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
523
524 PEPROCESS TheIdleProcess;
525
526 *ReqSize = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
527
528 /* Check user buffer's size */
529 if (Size < sizeof(SYSTEM_PERFORMANCE_INFORMATION))
530 {
531 return STATUS_INFO_LENGTH_MISMATCH;
532 }
533
534 TheIdleProcess = PsIdleProcess;
535
536 IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
537 Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
538 Spi->IoReadTransferCount = IoReadTransferCount;
539 Spi->IoWriteTransferCount = IoWriteTransferCount;
540 Spi->IoOtherTransferCount = IoOtherTransferCount;
541 Spi->IoReadOperationCount = IoReadOperationCount;
542 Spi->IoWriteOperationCount = IoWriteOperationCount;
543 Spi->IoOtherOperationCount = IoOtherOperationCount;
544
545 Spi->AvailablePages = MmAvailablePages;
546 /*
547 * Add up all the used "Committed" memory + pagefile.
548 * Not sure this is right. 8^\
549 */
550 Spi->CommittedPages = MiMemoryConsumers[MC_SYSTEM].PagesUsed +
551 MiMemoryConsumers[MC_CACHE].PagesUsed +
552 MiMemoryConsumers[MC_USER].PagesUsed +
553 MiUsedSwapPages;
554 /*
555 * Add up the full system total + pagefile.
556 * All this make Taskmgr happy but not sure it is the right numbers.
557 * This too, fixes some of GlobalMemoryStatusEx numbers.
558 */
559 Spi->CommitLimit = MmNumberOfPhysicalPages + MiFreeSwapPages + MiUsedSwapPages;
560
561 Spi->PeakCommitment = 0; /* FIXME */
562 Spi->PageFaultCount = 0; /* FIXME */
563 Spi->CopyOnWriteCount = 0; /* FIXME */
564 Spi->TransitionCount = 0; /* FIXME */
565 Spi->CacheTransitionCount = 0; /* FIXME */
566 Spi->DemandZeroCount = 0; /* FIXME */
567 Spi->PageReadCount = 0; /* FIXME */
568 Spi->PageReadIoCount = 0; /* FIXME */
569 Spi->CacheReadCount = 0; /* FIXME */
570 Spi->CacheIoCount = 0; /* FIXME */
571 Spi->DirtyPagesWriteCount = 0; /* FIXME */
572 Spi->DirtyWriteIoCount = 0; /* FIXME */
573 Spi->MappedPagesWriteCount = 0; /* FIXME */
574 Spi->MappedWriteIoCount = 0; /* FIXME */
575
576 Spi->PagedPoolPages = 0; /* FIXME */
577 Spi->PagedPoolAllocs = 0; /* FIXME */
578 Spi->PagedPoolFrees = 0; /* FIXME */
579 Spi->NonPagedPoolPages = 0; /* FIXME */
580 Spi->NonPagedPoolAllocs = 0; /* FIXME */
581 Spi->NonPagedPoolFrees = 0; /* FIXME */
582
583 Spi->FreeSystemPtes = 0; /* FIXME */
584
585 Spi->ResidentSystemCodePage = 0; /* FIXME */
586
587 Spi->TotalSystemDriverPages = 0; /* FIXME */
588 Spi->TotalSystemCodePages = 0; /* FIXME */
589 Spi->NonPagedPoolLookasideHits = 0; /* FIXME */
590 Spi->PagedPoolLookasideHits = 0; /* FIXME */
591 Spi->Spare3Count = 0; /* FIXME */
592
593 Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
594 Spi->ResidentPagedPoolPage = 0; /* FIXME */
595
596 Spi->ResidentSystemDriverPage = 0; /* FIXME */
597 Spi->CcFastReadNoWait = 0; /* FIXME */
598 Spi->CcFastReadWait = 0; /* FIXME */
599 Spi->CcFastReadResourceMiss = 0; /* FIXME */
600 Spi->CcFastReadNotPossible = 0; /* FIXME */
601
602 Spi->CcFastMdlReadNoWait = 0; /* FIXME */
603 Spi->CcFastMdlReadWait = 0; /* FIXME */
604 Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
605 Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
606
607 Spi->CcMapDataNoWait = 0; /* FIXME */
608 Spi->CcMapDataWait = 0; /* FIXME */
609 Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
610 Spi->CcMapDataWaitMiss = 0; /* FIXME */
611
612 Spi->CcPinMappedDataCount = 0; /* FIXME */
613 Spi->CcPinReadNoWait = 0; /* FIXME */
614 Spi->CcPinReadWait = 0; /* FIXME */
615 Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
616 Spi->CcPinReadWaitMiss = 0; /* FIXME */
617 Spi->CcCopyReadNoWait = 0; /* FIXME */
618 Spi->CcCopyReadWait = 0; /* FIXME */
619 Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
620 Spi->CcCopyReadWaitMiss = 0; /* FIXME */
621
622 Spi->CcMdlReadNoWait = 0; /* FIXME */
623 Spi->CcMdlReadWait = 0; /* FIXME */
624 Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
625 Spi->CcMdlReadWaitMiss = 0; /* FIXME */
626 Spi->CcReadAheadIos = 0; /* FIXME */
627 Spi->CcLazyWriteIos = 0; /* FIXME */
628 Spi->CcLazyWritePages = 0; /* FIXME */
629 Spi->CcDataFlushes = 0; /* FIXME */
630 Spi->CcDataPages = 0; /* FIXME */
631 Spi->ContextSwitches = 0; /* FIXME */
632 Spi->FirstLevelTbFills = 0; /* FIXME */
633 Spi->SecondLevelTbFills = 0; /* FIXME */
634 Spi->SystemCalls = 0; /* FIXME */
635
636 return STATUS_SUCCESS;
637 }
638
639 /* Class 3 - Time Of Day Information */
640 QSI_DEF(SystemTimeOfDayInformation)
641 {
642 SYSTEM_TIMEOFDAY_INFORMATION Sti;
643 LARGE_INTEGER CurrentTime;
644
645 /* Set amount of written information to 0 */
646 *ReqSize = 0;
647
648 /* Check user buffer's size */
649 if (Size > sizeof(SYSTEM_TIMEOFDAY_INFORMATION))
650 {
651 return STATUS_INFO_LENGTH_MISMATCH;
652 }
653
654 /* Get current time */
655 KeQuerySystemTime(&CurrentTime);
656
657 /* Zero local buffer */
658 RtlZeroMemory(&Sti, sizeof(SYSTEM_TIMEOFDAY_INFORMATION));
659
660 /* Fill local time structure */
661 Sti.BootTime= KeBootTime;
662 Sti.CurrentTime = CurrentTime;
663 Sti.TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
664 Sti.TimeZoneId = ExpTimeZoneId;
665 Sti.Reserved = 0;
666
667 /* Copy as much as requested by caller */
668 RtlCopyMemory(Buffer, &Sti, Size);
669
670 /* Set amount of information we copied */
671 *ReqSize = Size;
672
673 return STATUS_SUCCESS;
674 }
675
676 /* Class 4 - Path Information */
677 QSI_DEF(SystemPathInformation)
678 {
679 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
680 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
681
682 return STATUS_BREAKPOINT;
683 }
684
685 /* Class 5 - Process Information */
686 QSI_DEF(SystemProcessInformation)
687 {
688 PSYSTEM_PROCESS_INFORMATION SpiCurrent;
689 PSYSTEM_THREAD_INFORMATION ThreadInfo;
690 PEPROCESS Process = NULL, SystemProcess;
691 PETHREAD CurrentThread;
692 ANSI_STRING ImageName;
693 ULONG CurrentSize;
694 USHORT ImageNameMaximumLength; // image name len in bytes
695 USHORT ImageNameLength;
696 PLIST_ENTRY CurrentEntry;
697 ULONG TotalSize = 0, ThreadsCount;
698 ULONG TotalUser, TotalKernel;
699 PUCHAR Current;
700 NTSTATUS Status = STATUS_SUCCESS;
701 PUNICODE_STRING ProcessImageName;
702 PWCHAR szSrc;
703 BOOLEAN Overflow = FALSE;
704
705 _SEH2_TRY
706 {
707 /* scan the process list */
708
709 PSYSTEM_PROCESS_INFORMATION Spi
710 = (PSYSTEM_PROCESS_INFORMATION) Buffer;
711
712 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
713
714 /* Check for overflow */
715 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
716 Overflow = TRUE;
717
718 /* Zero user's buffer */
719 if (!Overflow) RtlZeroMemory(Spi, Size);
720
721 SystemProcess = PsIdleProcess;
722 Process = SystemProcess;
723 Current = (PUCHAR) Spi;
724
725 do
726 {
727 SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
728
729 ThreadsCount = 0;
730 CurrentEntry = Process->ThreadListHead.Flink;
731 while (CurrentEntry != &Process->ThreadListHead)
732 {
733 ThreadsCount++;
734 CurrentEntry = CurrentEntry->Flink;
735 }
736
737 // size of the structure for every process
738 CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
739 ImageNameLength = 0;
740 Status = SeLocateProcessImageName(Process, &ProcessImageName);
741 szSrc = NULL;
742 if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0))
743 {
744 szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length);
745 /* Loop the file name*/
746 while (szSrc > ProcessImageName->Buffer)
747 {
748 /* Make sure this isn't a backslash */
749 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
750 {
751 szSrc++;
752 break;
753 }
754 else
755 {
756 ImageNameLength += sizeof(WCHAR);
757 }
758 }
759 }
760 if (!ImageNameLength && Process != PsIdleProcess && Process->ImageFileName)
761 {
762 ImageNameLength = strlen(Process->ImageFileName) * sizeof(WCHAR);
763 }
764
765 /* Round up the image name length as NT does */
766 if (ImageNameLength > 0)
767 ImageNameMaximumLength = ROUND_UP(ImageNameLength + sizeof(WCHAR), 8);
768 else
769 ImageNameMaximumLength = 0;
770
771 TotalSize += CurrentSize + ImageNameMaximumLength;
772
773 /* Check for overflow */
774 if (TotalSize > Size)
775 Overflow = TRUE;
776
777 /* Fill system information */
778 if (!Overflow)
779 {
780 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginnnig of the next structure
781 SpiCurrent->NumberOfThreads = ThreadsCount;
782 SpiCurrent->CreateTime = Process->CreateTime;
783 SpiCurrent->ImageName.Length = ImageNameLength;
784 SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength;
785 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
786
787 /* Copy name to the end of the struct */
788 if(Process != PsIdleProcess)
789 {
790 if (szSrc)
791 {
792 RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
793
794 /* Release the memory allocated by SeLocateProcessImageName */
795 ExFreePool(ProcessImageName);
796 }
797 else if (Process->ImageFileName)
798 {
799 RtlInitAnsiString(&ImageName, Process->ImageFileName);
800 RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
801 }
802 }
803 else
804 {
805 RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
806 }
807
808 SpiCurrent->BasePriority = Process->Pcb.BasePriority;
809 SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
810 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId;
811 SpiCurrent->HandleCount = ObGetProcessHandleCount(Process);
812 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
813 SpiCurrent->VirtualSize = Process->VirtualSize;
814 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
815 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
816 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
817 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
818 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[0];
819 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
820 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
821 SpiCurrent->PagefileUsage = Process->QuotaUsage[2];
822 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[2];
823 SpiCurrent->PrivatePageCount = Process->CommitCharge;
824 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
825
826 CurrentEntry = Process->ThreadListHead.Flink;
827 while (CurrentEntry != &Process->ThreadListHead)
828 {
829 CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
830 ThreadListEntry);
831
832 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
833 ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
834 ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart;
835 ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
836 ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress;
837 ThreadInfo->ClientId = CurrentThread->Cid;
838 ThreadInfo->Priority = CurrentThread->Tcb.Priority;
839 ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
840 ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches;
841 ThreadInfo->ThreadState = CurrentThread->Tcb.State;
842 ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
843
844 ThreadInfo++;
845 CurrentEntry = CurrentEntry->Flink;
846 }
847
848 /* Query total user/kernel times of a process */
849 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser);
850 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
851 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
852 }
853
854 /* Handle idle process entry */
855 if (Process == PsIdleProcess) Process = NULL;
856
857 Process = PsGetNextProcess(Process);
858 ThreadsCount = 0;
859 if ((Process == SystemProcess) || (Process == NULL))
860 {
861 if (!Overflow)
862 SpiCurrent->NextEntryOffset = 0;
863 break;
864 }
865 else
866 Current += CurrentSize + ImageNameMaximumLength;
867 } while ((Process != SystemProcess) && (Process != NULL));
868
869 if(Process != NULL)
870 ObDereferenceObject(Process);
871 Status = STATUS_SUCCESS;
872 }
873 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
874 {
875 if(Process != NULL)
876 ObDereferenceObject(Process);
877 Status = _SEH2_GetExceptionCode();
878 }
879 _SEH2_END
880
881 if (Overflow)
882 Status = STATUS_INFO_LENGTH_MISMATCH;
883
884 *ReqSize = TotalSize;
885 return Status;
886 }
887
888 /* Class 6 - Call Count Information */
889 QSI_DEF(SystemCallCountInformation)
890 {
891 /* FIXME */
892 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
893 return STATUS_NOT_IMPLEMENTED;
894 }
895
896 /* Class 7 - Device Information */
897 QSI_DEF(SystemDeviceInformation)
898 {
899 PSYSTEM_DEVICE_INFORMATION Sdi
900 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
901 PCONFIGURATION_INFORMATION ConfigInfo;
902
903 *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION);
904
905 /* Check user buffer's size */
906 if (Size < sizeof(SYSTEM_DEVICE_INFORMATION))
907 {
908 return STATUS_INFO_LENGTH_MISMATCH;
909 }
910
911 ConfigInfo = IoGetConfigurationInformation();
912
913 Sdi->NumberOfDisks = ConfigInfo->DiskCount;
914 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
915 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
916 Sdi->NumberOfTapes = ConfigInfo->TapeCount;
917 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
918 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
919
920 return STATUS_SUCCESS;
921 }
922
923 /* Class 8 - Processor Performance Information */
924 QSI_DEF(SystemProcessorPerformanceInformation)
925 {
926 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
927 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
928
929 LONG i;
930 ULONG TotalTime;
931 PKPRCB Prcb;
932
933 *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
934
935 /* Check user buffer's size */
936 if (Size < *ReqSize)
937 {
938 return STATUS_INFO_LENGTH_MISMATCH;
939 }
940
941 for (i = 0; i < KeNumberProcessors; i++)
942 {
943 /* Get the PRCB on this processor */
944 Prcb = KiProcessorBlock[i];
945
946 /* Calculate total user and kernel times */
947 TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime;
948 Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement);
949 Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement);
950 Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement);
951 Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement);
952 Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement);
953 Spi->InterruptCount = Prcb->InterruptCount;
954 Spi++;
955 }
956
957 return STATUS_SUCCESS;
958 }
959
960 /* Class 9 - Flags Information */
961 QSI_DEF(SystemFlagsInformation)
962 {
963 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
964 {
965 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
966 return (STATUS_INFO_LENGTH_MISMATCH);
967 }
968 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
969 return STATUS_SUCCESS;
970 }
971
972 SSI_DEF(SystemFlagsInformation)
973 {
974 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
975 {
976 return STATUS_INFO_LENGTH_MISMATCH;
977 }
978 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
979 return STATUS_SUCCESS;
980 }
981
982 /* Class 10 - Call Time Information */
983 QSI_DEF(SystemCallTimeInformation)
984 {
985 /* FIXME */
986 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
987 return STATUS_NOT_IMPLEMENTED;
988 }
989
990 /* Class 11 - Module Information */
991 QSI_DEF(SystemModuleInformation)
992 {
993 NTSTATUS Status;
994
995 /* Acquire system module list lock */
996 KeEnterCriticalRegion();
997 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
998
999 /* Call the generic handler with the system module list */
1000 Status = ExpQueryModuleInformation(&PsLoadedModuleList,
1001 &MmLoadedUserImageList,
1002 (PRTL_PROCESS_MODULES)Buffer,
1003 Size,
1004 ReqSize);
1005
1006 /* Release list lock and return status */
1007 ExReleaseResourceLite(&PsLoadedModuleResource);
1008 KeLeaveCriticalRegion();
1009 return Status;
1010 }
1011
1012 /* Class 12 - Locks Information */
1013 QSI_DEF(SystemLocksInformation)
1014 {
1015 /* FIXME */
1016 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
1017 return STATUS_NOT_IMPLEMENTED;
1018 }
1019
1020 /* Class 13 - Stack Trace Information */
1021 QSI_DEF(SystemStackTraceInformation)
1022 {
1023 /* FIXME */
1024 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
1025 return STATUS_NOT_IMPLEMENTED;
1026 }
1027
1028 /* Class 14 - Paged Pool Information */
1029 QSI_DEF(SystemPagedPoolInformation)
1030 {
1031 /* FIXME */
1032 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
1033 return STATUS_NOT_IMPLEMENTED;
1034 }
1035
1036 /* Class 15 - Non Paged Pool Information */
1037 QSI_DEF(SystemNonPagedPoolInformation)
1038 {
1039 /* FIXME */
1040 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
1041 return STATUS_NOT_IMPLEMENTED;
1042 }
1043
1044
1045 /* Class 16 - Handle Information */
1046 QSI_DEF(SystemHandleInformation)
1047 {
1048 PEPROCESS pr, syspr;
1049 ULONG curSize, i = 0;
1050 ULONG hCount = 0;
1051
1052 PSYSTEM_HANDLE_INFORMATION Shi =
1053 (PSYSTEM_HANDLE_INFORMATION) Buffer;
1054
1055 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1056
1057 if (Size < sizeof(SYSTEM_HANDLE_INFORMATION))
1058 {
1059 *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
1060 return STATUS_INFO_LENGTH_MISMATCH;
1061 }
1062
1063 DPRINT("SystemHandleInformation 1\n");
1064
1065 /* First Calc Size from Count. */
1066 syspr = PsGetNextProcess(NULL);
1067 pr = syspr;
1068
1069 do
1070 {
1071 hCount = hCount + ObGetProcessHandleCount(pr);
1072 pr = PsGetNextProcess(pr);
1073
1074 if ((pr == syspr) || (pr == NULL)) break;
1075 }
1076 while ((pr != syspr) && (pr != NULL));
1077
1078 if(pr != NULL)
1079 {
1080 ObDereferenceObject(pr);
1081 }
1082
1083 DPRINT("SystemHandleInformation 2\n");
1084
1085 curSize = sizeof(SYSTEM_HANDLE_INFORMATION) +
1086 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) -
1087 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)));
1088
1089 Shi->NumberOfHandles = hCount;
1090
1091 if (curSize > Size)
1092 {
1093 *ReqSize = curSize;
1094 return (STATUS_INFO_LENGTH_MISMATCH);
1095 }
1096
1097 DPRINT("SystemHandleInformation 3\n");
1098
1099 /* Now get Handles from all processs. */
1100 syspr = PsGetNextProcess(NULL);
1101 pr = syspr;
1102
1103 do
1104 {
1105 int Count = 0, HandleCount;
1106
1107 HandleCount = ObGetProcessHandleCount(pr);
1108
1109 for (Count = 0; HandleCount > 0 ; HandleCount--)
1110 {
1111 Shi->Handles[i].UniqueProcessId = (USHORT)(ULONG_PTR)pr->UniqueProcessId;
1112 Count++;
1113 i++;
1114 }
1115
1116 pr = PsGetNextProcess(pr);
1117
1118 if ((pr == syspr) || (pr == NULL)) break;
1119 }
1120 while ((pr != syspr) && (pr != NULL));
1121
1122 if(pr != NULL) ObDereferenceObject(pr);
1123
1124 DPRINT("SystemHandleInformation 4\n");
1125 return STATUS_SUCCESS;
1126
1127 }
1128 /*
1129 SSI_DEF(SystemHandleInformation)
1130 {
1131
1132 return STATUS_SUCCESS;
1133 }
1134 */
1135
1136 /* Class 17 - Information */
1137 QSI_DEF(SystemObjectInformation)
1138 {
1139 /* FIXME */
1140 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1141 return STATUS_NOT_IMPLEMENTED;
1142 }
1143
1144 /* Class 18 - Information */
1145 QSI_DEF(SystemPageFileInformation)
1146 {
1147 UNICODE_STRING FileName; /* FIXME */
1148 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
1149
1150 if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION))
1151 {
1152 * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION);
1153 return STATUS_INFO_LENGTH_MISMATCH;
1154 }
1155
1156 RtlInitUnicodeString(&FileName, NULL); /* FIXME */
1157
1158 /* FIXME */
1159 Spfi->NextEntryOffset = 0;
1160
1161 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
1162 Spfi->TotalInUse = MiUsedSwapPages;
1163 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
1164 Spfi->PageFileName = FileName;
1165 return STATUS_SUCCESS;
1166 }
1167
1168 /* Class 19 - Vdm Instemul Information */
1169 QSI_DEF(SystemVdmInstemulInformation)
1170 {
1171 /* FIXME */
1172 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1173 return STATUS_NOT_IMPLEMENTED;
1174 }
1175
1176 /* Class 20 - Vdm Bop Information */
1177 QSI_DEF(SystemVdmBopInformation)
1178 {
1179 /* FIXME */
1180 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1181 return STATUS_NOT_IMPLEMENTED;
1182 }
1183
1184 /* Class 21 - File Cache Information */
1185 QSI_DEF(SystemFileCacheInformation)
1186 {
1187 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
1188
1189 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1190 {
1191 *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
1192 return STATUS_INFO_LENGTH_MISMATCH;
1193 }
1194
1195 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION));
1196
1197 /* Return the Byte size not the page size. */
1198 Sci->CurrentSize =
1199 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
1200 Sci->PeakSize =
1201 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE; /* FIXME */
1202 /* Taskmgr multiplies this one by page size right away */
1203 Sci->CurrentSizeIncludingTransitionInPages =
1204 MiMemoryConsumers[MC_CACHE].PagesUsed; /* FIXME: Should be */
1205 /* system working set and standby pages. */
1206 Sci->PageFaultCount = 0; /* FIXME */
1207 Sci->MinimumWorkingSet = 0; /* FIXME */
1208 Sci->MaximumWorkingSet = 0; /* FIXME */
1209
1210 return STATUS_SUCCESS;
1211 }
1212
1213 SSI_DEF(SystemFileCacheInformation)
1214 {
1215 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1216 {
1217 return STATUS_INFO_LENGTH_MISMATCH;
1218 }
1219 /* FIXME */
1220 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1221 return STATUS_NOT_IMPLEMENTED;
1222 }
1223
1224 /* Class 22 - Pool Tag Information */
1225 QSI_DEF(SystemPoolTagInformation)
1226 {
1227 /* FIXME */
1228 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1229 return STATUS_NOT_IMPLEMENTED;
1230 }
1231
1232 /* Class 23 - Interrupt Information for all processors */
1233 QSI_DEF(SystemInterruptInformation)
1234 {
1235 PKPRCB Prcb;
1236 LONG i;
1237 ULONG ti;
1238 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1239
1240 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1241 {
1242 return STATUS_INFO_LENGTH_MISMATCH;
1243 }
1244
1245 ti = KeQueryTimeIncrement();
1246
1247 for (i = 0; i < KeNumberProcessors; i++)
1248 {
1249 Prcb = KiProcessorBlock[i];
1250 sii->ContextSwitches = KeGetContextSwitches(Prcb);
1251 sii->DpcCount = Prcb->DpcData[0].DpcCount;
1252 sii->DpcRate = Prcb->DpcRequestRate;
1253 sii->TimeIncrement = ti;
1254 sii->DpcBypassCount = 0;
1255 sii->ApcBypassCount = 0;
1256 sii++;
1257 }
1258
1259 return STATUS_SUCCESS;
1260 }
1261
1262 /* Class 24 - DPC Behaviour Information */
1263 QSI_DEF(SystemDpcBehaviourInformation)
1264 {
1265 /* FIXME */
1266 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1267 return STATUS_NOT_IMPLEMENTED;
1268 }
1269
1270 SSI_DEF(SystemDpcBehaviourInformation)
1271 {
1272 /* FIXME */
1273 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1274 return STATUS_NOT_IMPLEMENTED;
1275 }
1276
1277 /* Class 25 - Full Memory Information */
1278 QSI_DEF(SystemFullMemoryInformation)
1279 {
1280 PULONG Spi = (PULONG) Buffer;
1281
1282 PEPROCESS TheIdleProcess;
1283
1284 *ReqSize = sizeof(ULONG);
1285
1286 if (sizeof(ULONG) != Size)
1287 {
1288 return STATUS_INFO_LENGTH_MISMATCH;
1289 }
1290
1291 DPRINT("SystemFullMemoryInformation\n");
1292
1293 TheIdleProcess = PsIdleProcess;
1294
1295 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1296 TheIdleProcess->UniqueProcessId,
1297 TheIdleProcess->Pcb.KernelTime,
1298 MiFreeSwapPages,
1299 MiUsedSwapPages);
1300
1301 #ifndef NDEBUG
1302 MmPrintMemoryStatistic();
1303 #endif
1304
1305 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1306
1307 return STATUS_SUCCESS;
1308 }
1309
1310 /* Class 26 - Load Image */
1311 SSI_DEF(SystemLoadGdiDriverInformation)
1312 {
1313 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1314 UNICODE_STRING ImageName;
1315 PVOID ImageBase;
1316 PVOID SectionPointer;
1317 ULONG_PTR EntryPoint;
1318 NTSTATUS Status;
1319 ULONG DirSize;
1320 PIMAGE_NT_HEADERS NtHeader;
1321
1322 /* Validate size */
1323 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1324 {
1325 /* Incorrect buffer length, fail */
1326 return STATUS_INFO_LENGTH_MISMATCH;
1327 }
1328
1329 /* Only kernel mode can call this function */
1330 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1331
1332 /* Load the driver */
1333 ImageName = DriverInfo->DriverName;
1334 Status = MmLoadSystemImage(&ImageName,
1335 NULL,
1336 NULL,
1337 0,
1338 &SectionPointer,
1339 &ImageBase);
1340 if (!NT_SUCCESS(Status)) return Status;
1341
1342 /* Return the export pointer */
1343 DriverInfo->ExportSectionPointer =
1344 RtlImageDirectoryEntryToData(ImageBase,
1345 TRUE,
1346 IMAGE_DIRECTORY_ENTRY_EXPORT,
1347 &DirSize);
1348
1349 /* Get the entrypoint */
1350 NtHeader = RtlImageNtHeader(ImageBase);
1351 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1352 EntryPoint += (ULONG_PTR)ImageBase;
1353
1354 /* Save other data */
1355 DriverInfo->ImageAddress = ImageBase;
1356 DriverInfo->SectionPointer = SectionPointer;
1357 DriverInfo->EntryPoint = (PVOID)EntryPoint;
1358 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1359
1360 /* All is good */
1361 return STATUS_SUCCESS;
1362 }
1363
1364 /* Class 27 - Unload Image */
1365 SSI_DEF(SystemUnloadGdiDriverInformation)
1366 {
1367 PVOID SectionPointer = Buffer;
1368
1369 /* Validate size */
1370 if (Size != sizeof(PVOID))
1371 {
1372 /* Incorrect length, fail */
1373 return STATUS_INFO_LENGTH_MISMATCH;
1374 }
1375
1376 /* Only kernel mode can call this function */
1377 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1378
1379 /* Unload the image */
1380 MmUnloadSystemImage(SectionPointer);
1381 return STATUS_SUCCESS;
1382 }
1383
1384 /* Class 28 - Time Adjustment Information */
1385 QSI_DEF(SystemTimeAdjustmentInformation)
1386 {
1387 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo =
1388 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer;
1389
1390 /* Check if enough storage was provided */
1391 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size)
1392 {
1393 * ReqSize = sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION);
1394 return STATUS_INFO_LENGTH_MISMATCH;
1395 }
1396
1397 /* Give time values to our caller */
1398 TimeInfo->TimeIncrement = KeMaximumIncrement;
1399 TimeInfo->TimeAdjustment = KeTimeAdjustment;
1400 TimeInfo->Enable = TRUE;
1401
1402 return STATUS_SUCCESS;
1403 }
1404
1405 SSI_DEF(SystemTimeAdjustmentInformation)
1406 {
1407 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1408 /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1409 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
1410
1411 /* Check size of a buffer, it must match our expectations */
1412 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
1413 return STATUS_INFO_LENGTH_MISMATCH;
1414
1415 /* Check who is calling */
1416 if (PreviousMode != KernelMode)
1417 {
1418 /* Check access rights */
1419 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode))
1420 {
1421 return STATUS_PRIVILEGE_NOT_HELD;
1422 }
1423 }
1424
1425 /* TODO: Set time adjustment information */
1426 DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
1427 return STATUS_NOT_IMPLEMENTED;
1428 }
1429
1430 /* Class 29 - Summary Memory Information */
1431 QSI_DEF(SystemSummaryMemoryInformation)
1432 {
1433 /* FIXME */
1434 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1435 return STATUS_NOT_IMPLEMENTED;
1436 }
1437
1438 /* Class 30 - Next Event Id Information */
1439 QSI_DEF(SystemNextEventIdInformation)
1440 {
1441 /* FIXME */
1442 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1443 return STATUS_NOT_IMPLEMENTED;
1444 }
1445
1446 /* Class 31 - Event Ids Information */
1447 QSI_DEF(SystemEventIdsInformation)
1448 {
1449 /* FIXME */
1450 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1451 return STATUS_NOT_IMPLEMENTED;
1452 }
1453
1454 /* Class 32 - Crash Dump Information */
1455 QSI_DEF(SystemCrashDumpInformation)
1456 {
1457 /* FIXME */
1458 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1459 return STATUS_NOT_IMPLEMENTED;
1460 }
1461
1462 /* Class 33 - Exception Information */
1463 QSI_DEF(SystemExceptionInformation)
1464 {
1465 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation =
1466 (PSYSTEM_EXCEPTION_INFORMATION)Buffer;
1467 PKPRCB Prcb;
1468 ULONG i, AlignmentFixupCount = 0, ExceptionDispatchCount = 0;
1469 ULONG FloatingEmulationCount = 0, ByteWordEmulationCount = 0;
1470
1471 /* Check size of a buffer, it must match our expectations */
1472 if (sizeof(SYSTEM_EXCEPTION_INFORMATION) != Size)
1473 return STATUS_INFO_LENGTH_MISMATCH;
1474
1475 /* Sum up exception count information from all processors */
1476 for (i = 0; i < KeNumberProcessors; i++)
1477 {
1478 Prcb = KiProcessorBlock[i];
1479 if (Prcb)
1480 {
1481 AlignmentFixupCount += Prcb->KeAlignmentFixupCount;
1482 ExceptionDispatchCount += Prcb->KeExceptionDispatchCount;
1483 FloatingEmulationCount += Prcb->KeFloatingEmulationCount;
1484 }
1485 }
1486
1487 /* Save information in user's buffer */
1488 ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount;
1489 ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount;
1490 ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount;
1491 ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount;
1492
1493 return STATUS_SUCCESS;
1494 }
1495
1496 /* Class 34 - Crash Dump State Information */
1497 QSI_DEF(SystemCrashDumpStateInformation)
1498 {
1499 /* FIXME */
1500 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1501 return STATUS_NOT_IMPLEMENTED;
1502 }
1503
1504 /* Class 35 - Kernel Debugger Information */
1505 QSI_DEF(SystemKernelDebuggerInformation)
1506 {
1507 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1508
1509 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1510 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1511 {
1512 return STATUS_INFO_LENGTH_MISMATCH;
1513 }
1514
1515 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1516 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1517
1518 return STATUS_SUCCESS;
1519 }
1520
1521 /* Class 36 - Context Switch Information */
1522 QSI_DEF(SystemContextSwitchInformation)
1523 {
1524 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation =
1525 (PSYSTEM_CONTEXT_SWITCH_INFORMATION)Buffer;
1526 ULONG ContextSwitches, i;
1527 PKPRCB Prcb;
1528
1529 /* Check size of a buffer, it must match our expectations */
1530 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION) != Size)
1531 return STATUS_INFO_LENGTH_MISMATCH;
1532
1533 /* Calculate total value of context switches across all processors */
1534 ContextSwitches = 0;
1535 for (i = 0; i < KeNumberProcessors; i ++)
1536 {
1537 Prcb = KiProcessorBlock[i];
1538 if (Prcb)
1539 {
1540 ContextSwitches += KeGetContextSwitches(Prcb);
1541 }
1542 }
1543
1544 ContextSwitchInformation->ContextSwitches = ContextSwitches;
1545
1546 /* FIXME */
1547 ContextSwitchInformation->FindAny = 0;
1548 ContextSwitchInformation->FindLast = 0;
1549 ContextSwitchInformation->FindIdeal = 0;
1550 ContextSwitchInformation->IdleAny = 0;
1551 ContextSwitchInformation->IdleCurrent = 0;
1552 ContextSwitchInformation->IdleLast = 0;
1553 ContextSwitchInformation->IdleIdeal = 0;
1554 ContextSwitchInformation->PreemptAny = 0;
1555 ContextSwitchInformation->PreemptCurrent = 0;
1556 ContextSwitchInformation->PreemptLast = 0;
1557 ContextSwitchInformation->SwitchToIdle = 0;
1558
1559 return STATUS_SUCCESS;
1560 }
1561
1562 /* Class 37 - Registry Quota Information */
1563 QSI_DEF(SystemRegistryQuotaInformation)
1564 {
1565 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1566
1567 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1568 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1569 {
1570 return STATUS_INFO_LENGTH_MISMATCH;
1571 }
1572
1573 DPRINT1("Faking max registry size of 32 MB\n");
1574 srqi->RegistryQuotaAllowed = 0x2000000;
1575 srqi->RegistryQuotaUsed = 0x200000;
1576 srqi->PagedPoolSize = 0x200000;
1577
1578 return STATUS_SUCCESS;
1579 }
1580
1581 SSI_DEF(SystemRegistryQuotaInformation)
1582 {
1583 /* FIXME */
1584 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1585 return STATUS_NOT_IMPLEMENTED;
1586 }
1587
1588 /* Class 38 - Load And Call Image */
1589 SSI_DEF(SystemExtendServiceTableInformation)
1590 {
1591 UNICODE_STRING ImageName;
1592 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1593 PLDR_DATA_TABLE_ENTRY ModuleObject;
1594 NTSTATUS Status;
1595 PIMAGE_NT_HEADERS NtHeader;
1596 DRIVER_OBJECT Win32k;
1597 PDRIVER_INITIALIZE DriverInit;
1598 PVOID ImageBase;
1599 ULONG_PTR EntryPoint;
1600
1601 /* Validate the size */
1602 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1603
1604 /* Check who is calling */
1605 if (PreviousMode != KernelMode)
1606 {
1607 /* Make sure we can load drivers */
1608 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1609 {
1610 /* FIXME: We can't, fail */
1611 //return STATUS_PRIVILEGE_NOT_HELD;
1612 }
1613 }
1614
1615 /* Probe and capture the driver name */
1616 ProbeAndCaptureUnicodeString(&ImageName, PreviousMode, Buffer);
1617
1618 /* Load the image */
1619 Status = MmLoadSystemImage(&ImageName,
1620 NULL,
1621 NULL,
1622 0,
1623 (PVOID)&ModuleObject,
1624 &ImageBase);
1625
1626 /* Release String */
1627 ReleaseCapturedUnicodeString(&ImageName, PreviousMode);
1628
1629 if (!NT_SUCCESS(Status)) return Status;
1630
1631 /* Get the headers */
1632 NtHeader = RtlImageNtHeader(ImageBase);
1633 if (!NtHeader)
1634 {
1635 /* Fail */
1636 MmUnloadSystemImage(ModuleObject);
1637 return STATUS_INVALID_IMAGE_FORMAT;
1638 }
1639
1640 /* Get the entrypoint */
1641 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1642 EntryPoint += (ULONG_PTR)ImageBase;
1643 DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1644
1645 /* Create a dummy device */
1646 RtlZeroMemory(&Win32k, sizeof(Win32k));
1647 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1648 Win32k.DriverStart = ImageBase;
1649
1650 /* Call it */
1651 Status = (DriverInit)(&Win32k, NULL);
1652 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1653
1654 /* Unload if we failed */
1655 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
1656 return Status;
1657 }
1658
1659 /* Class 39 - Priority Separation */
1660 SSI_DEF(SystemPrioritySeperation)
1661 {
1662 /* FIXME */
1663 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1664 return STATUS_NOT_IMPLEMENTED;
1665 }
1666
1667 /* Class 40 - Plug Play Bus Information */
1668 QSI_DEF(SystemPlugPlayBusInformation)
1669 {
1670 /* FIXME */
1671 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1672 return STATUS_NOT_IMPLEMENTED;
1673 }
1674
1675 /* Class 41 - Dock Information */
1676 QSI_DEF(SystemDockInformation)
1677 {
1678 /* FIXME */
1679 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1680 return STATUS_NOT_IMPLEMENTED;
1681 }
1682
1683 /* Class 42 - Power Information */
1684 QSI_DEF(SystemPowerInformation)
1685 {
1686 /* FIXME */
1687 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1688 return STATUS_NOT_IMPLEMENTED;
1689 }
1690
1691 /* Class 43 - Processor Speed Information */
1692 QSI_DEF(SystemProcessorSpeedInformation)
1693 {
1694 /* FIXME */
1695 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1696 return STATUS_NOT_IMPLEMENTED;
1697 }
1698
1699 /* Class 44 - Current Time Zone Information */
1700 QSI_DEF(SystemCurrentTimeZoneInformation)
1701 {
1702 *ReqSize = sizeof(TIME_ZONE_INFORMATION);
1703
1704 if (sizeof(TIME_ZONE_INFORMATION) != Size)
1705 {
1706 return STATUS_INFO_LENGTH_MISMATCH;
1707 }
1708
1709 /* Copy the time zone information struct */
1710 memcpy(Buffer,
1711 &ExpTimeZoneInfo,
1712 sizeof(TIME_ZONE_INFORMATION));
1713
1714 return STATUS_SUCCESS;
1715 }
1716
1717
1718 SSI_DEF(SystemCurrentTimeZoneInformation)
1719 {
1720 /* Check user buffer's size */
1721 if (Size < sizeof(TIME_ZONE_INFORMATION))
1722 {
1723 return STATUS_INFO_LENGTH_MISMATCH;
1724 }
1725
1726 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1727 }
1728
1729
1730 /* Class 45 - Lookaside Information */
1731 QSI_DEF(SystemLookasideInformation)
1732 {
1733 /* FIXME */
1734 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1735 return STATUS_NOT_IMPLEMENTED;
1736 }
1737
1738
1739 /* Class 46 - Set time slip event */
1740 SSI_DEF(SystemSetTimeSlipEvent)
1741 {
1742 /* FIXME */
1743 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1744 return STATUS_NOT_IMPLEMENTED;
1745 }
1746
1747
1748 /* Class 47 - Create a new session (TSE) */
1749 SSI_DEF(SystemCreateSession)
1750 {
1751 /* FIXME */
1752 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1753 return STATUS_NOT_IMPLEMENTED;
1754 }
1755
1756
1757 /* Class 48 - Delete an existing session (TSE) */
1758 SSI_DEF(SystemDeleteSession)
1759 {
1760 /* FIXME */
1761 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1762 return STATUS_NOT_IMPLEMENTED;
1763 }
1764
1765
1766 /* Class 49 - UNKNOWN */
1767 QSI_DEF(SystemInvalidInfoClass4)
1768 {
1769 /* FIXME */
1770 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1771 return STATUS_NOT_IMPLEMENTED;
1772 }
1773
1774
1775 /* Class 50 - System range start address */
1776 QSI_DEF(SystemRangeStartInformation)
1777 {
1778 /* FIXME */
1779 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1780 return STATUS_NOT_IMPLEMENTED;
1781 }
1782
1783
1784 /* Class 51 - Driver verifier information */
1785 QSI_DEF(SystemVerifierInformation)
1786 {
1787 /* FIXME */
1788 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1789 return STATUS_NOT_IMPLEMENTED;
1790 }
1791
1792
1793 SSI_DEF(SystemVerifierInformation)
1794 {
1795 /* FIXME */
1796 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1797 return STATUS_NOT_IMPLEMENTED;
1798 }
1799
1800
1801 /* Class 52 - Add a driver verifier */
1802 SSI_DEF(SystemAddVerifier)
1803 {
1804 /* FIXME */
1805 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1806 return STATUS_NOT_IMPLEMENTED;
1807 }
1808
1809
1810 /* Class 53 - A session's processes */
1811 QSI_DEF(SystemSessionProcessesInformation)
1812 {
1813 /* FIXME */
1814 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1815 return STATUS_NOT_IMPLEMENTED;
1816 }
1817
1818
1819 /* Query/Set Calls Table */
1820 typedef
1821 struct _QSSI_CALLS
1822 {
1823 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1824 NTSTATUS (* Set) (PVOID,ULONG);
1825
1826 } QSSI_CALLS;
1827
1828 // QS Query & Set
1829 // QX Query
1830 // XS Set
1831 // XX unknown behaviour
1832 //
1833 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1834 #define SI_QX(n) {QSI_USE(n),NULL}
1835 #define SI_XS(n) {NULL,SSI_USE(n)}
1836 #define SI_XX(n) {NULL,NULL}
1837
1838 static
1839 QSSI_CALLS
1840 CallQS [] =
1841 {
1842 SI_QX(SystemBasicInformation),
1843 SI_QX(SystemProcessorInformation),
1844 SI_QX(SystemPerformanceInformation),
1845 SI_QX(SystemTimeOfDayInformation),
1846 SI_QX(SystemPathInformation), /* should be SI_XX */
1847 SI_QX(SystemProcessInformation),
1848 SI_QX(SystemCallCountInformation),
1849 SI_QX(SystemDeviceInformation),
1850 SI_QX(SystemProcessorPerformanceInformation),
1851 SI_QS(SystemFlagsInformation),
1852 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1853 SI_QX(SystemModuleInformation),
1854 SI_QX(SystemLocksInformation),
1855 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1856 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1857 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1858 SI_QX(SystemHandleInformation),
1859 SI_QX(SystemObjectInformation),
1860 SI_QX(SystemPageFileInformation),
1861 SI_QX(SystemVdmInstemulInformation),
1862 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1863 SI_QS(SystemFileCacheInformation),
1864 SI_QX(SystemPoolTagInformation),
1865 SI_QX(SystemInterruptInformation),
1866 SI_QS(SystemDpcBehaviourInformation),
1867 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1868 SI_XS(SystemLoadGdiDriverInformation),
1869 SI_XS(SystemUnloadGdiDriverInformation),
1870 SI_QS(SystemTimeAdjustmentInformation),
1871 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1872 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1873 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1874 SI_QX(SystemCrashDumpInformation),
1875 SI_QX(SystemExceptionInformation),
1876 SI_QX(SystemCrashDumpStateInformation),
1877 SI_QX(SystemKernelDebuggerInformation),
1878 SI_QX(SystemContextSwitchInformation),
1879 SI_QS(SystemRegistryQuotaInformation),
1880 SI_XS(SystemExtendServiceTableInformation),
1881 SI_XS(SystemPrioritySeperation),
1882 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1883 SI_QX(SystemDockInformation), /* it should be SI_XX */
1884 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1885 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1886 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1887 SI_QX(SystemLookasideInformation),
1888 SI_XS(SystemSetTimeSlipEvent),
1889 SI_XS(SystemCreateSession),
1890 SI_XS(SystemDeleteSession),
1891 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1892 SI_QX(SystemRangeStartInformation),
1893 SI_QS(SystemVerifierInformation),
1894 SI_XS(SystemAddVerifier),
1895 SI_QX(SystemSessionProcessesInformation)
1896 };
1897
1898 C_ASSERT(SystemBasicInformation == 0);
1899 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1900 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1901
1902 /*
1903 * @implemented
1904 */
1905 NTSTATUS NTAPI
1906 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1907 OUT PVOID SystemInformation,
1908 IN ULONG Length,
1909 OUT PULONG UnsafeResultLength)
1910 {
1911 KPROCESSOR_MODE PreviousMode;
1912 ULONG ResultLength;
1913 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1914
1915 PAGED_CODE();
1916
1917 PreviousMode = ExGetPreviousMode();
1918
1919 _SEH2_TRY
1920 {
1921 if (PreviousMode != KernelMode)
1922 {
1923 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1924 ProbeForWrite(SystemInformation, Length, 1);
1925 if (UnsafeResultLength != NULL)
1926 ProbeForWriteUlong(UnsafeResultLength);
1927 }
1928
1929 /*
1930 * Check the request is valid.
1931 */
1932 if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
1933 {
1934 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
1935 }
1936
1937 if (NULL != CallQS [SystemInformationClass].Query)
1938 {
1939 /*
1940 * Hand the request to a subhandler.
1941 */
1942 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1943 Length,
1944 &ResultLength);
1945 if (UnsafeResultLength != NULL)
1946 {
1947 if (PreviousMode != KernelMode)
1948 {
1949 *UnsafeResultLength = ResultLength;
1950 }
1951 else
1952 {
1953 *UnsafeResultLength = ResultLength;
1954 }
1955 }
1956 }
1957 }
1958 _SEH2_EXCEPT(ExSystemExceptionFilter())
1959 {
1960 FStatus = _SEH2_GetExceptionCode();
1961 }
1962 _SEH2_END;
1963
1964 return FStatus;
1965 }
1966
1967
1968 NTSTATUS
1969 NTAPI
1970 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1971 IN PVOID SystemInformation,
1972 IN ULONG SystemInformationLength)
1973 {
1974 PAGED_CODE();
1975
1976 /*
1977 * If called from user mode, check
1978 * possible unsafe arguments.
1979 */
1980 #if 0
1981 if (KernelMode != KeGetPreviousMode())
1982 {
1983 // Check arguments
1984 //ProbeForWrite(
1985 // SystemInformation,
1986 // Length
1987 // );
1988 //ProbeForWrite(
1989 // ResultLength,
1990 // sizeof (ULONG)
1991 // );
1992 }
1993 #endif
1994 /*
1995 * Check the request is valid.
1996 */
1997 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
1998 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
1999 {
2000 if (NULL != CallQS [SystemInformationClass].Set)
2001 {
2002 /*
2003 * Hand the request to a subhandler.
2004 */
2005 return CallQS [SystemInformationClass].Set(SystemInformation,
2006 SystemInformationLength);
2007 }
2008 }
2009
2010 return STATUS_INVALID_INFO_CLASS;
2011 }
2012
2013 NTSTATUS
2014 NTAPI
2015 NtFlushInstructionCache(IN HANDLE ProcessHandle,
2016 IN PVOID BaseAddress,
2017 IN ULONG NumberOfBytesToFlush)
2018 {
2019 PAGED_CODE();
2020
2021 #if defined(_M_IX86) || defined(_M_AMD64)
2022 __wbinvd();
2023 #elif defined(_M_PPC)
2024 __asm__ __volatile__("tlbsync");
2025 #elif defined(_M_MIPS)
2026 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2027 for (;;);
2028 #elif defined(_M_ARM)
2029 __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
2030 #else
2031 #error Unknown architecture
2032 #endif
2033 return STATUS_SUCCESS;
2034 }
2035
2036 ULONG
2037 NTAPI
2038 NtGetCurrentProcessorNumber(VOID)
2039 {
2040 /* Just return the CPU */
2041 return KeGetCurrentProcessorNumber();
2042 }
2043
2044 /*
2045 * @implemented
2046 */
2047 #undef ExGetPreviousMode
2048 KPROCESSOR_MODE
2049 NTAPI
2050 ExGetPreviousMode (VOID)
2051 {
2052 return KeGetPreviousMode();
2053 }