- Change of names of variables
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/sysinfo.c
5 * PURPOSE: System information functions
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Aleksey Bragin (aleksey@reactos.org)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16
17 VOID MmPrintMemoryStatistic(VOID);
18
19 FAST_MUTEX ExpEnvironmentLock;
20 ERESOURCE ExpFirmwareTableResource;
21 LIST_ENTRY ExpFirmwareTableProviderListHead;
22
23 NTSTATUS
24 NTAPI
25 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
26 IN PLIST_ENTRY UserModeList,
27 OUT PRTL_PROCESS_MODULES Modules,
28 IN ULONG Length,
29 OUT PULONG ReturnLength)
30 {
31 NTSTATUS Status = STATUS_SUCCESS;
32 ULONG RequiredLength;
33 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
34 PLDR_DATA_TABLE_ENTRY LdrEntry;
35 ANSI_STRING ModuleName;
36 ULONG ModuleCount = 0;
37 PLIST_ENTRY NextEntry;
38 PCHAR p;
39
40 /* Setup defaults */
41 RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules);
42 ModuleInfo = &Modules->Modules[0];
43
44 /* Loop the kernel list */
45 NextEntry = KernelModeList->Flink;
46 while (NextEntry != KernelModeList)
47 {
48 /* Get the entry */
49 LdrEntry = CONTAINING_RECORD(NextEntry,
50 LDR_DATA_TABLE_ENTRY,
51 InLoadOrderLinks);
52
53 /* Update size and check if we can manage one more entry */
54 RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
55 if (Length >= RequiredLength)
56 {
57 /* Fill it out */
58 ModuleInfo->MappedBase = NULL;
59 ModuleInfo->ImageBase = LdrEntry->DllBase;
60 ModuleInfo->ImageSize = LdrEntry->SizeOfImage;
61 ModuleInfo->Flags = LdrEntry->Flags;
62 ModuleInfo->LoadCount = LdrEntry->LoadCount;
63 ModuleInfo->LoadOrderIndex = (USHORT)ModuleCount;
64 ModuleInfo->InitOrderIndex = 0;
65
66 /* Setup name */
67 RtlInitEmptyAnsiString(&ModuleName,
68 ModuleInfo->FullPathName,
69 sizeof(ModuleInfo->FullPathName));
70
71 /* Convert it */
72 Status = RtlUnicodeStringToAnsiString(&ModuleName,
73 &LdrEntry->FullDllName,
74 FALSE);
75 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
76 {
77 /* Calculate offset to name */
78 p = ModuleName.Buffer + ModuleName.Length;
79 while ((p > ModuleName.Buffer) && (*--p))
80 {
81 /* Check if we found the separator */
82 if (*p == OBJ_NAME_PATH_SEPARATOR)
83 {
84 /* We did, break out */
85 p++;
86 break;
87 }
88 }
89
90 /* Set the offset */
91 ModuleInfo->OffsetToFileName = p - ModuleName.Buffer;
92 }
93 else
94 {
95 /* Return empty name */
96 ModuleInfo->FullPathName[0] = ANSI_NULL;
97 ModuleInfo->OffsetToFileName = 0;
98 }
99
100 /* Go to the next module */
101 ModuleInfo++;
102 }
103 else
104 {
105 /* Set error code */
106 Status = STATUS_INFO_LENGTH_MISMATCH;
107 }
108
109 /* Update count and move to next entry */
110 ModuleCount++;
111 NextEntry = NextEntry->Flink;
112 }
113
114 /* Check if caller also wanted user modules */
115 if (UserModeList)
116 {
117 /* FIXME: TODO */
118 DPRINT1("User-mode list not yet supported in ReactOS!\n");
119 }
120
121 /* Update return length */
122 if (ReturnLength) *ReturnLength = RequiredLength;
123
124 /* Validate the length again */
125 if (Length >= FIELD_OFFSET(RTL_PROCESS_MODULES, Modules))
126 {
127 /* Set the final count */
128 Modules->NumberOfModules = ModuleCount;
129 }
130 else
131 {
132 /* Otherwise, we failed */
133 Status = STATUS_INFO_LENGTH_MISMATCH;
134 }
135
136 /* Done */
137 return Status;
138 }
139
140 /* FUNCTIONS *****************************************************************/
141
142 /*
143 * @implemented
144 */
145 #undef ExGetPreviousMode
146 KPROCESSOR_MODE
147 NTAPI
148 ExGetPreviousMode (VOID)
149 {
150 return KeGetPreviousMode();
151 }
152
153 /*
154 * @implemented
155 */
156 VOID
157 NTAPI
158 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage)
159 {
160 PKPRCB Prcb;
161 ULONG TotalTime;
162 ULONGLONG ScaledIdle;
163
164 Prcb = KeGetCurrentPrcb();
165
166 ScaledIdle = Prcb->IdleThread->KernelTime * 100;
167 TotalTime = Prcb->KernelTime + Prcb->UserTime;
168 if (TotalTime != 0)
169 *CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime));
170 else
171 *CpuUsage = 0;
172 }
173
174 /*
175 * @implemented
176 */
177 VOID
178 NTAPI
179 ExGetCurrentProcessorCounts(PULONG ThreadKernelTime,
180 PULONG TotalCpuTime,
181 PULONG ProcessorNumber)
182 {
183 PKPRCB Prcb;
184
185 Prcb = KeGetCurrentPrcb();
186
187 *ThreadKernelTime = Prcb->KernelTime + Prcb->UserTime;
188 *TotalCpuTime = Prcb->CurrentThread->KernelTime;
189 *ProcessorNumber = KeGetCurrentProcessorNumber();
190 }
191
192 /*
193 * @implemented
194 */
195 BOOLEAN
196 NTAPI
197 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
198 {
199 /* Quick check to see if it exists at all */
200 if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
201
202 /* Return our support for it */
203 return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
204 }
205
206 /*
207 * @implemented
208 */
209 BOOLEAN
210 NTAPI
211 ExVerifySuite(SUITE_TYPE SuiteType)
212 {
213 if (SuiteType == Personal) return TRUE;
214 return FALSE;
215 }
216
217 NTSTATUS
218 NTAPI
219 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName,
220 OUT PWSTR ValueBuffer,
221 IN ULONG ValueBufferLength,
222 IN OUT PULONG ReturnLength OPTIONAL)
223 {
224 ANSI_STRING AName;
225 UNICODE_STRING WName;
226 ARC_STATUS Result;
227 PCH Value;
228 ANSI_STRING AValue;
229 UNICODE_STRING WValue;
230 KPROCESSOR_MODE PreviousMode;
231 NTSTATUS Status = STATUS_SUCCESS;
232
233 PAGED_CODE();
234
235 PreviousMode = ExGetPreviousMode();
236
237 if (PreviousMode != KernelMode)
238 {
239 _SEH2_TRY
240 {
241 ProbeForRead(VariableName,
242 sizeof(UNICODE_STRING),
243 sizeof(ULONG));
244
245 ProbeForWrite(ValueBuffer,
246 ValueBufferLength,
247 sizeof(WCHAR));
248
249 if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength);
250 }
251 _SEH2_EXCEPT(ExSystemExceptionFilter())
252 {
253 Status = _SEH2_GetExceptionCode();
254 }
255 _SEH2_END;
256
257 if (!NT_SUCCESS(Status)) return Status;
258 }
259
260 /*
261 * Copy the name to kernel space if necessary and convert it to ANSI.
262 */
263 Status = ProbeAndCaptureUnicodeString(&WName,
264 PreviousMode,
265 VariableName);
266 if (NT_SUCCESS(Status))
267 {
268 /*
269 * according to ntinternals the SeSystemEnvironmentName privilege is required!
270 */
271 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
272 PreviousMode))
273 {
274 ReleaseCapturedUnicodeString(&WName, PreviousMode);
275 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
276 return STATUS_PRIVILEGE_NOT_HELD;
277 }
278
279 /*
280 * convert the value name to ansi
281 */
282 Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
283 ReleaseCapturedUnicodeString(&WName, PreviousMode);
284
285 if (!NT_SUCCESS(Status)) return Status;
286
287 /*
288 * Create a temporary buffer for the value
289 */
290 Value = ExAllocatePool(NonPagedPool, ValueBufferLength);
291 if (Value == NULL)
292 {
293 RtlFreeAnsiString(&AName);
294 return STATUS_INSUFFICIENT_RESOURCES;
295 }
296
297 /*
298 * Get the environment variable
299 */
300 Result = HalGetEnvironmentVariable(AName.Buffer,
301 (USHORT)ValueBufferLength,
302 Value);
303 if (!Result)
304 {
305 RtlFreeAnsiString(&AName);
306 ExFreePool(Value);
307 return STATUS_UNSUCCESSFUL;
308 }
309
310 /*
311 * Convert the result to UNICODE, protect with SEH in case the value buffer
312 * isn't NULL-terminated!
313 */
314 _SEH2_TRY
315 {
316 RtlInitAnsiString(&AValue, Value);
317 Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
318 }
319 _SEH2_EXCEPT(ExSystemExceptionFilter())
320 {
321 Status = _SEH2_GetExceptionCode();
322 }
323 _SEH2_END;
324
325 if (NT_SUCCESS(Status))
326 {
327 /*
328 * Copy the result back to the caller.
329 */
330 _SEH2_TRY
331 {
332 RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
333 ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
334 if (ReturnLength != NULL)
335 {
336 *ReturnLength = WValue.Length + sizeof(WCHAR);
337 }
338
339 Status = STATUS_SUCCESS;
340 }
341 _SEH2_EXCEPT(ExSystemExceptionFilter())
342 {
343 Status = _SEH2_GetExceptionCode();
344 }
345 _SEH2_END;
346 }
347
348 /*
349 * Cleanup allocated resources.
350 */
351 RtlFreeAnsiString(&AName);
352 ExFreePool(Value);
353 }
354
355 return Status;
356 }
357
358
359 NTSTATUS
360 NTAPI
361 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName,
362 IN PUNICODE_STRING Value)
363 {
364 UNICODE_STRING CapturedName, CapturedValue;
365 ANSI_STRING AName, AValue;
366 KPROCESSOR_MODE PreviousMode;
367 NTSTATUS Status;
368
369 PAGED_CODE();
370
371 PreviousMode = ExGetPreviousMode();
372
373 /*
374 * Copy the strings to kernel space if necessary
375 */
376 Status = ProbeAndCaptureUnicodeString(&CapturedName,
377 PreviousMode,
378 VariableName);
379 if (NT_SUCCESS(Status))
380 {
381 Status = ProbeAndCaptureUnicodeString(&CapturedValue,
382 PreviousMode,
383 Value);
384 if (NT_SUCCESS(Status))
385 {
386 /*
387 * according to ntinternals the SeSystemEnvironmentName privilege is required!
388 */
389 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
390 PreviousMode))
391 {
392 /*
393 * convert the strings to ANSI
394 */
395 Status = RtlUnicodeStringToAnsiString(&AName,
396 &CapturedName,
397 TRUE);
398 if (NT_SUCCESS(Status))
399 {
400 Status = RtlUnicodeStringToAnsiString(&AValue,
401 &CapturedValue,
402 TRUE);
403 if (NT_SUCCESS(Status))
404 {
405 ARC_STATUS Result = HalSetEnvironmentVariable(AName.Buffer,
406 AValue.Buffer);
407
408 Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
409 }
410 }
411 }
412 else
413 {
414 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
415 Status = STATUS_PRIVILEGE_NOT_HELD;
416 }
417
418 ReleaseCapturedUnicodeString(&CapturedValue,
419 PreviousMode);
420 }
421
422 ReleaseCapturedUnicodeString(&CapturedName,
423 PreviousMode);
424 }
425
426 return Status;
427 }
428
429 NTSTATUS
430 NTAPI
431 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass,
432 IN PVOID Buffer,
433 IN ULONG BufferLength)
434 {
435 UNIMPLEMENTED;
436 return STATUS_NOT_IMPLEMENTED;
437 }
438
439 NTSTATUS
440 NTAPI
441 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
442 IN LPGUID VendorGuid,
443 IN PVOID Value,
444 IN OUT PULONG ReturnLength,
445 IN OUT PULONG Attributes)
446 {
447 UNIMPLEMENTED;
448 return STATUS_NOT_IMPLEMENTED;
449 }
450
451 NTSTATUS
452 NTAPI
453 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
454 IN LPGUID VendorGuid)
455 {
456 UNIMPLEMENTED;
457 return STATUS_NOT_IMPLEMENTED;
458 }
459
460 /* --- Query/Set System Information --- */
461
462 /*
463 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
464 * so the stack is popped only in one place on x86 platform.
465 */
466 #define QSI_USE(n) QSI##n
467 #define QSI_DEF(n) \
468 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
469
470 #define SSI_USE(n) SSI##n
471 #define SSI_DEF(n) \
472 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
473
474
475 /* Class 0 - Basic Information */
476 QSI_DEF(SystemBasicInformation)
477 {
478 PSYSTEM_BASIC_INFORMATION Sbi
479 = (PSYSTEM_BASIC_INFORMATION) Buffer;
480
481 *ReqSize = sizeof(SYSTEM_BASIC_INFORMATION);
482
483 /* Check user buffer's size */
484 if (Size != sizeof(SYSTEM_BASIC_INFORMATION))
485 {
486 return STATUS_INFO_LENGTH_MISMATCH;
487 }
488
489 RtlZeroMemory(Sbi, Size);
490 Sbi->Reserved = 0;
491 Sbi->TimerResolution = KeMaximumIncrement;
492 Sbi->PageSize = PAGE_SIZE;
493 Sbi->NumberOfPhysicalPages = MmStats.NrTotalPages;
494 Sbi->LowestPhysicalPageNumber = 0; /* FIXME */
495 Sbi->HighestPhysicalPageNumber = MmStats.NrTotalPages; /* FIXME */
496 Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
497 Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
498 Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
499 Sbi->ActiveProcessorsAffinityMask = KeActiveProcessors;
500 Sbi->NumberOfProcessors = KeNumberProcessors;
501
502 return STATUS_SUCCESS;
503 }
504
505 /* Class 1 - Processor Information */
506 QSI_DEF(SystemProcessorInformation)
507 {
508 PSYSTEM_PROCESSOR_INFORMATION Spi
509 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
510 PKPRCB Prcb;
511
512 *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION);
513
514 /* Check user buffer's size */
515 if (Size < sizeof(SYSTEM_PROCESSOR_INFORMATION))
516 {
517 return STATUS_INFO_LENGTH_MISMATCH;
518 }
519 Prcb = KeGetCurrentPrcb();
520 Spi->ProcessorArchitecture = KeProcessorArchitecture;
521 Spi->ProcessorLevel = KeProcessorLevel;
522 Spi->ProcessorRevision = KeProcessorRevision;
523 Spi->Reserved = 0;
524 Spi->ProcessorFeatureBits = KeFeatureBits;
525
526 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
527 Spi->ProcessorLevel, Spi->ProcessorRevision);
528
529 return STATUS_SUCCESS;
530 }
531
532 /* Class 2 - Performance Information */
533 QSI_DEF(SystemPerformanceInformation)
534 {
535 ULONG IdleUser, IdleKernel;
536 PSYSTEM_PERFORMANCE_INFORMATION Spi
537 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
538
539 PEPROCESS TheIdleProcess;
540
541 *ReqSize = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
542
543 /* Check user buffer's size */
544 if (Size < sizeof(SYSTEM_PERFORMANCE_INFORMATION))
545 {
546 return STATUS_INFO_LENGTH_MISMATCH;
547 }
548
549 TheIdleProcess = PsIdleProcess;
550
551 IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
552 Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
553 Spi->IoReadTransferCount = IoReadTransferCount;
554 Spi->IoWriteTransferCount = IoWriteTransferCount;
555 Spi->IoOtherTransferCount = IoOtherTransferCount;
556 Spi->IoReadOperationCount = IoReadOperationCount;
557 Spi->IoWriteOperationCount = IoWriteOperationCount;
558 Spi->IoOtherOperationCount = IoOtherOperationCount;
559
560 Spi->AvailablePages = MmStats.NrFreePages;
561 /*
562 * Add up all the used "Committed" memory + pagefile.
563 * Not sure this is right. 8^\
564 */
565 Spi->CommittedPages = MiMemoryConsumers[MC_PPOOL].PagesUsed +
566 MiMemoryConsumers[MC_NPPOOL].PagesUsed +
567 MiMemoryConsumers[MC_CACHE].PagesUsed +
568 MiMemoryConsumers[MC_USER].PagesUsed +
569 MiUsedSwapPages;
570 /*
571 * Add up the full system total + pagefile.
572 * All this make Taskmgr happy but not sure it is the right numbers.
573 * This too, fixes some of GlobalMemoryStatusEx numbers.
574 */
575 Spi->CommitLimit = MmStats.NrTotalPages + MiFreeSwapPages + MiUsedSwapPages;
576
577 Spi->PeakCommitment = 0; /* FIXME */
578 Spi->PageFaultCount = 0; /* FIXME */
579 Spi->CopyOnWriteCount = 0; /* FIXME */
580 Spi->TransitionCount = 0; /* FIXME */
581 Spi->CacheTransitionCount = 0; /* FIXME */
582 Spi->DemandZeroCount = 0; /* FIXME */
583 Spi->PageReadCount = 0; /* FIXME */
584 Spi->PageReadIoCount = 0; /* FIXME */
585 Spi->CacheReadCount = 0; /* FIXME */
586 Spi->CacheIoCount = 0; /* FIXME */
587 Spi->DirtyPagesWriteCount = 0; /* FIXME */
588 Spi->DirtyWriteIoCount = 0; /* FIXME */
589 Spi->MappedPagesWriteCount = 0; /* FIXME */
590 Spi->MappedWriteIoCount = 0; /* FIXME */
591
592 Spi->PagedPoolPages = MiMemoryConsumers[MC_PPOOL].PagesUsed;
593 Spi->PagedPoolAllocs = 0; /* FIXME */
594 Spi->PagedPoolFrees = 0; /* FIXME */
595 Spi->NonPagedPoolPages = MiMemoryConsumers[MC_NPPOOL].PagesUsed;
596 Spi->NonPagedPoolAllocs = 0; /* FIXME */
597 Spi->NonPagedPoolFrees = 0; /* FIXME */
598
599 Spi->FreeSystemPtes = 0; /* FIXME */
600
601 Spi->ResidentSystemCodePage = MmStats.NrSystemPages; /* FIXME */
602
603 Spi->TotalSystemDriverPages = 0; /* FIXME */
604 Spi->TotalSystemCodePages = 0; /* FIXME */
605 Spi->NonPagedPoolLookasideHits = 0; /* FIXME */
606 Spi->PagedPoolLookasideHits = 0; /* FIXME */
607 Spi->Spare3Count = 0; /* FIXME */
608
609 Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
610 Spi->ResidentPagedPoolPage = MmPagedPoolSize; /* FIXME */
611
612 Spi->ResidentSystemDriverPage = 0; /* FIXME */
613 Spi->CcFastReadNoWait = 0; /* FIXME */
614 Spi->CcFastReadWait = 0; /* FIXME */
615 Spi->CcFastReadResourceMiss = 0; /* FIXME */
616 Spi->CcFastReadNotPossible = 0; /* FIXME */
617
618 Spi->CcFastMdlReadNoWait = 0; /* FIXME */
619 Spi->CcFastMdlReadWait = 0; /* FIXME */
620 Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
621 Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
622
623 Spi->CcMapDataNoWait = 0; /* FIXME */
624 Spi->CcMapDataWait = 0; /* FIXME */
625 Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
626 Spi->CcMapDataWaitMiss = 0; /* FIXME */
627
628 Spi->CcPinMappedDataCount = 0; /* FIXME */
629 Spi->CcPinReadNoWait = 0; /* FIXME */
630 Spi->CcPinReadWait = 0; /* FIXME */
631 Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
632 Spi->CcPinReadWaitMiss = 0; /* FIXME */
633 Spi->CcCopyReadNoWait = 0; /* FIXME */
634 Spi->CcCopyReadWait = 0; /* FIXME */
635 Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
636 Spi->CcCopyReadWaitMiss = 0; /* FIXME */
637
638 Spi->CcMdlReadNoWait = 0; /* FIXME */
639 Spi->CcMdlReadWait = 0; /* FIXME */
640 Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
641 Spi->CcMdlReadWaitMiss = 0; /* FIXME */
642 Spi->CcReadAheadIos = 0; /* FIXME */
643 Spi->CcLazyWriteIos = 0; /* FIXME */
644 Spi->CcLazyWritePages = 0; /* FIXME */
645 Spi->CcDataFlushes = 0; /* FIXME */
646 Spi->CcDataPages = 0; /* FIXME */
647 Spi->ContextSwitches = 0; /* FIXME */
648 Spi->FirstLevelTbFills = 0; /* FIXME */
649 Spi->SecondLevelTbFills = 0; /* FIXME */
650 Spi->SystemCalls = 0; /* FIXME */
651
652 return STATUS_SUCCESS;
653 }
654
655 /* Class 3 - Time Of Day Information */
656 QSI_DEF(SystemTimeOfDayInformation)
657 {
658 SYSTEM_TIMEOFDAY_INFORMATION Sti;
659 LARGE_INTEGER CurrentTime;
660
661 /* Set amount of written information to 0 */
662 *ReqSize = 0;
663
664 /* Check user buffer's size */
665 if (Size > sizeof(SYSTEM_TIMEOFDAY_INFORMATION))
666 {
667 return STATUS_INFO_LENGTH_MISMATCH;
668 }
669
670 /* Get current time */
671 KeQuerySystemTime(&CurrentTime);
672
673 /* Zero local buffer */
674 RtlZeroMemory(&Sti, sizeof(SYSTEM_TIMEOFDAY_INFORMATION));
675
676 /* Fill local time structure */
677 Sti.BootTime= KeBootTime;
678 Sti.CurrentTime = CurrentTime;
679 Sti.TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
680 Sti.TimeZoneId = ExpTimeZoneId;
681 Sti.Reserved = 0;
682
683 /* Copy as much as requested by caller */
684 RtlCopyMemory(Buffer, &Sti, Size);
685
686 /* Set amount of information we copied */
687 *ReqSize = Size;
688
689 return STATUS_SUCCESS;
690 }
691
692 /* Class 4 - Path Information */
693 QSI_DEF(SystemPathInformation)
694 {
695 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
696 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
697
698 return STATUS_BREAKPOINT;
699 }
700
701 /* Class 5 - Process Information */
702 QSI_DEF(SystemProcessInformation)
703 {
704 PSYSTEM_PROCESS_INFORMATION SpiCurrent;
705 PSYSTEM_THREAD_INFORMATION ThreadInfo;
706 PEPROCESS Process = NULL, SystemProcess;
707 PETHREAD CurrentThread;
708 ANSI_STRING ImageName;
709 int CurrentSize, ImageNameLength = 32; // image name len in bytes
710 PLIST_ENTRY CurrentEntry;
711 ULONG TotalSize = 0, ThreadsCount;
712 ULONG TotalUser, TotalKernel;
713 PUCHAR Current;
714 NTSTATUS Status = STATUS_SUCCESS;
715
716 _SEH2_TRY
717 {
718 /* scan the process list */
719
720 PSYSTEM_PROCESS_INFORMATION Spi
721 = (PSYSTEM_PROCESS_INFORMATION) Buffer;
722
723 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
724
725 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
726 {
727 _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
728 }
729 RtlZeroMemory(Spi, Size);
730
731 SystemProcess = PsIdleProcess;
732 Process = SystemProcess;
733 Current = (PUCHAR) Spi;
734
735 do
736 {
737 SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
738
739 ThreadsCount = 0;
740 CurrentEntry = Process->ThreadListHead.Flink;
741 while (CurrentEntry != &Process->ThreadListHead)
742 {
743 ThreadsCount++;
744 CurrentEntry = CurrentEntry->Flink;
745 }
746
747 // size of the structure for every process
748 CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
749 TotalSize += CurrentSize + ImageNameLength;
750
751 if (TotalSize > Size)
752 {
753 *ReqSize = TotalSize;
754 ObDereferenceObject(Process);
755
756 _SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
757 }
758
759 // fill system information
760 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameLength; // relative offset to the beginnnig of the next structure
761 SpiCurrent->NumberOfThreads = ThreadsCount;
762 SpiCurrent->CreateTime = Process->CreateTime;
763 SpiCurrent->ImageName.Length = strlen(Process->ImageFileName) * sizeof(WCHAR);
764 SpiCurrent->ImageName.MaximumLength = (USHORT)ImageNameLength;
765 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
766
767 // copy name to the end of the struct
768 if(Process != PsIdleProcess)
769 {
770 RtlInitAnsiString(&ImageName, Process->ImageFileName);
771 RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
772 }
773 else
774 {
775 RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
776 }
777
778 SpiCurrent->BasePriority = Process->Pcb.BasePriority;
779 SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
780 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId;
781 SpiCurrent->HandleCount = (Process->ObjectTable ? ObpGetHandleCountByHandleTable(Process->ObjectTable) : 0);
782 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
783 SpiCurrent->VirtualSize = Process->VirtualSize;
784 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
785 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
786 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
787 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
788 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[0];
789 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
790 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
791 SpiCurrent->PagefileUsage = Process->QuotaUsage[2];
792 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[2];
793 SpiCurrent->PrivatePageCount = Process->CommitCharge;
794 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
795
796 CurrentEntry = Process->ThreadListHead.Flink;
797 while (CurrentEntry != &Process->ThreadListHead)
798 {
799 CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
800 ThreadListEntry);
801
802 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
803 ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
804 ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart;
805 ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
806 ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress;
807 ThreadInfo->ClientId = CurrentThread->Cid;
808 ThreadInfo->Priority = CurrentThread->Tcb.Priority;
809 ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
810 ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches;
811 ThreadInfo->ThreadState = CurrentThread->Tcb.State;
812 ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
813
814 ThreadInfo++;
815 CurrentEntry = CurrentEntry->Flink;
816 }
817
818 /* Query total user/kernel times of a process */
819 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser);
820 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
821 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
822
823 /* Handle idle process entry */
824 if (Process == PsIdleProcess) Process = NULL;
825
826 Process = PsGetNextProcess(Process);
827 ThreadsCount = 0;
828 if ((Process == SystemProcess) || (Process == NULL))
829 {
830 SpiCurrent->NextEntryOffset = 0;
831 break;
832 }
833 else
834 Current += CurrentSize + ImageNameLength;
835 } while ((Process != SystemProcess) && (Process != NULL));
836
837 if(Process != NULL)
838 ObDereferenceObject(Process);
839 Status = STATUS_SUCCESS;
840 }
841 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
842 {
843 if(Process != NULL)
844 ObDereferenceObject(Process);
845 Status = _SEH2_GetExceptionCode();
846 }
847 _SEH2_END
848
849 *ReqSize = TotalSize;
850 return Status;
851 }
852
853 /* Class 6 - Call Count Information */
854 QSI_DEF(SystemCallCountInformation)
855 {
856 /* FIXME */
857 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
858 return STATUS_NOT_IMPLEMENTED;
859 }
860
861 /* Class 7 - Device Information */
862 QSI_DEF(SystemDeviceInformation)
863 {
864 PSYSTEM_DEVICE_INFORMATION Sdi
865 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
866 PCONFIGURATION_INFORMATION ConfigInfo;
867
868 *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION);
869
870 /* Check user buffer's size */
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)) break;
1030 }
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)) break;
1074 }
1075 while ((pr != syspr) && (pr != NULL));
1076
1077 if(pr != NULL) ObDereferenceObject(pr);
1078
1079 DPRINT("SystemHandleInformation 4\n");
1080 return STATUS_SUCCESS;
1081
1082 }
1083 /*
1084 SSI_DEF(SystemHandleInformation)
1085 {
1086
1087 return STATUS_SUCCESS;
1088 }
1089 */
1090
1091 /* Class 17 - Information */
1092 QSI_DEF(SystemObjectInformation)
1093 {
1094 /* FIXME */
1095 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
1096 return STATUS_NOT_IMPLEMENTED;
1097 }
1098
1099 /* Class 18 - Information */
1100 QSI_DEF(SystemPageFileInformation)
1101 {
1102 UNICODE_STRING FileName; /* FIXME */
1103 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
1104
1105 if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION))
1106 {
1107 * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION);
1108 return STATUS_INFO_LENGTH_MISMATCH;
1109 }
1110
1111 RtlInitUnicodeString(&FileName, NULL); /* FIXME */
1112
1113 /* FIXME */
1114 Spfi->NextEntryOffset = 0;
1115
1116 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
1117 Spfi->TotalInUse = MiUsedSwapPages;
1118 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
1119 Spfi->PageFileName = FileName;
1120 return STATUS_SUCCESS;
1121 }
1122
1123 /* Class 19 - Vdm Instemul Information */
1124 QSI_DEF(SystemVdmInstemulInformation)
1125 {
1126 /* FIXME */
1127 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1128 return STATUS_NOT_IMPLEMENTED;
1129 }
1130
1131 /* Class 20 - Vdm Bop Information */
1132 QSI_DEF(SystemVdmBopInformation)
1133 {
1134 /* FIXME */
1135 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1136 return STATUS_NOT_IMPLEMENTED;
1137 }
1138
1139 /* Class 21 - File Cache Information */
1140 QSI_DEF(SystemFileCacheInformation)
1141 {
1142 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
1143
1144 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
1145 {
1146 *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
1147 return STATUS_INFO_LENGTH_MISMATCH;
1148 }
1149
1150 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION));
1151
1152 /* Return the Byte size not the page size. */
1153 Sci->CurrentSize =
1154 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
1155 Sci->PeakSize =
1156 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE; /* FIXME */
1157 /* Taskmgr multiplies this one by page size right away */
1158 Sci->CurrentSizeIncludingTransitionInPages =
1159 MiMemoryConsumers[MC_CACHE].PagesUsed; /* FIXME: Should be */
1160 /* system working set and standby pages. */
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
1252 DPRINT("SystemFullMemoryInformation\n");
1253
1254 TheIdleProcess = PsIdleProcess;
1255
1256 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1257 TheIdleProcess->UniqueProcessId,
1258 TheIdleProcess->Pcb.KernelTime,
1259 MiFreeSwapPages,
1260 MiUsedSwapPages);
1261
1262 #ifndef NDEBUG
1263 MmPrintMemoryStatistic();
1264 #endif
1265
1266 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1267
1268 return STATUS_SUCCESS;
1269 }
1270
1271 /* Class 26 - Load Image */
1272 SSI_DEF(SystemLoadGdiDriverInformation)
1273 {
1274 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1275 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1276 UNICODE_STRING ImageName;
1277 PVOID ImageBase;
1278 PLDR_DATA_TABLE_ENTRY ModuleObject;
1279 ULONG_PTR EntryPoint;
1280 NTSTATUS Status;
1281 ULONG DirSize;
1282 PIMAGE_NT_HEADERS NtHeader;
1283
1284 /* Validate size */
1285 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1286 {
1287 /* Incorrect buffer length, fail */
1288 return STATUS_INFO_LENGTH_MISMATCH;
1289 }
1290
1291 /* Only kernel-mode can call this function */
1292 if (PreviousMode != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1293
1294 /* Load the driver */
1295 ImageName = DriverInfo->DriverName;
1296 Status = MmLoadSystemImage(&ImageName,
1297 NULL,
1298 NULL,
1299 0,
1300 (PVOID)&ModuleObject,
1301 &ImageBase);
1302 if (!NT_SUCCESS(Status)) return Status;
1303
1304 /* Return the export pointer */
1305 DriverInfo->ExportSectionPointer =
1306 RtlImageDirectoryEntryToData(ImageBase,
1307 TRUE,
1308 IMAGE_DIRECTORY_ENTRY_EXPORT,
1309 &DirSize);
1310
1311 /* Get the entrypoint */
1312 NtHeader = RtlImageNtHeader(ImageBase);
1313 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1314 EntryPoint += (ULONG_PTR)ImageBase;
1315
1316 /* Save other data */
1317 DriverInfo->ImageAddress = ImageBase;
1318 DriverInfo->SectionPointer = NULL;
1319 DriverInfo->EntryPoint = (PVOID)EntryPoint;
1320 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1321
1322 /* All is good */
1323 return STATUS_SUCCESS;
1324 }
1325
1326 /* Class 27 - Unload Image */
1327 SSI_DEF(SystemUnloadGdiDriverInformation)
1328 {
1329 PLDR_DATA_TABLE_ENTRY LdrEntry;
1330 PLIST_ENTRY NextEntry;
1331 PVOID BaseAddr = *((PVOID*)Buffer);
1332
1333 if(Size != sizeof(PVOID))
1334 return STATUS_INFO_LENGTH_MISMATCH;
1335
1336 if(KeGetPreviousMode() != KernelMode)
1337 return STATUS_PRIVILEGE_NOT_HELD;
1338
1339 // Scan the module list
1340 NextEntry = PsLoadedModuleList.Flink;
1341 while(NextEntry != &PsLoadedModuleList)
1342 {
1343 LdrEntry = CONTAINING_RECORD(NextEntry,
1344 LDR_DATA_TABLE_ENTRY,
1345 InLoadOrderLinks);
1346
1347 if (LdrEntry->DllBase == BaseAddr)
1348 {
1349 // Found it.
1350 break;
1351 }
1352
1353 NextEntry = NextEntry->Flink;
1354 }
1355
1356 // Check if we found the image
1357 if(NextEntry != &PsLoadedModuleList)
1358 {
1359 return MmUnloadSystemImage(LdrEntry);
1360 }
1361 else
1362 {
1363 DPRINT1("Image 0x%x not found.\n", BaseAddr);
1364 return STATUS_DLL_NOT_FOUND;
1365 }
1366
1367 }
1368
1369 /* Class 28 - Time Adjustment Information */
1370 QSI_DEF(SystemTimeAdjustmentInformation)
1371 {
1372 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo =
1373 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer;
1374
1375 /* Check if enough storage was provided */
1376 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size)
1377 {
1378 * ReqSize = sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION);
1379 return STATUS_INFO_LENGTH_MISMATCH;
1380 }
1381
1382 /* Give time values to our caller */
1383 TimeInfo->TimeIncrement = KeMaximumIncrement;
1384 TimeInfo->TimeAdjustment = KeTimeAdjustment;
1385 TimeInfo->Enable = TRUE;
1386
1387 return STATUS_SUCCESS;
1388 }
1389
1390 SSI_DEF(SystemTimeAdjustmentInformation)
1391 {
1392 /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1393 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
1394
1395 /* Check size of a buffer, it must match our expectations */
1396 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
1397 return STATUS_INFO_LENGTH_MISMATCH;
1398
1399 /* TODO: Check privileges */
1400
1401 /* TODO: Set time adjustment information */
1402 DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
1403 return STATUS_NOT_IMPLEMENTED;
1404 }
1405
1406 /* Class 29 - Summary Memory Information */
1407 QSI_DEF(SystemSummaryMemoryInformation)
1408 {
1409 /* FIXME */
1410 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1411 return STATUS_NOT_IMPLEMENTED;
1412 }
1413
1414 /* Class 30 - Next Event Id Information */
1415 QSI_DEF(SystemNextEventIdInformation)
1416 {
1417 /* FIXME */
1418 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1419 return STATUS_NOT_IMPLEMENTED;
1420 }
1421
1422 /* Class 31 - Event Ids Information */
1423 QSI_DEF(SystemEventIdsInformation)
1424 {
1425 /* FIXME */
1426 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1427 return STATUS_NOT_IMPLEMENTED;
1428 }
1429
1430 /* Class 32 - Crash Dump Information */
1431 QSI_DEF(SystemCrashDumpInformation)
1432 {
1433 /* FIXME */
1434 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1435 return STATUS_NOT_IMPLEMENTED;
1436 }
1437
1438 /* Class 33 - Exception Information */
1439 QSI_DEF(SystemExceptionInformation)
1440 {
1441 /* FIXME */
1442 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1443 return STATUS_NOT_IMPLEMENTED;
1444 }
1445
1446 /* Class 34 - Crash Dump State Information */
1447 QSI_DEF(SystemCrashDumpStateInformation)
1448 {
1449 /* FIXME */
1450 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1451 return STATUS_NOT_IMPLEMENTED;
1452 }
1453
1454 /* Class 35 - Kernel Debugger Information */
1455 QSI_DEF(SystemKernelDebuggerInformation)
1456 {
1457 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1458
1459 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1460 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1461 {
1462 return STATUS_INFO_LENGTH_MISMATCH;
1463 }
1464
1465 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1466 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1467
1468 return STATUS_SUCCESS;
1469 }
1470
1471 /* Class 36 - Context Switch Information */
1472 QSI_DEF(SystemContextSwitchInformation)
1473 {
1474 /* FIXME */
1475 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1476 return STATUS_NOT_IMPLEMENTED;
1477 }
1478
1479 /* Class 37 - Registry Quota Information */
1480 QSI_DEF(SystemRegistryQuotaInformation)
1481 {
1482 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1483
1484 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1485 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1486 {
1487 return STATUS_INFO_LENGTH_MISMATCH;
1488 }
1489
1490 DPRINT1("Faking max registry size of 32 MB\n");
1491 srqi->RegistryQuotaAllowed = 0x2000000;
1492 srqi->RegistryQuotaUsed = 0x200000;
1493 srqi->PagedPoolSize = 0x200000;
1494
1495 return STATUS_SUCCESS;
1496 }
1497
1498 SSI_DEF(SystemRegistryQuotaInformation)
1499 {
1500 /* FIXME */
1501 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1502 return STATUS_NOT_IMPLEMENTED;
1503 }
1504
1505 /* Class 38 - Load And Call Image */
1506 SSI_DEF(SystemExtendServiceTableInformation)
1507 {
1508 UNICODE_STRING ImageName;
1509 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1510 PLDR_DATA_TABLE_ENTRY ModuleObject;
1511 NTSTATUS Status;
1512 PIMAGE_NT_HEADERS NtHeader;
1513 DRIVER_OBJECT Win32k;
1514 PDRIVER_INITIALIZE DriverInit;
1515 PVOID ImageBase;
1516 ULONG_PTR EntryPoint;
1517
1518 /* Validate the size */
1519 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1520
1521 /* Check who is calling */
1522 if (PreviousMode != KernelMode)
1523 {
1524 /* Make sure we can load drivers */
1525 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1526 {
1527 /* FIXME: We can't, fail */
1528 //return STATUS_PRIVILEGE_NOT_HELD;
1529 }
1530
1531 /* Probe and capture the driver name */
1532 ProbeAndCaptureUnicodeString(&ImageName, UserMode, Buffer);
1533
1534 /* Force kernel as previous mode */
1535 return ZwSetSystemInformation(SystemExtendServiceTableInformation,
1536 &ImageName,
1537 sizeof(ImageName));
1538 }
1539
1540 /* Just copy the string */
1541 ImageName = *(PUNICODE_STRING)Buffer;
1542
1543 /* Load the image */
1544 Status = MmLoadSystemImage(&ImageName,
1545 NULL,
1546 NULL,
1547 0,
1548 (PVOID)&ModuleObject,
1549 &ImageBase);
1550 if (!NT_SUCCESS(Status)) return Status;
1551
1552 /* Get the headers */
1553 NtHeader = RtlImageNtHeader(ImageBase);
1554 if (!NtHeader)
1555 {
1556 /* Fail */
1557 MmUnloadSystemImage(ModuleObject);
1558 return STATUS_INVALID_IMAGE_FORMAT;
1559 }
1560
1561 /* Get the entrypoint */
1562 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1563 EntryPoint += (ULONG_PTR)ImageBase;
1564 DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1565
1566 /* Create a dummy device */
1567 RtlZeroMemory(&Win32k, sizeof(Win32k));
1568 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1569 Win32k.DriverStart = ImageBase;
1570
1571 /* Call it */
1572 Status = (DriverInit)(&Win32k, NULL);
1573 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1574
1575 /* Unload if we failed */
1576 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
1577 return Status;
1578 }
1579
1580 /* Class 39 - Priority Separation */
1581 SSI_DEF(SystemPrioritySeperation)
1582 {
1583 /* FIXME */
1584 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1585 return STATUS_NOT_IMPLEMENTED;
1586 }
1587
1588 /* Class 40 - Plug Play Bus Information */
1589 QSI_DEF(SystemPlugPlayBusInformation)
1590 {
1591 /* FIXME */
1592 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1593 return STATUS_NOT_IMPLEMENTED;
1594 }
1595
1596 /* Class 41 - Dock Information */
1597 QSI_DEF(SystemDockInformation)
1598 {
1599 /* FIXME */
1600 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1601 return STATUS_NOT_IMPLEMENTED;
1602 }
1603
1604 /* Class 42 - Power Information */
1605 QSI_DEF(SystemPowerInformation)
1606 {
1607 /* FIXME */
1608 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1609 return STATUS_NOT_IMPLEMENTED;
1610 }
1611
1612 /* Class 43 - Processor Speed Information */
1613 QSI_DEF(SystemProcessorSpeedInformation)
1614 {
1615 /* FIXME */
1616 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1617 return STATUS_NOT_IMPLEMENTED;
1618 }
1619
1620 /* Class 44 - Current Time Zone Information */
1621 QSI_DEF(SystemCurrentTimeZoneInformation)
1622 {
1623 *ReqSize = sizeof(TIME_ZONE_INFORMATION);
1624
1625 if (sizeof(TIME_ZONE_INFORMATION) != Size)
1626 {
1627 return STATUS_INFO_LENGTH_MISMATCH;
1628 }
1629
1630 /* Copy the time zone information struct */
1631 memcpy(Buffer,
1632 &ExpTimeZoneInfo,
1633 sizeof(TIME_ZONE_INFORMATION));
1634
1635 return STATUS_SUCCESS;
1636 }
1637
1638
1639 SSI_DEF(SystemCurrentTimeZoneInformation)
1640 {
1641 /* Check user buffer's size */
1642 if (Size < sizeof(TIME_ZONE_INFORMATION))
1643 {
1644 return STATUS_INFO_LENGTH_MISMATCH;
1645 }
1646
1647 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1648 }
1649
1650
1651 /* Class 45 - Lookaside Information */
1652 QSI_DEF(SystemLookasideInformation)
1653 {
1654 /* FIXME */
1655 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1656 return STATUS_NOT_IMPLEMENTED;
1657 }
1658
1659
1660 /* Class 46 - Set time slip event */
1661 SSI_DEF(SystemSetTimeSlipEvent)
1662 {
1663 /* FIXME */
1664 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1665 return STATUS_NOT_IMPLEMENTED;
1666 }
1667
1668
1669 /* Class 47 - Create a new session (TSE) */
1670 SSI_DEF(SystemCreateSession)
1671 {
1672 /* FIXME */
1673 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1674 return STATUS_NOT_IMPLEMENTED;
1675 }
1676
1677
1678 /* Class 48 - Delete an existing session (TSE) */
1679 SSI_DEF(SystemDeleteSession)
1680 {
1681 /* FIXME */
1682 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1683 return STATUS_NOT_IMPLEMENTED;
1684 }
1685
1686
1687 /* Class 49 - UNKNOWN */
1688 QSI_DEF(SystemInvalidInfoClass4)
1689 {
1690 /* FIXME */
1691 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1692 return STATUS_NOT_IMPLEMENTED;
1693 }
1694
1695
1696 /* Class 50 - System range start address */
1697 QSI_DEF(SystemRangeStartInformation)
1698 {
1699 /* FIXME */
1700 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1701 return STATUS_NOT_IMPLEMENTED;
1702 }
1703
1704
1705 /* Class 51 - Driver verifier information */
1706 QSI_DEF(SystemVerifierInformation)
1707 {
1708 /* FIXME */
1709 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1710 return STATUS_NOT_IMPLEMENTED;
1711 }
1712
1713
1714 SSI_DEF(SystemVerifierInformation)
1715 {
1716 /* FIXME */
1717 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1718 return STATUS_NOT_IMPLEMENTED;
1719 }
1720
1721
1722 /* Class 52 - Add a driver verifier */
1723 SSI_DEF(SystemAddVerifier)
1724 {
1725 /* FIXME */
1726 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1727 return STATUS_NOT_IMPLEMENTED;
1728 }
1729
1730
1731 /* Class 53 - A session's processes */
1732 QSI_DEF(SystemSessionProcessesInformation)
1733 {
1734 /* FIXME */
1735 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1736 return STATUS_NOT_IMPLEMENTED;
1737 }
1738
1739
1740 /* Query/Set Calls Table */
1741 typedef
1742 struct _QSSI_CALLS
1743 {
1744 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1745 NTSTATUS (* Set) (PVOID,ULONG);
1746
1747 } QSSI_CALLS;
1748
1749 // QS Query & Set
1750 // QX Query
1751 // XS Set
1752 // XX unknown behaviour
1753 //
1754 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1755 #define SI_QX(n) {QSI_USE(n),NULL}
1756 #define SI_XS(n) {NULL,SSI_USE(n)}
1757 #define SI_XX(n) {NULL,NULL}
1758
1759 static
1760 QSSI_CALLS
1761 CallQS [] =
1762 {
1763 SI_QX(SystemBasicInformation),
1764 SI_QX(SystemProcessorInformation),
1765 SI_QX(SystemPerformanceInformation),
1766 SI_QX(SystemTimeOfDayInformation),
1767 SI_QX(SystemPathInformation), /* should be SI_XX */
1768 SI_QX(SystemProcessInformation),
1769 SI_QX(SystemCallCountInformation),
1770 SI_QX(SystemDeviceInformation),
1771 SI_QX(SystemProcessorPerformanceInformation),
1772 SI_QS(SystemFlagsInformation),
1773 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1774 SI_QX(SystemModuleInformation),
1775 SI_QX(SystemLocksInformation),
1776 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1777 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1778 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1779 SI_QX(SystemHandleInformation),
1780 SI_QX(SystemObjectInformation),
1781 SI_QX(SystemPageFileInformation),
1782 SI_QX(SystemVdmInstemulInformation),
1783 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1784 SI_QS(SystemFileCacheInformation),
1785 SI_QX(SystemPoolTagInformation),
1786 SI_QX(SystemInterruptInformation),
1787 SI_QS(SystemDpcBehaviourInformation),
1788 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1789 SI_XS(SystemLoadGdiDriverInformation),
1790 SI_XS(SystemUnloadGdiDriverInformation),
1791 SI_QS(SystemTimeAdjustmentInformation),
1792 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1793 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1794 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1795 SI_QX(SystemCrashDumpInformation),
1796 SI_QX(SystemExceptionInformation),
1797 SI_QX(SystemCrashDumpStateInformation),
1798 SI_QX(SystemKernelDebuggerInformation),
1799 SI_QX(SystemContextSwitchInformation),
1800 SI_QS(SystemRegistryQuotaInformation),
1801 SI_XS(SystemExtendServiceTableInformation),
1802 SI_XS(SystemPrioritySeperation),
1803 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1804 SI_QX(SystemDockInformation), /* it should be SI_XX */
1805 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1806 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1807 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1808 SI_QX(SystemLookasideInformation),
1809 SI_XS(SystemSetTimeSlipEvent),
1810 SI_XS(SystemCreateSession),
1811 SI_XS(SystemDeleteSession),
1812 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1813 SI_QX(SystemRangeStartInformation),
1814 SI_QS(SystemVerifierInformation),
1815 SI_XS(SystemAddVerifier),
1816 SI_QX(SystemSessionProcessesInformation)
1817 };
1818
1819 C_ASSERT(SystemBasicInformation == 0);
1820 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1821 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1822
1823 /*
1824 * @implemented
1825 */
1826 NTSTATUS NTAPI
1827 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1828 OUT PVOID SystemInformation,
1829 IN ULONG Length,
1830 OUT PULONG UnsafeResultLength)
1831 {
1832 KPROCESSOR_MODE PreviousMode;
1833 ULONG ResultLength;
1834 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1835
1836 PAGED_CODE();
1837
1838 PreviousMode = ExGetPreviousMode();
1839
1840 _SEH2_TRY
1841 {
1842 if (PreviousMode != KernelMode)
1843 {
1844 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1845 ProbeForWrite(SystemInformation, Length, 1);
1846 if (UnsafeResultLength != NULL)
1847 ProbeForWriteUlong(UnsafeResultLength);
1848 }
1849
1850 /*
1851 * Check the request is valid.
1852 */
1853 if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
1854 {
1855 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
1856 }
1857
1858 if (NULL != CallQS [SystemInformationClass].Query)
1859 {
1860 /*
1861 * Hand the request to a subhandler.
1862 */
1863 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1864 Length,
1865 &ResultLength);
1866 if (UnsafeResultLength != NULL)
1867 {
1868 if (PreviousMode != KernelMode)
1869 {
1870 *UnsafeResultLength = ResultLength;
1871 }
1872 else
1873 {
1874 *UnsafeResultLength = ResultLength;
1875 }
1876 }
1877 }
1878 }
1879 _SEH2_EXCEPT(ExSystemExceptionFilter())
1880 {
1881 FStatus = _SEH2_GetExceptionCode();
1882 }
1883 _SEH2_END;
1884
1885 return FStatus;
1886 }
1887
1888
1889 NTSTATUS
1890 NTAPI
1891 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1892 IN PVOID SystemInformation,
1893 IN ULONG SystemInformationLength)
1894 {
1895 PAGED_CODE();
1896
1897 /*
1898 * If called from user mode, check
1899 * possible unsafe arguments.
1900 */
1901 #if 0
1902 if (KernelMode != KeGetPreviousMode())
1903 {
1904 // Check arguments
1905 //ProbeForWrite(
1906 // SystemInformation,
1907 // Length
1908 // );
1909 //ProbeForWrite(
1910 // ResultLength,
1911 // sizeof (ULONG)
1912 // );
1913 }
1914 #endif
1915 /*
1916 * Check the request is valid.
1917 */
1918 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
1919 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
1920 {
1921 if (NULL != CallQS [SystemInformationClass].Set)
1922 {
1923 /*
1924 * Hand the request to a subhandler.
1925 */
1926 return CallQS [SystemInformationClass].Set(SystemInformation,
1927 SystemInformationLength);
1928 }
1929 }
1930
1931 return STATUS_INVALID_INFO_CLASS;
1932 }
1933
1934
1935 NTSTATUS
1936 NTAPI
1937 NtFlushInstructionCache(IN HANDLE ProcessHandle,
1938 IN PVOID BaseAddress,
1939 IN ULONG NumberOfBytesToFlush)
1940 {
1941 PAGED_CODE();
1942
1943 #if defined(_M_IX86)
1944 __wbinvd();
1945 #elif defined(_M_PPC)
1946 __asm__ __volatile__("tlbsync");
1947 #elif defined(_M_MIPS)
1948 DPRINT1("NtFlushInstructionCache() is not implemented\n");
1949 for (;;);
1950 #elif defined(_M_ARM)
1951 __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
1952 #else
1953 #error Unknown architecture
1954 #endif
1955 return STATUS_SUCCESS;
1956 }
1957
1958 ULONG
1959 NTAPI
1960 NtGetCurrentProcessorNumber(VOID)
1961 {
1962 /* Just return the CPU */
1963 return KeGetCurrentProcessorNumber();
1964 }
1965
1966 /* EOF */