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