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