- Return success for SystemFileCacheInformation requests to NtQuerySystemInformation...
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
1 /* $Id: sysinfo.c,v 1.35 2004/05/26 19:56:35 navaraf Exp $
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 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 * 20/03/2003: implemented querying SystemProcessInformation,
11 * no more copying to-from the caller (Aleksey
12 * Bragin <aleksey@studiocerebral.com>)
13 */
14
15 /* INCLUDES *****************************************************************/
16
17 #define NTOS_MODE_KERNEL
18 #include <ntos.h>
19 #include <ddk/halfuncs.h>
20 #include <internal/ex.h>
21 #include <internal/io.h>
22 #include <internal/ldr.h>
23 #include <internal/safe.h>
24 #include <internal/ps.h>
25 #include <internal/mm.h>
26
27 #define NDEBUG
28 #include <internal/debug.h>
29
30 extern ULONG NtGlobalFlag; /* FIXME: it should go in a ddk/?.h */
31 VOID STDCALL KeQueryInterruptTime(PLARGE_INTEGER CurrentTime);
32
33 VOID MmPrintMemoryStatistic(VOID);
34
35 extern ULONG Ke386CpuidFlags;
36 extern ULONG Ke386Cpuid;
37
38 /* FUNCTIONS *****************************************************************/
39
40 NTSTATUS STDCALL
41 NtQuerySystemEnvironmentValue (IN PUNICODE_STRING UnsafeName,
42 OUT PVOID UnsafeValue,
43 IN ULONG Length,
44 IN OUT PULONG UnsafeReturnLength)
45 {
46 NTSTATUS Status;
47 ANSI_STRING AName;
48 UNICODE_STRING WName;
49 BOOLEAN Result;
50 PCH Value;
51 ANSI_STRING AValue;
52 UNICODE_STRING WValue;
53 ULONG ReturnLength;
54
55 /*
56 * Copy the name to kernel space if necessary and convert it to ANSI.
57 */
58 if (ExGetPreviousMode() != KernelMode)
59 {
60 Status = RtlCaptureUnicodeString(&WName, UnsafeName);
61 if (!NT_SUCCESS(Status))
62 {
63 return(Status);
64 }
65 Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
66 if (!NT_SUCCESS(Status))
67 {
68 return(Status);
69 }
70 }
71 else
72 {
73 Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
74 if (!NT_SUCCESS(Status))
75 {
76 return(Status);
77 }
78 }
79
80 /*
81 * Create a temporary buffer for the value
82 */
83 Value = ExAllocatePool(NonPagedPool, Length);
84 if (Value == NULL)
85 {
86 RtlFreeAnsiString(&AName);
87 if (ExGetPreviousMode() != KernelMode)
88 {
89 RtlFreeUnicodeString(&WName);
90 }
91 return(STATUS_NO_MEMORY);
92 }
93
94 /*
95 * Get the environment variable
96 */
97 Result = HalGetEnvironmentVariable(AName.Buffer, Value, Length);
98 if (!Result)
99 {
100 RtlFreeAnsiString(&AName);
101 if (ExGetPreviousMode() != KernelMode)
102 {
103 RtlFreeUnicodeString(&WName);
104 }
105 ExFreePool(Value);
106 return(STATUS_UNSUCCESSFUL);
107 }
108
109 /*
110 * Convert the result to UNICODE.
111 */
112 RtlInitAnsiString(&AValue, Value);
113 Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
114 if (!NT_SUCCESS(Status))
115 {
116 RtlFreeAnsiString(&AName);
117 if (ExGetPreviousMode() != KernelMode)
118 {
119 RtlFreeUnicodeString(&WName);
120 }
121 ExFreePool(Value);
122 return(Status);
123 }
124 ReturnLength = WValue.Length;
125
126 /*
127 * Copy the result back to the caller.
128 */
129 if (ExGetPreviousMode() != KernelMode)
130 {
131 Status = MmCopyToCaller(UnsafeValue, WValue.Buffer, ReturnLength);
132 if (!NT_SUCCESS(Status))
133 {
134 RtlFreeAnsiString(&AName);
135 if (ExGetPreviousMode() != KernelMode)
136 {
137 RtlFreeUnicodeString(&WName);
138 }
139 ExFreePool(Value);
140 RtlFreeUnicodeString(&WValue);
141 return(Status);
142 }
143
144 Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength,
145 sizeof(ULONG));
146 if (!NT_SUCCESS(Status))
147 {
148 RtlFreeAnsiString(&AName);
149 if (ExGetPreviousMode() != KernelMode)
150 {
151 RtlFreeUnicodeString(&WName);
152 }
153 ExFreePool(Value);
154 RtlFreeUnicodeString(&WValue);
155 return(Status);
156 }
157 }
158 else
159 {
160 memcpy(UnsafeValue, WValue.Buffer, ReturnLength);
161 memcpy(UnsafeReturnLength, &ReturnLength, sizeof(ULONG));
162 }
163
164 /*
165 * Free temporary buffers.
166 */
167 RtlFreeAnsiString(&AName);
168 if (ExGetPreviousMode() != KernelMode)
169 {
170 RtlFreeUnicodeString(&WName);
171 }
172 ExFreePool(Value);
173 RtlFreeUnicodeString(&WValue);
174
175 return(STATUS_SUCCESS);
176 }
177
178
179 NTSTATUS STDCALL
180 NtSetSystemEnvironmentValue (IN PUNICODE_STRING UnsafeName,
181 IN PUNICODE_STRING UnsafeValue)
182 {
183 UNICODE_STRING WName;
184 ANSI_STRING AName;
185 UNICODE_STRING WValue;
186 ANSI_STRING AValue;
187 BOOLEAN Result;
188 NTSTATUS Status;
189
190 /*
191 * Check for required privilege.
192 */
193 /* FIXME: Not implemented. */
194
195 /*
196 * Copy the name to kernel space if necessary and convert it to ANSI.
197 */
198 if (ExGetPreviousMode() != KernelMode)
199 {
200 Status = RtlCaptureUnicodeString(&WName, UnsafeName);
201 if (!NT_SUCCESS(Status))
202 {
203 return(Status);
204 }
205 Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
206 if (!NT_SUCCESS(Status))
207 {
208 return(Status);
209 }
210 }
211 else
212 {
213 Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
214 if (!NT_SUCCESS(Status))
215 {
216 return(Status);
217 }
218 }
219
220 /*
221 * Copy the value to kernel space and convert to ANSI.
222 */
223 if (ExGetPreviousMode() != KernelMode)
224 {
225 Status = RtlCaptureUnicodeString(&WValue, UnsafeValue);
226 if (!NT_SUCCESS(Status))
227 {
228 RtlFreeUnicodeString(&WName);
229 RtlFreeAnsiString(&AName);
230 return(Status);
231 }
232 Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE);
233 if (!NT_SUCCESS(Status))
234 {
235 RtlFreeUnicodeString(&WName);
236 RtlFreeAnsiString(&AName);
237 RtlFreeUnicodeString(&WValue);
238 return(Status);
239 }
240 }
241 else
242 {
243 Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE);
244 if (!NT_SUCCESS(Status))
245 {
246 RtlFreeAnsiString(&AName);
247 return(Status);
248 }
249 }
250
251 /*
252 * Set the environment variable
253 */
254 Result = HalSetEnvironmentVariable(AName.Buffer, AValue.Buffer);
255
256 /*
257 * Free everything and return status.
258 */
259 RtlFreeAnsiString(&AName);
260 RtlFreeAnsiString(&AValue);
261 if (ExGetPreviousMode() != KernelMode)
262 {
263 RtlFreeUnicodeString(&WName);
264 RtlFreeUnicodeString(&WValue);
265 }
266
267 if (!Result)
268 {
269 return(STATUS_UNSUCCESSFUL);
270 }
271 return(STATUS_SUCCESS);
272 }
273
274
275 /* --- Query/Set System Information --- */
276
277 /*
278 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
279 * so the stack is popped only in one place on x86 platform.
280 */
281 #define QSI_USE(n) QSI##n
282 #define QSI_DEF(n) \
283 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
284
285 #define SSI_USE(n) SSI##n
286 #define SSI_DEF(n) \
287 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
288
289
290 /* Class 0 - Basic Information */
291 QSI_DEF(SystemBasicInformation)
292 {
293 PSYSTEM_BASIC_INFORMATION Sbi
294 = (PSYSTEM_BASIC_INFORMATION) Buffer;
295
296 *ReqSize = sizeof (SYSTEM_BASIC_INFORMATION);
297 /*
298 * Check user buffer's size
299 */
300 if (Size < sizeof (SYSTEM_BASIC_INFORMATION))
301 {
302 return (STATUS_INFO_LENGTH_MISMATCH);
303 }
304 Sbi->Unknown = 0;
305 Sbi->MaximumIncrement = 100000; /* FIXME */
306 Sbi->PhysicalPageSize = PAGE_SIZE; /* FIXME: it should be PAGE_SIZE */
307 Sbi->NumberOfPhysicalPages = MmStats.NrTotalPages;
308 Sbi->LowestPhysicalPage = 0; /* FIXME */
309 Sbi->HighestPhysicalPage = MmStats.NrTotalPages; /* FIXME */
310 Sbi->AllocationGranularity = 65536; /* hard coded on Intel? */
311 Sbi->LowestUserAddress = 0x10000; /* Top of 64k */
312 Sbi->HighestUserAddress = 0x7ffeffff; /* From mm/mminit.c */
313 Sbi->ActiveProcessors = 0x00000001; /* FIXME */
314 Sbi->NumberProcessors = KeNumberProcessors;
315 return (STATUS_SUCCESS);
316 }
317
318 /* Class 1 - Processor Information */
319 QSI_DEF(SystemProcessorInformation)
320 {
321 PSYSTEM_PROCESSOR_INFORMATION Spi
322 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
323
324 *ReqSize = sizeof (SYSTEM_PROCESSOR_INFORMATION);
325 /*
326 * Check user buffer's size
327 */
328 if (Size < sizeof (SYSTEM_PROCESSOR_INFORMATION))
329 {
330 return (STATUS_INFO_LENGTH_MISMATCH);
331 }
332 Spi->ProcessorArchitecture = 0; /* Intel Processor */
333 Spi->ProcessorLevel = ((Ke386Cpuid >> 8) & 0xf);
334 Spi->ProcessorRevision = (Ke386Cpuid & 0xf) | ((Ke386Cpuid << 4) & 0xf00);
335 Spi->Unknown = 0;
336 Spi->FeatureBits = Ke386CpuidFlags;
337
338 DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
339 Spi->ProcessorLevel, Spi->ProcessorRevision);
340
341 return (STATUS_SUCCESS);
342 }
343
344 /* Class 2 - Performance Information */
345 QSI_DEF(SystemPerformanceInformation)
346 {
347 PSYSTEM_PERFORMANCE_INFORMATION Spi
348 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
349
350 PEPROCESS TheIdleProcess;
351
352 *ReqSize = sizeof (SYSTEM_PERFORMANCE_INFORMATION);
353 /*
354 * Check user buffer's size
355 */
356 if (Size < sizeof (SYSTEM_PERFORMANCE_INFORMATION))
357 {
358 return (STATUS_INFO_LENGTH_MISMATCH);
359 }
360
361 PsLookupProcessByProcessId((PVOID) 1, &TheIdleProcess);
362
363 Spi->IdleTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000;
364
365 Spi->ReadTransferCount.QuadPart = IoReadTransferCount;
366 Spi->WriteTransferCount.QuadPart = IoWriteTransferCount;
367 Spi->OtherTransferCount.QuadPart = IoOtherTransferCount;
368 Spi->ReadOperationCount = IoReadOperationCount;
369 Spi->WriteOperationCount = IoWriteOperationCount;
370 Spi->OtherOperationCount = IoOtherOperationCount;
371
372 Spi->AvailablePages = MiNrAvailablePages;
373 Spi->TotalCommittedPages = MiUsedSwapPages;
374 Spi->TotalCommitLimit = MiFreeSwapPages + MiUsedSwapPages; /* FIXME */
375
376 Spi->PeakCommitment = 0; /* FIXME */
377 Spi->PageFaults = 0; /* FIXME */
378 Spi->WriteCopyFaults = 0; /* FIXME */
379 Spi->TransitionFaults = 0; /* FIXME */
380 Spi->CacheTransitionFaults = 0; /* FIXME */
381 Spi->DemandZeroFaults = 0; /* FIXME */
382 Spi->PagesRead = 0; /* FIXME */
383 Spi->PageReadIos = 0; /* FIXME */
384 Spi->CacheReads = 0; /* FIXME */
385 Spi->CacheIos = 0; /* FIXME */
386 Spi->PagefilePagesWritten = 0; /* FIXME */
387 Spi->PagefilePageWriteIos = 0; /* FIXME */
388 Spi->MappedFilePagesWritten = 0; /* FIXME */
389 Spi->MappedFilePageWriteIos = 0; /* FIXME */
390
391 Spi->PagedPoolUsage = MiMemoryConsumers[MC_PPOOL].PagesUsed;
392 Spi->PagedPoolAllocs = 0; /* FIXME */
393 Spi->PagedPoolFrees = 0; /* FIXME */
394 Spi->NonPagedPoolUsage = MiMemoryConsumers[MC_NPPOOL].PagesUsed;
395 Spi->NonPagedPoolAllocs = 0; /* FIXME */
396 Spi->NonPagedPoolFrees = 0; /* FIXME */
397
398 Spi->TotalFreeSystemPtes = 0; /* FIXME */
399
400 Spi->SystemCodePage = MmStats.NrSystemPages; /* FIXME */
401
402 Spi->TotalSystemDriverPages = 0; /* FIXME */
403 Spi->TotalSystemCodePages = 0; /* FIXME */
404 Spi->SmallNonPagedLookasideListAllocateHits = 0; /* FIXME */
405 Spi->SmallPagedLookasideListAllocateHits = 0; /* FIXME */
406 Spi->Reserved3 = 0; /* FIXME */
407
408 Spi->MmSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
409 Spi->PagedPoolPage = MmPagedPoolSize; /* FIXME */
410
411 Spi->SystemDriverPage = 0; /* FIXME */
412 Spi->FastReadNoWait = 0; /* FIXME */
413 Spi->FastReadWait = 0; /* FIXME */
414 Spi->FastReadResourceMiss = 0; /* FIXME */
415 Spi->FastReadNotPossible = 0; /* FIXME */
416
417 Spi->FastMdlReadNoWait = 0; /* FIXME */
418 Spi->FastMdlReadWait = 0; /* FIXME */
419 Spi->FastMdlReadResourceMiss = 0; /* FIXME */
420 Spi->FastMdlReadNotPossible = 0; /* FIXME */
421
422 Spi->MapDataNoWait = 0; /* FIXME */
423 Spi->MapDataWait = 0; /* FIXME */
424 Spi->MapDataNoWaitMiss = 0; /* FIXME */
425 Spi->MapDataWaitMiss = 0; /* FIXME */
426
427 Spi->PinMappedDataCount = 0; /* FIXME */
428 Spi->PinReadNoWait = 0; /* FIXME */
429 Spi->PinReadWait = 0; /* FIXME */
430 Spi->PinReadNoWaitMiss = 0; /* FIXME */
431 Spi->PinReadWaitMiss = 0; /* FIXME */
432 Spi->CopyReadNoWait = 0; /* FIXME */
433 Spi->CopyReadWait = 0; /* FIXME */
434 Spi->CopyReadNoWaitMiss = 0; /* FIXME */
435 Spi->CopyReadWaitMiss = 0; /* FIXME */
436
437 Spi->MdlReadNoWait = 0; /* FIXME */
438 Spi->MdlReadWait = 0; /* FIXME */
439 Spi->MdlReadNoWaitMiss = 0; /* FIXME */
440 Spi->MdlReadWaitMiss = 0; /* FIXME */
441 Spi->ReadAheadIos = 0; /* FIXME */
442 Spi->LazyWriteIos = 0; /* FIXME */
443 Spi->LazyWritePages = 0; /* FIXME */
444 Spi->DataFlushes = 0; /* FIXME */
445 Spi->DataPages = 0; /* FIXME */
446 Spi->ContextSwitches = 0; /* FIXME */
447 Spi->FirstLevelTbFills = 0; /* FIXME */
448 Spi->SecondLevelTbFills = 0; /* FIXME */
449 Spi->SystemCalls = 0; /* FIXME */
450
451 ObDereferenceObject(TheIdleProcess);
452
453 return (STATUS_SUCCESS);
454 }
455
456 /* Class 3 - Time Of Day Information */
457 QSI_DEF(SystemTimeOfDayInformation)
458 {
459 LARGE_INTEGER CurrentTime;
460
461 PSYSTEM_TIMEOFDAY_INFORMATION Sti
462 = (PSYSTEM_TIMEOFDAY_INFORMATION) Buffer;
463
464 *ReqSize = sizeof (SYSTEM_TIMEOFDAY_INFORMATION);
465 /*
466 * Check user buffer's size
467 */
468 if (Size < sizeof (SYSTEM_TIMEOFDAY_INFORMATION))
469 {
470 return (STATUS_INFO_LENGTH_MISMATCH);
471 }
472
473 KeQuerySystemTime(&CurrentTime);
474
475 Sti->BootTime= SystemBootTime;
476 Sti->CurrentTime = CurrentTime;
477 Sti->TimeZoneBias.QuadPart = _SystemTimeZoneInfo.Bias;
478 Sti->TimeZoneId = 0; /* FIXME */
479 Sti->Reserved = 0; /* FIXME */
480
481 return (STATUS_SUCCESS);
482 }
483
484 /* Class 4 - Path Information */
485 QSI_DEF(SystemPathInformation)
486 {
487 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
488 return (STATUS_BREAKPOINT);
489 }
490
491 /* Class 5 - Process Information */
492 QSI_DEF(SystemProcessInformation)
493 {
494 ULONG ovlSize=0, nThreads=1;
495 PEPROCESS pr, syspr;
496 unsigned char *pCur;
497
498 /* scan the process list */
499 // TODO: Add thread information
500
501 PSYSTEM_PROCESSES Spi
502 = (PSYSTEM_PROCESSES) Buffer;
503
504 *ReqSize = sizeof(SYSTEM_PROCESSES);
505
506 if (Size < sizeof(SYSTEM_PROCESSES))
507 {
508 return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
509 }
510
511 syspr = PsGetNextProcess(NULL);
512 pr = syspr;
513 pCur = (unsigned char *)Spi;
514
515 do
516 {
517 PSYSTEM_PROCESSES SpiCur;
518 int curSize;
519 ANSI_STRING imgName;
520 int inLen=32; // image name len in bytes
521
522
523 SpiCur = (PSYSTEM_PROCESSES)pCur;
524
525 nThreads = 1; // FIXME
526
527 // size of the structure for every process
528 curSize = sizeof(SYSTEM_PROCESSES)-sizeof(SYSTEM_THREADS)+sizeof(SYSTEM_THREADS)*nThreads;
529 ovlSize += curSize+inLen;
530
531 if (ovlSize > Size)
532 {
533 *ReqSize = ovlSize;
534 ObDereferenceObject(pr);
535
536 return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
537 }
538
539 // fill system information
540 SpiCur->NextEntryDelta = curSize+inLen; // relative offset to the beginnnig of the next structure
541 SpiCur->ThreadCount = nThreads;
542 SpiCur->CreateTime = pr->CreateTime;
543 SpiCur->UserTime.QuadPart = pr->Pcb.UserTime * 100000;
544 SpiCur->KernelTime.QuadPart = pr->Pcb.KernelTime * 100000;
545 SpiCur->ProcessName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
546 SpiCur->ProcessName.MaximumLength = inLen;
547 SpiCur->ProcessName.Buffer = (void*)(pCur+curSize);
548
549 // copy name to the end of the struct
550 RtlInitAnsiString(&imgName, pr->ImageFileName);
551 RtlAnsiStringToUnicodeString(&SpiCur->ProcessName, &imgName, FALSE);
552
553 SpiCur->BasePriority = pr->Pcb.BasePriority;
554 SpiCur->ProcessId = pr->UniqueProcessId;
555 SpiCur->InheritedFromProcessId = (DWORD)(pr->InheritedFromUniqueProcessId);
556 SpiCur->HandleCount = ObpGetHandleCountbyHandleTable(&pr->HandleTable);
557 SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize;
558 SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart;
559 SpiCur->VmCounters.PageFaultCount = pr->LastFaultCount;
560 SpiCur->VmCounters.PeakWorkingSetSize = pr->Vm.PeakWorkingSetSize; // Is this right using ->Vm. here ?
561 SpiCur->VmCounters.WorkingSetSize = pr->Vm.WorkingSetSize; // Is this right using ->Vm. here ?
562 SpiCur->VmCounters.QuotaPeakPagedPoolUsage =
563 pr->QuotaPeakPoolUsage[0];
564 SpiCur->VmCounters.QuotaPagedPoolUsage =
565 pr->QuotaPoolUsage[0];
566 SpiCur->VmCounters.QuotaPeakNonPagedPoolUsage =
567 pr->QuotaPeakPoolUsage[1];
568 SpiCur->VmCounters.QuotaNonPagedPoolUsage =
569 pr->QuotaPoolUsage[1];
570 SpiCur->VmCounters.PagefileUsage = pr->PagefileUsage; // FIXME
571 SpiCur->VmCounters.PeakPagefileUsage = pr->PeakPagefileUsage;
572 // KJK::Hyperion: I don't know what does this mean. VM_COUNTERS
573 // doesn't seem to contain any equivalent field
574 //SpiCur->TotalPrivateBytes = pr->NumberOfPrivatePages; //FIXME: bytes != pages
575
576 pr = PsGetNextProcess(pr);
577
578 if ((pr == syspr) || (pr == NULL))
579 {
580 SpiCur->NextEntryDelta = 0;
581 break;
582 }
583 else
584 pCur = pCur + curSize + inLen;
585 } while ((pr != syspr) && (pr != NULL));
586
587 *ReqSize = ovlSize;
588 if (pr != NULL)
589 {
590 ObDereferenceObject(pr);
591 }
592 return (STATUS_SUCCESS);
593 }
594
595 /* Class 6 - Call Count Information */
596 QSI_DEF(SystemCallCountInformation)
597 {
598 /* FIXME */
599 return (STATUS_NOT_IMPLEMENTED);
600 }
601
602 /* Class 7 - Device Information */
603 QSI_DEF(SystemDeviceInformation)
604 {
605 PSYSTEM_DEVICE_INFORMATION Sdi
606 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
607 PCONFIGURATION_INFORMATION ConfigInfo;
608
609 *ReqSize = sizeof (SYSTEM_DEVICE_INFORMATION);
610 /*
611 * Check user buffer's size
612 */
613 if (Size < sizeof (SYSTEM_DEVICE_INFORMATION))
614 {
615 return (STATUS_INFO_LENGTH_MISMATCH);
616 }
617
618 ConfigInfo = IoGetConfigurationInformation ();
619
620 Sdi->NumberOfDisks = ConfigInfo->DiskCount;
621 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
622 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
623 Sdi->NumberOfTapes = ConfigInfo->TapeCount;
624 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
625 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
626
627 return (STATUS_SUCCESS);
628 }
629
630 /* Class 8 - Processor Performance Information */
631 QSI_DEF(SystemProcessorPerformanceInformation)
632 {
633 PSYSTEM_PROCESSORTIME_INFO Spi
634 = (PSYSTEM_PROCESSORTIME_INFO) Buffer;
635
636 PEPROCESS TheIdleProcess;
637 TIME CurrentTime;
638
639 *ReqSize = sizeof (SYSTEM_PROCESSORTIME_INFO);
640 /*
641 * Check user buffer's size
642 */
643 if (Size < sizeof (SYSTEM_PROCESSORTIME_INFO))
644 {
645 return (STATUS_INFO_LENGTH_MISMATCH);
646 }
647
648 PsLookupProcessByProcessId((PVOID) 1, &TheIdleProcess);
649
650 KeQueryInterruptTime((PLARGE_INTEGER) &CurrentTime);
651
652 Spi->TotalProcessorRunTime.QuadPart =
653 TheIdleProcess->Pcb.KernelTime * 100000; // IdleTime
654 Spi->TotalProcessorTime.QuadPart = KiKernelTime * 100000; // KernelTime
655 Spi->TotalProcessorUserTime.QuadPart = KiUserTime * 100000;
656 Spi->TotalDPCTime.QuadPart = KiDpcTime * 100000;
657 Spi->TotalInterruptTime = CurrentTime;
658 Spi->TotalInterrupts = CurrentTime.QuadPart / 100000; // Interrupt Count
659
660 ObDereferenceObject(TheIdleProcess);
661
662 return (STATUS_SUCCESS);
663 }
664
665 /* Class 9 - Flags Information */
666 QSI_DEF(SystemFlagsInformation)
667 {
668 if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
669 {
670 * ReqSize = sizeof (SYSTEM_FLAGS_INFORMATION);
671 return (STATUS_INFO_LENGTH_MISMATCH);
672 }
673 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
674 return (STATUS_SUCCESS);
675 }
676
677 SSI_DEF(SystemFlagsInformation)
678 {
679 if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
680 {
681 return (STATUS_INFO_LENGTH_MISMATCH);
682 }
683 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
684 return (STATUS_SUCCESS);
685 }
686
687 /* Class 10 - Call Time Information */
688 QSI_DEF(SystemCallTimeInformation)
689 {
690 /* FIXME */
691 return (STATUS_NOT_IMPLEMENTED);
692 }
693
694 /* Class 11 - Module Information */
695 QSI_DEF(SystemModuleInformation)
696 {
697 return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
698 }
699
700 /* Class 12 - Locks Information */
701 QSI_DEF(SystemLocksInformation)
702 {
703 /* FIXME */
704 return (STATUS_NOT_IMPLEMENTED);
705 }
706
707 /* Class 13 - Stack Trace Information */
708 QSI_DEF(SystemStackTraceInformation)
709 {
710 /* FIXME */
711 return (STATUS_NOT_IMPLEMENTED);
712 }
713
714 /* Class 14 - Paged Pool Information */
715 QSI_DEF(SystemPagedPoolInformation)
716 {
717 /* FIXME */
718 return (STATUS_NOT_IMPLEMENTED);
719 }
720
721 /* Class 15 - Non Paged Pool Information */
722 QSI_DEF(SystemNonPagedPoolInformation)
723 {
724 /* FIXME */
725 return (STATUS_NOT_IMPLEMENTED);
726 }
727
728 /* Class 16 - Handle Information */
729 QSI_DEF(SystemHandleInformation)
730 {
731 /* FIXME */
732 return (STATUS_NOT_IMPLEMENTED);
733 }
734
735 /* Class 17 - Information */
736 QSI_DEF(SystemObjectInformation)
737 {
738 /* FIXME */
739 return (STATUS_NOT_IMPLEMENTED);
740 }
741
742 /* Class 18 - Information */
743 QSI_DEF(SystemPageFileInformation)
744 {
745 /* FIXME */
746 return (STATUS_NOT_IMPLEMENTED);
747 }
748
749 /* Class 19 - Vdm Instemul Information */
750 QSI_DEF(SystemVdmInstemulInformation)
751 {
752 /* FIXME */
753 return (STATUS_NOT_IMPLEMENTED);
754 }
755
756 /* Class 20 - Vdm Bop Information */
757 QSI_DEF(SystemVdmBopInformation)
758 {
759 /* FIXME */
760 return (STATUS_NOT_IMPLEMENTED);
761 }
762
763 /* Class 21 - File Cache Information */
764 QSI_DEF(SystemFileCacheInformation)
765 {
766 SYSTEM_CACHE_INFORMATION *Sci = (SYSTEM_CACHE_INFORMATION *) Buffer;
767
768 if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
769 {
770 * ReqSize = sizeof (SYSTEM_CACHE_INFORMATION);
771 return (STATUS_INFO_LENGTH_MISMATCH);
772 }
773
774 Sci->CurrentSize = 0; /* FIXME */
775 Sci->PeakSize = 0; /* FIXME */
776 Sci->PageFaultCount = 0; /* FIXME */
777 Sci->MinimumWorkingSet = 0; /* FIXME */
778 Sci->MaximumWorkingSet = 0; /* FIXME */
779 Sci->TransitionSharedPages = 0; /* FIXME */
780 Sci->TransitionSharedPagesPeak = 0; /* FIXME */
781
782 return (STATUS_SUCCESS);
783 }
784
785 SSI_DEF(SystemFileCacheInformation)
786 {
787 if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
788 {
789 return (STATUS_INFO_LENGTH_MISMATCH);
790 }
791 /* FIXME */
792 return (STATUS_NOT_IMPLEMENTED);
793 }
794
795 /* Class 22 - Pool Tag Information */
796 QSI_DEF(SystemPoolTagInformation)
797 {
798 /* FIXME */
799 return (STATUS_NOT_IMPLEMENTED);
800 }
801
802 /* Class 23 - Interrupt Information */
803 QSI_DEF(SystemInterruptInformation)
804 {
805 /* FIXME */
806 return (STATUS_NOT_IMPLEMENTED);
807 }
808
809 /* Class 24 - DPC Behaviour Information */
810 QSI_DEF(SystemDpcBehaviourInformation)
811 {
812 /* FIXME */
813 return (STATUS_NOT_IMPLEMENTED);
814 }
815
816 SSI_DEF(SystemDpcBehaviourInformation)
817 {
818 /* FIXME */
819 return (STATUS_NOT_IMPLEMENTED);
820 }
821
822 /* Class 25 - Full Memory Information */
823 QSI_DEF(SystemFullMemoryInformation)
824 {
825 PULONG Spi = (PULONG) Buffer;
826
827 PEPROCESS TheIdleProcess;
828
829 * ReqSize = sizeof (ULONG);
830
831 if (sizeof (ULONG) != Size)
832 {
833 return (STATUS_INFO_LENGTH_MISMATCH);
834 }
835 DPRINT1("SystemFullMemoryInformation\n");
836
837 PsLookupProcessByProcessId((PVOID) 1, &TheIdleProcess);
838
839 DbgPrint("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
840 TheIdleProcess->UniqueProcessId,
841 TheIdleProcess->Pcb.KernelTime,
842 MiFreeSwapPages,
843 MiUsedSwapPages);
844
845 MmPrintMemoryStatistic();
846
847 *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
848
849 ObDereferenceObject(TheIdleProcess);
850
851 return (STATUS_SUCCESS);
852 }
853
854 /* Class 26 - Load Image */
855 SSI_DEF(SystemLoadImage)
856 {
857 PSYSTEM_LOAD_IMAGE Sli = (PSYSTEM_LOAD_IMAGE)Buffer;
858
859 if (sizeof(SYSTEM_LOAD_IMAGE) != Size)
860 {
861 return(STATUS_INFO_LENGTH_MISMATCH);
862 }
863
864 return(LdrpLoadImage(&Sli->ModuleName,
865 &Sli->ModuleBase,
866 &Sli->SectionPointer,
867 &Sli->EntryPoint,
868 &Sli->ExportDirectory));
869 }
870
871 /* Class 27 - Unload Image */
872 SSI_DEF(SystemUnloadImage)
873 {
874 PSYSTEM_UNLOAD_IMAGE Sui = (PSYSTEM_UNLOAD_IMAGE)Buffer;
875
876 if (sizeof(SYSTEM_UNLOAD_IMAGE) != Size)
877 {
878 return(STATUS_INFO_LENGTH_MISMATCH);
879 }
880
881 return(LdrpUnloadImage(Sui->ModuleBase));
882 }
883
884 /* Class 28 - Time Adjustment Information */
885 QSI_DEF(SystemTimeAdjustmentInformation)
886 {
887 if (sizeof (SYSTEM_SET_TIME_ADJUSTMENT) > Size)
888 {
889 * ReqSize = sizeof (SYSTEM_SET_TIME_ADJUSTMENT);
890 return (STATUS_INFO_LENGTH_MISMATCH);
891 }
892 /* FIXME: */
893 return (STATUS_NOT_IMPLEMENTED);
894 }
895
896 SSI_DEF(SystemTimeAdjustmentInformation)
897 {
898 if (sizeof (SYSTEM_SET_TIME_ADJUSTMENT) > Size)
899 {
900 return (STATUS_INFO_LENGTH_MISMATCH);
901 }
902 /* FIXME: */
903 return (STATUS_NOT_IMPLEMENTED);
904 }
905
906 /* Class 29 - Summary Memory Information */
907 QSI_DEF(SystemSummaryMemoryInformation)
908 {
909 /* FIXME */
910 return (STATUS_NOT_IMPLEMENTED);
911 }
912
913 /* Class 30 - Next Event Id Information */
914 QSI_DEF(SystemNextEventIdInformation)
915 {
916 /* FIXME */
917 return (STATUS_NOT_IMPLEMENTED);
918 }
919
920 /* Class 31 - Event Ids Information */
921 QSI_DEF(SystemEventIdsInformation)
922 {
923 /* FIXME */
924 return (STATUS_NOT_IMPLEMENTED);
925 }
926
927 /* Class 32 - Crach Dump Information */
928 QSI_DEF(SystemCrashDumpInformation)
929 {
930 /* FIXME */
931 return (STATUS_NOT_IMPLEMENTED);
932 }
933
934 /* Class 33 - Exception Information */
935 QSI_DEF(SystemExceptionInformation)
936 {
937 /* FIXME */
938 return (STATUS_NOT_IMPLEMENTED);
939 }
940
941 /* Class 34 - Crach Dump State Information */
942 QSI_DEF(SystemCrashDumpStateInformation)
943 {
944 /* FIXME */
945 return (STATUS_NOT_IMPLEMENTED);
946 }
947
948 /* Class 35 - Kernel Debugger Information */
949 QSI_DEF(SystemKernelDebuggerInformation)
950 {
951 /* FIXME */
952 return (STATUS_NOT_IMPLEMENTED);
953 }
954
955 /* Class 36 - Context Switch Information */
956 QSI_DEF(SystemContextSwitchInformation)
957 {
958 /* FIXME */
959 return (STATUS_NOT_IMPLEMENTED);
960 }
961
962 /* Class 37 - Registry Quota Information */
963 QSI_DEF(SystemRegistryQuotaInformation)
964 {
965 /* FIXME */
966 return (STATUS_NOT_IMPLEMENTED);
967 }
968
969 SSI_DEF(SystemRegistryQuotaInformation)
970 {
971 /* FIXME */
972 return (STATUS_NOT_IMPLEMENTED);
973 }
974
975 /* Class 38 - Load And Call Image */
976 SSI_DEF(SystemLoadAndCallImage)
977 {
978 PSYSTEM_LOAD_AND_CALL_IMAGE Slci = (PSYSTEM_LOAD_AND_CALL_IMAGE)Buffer;
979
980 if (sizeof(SYSTEM_LOAD_AND_CALL_IMAGE) != Size)
981 {
982 return(STATUS_INFO_LENGTH_MISMATCH);
983 }
984
985 return(LdrpLoadAndCallImage(&Slci->ModuleName));
986 }
987
988 /* Class 39 - Priority Seperation */
989 SSI_DEF(SystemPrioritySeperation)
990 {
991 /* FIXME */
992 return (STATUS_NOT_IMPLEMENTED);
993 }
994
995 /* Class 40 - Plug Play Bus Information */
996 QSI_DEF(SystemPlugPlayBusInformation)
997 {
998 /* FIXME */
999 return (STATUS_NOT_IMPLEMENTED);
1000 }
1001
1002 /* Class 41 - Dock Information */
1003 QSI_DEF(SystemDockInformation)
1004 {
1005 /* FIXME */
1006 return (STATUS_NOT_IMPLEMENTED);
1007 }
1008
1009 /* Class 42 - Power Information */
1010 QSI_DEF(SystemPowerInformation)
1011 {
1012 /* FIXME */
1013 return (STATUS_NOT_IMPLEMENTED);
1014 }
1015
1016 /* Class 43 - Processor Speed Information */
1017 QSI_DEF(SystemProcessorSpeedInformation)
1018 {
1019 /* FIXME */
1020 return (STATUS_NOT_IMPLEMENTED);
1021 }
1022
1023 /* Class 44 - Current Time Zone Information */
1024 QSI_DEF(SystemCurrentTimeZoneInformation)
1025 {
1026 * ReqSize = sizeof (TIME_ZONE_INFORMATION);
1027
1028 if (sizeof (TIME_ZONE_INFORMATION) != Size)
1029 {
1030 return (STATUS_INFO_LENGTH_MISMATCH);
1031 }
1032 /* Copy the time zone information struct */
1033 memcpy (
1034 Buffer,
1035 & _SystemTimeZoneInfo,
1036 sizeof (TIME_ZONE_INFORMATION)
1037 );
1038
1039 return (STATUS_SUCCESS);
1040 }
1041
1042
1043 SSI_DEF(SystemCurrentTimeZoneInformation)
1044 {
1045 /*
1046 * Check user buffer's size
1047 */
1048 if (Size < sizeof (TIME_ZONE_INFORMATION))
1049 {
1050 return (STATUS_INFO_LENGTH_MISMATCH);
1051 }
1052 /* Copy the time zone information struct */
1053 memcpy (
1054 & _SystemTimeZoneInfo,
1055 (TIME_ZONE_INFORMATION *) Buffer,
1056 sizeof (TIME_ZONE_INFORMATION)
1057 );
1058 return (STATUS_SUCCESS);
1059 }
1060
1061
1062 /* Class 45 - Lookaside Information */
1063 QSI_DEF(SystemLookasideInformation)
1064 {
1065 /* FIXME */
1066 return (STATUS_NOT_IMPLEMENTED);
1067 }
1068
1069
1070 /* Class 46 - Set time slip event */
1071 SSI_DEF(SystemSetTimeSlipEvent)
1072 {
1073 /* FIXME */
1074 return (STATUS_NOT_IMPLEMENTED);
1075 }
1076
1077
1078 /* Class 47 - Create a new session (TSE) */
1079 SSI_DEF(SystemCreateSession)
1080 {
1081 /* FIXME */
1082 return (STATUS_NOT_IMPLEMENTED);
1083 }
1084
1085
1086 /* Class 48 - Delete an existing session (TSE) */
1087 SSI_DEF(SystemDeleteSession)
1088 {
1089 /* FIXME */
1090 return (STATUS_NOT_IMPLEMENTED);
1091 }
1092
1093
1094 /* Class 49 - UNKNOWN */
1095 QSI_DEF(SystemInvalidInfoClass4)
1096 {
1097 /* FIXME */
1098 return (STATUS_NOT_IMPLEMENTED);
1099 }
1100
1101
1102 /* Class 50 - System range start address */
1103 QSI_DEF(SystemRangeStartInformation)
1104 {
1105 /* FIXME */
1106 return (STATUS_NOT_IMPLEMENTED);
1107 }
1108
1109
1110 /* Class 51 - Driver verifier information */
1111 QSI_DEF(SystemVerifierInformation)
1112 {
1113 /* FIXME */
1114 return (STATUS_NOT_IMPLEMENTED);
1115 }
1116
1117
1118 SSI_DEF(SystemVerifierInformation)
1119 {
1120 /* FIXME */
1121 return (STATUS_NOT_IMPLEMENTED);
1122 }
1123
1124
1125 /* Class 52 - Add a driver verifier */
1126 SSI_DEF(SystemAddVerifier)
1127 {
1128 /* FIXME */
1129 return (STATUS_NOT_IMPLEMENTED);
1130 }
1131
1132
1133 /* Class 53 - A session's processes */
1134 QSI_DEF(SystemSessionProcessesInformation)
1135 {
1136 /* FIXME */
1137 return (STATUS_NOT_IMPLEMENTED);
1138 }
1139
1140
1141 /* Query/Set Calls Table */
1142 typedef
1143 struct _QSSI_CALLS
1144 {
1145 NTSTATUS (* Query) (PVOID,ULONG,PULONG);
1146 NTSTATUS (* Set) (PVOID,ULONG);
1147
1148 } QSSI_CALLS;
1149
1150 // QS Query & Set
1151 // QX Query
1152 // XQ Set
1153 // XX unknown behaviour
1154 //
1155 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
1156 #define SI_QX(n) {QSI_USE(n),NULL}
1157 #define SI_XS(n) {NULL,SSI_USE(n)}
1158 #define SI_XX(n) {NULL,NULL}
1159
1160 static
1161 QSSI_CALLS
1162 CallQS [] =
1163 {
1164 SI_QX(SystemBasicInformation),
1165 SI_QX(SystemProcessorInformation),
1166 SI_QX(SystemPerformanceInformation),
1167 SI_QX(SystemTimeOfDayInformation),
1168 SI_QX(SystemPathInformation), /* should be SI_XX */
1169 SI_QX(SystemProcessInformation),
1170 SI_QX(SystemCallCountInformation),
1171 SI_QX(SystemDeviceInformation),
1172 SI_QX(SystemProcessorPerformanceInformation),
1173 SI_QS(SystemFlagsInformation),
1174 SI_QX(SystemCallTimeInformation), /* should be SI_XX */
1175 SI_QX(SystemModuleInformation),
1176 SI_QX(SystemLocksInformation),
1177 SI_QX(SystemStackTraceInformation), /* should be SI_XX */
1178 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
1179 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
1180 SI_QX(SystemHandleInformation),
1181 SI_QX(SystemObjectInformation),
1182 SI_QX(SystemPageFileInformation),
1183 SI_QX(SystemVdmInstemulInformation),
1184 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
1185 SI_QS(SystemFileCacheInformation),
1186 SI_QX(SystemPoolTagInformation),
1187 SI_QX(SystemInterruptInformation),
1188 SI_QS(SystemDpcBehaviourInformation),
1189 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
1190 SI_XS(SystemLoadImage),
1191 SI_XS(SystemUnloadImage),
1192 SI_QS(SystemTimeAdjustmentInformation),
1193 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1194 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1195 SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1196 SI_QX(SystemCrashDumpInformation),
1197 SI_QX(SystemExceptionInformation),
1198 SI_QX(SystemCrashDumpStateInformation),
1199 SI_QX(SystemKernelDebuggerInformation),
1200 SI_QX(SystemContextSwitchInformation),
1201 SI_QS(SystemRegistryQuotaInformation),
1202 SI_XS(SystemLoadAndCallImage),
1203 SI_XS(SystemPrioritySeperation),
1204 SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1205 SI_QX(SystemDockInformation), /* it should be SI_XX */
1206 SI_QX(SystemPowerInformation), /* it should be SI_XX */
1207 SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1208 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1209 SI_QX(SystemLookasideInformation),
1210 SI_XS(SystemSetTimeSlipEvent),
1211 SI_XS(SystemCreateSession),
1212 SI_XS(SystemDeleteSession),
1213 SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1214 SI_QX(SystemRangeStartInformation),
1215 SI_QS(SystemVerifierInformation),
1216 SI_XS(SystemAddVerifier),
1217 SI_QX(SystemSessionProcessesInformation)
1218 };
1219
1220
1221 /*
1222 * @implemented
1223 */
1224 NTSTATUS STDCALL
1225 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1226 OUT PVOID UnsafeSystemInformation,
1227 IN ULONG Length,
1228 OUT PULONG UnsafeResultLength)
1229 {
1230 ULONG ResultLength;
1231 PVOID SystemInformation;
1232 NTSTATUS Status;
1233 NTSTATUS FStatus;
1234
1235 /* DPRINT("NtQuerySystemInformation Start. Class:%d\n",
1236 SystemInformationClass );
1237 */
1238 /*if (ExGetPreviousMode() == KernelMode)
1239 {*/
1240 SystemInformation = UnsafeSystemInformation;
1241 /*}
1242 else
1243 {
1244 SystemInformation = ExAllocatePool(NonPagedPool, Length);
1245 if (SystemInformation == NULL)
1246 {
1247 return(STATUS_NO_MEMORY);
1248 }
1249 }*/
1250
1251 /* Clear user buffer. */
1252 RtlZeroMemory(SystemInformation, Length);
1253
1254 /*
1255 * Check the request is valid.
1256 */
1257 if ((SystemInformationClass >= SystemInformationClassMin) &&
1258 (SystemInformationClass < SystemInformationClassMax))
1259 {
1260 if (NULL != CallQS [SystemInformationClass].Query)
1261 {
1262 /*
1263 * Hand the request to a subhandler.
1264 */
1265 FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1266 Length,
1267 &ResultLength);
1268 /*if (ExGetPreviousMode() != KernelMode)
1269 {
1270 Status = MmCopyToCaller(UnsafeSystemInformation,
1271 SystemInformation,
1272 Length);
1273 ExFreePool(SystemInformation);
1274 if (!NT_SUCCESS(Status))
1275 {
1276 return(Status);
1277 }
1278 }*/
1279 if (UnsafeResultLength != NULL)
1280 {
1281 /*if (ExGetPreviousMode() == KernelMode)
1282 {
1283 *UnsafeResultLength = ResultLength;
1284 }
1285 else
1286 {*/
1287 Status = MmCopyToCaller(UnsafeResultLength,
1288 &ResultLength,
1289 sizeof(ULONG));
1290 if (!NT_SUCCESS(Status))
1291 {
1292 return(Status);
1293 }
1294 /*}*/
1295 }
1296 return(FStatus);
1297 }
1298 }
1299 return (STATUS_INVALID_INFO_CLASS);
1300 }
1301
1302
1303 NTSTATUS
1304 STDCALL
1305 NtSetSystemInformation (
1306 IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1307 IN PVOID SystemInformation,
1308 IN ULONG SystemInformationLength
1309 )
1310 {
1311 /*
1312 * If called from user mode, check
1313 * possible unsafe arguments.
1314 */
1315 #if 0
1316 if (KernelMode != KeGetPreviousMode())
1317 {
1318 // Check arguments
1319 //ProbeForWrite(
1320 // SystemInformation,
1321 // Length
1322 // );
1323 //ProbeForWrite(
1324 // ResultLength,
1325 // sizeof (ULONG)
1326 // );
1327 }
1328 #endif
1329 /*
1330 * Check the request is valid.
1331 */
1332 if ( (SystemInformationClass >= SystemInformationClassMin)
1333 && (SystemInformationClass < SystemInformationClassMax)
1334 )
1335 {
1336 if (NULL != CallQS [SystemInformationClass].Set)
1337 {
1338 /*
1339 * Hand the request to a subhandler.
1340 */
1341 return CallQS [SystemInformationClass].Set (
1342 SystemInformation,
1343 SystemInformationLength
1344 );
1345 }
1346 }
1347 return (STATUS_INVALID_INFO_CLASS);
1348 }
1349
1350
1351 NTSTATUS
1352 STDCALL
1353 NtFlushInstructionCache (
1354 IN HANDLE ProcessHandle,
1355 IN PVOID BaseAddress,
1356 IN UINT NumberOfBytesToFlush
1357 )
1358 {
1359 UNIMPLEMENTED;
1360 return(STATUS_NOT_IMPLEMENTED);
1361 }
1362
1363
1364 /* EOF */