[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / se / token.c
index e456471..8f73312 100644 (file)
@@ -22,6 +22,9 @@
 POBJECT_TYPE SepTokenObjectType = NULL;
 ERESOURCE SepTokenLock;
 
+TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
+LUID SeSystemAuthenticationId = SYSTEM_LUID;
+
 static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ,
     TOKEN_WRITE,
     TOKEN_EXECUTE,
@@ -244,10 +247,13 @@ SepDuplicateToken(PTOKEN Token,
                             (PVOID*)&AccessToken);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("ObCreateObject() failed (Status %lx)\n");
+        DPRINT1("ObCreateObject() failed (Status %lx)\n", Status);
         return(Status);
     }
-    
+
+    /* Zero out the buffer */
+    RtlZeroMemory(AccessToken, sizeof(TOKEN));
+
     Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId);
     if (!NT_SUCCESS(Status))
     {
@@ -264,7 +270,6 @@ SepDuplicateToken(PTOKEN Token,
     
     AccessToken->TokenLock = &SepTokenLock;
     
-    AccessToken->TokenInUse = 0;
     AccessToken->TokenType  = TokenType;
     AccessToken->ImpersonationLevel = Level;
     RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
@@ -285,7 +290,7 @@ SepDuplicateToken(PTOKEN Token,
     AccessToken->UserAndGroups =
     (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
                                                uLength,
-                                               TAG('T', 'O', 'K', 'u'));
+                                               'uKOT');
     
     EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
     
@@ -312,7 +317,7 @@ SepDuplicateToken(PTOKEN Token,
         AccessToken->Privileges =
         (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(PagedPool,
                                                     uLength,
-                                                    TAG('T', 'O', 'K', 'p'));
+                                                    'pKOT');
         
         for (i = 0; i < AccessToken->PrivilegeCount; i++)
         {
@@ -327,15 +332,11 @@ SepDuplicateToken(PTOKEN Token,
             AccessToken->DefaultDacl =
             (PACL) ExAllocatePoolWithTag(PagedPool,
                                          Token->DefaultDacl->AclSize,
-                                         TAG('T', 'O', 'K', 'd'));
+                                         'kDOT');
             memcpy(AccessToken->DefaultDacl,
                    Token->DefaultDacl,
                    Token->DefaultDacl->AclSize);
         }
-        else
-        {
-            AccessToken->DefaultDacl = 0;
-        }
     }
     
     if ( NT_SUCCESS(Status) )
@@ -512,34 +513,80 @@ SeAssignPrimaryToken(IN PEPROCESS Process,
     ObInitializeFastReference(&Process->Token, Token);
 }
 
-PTOKEN
+
+NTSTATUS
 NTAPI
-SepCreateSystemProcessToken(VOID)
-{
-    NTSTATUS Status;
-    ULONG uSize;
-    ULONG i;
-    ULONG uLocalSystemLength;
-    ULONG uWorldLength;
-    ULONG uAuthUserLength;
-    ULONG uAdminsLength;
+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;
-    PVOID SidArea;
+    LUID TokenId;
+    LUID ModifiedId;
+    PVOID EndMem;
+    ULONG uLength;
+    ULONG i;
+    NTSTATUS Status;
+    ULONG TokenFlags = 0;
     
-    PAGED_CODE();
+    /* 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;
+        }
+    }
     
-    uLocalSystemLength = RtlLengthSid(SeLocalSystemSid);
-    uWorldLength       = RtlLengthSid(SeWorldSid);
-    uAuthUserLength    = RtlLengthSid(SeAuthenticatedUserSid);
-    uAdminsLength      = RtlLengthSid(SeAliasAdminsSid);
+    /* 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);
     
-    /*
-     * Initialize the token
-     */
-    Status = ObCreateObject(KernelMode,
+    Status = ZwAllocateLocallyUniqueId(&ModifiedId);
+    if (!NT_SUCCESS(Status))
+        return(Status);
+    
+    Status = ObCreateObject(PreviousMode,
                             SepTokenObjectType,
-                            NULL,
-                            KernelMode,
+                            ObjectAttributes,
+                            PreviousMode,
                             NULL,
                             sizeof(TOKEN),
                             0,
@@ -547,179 +594,279 @@ SepCreateSystemProcessToken(VOID)
                             (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;
-    }
+    AccessToken->TokenLock = &SepTokenLock;
     
-    Status = ExpAllocateLocallyUniqueId(&AccessToken->ModifiedId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
+    RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
+                &TokenSource->SourceIdentifier);
+    memcpy(AccessToken->TokenSource.SourceName,
+           TokenSource->SourceName,
+           sizeof(TokenSource->SourceName));
     
-    Status = ExpAllocateLocallyUniqueId(&AccessToken->AuthenticationId);
-    if (!NT_SUCCESS(Status))
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
+    RtlCopyLuid(&AccessToken->TokenId, &TokenId);
+    RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
+    AccessToken->ExpirationTime = *ExpirationTime;
+    RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
     
-    AccessToken->TokenLock = &SepTokenLock;
+    AccessToken->UserAndGroupCount = GroupCount + 1;
+    AccessToken->PrivilegeCount = PrivilegeCount;
     
-    AccessToken->TokenType = TokenPrimary;
-    AccessToken->ImpersonationLevel = SecurityDelegation;
-    AccessToken->TokenSource.SourceIdentifier.LowPart = 0;
-    AccessToken->TokenSource.SourceIdentifier.HighPart = 0;
-    memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8);
-    AccessToken->ExpirationTime.QuadPart = -1;
-    AccessToken->UserAndGroupCount = 4;
+    AccessToken->TokenFlags = TokenFlags;
+    AccessToken->TokenType = TokenType;
+    AccessToken->ImpersonationLevel = ImpersonationLevel;
     
-    uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount;
-    uSize += uLocalSystemLength;
-    uSize += uWorldLength;
-    uSize += uAuthUserLength;
-    uSize += uAdminsLength;
+    /*
+     * 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,
-                                               TAG('T', 'O', 'K', 'u'));
-    SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
+                                               uLength,
+                                               'uKOT');
     
-    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,
-                                                TAG('T', 'O', 'K', 'p'));
+    EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount];
     
-    i = 0;
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeTcbPrivilege;
+    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);
+    }
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege;
+    if (NT_SUCCESS(Status))
+    {
+        Status = SepFindPrimaryGroupAndDefaultOwner(
+                                                    AccessToken,
+                                                    PrimaryGroup,
+                                                    Owner);
+    }
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege;
+    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));
+        }
+    }
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege;
+    if (NT_SUCCESS(Status))
+    {
+        AccessToken->DefaultDacl =
+        (PACL) ExAllocatePoolWithTag(PagedPool,
+                                     DefaultDacl->AclSize,
+                                     'kDOT');
+        memcpy(AccessToken->DefaultDacl,
+               DefaultDacl,
+               DefaultDacl->AclSize);
+    }
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege;
+    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;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
+    /* 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;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeTcbPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeCreateTokenPrivilege;
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeTakeOwnershipPrivilege;
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeCreatePagefilePrivilege;
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeDebugPrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeLockMemoryPrivilege;
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeAuditPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeSecurityPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeIncreaseQuotaPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege;
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeCreatePermanentPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeBackupPrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeDebugPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeRestorePrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeAuditPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeShutdownPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeSecurityPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeSystemEnvironmentPrivilege;
     
-    AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
-    AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeChangeNotifyPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege;
-#if 0
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeUndockPrivilege;
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeBackupPrivilege;
     
-    AccessToken->Privileges[i].Attributes = 0;
-    AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege;
-#endif
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeRestorePrivilege;
     
-    ASSERT(i == 20);
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeShutdownPrivilege;
     
-    uSize = sizeof(ACL);
-    uSize += sizeof(ACE) + uLocalSystemLength;
-    uSize += sizeof(ACE) + uAdminsLength;
-    uSize = (uSize & (~3)) + 8;
-    AccessToken->DefaultDacl =
-    (PACL) ExAllocatePoolWithTag(PagedPool,
-                                 uSize,
-                                 TAG('T', 'O', 'K', 'd'));
-    Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION);
-    if ( NT_SUCCESS(Status) )
-    {
-        Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid);
-    }
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeLoadDriverPrivilege;
     
-    if ( NT_SUCCESS(Status) )
-    {
-        Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid);
-    }
+    Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
+    Privileges[i++].Luid = SeProfileSingleProcessPrivilege;
     
-    if ( ! NT_SUCCESS(Status) )
-    {
-        ObDereferenceObject(AccessToken);
-        return NULL;
-    }
+    Privileges[i].Attributes = 0;
+    Privileges[i++].Luid = SeSystemtimePrivilege;
+    ASSERT(i == 20);
     
-    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 ***********************************************************/
@@ -1200,6 +1347,14 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
                 PSECURITY_IMPERSONATION_LEVEL sil = (PSECURITY_IMPERSONATION_LEVEL)TokenInformation;
                 
                 DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
+
+                /* Fail if the token is not an impersonation token */
+                if (Token->TokenType != TokenImpersonation)
+                {
+                    Status = STATUS_INVALID_INFO_CLASS;
+                    break;
+                }
+
                 RequiredLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
                 
                 _SEH2_TRY
@@ -1415,7 +1570,7 @@ NtSetInformationToken(IN HANDLE TokenHandle,
     PTOKEN Token;
     KPROCESSOR_MODE PreviousMode;
     ULONG NeededAccess = TOKEN_ADJUST_DEFAULT;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     
     PAGED_CODE();
     
@@ -1455,7 +1610,7 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                 if(TokenInformationLength >= sizeof(TOKEN_OWNER))
                 {
                     PTOKEN_OWNER to = (PTOKEN_OWNER)TokenInformation;
-                    PSID InputSid = NULL;
+                    PSID InputSid = NULL, CapturedSid;
                     
                     _SEH2_TRY
                     {
@@ -1463,28 +1618,23 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                     }
                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                     {
-                        Status = _SEH2_GetExceptionCode();
+                        _SEH2_YIELD(return _SEH2_GetExceptionCode());
                     }
                     _SEH2_END;
                     
+                    Status = SepCaptureSid(InputSid,
+                                           PreviousMode,
+                                           PagedPool,
+                                           FALSE,
+                                           &CapturedSid);
                     if(NT_SUCCESS(Status))
                     {
-                        PSID CapturedSid;
-                        
-                        Status = SepCaptureSid(InputSid,
-                                               PreviousMode,
-                                               PagedPool,
-                                               FALSE,
-                                               &CapturedSid);
-                        if(NT_SUCCESS(Status))
-                        {
-                            RtlCopySid(RtlLengthSid(CapturedSid),
-                                       Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
-                                       CapturedSid);
-                            SepReleaseSid(CapturedSid,
-                                          PreviousMode,
-                                          FALSE);
-                        }
+                        RtlCopySid(RtlLengthSid(CapturedSid),
+                                   Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
+                                   CapturedSid);
+                        SepReleaseSid(CapturedSid,
+                                      PreviousMode,
+                                      FALSE);
                     }
                 }
                 else
@@ -1499,7 +1649,7 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                 if(TokenInformationLength >= sizeof(TOKEN_PRIMARY_GROUP))
                 {
                     PTOKEN_PRIMARY_GROUP tpg = (PTOKEN_PRIMARY_GROUP)TokenInformation;
-                    PSID InputSid = NULL;
+                    PSID InputSid = NULL, CapturedSid;
                     
                     _SEH2_TRY
                     {
@@ -1507,28 +1657,23 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                     }
                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                     {
-                        Status = _SEH2_GetExceptionCode();
+                        _SEH2_YIELD(return _SEH2_GetExceptionCode());
                     }
                     _SEH2_END;
                     
+                    Status = SepCaptureSid(InputSid,
+                                           PreviousMode,
+                                           PagedPool,
+                                           FALSE,
+                                           &CapturedSid);
                     if(NT_SUCCESS(Status))
                     {
-                        PSID CapturedSid;
-                        
-                        Status = SepCaptureSid(InputSid,
-                                               PreviousMode,
-                                               PagedPool,
-                                               FALSE,
-                                               &CapturedSid);
-                        if(NT_SUCCESS(Status))
-                        {
-                            RtlCopySid(RtlLengthSid(CapturedSid),
-                                       Token->PrimaryGroup,
-                                       CapturedSid);
-                            SepReleaseSid(CapturedSid,
-                                          PreviousMode,
-                                          FALSE);
-                        }
+                        RtlCopySid(RtlLengthSid(CapturedSid),
+                                   Token->PrimaryGroup,
+                                   CapturedSid);
+                        SepReleaseSid(CapturedSid,
+                                      PreviousMode,
+                                      FALSE);
                     }
                 }
                 else
@@ -1551,42 +1696,39 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                     }
                     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                     {
-                        Status = _SEH2_GetExceptionCode();
+                        _SEH2_YIELD(return _SEH2_GetExceptionCode());
                     }
                     _SEH2_END;
-                    
-                    if(NT_SUCCESS(Status))
+
+                    if(InputAcl != NULL)
                     {
-                        if(InputAcl != NULL)
-                        {
-                            PACL CapturedAcl;
-                            
-                            /* capture and copy the dacl */
-                            Status = SepCaptureAcl(InputAcl,
-                                                   PreviousMode,
-                                                   PagedPool,
-                                                   TRUE,
-                                                   &CapturedAcl);
-                            if(NT_SUCCESS(Status))
-                            {
-                                /* free the previous dacl if present */
-                                if(Token->DefaultDacl != NULL)
-                                {
-                                    ExFreePool(Token->DefaultDacl);
-                                }
-                                
-                                /* set the new dacl */
-                                Token->DefaultDacl = CapturedAcl;
-                            }
-                        }
-                        else
+                        PACL CapturedAcl;
+
+                        /* capture and copy the dacl */
+                        Status = SepCaptureAcl(InputAcl,
+                                               PreviousMode,
+                                               PagedPool,
+                                               TRUE,
+                                               &CapturedAcl);
+                        if(NT_SUCCESS(Status))
                         {
-                            /* clear and free the default dacl if present */
+                            /* free the previous dacl if present */
                             if(Token->DefaultDacl != NULL)
                             {
                                 ExFreePool(Token->DefaultDacl);
-                                Token->DefaultDacl = NULL;
                             }
+
+                            /* set the new dacl */
+                            Token->DefaultDacl = CapturedAcl;
+                        }
+                    }
+                    else
+                    {
+                        /* clear and free the default dacl if present */
+                        if(Token->DefaultDacl != NULL)
+                        {
+                            ExFreePool(Token->DefaultDacl);
+                            Token->DefaultDacl = NULL;
                         }
                     }
                 }
@@ -1608,21 +1750,18 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                 }
                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
                 {
-                    Status = _SEH2_GetExceptionCode();
+                    _SEH2_YIELD(return _SEH2_GetExceptionCode());
                 }
                 _SEH2_END;
                 
-                if(NT_SUCCESS(Status))
+                if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
+                                           PreviousMode))
                 {
-                    if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
-                                               PreviousMode))
-                    {
-                        Status = STATUS_PRIVILEGE_NOT_HELD;
-                        break;
-                    }
-                    
-                    Token->SessionId = SessionId;
+                    Status = STATUS_PRIVILEGE_NOT_HELD;
+                    break;
                 }
+
+                Token->SessionId = SessionId;
                 break;
             }
                 
@@ -1662,13 +1801,13 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle,
     PTOKEN NewToken;
     PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService;
     BOOLEAN QoSPresent;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     
     PAGED_CODE();
     
     PreviousMode = KeGetPreviousMode();
     
-    if(PreviousMode != KernelMode)
+    if (PreviousMode != KernelMode)
     {
         _SEH2_TRY
         {
@@ -1676,14 +1815,10 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle,
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Status = _SEH2_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
         _SEH2_END;
-        
-        if(!NT_SUCCESS(Status))
-        {
-            return Status;
-        }
     }
     
     Status = SepCaptureSecurityQualityOfService(ObjectAttributes,
@@ -1941,7 +2076,8 @@ NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
     return Status;
 }
 
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 NtCreateToken(OUT PHANDLE TokenHandle,
               IN ACCESS_MASK DesiredAccess,
               IN POBJECT_ATTRIBUTES ObjectAttributes,
@@ -1957,16 +2093,10 @@ NtCreateToken(OUT PHANDLE TokenHandle,
               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}};
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     
     PAGED_CODE();
     
@@ -2006,14 +2136,10 @@ NtCreateToken(OUT PHANDLE TokenHandle,
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Status = _SEH2_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
         _SEH2_END;
-        
-        if(!NT_SUCCESS(Status))
-        {
-            return Status;
-        }
     }
     else
     {
@@ -2021,147 +2147,25 @@ NtCreateToken(OUT PHANDLE TokenHandle,
         LocalExpirationTime = *ExpirationTime;
     }
     
-    Status = ZwAllocateLocallyUniqueId(&TokenId);
-    if (!NT_SUCCESS(Status))
-        return(Status);
-    
-    Status = ZwAllocateLocallyUniqueId(&ModifiedId);
-    if (!NT_SUCCESS(Status))
-        return(Status);
-    
-    Status = ObCreateObject(PreviousMode,
-                            SepTokenObjectType,
-                            ObjectAttributes,
+    Status = SepCreateToken(&hToken,
                             PreviousMode,
-                            NULL,
-                            sizeof(TOKEN),
-                            0,
-                            0,
-                            (PVOID*)&AccessToken);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("ObCreateObject() failed (Status %lx)\n");
-        return(Status);
-    }
-    
-    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->UserAndGroups     = 0;
-    AccessToken->Privileges        = 0;
-    
-    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,
-                                               TAG('T', 'O', 'K', 'u'));
-    
-    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,
-                                                    TAG('T', 'O', 'K', 'p'));
-        
-        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,
-                                     TAG('T', 'O', 'K', 'd'));
-        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);
-    }
-    
+                            DesiredAccess,
+                            ObjectAttributes,
+                            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
@@ -2189,9 +2193,9 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
                     IN ULONG HandleAttributes,
                     OUT PHANDLE TokenHandle)
 {
-    PETHREAD Thread;
+    PETHREAD Thread, NewThread;
     HANDLE hToken;
-    PTOKEN Token, NewToken, PrimaryToken;
+    PTOKEN Token, NewToken = NULL, PrimaryToken;
     BOOLEAN CopyOnOpen, EffectiveOnly;
     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
     SE_IMPERSONATION_STATE ImpersonationState;
@@ -2199,13 +2203,13 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
     SECURITY_DESCRIPTOR SecurityDescriptor;
     PACL Dacl = NULL;
     KPROCESSOR_MODE PreviousMode;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     
     PAGED_CODE();
     
     PreviousMode = ExGetPreviousMode();
     
-    if(PreviousMode != KernelMode)
+    if (PreviousMode != KernelMode)
     {
         _SEH2_TRY
         {
@@ -2213,14 +2217,10 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Status = _SEH2_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
         _SEH2_END;
-        
-        if(!NT_SUCCESS(Status))
-        {
-            return Status;
-        }
     }
     
     /*
@@ -2240,15 +2240,14 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
                                           &ImpersonationLevel);
     if (Token == NULL)
     {
-        ObfDereferenceObject(Thread);
+        ObDereferenceObject(Thread);
         return STATUS_NO_TOKEN;
     }
-    
-    ObDereferenceObject(Thread);
-    
+       
     if (ImpersonationLevel == SecurityAnonymous)
     {
-        ObfDereferenceObject(Token);
+        PsDereferenceImpersonationToken(Token);
+        ObDereferenceObject(Thread);
         return STATUS_CANT_OPEN_ANONYMOUS;
     }
     
@@ -2264,58 +2263,41 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
     if (CopyOnOpen)
     {
         Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS,
-                                           PsThreadType, PreviousMode,
-                                           (PVOID*)&Thread, NULL);
-        if (!NT_SUCCESS(Status))
-        {
-            ObfDereferenceObject(Token);
-            if (OpenAsSelf)
-            {
-                PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
-            }
-            return Status;
-        }
-        
-        PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);
-        Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
-        ASSERT(FALSE);
-        ObfDereferenceObject(PrimaryToken);
-        ObfDereferenceObject(Thread);
-        if (!NT_SUCCESS(Status))
+                                           PsThreadType, KernelMode,
+                                           (PVOID*)&NewThread, NULL);
+        if (NT_SUCCESS(Status))
         {
-            ObfDereferenceObject(Token);
-            if (OpenAsSelf)
+            PrimaryToken = PsReferencePrimaryToken(NewThread->ThreadsProcess);
+            
+            Status = SepCreateImpersonationTokenDacl(Token, PrimaryToken, &Dacl);
+
+            ObFastDereferenceObject(&NewThread->ThreadsProcess->Token, PrimaryToken);
+            
+            if (NT_SUCCESS(Status))
             {
-                PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
-            }
-            return Status;
-        }
-        
-        RtlCreateSecurityDescriptor(&SecurityDescriptor,
-                                    SECURITY_DESCRIPTOR_REVISION);
-        RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
-                                     FALSE);
-        
-        InitializeObjectAttributes(&ObjectAttributes, NULL, HandleAttributes,
-                                   NULL, &SecurityDescriptor);
+                if (Dacl)
+                {
+                    RtlCreateSecurityDescriptor(&SecurityDescriptor,
+                                                SECURITY_DESCRIPTOR_REVISION);
+                    RtlSetDaclSecurityDescriptor(&SecurityDescriptor, TRUE, Dacl,
+                                                 FALSE);
+                }
         
-        Status = SepDuplicateToken(Token, &ObjectAttributes, EffectiveOnly,
-                                   TokenImpersonation, ImpersonationLevel,
-                                   KernelMode, &NewToken);
-        ExFreePool(Dacl);
-        if (!NT_SUCCESS(Status))
-        {
-            ObfDereferenceObject(Token);
-            if (OpenAsSelf)
-            {
-                PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
+                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;
         }
-        
-        Status = ObInsertObject(NewToken, NULL, DesiredAccess, 0, NULL,
-                                &hToken);
-        
     }
     else
     {
@@ -2324,13 +2306,24 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
                                        PreviousMode, &hToken);
     }
     
-    ObfDereferenceObject(Token);
+    if (Dacl) ExFreePool(Dacl);
     
     if (OpenAsSelf)
     {
         PsRestoreImpersonation(PsGetCurrentThread(), &ImpersonationState);
     }
     
+    ObDereferenceObject(Token);
+    
+    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
@@ -2374,7 +2367,7 @@ NtCompareTokens(IN HANDLE FirstTokenHandle,
     KPROCESSOR_MODE PreviousMode;
     PTOKEN FirstToken, SecondToken;
     BOOLEAN IsEqual;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
     
     PAGED_CODE();
     
@@ -2388,12 +2381,10 @@ NtCompareTokens(IN HANDLE FirstTokenHandle,
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Status = _SEH2_GetExceptionCode();
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
         _SEH2_END;
-        
-        if (!NT_SUCCESS(Status))
-            return Status;
     }
     
     Status = ObReferenceObjectByHandle(FirstTokenHandle,