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