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