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