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