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