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