:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / ex / sysinfo.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/ex/sysinfo.c
6  * PURPOSE:         System information functions
7  * PROGRAMMER:      David Welch (welch@mcmail.com)
8  * UPDATE HISTORY:
9  *                  Created 22/05/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ddk/exfuncs.h>
16 #include <ddk/halfuncs.h>
17 #include <ddk/iofuncs.h>
18 #include <internal/ex.h>
19 #include <internal/ldr.h>
20 #include <internal/safe.h>
21
22 #include <internal/debug.h>
23
24 extern ULONG NtGlobalFlag; /* FIXME: it should go in a ddk/?.h */
25
26 /* FUNCTIONS *****************************************************************/
27
28 NTSTATUS STDCALL
29 NtQuerySystemEnvironmentValue (IN       PUNICODE_STRING UnsafeName,
30                                OUT      PVOID           UnsafeValue,
31                                IN       ULONG           Length,
32                                IN OUT   PULONG          UnsafeReturnLength)
33 {
34   NTSTATUS Status;
35   ANSI_STRING AName;
36   UNICODE_STRING WName;
37   BOOLEAN Result;
38   PCH Value;
39   ANSI_STRING AValue;
40   UNICODE_STRING WValue;
41   ULONG ReturnLength;
42
43   /*
44    * Copy the name to kernel space if necessary and convert it to ANSI.
45    */
46   if (ExGetPreviousMode() != KernelMode)
47     {
48       Status = RtlCaptureUnicodeString(&WName, UnsafeName);
49       if (!NT_SUCCESS(Status))
50         {
51           return(Status);
52         }
53       Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
54       if (!NT_SUCCESS(Status))
55         {
56           return(Status);
57         }
58     }
59   else
60     {
61       Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
62       if (!NT_SUCCESS(Status))
63         {
64           return(Status);
65         }
66     }
67
68   /*
69    * Create a temporary buffer for the value
70    */
71   Value = ExAllocatePool(NonPagedPool, Length);
72   if (Value == NULL)
73     {
74       RtlFreeAnsiString(&AName);
75       if (ExGetPreviousMode() != KernelMode)
76         {
77           RtlFreeUnicodeString(&WName);
78         }
79       return(STATUS_NO_MEMORY);
80     }
81
82   /*
83    * Get the environment variable
84    */
85   Result = HalGetEnvironmentVariable(AName.Buffer, Value, Length);
86   if (!Result)
87     {
88       RtlFreeAnsiString(&AName);
89       if (ExGetPreviousMode() != KernelMode)
90         {
91           RtlFreeUnicodeString(&WName);
92         }
93       ExFreePool(Value);
94       return(STATUS_UNSUCCESSFUL);
95     }
96
97   /*
98    * Convert the result to UNICODE.
99    */
100   RtlInitAnsiString(&AValue, Value);
101   Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
102   if (!NT_SUCCESS(Status))
103     {
104       RtlFreeAnsiString(&AName);
105       if (ExGetPreviousMode() != KernelMode)
106         {
107           RtlFreeUnicodeString(&WName);
108         }
109       ExFreePool(Value);
110       return(Status);
111     }
112   ReturnLength = WValue.Length;
113
114   /*
115    * Copy the result back to the caller.
116    */
117   if (ExGetPreviousMode() != KernelMode)
118     {
119       Status = MmCopyToCaller(UnsafeValue, WValue.Buffer, ReturnLength);
120       if (!NT_SUCCESS(Status))
121         {
122           RtlFreeAnsiString(&AName);
123           if (ExGetPreviousMode() != KernelMode)
124             {
125               RtlFreeUnicodeString(&WName);
126             }
127           ExFreePool(Value);
128           RtlFreeUnicodeString(&WValue);
129           return(Status);
130         }
131
132       Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength, 
133                               sizeof(ULONG));
134       if (!NT_SUCCESS(Status))
135         {
136           RtlFreeAnsiString(&AName);
137           if (ExGetPreviousMode() != KernelMode)
138             {
139               RtlFreeUnicodeString(&WName);
140             }
141           ExFreePool(Value);
142           RtlFreeUnicodeString(&WValue);
143           return(Status);
144         }
145     }
146   else
147     {
148       memcpy(UnsafeValue, WValue.Buffer, ReturnLength);
149       memcpy(UnsafeReturnLength, &ReturnLength, sizeof(ULONG));
150     }
151
152   /*
153    * Free temporary buffers.
154    */
155   RtlFreeAnsiString(&AName);
156   if (ExGetPreviousMode() != KernelMode)
157     {
158       RtlFreeUnicodeString(&WName);
159     }
160   ExFreePool(Value);
161   RtlFreeUnicodeString(&WValue);
162
163   return(STATUS_SUCCESS);
164 }
165
166
167 NTSTATUS STDCALL
168 NtSetSystemEnvironmentValue (IN PUNICODE_STRING UnsafeName,
169                              IN PUNICODE_STRING UnsafeValue)
170 {
171   UNICODE_STRING WName;
172   ANSI_STRING AName;
173   UNICODE_STRING WValue;
174   ANSI_STRING AValue;
175   BOOLEAN Result;
176   NTSTATUS Status;
177
178   /*
179    * Check for required privilege.
180    */
181   /* FIXME: Not implemented. */
182
183   /*
184    * Copy the name to kernel space if necessary and convert it to ANSI.
185    */
186   if (ExGetPreviousMode() != KernelMode)
187     {
188       Status = RtlCaptureUnicodeString(&WName, UnsafeName);
189       if (!NT_SUCCESS(Status))
190         {
191           return(Status);
192         }
193       Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
194       if (!NT_SUCCESS(Status))
195         {
196           return(Status);
197         }      
198     }
199   else
200     {
201       Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE);
202       if (!NT_SUCCESS(Status))
203         {
204           return(Status);
205         }
206     }
207
208   /*
209    * Copy the value to kernel space and convert to ANSI.
210    */
211   if (ExGetPreviousMode() != KernelMode)
212     {
213       Status = RtlCaptureUnicodeString(&WValue, UnsafeValue);
214       if (!NT_SUCCESS(Status))
215         {
216           RtlFreeUnicodeString(&WName);
217           RtlFreeAnsiString(&AName);
218           return(Status);
219         }
220       Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE);
221       if (!NT_SUCCESS(Status))
222         {
223           RtlFreeUnicodeString(&WName);
224           RtlFreeAnsiString(&AName);
225           RtlFreeUnicodeString(&WValue);
226           return(Status);
227         }      
228     }
229   else
230     {
231       Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE);
232       if (!NT_SUCCESS(Status))
233         {
234           RtlFreeAnsiString(&AName);
235           return(Status);
236         }
237     }
238
239   /*
240    * Set the environment variable
241    */
242   Result = HalSetEnvironmentVariable(AName.Buffer, AValue.Buffer);
243
244   /*
245    * Free everything and return status.
246    */
247   RtlFreeAnsiString(&AName);
248   RtlFreeAnsiString(&AValue);
249   if (ExGetPreviousMode() != KernelMode)
250     {
251       RtlFreeUnicodeString(&WName);
252       RtlFreeUnicodeString(&WValue);
253     }
254
255   if (!Result)
256     {
257       return(STATUS_UNSUCCESSFUL);
258     }
259   return(STATUS_SUCCESS);
260 }
261
262
263 /* --- Query/Set System Information --- */
264
265
266 /*
267  * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
268  * so the stack is popped only in one place on x86 platform.
269  */
270 #define QSI_USE(n) QSI##n
271 #define QSI_DEF(n) \
272 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
273
274 #define SSI_USE(n) SSI##n
275 #define SSI_DEF(n) \
276 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
277
278 /* Class 0 - Basic Information */
279 QSI_DEF(SystemBasicInformation)
280 {
281         PSYSTEM_BASIC_INFORMATION Sbi 
282                 = (PSYSTEM_BASIC_INFORMATION) Buffer;
283
284         *ReqSize = sizeof (SYSTEM_BASIC_INFORMATION);
285         /*
286          * Check user buffer's size 
287          */
288         if (Size < sizeof (SYSTEM_BASIC_INFORMATION))
289         {
290                 return (STATUS_INFO_LENGTH_MISMATCH);
291         }
292
293         Sbi->Reserved = 0;
294         Sbi->TimerResolution = 0; /* FIXME */
295         Sbi->PageSize = PAGE_SIZE; /* FIXME: it should be PAGE_SIZE */
296         Sbi->NumberOfPhysicalPages = 0; /* FIXME */
297         Sbi->LowestPhysicalPageNumber = 0; /* FIXME */
298         Sbi->HighestPhysicalPageNumber = 0; /* FIXME */
299         Sbi->AllocationGranularity = 65536; /* hard coded on Intel? */
300         Sbi->MinimumUserModeAddress = 0; /* FIXME */
301         Sbi->MaximumUserModeAddress = 0; /* FIXME */
302         Sbi->ActiveProcessorsAffinityMask = 0x00000001; /* FIXME */
303         Sbi->NumberOfProcessors = 1; /* FIXME */
304
305         return (STATUS_SUCCESS);
306 }
307
308 /* Class 1 - Processor Information */
309 QSI_DEF(SystemProcessorInformation)
310 {
311         PSYSTEM_PROCESSOR_INFORMATION Spi 
312                 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
313
314         *ReqSize = sizeof (SYSTEM_PROCESSOR_INFORMATION);
315         /*
316          * Check user buffer's size 
317          */
318         if (Size < sizeof (SYSTEM_PROCESSOR_INFORMATION))
319         {
320                 return (STATUS_INFO_LENGTH_MISMATCH);
321         }
322
323         /* FIXME: add CPU type detection code */
324         Spi->ProcessorArchitecture = 0; /* FIXME */
325         Spi->ProcessorLevel = 0; /* FIXME */
326         Spi->ProcessorRevision = 0; /* FIXME */
327         Spi->Reserved = 0;
328         Spi->ProcessorFeatureBits = 0x00000000; /* FIXME */
329         
330         return (STATUS_SUCCESS);
331 }
332
333 /* Class 2 - Performance Information */
334 QSI_DEF(SystemPerformanceInformation)
335 {
336         PSYSTEM_PERFORMANCE_INFO Spi 
337                 = (PSYSTEM_PERFORMANCE_INFO) Buffer;
338
339         *ReqSize = sizeof (SYSTEM_PERFORMANCE_INFO);
340         /*
341          * Check user buffer's size 
342          */
343         if (Size < sizeof (SYSTEM_PERFORMANCE_INFO))
344         {
345                 return (STATUS_INFO_LENGTH_MISMATCH);
346         }
347         
348         Spi->IdleProcessorTime.QuadPart = 0; /* FIXME */
349         Spi->IoReadTransferCount.QuadPart = 0; /* FIXME */
350         Spi->IoWriteTransferCount.QuadPart = 0; /* FIXME */
351         Spi->IoOtherTransferCount.QuadPart = 0; /* FIXME */
352         Spi->IoReadOperationCount = 0; /* FIXME */
353         Spi->IoWriteOperationCount = 0; /* FIXME */
354         Spi->IoOtherOperationCount = 0; /* FIXME */
355         Spi->AvailablePages = 0; /* FIXME */
356         Spi->CommitedPages = 0; /* FIXME */
357         Spi->CommitLimit = 0; /* FIXME */
358         Spi->PeakCommitment = 0; /* FIXME */
359         Spi->PageFaultCount = 0; /* FIXME */
360         Spi->CopyOnWriteCount = 0; /* FIXME */
361         Spi->TransitionCount = 0; /* FIXME */
362         Spi->CacheTransitionCount = 0; /* FIXME */
363         Spi->DemandZeroCount = 0; /* FIXME */
364         Spi->PageReadCount = 0; /* FIXME */
365         Spi->PageReadIoCount = 0; /* FIXME */
366         Spi->CacheReadCount = 0; /* FIXME */
367         Spi->CacheIoCount = 0; /* FIXME */
368         Spi->DirtyPagesWriteCount = 0; /* FIXME */
369         Spi->DirtyWriteIoCount = 0; /* FIXME */
370         Spi->MappedPagesWriteCount = 0; /* FIXME */
371         Spi->MappedWriteIoCount = 0; /* FIXME */
372         Spi->PagedPoolPages = 0; /* FIXME */
373         Spi->NonPagedPoolPages = 0; /* FIXME */
374         Spi->Unknown6 = 0; /* FIXME */
375         Spi->Unknown7 = 0; /* FIXME */
376         Spi->Unknown8 = 0; /* FIXME */
377         Spi->Unknown9 = 0; /* FIXME */
378         Spi->MmTotalSystemFreePtes = 0; /* FIXME */
379         Spi->MmSystemCodepage = 0; /* FIXME */
380         Spi->MmTotalSystemDriverPages = 0; /* FIXME */
381         Spi->MmTotalSystemCodePages = 0; /* FIXME */
382         Spi->Unknown10 = 0; /* FIXME */
383         Spi->Unknown11 = 0; /* FIXME */
384         Spi->Unknown12 = 0; /* FIXME */
385         Spi->MmSystemCachePage = 0; /* FIXME */
386         Spi->MmPagedPoolPage = 0; /* FIXME */
387         Spi->MmSystemDriverPage = 0; /* FIXME */
388         Spi->CcFastReadNoWait = 0; /* FIXME */
389         Spi->CcFastReadWait = 0; /* FIXME */
390         Spi->CcFastReadResourceMiss = 0; /* FIXME */
391         Spi->CcFastReadNotPossible = 0; /* FIXME */
392         Spi->CcFastMdlReadNoWait = 0; /* FIXME */
393         Spi->CcFastMdlReadWait = 0; /* FIXME */
394         Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
395         Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
396         Spi->CcMapDataNoWait = 0; /* FIXME */
397         Spi->CcMapDataWait = 0; /* FIXME */
398         Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
399         Spi->CcMapDataWaitMiss = 0; /* FIXME */
400         Spi->CcPinMappedDataCount = 0; /* FIXME */
401         Spi->CcPinReadNoWait = 0; /* FIXME */
402         Spi->CcPinReadWait = 0; /* FIXME */
403         Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
404         Spi->CcPinReadWaitMiss = 0; /* FIXME */
405         Spi->CcCopyReadNoWait = 0; /* FIXME */
406         Spi->CcCopyReadWait = 0; /* FIXME */
407         Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
408         Spi->CcCopyReadWaitMiss = 0; /* FIXME */
409         Spi->CcMdlReadNoWait = 0; /* FIXME */
410         Spi->CcMdlReadWait = 0; /* FIXME */
411         Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
412         Spi->CcMdlReadWaitMiss = 0; /* FIXME */
413         Spi->CcReadaheadIos = 0; /* FIXME */
414         Spi->CcLazyWriteIos = 0; /* FIXME */
415         Spi->CcLazyWritePages = 0; /* FIXME */
416         Spi->CcDataFlushes = 0; /* FIXME */
417         Spi->CcDataPages = 0; /* FIXME */
418         Spi->ContextSwitches = 0; /* FIXME */
419         Spi->Unknown13 = 0; /* FIXME */
420         Spi->Unknown14 = 0; /* FIXME */
421         Spi->SystemCalls = 0; /* FIXME */
422         
423         return (STATUS_SUCCESS);
424 }
425
426 /* Class 3 - Time Of Day Information */
427 QSI_DEF(SystemTimeOfDayInformation)
428 {
429         PSYSTEM_TIMEOFDAY_INFORMATION Sti
430                 = (PSYSTEM_TIMEOFDAY_INFORMATION) Buffer;
431
432         *ReqSize = sizeof (SYSTEM_TIMEOFDAY_INFORMATION);
433         /*
434          * Check user buffer's size 
435          */
436         if (Size < sizeof (SYSTEM_TIMEOFDAY_INFORMATION))
437         {
438                 return (STATUS_INFO_LENGTH_MISMATCH);
439         }
440
441         Sti->BootTime.QuadPart = 0;     /* FIXME */
442         Sti->CurrentTime.QuadPart = 0;  /* FIXME */
443         Sti->TimeZoneBias.QuadPart = 0; /* FIXME */
444         Sti->TimeZoneId = 0;            /* FIXME */
445         Sti->Reserved = 0;              /* FIXME */
446
447         return (STATUS_SUCCESS);
448 }
449
450 /* Class 4 - Path Information */
451 QSI_DEF(SystemPathInformation)
452 {
453         /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
454         return (STATUS_BREAKPOINT);
455 }
456
457 /* Class 5 - Process Information */
458 QSI_DEF(SystemProcessInformation)
459 {
460         /* FIXME: scan the process+thread list */
461         return (STATUS_NOT_IMPLEMENTED);
462 }
463
464 /* Class 6 - Call Count Information */
465 QSI_DEF(SystemCallCountInformation)
466 {
467         /* FIXME */
468         return (STATUS_NOT_IMPLEMENTED);
469 }
470
471 /* Class 7 - Device Information */
472 QSI_DEF(SystemDeviceInformation)
473 {
474         PSYSTEM_DEVICE_INFORMATION Sdi 
475                 = (PSYSTEM_DEVICE_INFORMATION) Buffer;
476         PCONFIGURATION_INFORMATION ConfigInfo;
477
478         *ReqSize = sizeof (SYSTEM_DEVICE_INFORMATION);
479         /*
480          * Check user buffer's size 
481          */
482         if (Size < sizeof (SYSTEM_DEVICE_INFORMATION))
483         {
484                 return (STATUS_INFO_LENGTH_MISMATCH);
485         }
486
487         ConfigInfo = IoGetConfigurationInformation ();
488
489         Sdi->NumberOfDisks = ConfigInfo->DiskCount;
490         Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
491         Sdi->NumberOfCdRoms = ConfigInfo->CDRomCount;
492         Sdi->NumberOfTapes = ConfigInfo->TapeCount;
493         Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
494         Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
495
496         return (STATUS_SUCCESS);
497 }
498
499 /* Class 8 - Processor Performance Information */
500 QSI_DEF(SystemProcessorPerformanceInformation)
501 {
502         /* FIXME */
503         return (STATUS_NOT_IMPLEMENTED);
504 }
505
506 /* Class 9 - Flags Information */
507 QSI_DEF(SystemFlagsInformation)
508 {
509         if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
510         {
511                 * ReqSize = sizeof (SYSTEM_FLAGS_INFORMATION);
512                 return (STATUS_INFO_LENGTH_MISMATCH);
513         }
514         ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
515         return (STATUS_SUCCESS);
516 }
517
518 SSI_DEF(SystemFlagsInformation)
519 {
520         if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
521         {
522                 return (STATUS_INFO_LENGTH_MISMATCH);
523         }
524         NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
525         return (STATUS_SUCCESS);
526 }
527
528 /* Class 10 - Call Time Information */
529 QSI_DEF(SystemCallTimeInformation)
530 {
531         /* FIXME */
532         return (STATUS_NOT_IMPLEMENTED);
533 }
534
535 /* Class 11 - Module Information */
536 QSI_DEF(SystemModuleInformation)
537 {
538         return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
539 }
540
541 /* Class 12 - Locks Information */
542 QSI_DEF(SystemLocksInformation)
543 {
544         /* FIXME */
545         return (STATUS_NOT_IMPLEMENTED);
546 }
547
548 /* Class 13 - Stack Trace Information */
549 QSI_DEF(SystemStackTraceInformation)
550 {
551         /* FIXME */
552         return (STATUS_NOT_IMPLEMENTED);
553 }
554
555 /* Class 14 - Paged Pool Information */
556 QSI_DEF(SystemPagedPoolInformation)
557 {
558         /* FIXME */
559         return (STATUS_NOT_IMPLEMENTED);
560 }
561
562 /* Class 15 - Non Paged Pool Information */
563 QSI_DEF(SystemNonPagedPoolInformation)
564 {
565         /* FIXME */
566         return (STATUS_NOT_IMPLEMENTED);
567 }
568
569 /* Class 16 - Handle Information */
570 QSI_DEF(SystemHandleInformation)
571 {
572         /* FIXME */
573         return (STATUS_NOT_IMPLEMENTED);
574 }
575
576 /* Class 17 -  Information */
577 QSI_DEF(SystemObjectInformation)
578 {
579         /* FIXME */
580         return (STATUS_NOT_IMPLEMENTED);
581 }
582
583 /* Class 18 -  Information */
584 QSI_DEF(SystemPageFileInformation)
585 {
586         /* FIXME */
587         return (STATUS_NOT_IMPLEMENTED);
588 }
589
590 /* Class 19 - Vdm Instemul Information */
591 QSI_DEF(SystemVdmInstemulInformation)
592 {
593         /* FIXME */
594         return (STATUS_NOT_IMPLEMENTED);
595 }
596
597 /* Class 20 - Vdm Bop Information */
598 QSI_DEF(SystemVdmBopInformation)
599 {
600         /* FIXME */
601         return (STATUS_NOT_IMPLEMENTED);
602 }
603
604 /* Class 21 - File Cache Information */
605 QSI_DEF(SystemFileCacheInformation)
606 {
607         if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
608         {
609                 * ReqSize = sizeof (SYSTEM_CACHE_INFORMATION);
610                 return (STATUS_INFO_LENGTH_MISMATCH);
611         }
612         /* FIXME */
613         return (STATUS_NOT_IMPLEMENTED);
614 }
615
616 SSI_DEF(SystemFileCacheInformation)
617 {
618         if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
619         {
620                 return (STATUS_INFO_LENGTH_MISMATCH);
621         }
622         /* FIXME */
623         return (STATUS_NOT_IMPLEMENTED);
624 }
625
626 /* Class 22 - Pool Tag Information */
627 QSI_DEF(SystemPoolTagInformation)
628 {
629         /* FIXME */
630         return (STATUS_NOT_IMPLEMENTED);
631 }
632
633 /* Class 23 - Interrupt Information */
634 QSI_DEF(SystemInterruptInformation)
635 {
636         /* FIXME */
637         return (STATUS_NOT_IMPLEMENTED);
638 }
639
640 /* Class 24 - DPC Behaviour Information */
641 QSI_DEF(SystemDpcBehaviourInformation)
642 {
643         /* FIXME */
644         return (STATUS_NOT_IMPLEMENTED);
645 }
646
647 SSI_DEF(SystemDpcBehaviourInformation)
648 {
649         /* FIXME */
650         return (STATUS_NOT_IMPLEMENTED);
651 }
652
653 /* Class 25 - Full Memory Information */
654 QSI_DEF(SystemFullMemoryInformation)
655 {
656         /* FIXME */
657         return (STATUS_NOT_IMPLEMENTED);
658 }
659
660 /* Class 26 - Load Image */
661 SSI_DEF(SystemLoadImage)
662 {
663   PSYSTEM_LOAD_IMAGE Sli = (PSYSTEM_LOAD_IMAGE)Buffer;
664
665   if (sizeof(SYSTEM_LOAD_IMAGE) != Size)
666     {
667       return(STATUS_INFO_LENGTH_MISMATCH);
668     }
669
670   return(LdrpLoadImage(&Sli->ModuleName,
671                        &Sli->ModuleBase,
672                        &Sli->SectionPointer,
673                        &Sli->EntryPoint,
674                        &Sli->ExportDirectory));
675 }
676
677 /* Class 27 - Unload Image */
678 SSI_DEF(SystemUnloadImage)
679 {
680   PSYSTEM_UNLOAD_IMAGE Sui = (PSYSTEM_UNLOAD_IMAGE)Buffer;
681
682   if (sizeof(SYSTEM_UNLOAD_IMAGE) != Size)
683     {
684       return(STATUS_INFO_LENGTH_MISMATCH);
685     }
686
687   return(LdrpUnloadImage(Sui->ModuleBase));
688 }
689
690 /* Class 28 - Time Adjustment Information */
691 QSI_DEF(SystemTimeAdjustmentInformation)
692 {
693         if (sizeof (SYSTEM_TIME_ADJUSTMENT_INFO) > Size)
694         {
695                 * ReqSize = sizeof (SYSTEM_TIME_ADJUSTMENT_INFO);
696                 return (STATUS_INFO_LENGTH_MISMATCH);
697         }
698         /* FIXME: */
699         return (STATUS_NOT_IMPLEMENTED);
700 }
701
702 SSI_DEF(SystemTimeAdjustmentInformation)
703 {
704         if (sizeof (SYSTEM_TIME_ADJUSTMENT_INFO) > Size)
705         {
706                 return (STATUS_INFO_LENGTH_MISMATCH);
707         }
708         /* FIXME: */
709         return (STATUS_NOT_IMPLEMENTED);
710 }
711
712 /* Class 29 - Summary Memory Information */
713 QSI_DEF(SystemSummaryMemoryInformation)
714 {
715         /* FIXME */
716         return (STATUS_NOT_IMPLEMENTED);
717 }
718
719 /* Class 30 - Next Event Id Information */
720 QSI_DEF(SystemNextEventIdInformation)
721 {
722         /* FIXME */
723         return (STATUS_NOT_IMPLEMENTED);
724 }
725
726 /* Class 31 - Event Ids Information */
727 QSI_DEF(SystemEventIdsInformation)
728 {
729         /* FIXME */
730         return (STATUS_NOT_IMPLEMENTED);
731 }
732
733 /* Class 32 - Crach Dump Information */
734 QSI_DEF(SystemCrashDumpInformation)
735 {
736         /* FIXME */
737         return (STATUS_NOT_IMPLEMENTED);
738 }
739
740 /* Class 33 - Exception Information */
741 QSI_DEF(SystemExceptionInformation)
742 {
743         /* FIXME */
744         return (STATUS_NOT_IMPLEMENTED);
745 }
746
747 /* Class 34 - Crach Dump State Information */
748 QSI_DEF(SystemCrashDumpStateInformation)
749 {
750         /* FIXME */
751         return (STATUS_NOT_IMPLEMENTED);
752 }
753
754 /* Class 35 - Kernel Debugger Information */
755 QSI_DEF(SystemKernelDebuggerInformation)
756 {
757         /* FIXME */
758         return (STATUS_NOT_IMPLEMENTED);
759 }
760
761 /* Class 36 - Context Switch Information */
762 QSI_DEF(SystemContextSwitchInformation)
763 {
764         /* FIXME */
765         return (STATUS_NOT_IMPLEMENTED);
766 }
767
768 /* Class 37 - Registry Quota Information */
769 QSI_DEF(SystemRegistryQuotaInformation)
770 {
771         /* FIXME */
772         return (STATUS_NOT_IMPLEMENTED);
773 }
774
775 SSI_DEF(SystemRegistryQuotaInformation)
776 {
777         /* FIXME */
778         return (STATUS_NOT_IMPLEMENTED);
779 }
780
781 /* Class 38 - Load And Call Image */
782 SSI_DEF(SystemLoadAndCallImage)
783 {
784   PSYSTEM_LOAD_AND_CALL_IMAGE Slci = (PSYSTEM_LOAD_AND_CALL_IMAGE)Buffer;
785
786   if (sizeof(SYSTEM_LOAD_AND_CALL_IMAGE) != Size)
787     {
788       return(STATUS_INFO_LENGTH_MISMATCH);
789     }
790
791   return(LdrpLoadAndCallImage(&Slci->ModuleName));
792 }
793
794 /* Class 39 - Priority Seperation */
795 SSI_DEF(SystemPrioritySeperation)
796 {
797         /* FIXME */
798         return (STATUS_NOT_IMPLEMENTED);
799 }
800
801 /* Class 40 - Plug Play Bus Information */
802 QSI_DEF(SystemPlugPlayBusInformation)
803 {
804         /* FIXME */
805         return (STATUS_NOT_IMPLEMENTED);
806 }
807
808 /* Class 41 - Dock Information */
809 QSI_DEF(SystemDockInformation)
810 {
811         /* FIXME */
812         return (STATUS_NOT_IMPLEMENTED);
813 }
814
815 /* Class 42 - Power Information */
816 QSI_DEF(SystemPowerInformation)
817 {
818         /* FIXME */
819         return (STATUS_NOT_IMPLEMENTED);
820 }
821
822 /* Class 43 - Processor Speed Information */
823 QSI_DEF(SystemProcessorSpeedInformation)
824 {
825         /* FIXME */
826         return (STATUS_NOT_IMPLEMENTED);
827 }
828
829 /* Class 44 - Current Time Zone Information */
830 QSI_DEF(SystemCurrentTimeZoneInformation)
831 {
832         * ReqSize = sizeof (TIME_ZONE_INFORMATION);
833
834         if (sizeof (TIME_ZONE_INFORMATION) != Size)
835         {
836                 return (STATUS_INFO_LENGTH_MISMATCH);
837         }
838         /* Copy the time zone information struct */
839         memcpy (
840                 Buffer,
841                 & SystemTimeZoneInfo,
842                 sizeof (TIME_ZONE_INFORMATION)
843                 );
844
845         return (STATUS_SUCCESS);
846 }
847
848
849 SSI_DEF(SystemCurrentTimeZoneInformation)
850 {
851         /*
852          * Check user buffer's size 
853          */
854         if (Size < sizeof (TIME_ZONE_INFORMATION))
855         {
856                 return (STATUS_INFO_LENGTH_MISMATCH);
857         }
858         /* Copy the time zone information struct */
859         memcpy (
860                 & SystemTimeZoneInfo,
861                 (TIME_ZONE_INFORMATION *) Buffer,
862                 sizeof (TIME_ZONE_INFORMATION)
863                 );
864         return (STATUS_SUCCESS);
865 }
866
867
868 /* Class 45 - Lookaside Information */
869 QSI_DEF(SystemLookasideInformation)
870 {
871         /* FIXME */
872         return (STATUS_NOT_IMPLEMENTED);
873 }
874
875
876 /* Class 46 - Set time slip event */
877 SSI_DEF(SystemSetTimeSlipEvent)
878 {
879         /* FIXME */
880         return (STATUS_NOT_IMPLEMENTED);
881 }
882
883
884 /* Class 47 - Create a new session (TSE) */
885 SSI_DEF(SystemCreateSession)
886 {
887         /* FIXME */
888         return (STATUS_NOT_IMPLEMENTED);
889 }
890
891
892 /* Class 48 - Delete an existing session (TSE) */
893 SSI_DEF(SystemDeleteSession)
894 {
895         /* FIXME */
896         return (STATUS_NOT_IMPLEMENTED);
897 }
898
899
900 /* Class 49 - UNKNOWN */
901 QSI_DEF(SystemInvalidInfoClass4)
902 {
903         /* FIXME */
904         return (STATUS_NOT_IMPLEMENTED);
905 }
906
907
908 /* Class 50 - System range start address */
909 QSI_DEF(SystemRangeStartInformation)
910 {
911         /* FIXME */
912         return (STATUS_NOT_IMPLEMENTED);
913 }
914
915
916 /* Class 51 - Driver verifier information */
917 QSI_DEF(SystemVerifierInformation)
918 {
919         /* FIXME */
920         return (STATUS_NOT_IMPLEMENTED);
921 }
922
923
924 SSI_DEF(SystemVerifierInformation)
925 {
926         /* FIXME */
927         return (STATUS_NOT_IMPLEMENTED);
928 }
929
930
931 /* Class 52 - Add a driver verifier */
932 SSI_DEF(SystemAddVerifier)
933 {
934         /* FIXME */
935         return (STATUS_NOT_IMPLEMENTED);
936 }
937
938
939 /* Class 53 - A session's processes  */
940 QSI_DEF(SystemSessionProcessesInformation)
941 {
942         /* FIXME */
943         return (STATUS_NOT_IMPLEMENTED);
944 }
945
946
947 /* Query/Set Calls Table */
948 typedef
949 struct _QSSI_CALLS
950 {
951         NTSTATUS (* Query) (PVOID,ULONG,PULONG);
952         NTSTATUS (* Set) (PVOID,ULONG);
953
954 } QSSI_CALLS;
955
956 // QS   Query & Set
957 // QX   Query
958 // XQ   Set
959 // XX   unknown behaviour
960 //
961 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
962 #define SI_QX(n) {QSI_USE(n),NULL}
963 #define SI_XS(n) {NULL,SSI_USE(n)}
964 #define SI_XX(n) {NULL,NULL}
965
966 static
967 QSSI_CALLS
968 CallQS [] =
969 {
970         SI_QX(SystemBasicInformation),
971         SI_QX(SystemProcessorInformation),
972         SI_QX(SystemPerformanceInformation),
973         SI_QX(SystemTimeOfDayInformation),
974         SI_QX(SystemPathInformation), /* should be SI_XX */
975         SI_QX(SystemProcessInformation),
976         SI_QX(SystemCallCountInformation),
977         SI_QX(SystemDeviceInformation),
978         SI_QX(SystemProcessorPerformanceInformation),
979         SI_QS(SystemFlagsInformation),
980         SI_QX(SystemCallTimeInformation), /* should be SI_XX */
981         SI_QX(SystemModuleInformation),
982         SI_QX(SystemLocksInformation),
983         SI_QX(SystemStackTraceInformation), /* should be SI_XX */
984         SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
985         SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
986         SI_QX(SystemHandleInformation),
987         SI_QX(SystemObjectInformation),
988         SI_QX(SystemPageFileInformation),
989         SI_QX(SystemVdmInstemulInformation),
990         SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
991         SI_QS(SystemFileCacheInformation),
992         SI_QX(SystemPoolTagInformation),
993         SI_QX(SystemInterruptInformation),
994         SI_QS(SystemDpcBehaviourInformation),
995         SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
996         SI_XS(SystemLoadImage),
997         SI_XS(SystemUnloadImage),
998         SI_QS(SystemTimeAdjustmentInformation),
999         SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
1000         SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
1001         SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
1002         SI_QX(SystemCrashDumpInformation),
1003         SI_QX(SystemExceptionInformation),
1004         SI_QX(SystemCrashDumpStateInformation),
1005         SI_QX(SystemKernelDebuggerInformation),
1006         SI_QX(SystemContextSwitchInformation),
1007         SI_QS(SystemRegistryQuotaInformation),
1008         SI_XS(SystemLoadAndCallImage),
1009         SI_XS(SystemPrioritySeperation),
1010         SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
1011         SI_QX(SystemDockInformation), /* it should be SI_XX */
1012         SI_QX(SystemPowerInformation), /* it should be SI_XX */
1013         SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
1014         SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
1015         SI_QX(SystemLookasideInformation),
1016         SI_XS(SystemSetTimeSlipEvent),
1017         SI_XS(SystemCreateSession),
1018         SI_XS(SystemDeleteSession),
1019         SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
1020         SI_QX(SystemRangeStartInformation),
1021         SI_QS(SystemVerifierInformation),
1022         SI_XS(SystemAddVerifier),
1023         SI_QX(SystemSessionProcessesInformation)
1024 };
1025
1026
1027 NTSTATUS STDCALL
1028 NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
1029                           OUT PVOID UnsafeSystemInformation,
1030                           IN ULONG Length,
1031                           OUT PULONG UnsafeResultLength)
1032 {
1033   ULONG ResultLength;
1034   PVOID SystemInformation;
1035   NTSTATUS Status;
1036   NTSTATUS FStatus;
1037
1038   if (ExGetPreviousMode() == KernelMode)
1039     {
1040       SystemInformation = UnsafeSystemInformation;
1041     }
1042   else
1043     {
1044       SystemInformation = ExAllocatePool(NonPagedPool, Length);
1045       if (SystemInformation == NULL)
1046         {
1047           return(STATUS_NO_MEMORY);
1048         }
1049     }
1050   
1051   /* Clear user buffer. */
1052   RtlZeroMemory(SystemInformation, Length);
1053
1054   /*
1055    * Check the request is valid.
1056    */
1057   if ((SystemInformationClass >= SystemInformationClassMin) && 
1058       (SystemInformationClass < SystemInformationClassMax))
1059     {
1060       if (NULL != CallQS [SystemInformationClass].Query)
1061         {
1062           /*
1063            * Hand the request to a subhandler.
1064            */
1065           FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
1066                                                           Length,
1067                                                           &ResultLength);
1068           if (ExGetPreviousMode() != KernelMode)
1069             {
1070               Status = MmCopyToCaller(UnsafeSystemInformation, 
1071                                       SystemInformation,
1072                                       Length);
1073               ExFreePool(SystemInformation);
1074               if (!NT_SUCCESS(Status))
1075                 {
1076                   return(Status);
1077                 }
1078             }
1079           if (UnsafeResultLength != NULL)
1080             {
1081               if (ExGetPreviousMode() == KernelMode)
1082                 {
1083                   *UnsafeResultLength = ResultLength;
1084                 }
1085               else
1086                 {
1087                   Status = MmCopyToCaller(UnsafeResultLength,
1088                                           &ResultLength,
1089                                           sizeof(ULONG));
1090                   if (!NT_SUCCESS(Status))
1091                     {
1092                       return(Status);
1093                     }
1094                 }
1095             }
1096           return(FStatus);
1097         }
1098     }
1099   return (STATUS_INVALID_INFO_CLASS);
1100 }
1101
1102
1103 NTSTATUS
1104 STDCALL
1105 NtSetSystemInformation (
1106         IN      SYSTEM_INFORMATION_CLASS        SystemInformationClass,
1107         IN      PVOID                           SystemInformation,
1108         IN      ULONG                           SystemInformationLength
1109         )
1110 {
1111         /*
1112          * If called from user mode, check 
1113          * possible unsafe arguments.
1114          */
1115 #if 0
1116         if (KernelMode != KeGetPreviousMode())
1117         {
1118                 // Check arguments
1119                 //ProbeForWrite(
1120                 //      SystemInformation,
1121                 //      Length
1122                 //      );
1123                 //ProbeForWrite(
1124                 //      ResultLength,
1125                 //      sizeof (ULONG)
1126                 //      );
1127         }
1128 #endif
1129         /*
1130          * Check the request is valid.
1131          */
1132         if (    (SystemInformationClass >= SystemInformationClassMin)
1133                 && (SystemInformationClass < SystemInformationClassMax)
1134                 )
1135         {
1136                 if (NULL != CallQS [SystemInformationClass].Set)
1137                 {
1138                         /*
1139                          * Hand the request to a subhandler.
1140                          */
1141                         return CallQS [SystemInformationClass].Set (
1142                                         SystemInformation,
1143                                         SystemInformationLength
1144                                         );
1145                 }
1146         }
1147         return (STATUS_INVALID_INFO_CLASS);
1148 }
1149
1150
1151 NTSTATUS
1152 STDCALL
1153 NtFlushInstructionCache (
1154         IN      HANDLE  ProcessHandle,
1155         IN      PVOID   BaseAddress,
1156         IN      UINT    NumberOfBytesToFlush
1157         )
1158 {
1159         UNIMPLEMENTED;
1160 }
1161
1162
1163 /* EOF */