[ros-diffs] [sir_richard] 46028: [NTOS]: While attempting to ressucitate the user-mode shutdown code in CSRSS (disabled since 2006), it seemed clear that one of the main steps is to obtain the caller's LUID in order to kill the right processes. This LUID is obtained from the current thread's token, and we know it's the callers since we're supposed to impersonate the caller. Unfortunately, impersonation failed, making the whole process fail. Impersonation failed because NtImpersonateThread was actually inverting the THREAD_IMPERSONATE rights, asking the client thread for the server's permissions, and vice versa. Fixing this resulted in yet another failure. Analysis of this failure showed that even opening the server (ie: current) thread for THREAD_DIRECT_IMPERSONATION failed, which is unusual since the current thread should have access to all its rights. This is determined in PspCreateThread when the ETHREAD->GrantedAccess field is set. Continuing onto this path, tracing revealed that GrantedAccess was merely 0x1607F and not 0x1F3FF as expected, meaning that not all rights were given, including the impersonate right (0x200), explaining the failure, but not the deeper reason behind it. Attempting to identify which code path set this GrantedAccess, the SepAccessCheck routine came to light. A bug there caused MAXIMUM_ALLOWED accesses to fail in certain scenarios, such as when the object had no security descriptor, because MAXIMUM_ALLOWED would be granted as an absolute value, when instead of it is a flag that should grant GENERIC_ALL. Fixing that bug, the failure continued. Further analysis identified that the Administrators SID was being found with GENERIC_READ + WRITE + EXECUTE access, and no SID was found for GENERIC_ALL access. This happened when searching the system token's default DACL, which is assigned to the kernel (but for kernel-mode callers, this check was skipped), smss, winlogon, etc. The code for creating this system token was heavily hacked, so the function to create the system token, as well as NtCreateToken were refactored to use a common piece of token-creating code. Furthermode, the system token was correctly created with Local System as the user, and Administrators as one of the groups. Finally, SeDefaultDacl was used (already setup properly) instead of a badly configured Default DACL. The new shared code also correctly sets the SE_GROUP_ENABLED flag on all SE_GROUP_MANDATORY groups, and scans tokens to set the TOKEN_HAS_ADMIN_GROUP and TOKEN_HAS_TRAVERSE_PRIVILEGE flags which were not previously set. With the correct system token and default DACL, the Local System SID was now found, but the failure continued. This was revealed to be due to an even deeper rooted problem, as the SepIsSidInToken routine checked for SE_GROUP_ENABLED before listing a SID as "present". Although this is correct for actual groups, the User SID will never have the SE_GROUP_ENABLED flag as it is not a group. This caused any granted access ACE belonging to a user (instead of a group) to be ignored, causing either access check failures, or limited rights returned (in the MAXIMUM_ALLOWED case). Upon fixing this bug, the NtImpersonateThread call finally returned success, since the rights were now correct. Promptly upon calling NtOpenThreadToken to query the LUID however, the system ASSERTED with FALSE. The code at fault was a line in NtOpenThreadTokenEx which forcefully ASSERTed if the impersonation code path was taken, presumably because this was never tested, and ReactOS would actually always fail impersonation attempts due to the bugs fixed above. This routine was thus quickly reworked to fix some mistakes (such as forgetting to actually impersonate the client, incorrect referencing/dereferencing of thread/tokens, and assumptions about DACL creation success). Having fixed the NtOpenThreadTokenEx routine, the LUID query now went through for the impersonated token, but soon causing a user-mode crash, due to an incorrect parameter reference in the CsrGetProcessLuid function in the csrsrv code by Alex (which I copy/pasted to reduce code duplication). Fixing this final bug finally allowed the correct LUID to be queried and I was able to continue development of not-yet-commited user-mode shutdown code.

sir_richard at svn.reactos.org sir_richard at svn.reactos.org
Tue Mar 9 11:35:59 CET 2010


Author: sir_richard
Date: Tue Mar  9 11:35:58 2010
New Revision: 46028

URL: http://svn.reactos.org/svn/reactos?rev=46028&view=rev
Log:
[NTOS]: While attempting to ressucitate the user-mode shutdown code in CSRSS (disabled since 2006), it seemed clear that one of the main steps is to obtain the caller's LUID in order to kill the right processes. This LUID is obtained from the current thread's token, and we know it's the callers since we're supposed to impersonate the caller. Unfortunately, impersonation failed, making the whole process fail.
        Impersonation failed because NtImpersonateThread was actually inverting the THREAD_IMPERSONATE rights, asking the client thread for the server's permissions, and vice versa. Fixing this resulted in yet another failure.
        Analysis of this failure showed that even opening the server (ie: current) thread for THREAD_DIRECT_IMPERSONATION failed, which is unusual since the current thread should have access to all its rights. This is determined in PspCreateThread when the ETHREAD->GrantedAccess field is set.
        Continuing onto this path, tracing revealed that GrantedAccess was merely 0x1607F and not 0x1F3FF as expected, meaning that not all rights were given, including the impersonate right (0x200), explaining the failure, but not the deeper reason behind it.
        Attempting to identify which code path set this GrantedAccess, the SepAccessCheck routine came to light. A bug there caused MAXIMUM_ALLOWED accesses to fail in certain scenarios, such as when the object had no security descriptor, because MAXIMUM_ALLOWED would be granted as an absolute value, when instead of it is a flag that should grant GENERIC_ALL. Fixing that bug, the failure continued.
        Further analysis identified that the Administrators SID was being found with GENERIC_READ + WRITE + EXECUTE access, and no SID was found for GENERIC_ALL access. This happened when searching the system token's default DACL, which is assigned to the kernel (but for kernel-mode callers, this check was skipped), smss, winlogon, etc.
        The code for creating this system token was heavily hacked, so the function to create the system token, as well as NtCreateToken were refactored to use a common piece of token-creating code. Furthermode, the system token was correctly created with Local System as the user, and Administrators as one of the groups. Finally, SeDefaultDacl was used (already setup properly) instead of a badly configured Default DACL. The new shared code also correctly sets the SE_GROUP_ENABLED flag on all SE_GROUP_MANDATORY groups, and scans tokens to set the TOKEN_HAS_ADMIN_GROUP and TOKEN_HAS_TRAVERSE_PRIVILEGE flags which were not previously set.
        With the correct system token and default DACL, the Local System SID was now found, but the failure continued. This was revealed to be due to an even deeper rooted problem, as the SepIsSidInToken routine checked for SE_GROUP_ENABLED before listing a SID as "present". Although this is correct for actual groups, the User SID will never have the SE_GROUP_ENABLED flag as it is not a group. This caused any granted access ACE belonging to a user (instead of a group) to be ignored, causing either access check failures, or limited rights returned (in the MAXIMUM_ALLOWED case).
        Upon fixing this bug, the NtImpersonateThread call finally returned success, since the rights were now correct. Promptly upon calling NtOpenThreadToken to query the LUID however, the system ASSERTED with FALSE.
        The code at fault was a line in NtOpenThreadTokenEx which forcefully ASSERTed if the impersonation code path was taken, presumably because this was never tested, and ReactOS would actually always fail impersonation attempts due to the bugs fixed above. This routine was thus quickly reworked to fix some mistakes (such as forgetting to actually impersonate the client, incorrect referencing/dereferencing of thread/tokens, and assumptions about DACL creation success).
        Having fixed the NtOpenThreadTokenEx routine, the LUID query now went through for the impersonated token, but soon causing a user-mode crash, due to an incorrect parameter reference in the CsrGetProcessLuid function in the csrsrv code by Alex (which I copy/pasted to reduce code duplication).
        Fixing this final bug finally allowed the correct LUID to be queried and I was able to continue development of not-yet-commited user-mode shutdown code.

Modified:
    trunk/reactos/ntoskrnl/po/povolume.c
    trunk/reactos/ntoskrnl/ps/security.c
    trunk/reactos/ntoskrnl/se/semgr.c
    trunk/reactos/ntoskrnl/se/token.c
    trunk/reactos/subsystems/csr/csrsrv/process.c

Modified: trunk/reactos/ntoskrnl/po/povolume.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/povolume.c?rev=46028&r1=46027&r2=46028&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/po/povolume.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/po/povolume.c [iso-8859-1] Tue Mar  9 11:35:58 2010
@@ -84,16 +84,13 @@
     PAGED_CODE();
 
     /* Get dope from the device (if the device has no dope, it will receive some) */
-    DPRINT1("New volume: %p\n", DeviceObject);
     Dope = PopGetDope(DeviceObject);
     if (Dope)
     {
         /* Make sure we can flush safely */
-        DPRINT1("Acquiring volume lock\n");
         KeAcquireGuardedMutex(&PopVolumeLock);
 
         /* Add this volume into the list of power-manager volumes */
-        DPRINT1("Got DOPE: %p\n", Dope);
         if (!Dope->Volume.Flink) InsertTailList(&PopVolumeDevices, &Dope->Volume);
         
         /* Allow flushes to go through */

Modified: trunk/reactos/ntoskrnl/ps/security.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/security.c?rev=46028&r1=46027&r2=46028&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ps/security.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ps/security.c [iso-8859-1] Tue Mar  9 11:35:58 2010
@@ -965,32 +965,32 @@
 
     /* Reference the thread */
     Status = ObReferenceObjectByHandle(ThreadHandle,
-                                       THREAD_IMPERSONATE,
+                                       THREAD_DIRECT_IMPERSONATION,
                                        PsThreadType,
                                        PreviousMode,
                                        (PVOID*)&Thread,
                                        NULL);
-    if(NT_SUCCESS(Status))
+    if (NT_SUCCESS(Status))
     {
         /* Reference the impersonating thead */
         Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
-                                           THREAD_DIRECT_IMPERSONATION,
+                                           THREAD_IMPERSONATE,
                                            PsThreadType,
                                            PreviousMode,
                                            (PVOID*)&ThreadToImpersonate,
                                            NULL);
-        if(NT_SUCCESS(Status))
+        if (NT_SUCCESS(Status))
         {
             /* Create a client security context */
             Status = SeCreateClientSecurity(ThreadToImpersonate,
                                             SecurityQualityOfService,
                                             0,
                                             &ClientContext);
-            if(NT_SUCCESS(Status))
+            if (NT_SUCCESS(Status))
             {
                 /* Do the impersonation */
                 SeImpersonateClient(&ClientContext, Thread);
-                if(ClientContext.ClientToken)
+                if (ClientContext.ClientToken)
                 {
                     /* Dereference the client token if we had one */
                     ObDereferenceObject(ClientContext.ClientToken);

Modified: trunk/reactos/ntoskrnl/se/semgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/semgr.c?rev=46028&r1=46027&r2=46028&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/semgr.c [iso-8859-1] Tue Mar  9 11:35:58 2010
@@ -279,6 +279,7 @@
     return STATUS_SUCCESS;
 }
 
+ULONG SidInTokenCalls = 0;
 
 static BOOLEAN
 SepSidInToken(PACCESS_TOKEN _Token,
@@ -289,6 +290,9 @@
 
     PAGED_CODE();
 
+    SidInTokenCalls++;
+    if (!(SidInTokenCalls % 10000)) DPRINT1("SidInToken Calls: %d\n", SidInTokenCalls);
+    
     if (Token->UserAndGroupCount == 0)
     {
         return FALSE;
@@ -298,7 +302,7 @@
     {
         if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid))
         {
-            if (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED)
+            if ((i == 0)|| (Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED))
             {
                 return TRUE;
             }
@@ -470,7 +474,16 @@
             SeUnlockSubjectContext(SubjectSecurityContext);
         }
 
-        *GrantedAccess = DesiredAccess;
+        if (DesiredAccess & MAXIMUM_ALLOWED)
+        {
+            *GrantedAccess = GenericMapping->GenericAll;
+            *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
+        }
+        else
+        {
+            *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
+        }
+        
         *AccessStatus = STATUS_SUCCESS;
         return TRUE;
     }

Modified: trunk/reactos/ntoskrnl/se/token.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=46028&r1=46027&r2=46028&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] Tue Mar  9 11:35:58 2010
@@ -21,6 +21,9 @@
 
 POBJECT_TYPE SepTokenObjectType = NULL;
 ERESOURCE SepTokenLock;
+
+TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
+LUID SeSystemAuthenticationId = SYSTEM_LUID;
 
 static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ,
     TOKEN_WRITE,
@@ -244,7 +247,7 @@
                             (PVOID*)&AccessToken);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("ObCreateObject() failed (Status %lx)\n");
+        DPRINT1("ObCreateObject() failed (Status %lx)\n", Status);
         return(Status);
     }
 
@@ -510,34 +513,80 @@
     ObInitializeFastReference(&Process->Token, Token);
 }
 
-PTOKEN
+
+NTSTATUS
 NTAPI
-SepCreateSystemProcessToken(VOID)
-{
+SepCreateToken(OUT PHANDLE TokenHandle,
+              IN KPROCESSOR_MODE PreviousMode,
+              IN ACCESS_MASK DesiredAccess,
+              IN POBJECT_ATTRIBUTES ObjectAttributes,
+              IN TOKEN_TYPE TokenType,
+              IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+              IN PLUID AuthenticationId,
+              IN PLARGE_INTEGER ExpirationTime,
+              IN PSID_AND_ATTRIBUTES User,
+              IN ULONG GroupCount,
+              IN PSID_AND_ATTRIBUTES Groups,
+              IN ULONG GroupLength,
+              IN ULONG PrivilegeCount,
+              IN PLUID_AND_ATTRIBUTES Privileges,
+              IN PSID Owner,
+              IN PSID PrimaryGroup,
+              IN PACL DefaultDacl,
+              IN PTOKEN_SOURCE TokenSource,
+              IN BOOLEAN SystemToken)
+{                  
+    PTOKEN AccessToken;
+    LUID TokenId;
+    LUID ModifiedId;
+    PVOID EndMem;
+    ULONG uLength;
+    ULONG i;
     NTSTATUS Status;
-    ULONG uSize;
-    ULONG i;
-    ULONG uLocalSystemLength;
-    ULONG uWorldLength;
-    ULONG uAuthUserLength;
-    ULONG uAdminsLength;
-    PTOKEN AccessToken;
-    PVOID SidArea;
-    
-    PAGED_CODE();
-    
-    uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
-    uWorldLength       = RtlLengthSid(SeWorldSid);
-    uAuthUserLength    = RtlLengthSid(SeAuthenticatedUserSid);
-    uAdminsLength      = RtlLengthSid(SeAliasAdminsSid);
-    
-    /*
-     * Initialize the token
-     */
-    Status = ObCreateObject(KernelMode,
+    ULONG TokenFlags = 0;
+    
+    /* Loop all groups */
+    for (i = 0; i < GroupCount; i++)
+    {
+        /* Check for mandatory groups */
+        if (Groups[i].Attributes & SE_GROUP_MANDATORY)
+        {
+            /* Force them to be enabled */
+            Groups[i].Attributes |= (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT);
+        }
+        
+        /* Check of the group is an admin group */
+        if (RtlEqualSid(SeAliasAdminsSid, Groups[i].Sid))
+        {
+            /* Remember this so we can optimize queries later */
+            TokenFlags |= TOKEN_HAS_ADMIN_GROUP;
+        }
+    }
+    
+    /* Loop all privileges */
+    for (i = 0; i < PrivilegeCount; i++)
+    {
+        /* For optimization, check for change notify and impersonate rights */
+        if (((RtlEqualLuid(&Privileges[i].Luid, &SeChangeNotifyPrivilege)) &&
+            (Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)))
+        {
+            /* Remember token has traverse */
+            TokenFlags |= TOKEN_HAS_TRAVERSE_PRIVILEGE;
+        }
+    }
+
+    Status = ZwAllocateLocallyUniqueId(&TokenId);
+    if (!NT_SUCCESS(Status))
+        return(Status);
+    
+    Status = ZwAllocateLocallyUniqueId(&ModifiedId);
+    if (!NT_SUCCESS(Status))
+        return(Status);
+    
+    Status = ObCreateObject(PreviousMode,
                             SepTokenObjectType,
-                            NULL,
-                            KernelMode,
+                            ObjectAttributes,
+                            PreviousMode,
                             NULL,
                             sizeof(TOKEN),
                             0,
@@ -545,180 +594,279 @@
                             (PVOID*)&AccessToken);
     if (!NT_SUCCESS(Status))
     {
-        return NULL;
+        DPRINT1("ObCreateObject() failed (Status %lx)\n");
+        return(Status);
     }
 
     /* Zero out the buffer */
     RtlZeroMemory(AccessToken, sizeof(TOKEN));
     
-    Status = ExpAllocateLocallyUniqueId(&AccessToken->TokenId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
-    
-    Status = ExpAllocateLocallyUniqueId(&AccessToken->ModifiedId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
-    
-    Status = ExpAllocateLocallyUniqueId(&AccessToken->AuthenticationId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
-    
     AccessToken->TokenLock = &SepTokenLock;
     
-    AccessToken->TokenType = TokenPrimary;
-    AccessToken->ImpersonationLevel = SecurityDelegation;
-    memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
-    AccessToken->ExpirationTime.QuadPart = -1;
-    AccessToken->UserAndGroupCount = 4;
-    
-    uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
-    uSize += uLocalSystemLength;
-    uSize += uWorldLength;
-    uSize += uAuthUserLength;
-    uSize += uAdminsLength;
+    RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
+                &TokenSource->SourceIdentifier);
+    memcpy(AccessToken->TokenSource.SourceName,
+           TokenSource->SourceName,
+           sizeof(TokenSource->SourceName));
+    
+    RtlCopyLuid(&AccessToken->TokenId, &TokenId);
+    RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
+    AccessToken->ExpirationTime = *ExpirationTime;
+    RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
+    
+    AccessToken->UserAndGroupCount = GroupCount + 1;
+    AccessToken->PrivilegeCount = PrivilegeCount;
+    
+    AccessToken->TokenFlags = TokenFlags;
+    AccessToken->TokenType = TokenType;
+    AccessToken->ImpersonationLevel = ImpersonationLevel;
+    
+    /*
+     * Normally we would just point these members into the variable information
+     * area; however, our ObCreateObject() call can't allocate a variable information
+     * area, so we allocate them seperately and provide a destroy function.
+     */
+    
+    uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
+    uLength += RtlLengthSid(User);
+    for (i = 0; i < GroupCount; i++)
+        uLength += RtlLengthSid(Groups[i].Sid);
     
     AccessToken->UserAndGroups =
     (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
-                                               uSize,
+                                               uLength,
                                                'uKOT');
-    SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
-    
+    
+    EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
+    
+    Status = RtlCopySidAndAttributesArray(1,
+                                          User,
+                                          uLength,
+                                          AccessToken->UserAndGroups,
+                                          EndMem,
+                                          &EndMem,
+                                          &uLength);
+    if (NT_SUCCESS(Status))
+    {
+        Status = RtlCopySidAndAttributesArray(GroupCount,
+                                              Groups,
+                                              uLength,
+                                              &AccessToken->UserAndGroups[1],
+                                              EndMem,
+                                              &EndMem,
+                                              &uLength);
+    }
+    
+    if (NT_SUCCESS(Status))
+    {
+        Status = SepFindPrimaryGroupAndDefaultOwner(
+                                                    AccessToken,
+                                                    PrimaryGroup,
+                                                    Owner);
+    }
+    
+    if (NT_SUCCESS(Status))
+    {
+        uLength = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+        AccessToken->Privileges =
+        (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
+                                                    uLength,
+                                                    'pKOT');
+        
+        if (PreviousMode != KernelMode)
+        {
+            _SEH2_TRY
+            {
+                RtlCopyMemory(AccessToken->Privileges,
+                              Privileges,
+                              PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                Status = _SEH2_GetExceptionCode();
+            }
+            _SEH2_END;
+        }
+        else
+        {
+            RtlCopyMemory(AccessToken->Privileges,
+                          Privileges,
+                          PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
+        }
+    }
+    
+    if (NT_SUCCESS(Status))
+    {
+        AccessToken->DefaultDacl =
+        (PACL) ExAllocatePoolWithTag(PagedPool,
+                                     DefaultDacl->AclSize,
+                                     'kDOT');
+        memcpy(AccessToken->DefaultDacl,
+               DefaultDacl,
+               DefaultDacl->AclSize);
+    }
+    
+    if (!SystemToken)
+    {
+        
+        Status = ObInsertObject ((PVOID)AccessToken,
+                                 NULL,
+                                 DesiredAccess,
+                                 0,
+                                 NULL,
+                                 TokenHandle);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("ObInsertObject() failed (Status %lx)\n", Status);
+        }
+    }
+    else
+    {
+        /* Return pointer instead of handle */
+        *TokenHandle = (HANDLE)AccessToken;
+    }
+
+    return Status;
+}
+
+PTOKEN
+NTAPI
+SepCreateSystemProcessToken(VOID)
+{
+    LUID_AND_ATTRIBUTES Privileges[25];
+    ULONG GroupAttributes, OwnerAttributes;
+    SID_AND_ATTRIBUTES Groups[32];
+    LARGE_INTEGER Expiration;
+    SID_AND_ATTRIBUTES UserSid;
+    ULONG GroupLength;
+    PSID PrimaryGroup;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PSID Owner;
+    ULONG i;
+    PTOKEN Token;
+    NTSTATUS Status;
+    
+    /* Don't ever expire */
+    Expiration.QuadPart = -1;
+    
+    /* All groups mandatory and enabled */
+    GroupAttributes = SE_GROUP_ENABLED | SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT;
+    OwnerAttributes = SE_GROUP_ENABLED | SE_GROUP_OWNER | SE_GROUP_ENABLED_BY_DEFAULT;
+    
+    /* User is system */
+    UserSid.Sid = SeLocalSystemSid;
+    UserSid.Attributes = 0;
+    
+    /* Primary group is local system */
+    PrimaryGroup = SeLocalSystemSid;
+    
+    /* Owner is admins */
+    Owner = SeAliasAdminsSid;
+    
+    /* Groups are admins, world, and authenticated users */
+    Groups[0].Sid = SeAliasAdminsSid;
+    Groups[0].Attributes = OwnerAttributes;
+    Groups[1].Sid = SeWorldSid;
+    Groups[1].Attributes = GroupAttributes;
+    Groups[2].Sid = SeAuthenticatedUserSid;
+    Groups[2].Attributes = OwnerAttributes;
+    GroupLength = sizeof(SID_AND_ATTRIBUTES) +
+                  SeLengthSid(Groups[0].Sid) +
+                  SeLengthSid(Groups[1].Sid) +
+                  SeLengthSid(Groups[2].Sid);
+    ASSERT(GroupLength <= sizeof(Groups));
+
+    /* Setup the privileges */
     i = 0;
-    AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
-    AccessToken->UserAndGroups[i++].Attributes = 0;
-    RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
-    SidArea = (char*)SidArea + uLocalSystemLength;
-    
-    AccessToken->DefaultOwnerIndex = i;
-    AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
-    AccessToken->PrimaryGroup = (PSID) SidArea;
-    AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT;
-    Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid);
-    SidArea = (char*)SidArea + uAdminsLength;
-    
-    AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
-    AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
-    RtlCopySid(uWorldLength, SidArea, SeWorldSid);
-    SidArea = (char*)SidArea + uWorldLength;
-    
-    AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
-    AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY;
-    RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid);
-    SidArea = (char*)SidArea + uAuthUserLength;
-    
-    AccessToken->PrivilegeCount = 20;
-    
-    uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
-    AccessToken->Privileges =
-    (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
-                                                uSize,
-                                                'pKOT');
-    
-    i = 0;
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
-#if 0
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
-    
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
-#endif
-    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeTcbPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeCreateTokenPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeTakeOwnershipPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeCreatePagefilePrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeLockMemoryPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeCreatePermanentPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeDebugPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeAuditPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeSecurityPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeChangeNotifyPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeBackupPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeRestorePrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeShutdownPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeLoadDriverPrivilege;
+    
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
+    
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeSystemtimePrivilege;
     ASSERT(i == 20);
     
-    uSize = sizeof(ACL);
-    uSize += sizeof(ACE) + uLocalSystemLength;
-    uSize += sizeof(ACE) + uAdminsLength;
-    uSize = (uSize & (~3)) + 8;
-    AccessToken->DefaultDacl =
-    (PACL) ExAllocatePoolWithTag(PagedPool,
-                                 uSize,
-                                 'kDOT');
-    Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
-    if ( NT_SUCCESS(Status) )
-    {
-        Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
-    }
-    
-    if ( NT_SUCCESS(Status) )
-    {
-        Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
-    }
-    
-    if ( ! NT_SUCCESS(Status) )
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
-    
-    return AccessToken;
+    /* Setup the object attributes */
+    InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
+    ASSERT(SeSystemDefaultDacl != NULL);
+    
+    /* Create the token */
+    Status = SepCreateToken((PHANDLE)&Token,
+                            KernelMode,
+                            0,
+                            &ObjectAttributes,
+                            TokenPrimary,
+                            0,
+                            &SeSystemAuthenticationId,
+                            &Expiration,
+                            &UserSid,
+                            3,
+                            Groups,
+                            GroupLength,
+                            20,
+                            Privileges,
+                            Owner,
+                            PrimaryGroup,
+                            SeSystemDefaultDacl,
+                            &SeSystemTokenSource,
+                            TRUE);
+    ASSERT(Status == STATUS_SUCCESS);
+    
+    /* Return the token */
+    return Token;
 }
 
 /* PUBLIC FUNCTIONS ***********************************************************/
@@ -1920,7 +2068,8 @@
     return Status;
 }
 
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 NtCreateToken(OUT PHANDLE TokenHandle,
               IN ACCESS_MASK DesiredAccess,
               IN POBJECT_ATTRIBUTES ObjectAttributes,
@@ -1936,12 +2085,6 @@
               IN PTOKEN_SOURCE TokenSource)
 {
     HANDLE hToken;
-    PTOKEN AccessToken;
-    LUID TokenId;
-    LUID ModifiedId;
-    PVOID EndMem;
-    ULONG uLength;
-    ULONG i;
     KPROCESSOR_MODE PreviousMode;
     ULONG nTokenPrivileges = 0;
     LARGE_INTEGER LocalExpirationTime = {{0, 0}};
@@ -1996,148 +2139,25 @@
         LocalExpirationTime = *ExpirationTime;
     }
     
-    Status = ZwAllocateLocallyUniqueId(&TokenId);
-    if (!NT_SUCCESS(Status))
-        return(Status);
-    
-    Status = ZwAllocateLocallyUniqueId(&ModifiedId);
-    if (!NT_SUCCESS(Status))
-        return(Status);
-    
-    Status = ObCreateObject(PreviousMode,
-                            SepTokenObjectType,
+    Status = SepCreateToken(&hToken,
+                            PreviousMode,
+                            DesiredAccess,
                             ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(TOKEN),
-                            0,
-                            0,
-                            (PVOID*)&AccessToken);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("ObCreateObject() failed (Status %lx)\n");
-        return(Status);
-    }
-
-    /* Zero out the buffer */
-    RtlZeroMemory(AccessToken, sizeof(TOKEN));
-    
-    AccessToken->TokenLock = &SepTokenLock;
-    
-    RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
-                &TokenSource->SourceIdentifier);
-    memcpy(AccessToken->TokenSource.SourceName,
-           TokenSource->SourceName,
-           sizeof(TokenSource->SourceName));
-    
-    RtlCopyLuid(&AccessToken->TokenId, &TokenId);
-    RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
-    AccessToken->ExpirationTime = *ExpirationTime;
-    RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
-    
-    AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1;
-    AccessToken->PrivilegeCount    = TokenPrivileges->PrivilegeCount;
-    
-    AccessToken->TokenType = TokenType;
-    AccessToken->ImpersonationLevel = ((PSECURITY_QUALITY_OF_SERVICE)
-                                       (ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel;
-    
-    /*
-     * Normally we would just point these members into the variable information
-     * area; however, our ObCreateObject() call can't allocate a variable information
-     * area, so we allocate them seperately and provide a destroy function.
-     */
-    
-    uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
-    uLength += RtlLengthSid(TokenUser->User.Sid);
-    for (i = 0; i < TokenGroups->GroupCount; i++)
-        uLength += RtlLengthSid(TokenGroups->Groups[i].Sid);
-    
-    AccessToken->UserAndGroups =
-    (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
-                                               uLength,
-                                               'uKOT');
-    
-    EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
-    
-    Status = RtlCopySidAndAttributesArray(1,
-                                          &TokenUser->User,
-                                          uLength,
-                                          AccessToken->UserAndGroups,
-                                          EndMem,
-                                          &EndMem,
-                                          &uLength);
-    if (NT_SUCCESS(Status))
-    {
-        Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount,
-                                              TokenGroups->Groups,
-                                              uLength,
-                                              &AccessToken->UserAndGroups[1],
-                                              EndMem,
-                                              &EndMem,
-                                              &uLength);
-    }
-    
-    if (NT_SUCCESS(Status))
-    {
-        Status = SepFindPrimaryGroupAndDefaultOwner(
-                                                    AccessToken,
-                                                    TokenPrimaryGroup->PrimaryGroup,
-                                                    TokenOwner->Owner);
-    }
-    
-    if (NT_SUCCESS(Status))
-    {
-        uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
-        AccessToken->Privileges =
-        (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
-                                                    uLength,
-                                                    'pKOT');
-        
-        if (PreviousMode != KernelMode)
-        {
-            _SEH2_TRY
-            {
-                RtlCopyMemory(AccessToken->Privileges,
-                              TokenPrivileges->Privileges,
-                              nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
-            }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-            {
-                Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END;
-        }
-        else
-        {
-            RtlCopyMemory(AccessToken->Privileges,
-                          TokenPrivileges->Privileges,
-                          nTokenPrivileges * sizeof(LUID_AND_ATTRIBUTES));
-        }
-    }
-    
-    if (NT_SUCCESS(Status))
-    {
-        AccessToken->DefaultDacl =
-        (PACL) ExAllocatePoolWithTag(PagedPool,
-                                     TokenDefaultDacl->DefaultDacl->AclSize,
-                                     'kDOT');
-        memcpy(AccessToken->DefaultDacl,
-               TokenDefaultDacl->DefaultDacl,
-               TokenDefaultDacl->DefaultDacl->AclSize);
-    }
-    
-    Status = ObInsertObject ((PVOID)AccessToken,
-                             NULL,
-                             DesiredAccess,
-                             0,
-                             NULL,
-                             &hToken);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("ObInsertObject() failed (Status %lx)\n", Status);
-    }
-    
+                            TokenType,
+                            ((PSECURITY_QUALITY_OF_SERVICE)(ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel,
+                            AuthenticationId,
+                            &LocalExpirationTime,
+                            &TokenUser->User,
+                            TokenGroups->GroupCount,
+                            TokenGroups->Groups,
+                            0, // FIXME: Should capture
+                            nTokenPrivileges,
+                            TokenPrivileges->Privileges,
+                            TokenOwner->Owner,
+                            TokenPrimaryGroup->PrimaryGroup,
+                            TokenDefaultDacl->DefaultDacl,
+                            TokenSource,
+                            FALSE);
     if (NT_SUCCESS(Status))
     {
         _SEH2_TRY
@@ -2165,7 +2185,7 @@
                     IN ULONG HandleAttributes,
                     OUT PHANDLE TokenHandle)
 {
-    PETHREAD Thread;
+    PETHREAD Thread, NewThread;
     HANDLE hToken;
     PTOKEN Token, NewToken, PrimaryToken;
     BOOLEAN CopyOnOpen, EffectiveOnly;
@@ -2215,12 +2235,11 @@
         ObDereferenceObject(Thread);
         return STATUS_NO_TOKEN;
     }
-    
-    ObDereferenceObject(Thread);
-    
+       
     if (ImpersonationLevel == SecurityAnonymous)
     {
-        ObDereferenceObject(Token);
+        PsDereferenceImpersonationToken(Token);
+        ObDereferenceObject(Thread);
         return STATUS_CANT_OPEN_ANONYMOUS;
     }
     
@@ -2236,58 +2255,41 @@
     if (CopyOnOpen)
     {
         Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS,
-                                           PsThreadType, PreviousMode,
-                                           (PVOID*)&Thread, NULL);
-        if (!NT_SUCCESS(Status))
-        {
-            ObDereferenceObject(Token);
-            if (OpenAsSelf)
+                                           PsThreadType, KernelMode,
+                                           (PVOID*)&NewThread, NULL);
+        if (NT_SUCCESS(Status))
+        {
+            PrimaryToken = PsReferencePrimaryToken(NewThread->ThreadsProcess);
+            
+            Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
+
+            ObFastDereferenceObject(&NewThread->ThreadsProcess->Token, PrimaryToken);
+            
+            if (NT_SUCCESS(Status))
             {
-                PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
+                if (Dacl)
+                {
+                    RtlCreateSecurityDescriptor(&SecurityDescriptor,
+                                                SECURITY_DESCRIPTOR_REVISION);
+                    RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
+                                                 FALSE);
+                }
+        
+                InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
+                                           NULL, Dacl ? &SecurityDescriptor : NULL);
+            
+
+                Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
+                                           TokenImpersonation, ImpersonationLevel,
+                                           KernelMode, &NewToken);
+                if (NT_SUCCESS(Status))
+                {
+                    ObReferenceObject(NewToken);
+                    Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
+                                            &hToken);
+                }
             }
-            return Status;
-        }
-        
-        PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
-        Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
-        ASSERT(FALSE);
-        ObDereferenceObject(PrimaryToken);
-        ObDereferenceObject(Thread);
-        if (!NT_SUCCESS(Status))
-        {
-            ObDereferenceObject(Token);
-            if (OpenAsSelf)
-            {
-                PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
-            }
-            return Status;
-        }
-        
-        RtlCreateSecurityDescriptor(&SecurityDescriptor,
-                                    SECURITY_DESCRIPTOR_REVISION);
-        RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
-                                     FALSE);
-        
-        InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
-                                   NULL, &SecurityDescriptor);
-        
-        Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
-                                   TokenImpersonation, ImpersonationLevel,
-                                   KernelMode, &NewToken);
-        ExFreePool(Dacl);
-        if (!NT_SUCCESS(Status))
-        {
-            ObDereferenceObject(Token);
-            if (OpenAsSelf)
-            {
-                PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
-            }
-            return Status;
-        }
-        
-        Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
-                                &hToken);
-        
+        }
     }
     else
     {
@@ -2296,13 +2298,24 @@
                                        PreviousMode, &hToken);
     }
     
+    if (Dacl) ExFreePool(Dacl);
+    
+    if (OpenAsSelf)
+    {
+        PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
+    }
+    
     ObDereferenceObject(Token);
     
-    if (OpenAsSelf)
-    {
-        PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
-    }
-    
+    if (NT_SUCCESS(Status) && CopyOnOpen)
+    {
+        PsImpersonateClient(Thread, NewToken, FALSE, EffectiveOnly, ImpersonationLevel);
+    }
+    
+    if (NewToken) ObDereferenceObject(NewToken);
+    
+    if (CopyOnOpen && NewThread) ObDereferenceObject(NewThread);
+        
     if(NT_SUCCESS(Status))
     {
         _SEH2_TRY

Modified: trunk/reactos/subsystems/csr/csrsrv/process.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/csr/csrsrv/process.c?rev=46028&r1=46027&r2=46028&view=diff
==============================================================================
--- trunk/reactos/subsystems/csr/csrsrv/process.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/csr/csrsrv/process.c [iso-8859-1] Tue Mar  9 11:35:58 2010
@@ -916,7 +916,7 @@
     /* Now query the information */
     Status = NtQueryInformationToken(hToken,
                                      TokenStatistics,
-                                     &TokenStats,
+                                     TokenStats,
                                      Length,
                                      &Length);
 




More information about the Ros-diffs mailing list