Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / ntoskrnl / ex / sysinfo.c
index 11da146..0a6fb18 100644 (file)
@@ -14,7 +14,8 @@
 #define NDEBUG
 #include <debug.h>
 
-VOID MmPrintMemoryStatistic(VOID);
+/* The maximum size of an environment value (in bytes) */
+#define MAX_ENVVAL_SIZE 1024
 
 FAST_MUTEX ExpEnvironmentLock;
 ERESOURCE ExpFirmwareTableResource;
@@ -88,7 +89,7 @@ ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
                 }
 
                 /* Set the offset */
-                ModuleInfo->OffsetToFileName = p - ModuleName.Buffer;
+                ModuleInfo->OffsetToFileName = (USHORT)(p - ModuleName.Buffer);
             }
             else
             {
@@ -152,7 +153,7 @@ ExGetCurrentProcessorCpuUsage(PULONG CpuUsage)
 
     Prcb = KeGetCurrentPrcb();
 
-    ScaledIdle = Prcb->IdleThread->KernelTime * 100;
+    ScaledIdle = (ULONGLONG)Prcb->IdleThread->KernelTime * 100;
     TotalTime = Prcb->KernelTime + Prcb->UserTime;
     if (TotalTime != 0)
         *CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime));
@@ -213,27 +214,22 @@ NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName,
     ANSI_STRING AName;
     UNICODE_STRING WName;
     ARC_STATUS Result;
-    PCH Value;
+    PCH AnsiValueBuffer;
     ANSI_STRING AValue;
     UNICODE_STRING WValue;
     KPROCESSOR_MODE PreviousMode;
     NTSTATUS Status;
     PAGED_CODE();
 
+    /* Check if the call came from user mode */
     PreviousMode = ExGetPreviousMode();
-
     if (PreviousMode != KernelMode)
     {
         _SEH2_TRY
         {
-            ProbeForRead(VariableName,
-                         sizeof(UNICODE_STRING),
-                         sizeof(ULONG));
-
-            ProbeForWrite(ValueBuffer,
-                          ValueBufferLength,
-                          sizeof(WCHAR));
-
+            /* Probe the input and output buffers */
+            ProbeForRead(VariableName, sizeof(UNICODE_STRING), sizeof(ULONG));
+            ProbeForWrite(ValueBuffer, ValueBufferLength, sizeof(WCHAR));
             if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -244,101 +240,68 @@ NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName,
         _SEH2_END;
     }
 
-    /*
-     * Copy the name to kernel space if necessary and convert it to ANSI.
-     */
-    Status = ProbeAndCaptureUnicodeString(&WName,
-                                          PreviousMode,
-                                          VariableName);
-    if (NT_SUCCESS(Status))
+    /* According to NTInternals the SeSystemEnvironmentName privilege is required! */
+    if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, PreviousMode))
     {
-        /*
-         * according to ntinternals the SeSystemEnvironmentName privilege is required!
-         */
-        if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege,
-                                    PreviousMode))
-        {
-            ReleaseCapturedUnicodeString(&WName, PreviousMode);
-            DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
-            return STATUS_PRIVILEGE_NOT_HELD;
-        }
+        DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n");
+        return STATUS_PRIVILEGE_NOT_HELD;
+    }
 
-        /*
-         * convert the value name to ansi
-         */
-        Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
-        ReleaseCapturedUnicodeString(&WName, PreviousMode);
+    /* Copy the name to kernel space if necessary */
+    Status = ProbeAndCaptureUnicodeString(&WName, PreviousMode, VariableName);
+    if (!NT_SUCCESS(Status)) return Status;
 
-        if (!NT_SUCCESS(Status)) return Status;
+    /* Convert the name to ANSI and release the captured UNICODE string */
+    Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE);
+    ReleaseCapturedUnicodeString(&WName, PreviousMode);
+    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;
-        }
+    /* Allocate a buffer for the ANSI environment variable */
+    AnsiValueBuffer = ExAllocatePoolWithTag(NonPagedPool, MAX_ENVVAL_SIZE, 'rvnE');
+    if (AnsiValueBuffer == NULL)
+    {
+        RtlFreeAnsiString(&AName);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
 
-        /*
-         * Get the environment variable
-         */
-        Result = HalGetEnvironmentVariable(AName.Buffer,
-                                           (USHORT)ValueBufferLength,
-                                           Value);
-        if (!Result)
-        {
-            RtlFreeAnsiString(&AName);
-            ExFreePool(Value);
-            return STATUS_UNSUCCESSFUL;
-        }
+    /* Get the environment variable and free the ANSI name */
+    Result = HalGetEnvironmentVariable(AName.Buffer,
+                                       MAX_ENVVAL_SIZE,
+                                       AnsiValueBuffer);
+    RtlFreeAnsiString(&AName);
 
-        /*
-         * Convert the result to UNICODE, protect with SEH in case the value buffer
-         * isn't NULL-terminated!
-         */
+    /* Check if we had success */
+    if (Result == ESUCCESS)
+    {
+        /* Copy the result back to the caller. */
         _SEH2_TRY
         {
-            RtlInitAnsiString(&AValue, Value);
-            Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE);
+            /* Initialize ANSI string from the result */
+            RtlInitAnsiString(&AValue, AnsiValueBuffer);
+
+            /* Initialize a UNICODE string from the callers buffer */
+            RtlInitEmptyUnicodeString(&WValue, ValueBuffer, (USHORT)ValueBufferLength);
+
+            /* Convert the result to UNICODE */
+            Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, FALSE);
+
+            if (ReturnLength != NULL)
+                *ReturnLength = WValue.Length;
         }
         _SEH2_EXCEPT(ExSystemExceptionFilter())
         {
             Status = _SEH2_GetExceptionCode();
         }
         _SEH2_END;
-
-        if (NT_SUCCESS(Status))
-        {
-            /*
-             * Copy the result back to the caller.
-             */
-            _SEH2_TRY
-            {
-                RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length);
-                ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0';
-                if (ReturnLength != NULL)
-                {
-                    *ReturnLength = WValue.Length + sizeof(WCHAR);
-                }
-
-                Status = STATUS_SUCCESS;
-            }
-            _SEH2_EXCEPT(ExSystemExceptionFilter())
-            {
-                Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END;
-        }
-
-        /*
-         * Cleanup allocated resources.
-         */
-        RtlFreeAnsiString(&AName);
-        ExFreePool(Value);
+    }
+    else
+    {
+        Status = STATUS_UNSUCCESSFUL;
     }
 
+    /* Free the allocated ANSI value buffer */
+    ExFreePoolWithTag(AnsiValueBuffer, 'rvnE');
+
     return Status;
 }
 
@@ -458,6 +421,16 @@ static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize)
 #define SSI_DEF(n) \
 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size)
 
+VOID
+NTAPI
+ExQueryPoolUsage(OUT PULONG PagedPoolPages,
+                 OUT PULONG NonPagedPoolPages,
+                 OUT PULONG PagedPoolAllocs,
+                 OUT PULONG PagedPoolFrees,
+                 OUT PULONG PagedPoolLookasideHits,
+                 OUT PULONG NonPagedPoolAllocs,
+                 OUT PULONG NonPagedPoolFrees,
+                 OUT PULONG NonPagedPoolLookasideHits);
 
 /* Class 0 - Basic Information */
 QSI_DEF(SystemBasicInformation)
@@ -478,8 +451,8 @@ QSI_DEF(SystemBasicInformation)
     Sbi->TimerResolution = KeMaximumIncrement;
     Sbi->PageSize = PAGE_SIZE;
     Sbi->NumberOfPhysicalPages = MmNumberOfPhysicalPages;
-    Sbi->LowestPhysicalPageNumber = MmLowestPhysicalPage;
-    Sbi->HighestPhysicalPageNumber = MmHighestPhysicalPage;
+    Sbi->LowestPhysicalPageNumber = (ULONG)MmLowestPhysicalPage;
+    Sbi->HighestPhysicalPageNumber = (ULONG)MmHighestPhysicalPage;
     Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */
     Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */
     Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress;
@@ -494,7 +467,6 @@ QSI_DEF(SystemProcessorInformation)
 {
     PSYSTEM_PROCESSOR_INFORMATION Spi
         = (PSYSTEM_PROCESSOR_INFORMATION) Buffer;
-    PKPRCB Prcb;
 
     *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION);
 
@@ -503,7 +475,6 @@ QSI_DEF(SystemProcessorInformation)
     {
         return STATUS_INFO_LENGTH_MISMATCH;
     }
-    Prcb = KeGetCurrentPrcb();
     Spi->ProcessorArchitecture = KeProcessorArchitecture;
     Spi->ProcessorLevel = KeProcessorLevel;
     Spi->ProcessorRevision = KeProcessorRevision;
@@ -544,13 +515,12 @@ QSI_DEF(SystemPerformanceInformation)
     Spi->IoWriteOperationCount = IoWriteOperationCount;
     Spi->IoOtherOperationCount = IoOtherOperationCount;
 
-    Spi->AvailablePages = MmAvailablePages;
+    Spi->AvailablePages = (ULONG)MmAvailablePages;
     /*
      *   Add up all the used "Committed" memory + pagefile.
      *   Not sure this is right. 8^\
      */
-    Spi->CommittedPages = MiMemoryConsumers[MC_PPOOL].PagesUsed +
-                          MiMemoryConsumers[MC_NPPOOL].PagesUsed +
+    Spi->CommittedPages = MiMemoryConsumers[MC_SYSTEM].PagesUsed +
                           MiMemoryConsumers[MC_CACHE].PagesUsed +
                           MiMemoryConsumers[MC_USER].PagesUsed +
                           MiUsedSwapPages;
@@ -576,25 +546,31 @@ QSI_DEF(SystemPerformanceInformation)
     Spi->MappedPagesWriteCount = 0; /* FIXME */
     Spi->MappedWriteIoCount = 0; /* FIXME */
 
-    Spi->PagedPoolPages = MiMemoryConsumers[MC_PPOOL].PagesUsed;
-    Spi->PagedPoolAllocs = 0; /* FIXME */
-    Spi->PagedPoolFrees = 0; /* FIXME */
-    Spi->NonPagedPoolPages = MiMemoryConsumers[MC_NPPOOL].PagesUsed;
-    Spi->NonPagedPoolAllocs = 0; /* FIXME */
-    Spi->NonPagedPoolFrees = 0; /* FIXME */
-
+    Spi->PagedPoolPages = 0;
+    Spi->NonPagedPoolPages = 0;
+    Spi->PagedPoolAllocs = 0;
+    Spi->PagedPoolFrees = 0;
+    Spi->PagedPoolLookasideHits = 0;
+    Spi->NonPagedPoolAllocs = 0;
+    Spi->NonPagedPoolFrees = 0;
+    Spi->NonPagedPoolLookasideHits = 0;
+    ExQueryPoolUsage(&Spi->PagedPoolPages,
+                     &Spi->NonPagedPoolPages,
+                     &Spi->PagedPoolAllocs,
+                     &Spi->PagedPoolFrees,
+                     &Spi->PagedPoolLookasideHits,
+                     &Spi->NonPagedPoolAllocs,
+                     &Spi->NonPagedPoolFrees,
+                     &Spi->NonPagedPoolLookasideHits);
     Spi->FreeSystemPtes = 0; /* FIXME */
 
     Spi->ResidentSystemCodePage = 0; /* FIXME */
 
     Spi->TotalSystemDriverPages = 0; /* FIXME */
-    Spi->TotalSystemCodePages = 0; /* FIXME */
-    Spi->NonPagedPoolLookasideHits = 0; /* FIXME */
-    Spi->PagedPoolLookasideHits = 0; /* FIXME */
     Spi->Spare3Count = 0; /* FIXME */
 
     Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed;
-    Spi->ResidentPagedPoolPage = MiMemoryConsumers[MC_PPOOL].PagesUsed; /* FIXME */
+    Spi->ResidentPagedPoolPage = 0; /* FIXME */
 
     Spi->ResidentSystemDriverPage = 0; /* FIXME */
     Spi->CcFastReadNoWait = 0; /* FIXME */
@@ -716,7 +692,9 @@ QSI_DEF(SystemProcessInformation)
 
         /* Check for overflow */
         if (Size < sizeof(SYSTEM_PROCESS_INFORMATION))
+        {
             Overflow = TRUE;
+        }
 
         /* Zero user's buffer */
         if (!Overflow) RtlZeroMemory(Spi, Size);
@@ -729,9 +707,21 @@ QSI_DEF(SystemProcessInformation)
         {
             SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current;
 
+            if ((Process->ProcessExiting) &&
+                (Process->Pcb.Header.SignalState) &&
+                !(Process->ActiveThreads) &&
+                (IsListEmpty(&Process->Pcb.ThreadListHead)))
+            {
+                DPRINT1("Process %p (%s:%lx) is a zombie\n",
+                        Process, Process->ImageFileName, Process->UniqueProcessId);
+                CurrentSize = 0;
+                ImageNameMaximumLength = 0;
+                goto Skip;
+            }
+
             ThreadsCount = 0;
-            CurrentEntry = Process->ThreadListHead.Flink;
-            while (CurrentEntry != &Process->ThreadListHead)
+            CurrentEntry = Process->Pcb.ThreadListHead.Flink;
+            while (CurrentEntry != &Process->Pcb.ThreadListHead)
             {
                 ThreadsCount++;
                 CurrentEntry = CurrentEntry->Flink;
@@ -760,9 +750,9 @@ QSI_DEF(SystemProcessInformation)
                 }
               }
             }
-            if (!ImageNameLength && Process != PsIdleProcess && Process->ImageFileName)
+            if (!ImageNameLength && Process != PsIdleProcess)
             {
-              ImageNameLength = strlen(Process->ImageFileName) * sizeof(WCHAR);
+              ImageNameLength = (USHORT)strlen(Process->ImageFileName) * sizeof(WCHAR);
             }
 
             /* Round up the image name length as NT does */
@@ -775,7 +765,9 @@ QSI_DEF(SystemProcessInformation)
 
             /* Check for overflow */
             if (TotalSize > Size)
+            {
                 Overflow = TRUE;
+            }
 
             /* Fill system information */
             if (!Overflow)
@@ -795,9 +787,9 @@ QSI_DEF(SystemProcessInformation)
                         RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length);
 
                         /* Release the memory allocated by SeLocateProcessImageName */
-                        ExFreePool(ProcessImageName);
+                        ExFreePoolWithTag(ProcessImageName, TAG_SEPA);
                     }
-                    else if (Process->ImageFileName)
+                    else
                     {
                         RtlInitAnsiString(&ImageName, Process->ImageFileName);
                         RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE);
@@ -826,10 +818,10 @@ QSI_DEF(SystemProcessInformation)
                 SpiCurrent->PrivatePageCount = Process->CommitCharge;
                 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1);
 
-                CurrentEntry = Process->ThreadListHead.Flink;
-                while (CurrentEntry != &Process->ThreadListHead)
+                CurrentEntry = Process->Pcb.ThreadListHead.Flink;
+                while (CurrentEntry != &Process->Pcb.ThreadListHead)
                 {
-                    CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD,
+                    CurrentThread = (PETHREAD)CONTAINING_RECORD(CurrentEntry, KTHREAD,
                         ThreadListEntry);
 
                     ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement);
@@ -855,6 +847,7 @@ QSI_DEF(SystemProcessInformation)
             }
 
             /* Handle idle process entry */
+Skip:
             if (Process == PsIdleProcess) Process = NULL;
 
             Process = PsGetNextProcess(Process);
@@ -931,7 +924,6 @@ QSI_DEF(SystemProcessorPerformanceInformation)
 
     LONG i;
     ULONG TotalTime;
-    LARGE_INTEGER CurrentTime;
     PKPRCB Prcb;
 
     *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
@@ -942,7 +934,6 @@ QSI_DEF(SystemProcessorPerformanceInformation)
         return STATUS_INFO_LENGTH_MISMATCH;
     }
 
-    CurrentTime.QuadPart = KeQueryInterruptTime();
     for (i = 0; i < KeNumberProcessors; i++)
     {
         /* Get the PRCB on this processor */
@@ -1229,9 +1220,8 @@ SSI_DEF(SystemFileCacheInformation)
 /* Class 22 - Pool Tag Information */
 QSI_DEF(SystemPoolTagInformation)
 {
-    /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
-    return STATUS_NOT_IMPLEMENTED;
+    if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
+    return ExGetPoolTagInfo(Buffer, Size, ReqSize);
 }
 
 /* Class 23 - Interrupt Information for all processors */
@@ -1303,10 +1293,6 @@ QSI_DEF(SystemFullMemoryInformation)
            MiFreeSwapPages,
            MiUsedSwapPages);
 
-#ifndef NDEBUG
-    MmPrintMemoryStatistic();
-#endif
-
     *Spi = MiMemoryConsumers[MC_USER].PagesUsed;
 
     return STATUS_SUCCESS;
@@ -1402,7 +1388,7 @@ QSI_DEF(SystemTimeAdjustmentInformation)
     /* Give time values to our caller */
     TimeInfo->TimeIncrement = KeMaximumIncrement;
     TimeInfo->TimeAdjustment = KeTimeAdjustment;
-    TimeInfo->Enable = TRUE;
+    TimeInfo->Enable = !KiTimeAdjustmentEnabled;
 
     return STATUS_SUCCESS;
 }
@@ -1410,8 +1396,8 @@ QSI_DEF(SystemTimeAdjustmentInformation)
 SSI_DEF(SystemTimeAdjustmentInformation)
 {
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
-        (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/
+    PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo =
+        (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;
 
     /* Check size of a buffer, it must match our expectations */
     if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size)
@@ -1427,9 +1413,24 @@ SSI_DEF(SystemTimeAdjustmentInformation)
         }
     }
 
-    /* TODO: Set time adjustment information */
-    DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n");
-    return STATUS_NOT_IMPLEMENTED;
+    /* FIXME: behaviour suggests the member be named 'Disable' */
+    if (TimeInfo->Enable)
+    {
+        /* Disable time adjustment and set default value */
+        KiTimeAdjustmentEnabled = FALSE;
+        KeTimeAdjustment = KeMaximumIncrement;
+    }
+    else
+    {
+        /* Check if a valid time adjustment value is given */
+        if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2;
+
+        /* Enable time adjustment and set the adjustment value */
+        KiTimeAdjustmentEnabled = TRUE;
+        KeTimeAdjustment = TimeInfo->TimeAdjustment;
+    }
+
+    return STATUS_SUCCESS;
 }
 
 /* Class 29 - Summary Memory Information */
@@ -1470,8 +1471,9 @@ QSI_DEF(SystemExceptionInformation)
     PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation =
         (PSYSTEM_EXCEPTION_INFORMATION)Buffer;
     PKPRCB Prcb;
-    ULONG i, AlignmentFixupCount = 0, ExceptionDispatchCount = 0;
+    ULONG AlignmentFixupCount = 0, ExceptionDispatchCount = 0;
     ULONG FloatingEmulationCount = 0, ByteWordEmulationCount = 0;
+    CHAR i;
 
     /* Check size of a buffer, it must match our expectations */
     if (sizeof(SYSTEM_EXCEPTION_INFORMATION) != Size)
@@ -1528,8 +1530,9 @@ QSI_DEF(SystemContextSwitchInformation)
 {
     PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation =
         (PSYSTEM_CONTEXT_SWITCH_INFORMATION)Buffer;
-    ULONG ContextSwitches, i;
+    ULONG ContextSwitches;
     PKPRCB Prcb;
+    CHAR i;
 
     /* Check size of a buffer, it must match our expectations */
     if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION) != Size)
@@ -1749,22 +1752,57 @@ SSI_DEF(SystemSetTimeSlipEvent)
     return STATUS_NOT_IMPLEMENTED;
 }
 
+NTSTATUS
+NTAPI
+MmSessionCreate(OUT PULONG SessionId);
+
+NTSTATUS
+NTAPI
+MmSessionDelete(IN ULONG SessionId);
 
 /* Class 47 - Create a new session (TSE) */
 SSI_DEF(SystemCreateSession)
 {
-    /* FIXME */
-    DPRINT1("NtSetSystemInformation - SystemCreateSession not implemented\n");
-    return STATUS_NOT_IMPLEMENTED;
+    ULONG SessionId;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    NTSTATUS Status;
+
+    if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
+
+    if (PreviousMode != KernelMode)
+    {
+        if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
+        {
+            return STATUS_PRIVILEGE_NOT_HELD;
+        }
+    }
+
+    Status = MmSessionCreate(&SessionId);
+    if (NT_SUCCESS(Status)) *(PULONG)Buffer = SessionId;
+
+    return Status;
 }
 
 
 /* Class 48 - Delete an existing session (TSE) */
 SSI_DEF(SystemDeleteSession)
 {
-    /* FIXME */
-    DPRINT1("NtSetSystemInformation - SystemDeleteSession not implemented\n");
-    return STATUS_NOT_IMPLEMENTED;
+    ULONG SessionId;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+
+    if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
+
+    if (PreviousMode != KernelMode)
+    {
+        if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
+        {
+            return STATUS_PRIVILEGE_NOT_HELD;
+        }
+    }
+
+    SessionId = *(PULONG)Buffer;
+
+    return MmSessionDelete(SessionId);
 }
 
 
@@ -1780,11 +1818,15 @@ QSI_DEF(SystemInvalidInfoClass4)
 /* Class 50 - System range start address */
 QSI_DEF(SystemRangeStartInformation)
 {
-    /* FIXME */
-    DPRINT1("NtQuerySystemInformation - SystemRangeStartInformation not implemented\n");
-    return STATUS_NOT_IMPLEMENTED;
-}
+    /* Check user buffer's size */
+    if (Size != sizeof(ULONG_PTR)) return STATUS_INFO_LENGTH_MISMATCH;
+
+    *(PULONG_PTR)Buffer = (ULONG_PTR)MmSystemRangeStart;
 
+    if (ReqSize) *ReqSize = sizeof(ULONG_PTR);
+
+    return STATUS_SUCCESS;
+}
 
 /* Class 51 - Driver verifier information */
 QSI_DEF(SystemVerifierInformation)
@@ -1947,17 +1989,10 @@ NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
             FStatus = CallQS [SystemInformationClass].Query(SystemInformation,
                                                             Length,
                                                             &ResultLength);
-            if (UnsafeResultLength != NULL)
-            {
-                if (PreviousMode != KernelMode)
-                {
-                    *UnsafeResultLength = ResultLength;
-                }
-                else
-                {
-                    *UnsafeResultLength = ResultLength;
-                }
-            }
+
+            /* Save the result length to the caller */
+            if (UnsafeResultLength)
+                *UnsafeResultLength = ResultLength;
         }
     }
     _SEH2_EXCEPT(ExSystemExceptionFilter())