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