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