NtDuplicateToken() must create and return a handle to the duplicated token.
[reactos.git] / reactos / ntoskrnl / se / token.c
index 96e92ec..003300c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: token.c,v 1.23 2003/05/31 11:10:30 ekohl Exp $
+/* $Id: token.c,v 1.37 2004/07/13 08:43:35 ekohl Exp $
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
@@ -12,7 +12,9 @@
 /* INCLUDES *****************************************************************/
 
 #include <limits.h>
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
+#include <internal/ob.h>
 #include <internal/ps.h>
 #include <internal/se.h>
 #include <internal/safe.h>
@@ -41,6 +43,7 @@ VOID SepFreeProxyData(PVOID ProxyData)
 NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src)
 {
    UNIMPLEMENTED;
+   return(STATUS_NOT_IMPLEMENTED);
 }
 
 NTSTATUS SeExchangePrimaryToken(PEPROCESS Process,
@@ -144,10 +147,14 @@ SepDuplicateToken(PACCESS_TOKEN Token,
 
   PACCESS_TOKEN AccessToken;
 
-  Status = ObCreateObject(0,
-                         TOKEN_ALL_ACCESS,
-                         ObjectAttributes,
+  Status = ObCreateObject(PreviousMode,
                          SepTokenObjectType,
+                         ObjectAttributes,
+                         PreviousMode,
+                         NULL,
+                         sizeof(ACCESS_TOKEN),
+                         0,
+                         0,
                          (PVOID*)&AccessToken);
   if (!NT_SUCCESS(Status))
     {
@@ -312,6 +319,9 @@ NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 SeCreateClientSecurity(IN struct _ETHREAD *Thread,
                       IN PSECURITY_QUALITY_OF_SERVICE Qos,
@@ -401,6 +411,9 @@ SeCreateClientSecurity(IN struct _ETHREAD *Thread,
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
                    IN PETHREAD ServerThread OPTIONAL)
@@ -443,7 +456,7 @@ SepDeleteToken(PVOID ObjectBody)
 }
 
 
-VOID
+VOID INIT_FUNCTION
 SepInitializeTokenImplementation(VOID)
 {
   SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
@@ -469,9 +482,13 @@ SepInitializeTokenImplementation(VOID)
 
   RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
                         L"Token");
+  ObpCreateTypeObject (SepTokenObjectType);
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 NtQueryInformationToken(IN HANDLE TokenHandle,
                        IN TOKEN_INFORMATION_CLASS TokenInformationClass,
@@ -480,13 +497,13 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
                        OUT PULONG ReturnLength)
 {
   NTSTATUS Status;
-  PACCESS_TOKEN Token;
   PVOID UnusedInfo;
   PVOID EndMem;
+  PACCESS_TOKEN Token;
+  ULONG Length;
   PTOKEN_GROUPS PtrTokenGroups;
   PTOKEN_DEFAULT_DACL PtrDefaultDacl;
   PTOKEN_STATISTICS PtrTokenStatistics;
-  ULONG uLength;
 
   Status = ObReferenceObjectByHandle(TokenHandle,
                                     (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY,
@@ -502,11 +519,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
   switch (TokenInformationClass)
     {
       case TokenUser:
-        DPRINT("NtQueryInformationToken(TokenUser)\n");
-       uLength = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
-       if (TokenInformationLength < uLength)
+       DPRINT("NtQueryInformationToken(TokenUser)\n");
+       Length = RtlLengthSidAndAttributes(1, Token->UserAndGroups);
+       if (TokenInformationLength < Length)
          {
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -516,29 +533,29 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
                                                  Token->UserAndGroups,
                                                  TokenInformationLength,
                                                  TokenInformation,
-                                                 TokenInformation + 8,
+                                                 (char*)TokenInformation + 8,
                                                  &UnusedInfo,
-                                                 &uLength);
+                                                 &Length);
            if (NT_SUCCESS(Status))
              {
-               uLength = TokenInformationLength - uLength;
-               Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+               Length = TokenInformationLength - Length;
+               Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
              }
          }
        break;
        
       case TokenGroups:
-        DPRINT("NtQueryInformationToken(TokenGroups)\n");
-       uLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(DWORD);
-       if (TokenInformationLength < uLength)
+       DPRINT("NtQueryInformationToken(TokenGroups)\n");
+       Length = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(ULONG);
+       if (TokenInformationLength < Length)
          {
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
        else
          {
-           EndMem = TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES);
+           EndMem = (char*)TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES);
            PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation;
            PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1;
            Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1,
@@ -547,21 +564,21 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
                                                  PtrTokenGroups->Groups,
                                                  EndMem,
                                                  &UnusedInfo,
-                                                 &uLength);
+                                                 &Length);
            if (NT_SUCCESS(Status))
              {
-               uLength = TokenInformationLength - uLength;
-               Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+               Length = TokenInformationLength - Length;
+               Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
              }
          }
        break;
 
       case TokenPrivileges:
-        DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
-       uLength = sizeof(DWORD) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
-       if (TokenInformationLength < uLength)
+       DPRINT("NtQueryInformationToken(TokenPrivileges)\n");
+       Length = sizeof(ULONG) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
+       if (TokenInformationLength < Length)
          {
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -581,11 +598,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
        break;
 
       case TokenOwner:
-        DPRINT("NtQueryInformationToken(TokenOwner)\n");
-       uLength = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
-       if (TokenInformationLength < uLength)
+       DPRINT("NtQueryInformationToken(TokenOwner)\n");
+       Length = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER);
+       if (TokenInformationLength < Length)
          {
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -601,12 +618,12 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
        break;
 
       case TokenPrimaryGroup:
-        DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
+       DPRINT("NtQueryInformationToken(TokenPrimaryGroup),"
               "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
-       uLength = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
-       if (TokenInformationLength < uLength)
+       Length = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP);
+       if (TokenInformationLength < Length)
          {
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -622,19 +639,19 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
        break;
 
       case TokenDefaultDacl:
-        DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
+       DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n");
        PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation;
-       uLength = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
-       if (TokenInformationLength < uLength)
+       Length = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL);
+       if (TokenInformationLength < Length)
          {
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
        else if (!Token->DefaultDacl)
          {
            PtrDefaultDacl->DefaultDacl = 0;
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
          }
        else
          {
@@ -642,16 +659,16 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
            memmove(PtrDefaultDacl->DefaultDacl,
                    Token->DefaultDacl,
                    Token->DefaultDacl->AclSize);
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
          }
        break;
 
       case TokenSource:
-        DPRINT("NtQueryInformationToken(TokenSource)\n");
+       DPRINT("NtQueryInformationToken(TokenSource)\n");
        if (TokenInformationLength < sizeof(TOKEN_SOURCE))
          {
-           uLength = sizeof(TOKEN_SOURCE);
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Length = sizeof(TOKEN_SOURCE);
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -662,11 +679,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
        break;
 
       case TokenType:
-        DPRINT("NtQueryInformationToken(TokenType)\n");
+       DPRINT("NtQueryInformationToken(TokenType)\n");
        if (TokenInformationLength < sizeof(TOKEN_TYPE))
          {
-           uLength = sizeof(TOKEN_TYPE);
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Length = sizeof(TOKEN_TYPE);
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -677,11 +694,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
        break;
 
       case TokenImpersonationLevel:
-        DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
+       DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n");
        if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL))
          {
-           uLength = sizeof(SECURITY_IMPERSONATION_LEVEL);
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Length = sizeof(SECURITY_IMPERSONATION_LEVEL);
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -692,11 +709,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
        break;
 
       case TokenStatistics:
-        DPRINT("NtQueryInformationToken(TokenStatistics)\n");
+       DPRINT("NtQueryInformationToken(TokenStatistics)\n");
        if (TokenInformationLength < sizeof(TOKEN_STATISTICS))
          {
-           uLength = sizeof(TOKEN_STATISTICS);
-           Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG));
+           Length = sizeof(TOKEN_STATISTICS);
+           Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG));
            if (NT_SUCCESS(Status))
              Status = STATUS_BUFFER_TOO_SMALL;
          }
@@ -724,6 +741,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
   return(Status);
 }
 
+/*
+ * NtSetTokenInformation: Partly implemented.
+ * Unimplemented:
+ *  TokenOrigin, TokenDefaultDacl, TokenSessionId
+ */
 
 NTSTATUS STDCALL
 NtSetInformationToken(IN HANDLE TokenHandle,
@@ -731,10 +753,72 @@ NtSetInformationToken(IN HANDLE TokenHandle,
                      OUT PVOID TokenInformation,
                      IN ULONG TokenInformationLength)
 {
-  UNIMPLEMENTED;
+  NTSTATUS Status;
+  PACCESS_TOKEN Token;
+  TOKEN_OWNER TokenOwnerSet = { 0 };
+  TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet = { 0 };
+  DWORD NeededAccess = 0;
+
+  switch (TokenInformationClass) 
+    {
+    case TokenOwner:
+    case TokenPrimaryGroup:
+      NeededAccess = TOKEN_ADJUST_DEFAULT;
+      break;
+
+    default:
+      return STATUS_NOT_IMPLEMENTED;
+    }
+
+  Status = ObReferenceObjectByHandle(TokenHandle,
+                                    NeededAccess,
+                                    SepTokenObjectType,
+                                    UserMode,
+                                    (PVOID*)&Token,
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
+
+  switch (TokenInformationClass)
+    {
+    case TokenOwner:
+      MmCopyFromCaller( &TokenOwnerSet, TokenInformation,
+                       min(sizeof(TokenOwnerSet),TokenInformationLength) );
+      RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER),
+                Token->UserAndGroups[Token->DefaultOwnerIndex].Sid,
+                TokenOwnerSet.Owner);
+      Status = STATUS_SUCCESS;
+      DPRINT("NtSetInformationToken(TokenOwner)\n");
+      break;
+      
+    case TokenPrimaryGroup:
+      MmCopyFromCaller( &TokenPrimaryGroupSet, TokenInformation, 
+                       min(sizeof(TokenPrimaryGroupSet),
+                           TokenInformationLength) );
+      RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP),
+                Token->PrimaryGroup,
+                TokenPrimaryGroupSet.PrimaryGroup);
+      Status = STATUS_SUCCESS;
+      DPRINT("NtSetInformationToken(TokenPrimaryGroup),"
+            "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup);
+      break;
+
+    default:
+      Status = STATUS_NOT_IMPLEMENTED;
+      break;
+    }
+
+  ObDereferenceObject(Token);
+
+  return(Status);
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 NtDuplicateToken(IN HANDLE ExistingTokenHandle,
                 IN ACCESS_MASK DesiredAccess,
@@ -743,32 +827,61 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle,
                 IN TOKEN_TYPE TokenType,
                 OUT PHANDLE NewTokenHandle)
 {
-#if 0
-   PACCESS_TOKEN Token;
-   PACCESS_TOKEN NewToken;
-   NTSTATUS Status;
-   ULONG ExistingImpersonationLevel;
-   
-   Status = ObReferenceObjectByHandle(ExistingTokenHandle,
-                                     TOKEN_DUPLICATE,
-                                     SepTokenObjectType,
-                                     UserMode,
-                                     (PVOID*)&Token,
-                                     NULL);
-   
-   ExistingImpersonationLevel = Token->ImpersonationLevel;
-   SepDuplicateToken(Token,
-                    ObjectAttributes,
-                    ImpersonationLevel,
-                    TokenType,
-                    ExistingImpersonationLevel,
-                    KeGetPreviousMode(),
-                    &NewToken);
-#else
-   UNIMPLEMENTED;
-#endif
+  KPROCESSOR_MODE PreviousMode;
+  PACCESS_TOKEN Token;
+  PACCESS_TOKEN NewToken;
+  NTSTATUS Status;
+  ULONG ExistingImpersonationLevel;
+
+  PreviousMode = KeGetPreviousMode();
+  Status = ObReferenceObjectByHandle(ExistingTokenHandle,
+                                    TOKEN_DUPLICATE,
+                                    SepTokenObjectType,
+                                    PreviousMode,
+                                    (PVOID*)&Token,
+                                    NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("Failed to reference token (Status %lx)\n", Status);
+      return Status;
+    }
+
+  ExistingImpersonationLevel = Token->ImpersonationLevel;
+  Status = SepDuplicateToken(Token,
+                            ObjectAttributes,
+                            TokenType,
+                            ImpersonationLevel,
+                            ExistingImpersonationLevel,
+                            PreviousMode,
+                            &NewToken);
+
+  ObDereferenceObject(Token);
+
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("Failed to duplicate token (Status %lx)\n", Status);
+      return Status;
+    }
+
+  Status = ObInsertObject((PVOID)NewToken,
+                         NULL,
+                         DesiredAccess,
+                         0,
+                         NULL,
+                         NewTokenHandle);
+
+  ObDereferenceObject(NewToken);
+
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("Failed to create token handle (Status %lx)\n");
+      return Status;
+    }
+
+  return STATUS_SUCCESS;
 }
 
+
 VOID SepAdjustGroups(PACCESS_TOKEN Token,
                     ULONG a,
                     BOOLEAN ResetToDefault,
@@ -819,6 +932,7 @@ NtAdjustGroupsToken(IN HANDLE TokenHandle,
                   &c);
 #else
    UNIMPLEMENTED;
+   return(STATUS_NOT_IMPLEMENTED);
 #endif
 }
 
@@ -877,19 +991,26 @@ SepAdjustPrivileges(PACCESS_TOKEN Token,
 #endif
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
-                       IN BOOLEAN DisableAllPrivileges,
-                       IN PTOKEN_PRIVILEGES NewState,
-                       IN ULONG BufferLength,
-                       OUT PTOKEN_PRIVILEGES PreviousState,
-                       OUT PULONG ReturnLength)
+NtAdjustPrivilegesToken (IN HANDLE TokenHandle,
+                        IN BOOLEAN DisableAllPrivileges,
+                        IN PTOKEN_PRIVILEGES NewState,
+                        IN ULONG BufferLength,
+                        OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
+                        OUT PULONG ReturnLength OPTIONAL)
 {
-  PLUID_AND_ATTRIBUTES Privileges;
+//  PLUID_AND_ATTRIBUTES Privileges;
   KPROCESSOR_MODE PreviousMode;
-  ULONG PrivilegeCount;
+//  ULONG PrivilegeCount;
   PACCESS_TOKEN Token;
-  ULONG Length;
+//  ULONG Length;
+  ULONG i;
+  ULONG j;
+  ULONG k;
+  ULONG Count;
 #if 0
    ULONG a;
    ULONG b;
@@ -897,33 +1018,33 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
 #endif
   NTSTATUS Status;
 
-  DPRINT1("NtAdjustPrivilegesToken() called\n");
-
-  PrivilegeCount = NewState->PrivilegeCount;
-  PreviousMode = KeGetPreviousMode();
-  SeCaptureLuidAndAttributesArray(NewState->Privileges,
-                                 PrivilegeCount,
-                                 PreviousMode,
-                                 NULL,
-                                 0,
-                                 NonPagedPool,
-                                 1,
-                                 &Privileges,
-                                 &Length);
-
-  Status = ObReferenceObjectByHandle(TokenHandle,
-                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
-                                    SepTokenObjectType,
-                                    PreviousMode,
-                                    (PVOID*)&Token,
-                                    NULL);
+  DPRINT ("NtAdjustPrivilegesToken() called\n");
+
+//  PrivilegeCount = NewState->PrivilegeCount;
+  PreviousMode = KeGetPreviousMode ();
+//  SeCaptureLuidAndAttributesArray(NewState->Privileges,
+//                               PrivilegeCount,
+//                               PreviousMode,
+//                               NULL,
+//                               0,
+//                               NonPagedPool,
+//                               1,
+//                               &Privileges,
+//                               &Length);
+
+  Status = ObReferenceObjectByHandle (TokenHandle,
+                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+                                     SepTokenObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Token,
+                                     NULL);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT1("Failed to reference token (Status %lx)\n", Status);
-      SeReleaseLuidAndAttributesArray(Privileges,
-                                     PreviousMode,
-                                     0);
-      return(Status);
+      DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
+//      SeReleaseLuidAndAttributesArray(Privileges,
+//                                   PreviousMode,
+//                                   0);
+      return Status;
     }
 
 
@@ -939,15 +1060,86 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
                       &c);
 #endif
 
-  ObDereferenceObject(Token);
+  k = 0;
+  if (DisableAllPrivileges == TRUE)
+    {
+      for (i = 0; i < Token->PrivilegeCount; i++)
+       {
+         if (Token->Privileges[i].Attributes != 0)
+           {
+             DPRINT ("Attributes differ\n");
 
-  SeReleaseLuidAndAttributesArray(Privileges,
-                                 PreviousMode,
-                                 0);
+             /* Save current privilege */
+             if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
+               {
+                 PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
+                 PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
+                 k++;
+               }
+
+             /* Update current privlege */
+             Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
+           }
+       }
+      Status = STATUS_SUCCESS;
+    }
+  else
+    {
+      Count = 0;
+      for (i = 0; i < Token->PrivilegeCount; i++)
+       {
+         for (j = 0; j < NewState->PrivilegeCount; j++)
+           {
+             if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart &&
+                 Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart)
+               {
+                 DPRINT ("Found privilege\n");
 
-  DPRINT1("NtAdjustPrivilegesToken() done\n");
+                 if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) !=
+                     (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED))
+                   {
+                     DPRINT ("Attributes differ\n");
+                     DPRINT ("Current attributes %lx  desired attributes %lx\n",
+                             Token->Privileges[i].Attributes,
+                             NewState->Privileges[j].Attributes);
 
-  return STATUS_SUCCESS;
+                     /* Save current privilege */
+                     if (PreviousState != NULL && k < PreviousState->PrivilegeCount)
+                       {
+                         PreviousState->Privileges[k].Luid = Token->Privileges[i].Luid;
+                         PreviousState->Privileges[k].Attributes = Token->Privileges[i].Attributes;
+                         k++;
+                       }
+
+                     /* Update current privlege */
+                     Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
+                     Token->Privileges[i].Attributes |= 
+                       (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED);
+                     DPRINT ("New attributes %lx\n",
+                             Token->Privileges[i].Attributes);
+                   }
+                  Count++;
+               }
+           }
+       }
+      Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
+    }
+
+  if (ReturnLength != NULL)
+    {
+      *ReturnLength = sizeof(TOKEN_PRIVILEGES) +
+                     (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
+    }
+
+  ObDereferenceObject (Token);
+
+//  SeReleaseLuidAndAttributesArray(Privileges,
+//                               PreviousMode,
+//                               0);
+
+  DPRINT ("NtAdjustPrivilegesToken() done\n");
+
+  return Status;
 }
 
 
@@ -970,11 +1162,19 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process)
  /*
   * Initialize the token
   */
-  Status = ObCreateObject(NULL,
-                        TOKEN_ALL_ACCESS,
-                        NULL,
-                        SepTokenObjectType,
-                        (PVOID*)&AccessToken);
+  Status = ObCreateObject(KernelMode,
+                         SepTokenObjectType,
+                         NULL,
+                         KernelMode,
+                         NULL,
+                         sizeof(ACCESS_TOKEN),
+                         0,
+                         0,
+                         (PVOID*)&AccessToken);
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
 
   Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId);
   if (!NT_SUCCESS(Status))
@@ -1017,24 +1217,24 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process)
   AccessToken->UserAndGroups[i].Sid = (PSID) SidArea;
   AccessToken->UserAndGroups[i++].Attributes = 0;
   RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid);
-  SidArea += uLocalSystemLength;
+  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 += uAdminsLength;
+  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 += uWorldLength;
+  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 += uAuthUserLength;
+  SidArea = (char*)SidArea + uAuthUserLength;
 
   AccessToken->PrivilegeCount = 20;
 
@@ -1186,10 +1386,14 @@ NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
   if (!NT_SUCCESS(Status))
     return(Status);
 
-  Status = ObCreateObject(&TokenHandle,
-                         DesiredAccess,
-                         ObjectAttributes,
+  Status = ObCreateObject(ExGetPreviousMode(),
                          SepTokenObjectType,
+                         ObjectAttributes,
+                         ExGetPreviousMode(),
+                         NULL,
+                         sizeof(ACCESS_TOKEN),
+                         0,
+                         0,
                          (PVOID*)&AccessToken);
   if (!NT_SUCCESS(Status))
     {
@@ -1197,6 +1401,19 @@ NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
       return(Status);
     }
 
+  Status = ObInsertObject ((PVOID)AccessToken,
+                          NULL,
+                          DesiredAccess,
+                          0,
+                          NULL,
+                          &TokenHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("ObInsertObject() failed (Status %lx)\n");
+      ObDereferenceObject (AccessToken);
+      return Status;
+    }
+
   RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
              &TokenSource->SourceIdentifier);
   memcpy(AccessToken->TokenSource.SourceName,
@@ -1308,17 +1525,39 @@ NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
 }
 
 
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token,
+                            OUT PLUID LogonId)
+{
+  LogonId->LowPart = Token->AuthenticationId.LowPart;
+  LogonId->HighPart = Token->AuthenticationId.HighPart;
+
+  return STATUS_SUCCESS;
+}
+
+
+/*
+ * @implemented
+ */
 SECURITY_IMPERSONATION_LEVEL STDCALL
 SeTokenImpersonationLevel(IN PACCESS_TOKEN Token)
 {
-  return(Token->ImpersonationLevel);
+  return Token->ImpersonationLevel;
 }
 
 
+/*
+ * @implemented
+ */
 TOKEN_TYPE STDCALL
 SeTokenType(IN PACCESS_TOKEN Token)
 {
-  return(Token->TokenType);
+  return Token->TokenType;
 }
 
+
+
 /* EOF */