NtDuplicateToken() must create and return a handle to the duplicated token.
[reactos.git] / reactos / ntoskrnl / se / token.c
index 9f28e83..003300c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: token.c,v 1.18 2002/07/04 19:56:36 dwelch 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,
@@ -69,39 +72,6 @@ NTSTATUS SeExchangePrimaryToken(PEPROCESS Process,
    return(STATUS_SUCCESS);
 }
 
-
-NTSTATUS
-RtlCopySidAndAttributesArray(ULONG Count,                      // ebp + 8
-                            PSID_AND_ATTRIBUTES Src,           // ebp + C
-                            ULONG SidAreaSize,                 // ebp + 10
-                            PSID_AND_ATTRIBUTES Dest,          // ebp + 14
-                            PVOID SidArea,                     // ebp + 18
-                            PVOID* RemainingSidArea,           // ebp + 1C
-                            PULONG RemainingSidAreaSize)       // ebp + 20
-{
-   ULONG Length; // ebp - 4
-   ULONG i;
-   
-   Length = SidAreaSize;
-   
-   for (i=0; i<Count; i++)
-     {
-       if (RtlLengthSid(Src[i].Sid) > Length)
-         {
-            return(STATUS_BUFFER_TOO_SMALL);
-         }
-       Length = Length - RtlLengthSid(Src[i].Sid);
-       Dest[i].Sid = SidArea;
-       Dest[i].Attributes = Src[i].Attributes;
-       RtlCopySid(RtlLengthSid(Src[i].Sid), SidArea, Src[i].Sid);
-       SidArea = SidArea + RtlLengthSid(Src[i].Sid);
-     }
-   *RemainingSidArea = SidArea;
-   *RemainingSidAreaSize = Length;
-   return(STATUS_SUCCESS);
-}
-
-
 static ULONG
 RtlLengthSidAndAttributes(ULONG Count,
                          PSID_AND_ATTRIBUTES Src)
@@ -177,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))
     {
@@ -205,10 +179,14 @@ SepDuplicateToken(PACCESS_TOKEN Token,
   AccessToken->TokenInUse = 0;
   AccessToken->TokenType  = TokenType;
   AccessToken->ImpersonationLevel = Level;
-  AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID;
+  AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
+  AccessToken->AuthenticationId.HighPart = 0;
 
-  AccessToken->TokenSource.SourceIdentifier.QuadPart = Token->TokenSource.SourceIdentifier.QuadPart;
-  memcpy(AccessToken->TokenSource.SourceName, Token->TokenSource.SourceName, sizeof(Token->TokenSource.SourceName));
+  AccessToken->TokenSource.SourceIdentifier.LowPart = Token->TokenSource.SourceIdentifier.LowPart;
+  AccessToken->TokenSource.SourceIdentifier.HighPart = Token->TokenSource.SourceIdentifier.HighPart;
+  memcpy(AccessToken->TokenSource.SourceName,
+        Token->TokenSource.SourceName,
+        sizeof(Token->TokenSource.SourceName));
   AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart;
   AccessToken->UserAndGroupCount = Token->UserAndGroupCount;
   AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex;
@@ -341,6 +319,9 @@ NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token,
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 SeCreateClientSecurity(IN struct _ETHREAD *Thread,
                       IN PSECURITY_QUALITY_OF_SERVICE Qos,
@@ -430,6 +411,9 @@ SeCreateClientSecurity(IN struct _ETHREAD *Thread,
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
 SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext,
                    IN PETHREAD ServerThread OPTIONAL)
@@ -472,7 +456,7 @@ SepDeleteToken(PVOID ObjectBody)
 }
 
 
-VOID
+VOID INIT_FUNCTION
 SepInitializeTokenImplementation(VOID)
 {
   SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
@@ -498,9 +482,13 @@ SepInitializeTokenImplementation(VOID)
 
   RtlCreateUnicodeString(&SepTokenObjectType->TypeName,
                         L"Token");
+  ObpCreateTypeObject (SepTokenObjectType);
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
 NtQueryInformationToken(IN HANDLE TokenHandle,
                        IN TOKEN_INFORMATION_CLASS TokenInformationClass,
@@ -509,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,
@@ -531,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;
          }
@@ -545,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,
@@ -576,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;
          }
@@ -610,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;
          }
@@ -630,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;
          }
@@ -651,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
          {
@@ -671,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;
          }
@@ -691,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;
          }
@@ -706,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;
          }
@@ -721,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;
          }
@@ -753,6 +741,11 @@ NtQueryInformationToken(IN HANDLE TokenHandle,
   return(Status);
 }
 
+/*
+ * NtSetTokenInformation: Partly implemented.
+ * Unimplemented:
+ *  TokenOrigin, TokenDefaultDacl, TokenSessionId
+ */
 
 NTSTATUS STDCALL
 NtSetInformationToken(IN HANDLE TokenHandle,
@@ -760,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,
@@ -772,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,
@@ -848,104 +932,214 @@ NtAdjustGroupsToken(IN HANDLE TokenHandle,
                   &c);
 #else
    UNIMPLEMENTED;
+   return(STATUS_NOT_IMPLEMENTED);
 #endif
 }
 
 
 #if 0
-NTSTATUS SepAdjustPrivileges(PACCESS_TOKEN Token,           // 0x8
-                            ULONG a,                       // 0xC
-                            KPROCESSOR_MODE PreviousMode,  // 0x10
-                            ULONG PrivilegeCount,          // 0x14
-                            PLUID_AND_ATTRIBUTES Privileges, // 0x18
-                            PTOKEN_PRIVILEGES* PreviousState, // 0x1C
-                            PULONG b, // 0x20
-                            PULONG c, // 0x24
-                            PULONG d) // 0x28
+NTSTATUS
+SepAdjustPrivileges(PACCESS_TOKEN Token,
+                   ULONG a,
+                   KPROCESSOR_MODE PreviousMode,
+                   ULONG PrivilegeCount,
+                   PLUID_AND_ATTRIBUTES Privileges,
+                   PTOKEN_PRIVILEGES* PreviousState,
+                   PULONG b,
+                   PULONG c,
+                   PULONG d)
 {
-   ULONG i;
-   
-   *c = 0;
-   if (Token->PrivilegeCount > 0)
-     {
-       for (i=0; i<Token->PrivilegeCount; i++)
-         {
-            if (PreviousMode != 0)
-              {
-                 if (!(Token->Privileges[i]->Attributes & 
-                       SE_PRIVILEGE_ENABLED))
+  ULONG i;
+
+  *c = 0;
+
+  if (Token->PrivilegeCount > 0)
+    {
+      for (i = 0; i < Token->PrivilegeCount; i++)
+       {
+         if (PreviousMode != KernelMode)
+           {
+             if (Token->Privileges[i]->Attributes & SE_PRIVILEGE_ENABLED == 0)
+               {
+                 if (a != 0)
                    {
-                      if (a != 0)
-                        {
-                           if (PreviousState != NULL)
-                             {
-                                memcpy(&PreviousState[i],
-                                       &Token->Privileges[i],
-                                       sizeof(LUID_AND_ATTRIBUTES));
-                             }
-                           Token->Privileges[i].Attributes = 
-                             Token->Privileges[i].Attributes & 
-                             (~SE_PRIVILEGE_ENABLED);
-                        }
+                     if (PreviousState != NULL)
+                       {
+                         memcpy(&PreviousState[i],
+                                &Token->Privileges[i],
+                                sizeof(LUID_AND_ATTRIBUTES));
+                       }
+                     Token->Privileges[i].Attributes &= (~SE_PRIVILEGE_ENABLED);
                    }
-              }
-         }
-     }
-   if (PreviousMode != 0)
-     {
-       Token->TokenFlags = Token->TokenFlags & (~1);
-     }
-   else
-     {
-       if (PrivilegeCount <= ?)
-         {
-            
-         }
+               }
+           }
+       }
+    }
+
+  if (PreviousMode != KernelMode)
+    {
+      Token->TokenFlags = Token->TokenFlags & (~1);
+    }
+  else
+    {
+      if (PrivilegeCount <= ?)
+       {
+       }
      }
    if (
 }
 #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;
+  KPROCESSOR_MODE PreviousMode;
+//  ULONG PrivilegeCount;
+  PACCESS_TOKEN Token;
+//  ULONG Length;
+  ULONG i;
+  ULONG j;
+  ULONG k;
+  ULONG Count;
 #if 0
-   ULONG PrivilegeCount;
-   ULONG Length;
-   PSID_AND_ATTRIBUTES Privileges;
    ULONG a;
    ULONG b;
    ULONG c;
-   
-   PrivilegeCount = NewState->PrivilegeCount;
-   
-   SeCaptureLuidAndAttributesArray(NewState->Privileges,
-                                  &PrivilegeCount,
-                                  KeGetPreviousMode(),
-                                  NULL,
-                                  0,
-                                  NonPagedPool,
-                                  1,
-                                  &Privileges.
-                                  &Length);
+#endif
+  NTSTATUS Status;
+
+  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;
+    }
+
+
+#if 0
    SepAdjustPrivileges(Token,
                       0,
-                      KeGetPreviousMode(),
+                      PreviousMode,
                       PrivilegeCount,
                       Privileges,
                       PreviousState,
                       &a,
                       &b,
                       &c);
-#else
-   UNIMPLEMENTED;
 #endif
+
+  k = 0;
+  if (DisableAllPrivileges == TRUE)
+    {
+      for (i = 0; i < Token->PrivilegeCount; i++)
+       {
+         if (Token->Privileges[i].Attributes != 0)
+           {
+             DPRINT ("Attributes differ\n");
+
+             /* 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");
+
+                 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);
+
+                     /* 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;
 }
 
 
@@ -968,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))
@@ -988,11 +1190,13 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process)
       return(Status);
     }
 
-  AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID;
+  AccessToken->AuthenticationId.LowPart = SYSTEM_LUID;
+  AccessToken->AuthenticationId.HighPart = 0;
 
   AccessToken->TokenType = TokenPrimary;
   AccessToken->ImpersonationLevel = SecurityDelegation;
-  AccessToken->TokenSource.SourceIdentifier.QuadPart = 0;
+  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;
@@ -1013,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;
 
@@ -1111,8 +1315,8 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process)
   assert( i == 20 );
 
   uSize = sizeof(ACL);
-  uSize += sizeof(ACE_HEADER) + uLocalSystemLength;
-  uSize += sizeof(ACE_HEADER) + uAdminsLength;
+  uSize += sizeof(ACE) + uLocalSystemLength;
+  uSize += sizeof(ACE) + uAdminsLength;
   uSize = (uSize & (~3)) + 8;
   AccessToken->DefaultDacl =
     (PACL) ExAllocatePoolWithTag(NonPagedPool,
@@ -1139,6 +1343,7 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process)
   return(STATUS_SUCCESS);
 }
 
+
 NTSTATUS STDCALL
 NtCreateToken(OUT PHANDLE UnsafeTokenHandle,
              IN ACCESS_MASK DesiredAccess,
@@ -1181,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))
     {
@@ -1192,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,
@@ -1303,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 */