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