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