[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / ex / sysinfo.c
index a31be14..6d99e0a 100644 (file)
@@ -918,8 +918,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);
@@ -1081,6 +1080,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;
 }
@@ -1292,9 +1297,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;
     }
 
@@ -1559,11 +1565,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;
 }
 
@@ -1820,35 +1826,42 @@ SSI_DEF(SystemPrioritySeperation)
     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;
 }
 
@@ -2031,10 +2044,10 @@ Leave:
 
 
 /* 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;
 }
 
@@ -2047,7 +2060,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();
@@ -2061,6 +2074,8 @@ SSI_DEF(SystemCreateSession)
         {
             return STATUS_PRIVILEGE_NOT_HELD;
         }
+
+        ProbeForWriteUlong(Buffer);
     }
 
     Status = MmSessionCreate(&SessionId);
@@ -2071,7 +2086,7 @@ SSI_DEF(SystemCreateSession)
 
 
 /* Class 48 - Delete an existing session (TSE) */
-SSI_DEF(SystemDeleteSession)
+SSI_DEF(SystemSessionDetach)
 {
     ULONG SessionId;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
@@ -2093,10 +2108,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;
 }
 
@@ -2131,11 +2146,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;
 }
 
@@ -2149,6 +2164,144 @@ 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;
+}
+
+
 /* Query/Set Calls Table */
 typedef
 struct _QSSI_CALLS
@@ -2177,55 +2330,62 @@ CallQS [] =
     SI_QX(SystemPerformanceInformation),
     SI_QX(SystemTimeOfDayInformation),
     SI_QX(SystemPathInformation), /* should be SI_XX */
-    SI_QX(SystemProcessInformation),  // aka SystemProcessesAndThreadsInformation
-    SI_QX(SystemCallCountInformation), // aka SystemCallCounts
-    SI_QX(SystemDeviceInformation), // aka SystemConfigurationInformation
-    SI_QX(SystemProcessorPerformanceInformation), // aka SystemProcessorTimes
-    SI_QS(SystemFlagsInformation), // aka SystemGlobalFlag
+    SI_QX(SystemProcessInformation),
+    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), // aka SystemLockInformation
+    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), // aka SystemPagefileInformation
-    SI_QX(SystemVdmInstemulInformation), // aka SystemInstructionEmulationCounts
+    SI_QX(SystemPageFileInformation),
+    SI_QX(SystemVdmInstemulInformation),
     SI_QX(SystemVdmBopInformation), /* it should be SI_XX */
-    SI_QS(SystemFileCacheInformation), // aka SystemCacheInformation
+    SI_QS(SystemFileCacheInformation),
     SI_QX(SystemPoolTagInformation),
-    SI_QX(SystemInterruptInformation), // aka SystemProcessorStatistics
-    SI_QS(SystemDpcBehaviourInformation), // aka SystemDpcInformation
+    SI_QX(SystemInterruptInformation),
+    SI_QS(SystemDpcBehaviourInformation),
     SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */
-    SI_XS(SystemLoadGdiDriverInformation), // correct: SystemLoadImage
-    SI_XS(SystemUnloadGdiDriverInformation), // correct: SystemUnloadImage
-    SI_QS(SystemTimeAdjustmentInformation), // aka SystemTimeAdjustment
+    SI_XS(SystemLoadGdiDriverInformation),
+    SI_XS(SystemUnloadGdiDriverInformation),
+    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 */ // SystemPerformanceTraceInformation
+    SI_QX(SystemPerformanceTraceInformation), /* 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(SystemExtendServiceTableInformation), // correct: SystemLoadAndCallImage
+    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 */ // SystemPowerInformationNative? SystemInvalidInfoClass2
-    SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */
-    SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */ // aka SystemTimeZoneInformation
+    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 */ // SystemSessionInformation?
+    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)
 };
 
 C_ASSERT(SystemBasicInformation == 0);
@@ -2280,7 +2440,7 @@ NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
                                                             &ResultLength);
 
             /* Save the result length to the caller */
-            if (UnsafeResultLength)
+            if (NT_SUCCESS(FStatus) && UnsafeResultLength)
                 *UnsafeResultLength = ResultLength;
         }
     }
@@ -2300,43 +2460,47 @@ 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));
+        }
+
+        /*
+         * 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;
 
-    return STATUS_INVALID_INFO_CLASS;
+    return Status;
 }
 
 NTSTATUS