[NTOS] Addendum to d8cb37bf: return the correct Status from NtAllocateUuids().
[reactos.git] / ntoskrnl / ex / uuid.c
index 2a6343f..3c6e442 100644 (file)
@@ -227,9 +227,9 @@ ExpInitLuid(VOID)
 }
 
 
-NTSTATUS
+VOID
 NTAPI
-ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
+ExAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 {
     LARGE_INTEGER NewLuid, PrevLuid;
 
@@ -246,26 +246,24 @@ ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 
     LocallyUniqueId->LowPart = NewLuid.u.LowPart;
     LocallyUniqueId->HighPart = NewLuid.u.HighPart;
-
-    return STATUS_SUCCESS;
 }
 
 
 /*
  * @implemented
  */
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
 {
     LUID NewLuid;
     KPROCESSOR_MODE PreviousMode;
     NTSTATUS Status;
-
     PAGED_CODE();
 
+    /* Probe if user mode */
     PreviousMode = ExGetPreviousMode();
-
-    if(PreviousMode != KernelMode)
+    if (PreviousMode != KernelMode)
     {
         _SEH2_TRY
         {
@@ -280,18 +278,20 @@ NtAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId)
         _SEH2_END;
     }
 
-    Status = ExpAllocateLocallyUniqueId(&NewLuid);
+    /* Do the allocation */
+    ExAllocateLocallyUniqueId(&NewLuid);
+    Status = STATUS_SUCCESS;
 
+    /* Write back LUID to caller */
     _SEH2_TRY
     {
         *LocallyUniqueId = NewLuid;
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    _SEH2_EXCEPT(ExSystemExceptionFilter())
     {
         Status = _SEH2_GetExceptionCode();
     }
     _SEH2_END;
-
     return Status;
 }
 
@@ -319,9 +319,39 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
     ULARGE_INTEGER IntTime;
     ULONG IntRange;
     NTSTATUS Status;
+    KPROCESSOR_MODE PreviousMode;
 
     PAGED_CODE();
 
+    /* Probe if user mode */
+    PreviousMode = ExGetPreviousMode();
+    if (PreviousMode != KernelMode)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(Time,
+                          sizeof(ULARGE_INTEGER),
+                          sizeof(ULONG));
+
+            ProbeForWrite(Range,
+                          sizeof(ULONG),
+                          sizeof(ULONG));
+
+            ProbeForWrite(Sequence,
+                          sizeof(ULONG),
+                          sizeof(ULONG));
+
+            ProbeForWrite(Seed,
+                          SEED_BUFFER_SIZE,
+                          sizeof(UCHAR));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
+    }
+
     ExAcquireFastMutex(&UuidMutex);
 
     if (!UuidSequenceInitialized)
@@ -358,15 +388,26 @@ NtAllocateUuids(OUT PULARGE_INTEGER Time,
 
     ExReleaseFastMutex(&UuidMutex);
 
-    Time->QuadPart = IntTime.QuadPart;
-    *Range = IntRange;
-    *Sequence = UuidSequence;
+    /* Write back UUIDs to caller */
+    _SEH2_TRY
+    {
+        Time->QuadPart = IntTime.QuadPart;
+        *Range = IntRange;
+        *Sequence = UuidSequence;
 
-    RtlCopyMemory(Seed,
-                  UuidSeed,
-                  SEED_BUFFER_SIZE);
+        RtlCopyMemory(Seed,
+                      UuidSeed,
+                      SEED_BUFFER_SIZE);
 
-    return STATUS_SUCCESS;
+        Status = STATUS_SUCCESS;
+    }
+    _SEH2_EXCEPT(ExSystemExceptionFilter())
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    return Status;
 }
 
 
@@ -377,12 +418,58 @@ NTSTATUS
 NTAPI
 NtSetUuidSeed(IN PUCHAR Seed)
 {
+    NTSTATUS Status;
+    BOOLEAN GotContext;
+    PACCESS_TOKEN Token;
+    SECURITY_SUBJECT_CONTEXT SubjectContext;
+    LUID CallerLuid, SystemLuid = SYSTEM_LUID;
+
     PAGED_CODE();
 
-    RtlCopyMemory(UuidSeed,
-                  Seed,
-                  SEED_BUFFER_SIZE);
-    return STATUS_SUCCESS;
+    /* Should only be done by umode */
+    ASSERT(KeGetPreviousMode() != KernelMode);
+
+    /* No context to release */
+    GotContext = FALSE;
+    _SEH2_TRY
+    {
+        /* Get our caller context and remember to release it */
+        SeCaptureSubjectContext(&SubjectContext);
+        GotContext = TRUE;
+
+        /* Get caller access token and its associated ID */
+        Token = SeQuerySubjectContextToken(&SubjectContext);
+        Status = SeQueryAuthenticationIdToken(Token, &CallerLuid);
+        if (!NT_SUCCESS(Status))
+        {
+            RtlRaiseStatus(Status);
+        }
+
+        /* This call is only allowed for SYSTEM */
+        if (!RtlEqualLuid(&CallerLuid, &SystemLuid))
+        {
+            RtlRaiseStatus(STATUS_ACCESS_DENIED);
+        }
+
+        /* Check for buffer validity and then copy it to our seed */
+        ProbeForRead(Seed, SEED_BUFFER_SIZE, 1);
+        RtlCopyMemory(UuidSeed, Seed, SEED_BUFFER_SIZE);
+
+        Status = STATUS_SUCCESS;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    /* Release context if required */
+    if (GotContext)
+    {
+        SeReleaseSubjectContext(&SubjectContext);
+    }
+
+    return Status;
 }
 
 /* EOF */