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