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