fix uninitialized variable
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
index 903c245..4546b75 100644 (file)
-/* $Id: sysinfo.c,v 1.7 2000/10/22 16:36:49 ekohl Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/sysinfo.c
  * PURPOSE:         System information functions
- * PROGRAMMER:      David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                  Created 22/05/98
+ * 
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ *                  Aleksey Bragin (aleksey@studiocerebral.com)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/ex.h>
-#include <internal/ldr.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
 #include <internal/debug.h>
 
+extern PEPROCESS PsIdleProcess;
 extern ULONG NtGlobalFlag; /* FIXME: it should go in a ddk/?.h */
+ULONGLONG STDCALL KeQueryInterruptTime(VOID);
+
+VOID MmPrintMemoryStatistic(VOID);
 
 /* FUNCTIONS *****************************************************************/
 
-NTSTATUS
+/*
+ * @unimplemented
+ */
+VOID
 STDCALL
-NtQuerySystemEnvironmentValue (
-       IN      PUNICODE_STRING Name,
-       OUT     PVOID           Value,
-       IN      ULONG           Length,
-       IN OUT  PULONG          ReturnLength
+ExEnumHandleTable (
+       PULONG  HandleTable,
+       PVOID   Callback,
+       PVOID   Param,
+       PHANDLE Handle OPTIONAL
        )
 {
        UNIMPLEMENTED;
 }
 
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+ExGetCurrentProcessorCpuUsage (
+       PULONG  CpuUsage
+       )
+{
+       PKPRCB Prcb;
+       ULONG TotalTime;
+       ULONGLONG ScaledIdle;
+
+       Prcb = KeGetCurrentPrcb();
+
+       ScaledIdle = Prcb->IdleThread->KernelTime * 100;
+       TotalTime = Prcb->KernelTime + Prcb->UserTime;
+       if (TotalTime != 0)
+               *CpuUsage = 100 - (ScaledIdle / TotalTime);
+       else
+               *CpuUsage = 0;
+}
 
-NTSTATUS
+/*
+ * @implemented
+ */
+VOID
 STDCALL
-NtSetSystemEnvironmentValue (
-       IN      PUNICODE_STRING VariableName,
-       IN      PUNICODE_STRING Value
+ExGetCurrentProcessorCounts (
+       PULONG  ThreadKernelTime,
+       PULONG  TotalCpuTime,
+       PULONG  ProcessorNumber
        )
 {
-       UNIMPLEMENTED;
+       PKPRCB Prcb;
+
+       Prcb = KeGetCurrentPrcb();
+
+       *ThreadKernelTime = Prcb->KernelTime + Prcb->UserTime;
+       *TotalCpuTime = Prcb->CurrentThread->KernelTime;
+       *ProcessorNumber = KeGetCurrentKPCR()->ProcessorNumber;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN 
+STDCALL
+ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
+{
+    /* Quick check to see if it exists at all */
+    if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
+
+    /* Return our support for it */
+    return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
 }
 
+NTSTATUS STDCALL
+NtQuerySystemEnvironmentValue (IN      PUNICODE_STRING VariableName,
+                              OUT      PWCHAR          ValueBuffer,
+                              IN       ULONG           ValueBufferLength,
+                              IN OUT   PULONG          ReturnLength  OPTIONAL)
+{
+  ANSI_STRING AName;
+  UNICODE_STRING WName;
+  BOOLEAN Result;
+  PCH Value;
+  ANSI_STRING AValue;
+  UNICODE_STRING WValue;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status = STATUS_SUCCESS;
+  
+  PAGED_CODE();
+  
+  PreviousMode = ExGetPreviousMode();
+  
+  if(PreviousMode != KernelMode)
+  {
+    _SEH_TRY
+    {
+      ProbeForRead(VariableName,
+                   sizeof(UNICODE_STRING),
+                   sizeof(ULONG));
+      ProbeForWrite(ValueBuffer,
+                    ValueBufferLength,
+                    sizeof(WCHAR));
+      if(ReturnLength != NULL)
+      {
+        ProbeForWrite(ReturnLength,
+                      sizeof(ULONG),
+                      sizeof(ULONG));
+      }
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    
+    if(!NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  }
+
+  /*
+   * Copy the name to kernel space if necessary and convert it to ANSI.
+   */
+  Status = RtlCaptureUnicodeString(&WName,
+                                   PreviousMode,
+                                   NonPagedPool,
+                                   FALSE,
+                                   VariableName);
+  if(NT_SUCCESS(Status))
+  {
+    /*
+     * according to ntinternals the SeSystemEnvironmentName privilege is required!
+     */
+    if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
+                               PreviousMode))
+    {
+      RtlReleaseCapturedUnicodeString(&WName,
+                                     PreviousMode,
+                                     FALSE);
+      DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
+      return STATUS_PRIVILEGE_NOT_HELD;
+    }
+    
+    /*
+     * convert the value name to ansi
+     */
+    Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
+    RtlReleaseCapturedUnicodeString(&WName,
+                                   PreviousMode,
+                                   FALSE);
+    if(!NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+    
+  /*
+   * Create a temporary buffer for the value
+   */
+    Value = ExAllocatePool(NonPagedPool, ValueBufferLength);
+    if (Value == NULL)
+    {
+      RtlFreeAnsiString(&AName);
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    
+    /*
+     * Get the environment variable
+     */
+    Result = HalGetEnvironmentVariable(AName.Buffer, Value, ValueBufferLength);
+    if(!Result)
+    {
+      RtlFreeAnsiString(&AName);
+      ExFreePool(Value);
+      return STATUS_UNSUCCESSFUL;
+    }
+    
+    /*
+     * Convert the result to UNICODE, protect with SEH in case the value buffer
+     * isn't NULL-terminated!
+     */
+    _SEH_TRY
+    {
+      RtlInitAnsiString(&AValue, Value);
+      Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
+    if(NT_SUCCESS(Status))
+    {
+      /*
+       * Copy the result back to the caller.
+       */
+      _SEH_TRY
+      {
+        RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
+        ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
+        if(ReturnLength != NULL)
+        {
+          *ReturnLength = WValue.Length + sizeof(WCHAR);
+        }
 
-/* --- Query/Set System Information --- */
+        Status = STATUS_SUCCESS;
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+    }
+    
+    /*
+     * Cleanup allocated resources.
+     */
+    RtlFreeAnsiString(&AName);
+    ExFreePool(Value);
+  }
+
+  return Status;
+}
 
 
+NTSTATUS STDCALL
+NtSetSystemEnvironmentValue (IN        PUNICODE_STRING VariableName,
+                            IN PUNICODE_STRING Value)
+{
+  UNICODE_STRING CapturedName, CapturedValue;
+  ANSI_STRING AName, AValue;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status;
+  
+  PAGED_CODE();
+
+  PreviousMode = ExGetPreviousMode();
+  
+  /*
+   * Copy the strings to kernel space if necessary
+   */
+  Status = RtlCaptureUnicodeString(&CapturedName,
+                                   PreviousMode,
+                                   NonPagedPool,
+                                   FALSE,
+                                   VariableName);
+  if(NT_SUCCESS(Status))
+  {
+    Status = RtlCaptureUnicodeString(&CapturedValue,
+                                     PreviousMode,
+                                     NonPagedPool,
+                                     FALSE,
+                                     Value);
+    if(NT_SUCCESS(Status))
+    {
+      /*
+       * according to ntinternals the SeSystemEnvironmentName privilege is required!
+       */
+      if(SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
+                                PreviousMode))
+      {
+        /*
+         * convert the strings to ANSI
+         */
+        Status = RtlUnicodeStringToAnsiString(&AName,
+                                              &CapturedName,
+                                              TRUE);
+        if(NT_SUCCESS(Status))
+        {
+          Status = RtlUnicodeStringToAnsiString(&AValue,
+                                                &CapturedValue,
+                                                TRUE);
+          if(NT_SUCCESS(Status))
+          {
+            BOOLEAN Result = HalSetEnvironmentVariable(AName.Buffer,
+                                                       AValue.Buffer);
+
+            Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+          }
+        }
+      }
+      else
+      {
+        DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
+        Status = STATUS_PRIVILEGE_NOT_HELD;
+      }
+      
+      RtlReleaseCapturedUnicodeString(&CapturedValue,
+                                     PreviousMode,
+                                     FALSE);
+    }
+
+    RtlReleaseCapturedUnicodeString(&CapturedName,
+                                   PreviousMode,
+                                   FALSE);
+  }
+  
+  return Status;
+}
+
+
+/* --- Query/Set System Information --- */
+
 /*
  * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols
  * so the stack is popped only in one place on x86 platform.
@@ -60,6 +338,7 @@ static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
 #define SSI_DEF(n) \
 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
 
+
 /* Class 0 - Basic Information */
 QSI_DEF(SystemBasicInformation)
 {
@@ -74,19 +353,17 @@ QSI_DEF(SystemBasicInformation)
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
-
-       Sbi->AlwaysZero = 0;
-       Sbi->KeMaximumIncrement = 0; /* FIXME */
-       Sbi->MmPageSize = PAGESIZE; /* FIXME: it should be PAGE_SIZE */
-       Sbi->MmNumberOfPhysicalPages = 0; /* FIXME */
-       Sbi->MmLowestPhysicalPage = 0; /* FIXME */
-       Sbi->MmHighestPhysicalPage = 0; /* FIXME */
-       Sbi->MmLowestUserAddress = 0; /* FIXME */
-       Sbi->MmLowestUserAddress1 = 0; /* FIXME */
-       Sbi->MmHighestUserAddress = 0; /* FIXME */
-       Sbi->KeActiveProcessors = 0x00000001; /* FIXME */
-       Sbi->KeNumberProcessors = 1; /* FIXME */
-
+       Sbi->Unknown = 0;
+       Sbi->MaximumIncrement = KeMaximumIncrement;
+       Sbi->PhysicalPageSize = PAGE_SIZE;
+       Sbi->NumberOfPhysicalPages = MmStats.NrTotalPages;
+       Sbi->LowestPhysicalPage = 0; /* FIXME */ 
+       Sbi->HighestPhysicalPage = MmStats.NrTotalPages; /* FIXME */
+       Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
+       Sbi->LowestUserAddress = 0x10000; /* Top of 64k */
+       Sbi->HighestUserAddress = (ULONG_PTR)MmHighestUserAddress;
+       Sbi->ActiveProcessors = KeActiveProcessors;
+       Sbi->NumberProcessors = KeNumberProcessors;
        return (STATUS_SUCCESS);
 }
 
@@ -95,7 +372,7 @@ QSI_DEF(SystemProcessorInformation)
 {
        PSYSTEM_PROCESSOR_INFORMATION Spi 
                = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
-
+       PKPRCB Prcb;
        *ReqSize = sizeof (SYSTEM_PROCESSOR_INFORMATION);
        /*
         * Check user buffer's size 
@@ -104,287 +381,637 @@ QSI_DEF(SystemProcessorInformation)
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
+       Prcb = KeGetCurrentPrcb();
+       Spi->ProcessorArchitecture = 0; /* Intel Processor */
+       Spi->ProcessorLevel        = Prcb->CpuType;
+       Spi->ProcessorRevision     = Prcb->CpuStep;
+       Spi->Unknown               = 0;
+       Spi->FeatureBits           = Prcb->FeatureBits;
+
+       DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
+               Spi->ProcessorLevel, Spi->ProcessorRevision);
 
-       /* FIXME: add CPU type detection code */
-       Spi->KeProcessorArchitecture = 0; /* FIXME */
-       Spi->KeProcessorLevel = 0; /* FIXME */
-       Spi->KeProcessorRevision = 0; /* FIXME */
-       Spi->AlwaysZero = 0;
-       Spi->KeFeatureBits = 0x00000000; /* FIXME */
-       
        return (STATUS_SUCCESS);
 }
 
 /* Class 2 - Performance Information */
-QSI_DEF(SystemPerformanceInfo)
+QSI_DEF(SystemPerformanceInformation)
 {
-       PSYSTEM_PERFORMANCE_INFO Spi 
-               = (PSYSTEM_PERFORMANCE_INFO) Buffer;
+       PSYSTEM_PERFORMANCE_INFORMATION Spi 
+               = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer;
 
-       *ReqSize = sizeof (SYSTEM_PERFORMANCE_INFO);
+       PEPROCESS TheIdleProcess;
+       
+       *ReqSize = sizeof (SYSTEM_PERFORMANCE_INFORMATION);
        /*
         * Check user buffer's size 
         */
-       if (Size < sizeof (SYSTEM_PERFORMANCE_INFO))
+       if (Size < sizeof (SYSTEM_PERFORMANCE_INFORMATION))
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
        
-       Spi->TotalProcessorTime.QuadPart = 0; /* FIXME */
-       Spi->IoReadTransferCount.QuadPart = 0; /* FIXME */
-       Spi->IoWriteTransferCount.QuadPart = 0; /* FIXME */
-       Spi->IoOtherTransferCount.QuadPart = 0; /* FIXME */
-       Spi->IoReadOperationCount = 0; /* FIXME */
-       Spi->IoWriteOperationCount = 0; /* FIXME */
-       Spi->IoOtherOperationCount = 0; /* FIXME */
-       Spi->MmAvailablePages = 0; /* FIXME */
-       Spi->MmTotalCommitedPages = 0; /* FIXME */
-       Spi->MmTotalCommitLimit = 0; /* FIXME */
-       Spi->MmPeakLimit = 0; /* FIXME */
+       TheIdleProcess = PsIdleProcess;
+       
+       Spi->IdleTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000LL;
+
+       Spi->ReadTransferCount.QuadPart = IoReadTransferCount;
+       Spi->WriteTransferCount.QuadPart = IoWriteTransferCount;
+       Spi->OtherTransferCount.QuadPart = IoOtherTransferCount;
+       Spi->ReadOperationCount = IoReadOperationCount;
+       Spi->WriteOperationCount = IoWriteOperationCount;
+       Spi->OtherOperationCount = IoOtherOperationCount;
+
+       Spi->AvailablePages = MmStats.NrFreePages;
+/*
+        Add up all the used "Commitied" memory + pagefile.
+        Not sure this is right. 8^\
+ */
+       Spi->TotalCommittedPages = MiMemoryConsumers[MC_PPOOL].PagesUsed +
+                                  MiMemoryConsumers[MC_NPPOOL].PagesUsed+
+                                   MiMemoryConsumers[MC_CACHE].PagesUsed+
+                                  MiMemoryConsumers[MC_USER].PagesUsed+
+                                  MiUsedSwapPages;
+/*
+       Add up the full system total + pagefile.
+       All this make Taskmgr happy but not sure it is the right numbers.
+       This too, fixes some of GlobalMemoryStatusEx numbers.
+*/
+        Spi->TotalCommitLimit = MmStats.NrTotalPages + MiFreeSwapPages +
+                                MiUsedSwapPages;
+
+       Spi->PeakCommitment = 0; /* FIXME */
        Spi->PageFaults = 0; /* FIXME */
-       Spi->WriteCopies = 0; /* FIXME */
+       Spi->WriteCopyFaults = 0; /* FIXME */
        Spi->TransitionFaults = 0; /* FIXME */
-       Spi->Unknown1 = 0; /* FIXME */
+       Spi->CacheTransitionFaults = 0; /* FIXME */
        Spi->DemandZeroFaults = 0; /* FIXME */
-       Spi->PagesInput = 0; /* FIXME */
        Spi->PagesRead = 0; /* FIXME */
-       Spi->Unknown2 = 0; /* FIXME */
-       Spi->Unknown3 = 0; /* FIXME */
-       Spi->PagesOutput = 0; /* FIXME */
-       Spi->PageWrites = 0; /* FIXME */
-       Spi->Unknown4 = 0; /* FIXME */
-       Spi->Unknown5 = 0; /* FIXME */
-       Spi->PoolPagedBytes = 0; /* FIXME */
-       Spi->PoolNonPagedBytes = 0; /* FIXME */
-       Spi->Unknown6 = 0; /* FIXME */
-       Spi->Unknown7 = 0; /* FIXME */
-       Spi->Unknown8 = 0; /* FIXME */
-       Spi->Unknown9 = 0; /* FIXME */
-       Spi->MmTotalSystemFreePtes = 0; /* FIXME */
-       Spi->MmSystemCodepage = 0; /* FIXME */
-       Spi->MmTotalSystemDriverPages = 0; /* FIXME */
-       Spi->MmTotalSystemCodePages = 0; /* FIXME */
-       Spi->Unknown10 = 0; /* FIXME */
-       Spi->Unknown11 = 0; /* FIXME */
-       Spi->Unknown12 = 0; /* FIXME */
-       Spi->MmSystemCachePage = 0; /* FIXME */
-       Spi->MmPagedPoolPage = 0; /* FIXME */
-       Spi->MmSystemDriverPage = 0; /* FIXME */
-       Spi->CcFastReadNoWait = 0; /* FIXME */
-       Spi->CcFastReadWait = 0; /* FIXME */
-       Spi->CcFastReadResourceMiss = 0; /* FIXME */
-       Spi->CcFastReadNotPossible = 0; /* FIXME */
-       Spi->CcFastMdlReadNoWait = 0; /* FIXME */
-       Spi->CcFastMdlReadWait = 0; /* FIXME */
-       Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
-       Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
-       Spi->CcMapDataNoWait = 0; /* FIXME */
-       Spi->CcMapDataWait = 0; /* FIXME */
-       Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
-       Spi->CcMapDataWaitMiss = 0; /* FIXME */
-       Spi->CcPinMappedDataCount = 0; /* FIXME */
-       Spi->CcPinReadNoWait = 0; /* FIXME */
-       Spi->CcPinReadWait = 0; /* FIXME */
-       Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
-       Spi->CcPinReadWaitMiss = 0; /* FIXME */
-       Spi->CcCopyReadNoWait = 0; /* FIXME */
-       Spi->CcCopyReadWait = 0; /* FIXME */
-       Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */
-       Spi->CcCopyReadWaitMiss = 0; /* FIXME */
-       Spi->CcMdlReadNoWait = 0; /* FIXME */
-       Spi->CcMdlReadWait = 0; /* FIXME */
-       Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */
-       Spi->CcMdlReadWaitMiss = 0; /* FIXME */
-       Spi->CcReadaheadIos = 0; /* FIXME */
-       Spi->CcLazyWriteIos = 0; /* FIXME */
-       Spi->CcLazyWritePages = 0; /* FIXME */
-       Spi->CcDataFlushes = 0; /* FIXME */
-       Spi->CcDataPages = 0; /* FIXME */
+       Spi->PageReadIos = 0; /* FIXME */
+       Spi->CacheReads = 0; /* FIXME */
+       Spi->CacheIos = 0; /* FIXME */
+       Spi->PagefilePagesWritten = 0; /* FIXME */
+       Spi->PagefilePageWriteIos = 0; /* FIXME */
+       Spi->MappedFilePagesWritten = 0; /* FIXME */
+       Spi->MappedFilePageWriteIos = 0; /* FIXME */
+
+       Spi->PagedPoolUsage = MiMemoryConsumers[MC_PPOOL].PagesUsed;
+       Spi->PagedPoolAllocs = 0; /* FIXME */
+       Spi->PagedPoolFrees = 0; /* FIXME */
+       Spi->NonPagedPoolUsage = MiMemoryConsumers[MC_NPPOOL].PagesUsed;
+       Spi->NonPagedPoolAllocs = 0; /* FIXME */
+       Spi->NonPagedPoolFrees = 0; /* FIXME */
+
+       Spi->TotalFreeSystemPtes = 0; /* FIXME */
+       
+       Spi->SystemCodePage = MmStats.NrSystemPages; /* FIXME */
+       
+       Spi->TotalSystemDriverPages = 0; /* FIXME */
+       Spi->TotalSystemCodePages = 0; /* FIXME */
+       Spi->SmallNonPagedLookasideListAllocateHits = 0; /* FIXME */
+       Spi->SmallPagedLookasideListAllocateHits = 0; /* FIXME */
+       Spi->Reserved3 = 0; /* FIXME */
+
+       Spi->MmSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
+       Spi->PagedPoolPage = MmPagedPoolSize; /* FIXME */
+
+       Spi->SystemDriverPage = 0; /* FIXME */
+       Spi->FastReadNoWait = 0; /* FIXME */
+       Spi->FastReadWait = 0; /* FIXME */
+       Spi->FastReadResourceMiss = 0; /* FIXME */
+       Spi->FastReadNotPossible = 0; /* FIXME */
+
+       Spi->FastMdlReadNoWait = 0; /* FIXME */
+       Spi->FastMdlReadWait = 0; /* FIXME */
+       Spi->FastMdlReadResourceMiss = 0; /* FIXME */
+       Spi->FastMdlReadNotPossible = 0; /* FIXME */
+
+       Spi->MapDataNoWait = 0; /* FIXME */
+       Spi->MapDataWait = 0; /* FIXME */
+       Spi->MapDataNoWaitMiss = 0; /* FIXME */
+       Spi->MapDataWaitMiss = 0; /* FIXME */
+
+       Spi->PinMappedDataCount = 0; /* FIXME */
+       Spi->PinReadNoWait = 0; /* FIXME */
+       Spi->PinReadWait = 0; /* FIXME */
+       Spi->PinReadNoWaitMiss = 0; /* FIXME */
+       Spi->PinReadWaitMiss = 0; /* FIXME */
+       Spi->CopyReadNoWait = 0; /* FIXME */
+       Spi->CopyReadWait = 0; /* FIXME */
+       Spi->CopyReadNoWaitMiss = 0; /* FIXME */
+       Spi->CopyReadWaitMiss = 0; /* FIXME */
+
+       Spi->MdlReadNoWait = 0; /* FIXME */
+       Spi->MdlReadWait = 0; /* FIXME */
+       Spi->MdlReadNoWaitMiss = 0; /* FIXME */
+       Spi->MdlReadWaitMiss = 0; /* FIXME */
+       Spi->ReadAheadIos = 0; /* FIXME */
+       Spi->LazyWriteIos = 0; /* FIXME */
+       Spi->LazyWritePages = 0; /* FIXME */
+       Spi->DataFlushes = 0; /* FIXME */
+       Spi->DataPages = 0; /* FIXME */
        Spi->ContextSwitches = 0; /* FIXME */
-       Spi->Unknown13 = 0; /* FIXME */
-       Spi->Unknown14 = 0; /* FIXME */
+       Spi->FirstLevelTbFills = 0; /* FIXME */
+       Spi->SecondLevelTbFills = 0; /* FIXME */
        Spi->SystemCalls = 0; /* FIXME */
-       
+
        return (STATUS_SUCCESS);
 }
 
-/* Class 3 - Time Information */
-QSI_DEF(SystemTimeInformation)
+/* Class 3 - Time Of Day Information */
+QSI_DEF(SystemTimeOfDayInformation)
 {
-       PSYSTEM_TIME_INFORMATION Sti
-               = (PSYSTEM_TIME_INFORMATION) Buffer;
+  PSYSTEM_TIMEOFDAY_INFORMATION Sti;
+  LARGE_INTEGER CurrentTime;
 
-       *ReqSize = sizeof (SYSTEM_TIME_INFORMATION);
-       /*
-        * Check user buffer's size 
-        */
-       if (Size < sizeof (SYSTEM_TIME_INFORMATION))
-       {
-               return (STATUS_INFO_LENGTH_MISMATCH);
-       }
+  Sti = (PSYSTEM_TIMEOFDAY_INFORMATION)Buffer;
+  *ReqSize = sizeof (SYSTEM_TIMEOFDAY_INFORMATION);
 
-       Sti->KeBootTime.QuadPart = 0;           /* FIXME */
-       Sti->KeSystemTime.QuadPart = 0;         /* FIXME */
-       Sti->ExpTimeZoneBias.QuadPart = 0;      /* FIXME */
-       Sti->ExpTimeZoneId = 0;                 /* FIXME */
-       Sti->Unused = 0;                        /* FIXME */
+  /* Check user buffer's size */
+  if (Size < sizeof (SYSTEM_TIMEOFDAY_INFORMATION))
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
 
-       return (STATUS_SUCCESS);
+  KeQuerySystemTime(&CurrentTime);
+
+  Sti->BootTime= SystemBootTime;
+  Sti->CurrentTime = CurrentTime;
+  Sti->TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart;
+  Sti->TimeZoneId = ExpTimeZoneId;
+  Sti->Reserved = 0;
+
+  return STATUS_SUCCESS;
 }
 
 /* Class 4 - Path Information */
 QSI_DEF(SystemPathInformation)
 {
        /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */
+       DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n");
+
        return (STATUS_BREAKPOINT);
 }
 
 /* Class 5 - Process Information */
 QSI_DEF(SystemProcessInformation)
 {
-       /* FIXME: scan the process+thread list */
-       return (STATUS_NOT_IMPLEMENTED);
+       ULONG ovlSize=0, nThreads;
+       PEPROCESS pr, syspr;
+       unsigned char *pCur;
+
+       /* scan the process list */
+
+       PSYSTEM_PROCESS_INFORMATION Spi
+               = (PSYSTEM_PROCESS_INFORMATION) Buffer;
+
+       *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION);
+
+       if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
+       {
+               return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
+       }
+       
+       syspr = PsGetNextProcess(NULL);
+       pr = syspr;
+       pCur = (unsigned char *)Spi;
+
+       do
+       {
+               PSYSTEM_PROCESS_INFORMATION SpiCur;
+               int curSize, i = 0;
+               ANSI_STRING     imgName;
+               int inLen=32; // image name len in bytes
+               PLIST_ENTRY current_entry;
+               PETHREAD current;
+
+               SpiCur = (PSYSTEM_PROCESS_INFORMATION)pCur;
+
+               nThreads = 0;
+               current_entry = pr->ThreadListHead.Flink;
+               while (current_entry != &pr->ThreadListHead)
+               {
+                       nThreads++;
+                       current_entry = current_entry->Flink;
+               }
+
+               // size of the structure for every process
+               curSize = sizeof(SYSTEM_PROCESS_INFORMATION)-sizeof(SYSTEM_THREAD_INFORMATION)+sizeof(SYSTEM_THREAD_INFORMATION)*nThreads;
+               ovlSize += curSize+inLen;
+
+               if (ovlSize > Size)
+               {
+                       *ReqSize = ovlSize;
+                       ObDereferenceObject(pr);
+
+                       return (STATUS_INFO_LENGTH_MISMATCH); // in case buffer size is too small
+               }
+
+               // fill system information
+               SpiCur->NextEntryOffset = curSize+inLen; // relative offset to the beginnnig of the next structure
+               SpiCur->NumberOfThreads = nThreads;
+               SpiCur->CreateTime = pr->CreateTime;
+               SpiCur->UserTime.QuadPart = pr->Pcb.UserTime * 100000LL; 
+               SpiCur->KernelTime.QuadPart = pr->Pcb.KernelTime * 100000LL;
+               SpiCur->ImageName.Length = strlen(pr->ImageFileName) * sizeof(WCHAR);
+               SpiCur->ImageName.MaximumLength = inLen;
+               SpiCur->ImageName.Buffer = (void*)(pCur+curSize);
+
+               // copy name to the end of the struct
+               if(pr != PsIdleProcess)
+               {
+                 RtlInitAnsiString(&imgName, pr->ImageFileName);
+                 RtlAnsiStringToUnicodeString(&SpiCur->ImageName, &imgName, FALSE);
+               }
+               else
+               {
+                  RtlInitUnicodeString(&SpiCur->ImageName, NULL);
+               }
+
+               SpiCur->BasePriority = pr->Pcb.BasePriority;
+               SpiCur->UniqueProcessId = pr->UniqueProcessId;
+               SpiCur->InheritedFromUniqueProcessId = pr->InheritedFromUniqueProcessId;
+               SpiCur->HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
+               SpiCur->PeakVirtualSize = pr->PeakVirtualSize;
+               SpiCur->VirtualSize = pr->VirtualSize.QuadPart;
+               SpiCur->PageFaultCount = pr->LastFaultCount;
+               SpiCur->PeakWorkingSetSize = pr->Vm.PeakWorkingSetSize; // Is this right using ->Vm. here ?
+               SpiCur->WorkingSetSize = pr->Vm.WorkingSetSize; // Is this right using ->Vm. here ?
+               SpiCur->QuotaPeakPagedPoolUsage =
+                                       pr->QuotaPeakPoolUsage[0];
+               SpiCur->QuotaPagedPoolUsage =
+                                       pr->QuotaPoolUsage[0];
+               SpiCur->QuotaPeakNonPagedPoolUsage =
+                                       pr->QuotaPeakPoolUsage[1];
+               SpiCur->QuotaNonPagedPoolUsage =
+                                       pr->QuotaPoolUsage[1];
+               SpiCur->PagefileUsage = pr->PagefileUsage; // FIXME
+               SpiCur->PeakPagefileUsage = pr->PeakPagefileUsage;
+               // KJK::Hyperion: I don't know what does this mean. VM_COUNTERS
+               // doesn't seem to contain any equivalent field
+               //SpiCur->TotalPrivateBytes = pr->NumberOfPrivatePages; //FIXME: bytes != pages
+
+          current_entry = pr->ThreadListHead.Flink;
+          while (current_entry != &pr->ThreadListHead)
+               {
+                 current = CONTAINING_RECORD(current_entry, ETHREAD,
+                                             ThreadListEntry);
+
+                 SpiCur->TH[i].KernelTime.QuadPart = current->Tcb.KernelTime * 100000LL;
+                 SpiCur->TH[i].UserTime.QuadPart = current->Tcb.UserTime * 100000LL;
+//                 SpiCur->TH[i].CreateTime = current->CreateTime;
+                 SpiCur->TH[i].WaitTime = current->Tcb.WaitTime;
+                 SpiCur->TH[i].StartAddress = (PVOID) current->StartAddress;
+                 SpiCur->TH[i].ClientId = current->Cid;
+                 SpiCur->TH[i].Priority = current->Tcb.Priority;
+                 SpiCur->TH[i].BasePriority = current->Tcb.BasePriority;
+                 SpiCur->TH[i].ContextSwitches = current->Tcb.ContextSwitches;
+                 SpiCur->TH[i].ThreadState = current->Tcb.State;
+                 SpiCur->TH[i].WaitReason = current->Tcb.WaitReason;
+                 i++;
+                 current_entry = current_entry->Flink;
+               }
+               
+               pr = PsGetNextProcess(pr);
+        nThreads = 0;
+               if ((pr == syspr) || (pr == NULL))
+               {
+                       SpiCur->NextEntryOffset = 0;
+                       break;
+               }
+               else
+                       pCur = pCur + curSize + inLen;
+       }  while ((pr != syspr) && (pr != NULL));
+       
+       if(pr != NULL)
+       {
+          ObDereferenceObject(pr);
+       }
+
+       *ReqSize = ovlSize;
+       return (STATUS_SUCCESS);
 }
 
-/* Class 6 - SDT Information */
-QSI_DEF(SystemServiceDescriptorTableInfo)
+/* Class 6 - Call Count Information */
+QSI_DEF(SystemCallCountInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 7 - I/O Configuration Information */
-QSI_DEF(SystemIoConfigInfo)
+/* Class 7 - Device Information */
+QSI_DEF(SystemDeviceInformation)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+       PSYSTEM_DEVICE_INFORMATION Sdi 
+               = (PSYSTEM_DEVICE_INFORMATION) Buffer;
+       PCONFIGURATION_INFORMATION ConfigInfo;
+
+       *ReqSize = sizeof (SYSTEM_DEVICE_INFORMATION);
+       /*
+        * Check user buffer's size 
+        */
+       if (Size < sizeof (SYSTEM_DEVICE_INFORMATION))
+       {
+               return (STATUS_INFO_LENGTH_MISMATCH);
+       }
+
+       ConfigInfo = IoGetConfigurationInformation ();
+
+       Sdi->NumberOfDisks = ConfigInfo->DiskCount;
+       Sdi->NumberOfFloppies = ConfigInfo->FloppyCount;
+       Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount;
+       Sdi->NumberOfTapes = ConfigInfo->TapeCount;
+       Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount;
+       Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount;
+
+       return (STATUS_SUCCESS);
 }
 
-/* Class 8 - Processor Time Information */
-QSI_DEF(SystemProcessorTimeInfo)
+/* Class 8 - Processor Performance Information */
+QSI_DEF(SystemProcessorPerformanceInformation)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+       PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi
+               = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer;
+
+        ULONG i;
+       LARGE_INTEGER CurrentTime;
+       PKPRCB Prcb;
+
+       *ReqSize = KeNumberProcessors * sizeof (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
+       /*
+        * Check user buffer's size
+        */
+       if (Size < KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION))
+       {
+               return (STATUS_INFO_LENGTH_MISMATCH);
+       }
+
+       CurrentTime.QuadPart = KeQueryInterruptTime();
+       Prcb = ((PKPCR)KPCR_BASE)->Prcb;
+       for (i = 0; i < KeNumberProcessors; i++)
+       {
+          Spi->IdleTime.QuadPart = (Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime) * 100000LL; // IdleTime
+           Spi->KernelTime.QuadPart =  Prcb->KernelTime * 100000LL; // KernelTime
+           Spi->UserTime.QuadPart = Prcb->UserTime * 100000LL;
+           Spi->DpcTime.QuadPart = Prcb->DpcTime * 100000LL;
+           Spi->InterruptTime.QuadPart = Prcb->InterruptTime * 100000LL;
+           Spi->InterruptCount = Prcb->InterruptCount; // Interrupt Count
+          Spi++;
+          Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
+       }
+
+       return (STATUS_SUCCESS);
 }
 
-/* Class 9 - Global Flag Information */
-QSI_DEF(SystemNtGlobalFlagInformation)
+/* Class 9 - Flags Information */
+QSI_DEF(SystemFlagsInformation)
 {
-       if (sizeof (SYSTEM_GLOBAL_FLAG_INFO) != Size)
+       if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
        {
-               * ReqSize = sizeof (SYSTEM_GLOBAL_FLAG_INFO);
+               * ReqSize = sizeof (SYSTEM_FLAGS_INFORMATION);
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
-       ((PSYSTEM_GLOBAL_FLAG_INFO) Buffer)->NtGlobalFlag = NtGlobalFlag;
+       ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
        return (STATUS_SUCCESS);
 }
 
-SSI_DEF(SystemNtGlobalFlagInformation)
+SSI_DEF(SystemFlagsInformation)
 {
-       if (sizeof (SYSTEM_GLOBAL_FLAG_INFO) != Size)
+       if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size)
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
-       NtGlobalFlag = ((PSYSTEM_GLOBAL_FLAG_INFO) Buffer)->NtGlobalFlag;
+       NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
        return (STATUS_SUCCESS);
 }
 
-/* Class 10 - ? Information */
-QSI_DEF(SystemInformation10)
+/* Class 10 - Call Time Information */
+QSI_DEF(SystemCallTimeInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 11 - Modules Information */
-QSI_DEF(SystemModuleInfo)
+/* Class 11 - Module Information */
+QSI_DEF(SystemModuleInformation)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+       return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
 }
 
-/* Class 12 - Resource Lock Information */
-QSI_DEF(SystemResourceLockInfo)
+/* Class 12 - Locks Information */
+QSI_DEF(SystemLocksInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 13 - ? Information */
-QSI_DEF(SystemInformation13)
+/* Class 13 - Stack Trace Information */
+QSI_DEF(SystemStackTraceInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 14 - ? Information */
-QSI_DEF(SystemInformation14)
+/* Class 14 - Paged Pool Information */
+QSI_DEF(SystemPagedPoolInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 15 - ? Information */
-QSI_DEF(SystemInformation15)
+/* Class 15 - Non Paged Pool Information */
+QSI_DEF(SystemNonPagedPoolInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
+
+VOID
+ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
+                               PEPROCESS Process,
+                               int Count);
+
 /* Class 16 - Handle Information */
-QSI_DEF(SystemHandleInfo)
+QSI_DEF(SystemHandleInformation)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+        PSYSTEM_HANDLE_INFORMATION Shi = 
+               (PSYSTEM_HANDLE_INFORMATION) Buffer;
+
+        DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
+
+       if (Size < sizeof (SYSTEM_HANDLE_INFORMATION))
+        {
+               * ReqSize = sizeof (SYSTEM_HANDLE_INFORMATION);
+               return (STATUS_INFO_LENGTH_MISMATCH);
+       }
+
+       DPRINT("SystemHandleInformation 1\n");
+
+       PEPROCESS pr, syspr;
+       int curSize, i = 0;
+       ULONG hCount = 0;
+               
+        /* First Calc Size from Count. */
+        syspr = PsGetNextProcess(NULL);
+       pr = syspr;
+
+        do
+         {
+            hCount = hCount + (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
+            pr = PsGetNextProcess(pr);
+
+           if ((pr == syspr) || (pr == NULL))
+               break;
+        } while ((pr != syspr) && (pr != NULL));
+        
+       if(pr != NULL)
+       {
+          ObDereferenceObject(pr);
+       }
+
+       DPRINT("SystemHandleInformation 2\n");
+
+        curSize = sizeof(SYSTEM_HANDLE_INFORMATION)+
+                  (  (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) - 
+                     (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) ));
+
+        Shi->NumberOfHandles = hCount;
+
+        if (curSize > Size)
+          {
+            *ReqSize = curSize;
+             return (STATUS_INFO_LENGTH_MISMATCH);
+          }
+
+       DPRINT("SystemHandleInformation 3\n");
+
+        /* Now get Handles from all processs. */
+        syspr = PsGetNextProcess(NULL);
+       pr = syspr;
+
+        do
+         {
+            int Count = 0, HandleCount;
+
+            HandleCount = (pr->ObjectTable ? ObpGetHandleCountByHandleTable(pr->ObjectTable) : 0);
+
+            for (Count = 0; HandleCount > 0 ; HandleCount--)
+               {
+                 ObpGetNextHandleByProcessCount( &Shi->Handles[i], pr, Count);
+                 Count++;
+                 i++;
+               }
+
+           pr = PsGetNextProcess(pr);
+
+           if ((pr == syspr) || (pr == NULL))
+               break;
+          } while ((pr != syspr) && (pr != NULL));
+
+       if(pr != NULL)
+       {
+          ObDereferenceObject(pr);
+       }
+
+       DPRINT("SystemHandleInformation 4\n");
+       return (STATUS_SUCCESS);
+
 }
+/*
+SSI_DEF(SystemHandleInformation)
+{
+       
+       return (STATUS_SUCCESS);
+}
+*/
 
 /* Class 17 -  Information */
 QSI_DEF(SystemObjectInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
 /* Class 18 -  Information */
 QSI_DEF(SystemPageFileInformation)
 {
+       SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer;
+
+       if (Size < sizeof (SYSTEM_PAGEFILE_INFORMATION))
+       {
+               * ReqSize = sizeof (SYSTEM_PAGEFILE_INFORMATION);
+               return (STATUS_INFO_LENGTH_MISMATCH);
+       }
+
+       UNICODE_STRING FileName; /* FIXME */
+
        /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+       Spfi->NextEntryOffset = 0;
+
+       Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages;
+       Spfi->TotalInUse = MiUsedSwapPages;
+       Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */
+       Spfi->PageFileName = FileName;
+       return (STATUS_SUCCESS);
 }
 
-/* Class 19 -  Information */
-QSI_DEF(SystemInstructionEmulationInfo)
+/* Class 19 - Vdm Instemul Information */
+QSI_DEF(SystemVdmInstemulInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 20 - ? Information */
-QSI_DEF(SystemInformation20)
+/* Class 20 - Vdm Bop Information */
+QSI_DEF(SystemVdmBopInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 21 -  Information */
-QSI_DEF(SystemCacheInformation)
+/* Class 21 - File Cache Information */
+QSI_DEF(SystemFileCacheInformation)
 {
+       SYSTEM_CACHE_INFORMATION *Sci = (SYSTEM_CACHE_INFORMATION *) Buffer;
+
        if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
        {
                * ReqSize = sizeof (SYSTEM_CACHE_INFORMATION);
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+       /* Return the Byte size not the page size. */
+       Sci->CurrentSize = 
+               MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE;
+       Sci->PeakSize = 
+               MiMemoryConsumers[MC_CACHE].PagesUsed * PAGE_SIZE; /* FIXME */
+
+       Sci->PageFaultCount = 0; /* FIXME */
+       Sci->MinimumWorkingSet = 0; /* FIXME */
+       Sci->MaximumWorkingSet = 0; /* FIXME */
+       Sci->TransitionSharedPages = 0; /* FIXME */
+       Sci->TransitionSharedPagesPeak = 0; /* FIXME */
+
+       return (STATUS_SUCCESS);
 }
 
-SSI_DEF(SystemCacheInformation)
+SSI_DEF(SystemFileCacheInformation)
 {
        if (Size < sizeof (SYSTEM_CACHE_INFORMATION))
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
        /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
@@ -392,237 +1019,401 @@ SSI_DEF(SystemCacheInformation)
 QSI_DEF(SystemPoolTagInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 23 - Processor Schedule Information */
-QSI_DEF(SystemProcessorScheduleInfo)
+/* Class 23 - Interrupt Information for all processors */
+QSI_DEF(SystemInterruptInformation)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+  PKPRCB Prcb;
+  UINT i;
+  ULONG ti;
+  PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer;
+  
+  if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION))
+  {
+    return (STATUS_INFO_LENGTH_MISMATCH);
+  }
+  
+  ti = KeQueryTimeIncrement();
+  
+  Prcb = ((PKPCR)KPCR_BASE)->Prcb;
+  for (i = 0; i < KeNumberProcessors; i++)
+  {
+    sii->ContextSwitches = Prcb->KeContextSwitches;
+    sii->DpcCount = 0; /* FIXME */
+    sii->DpcRate = 0; /* FIXME */
+    sii->TimeIncrement = ti;
+    sii->DpcBypassCount = 0; /* FIXME */
+    sii->ApcBypassCount = 0; /* FIXME */
+    sii++;
+    Prcb = (PKPRCB)((ULONG_PTR)Prcb + PAGE_SIZE);
+  }
+  
+  return STATUS_SUCCESS;
 }
 
-/* Class 24 - DPC Information */
-QSI_DEF(SystemDpcInformation)
+/* Class 24 - DPC Behaviour Information */
+QSI_DEF(SystemDpcBehaviourInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemDpcBehaviourInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-SSI_DEF(SystemDpcInformation)
+SSI_DEF(SystemDpcBehaviourInformation)
 {
        /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 25 - ? Information */
-QSI_DEF(SystemInformation25)
+/* Class 25 - Full Memory Information */
+QSI_DEF(SystemFullMemoryInformation)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
-}
+       PULONG Spi = (PULONG) Buffer;
 
-/* Class 26 - Load Gdi Driver Information */
-SSI_DEF(SystemLoadGdiDriverInformation)
-{
-       PSYSTEM_GDI_DRIVER_INFORMATION Sdi
-               = (PSYSTEM_GDI_DRIVER_INFORMATION) Buffer;
+       PEPROCESS TheIdleProcess;
+
+       * ReqSize = sizeof (ULONG);
 
-       if (sizeof (SYSTEM_GDI_DRIVER_INFORMATION) != Size)
+       if (sizeof (ULONG) != Size)
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
+       DPRINT("SystemFullMemoryInformation\n");
+
+       TheIdleProcess = PsIdleProcess;
 
-       return LdrLoadGdiDriver (&Sdi->DriverName,
-                                &Sdi->ImageAddress,
-                                &Sdi->SectionPointer,
-                                &Sdi->EntryPoint,
-                                &Sdi->ExportSectionPointer);
+        DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
+               TheIdleProcess->UniqueProcessId,
+               TheIdleProcess->Pcb.KernelTime,
+               MiFreeSwapPages,
+               MiUsedSwapPages);
+
+#ifndef NDEBUG
+       MmPrintMemoryStatistic();
+#endif
+       
+       *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
+
+       return (STATUS_SUCCESS);
 }
 
-/* Class 27 - Unload Gdi Driver Information */
-SSI_DEF(SystemUnloadGdiDriverInformation)
+/* Class 26 - Load Image */
+SSI_DEF(SystemLoadImage)
 {
-       /* FIXME */
-       return (STATUS_NOT_IMPLEMENTED);
+  PSYSTEM_LOAD_IMAGE Sli = (PSYSTEM_LOAD_IMAGE)Buffer;
+
+  if (sizeof(SYSTEM_LOAD_IMAGE) != Size)
+    {
+      return(STATUS_INFO_LENGTH_MISMATCH);
+    }
+
+  return(LdrpLoadImage(&Sli->ModuleName,
+                      &Sli->ModuleBase,
+                      &Sli->SectionPointer,
+                      &Sli->EntryPoint,
+                      &Sli->ExportDirectory));
+}
+
+/* Class 27 - Unload Image */
+SSI_DEF(SystemUnloadImage)
+{
+  PSYSTEM_UNLOAD_IMAGE Sui = (PSYSTEM_UNLOAD_IMAGE)Buffer;
+
+  if (sizeof(SYSTEM_UNLOAD_IMAGE) != Size)
+    {
+      return(STATUS_INFO_LENGTH_MISMATCH);
+    }
+
+  return(LdrpUnloadImage(Sui->ModuleBase));
 }
 
-/* Class 28 -  Information */
+/* Class 28 - Time Adjustment Information */
 QSI_DEF(SystemTimeAdjustmentInformation)
 {
-       if (sizeof (SYSTEM_TIME_ADJUSTMENT_INFO) > Size)
+       if (sizeof (SYSTEM_SET_TIME_ADJUSTMENT) > Size)
        {
-               * ReqSize = sizeof (SYSTEM_TIME_ADJUSTMENT_INFO);
+               * ReqSize = sizeof (SYSTEM_SET_TIME_ADJUSTMENT);
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
        /* FIXME: */
+       DPRINT1("NtQuerySystemInformation - SystemTimeAdjustmentInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
 SSI_DEF(SystemTimeAdjustmentInformation)
 {
-       if (sizeof (SYSTEM_TIME_ADJUSTMENT_INFO) > Size)
+       if (sizeof (SYSTEM_SET_TIME_ADJUSTMENT) > Size)
        {
                return (STATUS_INFO_LENGTH_MISMATCH);
        }
        /* FIXME: */
+       DPRINT1("NtSetSystemInformation - SystemTimeAdjustmentInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 29 - ? Information */
-QSI_DEF(SystemInformation29)
+/* Class 29 - Summary Memory Information */
+QSI_DEF(SystemSummaryMemoryInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 30 - ? Information */
-QSI_DEF(SystemInformation30)
+/* Class 30 - Next Event Id Information */
+QSI_DEF(SystemNextEventIdInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 31 - ? Information */
-QSI_DEF(SystemInformation31)
+/* Class 31 - Event Ids Information */
+QSI_DEF(SystemEventIdsInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 32 - Crach Dump Information */
-QSI_DEF(SystemCrashDumpSectionInfo)
+/* Class 32 - Crash Dump Information */
+QSI_DEF(SystemCrashDumpInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 33 - Processor Fault Information */
-QSI_DEF(SystemProcessorFaultCountInfo)
+/* Class 33 - Exception Information */
+QSI_DEF(SystemExceptionInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemExceptionInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 34 - Crach Dump State Information */
-QSI_DEF(SystemCrashDumpStateInfo)
+/* Class 34 - Crash Dump State Information */
+QSI_DEF(SystemCrashDumpStateInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 35 - Debugger Information */
-QSI_DEF(SystemDebuggerInfo)
+/* Class 35 - Kernel Debugger Information */
+QSI_DEF(SystemKernelDebuggerInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemKernelDebuggerInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 36 - Thread Switch Counters Information */
-QSI_DEF(SystemThreadSwitchCountersInfo)
+/* Class 36 - Context Switch Information */
+QSI_DEF(SystemContextSwitchInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemContextSwitchInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 37 - Quota Information */
-QSI_DEF(SystemQuotaInformation)
+/* Class 37 - Registry Quota Information */
+QSI_DEF(SystemRegistryQuotaInformation)
+{
+  PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer;
+
+  *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION);
+  if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+  DPRINT1("Faking max registry size of 32 MB\n");
+  srqi->RegistryQuotaAllowed = 0x2000000;
+  srqi->RegistryQuotaUsed = 0x200000;
+  srqi->Reserved1 = (void*)0x200000;
+
+  return STATUS_SUCCESS;
+}
+
+SSI_DEF(SystemRegistryQuotaInformation)
 {
        /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-SSI_DEF(SystemQuotaInformation)
+/* Class 38 - Load And Call Image */
+SSI_DEF(SystemLoadAndCallImage)
+{
+  PSYSTEM_LOAD_AND_CALL_IMAGE Slci = (PSYSTEM_LOAD_AND_CALL_IMAGE)Buffer;
+
+  if (sizeof(SYSTEM_LOAD_AND_CALL_IMAGE) != Size)
+    {
+      return(STATUS_INFO_LENGTH_MISMATCH);
+    }
+
+  return(LdrpLoadAndCallImage(&Slci->ModuleName));
+}
+
+/* Class 39 - Priority Separation */
+SSI_DEF(SystemPrioritySeperation)
 {
        /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 38 - Load Driver Information */
-SSI_DEF(SystemLoadDriverInfo)
+/* Class 40 - Plug Play Bus Information */
+QSI_DEF(SystemPlugPlayBusInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 39 - Priority Separation Information */
-SSI_DEF(SystemPrioritySeparationInfo)
+/* Class 41 - Dock Information */
+QSI_DEF(SystemDockInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 40 - ? Information */
-QSI_DEF(SystemInformation40)
+/* Class 42 - Power Information */
+QSI_DEF(SystemPowerInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 41 - ? Information */
-QSI_DEF(SystemInformation41)
+/* Class 43 - Processor Speed Information */
+QSI_DEF(SystemProcessorSpeedInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 42 - ? Information */
-QSI_DEF(SystemInformation42)
+/* Class 44 - Current Time Zone Information */
+QSI_DEF(SystemCurrentTimeZoneInformation)
+{
+  * ReqSize = sizeof (TIME_ZONE_INFORMATION);
+
+  if (sizeof (TIME_ZONE_INFORMATION) != Size)
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+  /* Copy the time zone information struct */
+  memcpy(Buffer,
+         &ExpTimeZoneInfo,
+         sizeof(TIME_ZONE_INFORMATION));
+
+  return STATUS_SUCCESS;
+}
+
+
+SSI_DEF(SystemCurrentTimeZoneInformation)
+{
+  /* Check user buffer's size */
+  if (Size < sizeof (TIME_ZONE_INFORMATION))
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+  return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
+}
+
+
+/* Class 45 - Lookaside Information */
+QSI_DEF(SystemLookasideInformation)
 {
        /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 43 - ? Information */
-QSI_DEF(SystemInformation43)
+
+/* Class 46 - Set time slip event */
+SSI_DEF(SystemSetTimeSlipEvent)
 {
        /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
-/* Class 44 -  Information */
-QSI_DEF(SystemTimeZoneInformation)
+
+/* Class 47 - Create a new session (TSE) */
+SSI_DEF(SystemCreateSession)
 {
-       * ReqSize = sizeof (TIME_ZONE_INFORMATION);
+       /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
+}
 
-       if (sizeof (TIME_ZONE_INFORMATION) != Size)
-       {
-               return (STATUS_INFO_LENGTH_MISMATCH);
-       }
-       /* Copy the time zone information struct */
-        memcpy (
-               Buffer,
-                & SystemTimeZoneInfo,
-                sizeof (TIME_ZONE_INFORMATION)
-               );
 
-       return (STATUS_SUCCESS);
+/* Class 48 - Delete an existing session (TSE) */
+SSI_DEF(SystemDeleteSession)
+{
+       /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
 }
 
 
-SSI_DEF(SystemTimeZoneInformation)
+/* Class 49 - UNKNOWN */
+QSI_DEF(SystemInvalidInfoClass4)
 {
-       /*
-        * Check user buffer's size 
-        */
-       if (Size < sizeof (TIME_ZONE_INFORMATION))
-       {
-               return (STATUS_INFO_LENGTH_MISMATCH);
-       }
-       /* Copy the time zone information struct */
-       memcpy (
-               & SystemTimeZoneInfo,
-               (TIME_ZONE_INFORMATION *) Buffer,
-               sizeof (TIME_ZONE_INFORMATION)
-               );
-       return (STATUS_SUCCESS);
+       /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
 }
 
 
-/* Class 45 -  Information */
-QSI_DEF(SystemLookasideInformation)
+/* Class 50 - System range start address */
+QSI_DEF(SystemRangeStartInformation)
+{
+       /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
+}
+
+
+/* Class 51 - Driver verifier information */
+QSI_DEF(SystemVerifierInformation)
+{
+       /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
+}
+
+
+SSI_DEF(SystemVerifierInformation)
+{
+       /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
+}
+
+
+/* Class 52 - Add a driver verifier */
+SSI_DEF(SystemAddVerifier)
 {
        /* FIXME */
+       DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
+       return (STATUS_NOT_IMPLEMENTED);
+}
+
+
+/* Class 53 - A session's processes  */
+QSI_DEF(SystemSessionProcessesInformation)
+{
+       /* FIXME */
+       DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n");
        return (STATUS_NOT_IMPLEMENTED);
 }
 
@@ -638,7 +1429,7 @@ struct _QSSI_CALLS
 
 // QS  Query & Set
 // QX  Query
-// XQ  Set
+// XS  Set
 // XX  unknown behaviour
 //
 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)}
@@ -652,104 +1443,142 @@ CallQS [] =
 {
        SI_QX(SystemBasicInformation),
        SI_QX(SystemProcessorInformation),
-       SI_QX(SystemPerformanceInfo),
-       SI_QX(SystemTimeInformation),
+       SI_QX(SystemPerformanceInformation),
+       SI_QX(SystemTimeOfDayInformation),
        SI_QX(SystemPathInformation), /* should be SI_XX */
        SI_QX(SystemProcessInformation),
-       SI_QX(SystemServiceDescriptorTableInfo),
-       SI_QX(SystemIoConfigInfo),
-       SI_QX(SystemProcessorTimeInfo),
-       SI_QS(SystemNtGlobalFlagInformation),
-       SI_QX(SystemInformation10), /* should be SI_XX */
-       SI_QX(SystemModuleInfo),
-       SI_QX(SystemResourceLockInfo),
-       SI_QX(SystemInformation13), /* should be SI_XX */
-       SI_QX(SystemInformation14), /* should be SI_XX */
-       SI_QX(SystemInformation15), /* should be SI_XX */
-       SI_QX(SystemHandleInfo),
+       SI_QX(SystemCallCountInformation),
+       SI_QX(SystemDeviceInformation),
+       SI_QX(SystemProcessorPerformanceInformation),
+       SI_QS(SystemFlagsInformation),
+       SI_QX(SystemCallTimeInformation), /* should be SI_XX */
+       SI_QX(SystemModuleInformation),
+       SI_QX(SystemLocksInformation),
+       SI_QX(SystemStackTraceInformation), /* should be SI_XX */
+       SI_QX(SystemPagedPoolInformation), /* should be SI_XX */
+       SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */
+       SI_QX(SystemHandleInformation),
        SI_QX(SystemObjectInformation),
        SI_QX(SystemPageFileInformation),
-       SI_QX(SystemInstructionEmulationInfo),
-       SI_QX(SystemInformation20), /* it should be SI_XX */
-       SI_QS(SystemCacheInformation),
+       SI_QX(SystemVdmInstemulInformation),
+       SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
+       SI_QS(SystemFileCacheInformation),
        SI_QX(SystemPoolTagInformation),
-       SI_QX(SystemProcessorScheduleInfo),
-       SI_QS(SystemDpcInformation),
-       SI_QX(SystemInformation25), /* it should be SI_XX */
-       SI_XS(SystemLoadGdiDriverInformation),
-       SI_XS(SystemUnloadGdiDriverInformation),
+       SI_QX(SystemInterruptInformation),
+       SI_QS(SystemDpcBehaviourInformation),
+       SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
+       SI_XS(SystemLoadImage),
+       SI_XS(SystemUnloadImage),
        SI_QS(SystemTimeAdjustmentInformation),
-       SI_QX(SystemInformation29), /* it should be SI_XX */
-       SI_QX(SystemInformation30), /* it should be SI_XX */
-       SI_QX(SystemInformation31), /* it should be SI_XX */
-       SI_QX(SystemCrashDumpSectionInfo),
-       SI_QX(SystemProcessorFaultCountInfo),
-       SI_QX(SystemCrashDumpStateInfo),
-       SI_QX(SystemDebuggerInfo),
-       SI_QX(SystemThreadSwitchCountersInfo),
-       SI_QS(SystemQuotaInformation),
-       SI_XS(SystemLoadDriverInfo),
-       SI_XS(SystemPrioritySeparationInfo),
-       SI_QX(SystemInformation40), /* it should be SI_XX */
-       SI_QX(SystemInformation41), /* it should be SI_XX */
-       SI_QX(SystemInformation42), /* it should be SI_XX */
-       SI_QX(SystemInformation43), /* it should be SI_XX */
-       SI_QS(SystemTimeZoneInformation), /* it should be SI_QX */
-       SI_QX(SystemLookasideInformation)
+       SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */
+       SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */
+       SI_QX(SystemEventIdsInformation), /* it should be SI_XX */
+       SI_QX(SystemCrashDumpInformation),
+       SI_QX(SystemExceptionInformation),
+       SI_QX(SystemCrashDumpStateInformation),
+       SI_QX(SystemKernelDebuggerInformation),
+       SI_QX(SystemContextSwitchInformation),
+       SI_QS(SystemRegistryQuotaInformation),
+       SI_XS(SystemLoadAndCallImage),
+       SI_XS(SystemPrioritySeperation),
+       SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */
+       SI_QX(SystemDockInformation), /* it should be SI_XX */
+       SI_QX(SystemPowerInformation), /* it should be SI_XX */
+       SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
+       SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */
+       SI_QX(SystemLookasideInformation),
+       SI_XS(SystemSetTimeSlipEvent),
+       SI_XS(SystemCreateSession),
+       SI_XS(SystemDeleteSession),
+       SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */
+       SI_QX(SystemRangeStartInformation),
+       SI_QS(SystemVerifierInformation),
+       SI_XS(SystemAddVerifier),
+       SI_QX(SystemSessionProcessesInformation)
 };
 
 
-NTSTATUS
-STDCALL
-NtQuerySystemInformation (
-       IN      SYSTEM_INFORMATION_CLASS        SystemInformationClass,
-       OUT     PVOID                           SystemInformation,
-       IN      ULONG                           Length,
-       OUT     PULONG                          ResultLength
-       )
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+                         OUT PVOID UnsafeSystemInformation,
+                         IN ULONG Length,
+                         OUT PULONG UnsafeResultLength)
 {
-       /*
-        * If called from user mode, check 
-        * possible unsafe arguments.
-        */
-#if 0
-        if (KernelMode != KeGetPreviousMode())
-        {
-               // Check arguments
-               //ProbeForWrite(
-               //      SystemInformation,
-               //      Length
-               //      );
-               //ProbeForWrite(
-               //      ResultLength,
-               //      sizeof (ULONG)
-               //      );
-        }
-#endif
-       /*
-        * Clear the user buffer.
-        */
-       RtlZeroMemory (SystemInformation, Length);
-       /*
-        * Check the request is valid.
-        */
-       if (    (SystemInformationClass >= SystemInformationClassMin)
-               && (SystemInformationClass < SystemInformationClassMax)
-               )
+  ULONG ResultLength;
+  PVOID SystemInformation;
+  NTSTATUS Status;
+  NTSTATUS FStatus;
+  
+  PAGED_CODE();
+
+/*     DPRINT("NtQuerySystemInformation Start. Class:%d\n",
+                                       SystemInformationClass );
+*/
+  /*if (ExGetPreviousMode() == KernelMode)
+    {*/
+      SystemInformation = UnsafeSystemInformation;
+    /*}
+  else
+    {
+      SystemInformation = ExAllocatePool(NonPagedPool, Length);
+      if (SystemInformation == NULL)
+       {
+         return(STATUS_NO_MEMORY);
+       }
+    }*/
+  
+  /* Clear user buffer. */
+  RtlZeroMemory(SystemInformation, Length);
+
+  /*
+   * Check the request is valid.
+   */
+  if ((SystemInformationClass >= SystemInformationClassMin) && 
+      (SystemInformationClass < SystemInformationClassMax))
+    {
+      if (NULL != CallQS [SystemInformationClass].Query)
        {
-               if (NULL != CallQS [SystemInformationClass].Query)
+         /*
+          * Hand the request to a subhandler.
+          */
+         FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
+                                                         Length,
+                                                         &ResultLength);
+         /*if (ExGetPreviousMode() != KernelMode)
+           {
+             Status = MmCopyToCaller(UnsafeSystemInformation, 
+                                     SystemInformation,
+                                     Length);
+             ExFreePool(SystemInformation);
+             if (!NT_SUCCESS(Status))
                {
-                       /*
-                        * Hand the request to a subhandler.
-                        */
-                       return CallQS [SystemInformationClass].Query (
-                                       SystemInformation,
-                                       Length,
-                                       ResultLength
-                                       );
+                 return(Status);
                }
+           }*/
+         if (UnsafeResultLength != NULL)
+           {
+             /*if (ExGetPreviousMode() == KernelMode)
+               {
+                 *UnsafeResultLength = ResultLength;
+               }
+             else
+               {*/
+                 Status = MmCopyToCaller(UnsafeResultLength,
+                                         &ResultLength,
+                                         sizeof(ULONG));
+                 if (!NT_SUCCESS(Status))
+                   {
+                     return(Status);
+                   }
+               /*}*/
+           }
+         return(FStatus);
        }
-       return (STATUS_INVALID_INFO_CLASS);
+    }
+  return (STATUS_INVALID_INFO_CLASS);
 }
 
 
@@ -761,6 +1590,8 @@ NtSetSystemInformation (
        IN      ULONG                           SystemInformationLength
        )
 {
+        PAGED_CODE();
+        
        /*
         * If called from user mode, check 
         * possible unsafe arguments.
@@ -809,7 +1640,10 @@ NtFlushInstructionCache (
        IN      UINT    NumberOfBytesToFlush
        )
 {
-       UNIMPLEMENTED;
+        PAGED_CODE();
+        
+       __asm__("wbinvd\n");
+       return STATUS_SUCCESS;
 }