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