3373344bd346473045b8559ed43fe2b1403910c0
[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 ULONG ovlSize = 0, nThreads;
705 PEPROCESS pr = NULL, syspr;
706 PUCHAR pCur;
707 ULONG TotalUser, TotalKernel;
708 NTSTATUS Status = STATUS_SUCCESS;
709
710 _SEH2_TRY
711 {
712 /* scan the process list */
713
714 PSYSTEM_PROCESS_INFORMATION Spi
715 = (PSYSTEM_PROCESS_INFORMATION) Buffer;
716
717 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
718
719 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
720 {
721 _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
722 }
723 RtlZeroMemory(Spi, Size);
724
725 syspr = PsIdleProcess;
726 pr = syspr;
727 pCur = (unsigned char *)Spi;
728
729 do
730 {
731 PSYSTEM_PROCESS_INFORMATION SpiCur;
732 int curSize;
733 ANSI_STRING imgName;
734 int inLen = 32; // image name len in bytes
735 PLIST_ENTRY current_entry;
736 PETHREAD current;
737 PSYSTEM_THREAD_INFORMATION ThreadInfo;
738
739 SpiCur = (PSYSTEM_PROCESS_INFORMATION)pCur;
740
741 nThreads = 0;
742 current_entry = pr->ThreadListHead.Flink;
743 while (current_entry != &pr->ThreadListHead)
744 {
745 nThreads++;
746 current_entry = current_entry->Flink;
747 }
748
749 // size of the structure for every process
750 curSize = sizeof(SYSTEM_PROCESS_INFORMATION)+sizeof(SYSTEM_THREAD_INFORMATION)*nThreads;
751 ovlSize += curSize+inLen;
752
753 if (ovlSize > Size)
754 {
755 *ReqSize = ovlSize;
756 ObDereferenceObject(pr);
757
758 _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
759 }
760
761 // fill system information
762 SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
763 SpiCur->NumberOfThreads = nThreads;
764 SpiCur->CreateTime = pr->CreateTime;
765 SpiCur->ImageName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
766 SpiCur->ImageName.MaximumLength = (USHORT)inLen;
767 SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
768
769 // copy name to the end of the struct
770 if(pr != PsIdleProcess)
771 {
772 RtlInitAnsiString(&imgName, pr->ImageFileName);
773 RtlAnsiStringToUnicodeString(&SpiCur->ImageName, &imgName, FALSE);
774 }
775 else
776 {
777 RtlInitUnicodeString(&SpiCur->ImageName, NULL);
778 }
779
780 SpiCur->BasePriority = pr->Pcb.BasePriority;
781 SpiCur->UniqueProcessId = pr->UniqueProcessId;
782 SpiCur->InheritedFromUniqueProcessId = pr->InheritedFromUniqueProcessId;
783 SpiCur->HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
784 SpiCur->PeakVirtualSize = pr->PeakVirtualSize;
785 SpiCur->VirtualSize = pr->VirtualSize;
786 SpiCur->PageFaultCount = pr->Vm.PageFaultCount;
787 SpiCur->PeakWorkingSetSize = pr->Vm.PeakWorkingSetSize;
788 SpiCur->WorkingSetSize = pr->Vm.WorkingSetSize;
789 SpiCur->QuotaPeakPagedPoolUsage = pr->QuotaPeak[0];
790 SpiCur->QuotaPagedPoolUsage = pr->QuotaUsage[0];
791 SpiCur->QuotaPeakNonPagedPoolUsage = pr->QuotaPeak[1];
792 SpiCur->QuotaNonPagedPoolUsage = pr->QuotaUsage[1];
793 SpiCur->PagefileUsage = pr->QuotaUsage[2];
794 SpiCur->PeakPagefileUsage = pr->QuotaPeak[2];
795 SpiCur->PrivatePageCount = pr->CommitCharge;
796 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCur + 1);
797
798 current_entry = pr->ThreadListHead.Flink;
799 while (current_entry != &pr->ThreadListHead)
800 {
801 current = CONTAINING_RECORD(current_entry, ETHREAD,
802 ThreadListEntry);
803
804 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(current->Tcb.KernelTime, KeMaximumIncrement);
805 ThreadInfo->UserTime.QuadPart = UInt32x32To64(current->Tcb.UserTime, KeMaximumIncrement);
806 ThreadInfo->CreateTime.QuadPart = current->CreateTime.QuadPart;
807 ThreadInfo->WaitTime = current->Tcb.WaitTime;
808 ThreadInfo->StartAddress = (PVOID) current->StartAddress;
809 ThreadInfo->ClientId = current->Cid;
810 ThreadInfo->Priority = current->Tcb.Priority;
811 ThreadInfo->BasePriority = current->Tcb.BasePriority;
812 ThreadInfo->ContextSwitches = current->Tcb.ContextSwitches;
813 ThreadInfo->ThreadState = current->Tcb.State;
814 ThreadInfo->WaitReason = current->Tcb.WaitReason;
815
816 ThreadInfo++;
817 current_entry = current_entry->Flink;
818 }
819
820 /* Query total user/kernel times of a process */
821 TotalKernel = KeQueryRuntimeProcess(&pr->Pcb, &TotalUser);
822 SpiCur->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
823 SpiCur->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
824
825 /* Handle idle process entry */
826 if (pr == PsIdleProcess) pr = NULL;
827
828 pr = PsGetNextProcess(pr);
829 nThreads = 0;
830 if ((pr == syspr) || (pr == NULL))
831 {
832 SpiCur->NextEntryOffset = 0;
833 break;
834 }
835 else
836 pCur = pCur + curSize + inLen;
837 } while ((pr != syspr) && (pr != NULL));
838
839 if(pr != NULL)
840 ObDereferenceObject(pr);
841 Status = STATUS_SUCCESS;
842 }
843 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
844 {
845 if(pr != NULL)
846 ObDereferenceObject(pr);
847 Status = _SEH2_GetExceptionCode();
848 }
849 _SEH2_END
850
851 *ReqSize = ovlSize;
852 return Status;
853 }
854
855 /* Class 6 - Call Count Information */
856 QSI_DEF(SystemCallCountInformation)
857 {
858 /* FIXME */
859 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
860 return STATUS_NOT_IMPLEMENTED;
861 }
862
863 /* Class 7 - Device Information */
864 QSI_DEF(SystemDeviceInformation)
865 {
866 PSYSTEM_DEVICE_INFORMATION Sdi
867 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
868 PCONFIGURATION_INFORMATION ConfigInfo;
869
870 *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION);
871
872 /* Check user buffer's size */
873 if (Size < sizeof(SYSTEM_DEVICE_INFORMATION))
874 {
875 return STATUS_INFO_LENGTH_MISMATCH;
876 }
877
878 ConfigInfo = IoGetConfigurationInformation();
879
880 Sdi->NumberOfDisks = ConfigInfo->DiskCount;
881 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
882 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
883 Sdi->NumberOfTapes = ConfigInfo->TapeCount;
884 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
885 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
886
887 return STATUS_SUCCESS;
888 }
889
890 /* Class 8 - Processor Performance Information */
891 QSI_DEF(SystemProcessorPerformanceInformation)
892 {
893 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
894 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
895
896 LONG i;
897 ULONG TotalTime;
898 LARGE_INTEGER CurrentTime;
899 PKPRCB Prcb;
900
901 *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
902
903 /* Check user buffer's size */
904 if (Size < *ReqSize)
905 {
906 return STATUS_INFO_LENGTH_MISMATCH;
907 }
908
909 CurrentTime.QuadPart = KeQueryInterruptTime();
910 Prcb = KeGetPcr()->Prcb;
911 for (i = 0; i < KeNumberProcessors; i++)
912 {
913 /* Calculate total user and kernel times */
914 TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime;
915 Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement);
916 Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement);
917 Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement);
918 Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement);
919 Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement);
920 Spi->InterruptCount = Prcb->InterruptCount;
921 Spi++;
922 Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
923 }
924
925 return STATUS_SUCCESS;
926 }
927
928 /* Class 9 - Flags Information */
929 QSI_DEF(SystemFlagsInformation)
930 {
931 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
932 {
933 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
934 return (STATUS_INFO_LENGTH_MISMATCH);
935 }
936 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
937 return STATUS_SUCCESS;
938 }
939
940 SSI_DEF(SystemFlagsInformation)
941 {
942 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
943 {
944 return STATUS_INFO_LENGTH_MISMATCH;
945 }
946 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
947 return STATUS_SUCCESS;
948 }
949
950 /* Class 10 - Call Time Information */
951 QSI_DEF(SystemCallTimeInformation)
952 {
953 /* FIXME */
954 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
955 return STATUS_NOT_IMPLEMENTED;
956 }
957
958 /* Class 11 - Module Information */
959 QSI_DEF(SystemModuleInformation)
960 {
961 extern LIST_ENTRY PsLoadedModuleList;
962 return ExpQueryModuleInformation(&PsLoadedModuleList,
963 NULL,
964 (PRTL_PROCESS_MODULES)Buffer,
965 Size,
966 ReqSize);
967 }
968
969 /* Class 12 - Locks Information */
970 QSI_DEF(SystemLocksInformation)
971 {
972 /* FIXME */
973 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
974 return STATUS_NOT_IMPLEMENTED;
975 }
976
977 /* Class 13 - Stack Trace Information */
978 QSI_DEF(SystemStackTraceInformation)
979 {
980 /* FIXME */
981 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
982 return STATUS_NOT_IMPLEMENTED;
983 }
984
985 /* Class 14 - Paged Pool Information */
986 QSI_DEF(SystemPagedPoolInformation)
987 {
988 /* FIXME */
989 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
990 return STATUS_NOT_IMPLEMENTED;
991 }
992
993 /* Class 15 - Non Paged Pool Information */
994 QSI_DEF(SystemNonPagedPoolInformation)
995 {
996 /* FIXME */
997 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
998 return STATUS_NOT_IMPLEMENTED;
999 }
1000
1001
1002 /* Class 16 - Handle Information */
1003 QSI_DEF(SystemHandleInformation)
1004 {
1005 PEPROCESS pr, syspr;
1006 ULONG curSize, i = 0;
1007 ULONG hCount = 0;
1008
1009 PSYSTEM_HANDLE_INFORMATION Shi =
1010 (PSYSTEM_HANDLE_INFORMATION) Buffer;
1011
1012 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
1013
1014 if (Size < sizeof(SYSTEM_HANDLE_INFORMATION))
1015 {
1016 *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
1017 return STATUS_INFO_LENGTH_MISMATCH;
1018 }
1019
1020 DPRINT("SystemHandleInformation 1\n");
1021
1022 /* First Calc Size from Count. */
1023 syspr = PsGetNextProcess(NULL);
1024 pr = syspr;
1025
1026 do
1027 {
1028 hCount = hCount + (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
1029 pr = PsGetNextProcess(pr);
1030
1031 if ((pr == syspr) || (pr == NULL)) break;
1032 }
1033 while ((pr != syspr) && (pr != NULL));
1034
1035 if(pr != NULL)
1036 {
1037 ObDereferenceObject(pr);
1038 }
1039
1040 DPRINT("SystemHandleInformation 2\n");
1041
1042 curSize = sizeof(SYSTEM_HANDLE_INFORMATION) +
1043 ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) -
1044 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)));
1045
1046 Shi->NumberOfHandles = hCount;
1047
1048 if (curSize > Size)
1049 {
1050 *ReqSize = curSize;
1051 return (STATUS_INFO_LENGTH_MISMATCH);
1052 }
1053
1054 DPRINT("SystemHandleInformation 3\n");
1055
1056 /* Now get Handles from all processs. */
1057 syspr = PsGetNextProcess(NULL);
1058 pr = syspr;
1059
1060 do
1061 {
1062 int Count = 0, HandleCount;
1063
1064 HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
1065
1066 for (Count = 0; HandleCount > 0 ; HandleCount--)
1067 {
1068 Shi->Handles[i].UniqueProcessId = (USHORT)(ULONG)pr->UniqueProcessId;
1069 Count++;
1070 i++;
1071 }
1072
1073 pr = PsGetNextProcess(pr);
1074
1075 if ((pr == syspr) || (pr == NULL)) break;
1076 }
1077 while ((pr != syspr) && (pr != NULL));
1078
1079 if(pr != NULL) ObDereferenceObject(pr);
1080
1081 DPRINT("SystemHandleInformation 4\n");
1082 return STATUS_SUCCESS;
1083
1084 }
1085 /*
1086 SSI_DEF(SystemHandleInformation)
1087 {
1088
1089 return STATUS_SUCCESS;
1090 }
1091 */
1092
1093 /* Class 17 - Information */
1094 QSI_DEF(SystemObjectInformation)
1095 {
1096 /* FIXME */
1097 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1098 return STATUS_NOT_IMPLEMENTED;
1099 }
1100
1101 /* Class 18 - Information */
1102 QSI_DEF(SystemPageFileInformation)
1103 {
1104 UNICODE_STRING FileName; /* FIXME */
1105 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
1106
1107 if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION))
1108 {
1109 * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION);
1110 return STATUS_INFO_LENGTH_MISMATCH;
1111 }
1112
1113 RtlInitUnicodeString(&FileName, NULL); /* FIXME */
1114
1115 /* FIXME */
1116 Spfi->NextEntryOffset = 0;
1117
1118 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
1119 Spfi->TotalInUse = MiUsedSwapPages;
1120 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
1121 Spfi->PageFileName = FileName;
1122 return STATUS_SUCCESS;
1123 }
1124
1125 /* Class 19 - Vdm Instemul Information */
1126 QSI_DEF(SystemVdmInstemulInformation)
1127 {
1128 /* FIXME */
1129 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1130 return STATUS_NOT_IMPLEMENTED;
1131 }
1132
1133 /* Class 20 - Vdm Bop Information */
1134 QSI_DEF(SystemVdmBopInformation)
1135 {
1136 /* FIXME */
1137 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1138 return STATUS_NOT_IMPLEMENTED;
1139 }
1140
1141 /* Class 21 - File Cache Information */
1142 QSI_DEF(SystemFileCacheInformation)
1143 {
1144 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
1145
1146 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1147 {
1148 *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
1149 return STATUS_INFO_LENGTH_MISMATCH;
1150 }
1151
1152 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION));
1153
1154 /* Return the Byte size not the page size. */
1155 Sci->CurrentSize =
1156 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
1157 Sci->PeakSize =
1158 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE; /* FIXME */
1159 /* Taskmgr multiplies this one by page size right away */
1160 Sci->CurrentSizeIncludingTransitionInPages =
1161 MiMemoryConsumers[MC_CACHE].PagesUsed; /* FIXME: Should be */
1162 /* system working set and standby pages. */
1163 Sci->PageFaultCount = 0; /* FIXME */
1164 Sci->MinimumWorkingSet = 0; /* FIXME */
1165 Sci->MaximumWorkingSet = 0; /* FIXME */
1166
1167 return STATUS_SUCCESS;
1168 }
1169
1170 SSI_DEF(SystemFileCacheInformation)
1171 {
1172 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1173 {
1174 return STATUS_INFO_LENGTH_MISMATCH;
1175 }
1176 /* FIXME */
1177 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1178 return STATUS_NOT_IMPLEMENTED;
1179 }
1180
1181 /* Class 22 - Pool Tag Information */
1182 QSI_DEF(SystemPoolTagInformation)
1183 {
1184 /* FIXME */
1185 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1186 return STATUS_NOT_IMPLEMENTED;
1187 }
1188
1189 /* Class 23 - Interrupt Information for all processors */
1190 QSI_DEF(SystemInterruptInformation)
1191 {
1192 PKPRCB Prcb;
1193 PKPCR Pcr;
1194 LONG i;
1195 ULONG ti;
1196 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1197
1198 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1199 {
1200 return STATUS_INFO_LENGTH_MISMATCH;
1201 }
1202
1203 ti = KeQueryTimeIncrement();
1204
1205 for (i = 0; i < KeNumberProcessors; i++)
1206 {
1207 Prcb = KiProcessorBlock[i];
1208 Pcr = CONTAINING_RECORD(Prcb, KPCR, Prcb);
1209 #ifdef _M_ARM // This code should probably be done differently
1210 sii->ContextSwitches = Pcr->ContextSwitches;
1211 #else
1212 sii->ContextSwitches = ((PKIPCR)Pcr)->ContextSwitches;
1213 #endif
1214 sii->DpcCount = Prcb->DpcData[0].DpcCount;
1215 sii->DpcRate = Prcb->DpcRequestRate;
1216 sii->TimeIncrement = ti;
1217 sii->DpcBypassCount = 0;
1218 sii->ApcBypassCount = 0;
1219 sii++;
1220 }
1221
1222 return STATUS_SUCCESS;
1223 }
1224
1225 /* Class 24 - DPC Behaviour Information */
1226 QSI_DEF(SystemDpcBehaviourInformation)
1227 {
1228 /* FIXME */
1229 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1230 return STATUS_NOT_IMPLEMENTED;
1231 }
1232
1233 SSI_DEF(SystemDpcBehaviourInformation)
1234 {
1235 /* FIXME */
1236 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1237 return STATUS_NOT_IMPLEMENTED;
1238 }
1239
1240 /* Class 25 - Full Memory Information */
1241 QSI_DEF(SystemFullMemoryInformation)
1242 {
1243 PULONG Spi = (PULONG) Buffer;
1244
1245 PEPROCESS TheIdleProcess;
1246
1247 *ReqSize = sizeof(ULONG);
1248
1249 if (sizeof(ULONG) != Size)
1250 {
1251 return STATUS_INFO_LENGTH_MISMATCH;
1252 }
1253
1254 DPRINT("SystemFullMemoryInformation\n");
1255
1256 TheIdleProcess = PsIdleProcess;
1257
1258 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1259 TheIdleProcess->UniqueProcessId,
1260 TheIdleProcess->Pcb.KernelTime,
1261 MiFreeSwapPages,
1262 MiUsedSwapPages);
1263
1264 #ifndef NDEBUG
1265 MmPrintMemoryStatistic();
1266 #endif
1267
1268 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1269
1270 return STATUS_SUCCESS;
1271 }
1272
1273 /* Class 26 - Load Image */
1274 SSI_DEF(SystemLoadGdiDriverInformation)
1275 {
1276 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1277 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1278 UNICODE_STRING ImageName;
1279 PVOID ImageBase;
1280 PLDR_DATA_TABLE_ENTRY ModuleObject;
1281 ULONG_PTR EntryPoint;
1282 NTSTATUS Status;
1283 ULONG DirSize;
1284 PIMAGE_NT_HEADERS NtHeader;
1285
1286 /* Validate size */
1287 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1288 {
1289 /* Incorrect buffer length, fail */
1290 return STATUS_INFO_LENGTH_MISMATCH;
1291 }
1292
1293 /* Only kernel-mode can call this function */
1294 if (PreviousMode != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1295
1296 /* Load the driver */
1297 ImageName = DriverInfo->DriverName;
1298 Status = MmLoadSystemImage(&ImageName,
1299 NULL,
1300 NULL,
1301 0,
1302 (PVOID)&ModuleObject,
1303 &ImageBase);
1304 if (!NT_SUCCESS(Status)) return Status;
1305
1306 /* Return the export pointer */
1307 DriverInfo->ExportSectionPointer =
1308 RtlImageDirectoryEntryToData(ImageBase,
1309 TRUE,
1310 IMAGE_DIRECTORY_ENTRY_EXPORT,
1311 &DirSize);
1312
1313 /* Get the entrypoint */
1314 NtHeader = RtlImageNtHeader(ImageBase);
1315 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1316 EntryPoint += (ULONG_PTR)ImageBase;
1317
1318 /* Save other data */
1319 DriverInfo->ImageAddress = ImageBase;
1320 DriverInfo->SectionPointer = NULL;
1321 DriverInfo->EntryPoint = (PVOID)EntryPoint;
1322 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1323
1324 /* All is good */
1325 return STATUS_SUCCESS;
1326 }
1327
1328 /* Class 27 - Unload Image */
1329 SSI_DEF(SystemUnloadGdiDriverInformation)
1330 {
1331 PLDR_DATA_TABLE_ENTRY LdrEntry;
1332 PLIST_ENTRY NextEntry;
1333 PVOID BaseAddr = *((PVOID*)Buffer);
1334
1335 if(Size != sizeof(PVOID))
1336 return STATUS_INFO_LENGTH_MISMATCH;
1337
1338 if(KeGetPreviousMode() != KernelMode)
1339 return STATUS_PRIVILEGE_NOT_HELD;
1340
1341 // Scan the module list
1342 NextEntry = PsLoadedModuleList.Flink;
1343 while(NextEntry != &PsLoadedModuleList)
1344 {
1345 LdrEntry = CONTAINING_RECORD(NextEntry,
1346 LDR_DATA_TABLE_ENTRY,
1347 InLoadOrderLinks);
1348
1349 if (LdrEntry->DllBase == BaseAddr)
1350 {
1351 // Found it.
1352 break;
1353 }
1354
1355 NextEntry = NextEntry->Flink;
1356 }
1357
1358 // Check if we found the image
1359 if(NextEntry != &PsLoadedModuleList)
1360 {
1361 return MmUnloadSystemImage(LdrEntry);
1362 }
1363 else
1364 {
1365 DPRINT1("Image 0x%x not found.\n", BaseAddr);
1366 return STATUS_DLL_NOT_FOUND;
1367 }
1368
1369 }
1370
1371 /* Class 28 - Time Adjustment Information */
1372 QSI_DEF(SystemTimeAdjustmentInformation)
1373 {
1374 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo =
1375 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer;
1376
1377 /* Check if enough storage was provided */
1378 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size)
1379 {
1380 * ReqSize = sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION);
1381 return STATUS_INFO_LENGTH_MISMATCH;
1382 }
1383
1384 /* Give time values to our caller */
1385 TimeInfo->TimeIncrement = KeMaximumIncrement;
1386 TimeInfo->TimeAdjustment = KeTimeAdjustment;
1387 TimeInfo->Enable = TRUE;
1388
1389 return STATUS_SUCCESS;
1390 }
1391
1392 SSI_DEF(SystemTimeAdjustmentInformation)
1393 {
1394 /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1395 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
1396
1397 /* Check size of a buffer, it must match our expectations */
1398 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
1399 return STATUS_INFO_LENGTH_MISMATCH;
1400
1401 /* TODO: Check privileges */
1402
1403 /* TODO: Set time adjustment information */
1404 DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
1405 return STATUS_NOT_IMPLEMENTED;
1406 }
1407
1408 /* Class 29 - Summary Memory Information */
1409 QSI_DEF(SystemSummaryMemoryInformation)
1410 {
1411 /* FIXME */
1412 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1413 return STATUS_NOT_IMPLEMENTED;
1414 }
1415
1416 /* Class 30 - Next Event Id Information */
1417 QSI_DEF(SystemNextEventIdInformation)
1418 {
1419 /* FIXME */
1420 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1421 return STATUS_NOT_IMPLEMENTED;
1422 }
1423
1424 /* Class 31 - Event Ids Information */
1425 QSI_DEF(SystemEventIdsInformation)
1426 {
1427 /* FIXME */
1428 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1429 return STATUS_NOT_IMPLEMENTED;
1430 }
1431
1432 /* Class 32 - Crash Dump Information */
1433 QSI_DEF(SystemCrashDumpInformation)
1434 {
1435 /* FIXME */
1436 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1437 return STATUS_NOT_IMPLEMENTED;
1438 }
1439
1440 /* Class 33 - Exception Information */
1441 QSI_DEF(SystemExceptionInformation)
1442 {
1443 /* FIXME */
1444 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1445 return STATUS_NOT_IMPLEMENTED;
1446 }
1447
1448 /* Class 34 - Crash Dump State Information */
1449 QSI_DEF(SystemCrashDumpStateInformation)
1450 {
1451 /* FIXME */
1452 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1453 return STATUS_NOT_IMPLEMENTED;
1454 }
1455
1456 /* Class 35 - Kernel Debugger Information */
1457 QSI_DEF(SystemKernelDebuggerInformation)
1458 {
1459 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1460
1461 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1462 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1463 {
1464 return STATUS_INFO_LENGTH_MISMATCH;
1465 }
1466
1467 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1468 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1469
1470 return STATUS_SUCCESS;
1471 }
1472
1473 /* Class 36 - Context Switch Information */
1474 QSI_DEF(SystemContextSwitchInformation)
1475 {
1476 /* FIXME */
1477 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1478 return STATUS_NOT_IMPLEMENTED;
1479 }
1480
1481 /* Class 37 - Registry Quota Information */
1482 QSI_DEF(SystemRegistryQuotaInformation)
1483 {
1484 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1485
1486 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1487 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1488 {
1489 return STATUS_INFO_LENGTH_MISMATCH;
1490 }
1491
1492 DPRINT1("Faking max registry size of 32 MB\n");
1493 srqi->RegistryQuotaAllowed = 0x2000000;
1494 srqi->RegistryQuotaUsed = 0x200000;
1495 srqi->PagedPoolSize = 0x200000;
1496
1497 return STATUS_SUCCESS;
1498 }
1499
1500 SSI_DEF(SystemRegistryQuotaInformation)
1501 {
1502 /* FIXME */
1503 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1504 return STATUS_NOT_IMPLEMENTED;
1505 }
1506
1507 /* Class 38 - Load And Call Image */
1508 SSI_DEF(SystemExtendServiceTableInformation)
1509 {
1510 UNICODE_STRING ImageName;
1511 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1512 PLDR_DATA_TABLE_ENTRY ModuleObject;
1513 NTSTATUS Status;
1514 PIMAGE_NT_HEADERS NtHeader;
1515 DRIVER_OBJECT Win32k;
1516 PDRIVER_INITIALIZE DriverInit;
1517 PVOID ImageBase;
1518 ULONG_PTR EntryPoint;
1519
1520 /* Validate the size */
1521 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1522
1523 /* Check who is calling */
1524 if (PreviousMode != KernelMode)
1525 {
1526 /* Make sure we can load drivers */
1527 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1528 {
1529 /* FIXME: We can't, fail */
1530 //return STATUS_PRIVILEGE_NOT_HELD;
1531 }
1532
1533 /* Probe and capture the driver name */
1534 ProbeAndCaptureUnicodeString(&ImageName, UserMode, Buffer);
1535
1536 /* Force kernel as previous mode */
1537 return ZwSetSystemInformation(SystemExtendServiceTableInformation,
1538 &ImageName,
1539 sizeof(ImageName));
1540 }
1541
1542 /* Just copy the string */
1543 ImageName = *(PUNICODE_STRING)Buffer;
1544
1545 /* Load the image */
1546 Status = MmLoadSystemImage(&ImageName,
1547 NULL,
1548 NULL,
1549 0,
1550 (PVOID)&ModuleObject,
1551 &ImageBase);
1552 if (!NT_SUCCESS(Status)) return Status;
1553
1554 /* Get the headers */
1555 NtHeader = RtlImageNtHeader(ImageBase);
1556 if (!NtHeader)
1557 {
1558 /* Fail */
1559 MmUnloadSystemImage(ModuleObject);
1560 return STATUS_INVALID_IMAGE_FORMAT;
1561 }
1562
1563 /* Get the entrypoint */
1564 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1565 EntryPoint += (ULONG_PTR)ImageBase;
1566 DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1567
1568 /* Create a dummy device */
1569 RtlZeroMemory(&Win32k, sizeof(Win32k));
1570 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1571 Win32k.DriverStart = ImageBase;
1572
1573 /* Call it */
1574 Status = (DriverInit)(&Win32k, NULL);
1575 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1576
1577 /* Unload if we failed */
1578 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
1579 return Status;
1580 }
1581
1582 /* Class 39 - Priority Separation */
1583 SSI_DEF(SystemPrioritySeperation)
1584 {
1585 /* FIXME */
1586 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1587 return STATUS_NOT_IMPLEMENTED;
1588 }
1589
1590 /* Class 40 - Plug Play Bus Information */
1591 QSI_DEF(SystemPlugPlayBusInformation)
1592 {
1593 /* FIXME */
1594 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1595 return STATUS_NOT_IMPLEMENTED;
1596 }
1597
1598 /* Class 41 - Dock Information */
1599 QSI_DEF(SystemDockInformation)
1600 {
1601 /* FIXME */
1602 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1603 return STATUS_NOT_IMPLEMENTED;
1604 }
1605
1606 /* Class 42 - Power Information */
1607 QSI_DEF(SystemPowerInformation)
1608 {
1609 /* FIXME */
1610 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1611 return STATUS_NOT_IMPLEMENTED;
1612 }
1613
1614 /* Class 43 - Processor Speed Information */
1615 QSI_DEF(SystemProcessorSpeedInformation)
1616 {
1617 /* FIXME */
1618 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1619 return STATUS_NOT_IMPLEMENTED;
1620 }
1621
1622 /* Class 44 - Current Time Zone Information */
1623 QSI_DEF(SystemCurrentTimeZoneInformation)
1624 {
1625 *ReqSize = sizeof(TIME_ZONE_INFORMATION);
1626
1627 if (sizeof(TIME_ZONE_INFORMATION) != Size)
1628 {
1629 return STATUS_INFO_LENGTH_MISMATCH;
1630 }
1631
1632 /* Copy the time zone information struct */
1633 memcpy(Buffer,
1634 &ExpTimeZoneInfo,
1635 sizeof(TIME_ZONE_INFORMATION));
1636
1637 return STATUS_SUCCESS;
1638 }
1639
1640
1641 SSI_DEF(SystemCurrentTimeZoneInformation)
1642 {
1643 /* Check user buffer's size */
1644 if (Size < sizeof(TIME_ZONE_INFORMATION))
1645 {
1646 return STATUS_INFO_LENGTH_MISMATCH;
1647 }
1648
1649 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1650 }
1651
1652
1653 /* Class 45 - Lookaside Information */
1654 QSI_DEF(SystemLookasideInformation)
1655 {
1656 /* FIXME */
1657 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1658 return STATUS_NOT_IMPLEMENTED;
1659 }
1660
1661
1662 /* Class 46 - Set time slip event */
1663 SSI_DEF(SystemSetTimeSlipEvent)
1664 {
1665 /* FIXME */
1666 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1667 return STATUS_NOT_IMPLEMENTED;
1668 }
1669
1670
1671 /* Class 47 - Create a new session (TSE) */
1672 SSI_DEF(SystemCreateSession)
1673 {
1674 /* FIXME */
1675 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1676 return STATUS_NOT_IMPLEMENTED;
1677 }
1678
1679
1680 /* Class 48 - Delete an existing session (TSE) */
1681 SSI_DEF(SystemDeleteSession)
1682 {
1683 /* FIXME */
1684 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1685 return STATUS_NOT_IMPLEMENTED;
1686 }
1687
1688
1689 /* Class 49 - UNKNOWN */
1690 QSI_DEF(SystemInvalidInfoClass4)
1691 {
1692 /* FIXME */
1693 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1694 return STATUS_NOT_IMPLEMENTED;
1695 }
1696
1697
1698 /* Class 50 - System range start address */
1699 QSI_DEF(SystemRangeStartInformation)
1700 {
1701 /* FIXME */
1702 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1703 return STATUS_NOT_IMPLEMENTED;
1704 }
1705
1706
1707 /* Class 51 - Driver verifier information */
1708 QSI_DEF(SystemVerifierInformation)
1709 {
1710 /* FIXME */
1711 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1712 return STATUS_NOT_IMPLEMENTED;
1713 }
1714
1715
1716 SSI_DEF(SystemVerifierInformation)
1717 {
1718 /* FIXME */
1719 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1720 return STATUS_NOT_IMPLEMENTED;
1721 }
1722
1723
1724 /* Class 52 - Add a driver verifier */
1725 SSI_DEF(SystemAddVerifier)
1726 {
1727 /* FIXME */
1728 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1729 return STATUS_NOT_IMPLEMENTED;
1730 }
1731
1732
1733 /* Class 53 - A session's processes */
1734 QSI_DEF(SystemSessionProcessesInformation)
1735 {
1736 /* FIXME */
1737 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1738 return STATUS_NOT_IMPLEMENTED;
1739 }
1740
1741
1742 /* Query/Set Calls Table */
1743 typedef
1744 struct _QSSI_CALLS
1745 {
1746 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1747 NTSTATUS (* Set) (PVOID,ULONG);
1748
1749 } QSSI_CALLS;
1750
1751 // QS Query & Set
1752 // QX Query
1753 // XS Set
1754 // XX unknown behaviour
1755 //
1756 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1757 #define SI_QX(n) {QSI_USE(n),NULL}
1758 #define SI_XS(n) {NULL,SSI_USE(n)}
1759 #define SI_XX(n) {NULL,NULL}
1760
1761 static
1762 QSSI_CALLS
1763 CallQS [] =
1764 {
1765 SI_QX(SystemBasicInformation),
1766 SI_QX(SystemProcessorInformation),
1767 SI_QX(SystemPerformanceInformation),
1768 SI_QX(SystemTimeOfDayInformation),
1769 SI_QX(SystemPathInformation), /* should be SI_XX */
1770 SI_QX(SystemProcessInformation),
1771 SI_QX(SystemCallCountInformation),
1772 SI_QX(SystemDeviceInformation),
1773 SI_QX(SystemProcessorPerformanceInformation),
1774 SI_QS(SystemFlagsInformation),
1775 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1776 SI_QX(SystemModuleInformation),
1777 SI_QX(SystemLocksInformation),
1778 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1779 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1780 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1781 SI_QX(SystemHandleInformation),
1782 SI_QX(SystemObjectInformation),
1783 SI_QX(SystemPageFileInformation),
1784 SI_QX(SystemVdmInstemulInformation),
1785 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1786 SI_QS(SystemFileCacheInformation),
1787 SI_QX(SystemPoolTagInformation),
1788 SI_QX(SystemInterruptInformation),
1789 SI_QS(SystemDpcBehaviourInformation),
1790 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1791 SI_XS(SystemLoadGdiDriverInformation),
1792 SI_XS(SystemUnloadGdiDriverInformation),
1793 SI_QS(SystemTimeAdjustmentInformation),
1794 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1795 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1796 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1797 SI_QX(SystemCrashDumpInformation),
1798 SI_QX(SystemExceptionInformation),
1799 SI_QX(SystemCrashDumpStateInformation),
1800 SI_QX(SystemKernelDebuggerInformation),
1801 SI_QX(SystemContextSwitchInformation),
1802 SI_QS(SystemRegistryQuotaInformation),
1803 SI_XS(SystemExtendServiceTableInformation),
1804 SI_XS(SystemPrioritySeperation),
1805 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1806 SI_QX(SystemDockInformation), /* it should be SI_XX */
1807 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1808 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1809 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1810 SI_QX(SystemLookasideInformation),
1811 SI_XS(SystemSetTimeSlipEvent),
1812 SI_XS(SystemCreateSession),
1813 SI_XS(SystemDeleteSession),
1814 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1815 SI_QX(SystemRangeStartInformation),
1816 SI_QS(SystemVerifierInformation),
1817 SI_XS(SystemAddVerifier),
1818 SI_QX(SystemSessionProcessesInformation)
1819 };
1820
1821 C_ASSERT(SystemBasicInformation == 0);
1822 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1823 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1824
1825 /*
1826 * @implemented
1827 */
1828 NTSTATUS NTAPI
1829 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1830 OUT PVOID SystemInformation,
1831 IN ULONG Length,
1832 OUT PULONG UnsafeResultLength)
1833 {
1834 KPROCESSOR_MODE PreviousMode;
1835 ULONG ResultLength;
1836 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1837
1838 PAGED_CODE();
1839
1840 PreviousMode = ExGetPreviousMode();
1841
1842 _SEH2_TRY
1843 {
1844 if (PreviousMode != KernelMode)
1845 {
1846 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1847 ProbeForWrite(SystemInformation, Length, 1);
1848 if (UnsafeResultLength != NULL)
1849 ProbeForWriteUlong(UnsafeResultLength);
1850 }
1851
1852 /*
1853 * Check the request is valid.
1854 */
1855 if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
1856 {
1857 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
1858 }
1859
1860 if (NULL != CallQS [SystemInformationClass].Query)
1861 {
1862 /*
1863 * Hand the request to a subhandler.
1864 */
1865 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1866 Length,
1867 &ResultLength);
1868 if (UnsafeResultLength != NULL)
1869 {
1870 if (PreviousMode != KernelMode)
1871 {
1872 *UnsafeResultLength = ResultLength;
1873 }
1874 else
1875 {
1876 *UnsafeResultLength = ResultLength;
1877 }
1878 }
1879 }
1880 }
1881 _SEH2_EXCEPT(ExSystemExceptionFilter())
1882 {
1883 FStatus = _SEH2_GetExceptionCode();
1884 }
1885 _SEH2_END;
1886
1887 return FStatus;
1888 }
1889
1890
1891 NTSTATUS
1892 NTAPI
1893 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1894 IN PVOID SystemInformation,
1895 IN ULONG SystemInformationLength)
1896 {
1897 PAGED_CODE();
1898
1899 /*
1900 * If called from user mode, check
1901 * possible unsafe arguments.
1902 */
1903 #if 0
1904 if (KernelMode != KeGetPreviousMode())
1905 {
1906 // Check arguments
1907 //ProbeForWrite(
1908 // SystemInformation,
1909 // Length
1910 // );
1911 //ProbeForWrite(
1912 // ResultLength,
1913 // sizeof (ULONG)
1914 // );
1915 }
1916 #endif
1917 /*
1918 * Check the request is valid.
1919 */
1920 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
1921 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
1922 {
1923 if (NULL != CallQS [SystemInformationClass].Set)
1924 {
1925 /*
1926 * Hand the request to a subhandler.
1927 */
1928 return CallQS [SystemInformationClass].Set(SystemInformation,
1929 SystemInformationLength);
1930 }
1931 }
1932
1933 return STATUS_INVALID_INFO_CLASS;
1934 }
1935
1936
1937 NTSTATUS
1938 NTAPI
1939 NtFlushInstructionCache(IN HANDLE ProcessHandle,
1940 IN PVOID BaseAddress,
1941 IN ULONG NumberOfBytesToFlush)
1942 {
1943 PAGED_CODE();
1944
1945 #if defined(_M_IX86)
1946 __wbinvd();
1947 #elif defined(_M_PPC)
1948 __asm__ __volatile__("tlbsync");
1949 #elif defined(_M_MIPS)
1950 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1951 for (;;);
1952 #elif defined(_M_ARM)
1953 __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
1954 #else
1955 #error Unknown architecture
1956 #endif
1957 return STATUS_SUCCESS;
1958 }
1959
1960 ULONG
1961 NTAPI
1962 NtGetCurrentProcessorNumber(VOID)
1963 {
1964 /* Just return the CPU */
1965 return KeGetCurrentProcessorNumber();
1966 }
1967
1968 /* EOF */