mbctype.h: fix broken _mbctype[] and _mbcasemap[] declarations
[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)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 Pcr = CONTAINING_RECORD(Prcb, KPCR, Prcb);
1207 #ifdef _M_ARM // This code should probably be done differently
1208 sii->ContextSwitches = Pcr->ContextSwitches;
1209 #else
1210 sii->ContextSwitches = ((PKIPCR)Pcr)->ContextSwitches;
1211 #endif
1212 sii->DpcCount = Prcb->DpcData[0].DpcCount;
1213 sii->DpcRate = Prcb->DpcRequestRate;
1214 sii->TimeIncrement = ti;
1215 sii->DpcBypassCount = 0;
1216 sii->ApcBypassCount = 0;
1217 sii++;
1218 }
1219
1220 return STATUS_SUCCESS;
1221 }
1222
1223 /* Class 24 - DPC Behaviour Information */
1224 QSI_DEF(SystemDpcBehaviourInformation)
1225 {
1226 /* FIXME */
1227 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1228 return (STATUS_NOT_IMPLEMENTED);
1229 }
1230
1231 SSI_DEF(SystemDpcBehaviourInformation)
1232 {
1233 /* FIXME */
1234 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1235 return (STATUS_NOT_IMPLEMENTED);
1236 }
1237
1238 /* Class 25 - Full Memory Information */
1239 QSI_DEF(SystemFullMemoryInformation)
1240 {
1241 PULONG Spi = (PULONG) Buffer;
1242
1243 PEPROCESS TheIdleProcess;
1244
1245 * ReqSize = sizeof (ULONG);
1246
1247 if (sizeof (ULONG) != Size)
1248 {
1249 return (STATUS_INFO_LENGTH_MISMATCH);
1250 }
1251 DPRINT("SystemFullMemoryInformation\n");
1252
1253 TheIdleProcess = PsIdleProcess;
1254
1255 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1256 TheIdleProcess->UniqueProcessId,
1257 TheIdleProcess->Pcb.KernelTime,
1258 MiFreeSwapPages,
1259 MiUsedSwapPages);
1260
1261 #ifndef NDEBUG
1262 MmPrintMemoryStatistic();
1263 #endif
1264
1265 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1266
1267 return (STATUS_SUCCESS);
1268 }
1269
1270 /* Class 26 - Load Image */
1271 SSI_DEF(SystemLoadGdiDriverInformation)
1272 {
1273 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1274 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1275 UNICODE_STRING ImageName;
1276 PVOID ImageBase;
1277 PLDR_DATA_TABLE_ENTRY ModuleObject;
1278 ULONG_PTR EntryPoint;
1279 NTSTATUS Status;
1280 ULONG DirSize;
1281 PIMAGE_NT_HEADERS NtHeader;
1282
1283 /* Validate size */
1284 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1285 {
1286 /* Incorrect buffer length, fail */
1287 return STATUS_INFO_LENGTH_MISMATCH;
1288 }
1289
1290 /* Only kernel-mode can call this function */
1291 if (PreviousMode != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1292
1293 /* Load the driver */
1294 ImageName = DriverInfo->DriverName;
1295 Status = MmLoadSystemImage(&ImageName,
1296 NULL,
1297 NULL,
1298 0,
1299 (PVOID)&ModuleObject,
1300 &ImageBase);
1301 if (!NT_SUCCESS(Status)) return Status;
1302
1303 /* Return the export pointer */
1304 DriverInfo->ExportSectionPointer =
1305 RtlImageDirectoryEntryToData(ImageBase,
1306 TRUE,
1307 IMAGE_DIRECTORY_ENTRY_EXPORT,
1308 &DirSize);
1309
1310 /* Get the entrypoint */
1311 NtHeader = RtlImageNtHeader(ImageBase);
1312 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1313 EntryPoint += (ULONG_PTR)ImageBase;
1314
1315 /* Save other data */
1316 DriverInfo->ImageAddress = ImageBase;
1317 DriverInfo->SectionPointer = NULL;
1318 DriverInfo->EntryPoint = (PVOID)EntryPoint;
1319 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1320
1321 /* All is good */
1322 return STATUS_SUCCESS;
1323 }
1324
1325 /* Class 27 - Unload Image */
1326 SSI_DEF(SystemUnloadGdiDriverInformation)
1327 {
1328 PLDR_DATA_TABLE_ENTRY LdrEntry;
1329 PLIST_ENTRY NextEntry;
1330 PVOID BaseAddr = *((PVOID*)Buffer);
1331
1332 if(Size != sizeof(PVOID))
1333 return STATUS_INFO_LENGTH_MISMATCH;
1334
1335 if(KeGetPreviousMode() != KernelMode)
1336 return STATUS_PRIVILEGE_NOT_HELD;
1337
1338 // Scan the module list
1339 NextEntry = PsLoadedModuleList.Flink;
1340 while(NextEntry != &PsLoadedModuleList)
1341 {
1342 LdrEntry = CONTAINING_RECORD(NextEntry,
1343 LDR_DATA_TABLE_ENTRY,
1344 InLoadOrderLinks);
1345
1346 if (LdrEntry->DllBase == BaseAddr)
1347 {
1348 // Found it.
1349 break;
1350 }
1351
1352 NextEntry = NextEntry->Flink;
1353 }
1354
1355 // Check if we found the image
1356 if(NextEntry != &PsLoadedModuleList)
1357 {
1358 return MmUnloadSystemImage(LdrEntry);
1359 }
1360 else
1361 {
1362 DPRINT1("Image 0x%x not found.\n", BaseAddr);
1363 return STATUS_DLL_NOT_FOUND;
1364 }
1365
1366 }
1367
1368 /* Class 28 - Time Adjustment Information */
1369 QSI_DEF(SystemTimeAdjustmentInformation)
1370 {
1371 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION) > Size)
1372 {
1373 * ReqSize = sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION);
1374 return (STATUS_INFO_LENGTH_MISMATCH);
1375 }
1376 /* FIXME: */
1377 DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1378 return (STATUS_NOT_IMPLEMENTED);
1379 }
1380
1381 SSI_DEF(SystemTimeAdjustmentInformation)
1382 {
1383 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION) > Size)
1384 {
1385 return (STATUS_INFO_LENGTH_MISMATCH);
1386 }
1387 /* FIXME: */
1388 DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1389 return (STATUS_NOT_IMPLEMENTED);
1390 }
1391
1392 /* Class 29 - Summary Memory Information */
1393 QSI_DEF(SystemSummaryMemoryInformation)
1394 {
1395 /* FIXME */
1396 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1397 return (STATUS_NOT_IMPLEMENTED);
1398 }
1399
1400 /* Class 30 - Next Event Id Information */
1401 QSI_DEF(SystemNextEventIdInformation)
1402 {
1403 /* FIXME */
1404 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1405 return (STATUS_NOT_IMPLEMENTED);
1406 }
1407
1408 /* Class 31 - Event Ids Information */
1409 QSI_DEF(SystemEventIdsInformation)
1410 {
1411 /* FIXME */
1412 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1413 return (STATUS_NOT_IMPLEMENTED);
1414 }
1415
1416 /* Class 32 - Crash Dump Information */
1417 QSI_DEF(SystemCrashDumpInformation)
1418 {
1419 /* FIXME */
1420 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1421 return (STATUS_NOT_IMPLEMENTED);
1422 }
1423
1424 /* Class 33 - Exception Information */
1425 QSI_DEF(SystemExceptionInformation)
1426 {
1427 /* FIXME */
1428 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1429 return (STATUS_NOT_IMPLEMENTED);
1430 }
1431
1432 /* Class 34 - Crash Dump State Information */
1433 QSI_DEF(SystemCrashDumpStateInformation)
1434 {
1435 /* FIXME */
1436 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1437 return (STATUS_NOT_IMPLEMENTED);
1438 }
1439
1440 /* Class 35 - Kernel Debugger Information */
1441 QSI_DEF(SystemKernelDebuggerInformation)
1442 {
1443 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1444
1445 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1446 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1447 {
1448 return STATUS_INFO_LENGTH_MISMATCH;
1449 }
1450
1451 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1452 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1453
1454 return STATUS_SUCCESS;
1455 }
1456
1457 /* Class 36 - Context Switch Information */
1458 QSI_DEF(SystemContextSwitchInformation)
1459 {
1460 /* FIXME */
1461 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1462 return (STATUS_NOT_IMPLEMENTED);
1463 }
1464
1465 /* Class 37 - Registry Quota Information */
1466 QSI_DEF(SystemRegistryQuotaInformation)
1467 {
1468 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1469
1470 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1471 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1472 {
1473 return STATUS_INFO_LENGTH_MISMATCH;
1474 }
1475
1476 DPRINT1("Faking max registry size of 32 MB\n");
1477 srqi->RegistryQuotaAllowed = 0x2000000;
1478 srqi->RegistryQuotaUsed = 0x200000;
1479 srqi->PagedPoolSize = 0x200000;
1480
1481 return STATUS_SUCCESS;
1482 }
1483
1484 SSI_DEF(SystemRegistryQuotaInformation)
1485 {
1486 /* FIXME */
1487 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1488 return (STATUS_NOT_IMPLEMENTED);
1489 }
1490
1491 /* Class 38 - Load And Call Image */
1492 SSI_DEF(SystemExtendServiceTableInformation)
1493 {
1494 UNICODE_STRING ImageName;
1495 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1496 PLDR_DATA_TABLE_ENTRY ModuleObject;
1497 NTSTATUS Status;
1498 PIMAGE_NT_HEADERS NtHeader;
1499 DRIVER_OBJECT Win32k;
1500 PDRIVER_INITIALIZE DriverInit;
1501 PVOID ImageBase;
1502 ULONG_PTR EntryPoint;
1503
1504 /* Validate the size */
1505 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1506
1507 /* Check who is calling */
1508 if (PreviousMode != KernelMode)
1509 {
1510 /* Make sure we can load drivers */
1511 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1512 {
1513 /* FIXME: We can't, fail */
1514 //return STATUS_PRIVILEGE_NOT_HELD;
1515 }
1516
1517 /* Probe and capture the driver name */
1518 ProbeAndCaptureUnicodeString(&ImageName, UserMode, Buffer);
1519
1520 /* Force kernel as previous mode */
1521 return ZwSetSystemInformation(SystemExtendServiceTableInformation,
1522 &ImageName,
1523 sizeof(ImageName));
1524 }
1525
1526 /* Just copy the string */
1527 ImageName = *(PUNICODE_STRING)Buffer;
1528
1529 /* Load the image */
1530 Status = MmLoadSystemImage(&ImageName,
1531 NULL,
1532 NULL,
1533 0,
1534 (PVOID)&ModuleObject,
1535 &ImageBase);
1536 if (!NT_SUCCESS(Status)) return Status;
1537
1538 /* Get the headers */
1539 NtHeader = RtlImageNtHeader(ImageBase);
1540 if (!NtHeader)
1541 {
1542 /* Fail */
1543 MmUnloadSystemImage(ModuleObject);
1544 return STATUS_INVALID_IMAGE_FORMAT;
1545 }
1546
1547 /* Get the entrypoint */
1548 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1549 EntryPoint += (ULONG_PTR)ImageBase;
1550 DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1551
1552 /* Create a dummy device */
1553 RtlZeroMemory(&Win32k, sizeof(Win32k));
1554 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1555 Win32k.DriverStart = ImageBase;
1556
1557 /* Call it */
1558 Status = (DriverInit)(&Win32k, NULL);
1559 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1560
1561 /* Unload if we failed */
1562 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
1563 return Status;
1564 }
1565
1566 /* Class 39 - Priority Separation */
1567 SSI_DEF(SystemPrioritySeperation)
1568 {
1569 /* FIXME */
1570 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1571 return (STATUS_NOT_IMPLEMENTED);
1572 }
1573
1574 /* Class 40 - Plug Play Bus Information */
1575 QSI_DEF(SystemPlugPlayBusInformation)
1576 {
1577 /* FIXME */
1578 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1579 return (STATUS_NOT_IMPLEMENTED);
1580 }
1581
1582 /* Class 41 - Dock Information */
1583 QSI_DEF(SystemDockInformation)
1584 {
1585 /* FIXME */
1586 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1587 return (STATUS_NOT_IMPLEMENTED);
1588 }
1589
1590 /* Class 42 - Power Information */
1591 QSI_DEF(SystemPowerInformation)
1592 {
1593 /* FIXME */
1594 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1595 return (STATUS_NOT_IMPLEMENTED);
1596 }
1597
1598 /* Class 43 - Processor Speed Information */
1599 QSI_DEF(SystemProcessorSpeedInformation)
1600 {
1601 /* FIXME */
1602 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1603 return (STATUS_NOT_IMPLEMENTED);
1604 }
1605
1606 /* Class 44 - Current Time Zone Information */
1607 QSI_DEF(SystemCurrentTimeZoneInformation)
1608 {
1609 * ReqSize = sizeof (TIME_ZONE_INFORMATION);
1610
1611 if (sizeof (TIME_ZONE_INFORMATION) != Size)
1612 {
1613 return STATUS_INFO_LENGTH_MISMATCH;
1614 }
1615
1616 /* Copy the time zone information struct */
1617 memcpy(Buffer,
1618 &ExpTimeZoneInfo,
1619 sizeof(TIME_ZONE_INFORMATION));
1620
1621 return STATUS_SUCCESS;
1622 }
1623
1624
1625 SSI_DEF(SystemCurrentTimeZoneInformation)
1626 {
1627 /* Check user buffer's size */
1628 if (Size < sizeof (TIME_ZONE_INFORMATION))
1629 {
1630 return STATUS_INFO_LENGTH_MISMATCH;
1631 }
1632
1633 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1634 }
1635
1636
1637 /* Class 45 - Lookaside Information */
1638 QSI_DEF(SystemLookasideInformation)
1639 {
1640 /* FIXME */
1641 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1642 return (STATUS_NOT_IMPLEMENTED);
1643 }
1644
1645
1646 /* Class 46 - Set time slip event */
1647 SSI_DEF(SystemSetTimeSlipEvent)
1648 {
1649 /* FIXME */
1650 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1651 return (STATUS_NOT_IMPLEMENTED);
1652 }
1653
1654
1655 /* Class 47 - Create a new session (TSE) */
1656 SSI_DEF(SystemCreateSession)
1657 {
1658 /* FIXME */
1659 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1660 return (STATUS_NOT_IMPLEMENTED);
1661 }
1662
1663
1664 /* Class 48 - Delete an existing session (TSE) */
1665 SSI_DEF(SystemDeleteSession)
1666 {
1667 /* FIXME */
1668 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1669 return (STATUS_NOT_IMPLEMENTED);
1670 }
1671
1672
1673 /* Class 49 - UNKNOWN */
1674 QSI_DEF(SystemInvalidInfoClass4)
1675 {
1676 /* FIXME */
1677 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1678 return (STATUS_NOT_IMPLEMENTED);
1679 }
1680
1681
1682 /* Class 50 - System range start address */
1683 QSI_DEF(SystemRangeStartInformation)
1684 {
1685 /* FIXME */
1686 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1687 return (STATUS_NOT_IMPLEMENTED);
1688 }
1689
1690
1691 /* Class 51 - Driver verifier information */
1692 QSI_DEF(SystemVerifierInformation)
1693 {
1694 /* FIXME */
1695 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1696 return (STATUS_NOT_IMPLEMENTED);
1697 }
1698
1699
1700 SSI_DEF(SystemVerifierInformation)
1701 {
1702 /* FIXME */
1703 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1704 return (STATUS_NOT_IMPLEMENTED);
1705 }
1706
1707
1708 /* Class 52 - Add a driver verifier */
1709 SSI_DEF(SystemAddVerifier)
1710 {
1711 /* FIXME */
1712 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1713 return (STATUS_NOT_IMPLEMENTED);
1714 }
1715
1716
1717 /* Class 53 - A session's processes */
1718 QSI_DEF(SystemSessionProcessesInformation)
1719 {
1720 /* FIXME */
1721 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1722 return (STATUS_NOT_IMPLEMENTED);
1723 }
1724
1725
1726 /* Query/Set Calls Table */
1727 typedef
1728 struct _QSSI_CALLS
1729 {
1730 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1731 NTSTATUS (* Set) (PVOID,ULONG);
1732
1733 } QSSI_CALLS;
1734
1735 // QS Query & Set
1736 // QX Query
1737 // XS Set
1738 // XX unknown behaviour
1739 //
1740 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1741 #define SI_QX(n) {QSI_USE(n),NULL}
1742 #define SI_XS(n) {NULL,SSI_USE(n)}
1743 #define SI_XX(n) {NULL,NULL}
1744
1745 static
1746 QSSI_CALLS
1747 CallQS [] =
1748 {
1749 SI_QX(SystemBasicInformation),
1750 SI_QX(SystemProcessorInformation),
1751 SI_QX(SystemPerformanceInformation),
1752 SI_QX(SystemTimeOfDayInformation),
1753 SI_QX(SystemPathInformation), /* should be SI_XX */
1754 SI_QX(SystemProcessInformation),
1755 SI_QX(SystemCallCountInformation),
1756 SI_QX(SystemDeviceInformation),
1757 SI_QX(SystemProcessorPerformanceInformation),
1758 SI_QS(SystemFlagsInformation),
1759 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1760 SI_QX(SystemModuleInformation),
1761 SI_QX(SystemLocksInformation),
1762 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1763 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1764 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1765 SI_QX(SystemHandleInformation),
1766 SI_QX(SystemObjectInformation),
1767 SI_QX(SystemPageFileInformation),
1768 SI_QX(SystemVdmInstemulInformation),
1769 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1770 SI_QS(SystemFileCacheInformation),
1771 SI_QX(SystemPoolTagInformation),
1772 SI_QX(SystemInterruptInformation),
1773 SI_QS(SystemDpcBehaviourInformation),
1774 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1775 SI_XS(SystemLoadGdiDriverInformation),
1776 SI_XS(SystemUnloadGdiDriverInformation),
1777 SI_QS(SystemTimeAdjustmentInformation),
1778 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1779 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1780 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1781 SI_QX(SystemCrashDumpInformation),
1782 SI_QX(SystemExceptionInformation),
1783 SI_QX(SystemCrashDumpStateInformation),
1784 SI_QX(SystemKernelDebuggerInformation),
1785 SI_QX(SystemContextSwitchInformation),
1786 SI_QS(SystemRegistryQuotaInformation),
1787 SI_XS(SystemExtendServiceTableInformation),
1788 SI_XS(SystemPrioritySeperation),
1789 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1790 SI_QX(SystemDockInformation), /* it should be SI_XX */
1791 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1792 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1793 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1794 SI_QX(SystemLookasideInformation),
1795 SI_XS(SystemSetTimeSlipEvent),
1796 SI_XS(SystemCreateSession),
1797 SI_XS(SystemDeleteSession),
1798 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1799 SI_QX(SystemRangeStartInformation),
1800 SI_QS(SystemVerifierInformation),
1801 SI_XS(SystemAddVerifier),
1802 SI_QX(SystemSessionProcessesInformation)
1803 };
1804
1805 C_ASSERT(SystemBasicInformation == 0);
1806 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1807 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1808
1809 /*
1810 * @implemented
1811 */
1812 NTSTATUS NTAPI
1813 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1814 OUT PVOID SystemInformation,
1815 IN ULONG Length,
1816 OUT PULONG UnsafeResultLength)
1817 {
1818 KPROCESSOR_MODE PreviousMode;
1819 ULONG ResultLength;
1820 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1821
1822 PAGED_CODE();
1823
1824 PreviousMode = ExGetPreviousMode();
1825
1826 _SEH2_TRY
1827 {
1828 if (PreviousMode != KernelMode)
1829 {
1830 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1831 ProbeForWrite(SystemInformation, Length, 1);
1832 if (UnsafeResultLength != NULL)
1833 ProbeForWriteUlong(UnsafeResultLength);
1834 }
1835
1836 /*
1837 * Check the request is valid.
1838 */
1839 if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
1840 {
1841 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
1842 }
1843
1844 if (NULL != CallQS [SystemInformationClass].Query)
1845 {
1846 /*
1847 * Hand the request to a subhandler.
1848 */
1849 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1850 Length,
1851 &ResultLength);
1852 if (UnsafeResultLength != NULL)
1853 {
1854 if (PreviousMode != KernelMode)
1855 {
1856 *UnsafeResultLength = ResultLength;
1857 }
1858 else
1859 {
1860 *UnsafeResultLength = ResultLength;
1861 }
1862 }
1863 }
1864 }
1865 _SEH2_EXCEPT(ExSystemExceptionFilter())
1866 {
1867 FStatus = _SEH2_GetExceptionCode();
1868 }
1869 _SEH2_END;
1870
1871 return (FStatus);
1872 }
1873
1874
1875 NTSTATUS
1876 NTAPI
1877 NtSetSystemInformation (
1878 IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1879 IN PVOID SystemInformation,
1880 IN ULONG SystemInformationLength
1881 )
1882 {
1883 PAGED_CODE();
1884
1885 /*
1886 * If called from user mode, check
1887 * possible unsafe arguments.
1888 */
1889 #if 0
1890 if (KernelMode != KeGetPreviousMode())
1891 {
1892 // Check arguments
1893 //ProbeForWrite(
1894 // SystemInformation,
1895 // Length
1896 // );
1897 //ProbeForWrite(
1898 // ResultLength,
1899 // sizeof (ULONG)
1900 // );
1901 }
1902 #endif
1903 /*
1904 * Check the request is valid.
1905 */
1906 if ( (SystemInformationClass >= MIN_SYSTEM_INFO_CLASS)
1907 && (SystemInformationClass < MAX_SYSTEM_INFO_CLASS)
1908 )
1909 {
1910 if (NULL != CallQS [SystemInformationClass].Set)
1911 {
1912 /*
1913 * Hand the request to a subhandler.
1914 */
1915 return CallQS [SystemInformationClass].Set (
1916 SystemInformation,
1917 SystemInformationLength
1918 );
1919 }
1920 }
1921 return (STATUS_INVALID_INFO_CLASS);
1922 }
1923
1924
1925 NTSTATUS
1926 NTAPI
1927 NtFlushInstructionCache (
1928 IN HANDLE ProcessHandle,
1929 IN PVOID BaseAddress,
1930 IN ULONG NumberOfBytesToFlush
1931 )
1932 {
1933 PAGED_CODE();
1934
1935 #if defined(_M_IX86)
1936 __wbinvd();
1937 #elif defined(_M_PPC)
1938 __asm__ __volatile__("tlbsync");
1939 #elif defined(_M_MIPS)
1940 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1941 for (;;);
1942 #elif defined(_M_ARM)
1943 __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
1944 #else
1945 #error Unknown architecture
1946 #endif
1947 return STATUS_SUCCESS;
1948 }
1949
1950 ULONG
1951 NTAPI
1952 NtGetCurrentProcessorNumber(VOID)
1953 {
1954 /* Just return the CPU */
1955 return KeGetCurrentProcessorNumber();
1956 }
1957
1958 /* EOF */