Merge 25584, 25588.
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/sysinfo.c
6 * PURPOSE: System information functions
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Aleksey Bragin (aleksey@studiocerebral.com)
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 extern PEPROCESS PsIdleProcess;
19 extern ULONG NtGlobalFlag; /* FIXME: it should go in a ddk/?.h */
20 ULONGLONG STDCALL KeQueryInterruptTime(VOID);
21
22 VOID MmPrintMemoryStatistic(VOID);
23
24 FAST_MUTEX ExpEnvironmentLock;
25 ERESOURCE ExpFirmwareTableResource;
26 LIST_ENTRY ExpFirmwareTableProviderListHead;
27
28 /* FUNCTIONS *****************************************************************/
29
30 /*
31 * @implemented
32 */
33 #undef ExGetPreviousMode
34 KPROCESSOR_MODE
35 NTAPI
36 ExGetPreviousMode (VOID)
37 {
38 return KeGetPreviousMode();
39 }
40
41 /*
42 * @unimplemented
43 */
44 VOID
45 STDCALL
46 ExEnumHandleTable (
47 PULONG HandleTable,
48 PVOID Callback,
49 PVOID Param,
50 PHANDLE Handle OPTIONAL
51 )
52 {
53 UNIMPLEMENTED;
54 }
55
56 /*
57 * @implemented
58 */
59 VOID
60 STDCALL
61 ExGetCurrentProcessorCpuUsage (
62 PULONG CpuUsage
63 )
64 {
65 PKPRCB Prcb;
66 ULONG TotalTime;
67 ULONGLONG ScaledIdle;
68
69 Prcb = KeGetCurrentPrcb();
70
71 ScaledIdle = Prcb->IdleThread->KernelTime * 100;
72 TotalTime = Prcb->KernelTime + Prcb->UserTime;
73 if (TotalTime != 0)
74 *CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime));
75 else
76 *CpuUsage = 0;
77 }
78
79 /*
80 * @implemented
81 */
82 VOID
83 STDCALL
84 ExGetCurrentProcessorCounts (
85 PULONG ThreadKernelTime,
86 PULONG TotalCpuTime,
87 PULONG ProcessorNumber
88 )
89 {
90 PKPRCB Prcb;
91
92 Prcb = KeGetCurrentPrcb();
93
94 *ThreadKernelTime = Prcb->KernelTime + Prcb->UserTime;
95 *TotalCpuTime = Prcb->CurrentThread->KernelTime;
96 *ProcessorNumber = KeGetCurrentProcessorNumber();
97 }
98
99 /*
100 * @implemented
101 */
102 BOOLEAN
103 STDCALL
104 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
105 {
106 /* Quick check to see if it exists at all */
107 if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
108
109 /* Return our support for it */
110 return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
111 }
112
113 /*
114 * @implemented
115 */
116 BOOLEAN
117 STDCALL
118 ExVerifySuite(SUITE_TYPE SuiteType)
119 {
120 if (SuiteType == Personal) return TRUE;
121 return FALSE;
122 }
123
124 NTSTATUS STDCALL
125 NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
126 OUT PWSTR ValueBuffer,
127 IN ULONG ValueBufferLength,
128 IN OUT PULONG ReturnLength OPTIONAL)
129 {
130 ANSI_STRING AName;
131 UNICODE_STRING WName;
132 BOOLEAN Result;
133 PCH Value;
134 ANSI_STRING AValue;
135 UNICODE_STRING WValue;
136 KPROCESSOR_MODE PreviousMode;
137 NTSTATUS Status = STATUS_SUCCESS;
138
139 PAGED_CODE();
140
141 PreviousMode = ExGetPreviousMode();
142
143 if(PreviousMode != KernelMode)
144 {
145 _SEH_TRY
146 {
147 ProbeForRead(VariableName,
148 sizeof(UNICODE_STRING),
149 sizeof(ULONG));
150 ProbeForWrite(ValueBuffer,
151 ValueBufferLength,
152 sizeof(WCHAR));
153 if(ReturnLength != NULL)
154 {
155 ProbeForWriteUlong(ReturnLength);
156 }
157 }
158 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
159 {
160 Status = _SEH_GetExceptionCode();
161 }
162 _SEH_END;
163
164 if(!NT_SUCCESS(Status))
165 {
166 return Status;
167 }
168 }
169
170 /*
171 * Copy the name to kernel space if necessary and convert it to ANSI.
172 */
173 Status = ProbeAndCaptureUnicodeString(&WName,
174 PreviousMode,
175 VariableName);
176 if(NT_SUCCESS(Status))
177 {
178 /*
179 * according to ntinternals the SeSystemEnvironmentName privilege is required!
180 */
181 if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
182 PreviousMode))
183 {
184 ReleaseCapturedUnicodeString(&WName,
185 PreviousMode);
186 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
187 return STATUS_PRIVILEGE_NOT_HELD;
188 }
189
190 /*
191 * convert the value name to ansi
192 */
193 Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
194 ReleaseCapturedUnicodeString(&WName,
195 PreviousMode);
196 if(!NT_SUCCESS(Status))
197 {
198 return Status;
199 }
200
201 /*
202 * Create a temporary buffer for the value
203 */
204 Value = ExAllocatePool(NonPagedPool, ValueBufferLength);
205 if (Value == NULL)
206 {
207 RtlFreeAnsiString(&AName);
208 return STATUS_INSUFFICIENT_RESOURCES;
209 }
210
211 /*
212 * Get the environment variable
213 */
214 Result = HalGetEnvironmentVariable(AName.Buffer,
215 (USHORT)ValueBufferLength,
216 Value);
217 if(!Result)
218 {
219 RtlFreeAnsiString(&AName);
220 ExFreePool(Value);
221 return STATUS_UNSUCCESSFUL;
222 }
223
224 /*
225 * Convert the result to UNICODE, protect with SEH in case the value buffer
226 * isn't NULL-terminated!
227 */
228 _SEH_TRY
229 {
230 RtlInitAnsiString(&AValue, Value);
231 Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
232 }
233 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
234 {
235 Status = _SEH_GetExceptionCode();
236 }
237 _SEH_END;
238
239 if(NT_SUCCESS(Status))
240 {
241 /*
242 * Copy the result back to the caller.
243 */
244 _SEH_TRY
245 {
246 RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
247 ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
248 if(ReturnLength != NULL)
249 {
250 *ReturnLength = WValue.Length + sizeof(WCHAR);
251 }
252
253 Status = STATUS_SUCCESS;
254 }
255 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
256 {
257 Status = _SEH_GetExceptionCode();
258 }
259 _SEH_END;
260 }
261
262 /*
263 * Cleanup allocated resources.
264 */
265 RtlFreeAnsiString(&AName);
266 ExFreePool(Value);
267 }
268
269 return Status;
270 }
271
272
273 NTSTATUS STDCALL
274 NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName,
275 IN PUNICODE_STRING Value)
276 {
277 UNICODE_STRING CapturedName, CapturedValue;
278 ANSI_STRING AName, AValue;
279 KPROCESSOR_MODE PreviousMode;
280 NTSTATUS Status;
281
282 PAGED_CODE();
283
284 PreviousMode = ExGetPreviousMode();
285
286 /*
287 * Copy the strings to kernel space if necessary
288 */
289 Status = ProbeAndCaptureUnicodeString(&CapturedName,
290 PreviousMode,
291 VariableName);
292 if(NT_SUCCESS(Status))
293 {
294 Status = ProbeAndCaptureUnicodeString(&CapturedValue,
295 PreviousMode,
296 Value);
297 if(NT_SUCCESS(Status))
298 {
299 /*
300 * according to ntinternals the SeSystemEnvironmentName privilege is required!
301 */
302 if(SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
303 PreviousMode))
304 {
305 /*
306 * convert the strings to ANSI
307 */
308 Status = RtlUnicodeStringToAnsiString(&AName,
309 &CapturedName,
310 TRUE);
311 if(NT_SUCCESS(Status))
312 {
313 Status = RtlUnicodeStringToAnsiString(&AValue,
314 &CapturedValue,
315 TRUE);
316 if(NT_SUCCESS(Status))
317 {
318 BOOLEAN Result = HalSetEnvironmentVariable(AName.Buffer,
319 AValue.Buffer);
320
321 Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
322 }
323 }
324 }
325 else
326 {
327 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
328 Status = STATUS_PRIVILEGE_NOT_HELD;
329 }
330
331 ReleaseCapturedUnicodeString(&CapturedValue,
332 PreviousMode);
333 }
334
335 ReleaseCapturedUnicodeString(&CapturedName,
336 PreviousMode);
337 }
338
339 return Status;
340 }
341
342 NTSTATUS
343 NTAPI
344 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass,
345 IN PVOID Buffer,
346 IN ULONG BufferLength)
347 {
348 UNIMPLEMENTED;
349 return STATUS_NOT_IMPLEMENTED;
350 }
351
352 NTSTATUS
353 NTAPI
354 NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
355 IN LPGUID VendorGuid,
356 IN PVOID Value,
357 IN OUT PULONG ReturnLength,
358 IN OUT PULONG Attributes)
359 {
360 UNIMPLEMENTED;
361 return STATUS_NOT_IMPLEMENTED;
362 }
363
364 NTSTATUS
365 NTAPI
366 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
367 IN LPGUID VendorGuid)
368 {
369 UNIMPLEMENTED;
370 return STATUS_NOT_IMPLEMENTED;
371 }
372
373 /* --- Query/Set System Information --- */
374
375 /*
376 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
377 * so the stack is popped only in one place on x86 platform.
378 */
379 #define QSI_USE(n) QSI##n
380 #define QSI_DEF(n) \
381 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
382
383 #define SSI_USE(n) SSI##n
384 #define SSI_DEF(n) \
385 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
386
387
388 /* Class 0 - Basic Information */
389 QSI_DEF(SystemBasicInformation)
390 {
391 PSYSTEM_BASIC_INFORMATION Sbi
392 = (PSYSTEM_BASIC_INFORMATION) Buffer;
393
394 *ReqSize = sizeof (SYSTEM_BASIC_INFORMATION);
395 /*
396 * Check user buffer's size
397 */
398 if (Size != sizeof (SYSTEM_BASIC_INFORMATION))
399 {
400 return (STATUS_INFO_LENGTH_MISMATCH);
401 }
402 Sbi->Reserved = 0;
403 Sbi->TimerResolution = KeMaximumIncrement;
404 Sbi->PageSize = PAGE_SIZE;
405 Sbi->NumberOfPhysicalPages = MmStats.NrTotalPages;
406 Sbi->LowestPhysicalPageNumber = 0; /* FIXME */
407 Sbi->HighestPhysicalPageNumber = MmStats.NrTotalPages; /* FIXME */
408 Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
409 Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
410 Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
411 Sbi->ActiveProcessorsAffinityMask = KeActiveProcessors;
412 Sbi->NumberOfProcessors = KeNumberProcessors;
413 return (STATUS_SUCCESS);
414 }
415
416 /* Class 1 - Processor Information */
417 QSI_DEF(SystemProcessorInformation)
418 {
419 PSYSTEM_PROCESSOR_INFORMATION Spi
420 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
421 PKPRCB Prcb;
422 *ReqSize = sizeof (SYSTEM_PROCESSOR_INFORMATION);
423 /*
424 * Check user buffer's size
425 */
426 if (Size < sizeof (SYSTEM_PROCESSOR_INFORMATION))
427 {
428 return (STATUS_INFO_LENGTH_MISMATCH);
429 }
430 Prcb = KeGetCurrentPrcb();
431 Spi->ProcessorArchitecture = 0; /* Intel Processor */
432 Spi->ProcessorLevel = Prcb->CpuType;
433 Spi->ProcessorRevision = Prcb->CpuStep;
434 Spi->Reserved = 0;
435 Spi->ProcessorFeatureBits = Prcb->FeatureBits;
436
437 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
438 Spi->ProcessorLevel, Spi->ProcessorRevision);
439
440 return (STATUS_SUCCESS);
441 }
442
443 /* Class 2 - Performance Information */
444 QSI_DEF(SystemPerformanceInformation)
445 {
446 PSYSTEM_PERFORMANCE_INFORMATION Spi
447 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
448
449 PEPROCESS TheIdleProcess;
450
451 *ReqSize = sizeof (SYSTEM_PERFORMANCE_INFORMATION);
452 /*
453 * Check user buffer's size
454 */
455 if (Size < sizeof (SYSTEM_PERFORMANCE_INFORMATION))
456 {
457 return (STATUS_INFO_LENGTH_MISMATCH);
458 }
459
460 TheIdleProcess = PsIdleProcess;
461
462 Spi->IdleProcessTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000LL;
463
464 Spi->IoReadTransferCount = IoReadTransferCount;
465 Spi->IoWriteTransferCount = IoWriteTransferCount;
466 Spi->IoOtherTransferCount = IoOtherTransferCount;
467 Spi->IoReadOperationCount = IoReadOperationCount;
468 Spi->IoWriteOperationCount = IoWriteOperationCount;
469 Spi->IoOtherOperationCount = IoOtherOperationCount;
470
471 Spi->AvailablePages = MmStats.NrFreePages;
472 /*
473 Add up all the used "Commitied" memory + pagefile.
474 Not sure this is right. 8^\
475 */
476 Spi->CommittedPages = MiMemoryConsumers[MC_PPOOL].PagesUsed +
477 MiMemoryConsumers[MC_NPPOOL].PagesUsed+
478 MiMemoryConsumers[MC_CACHE].PagesUsed+
479 MiMemoryConsumers[MC_USER].PagesUsed+
480 MiUsedSwapPages;
481 /*
482 Add up the full system total + pagefile.
483 All this make Taskmgr happy but not sure it is the right numbers.
484 This too, fixes some of GlobalMemoryStatusEx numbers.
485 */
486 Spi->CommitLimit = MmStats.NrTotalPages + MiFreeSwapPages +
487 MiUsedSwapPages;
488
489 Spi->PeakCommitment = 0; /* FIXME */
490 Spi->PageFaultCount = 0; /* FIXME */
491 Spi->CopyOnWriteCount = 0; /* FIXME */
492 Spi->TransitionCount = 0; /* FIXME */
493 Spi->CacheTransitionCount = 0; /* FIXME */
494 Spi->DemandZeroCount = 0; /* FIXME */
495 Spi->PageReadCount = 0; /* FIXME */
496 Spi->PageReadIoCount = 0; /* FIXME */
497 Spi->CacheReadCount = 0; /* FIXME */
498 Spi->CacheIoCount = 0; /* FIXME */
499 Spi->DirtyPagesWriteCount = 0; /* FIXME */
500 Spi->DirtyWriteIoCount = 0; /* FIXME */
501 Spi->MappedPagesWriteCount = 0; /* FIXME */
502 Spi->MappedWriteIoCount = 0; /* FIXME */
503
504 Spi->PagedPoolPages = MiMemoryConsumers[MC_PPOOL].PagesUsed;
505 Spi->PagedPoolAllocs = 0; /* FIXME */
506 Spi->PagedPoolFrees = 0; /* FIXME */
507 Spi->NonPagedPoolPages = MiMemoryConsumers[MC_NPPOOL].PagesUsed;
508 Spi->NonPagedPoolAllocs = 0; /* FIXME */
509 Spi->NonPagedPoolFrees = 0; /* FIXME */
510
511 Spi->FreeSystemPtes = 0; /* FIXME */
512
513 Spi->ResidentSystemCodePage = MmStats.NrSystemPages; /* FIXME */
514
515 Spi->TotalSystemDriverPages = 0; /* FIXME */
516 Spi->TotalSystemCodePages = 0; /* FIXME */
517 Spi->NonPagedPoolLookasideHits = 0; /* FIXME */
518 Spi->PagedPoolLookasideHits = 0; /* FIXME */
519 Spi->Spare3Count = 0; /* FIXME */
520
521 Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
522 Spi->ResidentPagedPoolPage = MmPagedPoolSize; /* FIXME */
523
524 Spi->ResidentSystemDriverPage = 0; /* FIXME */
525 Spi->CcFastReadNoWait = 0; /* FIXME */
526 Spi->CcFastReadWait = 0; /* FIXME */
527 Spi->CcFastReadResourceMiss = 0; /* FIXME */
528 Spi->CcFastReadNotPossible = 0; /* FIXME */
529
530 Spi->CcFastMdlReadNoWait = 0; /* FIXME */
531 Spi->CcFastMdlReadWait = 0; /* FIXME */
532 Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
533 Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
534
535 Spi->CcMapDataNoWait = 0; /* FIXME */
536 Spi->CcMapDataWait = 0; /* FIXME */
537 Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
538 Spi->CcMapDataWaitMiss = 0; /* FIXME */
539
540 Spi->CcPinMappedDataCount = 0; /* FIXME */
541 Spi->CcPinReadNoWait = 0; /* FIXME */
542 Spi->CcPinReadWait = 0; /* FIXME */
543 Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
544 Spi->CcPinReadWaitMiss = 0; /* FIXME */
545 Spi->CcCopyReadNoWait = 0; /* FIXME */
546 Spi->CcCopyReadWait = 0; /* FIXME */
547 Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
548 Spi->CcCopyReadWaitMiss = 0; /* FIXME */
549
550 Spi->CcMdlReadNoWait = 0; /* FIXME */
551 Spi->CcMdlReadWait = 0; /* FIXME */
552 Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
553 Spi->CcMdlReadWaitMiss = 0; /* FIXME */
554 Spi->CcReadAheadIos = 0; /* FIXME */
555 Spi->CcLazyWriteIos = 0; /* FIXME */
556 Spi->CcLazyWritePages = 0; /* FIXME */
557 Spi->CcDataFlushes = 0; /* FIXME */
558 Spi->CcDataPages = 0; /* FIXME */
559 Spi->ContextSwitches = 0; /* FIXME */
560 Spi->FirstLevelTbFills = 0; /* FIXME */
561 Spi->SecondLevelTbFills = 0; /* FIXME */
562 Spi->SystemCalls = 0; /* FIXME */
563
564 return (STATUS_SUCCESS);
565 }
566
567 /* Class 3 - Time Of Day Information */
568 QSI_DEF(SystemTimeOfDayInformation)
569 {
570 PSYSTEM_TIMEOFDAY_INFORMATION Sti;
571 LARGE_INTEGER CurrentTime;
572
573 Sti = (PSYSTEM_TIMEOFDAY_INFORMATION)Buffer;
574 *ReqSize = sizeof (SYSTEM_TIMEOFDAY_INFORMATION);
575
576 /* Check user buffer's size */
577 if (Size != sizeof (SYSTEM_TIMEOFDAY_INFORMATION))
578 {
579 return STATUS_INFO_LENGTH_MISMATCH;
580 }
581
582 KeQuerySystemTime(&CurrentTime);
583
584 Sti->BootTime= KeBootTime;
585 Sti->CurrentTime = CurrentTime;
586 Sti->TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
587 Sti->TimeZoneId = ExpTimeZoneId;
588 Sti->Reserved = 0;
589
590 return STATUS_SUCCESS;
591 }
592
593 /* Class 4 - Path Information */
594 QSI_DEF(SystemPathInformation)
595 {
596 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
597 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
598
599 return (STATUS_BREAKPOINT);
600 }
601
602 /* Class 5 - Process Information */
603 QSI_DEF(SystemProcessInformation)
604 {
605 ULONG ovlSize = 0, nThreads;
606 PEPROCESS pr = NULL, syspr;
607 unsigned char *pCur;
608 NTSTATUS Status = STATUS_SUCCESS;
609
610 _SEH_TRY
611 {
612 /* scan the process list */
613
614 PSYSTEM_PROCESS_INFORMATION Spi
615 = (PSYSTEM_PROCESS_INFORMATION) Buffer;
616
617 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
618
619 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
620 {
621 return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
622 }
623
624 syspr = PsGetNextProcess(NULL);
625 pr = syspr;
626 pCur = (unsigned char *)Spi;
627
628 do
629 {
630 PSYSTEM_PROCESS_INFORMATION SpiCur;
631 int curSize;
632 ANSI_STRING imgName;
633 int inLen=32; // image name len in bytes
634 PLIST_ENTRY current_entry;
635 PETHREAD current;
636 PSYSTEM_THREAD_INFORMATION ThreadInfo;
637
638 SpiCur = (PSYSTEM_PROCESS_INFORMATION)pCur;
639
640 nThreads = 0;
641 current_entry = pr->ThreadListHead.Flink;
642 while (current_entry != &pr->ThreadListHead)
643 {
644 nThreads++;
645 current_entry = current_entry->Flink;
646 }
647
648 // size of the structure for every process
649 curSize = sizeof(SYSTEM_PROCESS_INFORMATION)+sizeof(SYSTEM_THREAD_INFORMATION)*nThreads;
650 ovlSize += curSize+inLen;
651
652 if (ovlSize > Size)
653 {
654 *ReqSize = ovlSize;
655 ObDereferenceObject(pr);
656
657 return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
658 }
659
660 // fill system information
661 SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
662 SpiCur->NumberOfThreads = nThreads;
663 SpiCur->CreateTime = pr->CreateTime;
664 SpiCur->UserTime.QuadPart = pr->Pcb.UserTime * 100000LL;
665 SpiCur->KernelTime.QuadPart = pr->Pcb.KernelTime * 100000LL;
666 SpiCur->ImageName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
667 SpiCur->ImageName.MaximumLength = inLen;
668 SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
669
670 // copy name to the end of the struct
671 if(pr != PsIdleProcess)
672 {
673 RtlInitAnsiString(&imgName, pr->ImageFileName);
674 RtlAnsiStringToUnicodeString(&SpiCur->ImageName, &imgName, FALSE);
675 }
676 else
677 {
678 RtlInitUnicodeString(&SpiCur->ImageName, NULL);
679 }
680
681 SpiCur->BasePriority = pr->Pcb.BasePriority;
682 SpiCur->UniqueProcessId = pr->UniqueProcessId;
683 SpiCur->InheritedFromUniqueProcessId = pr->InheritedFromUniqueProcessId;
684 SpiCur->HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
685 SpiCur->PeakVirtualSize = pr->PeakVirtualSize;
686 SpiCur->VirtualSize = pr->VirtualSize;
687 SpiCur->PageFaultCount = pr->Vm.PageFaultCount;
688 SpiCur->PeakWorkingSetSize = pr->Vm.PeakWorkingSetSize;
689 SpiCur->WorkingSetSize = pr->Vm.WorkingSetSize;
690 SpiCur->QuotaPeakPagedPoolUsage = pr->QuotaPeak[0];
691 SpiCur->QuotaPagedPoolUsage = pr->QuotaUsage[0];
692 SpiCur->QuotaPeakNonPagedPoolUsage = pr->QuotaPeak[1];
693 SpiCur->QuotaNonPagedPoolUsage = pr->QuotaUsage[1];
694 SpiCur->PagefileUsage = pr->QuotaUsage[2];
695 SpiCur->PeakPagefileUsage = pr->QuotaPeak[2];
696 SpiCur->PrivatePageCount = pr->CommitCharge;
697 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCur + 1);
698
699 current_entry = pr->ThreadListHead.Flink;
700 while (current_entry != &pr->ThreadListHead)
701 {
702 current = CONTAINING_RECORD(current_entry, ETHREAD,
703 ThreadListEntry);
704
705
706 ThreadInfo->KernelTime.QuadPart = current->Tcb.KernelTime * 100000LL;
707 ThreadInfo->UserTime.QuadPart = current->Tcb.UserTime * 100000LL;
708 // SpiCur->TH[i].CreateTime = current->CreateTime;
709 ThreadInfo->WaitTime = current->Tcb.WaitTime;
710 ThreadInfo->StartAddress = (PVOID) current->StartAddress;
711 ThreadInfo->ClientId = current->Cid;
712 ThreadInfo->Priority = current->Tcb.Priority;
713 ThreadInfo->BasePriority = current->Tcb.BasePriority;
714 ThreadInfo->ContextSwitches = current->Tcb.ContextSwitches;
715 ThreadInfo->ThreadState = current->Tcb.State;
716 ThreadInfo->WaitReason = current->Tcb.WaitReason;
717 ThreadInfo++;
718 current_entry = current_entry->Flink;
719 }
720
721 pr = PsGetNextProcess(pr);
722 nThreads = 0;
723 if ((pr == syspr) || (pr == NULL))
724 {
725 SpiCur->NextEntryOffset = 0;
726 break;
727 }
728 else
729 pCur = pCur + curSize + inLen;
730 } while ((pr != syspr) && (pr != NULL));
731
732 if(pr != NULL)
733 ObDereferenceObject(pr);
734 Status = STATUS_SUCCESS;
735 }
736 _SEH_HANDLE
737 {
738 if(pr != NULL)
739 ObDereferenceObject(pr);
740 Status = _SEH_GetExceptionCode();
741 }
742 _SEH_END
743
744 *ReqSize = ovlSize;
745 return Status;
746 }
747
748 /* Class 6 - Call Count Information */
749 QSI_DEF(SystemCallCountInformation)
750 {
751 /* FIXME */
752 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
753 return (STATUS_NOT_IMPLEMENTED);
754 }
755
756 /* Class 7 - Device Information */
757 QSI_DEF(SystemDeviceInformation)
758 {
759 PSYSTEM_DEVICE_INFORMATION Sdi
760 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
761 PCONFIGURATION_INFORMATION ConfigInfo;
762
763 *ReqSize = sizeof (SYSTEM_DEVICE_INFORMATION);
764 /*
765 * Check user buffer's size
766 */
767 if (Size < sizeof (SYSTEM_DEVICE_INFORMATION))
768 {
769 return (STATUS_INFO_LENGTH_MISMATCH);
770 }
771
772 ConfigInfo = IoGetConfigurationInformation ();
773
774 Sdi->NumberOfDisks = ConfigInfo->DiskCount;
775 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
776 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
777 Sdi->NumberOfTapes = ConfigInfo->TapeCount;
778 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
779 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
780
781 return (STATUS_SUCCESS);
782 }
783
784 /* Class 8 - Processor Performance Information */
785 QSI_DEF(SystemProcessorPerformanceInformation)
786 {
787 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
788 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
789
790 LONG i;
791 LARGE_INTEGER CurrentTime;
792 PKPRCB Prcb;
793
794 *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
795 /*
796 * Check user buffer's size
797 */
798 if (Size < KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION))
799 {
800 return (STATUS_INFO_LENGTH_MISMATCH);
801 }
802
803 CurrentTime.QuadPart = KeQueryInterruptTime();
804 Prcb = ((PKPCR)KPCR_BASE)->Prcb;
805 for (i = 0; i < KeNumberProcessors; i++)
806 {
807 Spi->IdleTime.QuadPart = (Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime) * 100000LL; // IdleTime
808 Spi->KernelTime.QuadPart = Prcb->KernelTime * 100000LL; // KernelTime
809 Spi->UserTime.QuadPart = Prcb->UserTime * 100000LL;
810 Spi->DpcTime.QuadPart = Prcb->DpcTime * 100000LL;
811 Spi->InterruptTime.QuadPart = Prcb->InterruptTime * 100000LL;
812 Spi->InterruptCount = Prcb->InterruptCount; // Interrupt Count
813 Spi++;
814 Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
815 }
816
817 return (STATUS_SUCCESS);
818 }
819
820 /* Class 9 - Flags Information */
821 QSI_DEF(SystemFlagsInformation)
822 {
823 if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
824 {
825 * ReqSize = sizeof (SYSTEM_FLAGS_INFORMATION);
826 return (STATUS_INFO_LENGTH_MISMATCH);
827 }
828 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
829 return (STATUS_SUCCESS);
830 }
831
832 SSI_DEF(SystemFlagsInformation)
833 {
834 if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
835 {
836 return (STATUS_INFO_LENGTH_MISMATCH);
837 }
838 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
839 return (STATUS_SUCCESS);
840 }
841
842 /* Class 10 - Call Time Information */
843 QSI_DEF(SystemCallTimeInformation)
844 {
845 /* FIXME */
846 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
847 return (STATUS_NOT_IMPLEMENTED);
848 }
849
850 /* Class 11 - Module Information */
851 QSI_DEF(SystemModuleInformation)
852 {
853 return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
854 }
855
856 /* Class 12 - Locks Information */
857 QSI_DEF(SystemLocksInformation)
858 {
859 /* FIXME */
860 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
861 return (STATUS_NOT_IMPLEMENTED);
862 }
863
864 /* Class 13 - Stack Trace Information */
865 QSI_DEF(SystemStackTraceInformation)
866 {
867 /* FIXME */
868 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
869 return (STATUS_NOT_IMPLEMENTED);
870 }
871
872 /* Class 14 - Paged Pool Information */
873 QSI_DEF(SystemPagedPoolInformation)
874 {
875 /* FIXME */
876 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
877 return (STATUS_NOT_IMPLEMENTED);
878 }
879
880 /* Class 15 - Non Paged Pool Information */
881 QSI_DEF(SystemNonPagedPoolInformation)
882 {
883 /* FIXME */
884 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
885 return (STATUS_NOT_IMPLEMENTED);
886 }
887
888
889 /* Class 16 - Handle Information */
890 QSI_DEF(SystemHandleInformation)
891 {
892 PEPROCESS pr, syspr;
893 ULONG curSize, i = 0;
894 ULONG hCount = 0;
895
896 PSYSTEM_HANDLE_INFORMATION Shi =
897 (PSYSTEM_HANDLE_INFORMATION) Buffer;
898
899 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
900
901 if (Size < sizeof (SYSTEM_HANDLE_INFORMATION))
902 {
903 * ReqSize = sizeof (SYSTEM_HANDLE_INFORMATION);
904 return (STATUS_INFO_LENGTH_MISMATCH);
905 }
906
907 DPRINT("SystemHandleInformation 1\n");
908
909 /* First Calc Size from Count. */
910 syspr = PsGetNextProcess(NULL);
911 pr = syspr;
912
913 do
914 {
915 hCount = hCount + (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
916 pr = PsGetNextProcess(pr);
917
918 if ((pr == syspr) || (pr == NULL))
919 break;
920 } while ((pr != syspr) && (pr != NULL));
921
922 if(pr != NULL)
923 {
924 ObDereferenceObject(pr);
925 }
926
927 DPRINT("SystemHandleInformation 2\n");
928
929 curSize = sizeof(SYSTEM_HANDLE_INFORMATION)+
930 ( (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) -
931 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) ));
932
933 Shi->NumberOfHandles = hCount;
934
935 if (curSize > Size)
936 {
937 *ReqSize = curSize;
938 return (STATUS_INFO_LENGTH_MISMATCH);
939 }
940
941 DPRINT("SystemHandleInformation 3\n");
942
943 /* Now get Handles from all processs. */
944 syspr = PsGetNextProcess(NULL);
945 pr = syspr;
946
947 do
948 {
949 int Count = 0, HandleCount;
950
951 HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
952
953 for (Count = 0; HandleCount > 0 ; HandleCount--)
954 {
955 Shi->Handles[i].UniqueProcessId = (ULONG)pr->UniqueProcessId;
956 Count++;
957 i++;
958 }
959
960 pr = PsGetNextProcess(pr);
961
962 if ((pr == syspr) || (pr == NULL))
963 break;
964 } while ((pr != syspr) && (pr != NULL));
965
966 if(pr != NULL)
967 {
968 ObDereferenceObject(pr);
969 }
970
971 DPRINT("SystemHandleInformation 4\n");
972 return (STATUS_SUCCESS);
973
974 }
975 /*
976 SSI_DEF(SystemHandleInformation)
977 {
978
979 return (STATUS_SUCCESS);
980 }
981 */
982
983 /* Class 17 - Information */
984 QSI_DEF(SystemObjectInformation)
985 {
986 /* FIXME */
987 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
988 return (STATUS_NOT_IMPLEMENTED);
989 }
990
991 /* Class 18 - Information */
992 QSI_DEF(SystemPageFileInformation)
993 {
994 UNICODE_STRING FileName; /* FIXME */
995 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
996
997 if (Size < sizeof (SYSTEM_PAGEFILE_INFORMATION))
998 {
999 * ReqSize = sizeof (SYSTEM_PAGEFILE_INFORMATION);
1000 return (STATUS_INFO_LENGTH_MISMATCH);
1001 }
1002
1003 RtlInitUnicodeString(&FileName, NULL); /* FIXME */
1004
1005 /* FIXME */
1006 Spfi->NextEntryOffset = 0;
1007
1008 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
1009 Spfi->TotalInUse = MiUsedSwapPages;
1010 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
1011 Spfi->PageFileName = FileName;
1012 return (STATUS_SUCCESS);
1013 }
1014
1015 /* Class 19 - Vdm Instemul Information */
1016 QSI_DEF(SystemVdmInstemulInformation)
1017 {
1018 /* FIXME */
1019 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
1020 return (STATUS_NOT_IMPLEMENTED);
1021 }
1022
1023 /* Class 20 - Vdm Bop Information */
1024 QSI_DEF(SystemVdmBopInformation)
1025 {
1026 /* FIXME */
1027 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
1028 return (STATUS_NOT_IMPLEMENTED);
1029 }
1030
1031 /* Class 21 - File Cache Information */
1032 QSI_DEF(SystemFileCacheInformation)
1033 {
1034 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
1035
1036 if (Size < sizeof (SYSTEM_FILECACHE_INFORMATION))
1037 {
1038 * ReqSize = sizeof (SYSTEM_FILECACHE_INFORMATION);
1039 return (STATUS_INFO_LENGTH_MISMATCH);
1040 }
1041
1042 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION));
1043
1044 /* Return the Byte size not the page size. */
1045 Sci->CurrentSize =
1046 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
1047 Sci->PeakSize =
1048 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE; /* FIXME */
1049
1050 Sci->PageFaultCount = 0; /* FIXME */
1051 Sci->MinimumWorkingSet = 0; /* FIXME */
1052 Sci->MaximumWorkingSet = 0; /* FIXME */
1053
1054 return (STATUS_SUCCESS);
1055 }
1056
1057 SSI_DEF(SystemFileCacheInformation)
1058 {
1059 if (Size < sizeof (SYSTEM_FILECACHE_INFORMATION))
1060 {
1061 return (STATUS_INFO_LENGTH_MISMATCH);
1062 }
1063 /* FIXME */
1064 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1065 return (STATUS_NOT_IMPLEMENTED);
1066 }
1067
1068 /* Class 22 - Pool Tag Information */
1069 QSI_DEF(SystemPoolTagInformation)
1070 {
1071 /* FIXME */
1072 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1073 return (STATUS_NOT_IMPLEMENTED);
1074 }
1075
1076 /* Class 23 - Interrupt Information for all processors */
1077 QSI_DEF(SystemInterruptInformation)
1078 {
1079 PKPRCB Prcb;
1080 LONG i;
1081 ULONG ti;
1082 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1083
1084 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1085 {
1086 return (STATUS_INFO_LENGTH_MISMATCH);
1087 }
1088
1089 ti = KeQueryTimeIncrement();
1090
1091 Prcb = ((PKPCR)KPCR_BASE)->Prcb;
1092 for (i = 0; i < KeNumberProcessors; i++)
1093 {
1094 //sii->ContextSwitches = Prcb->KeContextSwitches;
1095 sii->DpcCount = 0; /* FIXME */
1096 sii->DpcRate = 0; /* FIXME */
1097 sii->TimeIncrement = ti;
1098 sii->DpcBypassCount = 0; /* FIXME */
1099 sii->ApcBypassCount = 0; /* FIXME */
1100 sii++;
1101 Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
1102 }
1103
1104 return STATUS_SUCCESS;
1105 }
1106
1107 /* Class 24 - DPC Behaviour Information */
1108 QSI_DEF(SystemDpcBehaviourInformation)
1109 {
1110 /* FIXME */
1111 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1112 return (STATUS_NOT_IMPLEMENTED);
1113 }
1114
1115 SSI_DEF(SystemDpcBehaviourInformation)
1116 {
1117 /* FIXME */
1118 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1119 return (STATUS_NOT_IMPLEMENTED);
1120 }
1121
1122 /* Class 25 - Full Memory Information */
1123 QSI_DEF(SystemFullMemoryInformation)
1124 {
1125 PULONG Spi = (PULONG) Buffer;
1126
1127 PEPROCESS TheIdleProcess;
1128
1129 * ReqSize = sizeof (ULONG);
1130
1131 if (sizeof (ULONG) != Size)
1132 {
1133 return (STATUS_INFO_LENGTH_MISMATCH);
1134 }
1135 DPRINT("SystemFullMemoryInformation\n");
1136
1137 TheIdleProcess = PsIdleProcess;
1138
1139 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1140 TheIdleProcess->UniqueProcessId,
1141 TheIdleProcess->Pcb.KernelTime,
1142 MiFreeSwapPages,
1143 MiUsedSwapPages);
1144
1145 #ifndef NDEBUG
1146 MmPrintMemoryStatistic();
1147 #endif
1148
1149 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1150
1151 return (STATUS_SUCCESS);
1152 }
1153
1154 /* Class 26 - Load Image */
1155 SSI_DEF(SystemLoadImage)
1156 {
1157 PSYSTEM_GDI_DRIVER_INFORMATION Sli = (PSYSTEM_GDI_DRIVER_INFORMATION)Buffer;
1158
1159 if (sizeof(SYSTEM_GDI_DRIVER_INFORMATION) != Size)
1160 {
1161 return(STATUS_INFO_LENGTH_MISMATCH);
1162 }
1163
1164 return(LdrpLoadImage(&Sli->DriverName,
1165 &Sli->ImageAddress,
1166 &Sli->SectionPointer,
1167 &Sli->EntryPoint,
1168 (PVOID)&Sli->ExportSectionPointer));
1169 }
1170
1171 /* Class 27 - Unload Image */
1172 SSI_DEF(SystemUnloadImage)
1173 {
1174 PVOID Sui = (PVOID)Buffer;
1175
1176 if (sizeof(PVOID) != Size)
1177 {
1178 return(STATUS_INFO_LENGTH_MISMATCH);
1179 }
1180
1181 return(LdrpUnloadImage(Sui));
1182 }
1183
1184 /* Class 28 - Time Adjustment Information */
1185 QSI_DEF(SystemTimeAdjustmentInformation)
1186 {
1187 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION) > Size)
1188 {
1189 * ReqSize = sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION);
1190 return (STATUS_INFO_LENGTH_MISMATCH);
1191 }
1192 /* FIXME: */
1193 DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1194 return (STATUS_NOT_IMPLEMENTED);
1195 }
1196
1197 SSI_DEF(SystemTimeAdjustmentInformation)
1198 {
1199 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION) > Size)
1200 {
1201 return (STATUS_INFO_LENGTH_MISMATCH);
1202 }
1203 /* FIXME: */
1204 DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1205 return (STATUS_NOT_IMPLEMENTED);
1206 }
1207
1208 /* Class 29 - Summary Memory Information */
1209 QSI_DEF(SystemSummaryMemoryInformation)
1210 {
1211 /* FIXME */
1212 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1213 return (STATUS_NOT_IMPLEMENTED);
1214 }
1215
1216 /* Class 30 - Next Event Id Information */
1217 QSI_DEF(SystemNextEventIdInformation)
1218 {
1219 /* FIXME */
1220 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1221 return (STATUS_NOT_IMPLEMENTED);
1222 }
1223
1224 /* Class 31 - Event Ids Information */
1225 QSI_DEF(SystemEventIdsInformation)
1226 {
1227 /* FIXME */
1228 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1229 return (STATUS_NOT_IMPLEMENTED);
1230 }
1231
1232 /* Class 32 - Crash Dump Information */
1233 QSI_DEF(SystemCrashDumpInformation)
1234 {
1235 /* FIXME */
1236 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1237 return (STATUS_NOT_IMPLEMENTED);
1238 }
1239
1240 /* Class 33 - Exception Information */
1241 QSI_DEF(SystemExceptionInformation)
1242 {
1243 /* FIXME */
1244 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1245 return (STATUS_NOT_IMPLEMENTED);
1246 }
1247
1248 /* Class 34 - Crash Dump State Information */
1249 QSI_DEF(SystemCrashDumpStateInformation)
1250 {
1251 /* FIXME */
1252 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1253 return (STATUS_NOT_IMPLEMENTED);
1254 }
1255
1256 /* Class 35 - Kernel Debugger Information */
1257 QSI_DEF(SystemKernelDebuggerInformation)
1258 {
1259 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1260
1261 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1262 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1263 {
1264 return STATUS_INFO_LENGTH_MISMATCH;
1265 }
1266
1267 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1268 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1269
1270 return STATUS_SUCCESS;
1271 }
1272
1273 /* Class 36 - Context Switch Information */
1274 QSI_DEF(SystemContextSwitchInformation)
1275 {
1276 /* FIXME */
1277 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1278 return (STATUS_NOT_IMPLEMENTED);
1279 }
1280
1281 /* Class 37 - Registry Quota Information */
1282 QSI_DEF(SystemRegistryQuotaInformation)
1283 {
1284 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1285
1286 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1287 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1288 {
1289 return STATUS_INFO_LENGTH_MISMATCH;
1290 }
1291
1292 DPRINT1("Faking max registry size of 32 MB\n");
1293 srqi->RegistryQuotaAllowed = 0x2000000;
1294 srqi->RegistryQuotaUsed = 0x200000;
1295 srqi->PagedPoolSize = 0x200000;
1296
1297 return STATUS_SUCCESS;
1298 }
1299
1300 SSI_DEF(SystemRegistryQuotaInformation)
1301 {
1302 /* FIXME */
1303 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1304 return (STATUS_NOT_IMPLEMENTED);
1305 }
1306
1307 /* Class 38 - Load And Call Image */
1308 SSI_DEF(SystemLoadAndCallImage)
1309 {
1310 PUNICODE_STRING Slci = (PUNICODE_STRING)Buffer;
1311
1312 if (sizeof(UNICODE_STRING) != Size)
1313 {
1314 return(STATUS_INFO_LENGTH_MISMATCH);
1315 }
1316
1317 return(LdrpLoadAndCallImage(Slci));
1318 }
1319
1320 /* Class 39 - Priority Separation */
1321 SSI_DEF(SystemPrioritySeperation)
1322 {
1323 /* FIXME */
1324 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1325 return (STATUS_NOT_IMPLEMENTED);
1326 }
1327
1328 /* Class 40 - Plug Play Bus Information */
1329 QSI_DEF(SystemPlugPlayBusInformation)
1330 {
1331 /* FIXME */
1332 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1333 return (STATUS_NOT_IMPLEMENTED);
1334 }
1335
1336 /* Class 41 - Dock Information */
1337 QSI_DEF(SystemDockInformation)
1338 {
1339 /* FIXME */
1340 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1341 return (STATUS_NOT_IMPLEMENTED);
1342 }
1343
1344 /* Class 42 - Power Information */
1345 QSI_DEF(SystemPowerInformation)
1346 {
1347 /* FIXME */
1348 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1349 return (STATUS_NOT_IMPLEMENTED);
1350 }
1351
1352 /* Class 43 - Processor Speed Information */
1353 QSI_DEF(SystemProcessorSpeedInformation)
1354 {
1355 /* FIXME */
1356 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1357 return (STATUS_NOT_IMPLEMENTED);
1358 }
1359
1360 /* Class 44 - Current Time Zone Information */
1361 QSI_DEF(SystemCurrentTimeZoneInformation)
1362 {
1363 * ReqSize = sizeof (TIME_ZONE_INFORMATION);
1364
1365 if (sizeof (TIME_ZONE_INFORMATION) != Size)
1366 {
1367 return STATUS_INFO_LENGTH_MISMATCH;
1368 }
1369
1370 /* Copy the time zone information struct */
1371 memcpy(Buffer,
1372 &ExpTimeZoneInfo,
1373 sizeof(TIME_ZONE_INFORMATION));
1374
1375 return STATUS_SUCCESS;
1376 }
1377
1378
1379 SSI_DEF(SystemCurrentTimeZoneInformation)
1380 {
1381 /* Check user buffer's size */
1382 if (Size < sizeof (TIME_ZONE_INFORMATION))
1383 {
1384 return STATUS_INFO_LENGTH_MISMATCH;
1385 }
1386
1387 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1388 }
1389
1390
1391 /* Class 45 - Lookaside Information */
1392 QSI_DEF(SystemLookasideInformation)
1393 {
1394 /* FIXME */
1395 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1396 return (STATUS_NOT_IMPLEMENTED);
1397 }
1398
1399
1400 /* Class 46 - Set time slip event */
1401 SSI_DEF(SystemSetTimeSlipEvent)
1402 {
1403 /* FIXME */
1404 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1405 return (STATUS_NOT_IMPLEMENTED);
1406 }
1407
1408
1409 /* Class 47 - Create a new session (TSE) */
1410 SSI_DEF(SystemCreateSession)
1411 {
1412 /* FIXME */
1413 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1414 return (STATUS_NOT_IMPLEMENTED);
1415 }
1416
1417
1418 /* Class 48 - Delete an existing session (TSE) */
1419 SSI_DEF(SystemDeleteSession)
1420 {
1421 /* FIXME */
1422 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1423 return (STATUS_NOT_IMPLEMENTED);
1424 }
1425
1426
1427 /* Class 49 - UNKNOWN */
1428 QSI_DEF(SystemInvalidInfoClass4)
1429 {
1430 /* FIXME */
1431 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1432 return (STATUS_NOT_IMPLEMENTED);
1433 }
1434
1435
1436 /* Class 50 - System range start address */
1437 QSI_DEF(SystemRangeStartInformation)
1438 {
1439 /* FIXME */
1440 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1441 return (STATUS_NOT_IMPLEMENTED);
1442 }
1443
1444
1445 /* Class 51 - Driver verifier information */
1446 QSI_DEF(SystemVerifierInformation)
1447 {
1448 /* FIXME */
1449 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1450 return (STATUS_NOT_IMPLEMENTED);
1451 }
1452
1453
1454 SSI_DEF(SystemVerifierInformation)
1455 {
1456 /* FIXME */
1457 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1458 return (STATUS_NOT_IMPLEMENTED);
1459 }
1460
1461
1462 /* Class 52 - Add a driver verifier */
1463 SSI_DEF(SystemAddVerifier)
1464 {
1465 /* FIXME */
1466 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1467 return (STATUS_NOT_IMPLEMENTED);
1468 }
1469
1470
1471 /* Class 53 - A session's processes */
1472 QSI_DEF(SystemSessionProcessesInformation)
1473 {
1474 /* FIXME */
1475 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1476 return (STATUS_NOT_IMPLEMENTED);
1477 }
1478
1479
1480 /* Query/Set Calls Table */
1481 typedef
1482 struct _QSSI_CALLS
1483 {
1484 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1485 NTSTATUS (* Set) (PVOID,ULONG);
1486
1487 } QSSI_CALLS;
1488
1489 // QS Query & Set
1490 // QX Query
1491 // XS Set
1492 // XX unknown behaviour
1493 //
1494 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1495 #define SI_QX(n) {QSI_USE(n),NULL}
1496 #define SI_XS(n) {NULL,SSI_USE(n)}
1497 #define SI_XX(n) {NULL,NULL}
1498
1499 static
1500 QSSI_CALLS
1501 CallQS [] =
1502 {
1503 SI_QX(SystemBasicInformation),
1504 SI_QX(SystemProcessorInformation),
1505 SI_QX(SystemPerformanceInformation),
1506 SI_QX(SystemTimeOfDayInformation),
1507 SI_QX(SystemPathInformation), /* should be SI_XX */
1508 SI_QX(SystemProcessInformation),
1509 SI_QX(SystemCallCountInformation),
1510 SI_QX(SystemDeviceInformation),
1511 SI_QX(SystemProcessorPerformanceInformation),
1512 SI_QS(SystemFlagsInformation),
1513 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1514 SI_QX(SystemModuleInformation),
1515 SI_QX(SystemLocksInformation),
1516 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1517 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1518 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1519 SI_QX(SystemHandleInformation),
1520 SI_QX(SystemObjectInformation),
1521 SI_QX(SystemPageFileInformation),
1522 SI_QX(SystemVdmInstemulInformation),
1523 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1524 SI_QS(SystemFileCacheInformation),
1525 SI_QX(SystemPoolTagInformation),
1526 SI_QX(SystemInterruptInformation),
1527 SI_QS(SystemDpcBehaviourInformation),
1528 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1529 SI_XS(SystemLoadImage),
1530 SI_XS(SystemUnloadImage),
1531 SI_QS(SystemTimeAdjustmentInformation),
1532 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1533 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1534 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1535 SI_QX(SystemCrashDumpInformation),
1536 SI_QX(SystemExceptionInformation),
1537 SI_QX(SystemCrashDumpStateInformation),
1538 SI_QX(SystemKernelDebuggerInformation),
1539 SI_QX(SystemContextSwitchInformation),
1540 SI_QS(SystemRegistryQuotaInformation),
1541 SI_XS(SystemLoadAndCallImage),
1542 SI_XS(SystemPrioritySeperation),
1543 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1544 SI_QX(SystemDockInformation), /* it should be SI_XX */
1545 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1546 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1547 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1548 SI_QX(SystemLookasideInformation),
1549 SI_XS(SystemSetTimeSlipEvent),
1550 SI_XS(SystemCreateSession),
1551 SI_XS(SystemDeleteSession),
1552 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1553 SI_QX(SystemRangeStartInformation),
1554 SI_QS(SystemVerifierInformation),
1555 SI_XS(SystemAddVerifier),
1556 SI_QX(SystemSessionProcessesInformation)
1557 };
1558
1559
1560 /*
1561 * @implemented
1562 */
1563 NTSTATUS STDCALL
1564 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1565 OUT PVOID SystemInformation,
1566 IN ULONG Length,
1567 OUT PULONG UnsafeResultLength)
1568 {
1569 KPROCESSOR_MODE PreviousMode;
1570 ULONG ResultLength;
1571 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1572
1573 PAGED_CODE();
1574
1575 PreviousMode = ExGetPreviousMode();
1576
1577 _SEH_TRY
1578 {
1579 if (PreviousMode != KernelMode)
1580 {
1581 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1582 ProbeForWrite(SystemInformation, Length, 1);
1583 if (UnsafeResultLength != NULL)
1584 ProbeForWriteUlong(UnsafeResultLength);
1585 }
1586
1587 /* Clear user buffer. */
1588 RtlZeroMemory(SystemInformation, Length);
1589
1590 /*
1591 * Check the request is valid.
1592 */
1593 if (SystemInformationClass >= MaxSystemInfoClass)
1594 {
1595 return (STATUS_INVALID_INFO_CLASS);
1596 }
1597
1598 if (NULL != CallQS [SystemInformationClass].Query)
1599 {
1600 /*
1601 * Hand the request to a subhandler.
1602 */
1603 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1604 Length,
1605 &ResultLength);
1606 if (UnsafeResultLength != NULL)
1607 {
1608 if (PreviousMode != KernelMode)
1609 {
1610 _SEH_TRY
1611 {
1612 *UnsafeResultLength = ResultLength;
1613 }
1614 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
1615 {
1616 FStatus = _SEH_GetExceptionCode();
1617 }
1618 _SEH_END;
1619 }
1620 else
1621 {
1622 *UnsafeResultLength = ResultLength;
1623 }
1624 }
1625 }
1626 }
1627 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
1628 {
1629 FStatus = _SEH_GetExceptionCode();
1630 }
1631 _SEH_END;
1632
1633 return (FStatus);
1634 }
1635
1636
1637 NTSTATUS
1638 STDCALL
1639 NtSetSystemInformation (
1640 IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1641 IN PVOID SystemInformation,
1642 IN ULONG SystemInformationLength
1643 )
1644 {
1645 PAGED_CODE();
1646
1647 /*
1648 * If called from user mode, check
1649 * possible unsafe arguments.
1650 */
1651 #if 0
1652 if (KernelMode != KeGetPreviousMode())
1653 {
1654 // Check arguments
1655 //ProbeForWrite(
1656 // SystemInformation,
1657 // Length
1658 // );
1659 //ProbeForWrite(
1660 // ResultLength,
1661 // sizeof (ULONG)
1662 // );
1663 }
1664 #endif
1665 /*
1666 * Check the request is valid.
1667 */
1668 if ( (SystemInformationClass >= SystemBasicInformation)
1669 && (SystemInformationClass < MaxSystemInfoClass)
1670 )
1671 {
1672 if (NULL != CallQS [SystemInformationClass].Set)
1673 {
1674 /*
1675 * Hand the request to a subhandler.
1676 */
1677 return CallQS [SystemInformationClass].Set (
1678 SystemInformation,
1679 SystemInformationLength
1680 );
1681 }
1682 }
1683 return (STATUS_INVALID_INFO_CLASS);
1684 }
1685
1686
1687 NTSTATUS
1688 STDCALL
1689 NtFlushInstructionCache (
1690 IN HANDLE ProcessHandle,
1691 IN PVOID BaseAddress,
1692 IN ULONG NumberOfBytesToFlush
1693 )
1694 {
1695 PAGED_CODE();
1696
1697 __wbinvd();
1698 return STATUS_SUCCESS;
1699 }
1700
1701 ULONG
1702 NTAPI
1703 NtGetCurrentProcessorNumber(VOID)
1704 {
1705 /* Just return the CPU */
1706 return KeGetCurrentProcessorNumber();
1707 }
1708
1709 /* EOF */