[NTOSKRNL] Add the CcPinMappedDataCount counter
[reactos.git] / ntoskrnl / ex / sysinfo.c
index 6fb5e25..09b9a63 100644 (file)
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
+#include <wmidata.h>
+#include <wmistr.h>
 #define NDEBUG
 #include <debug.h>
 
 /* The maximum size of an environment value (in bytes) */
 #define MAX_ENVVAL_SIZE 1024
 
+#define SIG_ACPI 0x41435049
+#define SIG_FIRM 0x4649524D
+#define SIG_RSMB 0x52534D42
+
+extern LIST_ENTRY HandleTableListHead;
+extern EX_PUSH_LOCK HandleTableListLock;
+
 FAST_MUTEX ExpEnvironmentLock;
 ERESOURCE ExpFirmwareTableResource;
 LIST_ENTRY ExpFirmwareTableProviderListHead;
 
+FORCEINLINE
+NTSTATUS
+ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount,
+                               IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+                               OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo)
+{
+    PCHAR p;
+    NTSTATUS Status;
+    ANSI_STRING ModuleName;
+
+    /* Fill it out */
+    ModuleInfo->MappedBase = NULL;
+    ModuleInfo->ImageBase = LdrEntry->DllBase;
+    ModuleInfo->ImageSize = LdrEntry->SizeOfImage;
+    ModuleInfo->Flags = LdrEntry->Flags;
+    ModuleInfo->LoadCount = LdrEntry->LoadCount;
+    ModuleInfo->LoadOrderIndex = (USHORT)ModuleCount;
+    ModuleInfo->InitOrderIndex = 0;
+
+    /* Setup name */
+    RtlInitEmptyAnsiString(&ModuleName,
+                           ModuleInfo->FullPathName,
+                           sizeof(ModuleInfo->FullPathName));
+
+    /* Convert it */
+    Status = RtlUnicodeStringToAnsiString(&ModuleName,
+                                          &LdrEntry->FullDllName,
+                                          FALSE);
+    if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+    {
+        /* Calculate offset to name */
+        p = ModuleName.Buffer + ModuleName.Length;
+        while ((p > ModuleName.Buffer) && (*--p))
+        {
+            /* Check if we found the separator */
+            if (*p == OBJ_NAME_PATH_SEPARATOR)
+            {
+                /* We did, break out */
+                p++;
+                break;
+            }
+        }
+
+        /* Set the offset */
+        ModuleInfo->OffsetToFileName = (USHORT)(p - ModuleName.Buffer);
+    }
+    else
+    {
+        /* Return empty name */
+        ModuleInfo->FullPathName[0] = ANSI_NULL;
+        ModuleInfo->OffsetToFileName = 0;
+    }
+
+    return Status;
+}
+
 NTSTATUS
 NTAPI
 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
@@ -33,10 +98,8 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
     ULONG RequiredLength;
     PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
     PLDR_DATA_TABLE_ENTRY LdrEntry;
-    ANSI_STRING ModuleName;
     ULONG ModuleCount = 0;
     PLIST_ENTRY NextEntry;
-    PCHAR p;
 
     /* Setup defaults */
     RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules);
@@ -55,48 +118,9 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
         RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
         if (Length >= RequiredLength)
         {
-            /* Fill it out */
-            ModuleInfo->MappedBase = NULL;
-            ModuleInfo->ImageBase = LdrEntry->DllBase;
-            ModuleInfo->ImageSize = LdrEntry->SizeOfImage;
-            ModuleInfo->Flags = LdrEntry->Flags;
-            ModuleInfo->LoadCount = LdrEntry->LoadCount;
-            ModuleInfo->LoadOrderIndex = (USHORT)ModuleCount;
-            ModuleInfo->InitOrderIndex = 0;
-
-            /* Setup name */
-            RtlInitEmptyAnsiString(&ModuleName,
-                                   ModuleInfo->FullPathName,
-                                   sizeof(ModuleInfo->FullPathName));
-
-            /* Convert it */
-            Status = RtlUnicodeStringToAnsiString(&ModuleName,
-                                                  &LdrEntry->FullDllName,
-                                                  FALSE);
-            if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
-            {
-                /* Calculate offset to name */
-                p = ModuleName.Buffer + ModuleName.Length;
-                while ((p > ModuleName.Buffer) && (*--p))
-                {
-                    /* Check if we found the separator */
-                    if (*p == OBJ_NAME_PATH_SEPARATOR)
-                    {
-                        /* We did, break out */
-                        p++;
-                        break;
-                    }
-                }
-
-                /* Set the offset */
-                ModuleInfo->OffsetToFileName = (USHORT)(p - ModuleName.Buffer);
-            }
-            else
-            {
-                /* Return empty name */
-                ModuleInfo->FullPathName[0] = ANSI_NULL;
-                ModuleInfo->OffsetToFileName = 0;
-            }
+            Status = ExpConvertLdrModuleToRtlModule(ModuleCount,
+                                                    LdrEntry,
+                                                    ModuleInfo);
 
             /* Go to the next module */
             ModuleInfo++;
@@ -115,8 +139,35 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
     /* Check if caller also wanted user modules */
     if (UserModeList)
     {
-        /* FIXME: TODO */
-        DPRINT1("User-mode list not yet supported in ReactOS!\n");
+        NextEntry = UserModeList->Flink;
+        while (NextEntry != UserModeList)
+        {
+            /* Get the entry */
+            LdrEntry = CONTAINING_RECORD(NextEntry,
+                                         LDR_DATA_TABLE_ENTRY,
+                                         InLoadOrderLinks);
+
+            /* Update size and check if we can manage one more entry */
+            RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
+            if (Length >= RequiredLength)
+            {
+                Status = ExpConvertLdrModuleToRtlModule(ModuleCount,
+                                                        LdrEntry,
+                                                        ModuleInfo);
+
+                /* Go to the next module */
+                ModuleInfo++;
+            }
+            else
+            {
+                /* Set error code */
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+            }
+
+            /* Update count and move to next entry */
+            ModuleCount++;
+            NextEntry = NextEntry->Flink;
+        }
     }
 
     /* Update return length */
@@ -138,6 +189,131 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
     return Status;
 }
 
+VOID
+NTAPI
+ExUnlockUserBuffer(PMDL Mdl)
+{
+    MmUnlockPages(Mdl);
+    ExFreePoolWithTag(Mdl, TAG_MDL);
+}
+
+NTSTATUS
+NTAPI
+ExLockUserBuffer(
+    PVOID BaseAddress,
+    ULONG Length,
+    KPROCESSOR_MODE AccessMode,
+    LOCK_OPERATION Operation,
+    PVOID *MappedSystemVa,
+    PMDL *OutMdl)
+{
+    PMDL Mdl;
+    PAGED_CODE();
+
+    *MappedSystemVa = NULL;
+    *OutMdl = NULL;
+
+    /* Allocate an MDL for the buffer */
+    Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, TRUE, NULL);
+    if (Mdl == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Enter SEH for probing */
+    _SEH2_TRY
+    {
+        MmProbeAndLockPages(Mdl, AccessMode, Operation);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        ExFreePoolWithTag(Mdl, TAG_MDL);
+        _SEH2_YIELD(return _SEH2_GetExceptionCode());
+    }
+    _SEH2_END;
+
+    /* Return the safe kernel mode buffer */
+    *MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+    if (*MappedSystemVa == NULL)
+    {
+        ExUnlockUserBuffer(Mdl);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Return the MDL */
+    *OutMdl = Mdl;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+ExpGetRawSMBiosTable(
+    _Out_opt_ PVOID Buffer,
+    _Out_ ULONG * OutSize,
+    _In_ ULONG BufferSize)
+{
+    NTSTATUS Status;
+    PVOID DataBlockObject;
+    PWNODE_ALL_DATA AllData;
+    ULONG WMIBufSize;
+
+    ASSERT(OutSize != NULL);
+    *OutSize = 0;
+
+    /* Open the data block object for the SMBIOS table */
+    Status = IoWMIOpenBlock(&MSSmBios_RawSMBiosTables_GUID,
+                            WMIGUID_QUERY,
+                            &DataBlockObject);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
+        return Status;
+    }
+
+    /* Query the required buffer size */
+    WMIBufSize = 0;
+    Status = IoWMIQueryAllData(DataBlockObject, &WMIBufSize, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
+        return Status;
+    }
+    
+    AllData = ExAllocatePoolWithTag(PagedPool, WMIBufSize, 'itfS');
+    if (AllData == NULL)
+    {
+        DPRINT1("Failed to allocate %lu bytes for SMBIOS tables\n", WMIBufSize);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Query the buffer data */
+    Status = IoWMIQueryAllData(DataBlockObject, &WMIBufSize, AllData);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status);
+        ExFreePoolWithTag(AllData, 'itfS');
+        return Status;
+    }
+
+    Status = STATUS_SUCCESS;
+    *OutSize = AllData->FixedInstanceSize;
+    if (Buffer != NULL)
+    {
+        if (BufferSize >= *OutSize)
+        {
+            RtlMoveMemory(Buffer, AllData + 1, *OutSize);
+        }
+        else
+        {
+            Status = STATUS_BUFFER_TOO_SMALL;
+        }
+    }
+
+    /* Free the buffer */
+    ExFreePoolWithTag(AllData, 'itfS');
+    return Status;
+}
+
 /* FUNCTIONS *****************************************************************/
 
 /*
@@ -401,7 +577,10 @@ NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
 NTSTATUS
 NTAPI
 NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
-                              IN LPGUID VendorGuid)
+                              IN LPGUID VendorGuid,
+                              IN PVOID Value,
+                              IN OUT PULONG ReturnLength,
+                              IN OUT PULONG Attributes)
 {
     UNIMPLEMENTED;
     return STATUS_NOT_IMPLEMENTED;
@@ -481,7 +660,7 @@ QSI_DEF(SystemProcessorInformation)
     Spi->Reserved = 0;
     Spi->ProcessorFeatureBits = KeFeatureBits;
 
-    DPRINT("Arch %d Level %d Rev 0x%x\n", Spi->ProcessorArchitecture,
+    DPRINT("Arch %u Level %u Rev 0x%x\n", Spi->ProcessorArchitecture,
         Spi->ProcessorLevel, Spi->ProcessorRevision);
 
     return STATUS_SUCCESS;
@@ -583,14 +762,14 @@ QSI_DEF(SystemPerformanceInformation)
     Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */
     Spi->CcFastMdlReadNotPossible = 0; /* FIXME */
 
-    Spi->CcMapDataNoWait = 0; /* FIXME */
-    Spi->CcMapDataWait = 0; /* FIXME */
+    Spi->CcMapDataNoWait = CcMapDataNoWait;
+    Spi->CcMapDataWait = CcMapDataWait;
     Spi->CcMapDataNoWaitMiss = 0; /* FIXME */
     Spi->CcMapDataWaitMiss = 0; /* FIXME */
 
-    Spi->CcPinMappedDataCount = 0; /* FIXME */
-    Spi->CcPinReadNoWait = 0; /* FIXME */
-    Spi->CcPinReadWait = 0; /* FIXME */
+    Spi->CcPinMappedDataCount = CcPinMappedDataCount;
+    Spi->CcPinReadNoWait = CcPinReadNoWait;
+    Spi->CcPinReadWait = CcPinReadWait;
     Spi->CcPinReadNoWaitMiss = 0; /* FIXME */
     Spi->CcPinReadWaitMiss = 0; /* FIXME */
     Spi->CcCopyReadNoWait = 0; /* FIXME */
@@ -603,10 +782,10 @@ QSI_DEF(SystemPerformanceInformation)
     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->CcLazyWriteIos = CcLazyWriteIos;
+    Spi->CcLazyWritePages = CcLazyWritePages;
+    Spi->CcDataFlushes = CcDataFlushes;
+    Spi->CcDataPages = CcDataPages;
     Spi->ContextSwitches = 0; /* FIXME */
     Spi->FirstLevelTbFills = 0; /* FIXME */
     Spi->SecondLevelTbFills = 0; /* FIXME */
@@ -670,14 +849,15 @@ QSI_DEF(SystemProcessInformation)
     PETHREAD CurrentThread;
     ANSI_STRING ImageName;
     ULONG CurrentSize;
-    USHORT ImageNameMaximumLength; // image name len in bytes
+    USHORT ImageNameMaximumLength; // image name length in bytes
     USHORT ImageNameLength;
     PLIST_ENTRY CurrentEntry;
     ULONG TotalSize = 0, ThreadsCount;
     ULONG TotalUser, TotalKernel;
     PUCHAR Current;
     NTSTATUS Status = STATUS_SUCCESS;
-    PUNICODE_STRING ProcessImageName;
+    PUNICODE_STRING TempProcessImageName;
+    _SEH2_VOLATILE PUNICODE_STRING ProcessImageName = NULL;
     PWCHAR szSrc;
     BOOLEAN Overflow = FALSE;
 
@@ -707,15 +887,23 @@ QSI_DEF(SystemProcessInformation)
         {
             SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
 
+            /* Lock the Process */
+            KeEnterCriticalRegion();
+            ExAcquirePushLockShared(&Process->ProcessLock);
+
             if ((Process->ProcessExiting) &&
                 (Process->Pcb.Header.SignalState) &&
                 !(Process->ActiveThreads) &&
                 (IsListEmpty(&Process->Pcb.ThreadListHead)))
             {
-                DPRINT1("Process %p (%s:%lx) is a zombie\n",
+                DPRINT1("Process %p (%s:%p) is a zombie\n",
                         Process, Process->ImageFileName, Process->UniqueProcessId);
                 CurrentSize = 0;
                 ImageNameMaximumLength = 0;
+
+                /* Unlock the Process */
+                ExReleasePushLockShared(&Process->ProcessLock);
+                KeLeaveCriticalRegion();
                 goto Skip;
             }
 
@@ -730,7 +918,8 @@ QSI_DEF(SystemProcessInformation)
             // size of the structure for every process
             CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount;
             ImageNameLength = 0;
-            Status = SeLocateProcessImageName(Process, &ProcessImageName);
+            Status = SeLocateProcessImageName(Process, &TempProcessImageName);
+            ProcessImageName = TempProcessImageName;
             szSrc = NULL;
             if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0))
             {
@@ -772,7 +961,7 @@ QSI_DEF(SystemProcessInformation)
             /* Fill system information */
             if (!Overflow)
             {
-                SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginnnig of the next structure
+                SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginning of the next structure
                 SpiCurrent->NumberOfThreads = ThreadsCount;
                 SpiCurrent->CreateTime = Process->CreateTime;
                 SpiCurrent->ImageName.Length = ImageNameLength;
@@ -785,9 +974,6 @@ QSI_DEF(SystemProcessInformation)
                     if (szSrc)
                     {
                         RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
-
-                        /* Release the memory allocated by SeLocateProcessImageName */
-                        ExFreePool(ProcessImageName);
                     }
                     else
                     {
@@ -821,8 +1007,7 @@ QSI_DEF(SystemProcessInformation)
                 CurrentEntry = Process->Pcb.ThreadListHead.Flink;
                 while (CurrentEntry != &Process->Pcb.ThreadListHead)
                 {
-                    CurrentThread = (PETHREAD)CONTAINING_RECORD(CurrentEntry, KTHREAD,
-                        ThreadListEntry);
+                    CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD, Tcb.ThreadListEntry);
 
                     ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
                     ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement);
@@ -846,6 +1031,17 @@ QSI_DEF(SystemProcessInformation)
                 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement);
             }
 
+            if (ProcessImageName)
+            {
+                /* Release the memory allocated by SeLocateProcessImageName */
+                ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
+                ProcessImageName = NULL;
+            }
+
+            /* Unlock the Process */
+            ExReleasePushLockShared(&Process->ProcessLock);
+            KeLeaveCriticalRegion();
+
             /* Handle idle process entry */
 Skip:
             if (Process == PsIdleProcess) Process = NULL;
@@ -870,6 +1066,12 @@ Skip:
     {
         if(Process != NULL)
             ObDereferenceObject(Process);
+        if (ProcessImageName)
+        {
+            /* Release the memory allocated by SeLocateProcessImageName */
+            ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
+        }
+
         Status = _SEH2_GetExceptionCode();
     }
     _SEH2_END
@@ -956,12 +1158,20 @@ QSI_DEF(SystemProcessorPerformanceInformation)
 /* Class 9 - Flags Information */
 QSI_DEF(SystemFlagsInformation)
 {
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+    *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
+#endif
+
     if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size)
     {
-        *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
-        return (STATUS_INFO_LENGTH_MISMATCH);
+        return STATUS_INFO_LENGTH_MISMATCH;
     }
+
     ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag;
+#if (NTDDI_VERSION < NTDDI_VISTA)
+    *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION);
+#endif
+
     return STATUS_SUCCESS;
 }
 
@@ -971,6 +1181,12 @@ SSI_DEF(SystemFlagsInformation)
     {
         return STATUS_INFO_LENGTH_MISMATCH;
     }
+
+    if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode()))
+    {
+        return STATUS_ACCESS_DENIED;
+    }
+
     NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags;
     return STATUS_SUCCESS;
 }
@@ -1041,93 +1257,131 @@ QSI_DEF(SystemNonPagedPoolInformation)
 /* Class 16 - Handle Information */
 QSI_DEF(SystemHandleInformation)
 {
-    PEPROCESS pr, syspr;
-    ULONG curSize, i = 0;
-    ULONG hCount = 0;
-
-    PSYSTEM_HANDLE_INFORMATION Shi =
-        (PSYSTEM_HANDLE_INFORMATION) Buffer;
+    PSYSTEM_HANDLE_INFORMATION HandleInformation;
+    PLIST_ENTRY NextTableEntry;
+    PHANDLE_TABLE HandleTable;
+    PHANDLE_TABLE_ENTRY HandleTableEntry;
+    EXHANDLE Handle;
+    ULONG Index = 0;
+    NTSTATUS Status;
+    PMDL Mdl;
+    PAGED_CODE();
 
     DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
 
-    if (Size < sizeof(SYSTEM_HANDLE_INFORMATION))
+    /* Set initial required buffer size */
+    *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handles);
+
+    /* Check user's buffer size */
+    if (Size < *ReqSize)
     {
-        *ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
         return STATUS_INFO_LENGTH_MISMATCH;
     }
 
-    DPRINT("SystemHandleInformation 1\n");
+    /* We need to lock down the memory */
+    Status = ExLockUserBuffer(Buffer,
+                              Size,
+                              ExGetPreviousMode(),
+                              IoWriteAccess,
+                              (PVOID*)&HandleInformation,
+                              &Mdl);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
+        return Status;
+    }
 
-    /* First Calc Size from Count. */
-    syspr = PsGetNextProcess(NULL);
-    pr = syspr;
+    /* Reset of count of handles */
+    HandleInformation->NumberOfHandles = 0;
 
-    do
-    {
-        hCount = hCount + ObGetProcessHandleCount(pr);
-        pr = PsGetNextProcess(pr);
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
 
-        if ((pr == syspr) || (pr == NULL)) break;
-    }
-    while ((pr != syspr) && (pr != NULL));
+    /* Acquire the handle table lock */
+    ExAcquirePushLockShared(&HandleTableListLock);
 
-    if(pr != NULL)
+    /* Enumerate all system handles */
+    for (NextTableEntry = HandleTableListHead.Flink;
+         NextTableEntry != &HandleTableListHead;
+         NextTableEntry = NextTableEntry->Flink)
     {
-        ObDereferenceObject(pr);
-    }
+        /* Get current handle table */
+        HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList);
 
-    DPRINT("SystemHandleInformation 2\n");
+        /* Set the initial value and loop the entries */
+        Handle.Value = 0;
+        while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
+        {
+            /* Validate the entry */
+            if ((HandleTableEntry->Object) &&
+                (HandleTableEntry->NextFreeTableEntry != -2))
+            {
+                /* Increase of count of handles */
+                ++HandleInformation->NumberOfHandles;
 
-    curSize = sizeof(SYSTEM_HANDLE_INFORMATION) +
-                     ((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * hCount) -
-                     (sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)));
+                /* Lock the entry */
+                if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
+                {
+                    /* Increase required buffer size */
+                    *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO);
 
-    Shi->NumberOfHandles = hCount;
+                    /* Check user's buffer size */
+                    if (*ReqSize > Size)
+                    {
+                        Status = STATUS_INFO_LENGTH_MISMATCH;
+                    }
+                    else
+                    {
+                        POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
 
-    if (curSize > Size)
-    {
-        *ReqSize = curSize;
-        return (STATUS_INFO_LENGTH_MISMATCH);
-    }
+                        /* Filling handle information */
+                        HandleInformation->Handles[Index].UniqueProcessId =
+                            (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId;
 
-    DPRINT("SystemHandleInformation 3\n");
+                        HandleInformation->Handles[Index].CreatorBackTraceIndex = 0;
 
-    /* Now get Handles from all processs. */
-    syspr = PsGetNextProcess(NULL);
-    pr = syspr;
+#if 0 /* FIXME!!! Type field currupted */
+                        HandleInformation->Handles[Index].ObjectTypeIndex =
+                            (UCHAR) ObjectHeader->Type->Index;
+#else
+                        HandleInformation->Handles[Index].ObjectTypeIndex = 0;
+#endif
 
-    do
-    {
-        int Count = 0, HandleCount;
+                        HandleInformation->Handles[Index].HandleAttributes =
+                            HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
 
-        HandleCount = ObGetProcessHandleCount(pr);
+                        HandleInformation->Handles[Index].HandleValue =
+                            (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay;
 
-        for (Count = 0; HandleCount > 0 ; HandleCount--)
-        {
-            Shi->Handles[i].UniqueProcessId = (USHORT)(ULONG_PTR)pr->UniqueProcessId;
-            Count++;
-            i++;
-        }
+                        HandleInformation->Handles[Index].Object = &ObjectHeader->Body;
 
-        pr = PsGetNextProcess(pr);
+                        HandleInformation->Handles[Index].GrantedAccess =
+                            HandleTableEntry->GrantedAccess;
 
-        if ((pr == syspr) || (pr == NULL)) break;
+                        ++Index;
+                    }
+
+                    /* Unlock it */
+                    ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
+                }
+            }
+
+            /* Go to the next entry */
+            Handle.Value += sizeof(HANDLE);
+        }
     }
-    while ((pr != syspr) && (pr != NULL));
 
-    if(pr != NULL) ObDereferenceObject(pr);
+    /* Release the lock */
+    ExReleasePushLockShared(&HandleTableListLock);
 
-    DPRINT("SystemHandleInformation 4\n");
-    return STATUS_SUCCESS;
+    /* Leave the critical region */
+    KeLeaveCriticalRegion();
 
-}
-/*
-SSI_DEF(SystemHandleInformation)
-{
+    /* Release the locked user buffer */
+    ExUnlockUserBuffer(Mdl);
 
-    return STATUS_SUCCESS;
+    return Status;
 }
-*/
 
 /* Class 17 -  Information */
 QSI_DEF(SystemObjectInformation)
@@ -1182,9 +1436,10 @@ QSI_DEF(SystemFileCacheInformation)
 {
     SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer;
 
-    if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION))
+    *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
+
+    if (Size < *ReqSize)
     {
-        *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION);
         return STATUS_INFO_LENGTH_MISMATCH;
     }
 
@@ -1287,7 +1542,7 @@ QSI_DEF(SystemFullMemoryInformation)
 
     TheIdleProcess = PsIdleProcess;
 
-    DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n",
+    DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n",
            TheIdleProcess->UniqueProcessId,
            TheIdleProcess->Pcb.KernelTime,
            MiFreeSwapPages,
@@ -1355,7 +1610,7 @@ SSI_DEF(SystemLoadGdiDriverInformation)
 /* Class 27 - Unload Image */
 SSI_DEF(SystemUnloadGdiDriverInformation)
 {
-    PVOID SectionPointer = Buffer;
+    PVOID *SectionPointer = Buffer;
 
     /* Validate size */
     if (Size != sizeof(PVOID))
@@ -1368,7 +1623,7 @@ SSI_DEF(SystemUnloadGdiDriverInformation)
     if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
 
     /* Unload the image */
-    MmUnloadSystemImage(SectionPointer);
+    MmUnloadSystemImage(*SectionPointer);
     return STATUS_SUCCESS;
 }
 
@@ -1449,11 +1704,11 @@ QSI_DEF(SystemNextEventIdInformation)
     return STATUS_NOT_IMPLEMENTED;
 }
 
-/* Class 31 - Event Ids Information */
-QSI_DEF(SystemEventIdsInformation)
+/* Class 31 */
+QSI_DEF(SystemPerformanceTraceInformation)
 {
     /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemEventIdsInformation not implemented\n");
+    DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -1487,7 +1742,9 @@ QSI_DEF(SystemExceptionInformation)
         {
             AlignmentFixupCount += Prcb->KeAlignmentFixupCount;
             ExceptionDispatchCount += Prcb->KeExceptionDispatchCount;
+#ifndef _M_ARM
             FloatingEmulationCount += Prcb->KeFloatingEmulationCount;
+#endif // _M_ARM
         }
     }
 
@@ -1513,7 +1770,10 @@ QSI_DEF(SystemKernelDebuggerInformation)
 {
     PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer;
 
+#if (NTDDI_VERSION >= NTDDI_VISTA)
     *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
+#endif
+
     if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION))
     {
         return STATUS_INFO_LENGTH_MISMATCH;
@@ -1522,6 +1782,10 @@ QSI_DEF(SystemKernelDebuggerInformation)
     skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED;
     skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT;
 
+#if (NTDDI_VERSION < NTDDI_VISTA)
+    *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION);
+#endif
+
     return STATUS_SUCCESS;
 }
 
@@ -1612,28 +1876,51 @@ SSI_DEF(SystemExtendServiceTableInformation)
     /* Check who is calling */
     if (PreviousMode != KernelMode)
     {
+        static const UNICODE_STRING Win32kName =
+            RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\win32k.sys");
+
         /* Make sure we can load drivers */
         if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode))
         {
             /* FIXME: We can't, fail */
-            //return STATUS_PRIVILEGE_NOT_HELD;
+            return STATUS_PRIVILEGE_NOT_HELD;
         }
-    }
 
-    /* Probe and capture the driver name */
-    ProbeAndCaptureUnicodeString(&ImageName, PreviousMode, Buffer);
+        _SEH2_TRY
+        {
+            /* Probe and copy the unicode string */
+            ProbeForRead(Buffer, sizeof(ImageName), 1);
+            ImageName = *(PUNICODE_STRING)Buffer;
+
+            /* Probe the string buffer */
+            ProbeForRead(ImageName.Buffer, ImageName.Length, sizeof(WCHAR));
+
+            /* Check if we have the correct name (nothing else is allowed!) */
+            if (!RtlEqualUnicodeString(&ImageName, &Win32kName, FALSE))
+            {
+                _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD);
+            }
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
+
+        /* Recursively call the function, so that we are from kernel mode */
+        return ZwSetSystemInformation(SystemExtendServiceTableInformation,
+                                      (PVOID)&Win32kName,
+                                      sizeof(Win32kName));
+    }
 
     /* Load the image */
-    Status = MmLoadSystemImage(&ImageName,
+    Status = MmLoadSystemImage((PUNICODE_STRING)Buffer,
                                NULL,
                                NULL,
                                0,
                                (PVOID)&ModuleObject,
                                &ImageBase);
 
-    /* Release String */
-    ReleaseCapturedUnicodeString(&ImageName, PreviousMode);
-
     if (!NT_SUCCESS(Status)) return Status;
 
     /* Get the headers */
@@ -1667,49 +1954,69 @@ SSI_DEF(SystemExtendServiceTableInformation)
 /* Class 39 - Priority Separation */
 SSI_DEF(SystemPrioritySeperation)
 {
-    /* FIXME */
-    DPRINT1("NtSetSystemInformation - SystemPrioritySeperation not implemented\n");
-    return STATUS_NOT_IMPLEMENTED;
+    /* Check if the size is correct */
+    if (Size != sizeof(ULONG))
+    {
+        return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+    /* We need the TCB privilege */
+    if (!SeSinglePrivilegeCheck(SeTcbPrivilege, ExGetPreviousMode()))
+    {
+        return STATUS_PRIVILEGE_NOT_HELD;
+    }
+
+    /* Modify the quantum table */
+    PsChangeQuantumTable(TRUE, *(PULONG)Buffer);
+
+    return STATUS_SUCCESS;
 }
 
-/* Class 40 - Plug Play Bus Information */
-QSI_DEF(SystemPlugPlayBusInformation)
+/* Class 40 */
+QSI_DEF(SystemVerifierAddDriverInformation)
 {
     /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemPlugPlayBusInformation not implemented\n");
+    DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
-/* Class 41 - Dock Information */
-QSI_DEF(SystemDockInformation)
+/* Class 41 */
+QSI_DEF(SystemVerifierRemoveDriverInformation)
 {
     /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemDockInformation not implemented\n");
+    DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
 /* Class 42 - Power Information */
-QSI_DEF(SystemPowerInformation)
+QSI_DEF(SystemProcessorIdleInformation)
 {
+    *ReqSize = sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors;
+
+    if (sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors > Size)
+    {
+        return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
     /* FIXME */
     DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
-/* Class 43 - Processor Speed Information */
-QSI_DEF(SystemProcessorSpeedInformation)
+/* Class 43 */
+QSI_DEF(SystemLegacyDriverInformation)
 {
     /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemProcessorSpeedInformation not implemented\n");
+    DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
 /* Class 44 - Current Time Zone Information */
 QSI_DEF(SystemCurrentTimeZoneInformation)
 {
-    *ReqSize = sizeof(TIME_ZONE_INFORMATION);
+    *ReqSize = sizeof(RTL_TIME_ZONE_INFORMATION);
 
-    if (sizeof(TIME_ZONE_INFORMATION) != Size)
+    if (sizeof(RTL_TIME_ZONE_INFORMATION) != Size)
     {
         return STATUS_INFO_LENGTH_MISMATCH;
     }
@@ -1717,7 +2024,7 @@ QSI_DEF(SystemCurrentTimeZoneInformation)
     /* Copy the time zone information struct */
     memcpy(Buffer,
            &ExpTimeZoneInfo,
-           sizeof(TIME_ZONE_INFORMATION));
+           sizeof(RTL_TIME_ZONE_INFORMATION));
 
     return STATUS_SUCCESS;
 }
@@ -1726,29 +2033,167 @@ QSI_DEF(SystemCurrentTimeZoneInformation)
 SSI_DEF(SystemCurrentTimeZoneInformation)
 {
     /* Check user buffer's size */
-    if (Size < sizeof(TIME_ZONE_INFORMATION))
+    if (Size < sizeof(RTL_TIME_ZONE_INFORMATION))
     {
         return STATUS_INFO_LENGTH_MISMATCH;
     }
 
-    return ExpSetTimeZoneInformation((PTIME_ZONE_INFORMATION)Buffer);
+    return ExpSetTimeZoneInformation((PRTL_TIME_ZONE_INFORMATION)Buffer);
 }
 
+static
+VOID
+ExpCopyLookasideInformation(
+    PSYSTEM_LOOKASIDE_INFORMATION *InfoPointer,
+    PULONG RemainingPointer,
+    PLIST_ENTRY ListHead,
+    BOOLEAN ListUsesMisses)
+
+{
+    PSYSTEM_LOOKASIDE_INFORMATION Info;
+    PGENERAL_LOOKASIDE LookasideList;
+    PLIST_ENTRY ListEntry;
+    ULONG Remaining;
+
+    /* Get info pointer and remaining count of free array element */
+    Info = *InfoPointer;
+    Remaining = *RemainingPointer;
+
+    /* Loop as long as we have lookaside lists and free array elements */
+    for (ListEntry = ListHead->Flink;
+         (ListEntry != ListHead) && (Remaining > 0);
+         ListEntry = ListEntry->Flink, Remaining--)
+    {
+        LookasideList = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry);
+
+        /* Fill the next array element */
+        Info->CurrentDepth = LookasideList->Depth;
+        Info->MaximumDepth = LookasideList->MaximumDepth;
+        Info->TotalAllocates = LookasideList->TotalAllocates;
+        Info->TotalFrees = LookasideList->TotalFrees;
+        Info->Type = LookasideList->Type;
+        Info->Tag = LookasideList->Tag;
+        Info->Size = LookasideList->Size;
+
+        /* Check how the lists track misses/hits */
+        if (ListUsesMisses)
+        {
+            /* Copy misses */
+            Info->AllocateMisses = LookasideList->AllocateMisses;
+            Info->FreeMisses = LookasideList->FreeMisses;
+        }
+        else
+        {
+            /* Calculate misses */
+            Info->AllocateMisses = LookasideList->TotalAllocates
+                                   - LookasideList->AllocateHits;
+            Info->FreeMisses = LookasideList->TotalFrees
+                               - LookasideList->FreeHits;
+        }
+    }
+
+    /* Return the updated pointer and remaining count */
+    *InfoPointer = Info;
+    *RemainingPointer = Remaining;
+}
 
 /* Class 45 - Lookaside Information */
 QSI_DEF(SystemLookasideInformation)
 {
-    /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemLookasideInformation not implemented\n");
-    return STATUS_NOT_IMPLEMENTED;
+    KPROCESSOR_MODE PreviousMode;
+    PSYSTEM_LOOKASIDE_INFORMATION Info;
+    PMDL Mdl;
+    ULONG MaxCount, Remaining;
+    KIRQL OldIrql;
+    NTSTATUS Status;
+
+    /* First we need to lock down the memory, since we are going to access it
+       at high IRQL */
+    PreviousMode = ExGetPreviousMode();
+    Status = ExLockUserBuffer(Buffer,
+                              Size,
+                              PreviousMode,
+                              IoWriteAccess,
+                              (PVOID*)&Info,
+                              &Mdl);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Calculate how many items we can store */
+    Remaining = MaxCount = Size / sizeof(SYSTEM_LOOKASIDE_INFORMATION);
+    if (Remaining == 0)
+    {
+        goto Leave;
+    }
+
+    /* Copy info from pool lookaside lists */
+    ExpCopyLookasideInformation(&Info,
+                                &Remaining,
+                                &ExPoolLookasideListHead,
+                                FALSE);
+    if (Remaining == 0)
+    {
+        goto Leave;
+    }
+
+    /* Copy info from system lookaside lists */
+    ExpCopyLookasideInformation(&Info,
+                                &Remaining,
+                                &ExSystemLookasideListHead,
+                                TRUE);
+    if (Remaining == 0)
+    {
+        goto Leave;
+    }
+
+    /* Acquire spinlock for ExpNonPagedLookasideListHead */
+    KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql);
+
+    /* Copy info from non-paged lookaside lists */
+    ExpCopyLookasideInformation(&Info,
+                                &Remaining,
+                                &ExpNonPagedLookasideListHead,
+                                TRUE);
+
+    /* Release spinlock for ExpNonPagedLookasideListHead */
+    KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql);
+
+    if (Remaining == 0)
+    {
+        goto Leave;
+    }
+
+    /* Acquire spinlock for ExpPagedLookasideListHead */
+    KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql);
+
+    /* Copy info from paged lookaside lists */
+    ExpCopyLookasideInformation(&Info,
+                                &Remaining,
+                                &ExpPagedLookasideListHead,
+                                TRUE);
+
+    /* Release spinlock for ExpPagedLookasideListHead */
+    KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql);
+
+Leave:
+
+    /* Release the locked user buffer */
+    ExUnlockUserBuffer(Mdl);
+
+    /* Return the size of the actually written data */
+    *ReqSize = (MaxCount - Remaining) * sizeof(SYSTEM_LOOKASIDE_INFORMATION);
+    return STATUS_SUCCESS;
 }
 
 
 /* Class 46 - Set time slip event */
-SSI_DEF(SystemSetTimeSlipEvent)
+SSI_DEF(SystemTimeSlipNotification)
 {
     /* FIXME */
-    DPRINT1("NtSetSystemInformation - SystemSetTimSlipEvent not implemented\n");
+    DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -1761,7 +2206,7 @@ NTAPI
 MmSessionDelete(IN ULONG SessionId);
 
 /* Class 47 - Create a new session (TSE) */
-SSI_DEF(SystemCreateSession)
+SSI_DEF(SystemSessionCreate)
 {
     ULONG SessionId;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
@@ -1775,6 +2220,8 @@ SSI_DEF(SystemCreateSession)
         {
             return STATUS_PRIVILEGE_NOT_HELD;
         }
+
+        ProbeForWriteUlong(Buffer);
     }
 
     Status = MmSessionCreate(&SessionId);
@@ -1785,7 +2232,7 @@ SSI_DEF(SystemCreateSession)
 
 
 /* Class 48 - Delete an existing session (TSE) */
-SSI_DEF(SystemDeleteSession)
+SSI_DEF(SystemSessionDetach)
 {
     ULONG SessionId;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
@@ -1807,10 +2254,10 @@ SSI_DEF(SystemDeleteSession)
 
 
 /* Class 49 - UNKNOWN */
-QSI_DEF(SystemInvalidInfoClass4)
+QSI_DEF(SystemSessionInformation)
 {
     /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemInvalidInfoClass4 not implemented\n");
+    DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -1845,11 +2292,11 @@ SSI_DEF(SystemVerifierInformation)
 }
 
 
-/* Class 52 - Add a driver verifier */
-SSI_DEF(SystemAddVerifier)
+/* Class 52 */
+SSI_DEF(SystemVerifierThunkExtend)
 {
     /* FIXME */
-    DPRINT1("NtSetSystemInformation - SystemAddVerifier not implemented\n");
+    DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -1863,13 +2310,380 @@ QSI_DEF(SystemSessionProcessesInformation)
 }
 
 
+/* Class 54 - Load & map in system space */
+SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation)
+{
+    /* FIXME */
+    DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 55 - NUMA processor information  */
+QSI_DEF(SystemNumaProcessorMap)
+{
+    ULONG MaxEntries, Node;
+    PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer;
+
+    /* Validate input size */
+    if (Size < sizeof(ULONG))
+    {
+        return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+    /* Return highest node */
+    NumaInformation->HighestNodeNumber = KeNumberNodes - 1;
+
+    /* Compute how much entries we will be able to put in output structure */
+    MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask)) / sizeof(ULONGLONG);
+    /* Make sure we don't overflow KeNodeBlock */
+    if (MaxEntries > KeNumberNodes)
+    {
+        MaxEntries = KeNumberNodes;
+    }
+
+    /* If we have entries to write, and room for it */
+    if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) &&
+        MaxEntries != 0)
+    {
+        /* Already set size we return */
+        *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) +
+                   MaxEntries * sizeof(ULONGLONG);
+
+        /* For each node, return processor mask */
+        for (Node = 0; Node < MaxEntries; ++Node)
+        {
+            NumaInformation->ActiveProcessorsAffinityMask[Node] = KeNodeBlock[Node]->ProcessorMask;
+        }
+    }
+    else
+    {
+        /* We only returned highest node number */
+        *ReqSize = sizeof(ULONG);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+/* Class 56 - Prefetcher information  */
+QSI_DEF(SystemPrefetcherInformation)
+{
+    /* FIXME */
+    DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 57 - Extended process information  */
+QSI_DEF(SystemExtendedProcessInformation)
+{
+    /* FIXME */
+    DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 58 - Recommended shared ata alignment  */
+QSI_DEF(SystemRecommendedSharedDataAlignment)
+{
+    /* FIXME */
+    DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/* Class 60 - NUMA memory information  */
+QSI_DEF(SystemNumaAvailableMemory)
+{
+    ULONG MaxEntries, Node;
+    PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer;
+
+    /* Validate input size */
+    if (Size < sizeof(ULONG))
+    {
+        return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+    /* Return highest node */
+    NumaInformation->HighestNodeNumber = KeNumberNodes - 1;
+
+    /* Compute how much entries we will be able to put in output structure */
+    MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory)) / sizeof(ULONGLONG);
+    /* Make sure we don't overflow KeNodeBlock */
+    if (MaxEntries > KeNumberNodes)
+    {
+        MaxEntries = KeNumberNodes;
+    }
+
+    /* If we have entries to write, and room for it */
+    if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) &&
+        MaxEntries != 0)
+    {
+        /* Already set size we return */
+        *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) +
+                   MaxEntries * sizeof(ULONGLONG);
+
+        /* If we have a single entry (us), directly return MM information */
+        if (MaxEntries == 1)
+        {
+            NumaInformation->AvailableMemory[0] = MmAvailablePages << PAGE_SHIFT;
+        }
+        else
+        {
+            /* Otherwise, for each node, return available bytes */
+            for (Node = 0; Node < MaxEntries; ++Node)
+            {
+                NumaInformation->AvailableMemory[Node] = (KeNodeBlock[Node]->FreeCount[0] + KeNodeBlock[Node]->FreeCount[1]) << PAGE_SHIFT;
+            }
+        }
+    }
+    else
+    {
+        /* We only returned highest node number */
+        *ReqSize = sizeof(ULONG);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+/* Class 64 - Extended handle information  */
+QSI_DEF(SystemExtendedHandleInformation)
+{
+    PSYSTEM_HANDLE_INFORMATION_EX HandleInformation;
+    PLIST_ENTRY NextTableEntry;
+    PHANDLE_TABLE HandleTable;
+    PHANDLE_TABLE_ENTRY HandleTableEntry;
+    EXHANDLE Handle;
+    ULONG Index = 0;
+    NTSTATUS Status;
+    PMDL Mdl;
+    PAGED_CODE();
+
+    DPRINT("NtQuerySystemInformation - SystemExtendedHandleInformation\n");
+
+    /* Set initial required buffer size */
+    *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handle);
+
+    /* Check user's buffer size */
+    if (Size < *ReqSize)
+    {
+        return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+    /* We need to lock down the memory */
+    Status = ExLockUserBuffer(Buffer,
+                              Size,
+                              ExGetPreviousMode(),
+                              IoWriteAccess,
+                              (PVOID*)&HandleInformation,
+                              &Mdl);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Reset of count of handles */
+    HandleInformation->Count = 0;
+
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
+
+    /* Acquire the handle table lock */
+    ExAcquirePushLockShared(&HandleTableListLock);
+
+    /* Enumerate all system handles */
+    for (NextTableEntry = HandleTableListHead.Flink;
+         NextTableEntry != &HandleTableListHead;
+         NextTableEntry = NextTableEntry->Flink)
+    {
+        /* Get current handle table */
+        HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList);
+
+        /* Set the initial value and loop the entries */
+        Handle.Value = 0;
+        while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
+        {
+            /* Validate the entry */
+            if ((HandleTableEntry->Object) &&
+                (HandleTableEntry->NextFreeTableEntry != -2))
+            {
+                /* Increase of count of handles */
+                ++HandleInformation->Count;
+
+                /* Lock the entry */
+                if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
+                {
+                    /* Increase required buffer size */
+                    *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX);
+
+                    /* Check user's buffer size */
+                    if (*ReqSize > Size)
+                    {
+                        Status = STATUS_INFO_LENGTH_MISMATCH;
+                    }
+                    else
+                    {
+                        POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
+
+                        /* Filling handle information */
+                        HandleInformation->Handle[Index].UniqueProcessId =
+                            (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId;
+
+                        HandleInformation->Handle[Index].CreatorBackTraceIndex = 0;
+
+#if 0 /* FIXME!!! Type field currupted */
+                        HandleInformation->Handles[Index].ObjectTypeIndex =
+                            (UCHAR) ObjectHeader->Type->Index;
+#else
+                        HandleInformation->Handle[Index].ObjectTypeIndex = 0;
+#endif
+
+                        HandleInformation->Handle[Index].HandleAttributes =
+                            HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
+
+                        HandleInformation->Handle[Index].HandleValue =
+                            (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay;
+
+                        HandleInformation->Handle[Index].Object = &ObjectHeader->Body;
+
+                        HandleInformation->Handle[Index].GrantedAccess =
+                            HandleTableEntry->GrantedAccess;
+
+                        HandleInformation->Handle[Index].Reserved = 0;
+
+                        ++Index;
+                    }
+
+                    /* Unlock it */
+                    ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
+                }
+            }
+
+            /* Go to the next entry */
+            Handle.Value += sizeof(HANDLE);
+        }
+    }
+
+    /* Release the lock */
+    ExReleasePushLockShared(&HandleTableListLock);
+
+    /* Leave the critical region */
+    KeLeaveCriticalRegion();
+
+    /* Release the locked user buffer */
+    ExUnlockUserBuffer(Mdl);
+
+    return Status;
+}
+
+/* Class 76 - System firmware table information  */
+QSI_DEF(SystemFirmwareTableInformation)
+{
+    PSYSTEM_FIRMWARE_TABLE_INFORMATION SysFirmwareInfo = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)Buffer;
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG InputBufSize;
+    ULONG DataSize = 0;
+    ULONG TableCount = 0;
+
+    DPRINT("NtQuerySystemInformation - SystemFirmwareTableInformation\n");
+
+    /* Set initial required buffer size */
+    *ReqSize = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
+
+    /* Check user's buffer size */
+    if (Size < *ReqSize)
+    {
+        return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+    InputBufSize = SysFirmwareInfo->TableBufferLength;
+    switch (SysFirmwareInfo->ProviderSignature)
+    {
+        /*
+         * ExpFirmwareTableResource and ExpFirmwareTableProviderListHead
+         * variables should be used there somehow...
+         */
+        case SIG_ACPI:
+        {
+            /* FIXME: Not implemented yet */
+            DPRINT1("ACPI provider not implemented\n");
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+        }
+        case SIG_FIRM:
+        {
+            /* FIXME: Not implemented yet */
+            DPRINT1("FIRM provider not implemented\n");
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+        }
+        case SIG_RSMB:
+        {
+            Status = ExpGetRawSMBiosTable(NULL, &DataSize, 0);
+            if (DataSize > 0)
+            {
+                TableCount = 1;
+                if (SysFirmwareInfo->Action == SystemFirmwareTable_Enumerate)
+                {
+                    DataSize = TableCount * sizeof(ULONG);
+                    if (DataSize <= InputBufSize)
+                    {
+                        *(ULONG *)SysFirmwareInfo->TableBuffer = 0;
+                    }
+                }
+                else if (SysFirmwareInfo->Action == SystemFirmwareTable_Get
+                         && DataSize <= InputBufSize)
+                {
+                    Status = ExpGetRawSMBiosTable(SysFirmwareInfo->TableBuffer, &DataSize, InputBufSize);
+                }
+                SysFirmwareInfo->TableBufferLength = DataSize;
+            }
+            break;
+        }
+        default:
+        {
+            DPRINT1("SystemFirmwareTableInformation: Unsupported provider (0x%x)\n",
+                    SysFirmwareInfo->ProviderSignature);
+            Status = STATUS_ILLEGAL_FUNCTION;
+        }
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        switch (SysFirmwareInfo->Action)
+        {
+            case SystemFirmwareTable_Enumerate:
+            case SystemFirmwareTable_Get:
+            {
+                if (SysFirmwareInfo->TableBufferLength > InputBufSize)
+                {
+                    Status = STATUS_BUFFER_TOO_SMALL;
+                }
+                break;
+            }
+            default:
+            {
+                DPRINT1("SystemFirmwareTableInformation: Unsupported action (0x%x)\n",
+                        SysFirmwareInfo->Action);
+                Status = STATUS_ILLEGAL_FUNCTION;
+            }
+        }
+    }
+    else
+    {
+        SysFirmwareInfo->TableBufferLength = 0;
+    }
+    return Status;
+}
+
 /* Query/Set Calls Table */
 typedef
 struct _QSSI_CALLS
 {
     NTSTATUS (* Query) (PVOID,ULONG,PULONG);
     NTSTATUS (* Set) (PVOID,ULONG);
-
 } QSSI_CALLS;
 
 // QS    Query & Set
@@ -1917,7 +2731,7 @@ CallQS [] =
     SI_QS(SystemTimeAdjustmentInformation),
     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(SystemPerformanceTraceInformation), /* it should be SI_XX */
     SI_QX(SystemCrashDumpInformation),
     SI_QX(SystemExceptionInformation),
     SI_QX(SystemCrashDumpStateInformation),
@@ -1926,20 +2740,43 @@ CallQS [] =
     SI_QS(SystemRegistryQuotaInformation),
     SI_XS(SystemExtendServiceTableInformation),
     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_QX(SystemVerifierAddDriverInformation), /* it should be SI_XX */
+    SI_QX(SystemVerifierRemoveDriverInformation), /* it should be SI_XX */
+    SI_QX(SystemProcessorIdleInformation), /* it should be SI_XX */
+    SI_QX(SystemLegacyDriverInformation), /* 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_XS(SystemTimeSlipNotification),
+    SI_XS(SystemSessionCreate),
+    SI_XS(SystemSessionDetach),
+    SI_QX(SystemSessionInformation), /* it should be SI_XX */
     SI_QX(SystemRangeStartInformation),
     SI_QS(SystemVerifierInformation),
-    SI_XS(SystemAddVerifier),
-    SI_QX(SystemSessionProcessesInformation)
+    SI_XS(SystemVerifierThunkExtend),
+    SI_QX(SystemSessionProcessesInformation),
+    SI_XS(SystemLoadGdiDriverInSystemSpaceInformation),
+    SI_QX(SystemNumaProcessorMap),
+    SI_QX(SystemPrefetcherInformation),
+    SI_QX(SystemExtendedProcessInformation),
+    SI_QX(SystemRecommendedSharedDataAlignment),
+    SI_XX(SystemComPlusPackage),
+    SI_QX(SystemNumaAvailableMemory),
+    SI_XX(SystemProcessorPowerInformation), /* FIXME: not implemented */
+    SI_XX(SystemEmulationBasicInformation), /* FIXME: not implemented */
+    SI_XX(SystemEmulationProcessorInformation), /* FIXME: not implemented */
+    SI_QX(SystemExtendedHandleInformation),
+    SI_XX(SystemLostDelayedWriteInformation), /* FIXME: not implemented */
+    SI_XX(SystemBigPoolInformation), /* FIXME: not implemented */
+    SI_XX(SystemSessionPoolTagInformation), /* FIXME: not implemented */
+    SI_XX(SystemSessionMappedViewInformation), /* FIXME: not implemented */
+    SI_XX(SystemHotpatchInformation), /* FIXME: not implemented */
+    SI_XX(SystemObjectSecurityMode), /* FIXME: not implemented */
+    SI_XX(SystemWatchdogTimerHandler), /* FIXME: not implemented */
+    SI_XX(SystemWatchdogTimerInformation), /* FIXME: not implemented */
+    SI_XX(SystemLogicalProcessorInformation), /* FIXME: not implemented */
+    SI_XX(SystemWow64SharedInformation), /* FIXME: not implemented */
+    SI_XX(SystemRegisterFirmwareTableInformationHandler), /* FIXME: not implemented */
+    SI_QX(SystemFirmwareTableInformation),
 };
 
 C_ASSERT(SystemBasicInformation == 0);
@@ -1949,14 +2786,18 @@ C_ASSERT(SystemBasicInformation == 0);
 /*
  * @implemented
  */
-NTSTATUS NTAPI
-NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
-                         OUT PVOID SystemInformation,
-                         IN ULONG Length,
-                         OUT PULONG UnsafeResultLength)
+__kernel_entry
+NTSTATUS
+NTAPI
+NtQuerySystemInformation(
+    _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
+    _Out_writes_bytes_to_opt_(SystemInformationLength, *ReturnLength) PVOID SystemInformation,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG UnsafeResultLength)
 {
     KPROCESSOR_MODE PreviousMode;
-    ULONG ResultLength;
+    ULONG ResultLength = 0;
+    ULONG Alignment = TYPE_ALIGNMENT(ULONG);
     NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED;
 
     PAGED_CODE();
@@ -1965,21 +2806,39 @@ NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
 
     _SEH2_TRY
     {
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+        /*
+         * Check if the request is valid.
+         */
+        if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
+        {
+            _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
+        }
+#endif
+
         if (PreviousMode != KernelMode)
         {
             /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */
-            ProbeForWrite(SystemInformation, Length, 1);
+            if (SystemInformationClass == SystemKernelDebuggerInformation)
+                Alignment = TYPE_ALIGNMENT(BOOLEAN);
+
+            ProbeForWrite(SystemInformation, Length, Alignment);
             if (UnsafeResultLength != NULL)
                 ProbeForWriteUlong(UnsafeResultLength);
         }
 
+        if (UnsafeResultLength)
+            *UnsafeResultLength = 0;
+
+#if (NTDDI_VERSION < NTDDI_VISTA)
         /*
-         * Check the request is valid.
+         * Check if the request is valid.
          */
         if (SystemInformationClass >= MAX_SYSTEM_INFO_CLASS)
         {
             _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS);
         }
+#endif
 
         if (NULL != CallQS [SystemInformationClass].Query)
         {
@@ -2011,83 +2870,62 @@ NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
                         IN PVOID SystemInformation,
                         IN ULONG SystemInformationLength)
 {
+    NTSTATUS Status = STATUS_INVALID_INFO_CLASS;
+    KPROCESSOR_MODE PreviousMode;
+
     PAGED_CODE();
 
-    /*
-     * If called from user mode, check
-     * possible unsafe arguments.
-     */
-#if 0
-    if (KernelMode != KeGetPreviousMode())
-    {
-        // Check arguments
-        //ProbeForWrite(
-        //    SystemInformation,
-        //    Length
-        //    );
-        //ProbeForWrite(
-        //    ResultLength,
-        //    sizeof (ULONG)
-        //    );
-    }
-#endif
-    /*
-     * Check the request is valid.
-     */
-    if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
-        (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
+    PreviousMode = ExGetPreviousMode();
+
+    _SEH2_TRY
     {
-        if (NULL != CallQS [SystemInformationClass].Set)
+        /*
+         * If called from user mode, check
+         * possible unsafe arguments.
+         */
+        if (PreviousMode != KernelMode)
         {
-            /*
-             * Hand the request to a subhandler.
-             */
-            return CallQS [SystemInformationClass].Set(SystemInformation,
-                                                       SystemInformationLength);
+            ProbeForRead(SystemInformation, SystemInformationLength, sizeof(ULONG));
         }
-    }
-
-    return STATUS_INVALID_INFO_CLASS;
-}
 
-NTSTATUS
-NTAPI
-NtFlushInstructionCache(IN HANDLE ProcessHandle,
-                        IN PVOID BaseAddress,
-                        IN ULONG NumberOfBytesToFlush)
-{
-    PAGED_CODE();
+        /*
+         * Check the request is valid.
+         */
+        if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) &&
+            (SystemInformationClass < MAX_SYSTEM_INFO_CLASS))
+        {
+            if (NULL != CallQS [SystemInformationClass].Set)
+            {
+                /*
+                 * Hand the request to a subhandler.
+                 */
+                Status = CallQS [SystemInformationClass].Set(SystemInformation,
+                                                             SystemInformationLength);
+            }
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
 
-#if defined(_M_IX86) || defined(_M_AMD64)
-    __wbinvd();
-#elif defined(_M_PPC)
-    __asm__ __volatile__("tlbsync");
-#elif defined(_M_MIPS)
-    DPRINT1("NtFlushInstructionCache() is not implemented\n");
-    for (;;);
-#elif defined(_M_ARM)
-    __asm__ __volatile__("mov r1, #0; mcr p15, 0, r1, c7, c5, 0");
-#else
-#error Unknown architecture
-#endif
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 ULONG
 NTAPI
 NtGetCurrentProcessorNumber(VOID)
 {
-    /* Just return the CPU */
+    /* Just use Ke */
     return KeGetCurrentProcessorNumber();
 }
 
-/*
- * @implemented
- */
 #undef ExGetPreviousMode
 KPROCESSOR_MODE
 NTAPI
-ExGetPreviousMode (VOID)
+ExGetPreviousMode(VOID)
 {
+    /* Just use Ke */
     return KeGetPreviousMode();
 }