[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 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 = (ULONGLONG)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 AnsiValueBuffer;
215 ANSI_STRING AValue;
216 UNICODE_STRING WValue;
217 KPROCESSOR_MODE PreviousMode;
218 NTSTATUS Status;
219 PAGED_CODE();
220
221 /* Check if the call came from user mode */
222 PreviousMode = ExGetPreviousMode();
223 if (PreviousMode != KernelMode)
224 {
225 _SEH2_TRY
226 {
227 /* Probe the input and output buffers */
228 ProbeForRead(VariableName, sizeof(UNICODE_STRING), sizeof(ULONG));
229 ProbeForWrite(ValueBuffer, ValueBufferLength, sizeof(WCHAR));
230 if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength);
231 }
232 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
233 {
234 /* Return the exception code */
235 _SEH2_YIELD(return _SEH2_GetExceptionCode());
236 }
237 _SEH2_END;
238 }
239
240 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
241 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, PreviousMode))
242 {
243 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
244 return STATUS_PRIVILEGE_NOT_HELD;
245 }
246
247 /* Copy the name to kernel space if necessary */
248 Status = ProbeAndCaptureUnicodeString(&WName, PreviousMode, VariableName);
249 if (!NT_SUCCESS(Status))
250 {
251 return Status;
252 }
253
254 /* Convert the name to ANSI and release the captured UNICODE string */
255 Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
256 ReleaseCapturedUnicodeString(&WName, PreviousMode);
257 if (!NT_SUCCESS(Status)) return Status;
258
259 /* Allocate a buffer for the ANSI environment variable */
260 AnsiValueBuffer = ExAllocatePoolWithTag(NonPagedPool, ValueBufferLength, 'pmeT');
261 if (AnsiValueBuffer == NULL)
262 {
263 RtlFreeAnsiString(&AName);
264 return STATUS_INSUFFICIENT_RESOURCES;
265 }
266
267 /* Get the environment variable and free the ANSI name */
268 Result = HalGetEnvironmentVariable(AName.Buffer,
269 (USHORT)ValueBufferLength,
270 AnsiValueBuffer);
271 RtlFreeAnsiString(&AName);
272
273 /* Check if we had success */
274 if (Result == ESUCCESS)
275 {
276 /* Copy the result back to the caller. */
277 _SEH2_TRY
278 {
279 /* Initialize ANSI string from the result */
280 RtlInitAnsiString(&AValue, AnsiValueBuffer);
281
282 /* Initialize a UNICODE string from the callers buffer */
283 RtlInitEmptyUnicodeString(&WValue, ValueBuffer, ValueBufferLength);
284
285 /* Convert the result to UNICODE */
286 Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, FALSE);
287
288 if (ReturnLength != NULL)
289 {
290 *ReturnLength = WValue.Length;
291 }
292 }
293 _SEH2_EXCEPT(ExSystemExceptionFilter())
294 {
295 Status = _SEH2_GetExceptionCode();
296 }
297 _SEH2_END;
298 }
299 else
300 {
301 Status = STATUS_UNSUCCESSFUL;
302 }
303
304 /* Free the allocated ANSI value buffer */
305 ExFreePoolWithTag(AnsiValueBuffer, 'pmeT');
306
307 return Status;
308 }
309
310
311 NTSTATUS
312 NTAPI
313 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName,
314 IN PUNICODE_STRING Value)
315 {
316 UNICODE_STRING CapturedName, CapturedValue;
317 ANSI_STRING AName, AValue;
318 KPROCESSOR_MODE PreviousMode;
319 NTSTATUS Status;
320
321 PAGED_CODE();
322
323 PreviousMode = ExGetPreviousMode();
324
325 /*
326 * Copy the strings to kernel space if necessary
327 */
328 Status = ProbeAndCaptureUnicodeString(&CapturedName,
329 PreviousMode,
330 VariableName);
331 if (NT_SUCCESS(Status))
332 {
333 Status = ProbeAndCaptureUnicodeString(&CapturedValue,
334 PreviousMode,
335 Value);
336 if (NT_SUCCESS(Status))
337 {
338 /*
339 * according to ntinternals the SeSystemEnvironmentName privilege is required!
340 */
341 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
342 PreviousMode))
343 {
344 /*
345 * convert the strings to ANSI
346 */
347 Status = RtlUnicodeStringToAnsiString(&AName,
348 &CapturedName,
349 TRUE);
350 if (NT_SUCCESS(Status))
351 {
352 Status = RtlUnicodeStringToAnsiString(&AValue,
353 &CapturedValue,
354 TRUE);
355 if (NT_SUCCESS(Status))
356 {
357 ARC_STATUS Result = HalSetEnvironmentVariable(AName.Buffer,
358 AValue.Buffer);
359
360 Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
361 }
362 }
363 }
364 else
365 {
366 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
367 Status = STATUS_PRIVILEGE_NOT_HELD;
368 }
369
370 ReleaseCapturedUnicodeString(&CapturedValue,
371 PreviousMode);
372 }
373
374 ReleaseCapturedUnicodeString(&CapturedName,
375 PreviousMode);
376 }
377
378 return Status;
379 }
380
381 NTSTATUS
382 NTAPI
383 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass,
384 IN PVOID Buffer,
385 IN ULONG BufferLength)
386 {
387 UNIMPLEMENTED;
388 return STATUS_NOT_IMPLEMENTED;
389 }
390
391 NTSTATUS
392 NTAPI
393 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
394 IN LPGUID VendorGuid,
395 IN PVOID Value,
396 IN OUT PULONG ReturnLength,
397 IN OUT PULONG Attributes)
398 {
399 UNIMPLEMENTED;
400 return STATUS_NOT_IMPLEMENTED;
401 }
402
403 NTSTATUS
404 NTAPI
405 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
406 IN LPGUID VendorGuid)
407 {
408 UNIMPLEMENTED;
409 return STATUS_NOT_IMPLEMENTED;
410 }
411
412 /* --- Query/Set System Information --- */
413
414 /*
415 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
416 * so the stack is popped only in one place on x86 platform.
417 */
418 #define QSI_USE(n) QSI##n
419 #define QSI_DEF(n) \
420 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
421
422 #define SSI_USE(n) SSI##n
423 #define SSI_DEF(n) \
424 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
425
426 VOID
427 NTAPI
428 ExQueryPoolUsage(OUT PULONG PagedPoolPages,
429 OUT PULONG NonPagedPoolPages,
430 OUT PULONG PagedPoolAllocs,
431 OUT PULONG PagedPoolFrees,
432 OUT PULONG PagedPoolLookasideHits,
433 OUT PULONG NonPagedPoolAllocs,
434 OUT PULONG NonPagedPoolFrees,
435 OUT PULONG NonPagedPoolLookasideHits);
436
437 /* Class 0 - Basic Information */
438 QSI_DEF(SystemBasicInformation)
439 {
440 PSYSTEM_BASIC_INFORMATION Sbi
441 = (PSYSTEM_BASIC_INFORMATION) Buffer;
442
443 *ReqSize = sizeof(SYSTEM_BASIC_INFORMATION);
444
445 /* Check user buffer's size */
446 if (Size != sizeof(SYSTEM_BASIC_INFORMATION))
447 {
448 return STATUS_INFO_LENGTH_MISMATCH;
449 }
450
451 RtlZeroMemory(Sbi, Size);
452 Sbi->Reserved = 0;
453 Sbi->TimerResolution = KeMaximumIncrement;
454 Sbi->PageSize = PAGE_SIZE;
455 Sbi->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
456 Sbi->LowestPhysicalPageNumber = (ULONG)MmLowestPhysicalPage;
457 Sbi->HighestPhysicalPageNumber = (ULONG)MmHighestPhysicalPage;
458 Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
459 Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
460 Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
461 Sbi->ActiveProcessorsAffinityMask = KeActiveProcessors;
462 Sbi->NumberOfProcessors = KeNumberProcessors;
463
464 return STATUS_SUCCESS;
465 }
466
467 /* Class 1 - Processor Information */
468 QSI_DEF(SystemProcessorInformation)
469 {
470 PSYSTEM_PROCESSOR_INFORMATION Spi
471 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
472
473 *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION);
474
475 /* Check user buffer's size */
476 if (Size < sizeof(SYSTEM_PROCESSOR_INFORMATION))
477 {
478 return STATUS_INFO_LENGTH_MISMATCH;
479 }
480 Spi->ProcessorArchitecture = KeProcessorArchitecture;
481 Spi->ProcessorLevel = KeProcessorLevel;
482 Spi->ProcessorRevision = KeProcessorRevision;
483 Spi->Reserved = 0;
484 Spi->ProcessorFeatureBits = KeFeatureBits;
485
486 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
487 Spi->ProcessorLevel, Spi->ProcessorRevision);
488
489 return STATUS_SUCCESS;
490 }
491
492 /* Class 2 - Performance Information */
493 QSI_DEF(SystemPerformanceInformation)
494 {
495 ULONG IdleUser, IdleKernel;
496 PSYSTEM_PERFORMANCE_INFORMATION Spi
497 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
498
499 PEPROCESS TheIdleProcess;
500
501 *ReqSize = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
502
503 /* Check user buffer's size */
504 if (Size < sizeof(SYSTEM_PERFORMANCE_INFORMATION))
505 {
506 return STATUS_INFO_LENGTH_MISMATCH;
507 }
508
509 TheIdleProcess = PsIdleProcess;
510
511 IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser);
512 Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement);
513 Spi->IoReadTransferCount = IoReadTransferCount;
514 Spi->IoWriteTransferCount = IoWriteTransferCount;
515 Spi->IoOtherTransferCount = IoOtherTransferCount;
516 Spi->IoReadOperationCount = IoReadOperationCount;
517 Spi->IoWriteOperationCount = IoWriteOperationCount;
518 Spi->IoOtherOperationCount = IoOtherOperationCount;
519
520 Spi->AvailablePages = (ULONG)MmAvailablePages;
521 /*
522 * Add up all the used "Committed" memory + pagefile.
523 * Not sure this is right. 8^\
524 */
525 Spi->CommittedPages = MiMemoryConsumers[MC_SYSTEM].PagesUsed +
526 MiMemoryConsumers[MC_CACHE].PagesUsed +
527 MiMemoryConsumers[MC_USER].PagesUsed +
528 MiUsedSwapPages;
529 /*
530 * Add up the full system total + pagefile.
531 * All this make Taskmgr happy but not sure it is the right numbers.
532 * This too, fixes some of GlobalMemoryStatusEx numbers.
533 */
534 Spi->CommitLimit = MmNumberOfPhysicalPages + MiFreeSwapPages + MiUsedSwapPages;
535
536 Spi->PeakCommitment = 0; /* FIXME */
537 Spi->PageFaultCount = 0; /* FIXME */
538 Spi->CopyOnWriteCount = 0; /* FIXME */
539 Spi->TransitionCount = 0; /* FIXME */
540 Spi->CacheTransitionCount = 0; /* FIXME */
541 Spi->DemandZeroCount = 0; /* FIXME */
542 Spi->PageReadCount = 0; /* FIXME */
543 Spi->PageReadIoCount = 0; /* FIXME */
544 Spi->CacheReadCount = 0; /* FIXME */
545 Spi->CacheIoCount = 0; /* FIXME */
546 Spi->DirtyPagesWriteCount = 0; /* FIXME */
547 Spi->DirtyWriteIoCount = 0; /* FIXME */
548 Spi->MappedPagesWriteCount = 0; /* FIXME */
549 Spi->MappedWriteIoCount = 0; /* FIXME */
550
551 Spi->PagedPoolPages = 0;
552 Spi->NonPagedPoolPages = 0;
553 Spi->PagedPoolAllocs = 0;
554 Spi->PagedPoolFrees = 0;
555 Spi->PagedPoolLookasideHits = 0;
556 Spi->NonPagedPoolAllocs = 0;
557 Spi->NonPagedPoolFrees = 0;
558 Spi->NonPagedPoolLookasideHits = 0;
559 ExQueryPoolUsage(&Spi->PagedPoolPages,
560 &Spi->NonPagedPoolPages,
561 &Spi->PagedPoolAllocs,
562 &Spi->PagedPoolFrees,
563 &Spi->PagedPoolLookasideHits,
564 &Spi->NonPagedPoolAllocs,
565 &Spi->NonPagedPoolFrees,
566 &Spi->NonPagedPoolLookasideHits);
567 Spi->FreeSystemPtes = 0; /* FIXME */
568
569 Spi->ResidentSystemCodePage = 0; /* FIXME */
570
571 Spi->TotalSystemDriverPages = 0; /* FIXME */
572 Spi->Spare3Count = 0; /* FIXME */
573
574 Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
575 Spi->ResidentPagedPoolPage = 0; /* FIXME */
576
577 Spi->ResidentSystemDriverPage = 0; /* FIXME */
578 Spi->CcFastReadNoWait = 0; /* FIXME */
579 Spi->CcFastReadWait = 0; /* FIXME */
580 Spi->CcFastReadResourceMiss = 0; /* FIXME */
581 Spi->CcFastReadNotPossible = 0; /* FIXME */
582
583 Spi->CcFastMdlReadNoWait = 0; /* FIXME */
584 Spi->CcFastMdlReadWait = 0; /* FIXME */
585 Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
586 Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
587
588 Spi->CcMapDataNoWait = 0; /* FIXME */
589 Spi->CcMapDataWait = 0; /* FIXME */
590 Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
591 Spi->CcMapDataWaitMiss = 0; /* FIXME */
592
593 Spi->CcPinMappedDataCount = 0; /* FIXME */
594 Spi->CcPinReadNoWait = 0; /* FIXME */
595 Spi->CcPinReadWait = 0; /* FIXME */
596 Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
597 Spi->CcPinReadWaitMiss = 0; /* FIXME */
598 Spi->CcCopyReadNoWait = 0; /* FIXME */
599 Spi->CcCopyReadWait = 0; /* FIXME */
600 Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
601 Spi->CcCopyReadWaitMiss = 0; /* FIXME */
602
603 Spi->CcMdlReadNoWait = 0; /* FIXME */
604 Spi->CcMdlReadWait = 0; /* FIXME */
605 Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
606 Spi->CcMdlReadWaitMiss = 0; /* FIXME */
607 Spi->CcReadAheadIos = 0; /* FIXME */
608 Spi->CcLazyWriteIos = 0; /* FIXME */
609 Spi->CcLazyWritePages = 0; /* FIXME */
610 Spi->CcDataFlushes = 0; /* FIXME */
611 Spi->CcDataPages = 0; /* FIXME */
612 Spi->ContextSwitches = 0; /* FIXME */
613 Spi->FirstLevelTbFills = 0; /* FIXME */
614 Spi->SecondLevelTbFills = 0; /* FIXME */
615 Spi->SystemCalls = 0; /* FIXME */
616
617 return STATUS_SUCCESS;
618 }
619
620 /* Class 3 - Time Of Day Information */
621 QSI_DEF(SystemTimeOfDayInformation)
622 {
623 SYSTEM_TIMEOFDAY_INFORMATION Sti;
624 LARGE_INTEGER CurrentTime;
625
626 /* Set amount of written information to 0 */
627 *ReqSize = 0;
628
629 /* Check user buffer's size */
630 if (Size > sizeof(SYSTEM_TIMEOFDAY_INFORMATION))
631 {
632 return STATUS_INFO_LENGTH_MISMATCH;
633 }
634
635 /* Get current time */
636 KeQuerySystemTime(&CurrentTime);
637
638 /* Zero local buffer */
639 RtlZeroMemory(&Sti, sizeof(SYSTEM_TIMEOFDAY_INFORMATION));
640
641 /* Fill local time structure */
642 Sti.BootTime= KeBootTime;
643 Sti.CurrentTime = CurrentTime;
644 Sti.TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
645 Sti.TimeZoneId = ExpTimeZoneId;
646 Sti.Reserved = 0;
647
648 /* Copy as much as requested by caller */
649 RtlCopyMemory(Buffer, &Sti, Size);
650
651 /* Set amount of information we copied */
652 *ReqSize = Size;
653
654 return STATUS_SUCCESS;
655 }
656
657 /* Class 4 - Path Information */
658 QSI_DEF(SystemPathInformation)
659 {
660 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
661 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
662
663 return STATUS_BREAKPOINT;
664 }
665
666 /* Class 5 - Process Information */
667 QSI_DEF(SystemProcessInformation)
668 {
669 PSYSTEM_PROCESS_INFORMATION SpiCurrent;
670 PSYSTEM_THREAD_INFORMATION ThreadInfo;
671 PEPROCESS Process = NULL, SystemProcess;
672 PETHREAD CurrentThread;
673 ANSI_STRING ImageName;
674 ULONG CurrentSize;
675 USHORT ImageNameMaximumLength; // image name len in bytes
676 USHORT ImageNameLength;
677 PLIST_ENTRY CurrentEntry;
678 ULONG TotalSize = 0, ThreadsCount;
679 ULONG TotalUser, TotalKernel;
680 PUCHAR Current;
681 NTSTATUS Status = STATUS_SUCCESS;
682 PUNICODE_STRING ProcessImageName;
683 PWCHAR szSrc;
684 BOOLEAN Overflow = FALSE;
685
686 _SEH2_TRY
687 {
688 /* scan the process list */
689
690 PSYSTEM_PROCESS_INFORMATION Spi
691 = (PSYSTEM_PROCESS_INFORMATION) Buffer;
692
693 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
694
695 /* Check for overflow */
696 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
697 {
698 Overflow = TRUE;
699 }
700
701 /* Zero user's buffer */
702 if (!Overflow) RtlZeroMemory(Spi, Size);
703
704 SystemProcess = PsIdleProcess;
705 Process = SystemProcess;
706 Current = (PUCHAR) Spi;
707
708 do
709 {
710 SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
711
712 if ((Process->ProcessExiting) &&
713 (Process->Pcb.Header.SignalState) &&
714 !(Process->ActiveThreads) &&
715 (IsListEmpty(&Process->Pcb.ThreadListHead)))
716 {
717 DPRINT1("Process %p (%s:%lx) is a zombie\n",
718 Process, Process->ImageFileName, Process->UniqueProcessId);
719 CurrentSize = 0;
720 ImageNameMaximumLength = 0;
721 goto Skip;
722 }
723
724 ThreadsCount = 0;
725 CurrentEntry = Process->Pcb.ThreadListHead.Flink;
726 while (CurrentEntry != &Process->Pcb.ThreadListHead)
727 {
728 ThreadsCount++;
729 CurrentEntry = CurrentEntry->Flink;
730 }
731
732 // size of the structure for every process
733 CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
734 ImageNameLength = 0;
735 Status = SeLocateProcessImageName(Process, &ProcessImageName);
736 szSrc = NULL;
737 if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0))
738 {
739 szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length);
740 /* Loop the file name*/
741 while (szSrc > ProcessImageName->Buffer)
742 {
743 /* Make sure this isn't a backslash */
744 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR)
745 {
746 szSrc++;
747 break;
748 }
749 else
750 {
751 ImageNameLength += sizeof(WCHAR);
752 }
753 }
754 }
755 if (!ImageNameLength && Process != PsIdleProcess)
756 {
757 ImageNameLength = (USHORT)strlen(Process->ImageFileName) * sizeof(WCHAR);
758 }
759
760 /* Round up the image name length as NT does */
761 if (ImageNameLength > 0)
762 ImageNameMaximumLength = ROUND_UP(ImageNameLength + sizeof(WCHAR), 8);
763 else
764 ImageNameMaximumLength = 0;
765
766 TotalSize += CurrentSize + ImageNameMaximumLength;
767
768 /* Check for overflow */
769 if (TotalSize > Size)
770 {
771 Overflow = TRUE;
772 }
773
774 /* Fill system information */
775 if (!Overflow)
776 {
777 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginnnig of the next structure
778 SpiCurrent->NumberOfThreads = ThreadsCount;
779 SpiCurrent->CreateTime = Process->CreateTime;
780 SpiCurrent->ImageName.Length = ImageNameLength;
781 SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength;
782 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize);
783
784 /* Copy name to the end of the struct */
785 if(Process != PsIdleProcess)
786 {
787 if (szSrc)
788 {
789 RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
790
791 /* Release the memory allocated by SeLocateProcessImageName */
792 ExFreePool(ProcessImageName);
793 }
794 else
795 {
796 RtlInitAnsiString(&ImageName, Process->ImageFileName);
797 RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
798 }
799 }
800 else
801 {
802 RtlInitUnicodeString(&SpiCurrent->ImageName, NULL);
803 }
804
805 SpiCurrent->BasePriority = Process->Pcb.BasePriority;
806 SpiCurrent->UniqueProcessId = Process->UniqueProcessId;
807 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId;
808 SpiCurrent->HandleCount = ObGetProcessHandleCount(Process);
809 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize;
810 SpiCurrent->VirtualSize = Process->VirtualSize;
811 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount;
812 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
813 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize;
814 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
815 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[0];
816 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
817 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
818 SpiCurrent->PagefileUsage = Process->QuotaUsage[2];
819 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[2];
820 SpiCurrent->PrivatePageCount = Process->CommitCharge;
821 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
822
823 CurrentEntry = Process->Pcb.ThreadListHead.Flink;
824 while (CurrentEntry != &Process->Pcb.ThreadListHead)
825 {
826 CurrentThread = (PETHREAD)CONTAINING_RECORD(CurrentEntry, KTHREAD,
827 ThreadListEntry);
828
829 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
830 ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
831 ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart;
832 ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime;
833 ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress;
834 ThreadInfo->ClientId = CurrentThread->Cid;
835 ThreadInfo->Priority = CurrentThread->Tcb.Priority;
836 ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority;
837 ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches;
838 ThreadInfo->ThreadState = CurrentThread->Tcb.State;
839 ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason;
840
841 ThreadInfo++;
842 CurrentEntry = CurrentEntry->Flink;
843 }
844
845 /* Query total user/kernel times of a process */
846 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser);
847 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement);
848 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
849 }
850
851 /* Handle idle process entry */
852 Skip:
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 if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
1226 return ExGetPoolTagInfo(Buffer, Size, ReqSize);
1227 }
1228
1229 /* Class 23 - Interrupt Information for all processors */
1230 QSI_DEF(SystemInterruptInformation)
1231 {
1232 PKPRCB Prcb;
1233 LONG i;
1234 ULONG ti;
1235 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1236
1237 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1238 {
1239 return STATUS_INFO_LENGTH_MISMATCH;
1240 }
1241
1242 ti = KeQueryTimeIncrement();
1243
1244 for (i = 0; i < KeNumberProcessors; i++)
1245 {
1246 Prcb = KiProcessorBlock[i];
1247 sii->ContextSwitches = KeGetContextSwitches(Prcb);
1248 sii->DpcCount = Prcb->DpcData[0].DpcCount;
1249 sii->DpcRate = Prcb->DpcRequestRate;
1250 sii->TimeIncrement = ti;
1251 sii->DpcBypassCount = 0;
1252 sii->ApcBypassCount = 0;
1253 sii++;
1254 }
1255
1256 return STATUS_SUCCESS;
1257 }
1258
1259 /* Class 24 - DPC Behaviour Information */
1260 QSI_DEF(SystemDpcBehaviourInformation)
1261 {
1262 /* FIXME */
1263 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1264 return STATUS_NOT_IMPLEMENTED;
1265 }
1266
1267 SSI_DEF(SystemDpcBehaviourInformation)
1268 {
1269 /* FIXME */
1270 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1271 return STATUS_NOT_IMPLEMENTED;
1272 }
1273
1274 /* Class 25 - Full Memory Information */
1275 QSI_DEF(SystemFullMemoryInformation)
1276 {
1277 PULONG Spi = (PULONG) Buffer;
1278
1279 PEPROCESS TheIdleProcess;
1280
1281 *ReqSize = sizeof(ULONG);
1282
1283 if (sizeof(ULONG) != Size)
1284 {
1285 return STATUS_INFO_LENGTH_MISMATCH;
1286 }
1287
1288 DPRINT("SystemFullMemoryInformation\n");
1289
1290 TheIdleProcess = PsIdleProcess;
1291
1292 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1293 TheIdleProcess->UniqueProcessId,
1294 TheIdleProcess->Pcb.KernelTime,
1295 MiFreeSwapPages,
1296 MiUsedSwapPages);
1297
1298 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1299
1300 return STATUS_SUCCESS;
1301 }
1302
1303 /* Class 26 - Load Image */
1304 SSI_DEF(SystemLoadGdiDriverInformation)
1305 {
1306 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer;
1307 UNICODE_STRING ImageName;
1308 PVOID ImageBase;
1309 PVOID SectionPointer;
1310 ULONG_PTR EntryPoint;
1311 NTSTATUS Status;
1312 ULONG DirSize;
1313 PIMAGE_NT_HEADERS NtHeader;
1314
1315 /* Validate size */
1316 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION))
1317 {
1318 /* Incorrect buffer length, fail */
1319 return STATUS_INFO_LENGTH_MISMATCH;
1320 }
1321
1322 /* Only kernel mode can call this function */
1323 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1324
1325 /* Load the driver */
1326 ImageName = DriverInfo->DriverName;
1327 Status = MmLoadSystemImage(&ImageName,
1328 NULL,
1329 NULL,
1330 0,
1331 &SectionPointer,
1332 &ImageBase);
1333 if (!NT_SUCCESS(Status)) return Status;
1334
1335 /* Return the export pointer */
1336 DriverInfo->ExportSectionPointer =
1337 RtlImageDirectoryEntryToData(ImageBase,
1338 TRUE,
1339 IMAGE_DIRECTORY_ENTRY_EXPORT,
1340 &DirSize);
1341
1342 /* Get the entrypoint */
1343 NtHeader = RtlImageNtHeader(ImageBase);
1344 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1345 EntryPoint += (ULONG_PTR)ImageBase;
1346
1347 /* Save other data */
1348 DriverInfo->ImageAddress = ImageBase;
1349 DriverInfo->SectionPointer = SectionPointer;
1350 DriverInfo->EntryPoint = (PVOID)EntryPoint;
1351 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage;
1352
1353 /* All is good */
1354 return STATUS_SUCCESS;
1355 }
1356
1357 /* Class 27 - Unload Image */
1358 SSI_DEF(SystemUnloadGdiDriverInformation)
1359 {
1360 PVOID SectionPointer = Buffer;
1361
1362 /* Validate size */
1363 if (Size != sizeof(PVOID))
1364 {
1365 /* Incorrect length, fail */
1366 return STATUS_INFO_LENGTH_MISMATCH;
1367 }
1368
1369 /* Only kernel mode can call this function */
1370 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
1371
1372 /* Unload the image */
1373 MmUnloadSystemImage(SectionPointer);
1374 return STATUS_SUCCESS;
1375 }
1376
1377 /* Class 28 - Time Adjustment Information */
1378 QSI_DEF(SystemTimeAdjustmentInformation)
1379 {
1380 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo =
1381 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer;
1382
1383 /* Check if enough storage was provided */
1384 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size)
1385 {
1386 * ReqSize = sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION);
1387 return STATUS_INFO_LENGTH_MISMATCH;
1388 }
1389
1390 /* Give time values to our caller */
1391 TimeInfo->TimeIncrement = KeMaximumIncrement;
1392 TimeInfo->TimeAdjustment = KeTimeAdjustment;
1393 TimeInfo->Enable = !KiTimeAdjustmentEnabled;
1394
1395 return STATUS_SUCCESS;
1396 }
1397
1398 SSI_DEF(SystemTimeAdjustmentInformation)
1399 {
1400 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1401 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
1402 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;
1403
1404 /* Check size of a buffer, it must match our expectations */
1405 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
1406 return STATUS_INFO_LENGTH_MISMATCH;
1407
1408 /* Check who is calling */
1409 if (PreviousMode != KernelMode)
1410 {
1411 /* Check access rights */
1412 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode))
1413 {
1414 return STATUS_PRIVILEGE_NOT_HELD;
1415 }
1416 }
1417
1418 /* FIXME: behaviour suggests the member be named 'Disable' */
1419 if (TimeInfo->Enable)
1420 {
1421 /* Disable time adjustment and set default value */
1422 KiTimeAdjustmentEnabled = FALSE;
1423 KeTimeAdjustment = KeMaximumIncrement;
1424 }
1425 else
1426 {
1427 /* Check if a valid time adjustment value is given */
1428 if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2;
1429
1430 /* Enable time adjustment and set the adjustment value */
1431 KiTimeAdjustmentEnabled = TRUE;
1432 KeTimeAdjustment = TimeInfo->TimeAdjustment;
1433 }
1434
1435 return STATUS_SUCCESS;
1436 }
1437
1438 /* Class 29 - Summary Memory Information */
1439 QSI_DEF(SystemSummaryMemoryInformation)
1440 {
1441 /* FIXME */
1442 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1443 return STATUS_NOT_IMPLEMENTED;
1444 }
1445
1446 /* Class 30 - Next Event Id Information */
1447 QSI_DEF(SystemNextEventIdInformation)
1448 {
1449 /* FIXME */
1450 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1451 return STATUS_NOT_IMPLEMENTED;
1452 }
1453
1454 /* Class 31 - Event Ids Information */
1455 QSI_DEF(SystemEventIdsInformation)
1456 {
1457 /* FIXME */
1458 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1459 return STATUS_NOT_IMPLEMENTED;
1460 }
1461
1462 /* Class 32 - Crash Dump Information */
1463 QSI_DEF(SystemCrashDumpInformation)
1464 {
1465 /* FIXME */
1466 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1467 return STATUS_NOT_IMPLEMENTED;
1468 }
1469
1470 /* Class 33 - Exception Information */
1471 QSI_DEF(SystemExceptionInformation)
1472 {
1473 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation =
1474 (PSYSTEM_EXCEPTION_INFORMATION)Buffer;
1475 PKPRCB Prcb;
1476 ULONG AlignmentFixupCount = 0, ExceptionDispatchCount = 0;
1477 ULONG FloatingEmulationCount = 0, ByteWordEmulationCount = 0;
1478 CHAR i;
1479
1480 /* Check size of a buffer, it must match our expectations */
1481 if (sizeof(SYSTEM_EXCEPTION_INFORMATION) != Size)
1482 return STATUS_INFO_LENGTH_MISMATCH;
1483
1484 /* Sum up exception count information from all processors */
1485 for (i = 0; i < KeNumberProcessors; i++)
1486 {
1487 Prcb = KiProcessorBlock[i];
1488 if (Prcb)
1489 {
1490 AlignmentFixupCount += Prcb->KeAlignmentFixupCount;
1491 ExceptionDispatchCount += Prcb->KeExceptionDispatchCount;
1492 FloatingEmulationCount += Prcb->KeFloatingEmulationCount;
1493 }
1494 }
1495
1496 /* Save information in user's buffer */
1497 ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount;
1498 ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount;
1499 ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount;
1500 ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount;
1501
1502 return STATUS_SUCCESS;
1503 }
1504
1505 /* Class 34 - Crash Dump State Information */
1506 QSI_DEF(SystemCrashDumpStateInformation)
1507 {
1508 /* FIXME */
1509 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1510 return STATUS_NOT_IMPLEMENTED;
1511 }
1512
1513 /* Class 35 - Kernel Debugger Information */
1514 QSI_DEF(SystemKernelDebuggerInformation)
1515 {
1516 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1517
1518 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1519 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1520 {
1521 return STATUS_INFO_LENGTH_MISMATCH;
1522 }
1523
1524 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1525 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1526
1527 return STATUS_SUCCESS;
1528 }
1529
1530 /* Class 36 - Context Switch Information */
1531 QSI_DEF(SystemContextSwitchInformation)
1532 {
1533 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation =
1534 (PSYSTEM_CONTEXT_SWITCH_INFORMATION)Buffer;
1535 ULONG ContextSwitches;
1536 PKPRCB Prcb;
1537 CHAR i;
1538
1539 /* Check size of a buffer, it must match our expectations */
1540 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION) != Size)
1541 return STATUS_INFO_LENGTH_MISMATCH;
1542
1543 /* Calculate total value of context switches across all processors */
1544 ContextSwitches = 0;
1545 for (i = 0; i < KeNumberProcessors; i ++)
1546 {
1547 Prcb = KiProcessorBlock[i];
1548 if (Prcb)
1549 {
1550 ContextSwitches += KeGetContextSwitches(Prcb);
1551 }
1552 }
1553
1554 ContextSwitchInformation->ContextSwitches = ContextSwitches;
1555
1556 /* FIXME */
1557 ContextSwitchInformation->FindAny = 0;
1558 ContextSwitchInformation->FindLast = 0;
1559 ContextSwitchInformation->FindIdeal = 0;
1560 ContextSwitchInformation->IdleAny = 0;
1561 ContextSwitchInformation->IdleCurrent = 0;
1562 ContextSwitchInformation->IdleLast = 0;
1563 ContextSwitchInformation->IdleIdeal = 0;
1564 ContextSwitchInformation->PreemptAny = 0;
1565 ContextSwitchInformation->PreemptCurrent = 0;
1566 ContextSwitchInformation->PreemptLast = 0;
1567 ContextSwitchInformation->SwitchToIdle = 0;
1568
1569 return STATUS_SUCCESS;
1570 }
1571
1572 /* Class 37 - Registry Quota Information */
1573 QSI_DEF(SystemRegistryQuotaInformation)
1574 {
1575 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1576
1577 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1578 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1579 {
1580 return STATUS_INFO_LENGTH_MISMATCH;
1581 }
1582
1583 DPRINT1("Faking max registry size of 32 MB\n");
1584 srqi->RegistryQuotaAllowed = 0x2000000;
1585 srqi->RegistryQuotaUsed = 0x200000;
1586 srqi->PagedPoolSize = 0x200000;
1587
1588 return STATUS_SUCCESS;
1589 }
1590
1591 SSI_DEF(SystemRegistryQuotaInformation)
1592 {
1593 /* FIXME */
1594 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1595 return STATUS_NOT_IMPLEMENTED;
1596 }
1597
1598 /* Class 38 - Load And Call Image */
1599 SSI_DEF(SystemExtendServiceTableInformation)
1600 {
1601 UNICODE_STRING ImageName;
1602 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1603 PLDR_DATA_TABLE_ENTRY ModuleObject;
1604 NTSTATUS Status;
1605 PIMAGE_NT_HEADERS NtHeader;
1606 DRIVER_OBJECT Win32k;
1607 PDRIVER_INITIALIZE DriverInit;
1608 PVOID ImageBase;
1609 ULONG_PTR EntryPoint;
1610
1611 /* Validate the size */
1612 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH;
1613
1614 /* Check who is calling */
1615 if (PreviousMode != KernelMode)
1616 {
1617 /* Make sure we can load drivers */
1618 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
1619 {
1620 /* FIXME: We can't, fail */
1621 //return STATUS_PRIVILEGE_NOT_HELD;
1622 }
1623 }
1624
1625 /* Probe and capture the driver name */
1626 ProbeAndCaptureUnicodeString(&ImageName, PreviousMode, Buffer);
1627
1628 /* Load the image */
1629 Status = MmLoadSystemImage(&ImageName,
1630 NULL,
1631 NULL,
1632 0,
1633 (PVOID)&ModuleObject,
1634 &ImageBase);
1635
1636 /* Release String */
1637 ReleaseCapturedUnicodeString(&ImageName, PreviousMode);
1638
1639 if (!NT_SUCCESS(Status)) return Status;
1640
1641 /* Get the headers */
1642 NtHeader = RtlImageNtHeader(ImageBase);
1643 if (!NtHeader)
1644 {
1645 /* Fail */
1646 MmUnloadSystemImage(ModuleObject);
1647 return STATUS_INVALID_IMAGE_FORMAT;
1648 }
1649
1650 /* Get the entrypoint */
1651 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
1652 EntryPoint += (ULONG_PTR)ImageBase;
1653 DriverInit = (PDRIVER_INITIALIZE)EntryPoint;
1654
1655 /* Create a dummy device */
1656 RtlZeroMemory(&Win32k, sizeof(Win32k));
1657 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1658 Win32k.DriverStart = ImageBase;
1659
1660 /* Call it */
1661 Status = (DriverInit)(&Win32k, NULL);
1662 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
1663
1664 /* Unload if we failed */
1665 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject);
1666 return Status;
1667 }
1668
1669 /* Class 39 - Priority Separation */
1670 SSI_DEF(SystemPrioritySeperation)
1671 {
1672 /* FIXME */
1673 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1674 return STATUS_NOT_IMPLEMENTED;
1675 }
1676
1677 /* Class 40 - Plug Play Bus Information */
1678 QSI_DEF(SystemPlugPlayBusInformation)
1679 {
1680 /* FIXME */
1681 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1682 return STATUS_NOT_IMPLEMENTED;
1683 }
1684
1685 /* Class 41 - Dock Information */
1686 QSI_DEF(SystemDockInformation)
1687 {
1688 /* FIXME */
1689 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1690 return STATUS_NOT_IMPLEMENTED;
1691 }
1692
1693 /* Class 42 - Power Information */
1694 QSI_DEF(SystemPowerInformation)
1695 {
1696 /* FIXME */
1697 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1698 return STATUS_NOT_IMPLEMENTED;
1699 }
1700
1701 /* Class 43 - Processor Speed Information */
1702 QSI_DEF(SystemProcessorSpeedInformation)
1703 {
1704 /* FIXME */
1705 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1706 return STATUS_NOT_IMPLEMENTED;
1707 }
1708
1709 /* Class 44 - Current Time Zone Information */
1710 QSI_DEF(SystemCurrentTimeZoneInformation)
1711 {
1712 *ReqSize = sizeof(TIME_ZONE_INFORMATION);
1713
1714 if (sizeof(TIME_ZONE_INFORMATION) != Size)
1715 {
1716 return STATUS_INFO_LENGTH_MISMATCH;
1717 }
1718
1719 /* Copy the time zone information struct */
1720 memcpy(Buffer,
1721 &ExpTimeZoneInfo,
1722 sizeof(TIME_ZONE_INFORMATION));
1723
1724 return STATUS_SUCCESS;
1725 }
1726
1727
1728 SSI_DEF(SystemCurrentTimeZoneInformation)
1729 {
1730 /* Check user buffer's size */
1731 if (Size < sizeof(TIME_ZONE_INFORMATION))
1732 {
1733 return STATUS_INFO_LENGTH_MISMATCH;
1734 }
1735
1736 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1737 }
1738
1739
1740 /* Class 45 - Lookaside Information */
1741 QSI_DEF(SystemLookasideInformation)
1742 {
1743 /* FIXME */
1744 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1745 return STATUS_NOT_IMPLEMENTED;
1746 }
1747
1748
1749 /* Class 46 - Set time slip event */
1750 SSI_DEF(SystemSetTimeSlipEvent)
1751 {
1752 /* FIXME */
1753 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1754 return STATUS_NOT_IMPLEMENTED;
1755 }
1756
1757 NTSTATUS
1758 NTAPI
1759 MmSessionCreate(OUT PULONG SessionId);
1760
1761 NTSTATUS
1762 NTAPI
1763 MmSessionDelete(IN ULONG SessionId);
1764
1765 /* Class 47 - Create a new session (TSE) */
1766 SSI_DEF(SystemCreateSession)
1767 {
1768 ULONG SessionId;
1769 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1770 NTSTATUS Status;
1771
1772 if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
1773
1774 if (PreviousMode != KernelMode)
1775 {
1776 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
1777 {
1778 return STATUS_PRIVILEGE_NOT_HELD;
1779 }
1780 }
1781
1782 Status = MmSessionCreate(&SessionId);
1783 if (NT_SUCCESS(Status)) *(PULONG)Buffer = SessionId;
1784
1785 return Status;
1786 }
1787
1788
1789 /* Class 48 - Delete an existing session (TSE) */
1790 SSI_DEF(SystemDeleteSession)
1791 {
1792 ULONG SessionId;
1793 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
1794
1795 if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
1796
1797 if (PreviousMode != KernelMode)
1798 {
1799 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
1800 {
1801 return STATUS_PRIVILEGE_NOT_HELD;
1802 }
1803 }
1804
1805 SessionId = *(PULONG)Buffer;
1806
1807 return MmSessionDelete(SessionId);
1808 }
1809
1810
1811 /* Class 49 - UNKNOWN */
1812 QSI_DEF(SystemInvalidInfoClass4)
1813 {
1814 /* FIXME */
1815 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1816 return STATUS_NOT_IMPLEMENTED;
1817 }
1818
1819
1820 /* Class 50 - System range start address */
1821 QSI_DEF(SystemRangeStartInformation)
1822 {
1823 /* Check user buffer's size */
1824 if (Size != sizeof(ULONG_PTR)) return STATUS_INFO_LENGTH_MISMATCH;
1825
1826 *(PULONG_PTR)Buffer = (ULONG_PTR)MmSystemRangeStart;
1827
1828 if (ReqSize) *ReqSize = sizeof(ULONG_PTR);
1829
1830 return STATUS_SUCCESS;
1831 }
1832
1833 /* Class 51 - Driver verifier information */
1834 QSI_DEF(SystemVerifierInformation)
1835 {
1836 /* FIXME */
1837 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1838 return STATUS_NOT_IMPLEMENTED;
1839 }
1840
1841
1842 SSI_DEF(SystemVerifierInformation)
1843 {
1844 /* FIXME */
1845 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1846 return STATUS_NOT_IMPLEMENTED;
1847 }
1848
1849
1850 /* Class 52 - Add a driver verifier */
1851 SSI_DEF(SystemAddVerifier)
1852 {
1853 /* FIXME */
1854 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1855 return STATUS_NOT_IMPLEMENTED;
1856 }
1857
1858
1859 /* Class 53 - A session's processes */
1860 QSI_DEF(SystemSessionProcessesInformation)
1861 {
1862 /* FIXME */
1863 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1864 return STATUS_NOT_IMPLEMENTED;
1865 }
1866
1867
1868 /* Query/Set Calls Table */
1869 typedef
1870 struct _QSSI_CALLS
1871 {
1872 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1873 NTSTATUS (* Set) (PVOID,ULONG);
1874
1875 } QSSI_CALLS;
1876
1877 // QS Query & Set
1878 // QX Query
1879 // XS Set
1880 // XX unknown behaviour
1881 //
1882 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1883 #define SI_QX(n) {QSI_USE(n),NULL}
1884 #define SI_XS(n) {NULL,SSI_USE(n)}
1885 #define SI_XX(n) {NULL,NULL}
1886
1887 static
1888 QSSI_CALLS
1889 CallQS [] =
1890 {
1891 SI_QX(SystemBasicInformation),
1892 SI_QX(SystemProcessorInformation),
1893 SI_QX(SystemPerformanceInformation),
1894 SI_QX(SystemTimeOfDayInformation),
1895 SI_QX(SystemPathInformation), /* should be SI_XX */
1896 SI_QX(SystemProcessInformation),
1897 SI_QX(SystemCallCountInformation),
1898 SI_QX(SystemDeviceInformation),
1899 SI_QX(SystemProcessorPerformanceInformation),
1900 SI_QS(SystemFlagsInformation),
1901 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1902 SI_QX(SystemModuleInformation),
1903 SI_QX(SystemLocksInformation),
1904 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1905 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1906 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1907 SI_QX(SystemHandleInformation),
1908 SI_QX(SystemObjectInformation),
1909 SI_QX(SystemPageFileInformation),
1910 SI_QX(SystemVdmInstemulInformation),
1911 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1912 SI_QS(SystemFileCacheInformation),
1913 SI_QX(SystemPoolTagInformation),
1914 SI_QX(SystemInterruptInformation),
1915 SI_QS(SystemDpcBehaviourInformation),
1916 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1917 SI_XS(SystemLoadGdiDriverInformation),
1918 SI_XS(SystemUnloadGdiDriverInformation),
1919 SI_QS(SystemTimeAdjustmentInformation),
1920 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1921 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1922 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1923 SI_QX(SystemCrashDumpInformation),
1924 SI_QX(SystemExceptionInformation),
1925 SI_QX(SystemCrashDumpStateInformation),
1926 SI_QX(SystemKernelDebuggerInformation),
1927 SI_QX(SystemContextSwitchInformation),
1928 SI_QS(SystemRegistryQuotaInformation),
1929 SI_XS(SystemExtendServiceTableInformation),
1930 SI_XS(SystemPrioritySeperation),
1931 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1932 SI_QX(SystemDockInformation), /* it should be SI_XX */
1933 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1934 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1935 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1936 SI_QX(SystemLookasideInformation),
1937 SI_XS(SystemSetTimeSlipEvent),
1938 SI_XS(SystemCreateSession),
1939 SI_XS(SystemDeleteSession),
1940 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1941 SI_QX(SystemRangeStartInformation),
1942 SI_QS(SystemVerifierInformation),
1943 SI_XS(SystemAddVerifier),
1944 SI_QX(SystemSessionProcessesInformation)
1945 };
1946
1947 C_ASSERT(SystemBasicInformation == 0);
1948 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation)
1949 #define MAX_SYSTEM_INFO_CLASS (sizeof(CallQS) / sizeof(CallQS[0]))
1950
1951 /*
1952 * @implemented
1953 */
1954 NTSTATUS NTAPI
1955 NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1956 OUT PVOID SystemInformation,
1957 IN ULONG Length,
1958 OUT PULONG UnsafeResultLength)
1959 {
1960 KPROCESSOR_MODE PreviousMode;
1961 ULONG ResultLength;
1962 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1963
1964 PAGED_CODE();
1965
1966 PreviousMode = ExGetPreviousMode();
1967
1968 _SEH2_TRY
1969 {
1970 if (PreviousMode != KernelMode)
1971 {
1972 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1973 ProbeForWrite(SystemInformation, Length, 1);
1974 if (UnsafeResultLength != NULL)
1975 ProbeForWriteUlong(UnsafeResultLength);
1976 }
1977
1978 /*
1979 * Check the request is valid.
1980 */
1981 if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
1982 {
1983 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
1984 }
1985
1986 if (NULL != CallQS [SystemInformationClass].Query)
1987 {
1988 /*
1989 * Hand the request to a subhandler.
1990 */
1991 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1992 Length,
1993 &ResultLength);
1994
1995 /* Save the result length to the caller */
1996 if (UnsafeResultLength)
1997 *UnsafeResultLength = ResultLength;
1998 }
1999 }
2000 _SEH2_EXCEPT(ExSystemExceptionFilter())
2001 {
2002 FStatus = _SEH2_GetExceptionCode();
2003 }
2004 _SEH2_END;
2005
2006 return FStatus;
2007 }
2008
2009
2010 NTSTATUS
2011 NTAPI
2012 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
2013 IN PVOID SystemInformation,
2014 IN ULONG SystemInformationLength)
2015 {
2016 PAGED_CODE();
2017
2018 /*
2019 * If called from user mode, check
2020 * possible unsafe arguments.
2021 */
2022 #if 0
2023 if (KernelMode != KeGetPreviousMode())
2024 {
2025 // Check arguments
2026 //ProbeForWrite(
2027 // SystemInformation,
2028 // Length
2029 // );
2030 //ProbeForWrite(
2031 // ResultLength,
2032 // sizeof (ULONG)
2033 // );
2034 }
2035 #endif
2036 /*
2037 * Check the request is valid.
2038 */
2039 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
2040 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
2041 {
2042 if (NULL != CallQS [SystemInformationClass].Set)
2043 {
2044 /*
2045 * Hand the request to a subhandler.
2046 */
2047 return CallQS [SystemInformationClass].Set(SystemInformation,
2048 SystemInformationLength);
2049 }
2050 }
2051
2052 return STATUS_INVALID_INFO_CLASS;
2053 }
2054
2055 NTSTATUS
2056 NTAPI
2057 NtFlushInstructionCache(IN HANDLE ProcessHandle,
2058 IN PVOID BaseAddress,
2059 IN ULONG NumberOfBytesToFlush)
2060 {
2061 PAGED_CODE();
2062
2063 #if defined(_M_IX86) || defined(_M_AMD64)
2064 __wbinvd();
2065 #elif defined(_M_PPC)
2066 __asm__ __volatile__("tlbsync");
2067 #elif defined(_M_MIPS)
2068 DPRINT1("NtFlushInstructionCache() is not implemented\n");
2069 for (;;);
2070 #elif defined(_M_ARM)
2071 __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
2072 #else
2073 #error Unknown architecture
2074 #endif
2075 return STATUS_SUCCESS;
2076 }
2077
2078 ULONG
2079 NTAPI
2080 NtGetCurrentProcessorNumber(VOID)
2081 {
2082 /* Just return the CPU */
2083 return KeGetCurrentProcessorNumber();
2084 }
2085
2086 /*
2087 * @implemented
2088 */
2089 #undef ExGetPreviousMode
2090 KPROCESSOR_MODE
2091 NTAPI
2092 ExGetPreviousMode (VOID)
2093 {
2094 return KeGetPreviousMode();
2095 }