- Implemented InterlockedBitTestAndReset, InterlockedBitTestAndSet, InterlockedExchan...
[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, i = 0;
585 ANSI_STRING imgName;
586 int inLen=32; // image name len in bytes
587 PLIST_ENTRY current_entry;
588 PETHREAD current;
589
590 SpiCur = (PSYSTEM_PROCESS_INFORMATION)pCur;
591
592 nThreads = 0;
593 current_entry = pr->ThreadListHead.Flink;
594 while (current_entry != &pr->ThreadListHead)
595 {
596 nThreads++;
597 current_entry = current_entry->Flink;
598 }
599
600 // size of the structure for every process
601 curSize = sizeof(SYSTEM_PROCESS_INFORMATION)-sizeof(SYSTEM_THREAD_INFORMATION)+sizeof(SYSTEM_THREAD_INFORMATION)*nThreads;
602 ovlSize += curSize+inLen;
603
604 if (ovlSize > Size)
605 {
606 *ReqSize = ovlSize;
607 ObDereferenceObject(pr);
608
609 return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
610 }
611
612 // fill system information
613 SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
614 SpiCur->NumberOfThreads = nThreads;
615 SpiCur->CreateTime = pr->CreateTime;
616 SpiCur->UserTime.QuadPart = pr->Pcb.UserTime * 100000LL;
617 SpiCur->KernelTime.QuadPart = pr->Pcb.KernelTime * 100000LL;
618 SpiCur->ImageName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
619 SpiCur->ImageName.MaximumLength = inLen;
620 SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
621
622 // copy name to the end of the struct
623 if(pr != PsIdleProcess)
624 {
625 RtlInitAnsiString(&imgName, pr->ImageFileName);
626 RtlAnsiStringToUnicodeString(&SpiCur->ImageName, &imgName, FALSE);
627 }
628 else
629 {
630 RtlInitUnicodeString(&SpiCur->ImageName, NULL);
631 }
632
633 SpiCur->BasePriority = pr->Pcb.BasePriority;
634 SpiCur->UniqueProcessId = pr->UniqueProcessId;
635 SpiCur->InheritedFromUniqueProcessId = pr->InheritedFromUniqueProcessId;
636 SpiCur->HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
637 SpiCur->PeakVirtualSize = pr->PeakVirtualSize;
638 SpiCur->VirtualSize = pr->VirtualSize;
639 SpiCur->PageFaultCount = pr->Vm.PageFaultCount;
640 SpiCur->PeakWorkingSetSize = pr->Vm.PeakWorkingSetSize;
641 SpiCur->WorkingSetSize = pr->Vm.WorkingSetSize;
642 SpiCur->QuotaPeakPagedPoolUsage = pr->QuotaPeak[0];
643 SpiCur->QuotaPagedPoolUsage = pr->QuotaUsage[0];
644 SpiCur->QuotaPeakNonPagedPoolUsage = pr->QuotaPeak[1];
645 SpiCur->QuotaNonPagedPoolUsage = pr->QuotaUsage[1];
646 SpiCur->PagefileUsage = pr->QuotaUsage[3];
647 SpiCur->PeakPagefileUsage = pr->QuotaPeak[3];
648 SpiCur->PrivateUsage = pr->CommitCharge;
649
650 current_entry = pr->ThreadListHead.Flink;
651 while (current_entry != &pr->ThreadListHead)
652 {
653 current = CONTAINING_RECORD(current_entry, ETHREAD,
654 ThreadListEntry);
655
656 SpiCur->TH[i].KernelTime.QuadPart = current->Tcb.KernelTime * 100000LL;
657 SpiCur->TH[i].UserTime.QuadPart = current->Tcb.UserTime * 100000LL;
658 // SpiCur->TH[i].CreateTime = current->CreateTime;
659 SpiCur->TH[i].WaitTime = current->Tcb.WaitTime;
660 SpiCur->TH[i].StartAddress = (PVOID) current->StartAddress;
661 SpiCur->TH[i].ClientId = current->Cid;
662 SpiCur->TH[i].Priority = current->Tcb.Priority;
663 SpiCur->TH[i].BasePriority = current->Tcb.BasePriority;
664 SpiCur->TH[i].ContextSwitches = current->Tcb.ContextSwitches;
665 SpiCur->TH[i].ThreadState = current->Tcb.State;
666 SpiCur->TH[i].WaitReason = current->Tcb.WaitReason;
667 i++;
668 current_entry = current_entry->Flink;
669 }
670
671 pr = PsGetNextProcess(pr);
672 nThreads = 0;
673 if ((pr == syspr) || (pr == NULL))
674 {
675 SpiCur->NextEntryOffset = 0;
676 break;
677 }
678 else
679 pCur = pCur + curSize + inLen;
680 } while ((pr != syspr) && (pr != NULL));
681
682 if(pr != NULL)
683 ObDereferenceObject(pr);
684 Status = STATUS_SUCCESS;
685 }
686 _SEH_HANDLE
687 {
688 if(pr != NULL)
689 ObDereferenceObject(pr);
690 Status = _SEH_GetExceptionCode();
691 }
692 _SEH_END
693
694 *ReqSize = ovlSize;
695 return Status;
696 }
697
698 /* Class 6 - Call Count Information */
699 QSI_DEF(SystemCallCountInformation)
700 {
701 /* FIXME */
702 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
703 return (STATUS_NOT_IMPLEMENTED);
704 }
705
706 /* Class 7 - Device Information */
707 QSI_DEF(SystemDeviceInformation)
708 {
709 PSYSTEM_DEVICE_INFORMATION Sdi
710 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
711 PCONFIGURATION_INFORMATION ConfigInfo;
712
713 *ReqSize = sizeof (SYSTEM_DEVICE_INFORMATION);
714 /*
715 * Check user buffer's size
716 */
717 if (Size < sizeof (SYSTEM_DEVICE_INFORMATION))
718 {
719 return (STATUS_INFO_LENGTH_MISMATCH);
720 }
721
722 ConfigInfo = IoGetConfigurationInformation ();
723
724 Sdi->NumberOfDisks = ConfigInfo->DiskCount;
725 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
726 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
727 Sdi->NumberOfTapes = ConfigInfo->TapeCount;
728 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
729 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
730
731 return (STATUS_SUCCESS);
732 }
733
734 /* Class 8 - Processor Performance Information */
735 QSI_DEF(SystemProcessorPerformanceInformation)
736 {
737 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
738 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
739
740 LONG i;
741 LARGE_INTEGER CurrentTime;
742 PKPRCB Prcb;
743
744 *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
745 /*
746 * Check user buffer's size
747 */
748 if (Size < KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION))
749 {
750 return (STATUS_INFO_LENGTH_MISMATCH);
751 }
752
753 CurrentTime.QuadPart = KeQueryInterruptTime();
754 Prcb = ((PKPCR)KPCR_BASE)->Prcb;
755 for (i = 0; i < KeNumberProcessors; i++)
756 {
757 Spi->IdleTime.QuadPart = (Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime) * 100000LL; // IdleTime
758 Spi->KernelTime.QuadPart = Prcb->KernelTime * 100000LL; // KernelTime
759 Spi->UserTime.QuadPart = Prcb->UserTime * 100000LL;
760 Spi->DpcTime.QuadPart = Prcb->DpcTime * 100000LL;
761 Spi->InterruptTime.QuadPart = Prcb->InterruptTime * 100000LL;
762 Spi->InterruptCount = Prcb->InterruptCount; // Interrupt Count
763 Spi++;
764 Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
765 }
766
767 return (STATUS_SUCCESS);
768 }
769
770 /* Class 9 - Flags Information */
771 QSI_DEF(SystemFlagsInformation)
772 {
773 if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
774 {
775 * ReqSize = sizeof (SYSTEM_FLAGS_INFORMATION);
776 return (STATUS_INFO_LENGTH_MISMATCH);
777 }
778 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
779 return (STATUS_SUCCESS);
780 }
781
782 SSI_DEF(SystemFlagsInformation)
783 {
784 if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
785 {
786 return (STATUS_INFO_LENGTH_MISMATCH);
787 }
788 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
789 return (STATUS_SUCCESS);
790 }
791
792 /* Class 10 - Call Time Information */
793 QSI_DEF(SystemCallTimeInformation)
794 {
795 /* FIXME */
796 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
797 return (STATUS_NOT_IMPLEMENTED);
798 }
799
800 /* Class 11 - Module Information */
801 QSI_DEF(SystemModuleInformation)
802 {
803 return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
804 }
805
806 /* Class 12 - Locks Information */
807 QSI_DEF(SystemLocksInformation)
808 {
809 /* FIXME */
810 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
811 return (STATUS_NOT_IMPLEMENTED);
812 }
813
814 /* Class 13 - Stack Trace Information */
815 QSI_DEF(SystemStackTraceInformation)
816 {
817 /* FIXME */
818 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
819 return (STATUS_NOT_IMPLEMENTED);
820 }
821
822 /* Class 14 - Paged Pool Information */
823 QSI_DEF(SystemPagedPoolInformation)
824 {
825 /* FIXME */
826 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
827 return (STATUS_NOT_IMPLEMENTED);
828 }
829
830 /* Class 15 - Non Paged Pool Information */
831 QSI_DEF(SystemNonPagedPoolInformation)
832 {
833 /* FIXME */
834 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
835 return (STATUS_NOT_IMPLEMENTED);
836 }
837
838
839 VOID
840 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
841 PEPROCESS Process,
842 int Count);
843
844 /* Class 16 - Handle Information */
845 QSI_DEF(SystemHandleInformation)
846 {
847 PEPROCESS pr, syspr;
848 ULONG curSize, i = 0;
849 ULONG hCount = 0;
850
851 PSYSTEM_HANDLE_INFORMATION Shi =
852 (PSYSTEM_HANDLE_INFORMATION) Buffer;
853
854 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
855
856 if (Size < sizeof (SYSTEM_HANDLE_INFORMATION))
857 {
858 * ReqSize = sizeof (SYSTEM_HANDLE_INFORMATION);
859 return (STATUS_INFO_LENGTH_MISMATCH);
860 }
861
862 DPRINT("SystemHandleInformation 1\n");
863
864 /* First Calc Size from Count. */
865 syspr = PsGetNextProcess(NULL);
866 pr = syspr;
867
868 do
869 {
870 hCount = hCount + (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
871 pr = PsGetNextProcess(pr);
872
873 if ((pr == syspr) || (pr == NULL))
874 break;
875 } while ((pr != syspr) && (pr != NULL));
876
877 if(pr != NULL)
878 {
879 ObDereferenceObject(pr);
880 }
881
882 DPRINT("SystemHandleInformation 2\n");
883
884 curSize = sizeof(SYSTEM_HANDLE_INFORMATION)+
885 ( (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) -
886 (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) ));
887
888 Shi->NumberOfHandles = hCount;
889
890 if (curSize > Size)
891 {
892 *ReqSize = curSize;
893 return (STATUS_INFO_LENGTH_MISMATCH);
894 }
895
896 DPRINT("SystemHandleInformation 3\n");
897
898 /* Now get Handles from all processs. */
899 syspr = PsGetNextProcess(NULL);
900 pr = syspr;
901
902 do
903 {
904 int Count = 0, HandleCount;
905
906 HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
907
908 for (Count = 0; HandleCount > 0 ; HandleCount--)
909 {
910 ObpGetNextHandleByProcessCount( &Shi->Handles[i], pr, Count);
911 Count++;
912 i++;
913 }
914
915 pr = PsGetNextProcess(pr);
916
917 if ((pr == syspr) || (pr == NULL))
918 break;
919 } while ((pr != syspr) && (pr != NULL));
920
921 if(pr != NULL)
922 {
923 ObDereferenceObject(pr);
924 }
925
926 DPRINT("SystemHandleInformation 4\n");
927 return (STATUS_SUCCESS);
928
929 }
930 /*
931 SSI_DEF(SystemHandleInformation)
932 {
933
934 return (STATUS_SUCCESS);
935 }
936 */
937
938 /* Class 17 - Information */
939 QSI_DEF(SystemObjectInformation)
940 {
941 /* FIXME */
942 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
943 return (STATUS_NOT_IMPLEMENTED);
944 }
945
946 /* Class 18 - Information */
947 QSI_DEF(SystemPageFileInformation)
948 {
949 UNICODE_STRING FileName; /* FIXME */
950 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
951
952 if (Size < sizeof (SYSTEM_PAGEFILE_INFORMATION))
953 {
954 * ReqSize = sizeof (SYSTEM_PAGEFILE_INFORMATION);
955 return (STATUS_INFO_LENGTH_MISMATCH);
956 }
957
958 RtlInitUnicodeString(&FileName, NULL); /* FIXME */
959
960 /* FIXME */
961 Spfi->NextEntryOffset = 0;
962
963 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
964 Spfi->TotalInUse = MiUsedSwapPages;
965 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
966 Spfi->PageFileName = FileName;
967 return (STATUS_SUCCESS);
968 }
969
970 /* Class 19 - Vdm Instemul Information */
971 QSI_DEF(SystemVdmInstemulInformation)
972 {
973 /* FIXME */
974 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
975 return (STATUS_NOT_IMPLEMENTED);
976 }
977
978 /* Class 20 - Vdm Bop Information */
979 QSI_DEF(SystemVdmBopInformation)
980 {
981 /* FIXME */
982 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
983 return (STATUS_NOT_IMPLEMENTED);
984 }
985
986 /* Class 21 - File Cache Information */
987 QSI_DEF(SystemFileCacheInformation)
988 {
989 SYSTEM_CACHE_INFORMATION *Sci = (SYSTEM_CACHE_INFORMATION *) Buffer;
990
991 if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
992 {
993 * ReqSize = sizeof (SYSTEM_CACHE_INFORMATION);
994 return (STATUS_INFO_LENGTH_MISMATCH);
995 }
996
997 RtlZeroMemory(Sci, sizeof(SYSTEM_CACHE_INFORMATION));
998
999 /* Return the Byte size not the page size. */
1000 Sci->CurrentSize =
1001 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
1002 Sci->PeakSize =
1003 MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE; /* FIXME */
1004
1005 Sci->PageFaultCount = 0; /* FIXME */
1006 Sci->MinimumWorkingSet = 0; /* FIXME */
1007 Sci->MaximumWorkingSet = 0; /* FIXME */
1008
1009 return (STATUS_SUCCESS);
1010 }
1011
1012 SSI_DEF(SystemFileCacheInformation)
1013 {
1014 if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
1015 {
1016 return (STATUS_INFO_LENGTH_MISMATCH);
1017 }
1018 /* FIXME */
1019 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
1020 return (STATUS_NOT_IMPLEMENTED);
1021 }
1022
1023 /* Class 22 - Pool Tag Information */
1024 QSI_DEF(SystemPoolTagInformation)
1025 {
1026 /* FIXME */
1027 DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
1028 return (STATUS_NOT_IMPLEMENTED);
1029 }
1030
1031 /* Class 23 - Interrupt Information for all processors */
1032 QSI_DEF(SystemInterruptInformation)
1033 {
1034 PKPRCB Prcb;
1035 LONG i;
1036 ULONG ti;
1037 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
1038
1039 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
1040 {
1041 return (STATUS_INFO_LENGTH_MISMATCH);
1042 }
1043
1044 ti = KeQueryTimeIncrement();
1045
1046 Prcb = ((PKPCR)KPCR_BASE)->Prcb;
1047 for (i = 0; i < KeNumberProcessors; i++)
1048 {
1049 sii->ContextSwitches = Prcb->KeContextSwitches;
1050 sii->DpcCount = 0; /* FIXME */
1051 sii->DpcRate = 0; /* FIXME */
1052 sii->TimeIncrement = ti;
1053 sii->DpcBypassCount = 0; /* FIXME */
1054 sii->ApcBypassCount = 0; /* FIXME */
1055 sii++;
1056 Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
1057 }
1058
1059 return STATUS_SUCCESS;
1060 }
1061
1062 /* Class 24 - DPC Behaviour Information */
1063 QSI_DEF(SystemDpcBehaviourInformation)
1064 {
1065 /* FIXME */
1066 DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
1067 return (STATUS_NOT_IMPLEMENTED);
1068 }
1069
1070 SSI_DEF(SystemDpcBehaviourInformation)
1071 {
1072 /* FIXME */
1073 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
1074 return (STATUS_NOT_IMPLEMENTED);
1075 }
1076
1077 /* Class 25 - Full Memory Information */
1078 QSI_DEF(SystemFullMemoryInformation)
1079 {
1080 PULONG Spi = (PULONG) Buffer;
1081
1082 PEPROCESS TheIdleProcess;
1083
1084 * ReqSize = sizeof (ULONG);
1085
1086 if (sizeof (ULONG) != Size)
1087 {
1088 return (STATUS_INFO_LENGTH_MISMATCH);
1089 }
1090 DPRINT("SystemFullMemoryInformation\n");
1091
1092 TheIdleProcess = PsIdleProcess;
1093
1094 DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
1095 TheIdleProcess->UniqueProcessId,
1096 TheIdleProcess->Pcb.KernelTime,
1097 MiFreeSwapPages,
1098 MiUsedSwapPages);
1099
1100 #ifndef NDEBUG
1101 MmPrintMemoryStatistic();
1102 #endif
1103
1104 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
1105
1106 return (STATUS_SUCCESS);
1107 }
1108
1109 /* Class 26 - Load Image */
1110 SSI_DEF(SystemLoadImage)
1111 {
1112 PSYSTEM_GDI_DRIVER_INFORMATION Sli = (PSYSTEM_GDI_DRIVER_INFORMATION)Buffer;
1113
1114 if (sizeof(SYSTEM_GDI_DRIVER_INFORMATION) != Size)
1115 {
1116 return(STATUS_INFO_LENGTH_MISMATCH);
1117 }
1118
1119 return(LdrpLoadImage(&Sli->DriverName,
1120 &Sli->ImageAddress,
1121 &Sli->SectionPointer,
1122 &Sli->EntryPoint,
1123 (PVOID)&Sli->ExportSectionPointer));
1124 }
1125
1126 /* Class 27 - Unload Image */
1127 SSI_DEF(SystemUnloadImage)
1128 {
1129 PVOID Sui = (PVOID)Buffer;
1130
1131 if (sizeof(PVOID) != Size)
1132 {
1133 return(STATUS_INFO_LENGTH_MISMATCH);
1134 }
1135
1136 return(LdrpUnloadImage(Sui));
1137 }
1138
1139 /* Class 28 - Time Adjustment Information */
1140 QSI_DEF(SystemTimeAdjustmentInformation)
1141 {
1142 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION) > Size)
1143 {
1144 * ReqSize = sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION);
1145 return (STATUS_INFO_LENGTH_MISMATCH);
1146 }
1147 /* FIXME: */
1148 DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1149 return (STATUS_NOT_IMPLEMENTED);
1150 }
1151
1152 SSI_DEF(SystemTimeAdjustmentInformation)
1153 {
1154 if (sizeof (SYSTEM_SET_TIME_ADJUST_INFORMATION) > Size)
1155 {
1156 return (STATUS_INFO_LENGTH_MISMATCH);
1157 }
1158 /* FIXME: */
1159 DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
1160 return (STATUS_NOT_IMPLEMENTED);
1161 }
1162
1163 /* Class 29 - Summary Memory Information */
1164 QSI_DEF(SystemSummaryMemoryInformation)
1165 {
1166 /* FIXME */
1167 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
1168 return (STATUS_NOT_IMPLEMENTED);
1169 }
1170
1171 /* Class 30 - Next Event Id Information */
1172 QSI_DEF(SystemNextEventIdInformation)
1173 {
1174 /* FIXME */
1175 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
1176 return (STATUS_NOT_IMPLEMENTED);
1177 }
1178
1179 /* Class 31 - Event Ids Information */
1180 QSI_DEF(SystemEventIdsInformation)
1181 {
1182 /* FIXME */
1183 DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
1184 return (STATUS_NOT_IMPLEMENTED);
1185 }
1186
1187 /* Class 32 - Crash Dump Information */
1188 QSI_DEF(SystemCrashDumpInformation)
1189 {
1190 /* FIXME */
1191 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
1192 return (STATUS_NOT_IMPLEMENTED);
1193 }
1194
1195 /* Class 33 - Exception Information */
1196 QSI_DEF(SystemExceptionInformation)
1197 {
1198 /* FIXME */
1199 DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
1200 return (STATUS_NOT_IMPLEMENTED);
1201 }
1202
1203 /* Class 34 - Crash Dump State Information */
1204 QSI_DEF(SystemCrashDumpStateInformation)
1205 {
1206 /* FIXME */
1207 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
1208 return (STATUS_NOT_IMPLEMENTED);
1209 }
1210
1211 /* Class 35 - Kernel Debugger Information */
1212 QSI_DEF(SystemKernelDebuggerInformation)
1213 {
1214 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
1215
1216 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
1217 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
1218 {
1219 return STATUS_INFO_LENGTH_MISMATCH;
1220 }
1221
1222 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
1223 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
1224
1225 return STATUS_SUCCESS;
1226 }
1227
1228 /* Class 36 - Context Switch Information */
1229 QSI_DEF(SystemContextSwitchInformation)
1230 {
1231 /* FIXME */
1232 DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
1233 return (STATUS_NOT_IMPLEMENTED);
1234 }
1235
1236 /* Class 37 - Registry Quota Information */
1237 QSI_DEF(SystemRegistryQuotaInformation)
1238 {
1239 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
1240
1241 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
1242 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
1243 {
1244 return STATUS_INFO_LENGTH_MISMATCH;
1245 }
1246
1247 DPRINT1("Faking max registry size of 32 MB\n");
1248 srqi->RegistryQuotaAllowed = 0x2000000;
1249 srqi->RegistryQuotaUsed = 0x200000;
1250 srqi->PagedPoolSize = 0x200000;
1251
1252 return STATUS_SUCCESS;
1253 }
1254
1255 SSI_DEF(SystemRegistryQuotaInformation)
1256 {
1257 /* FIXME */
1258 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
1259 return (STATUS_NOT_IMPLEMENTED);
1260 }
1261
1262 /* Class 38 - Load And Call Image */
1263 SSI_DEF(SystemLoadAndCallImage)
1264 {
1265 PUNICODE_STRING Slci = (PUNICODE_STRING)Buffer;
1266
1267 if (sizeof(UNICODE_STRING) != Size)
1268 {
1269 return(STATUS_INFO_LENGTH_MISMATCH);
1270 }
1271
1272 return(LdrpLoadAndCallImage(Slci));
1273 }
1274
1275 /* Class 39 - Priority Separation */
1276 SSI_DEF(SystemPrioritySeperation)
1277 {
1278 /* FIXME */
1279 DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
1280 return (STATUS_NOT_IMPLEMENTED);
1281 }
1282
1283 /* Class 40 - Plug Play Bus Information */
1284 QSI_DEF(SystemPlugPlayBusInformation)
1285 {
1286 /* FIXME */
1287 DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
1288 return (STATUS_NOT_IMPLEMENTED);
1289 }
1290
1291 /* Class 41 - Dock Information */
1292 QSI_DEF(SystemDockInformation)
1293 {
1294 /* FIXME */
1295 DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
1296 return (STATUS_NOT_IMPLEMENTED);
1297 }
1298
1299 /* Class 42 - Power Information */
1300 QSI_DEF(SystemPowerInformation)
1301 {
1302 /* FIXME */
1303 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
1304 return (STATUS_NOT_IMPLEMENTED);
1305 }
1306
1307 /* Class 43 - Processor Speed Information */
1308 QSI_DEF(SystemProcessorSpeedInformation)
1309 {
1310 /* FIXME */
1311 DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
1312 return (STATUS_NOT_IMPLEMENTED);
1313 }
1314
1315 /* Class 44 - Current Time Zone Information */
1316 QSI_DEF(SystemCurrentTimeZoneInformation)
1317 {
1318 * ReqSize = sizeof (TIME_ZONE_INFORMATION);
1319
1320 if (sizeof (TIME_ZONE_INFORMATION) != Size)
1321 {
1322 return STATUS_INFO_LENGTH_MISMATCH;
1323 }
1324
1325 /* Copy the time zone information struct */
1326 memcpy(Buffer,
1327 &ExpTimeZoneInfo,
1328 sizeof(TIME_ZONE_INFORMATION));
1329
1330 return STATUS_SUCCESS;
1331 }
1332
1333
1334 SSI_DEF(SystemCurrentTimeZoneInformation)
1335 {
1336 /* Check user buffer's size */
1337 if (Size < sizeof (TIME_ZONE_INFORMATION))
1338 {
1339 return STATUS_INFO_LENGTH_MISMATCH;
1340 }
1341
1342 return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
1343 }
1344
1345
1346 /* Class 45 - Lookaside Information */
1347 QSI_DEF(SystemLookasideInformation)
1348 {
1349 /* FIXME */
1350 DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
1351 return (STATUS_NOT_IMPLEMENTED);
1352 }
1353
1354
1355 /* Class 46 - Set time slip event */
1356 SSI_DEF(SystemSetTimeSlipEvent)
1357 {
1358 /* FIXME */
1359 DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
1360 return (STATUS_NOT_IMPLEMENTED);
1361 }
1362
1363
1364 /* Class 47 - Create a new session (TSE) */
1365 SSI_DEF(SystemCreateSession)
1366 {
1367 /* FIXME */
1368 DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
1369 return (STATUS_NOT_IMPLEMENTED);
1370 }
1371
1372
1373 /* Class 48 - Delete an existing session (TSE) */
1374 SSI_DEF(SystemDeleteSession)
1375 {
1376 /* FIXME */
1377 DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
1378 return (STATUS_NOT_IMPLEMENTED);
1379 }
1380
1381
1382 /* Class 49 - UNKNOWN */
1383 QSI_DEF(SystemInvalidInfoClass4)
1384 {
1385 /* FIXME */
1386 DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
1387 return (STATUS_NOT_IMPLEMENTED);
1388 }
1389
1390
1391 /* Class 50 - System range start address */
1392 QSI_DEF(SystemRangeStartInformation)
1393 {
1394 /* FIXME */
1395 DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
1396 return (STATUS_NOT_IMPLEMENTED);
1397 }
1398
1399
1400 /* Class 51 - Driver verifier information */
1401 QSI_DEF(SystemVerifierInformation)
1402 {
1403 /* FIXME */
1404 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
1405 return (STATUS_NOT_IMPLEMENTED);
1406 }
1407
1408
1409 SSI_DEF(SystemVerifierInformation)
1410 {
1411 /* FIXME */
1412 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
1413 return (STATUS_NOT_IMPLEMENTED);
1414 }
1415
1416
1417 /* Class 52 - Add a driver verifier */
1418 SSI_DEF(SystemAddVerifier)
1419 {
1420 /* FIXME */
1421 DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
1422 return (STATUS_NOT_IMPLEMENTED);
1423 }
1424
1425
1426 /* Class 53 - A session's processes */
1427 QSI_DEF(SystemSessionProcessesInformation)
1428 {
1429 /* FIXME */
1430 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
1431 return (STATUS_NOT_IMPLEMENTED);
1432 }
1433
1434
1435 /* Query/Set Calls Table */
1436 typedef
1437 struct _QSSI_CALLS
1438 {
1439 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1440 NTSTATUS (* Set) (PVOID,ULONG);
1441
1442 } QSSI_CALLS;
1443
1444 // QS Query & Set
1445 // QX Query
1446 // XS Set
1447 // XX unknown behaviour
1448 //
1449 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1450 #define SI_QX(n) {QSI_USE(n),NULL}
1451 #define SI_XS(n) {NULL,SSI_USE(n)}
1452 #define SI_XX(n) {NULL,NULL}
1453
1454 static
1455 QSSI_CALLS
1456 CallQS [] =
1457 {
1458 SI_QX(SystemBasicInformation),
1459 SI_QX(SystemProcessorInformation),
1460 SI_QX(SystemPerformanceInformation),
1461 SI_QX(SystemTimeOfDayInformation),
1462 SI_QX(SystemPathInformation), /* should be SI_XX */
1463 SI_QX(SystemProcessInformation),
1464 SI_QX(SystemCallCountInformation),
1465 SI_QX(SystemDeviceInformation),
1466 SI_QX(SystemProcessorPerformanceInformation),
1467 SI_QS(SystemFlagsInformation),
1468 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1469 SI_QX(SystemModuleInformation),
1470 SI_QX(SystemLocksInformation),
1471 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1472 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1473 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1474 SI_QX(SystemHandleInformation),
1475 SI_QX(SystemObjectInformation),
1476 SI_QX(SystemPageFileInformation),
1477 SI_QX(SystemVdmInstemulInformation),
1478 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1479 SI_QS(SystemFileCacheInformation),
1480 SI_QX(SystemPoolTagInformation),
1481 SI_QX(SystemInterruptInformation),
1482 SI_QS(SystemDpcBehaviourInformation),
1483 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1484 SI_XS(SystemLoadImage),
1485 SI_XS(SystemUnloadImage),
1486 SI_QS(SystemTimeAdjustmentInformation),
1487 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1488 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1489 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1490 SI_QX(SystemCrashDumpInformation),
1491 SI_QX(SystemExceptionInformation),
1492 SI_QX(SystemCrashDumpStateInformation),
1493 SI_QX(SystemKernelDebuggerInformation),
1494 SI_QX(SystemContextSwitchInformation),
1495 SI_QS(SystemRegistryQuotaInformation),
1496 SI_XS(SystemLoadAndCallImage),
1497 SI_XS(SystemPrioritySeperation),
1498 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1499 SI_QX(SystemDockInformation), /* it should be SI_XX */
1500 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1501 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1502 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1503 SI_QX(SystemLookasideInformation),
1504 SI_XS(SystemSetTimeSlipEvent),
1505 SI_XS(SystemCreateSession),
1506 SI_XS(SystemDeleteSession),
1507 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1508 SI_QX(SystemRangeStartInformation),
1509 SI_QS(SystemVerifierInformation),
1510 SI_XS(SystemAddVerifier),
1511 SI_QX(SystemSessionProcessesInformation)
1512 };
1513
1514
1515 /*
1516 * @implemented
1517 */
1518 NTSTATUS STDCALL
1519 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1520 OUT PVOID SystemInformation,
1521 IN ULONG Length,
1522 OUT PULONG UnsafeResultLength)
1523 {
1524 KPROCESSOR_MODE PreviousMode;
1525 ULONG ResultLength;
1526 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
1527
1528 PAGED_CODE();
1529
1530 PreviousMode = ExGetPreviousMode();
1531
1532 _SEH_TRY
1533 {
1534 if (PreviousMode != KernelMode)
1535 {
1536 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
1537 ProbeForWrite(SystemInformation, Length, 1);
1538 if (UnsafeResultLength != NULL)
1539 ProbeForWriteUlong(UnsafeResultLength);
1540 }
1541
1542 /* Clear user buffer. */
1543 RtlZeroMemory(SystemInformation, Length);
1544
1545 /*
1546 * Check the request is valid.
1547 */
1548 if (SystemInformationClass >= SystemInformationClassMax)
1549 {
1550 return (STATUS_INVALID_INFO_CLASS);
1551 }
1552
1553 if (NULL != CallQS [SystemInformationClass].Query)
1554 {
1555 /*
1556 * Hand the request to a subhandler.
1557 */
1558 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1559 Length,
1560 &ResultLength);
1561 if (UnsafeResultLength != NULL)
1562 {
1563 if (PreviousMode != KernelMode)
1564 {
1565 _SEH_TRY
1566 {
1567 *UnsafeResultLength = ResultLength;
1568 }
1569 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
1570 {
1571 FStatus = _SEH_GetExceptionCode();
1572 }
1573 _SEH_END;
1574 }
1575 else
1576 {
1577 *UnsafeResultLength = ResultLength;
1578 }
1579 }
1580 }
1581 }
1582 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
1583 {
1584 FStatus = _SEH_GetExceptionCode();
1585 }
1586 _SEH_END;
1587
1588 return (FStatus);
1589 }
1590
1591
1592 NTSTATUS
1593 STDCALL
1594 NtSetSystemInformation (
1595 IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1596 IN PVOID SystemInformation,
1597 IN ULONG SystemInformationLength
1598 )
1599 {
1600 PAGED_CODE();
1601
1602 /*
1603 * If called from user mode, check
1604 * possible unsafe arguments.
1605 */
1606 #if 0
1607 if (KernelMode != KeGetPreviousMode())
1608 {
1609 // Check arguments
1610 //ProbeForWrite(
1611 // SystemInformation,
1612 // Length
1613 // );
1614 //ProbeForWrite(
1615 // ResultLength,
1616 // sizeof (ULONG)
1617 // );
1618 }
1619 #endif
1620 /*
1621 * Check the request is valid.
1622 */
1623 if ( (SystemInformationClass >= SystemBasicInformation)
1624 && (SystemInformationClass < SystemInformationClassMax)
1625 )
1626 {
1627 if (NULL != CallQS [SystemInformationClass].Set)
1628 {
1629 /*
1630 * Hand the request to a subhandler.
1631 */
1632 return CallQS [SystemInformationClass].Set (
1633 SystemInformation,
1634 SystemInformationLength
1635 );
1636 }
1637 }
1638 return (STATUS_INVALID_INFO_CLASS);
1639 }
1640
1641
1642 NTSTATUS
1643 STDCALL
1644 NtFlushInstructionCache (
1645 IN HANDLE ProcessHandle,
1646 IN PVOID BaseAddress,
1647 IN ULONG NumberOfBytesToFlush
1648 )
1649 {
1650 PAGED_CODE();
1651
1652 __asm__("wbinvd\n");
1653 return STATUS_SUCCESS;
1654 }
1655
1656
1657 /* EOF */