[ADVAPI32]
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 24 Oct 2014 16:52:57 +0000 (16:52 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 24 Oct 2014 16:52:57 +0000 (16:52 +0000)
* Move some functions from token.c to security.c.
CORE-8540

svn path=/trunk/; revision=64962

reactos/dll/win32/advapi32/token/token.c
reactos/dll/win32/advapi32/wine/security.c

index 5cb88a9..6be7890 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 
-/*
- * @implemented
- */
-BOOL WINAPI
-AdjustTokenGroups(HANDLE TokenHandle,
-                  BOOL ResetToDefault,
-                  PTOKEN_GROUPS NewState,
-                  DWORD BufferLength,
-                  PTOKEN_GROUPS PreviousState,
-                  PDWORD ReturnLength)
-{
-    NTSTATUS Status;
-
-    Status = NtAdjustGroupsToken(TokenHandle,
-                                 ResetToDefault,
-                                 NewState,
-                                 BufferLength,
-                                 PreviousState,
-                                 (PULONG)ReturnLength);
-    if (!NT_SUCCESS(Status))
-    {
-       SetLastError(RtlNtStatusToDosError(Status));
-       return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-AdjustTokenPrivileges(HANDLE TokenHandle,
-                      BOOL DisableAllPrivileges,
-                      PTOKEN_PRIVILEGES NewState,
-                      DWORD BufferLength,
-                      PTOKEN_PRIVILEGES PreviousState,
-                      PDWORD ReturnLength)
-{
-    NTSTATUS Status;
-
-    Status = NtAdjustPrivilegesToken(TokenHandle,
-                                     DisableAllPrivileges,
-                                     NewState,
-                                     BufferLength,
-                                     PreviousState,
-                                     (PULONG)ReturnLength);
-    if (STATUS_NOT_ALL_ASSIGNED == Status)
-    {
-        SetLastError(ERROR_NOT_ALL_ASSIGNED);
-        return TRUE;
-    }
-
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    /* AdjustTokenPrivileges is documented to do this */
-    SetLastError(ERROR_SUCCESS);
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-GetTokenInformation(HANDLE TokenHandle,
-                    TOKEN_INFORMATION_CLASS TokenInformationClass,
-                    LPVOID TokenInformation,
-                    DWORD TokenInformationLength,
-                    PDWORD ReturnLength)
-{
-    NTSTATUS Status;
-
-    Status = NtQueryInformationToken(TokenHandle,
-                                     TokenInformationClass,
-                                     TokenInformation,
-                                     TokenInformationLength,
-                                     (PULONG)ReturnLength);
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-  return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-SetTokenInformation(HANDLE TokenHandle,
-                    TOKEN_INFORMATION_CLASS TokenInformationClass,
-                    LPVOID TokenInformation,
-                    DWORD TokenInformationLength)
-{
-    NTSTATUS Status;
-
-    Status = NtSetInformationToken(TokenHandle,
-                                   TokenInformationClass,
-                                   TokenInformation,
-                                   TokenInformationLength);
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
-            IN HANDLE ClientToken,
-            IN DWORD DesiredAccess,
-            IN PGENERIC_MAPPING GenericMapping,
-            OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
-            IN OUT LPDWORD PrivilegeSetLength,
-            OUT LPDWORD GrantedAccess,
-            OUT LPBOOL AccessStatus)
-{
-    NTSTATUS Status;
-    NTSTATUS NtAccessStatus;
-
-    /* Do the access check */
-    Status = NtAccessCheck(pSecurityDescriptor,
-                           ClientToken,
-                           DesiredAccess,
-                           GenericMapping,
-                           PrivilegeSet,
-                           (PULONG)PrivilegeSetLength,
-                           (PACCESS_MASK)GrantedAccess,
-                           &NtAccessStatus);
-
-    /* See if the access check operation succeeded */
-    if (!NT_SUCCESS(Status))
-    {
-        /* Check failed */
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    /* Now check the access status  */
-    if (!NT_SUCCESS(NtAccessStatus))
-    {
-        /* Access denied */
-        SetLastError(RtlNtStatusToDosError(NtAccessStatus));
-        *AccessStatus = FALSE;
-    }
-    else
-    {
-        /* Access granted */
-        *AccessStatus = TRUE;
-    }
-
-    /* Check succeeded */
-    return TRUE;
-}
-
-/*
- * @unimplemented
- */
-BOOL WINAPI AccessCheckByType(
-    PSECURITY_DESCRIPTOR pSecurityDescriptor, 
-    PSID PrincipalSelfSid,
-    HANDLE ClientToken, 
-    DWORD DesiredAccess, 
-    POBJECT_TYPE_LIST ObjectTypeList,
-    DWORD ObjectTypeListLength,
-    PGENERIC_MAPPING GenericMapping,
-    PPRIVILEGE_SET PrivilegeSet,
-    LPDWORD PrivilegeSetLength, 
-    LPDWORD GrantedAccess,
-    LPBOOL AccessStatus)
-{
-       FIXME("stub\n");
-
-       *AccessStatus = TRUE;
-
-       return !*AccessStatus;
-}
-
-/*
- * @implemented
- */
-BOOL WINAPI
-OpenProcessToken(HANDLE ProcessHandle,
-                 DWORD DesiredAccess,
-                 PHANDLE TokenHandle)
-{
-    NTSTATUS Status;
-
-    TRACE("%p, %x, %p.\n", ProcessHandle, DesiredAccess, TokenHandle);
-
-    Status = NtOpenProcessToken(ProcessHandle,
-                                DesiredAccess,
-                                TokenHandle);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("NtOpenProcessToken failed! Status %08x.\n", Status);
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    TRACE("Returning token %p.\n", *TokenHandle);
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-OpenThreadToken(HANDLE ThreadHandle,
-                DWORD DesiredAccess,
-                BOOL OpenAsSelf,
-                PHANDLE TokenHandle)
-{
-    NTSTATUS Status;
-
-    Status = NtOpenThreadToken(ThreadHandle,
-                               DesiredAccess,
-                               OpenAsSelf,
-                               TokenHandle);
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-SetThreadToken(IN PHANDLE ThreadHandle  OPTIONAL,
-               IN HANDLE TokenHandle)
-{
-    NTSTATUS Status;
-    HANDLE hThread;
-
-    hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread();
-
-    Status = NtSetInformationThread(hThread,
-                                    ThreadImpersonationToken,
-                                    &TokenHandle,
-                                    sizeof(HANDLE));
-    if (!NT_SUCCESS(Status))
-    {
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
-                 IN DWORD dwDesiredAccess,
-                 IN LPSECURITY_ATTRIBUTES lpTokenAttributes  OPTIONAL,
-                 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
-                 IN TOKEN_TYPE TokenType,
-                 OUT PHANDLE DuplicateTokenHandle)
-{
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    NTSTATUS Status;
-    SECURITY_QUALITY_OF_SERVICE Sqos;
-
-    TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
-        ImpersonationLevel, TokenType, DuplicateTokenHandle);
-
-    Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
-    Sqos.ImpersonationLevel = ImpersonationLevel;
-    Sqos.ContextTrackingMode = 0;
-    Sqos.EffectiveOnly = FALSE;
-
-    if (lpTokenAttributes != NULL)
-    {
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   NULL,
-                                   lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
-                                   NULL,
-                                   lpTokenAttributes->lpSecurityDescriptor);
-    }
-    else
-    {
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   NULL,
-                                   0,
-                                   NULL,
-                                   NULL);
-    }
-
-    ObjectAttributes.SecurityQualityOfService = &Sqos;
-
-    Status = NtDuplicateToken(ExistingTokenHandle,
-                              dwDesiredAccess,
-                              &ObjectAttributes,
-                              FALSE,
-                              TokenType,
-                              DuplicateTokenHandle);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("NtDuplicateToken failed: Status %08x\n", Status);
-        SetLastError(RtlNtStatusToDosError(Status));
-        return FALSE;
-    }
-
-    TRACE("Returning token %p.\n", *DuplicateTokenHandle);
-
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-DuplicateToken(IN HANDLE ExistingTokenHandle,
-               IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
-               OUT PHANDLE DuplicateTokenHandle)
-{
-    return DuplicateTokenEx(ExistingTokenHandle,
-                            TOKEN_IMPERSONATE | TOKEN_QUERY,
-                            NULL,
-                            ImpersonationLevel,
-                            TokenImpersonation,
-                            DuplicateTokenHandle);
-}
-
-
 /*
  * @implemented
  */
@@ -617,23 +266,6 @@ AllocAndReadRestrictedSids:
     return Ret;
 }
 
-
-BOOL WINAPI
-CreateRestrictedToken(HANDLE TokenHandle,
-                      DWORD Flags,
-                      DWORD DisableSidCount,
-                      PSID_AND_ATTRIBUTES pSidAndAttributes,
-                      DWORD DeletePrivilegeCount,
-                      PLUID_AND_ATTRIBUTES pLUIDAndAttributes,
-                      DWORD RestrictedSidCount,
-                      PSID_AND_ATTRIBUTES pSIDAndAttributes,
-                      PHANDLE NewTokenHandle)
-{
-    UNIMPLEMENTED;
-    return FALSE;
-}
-
-
 /*
  * @unimplemented
  */
@@ -711,20 +343,3 @@ GetSiteSidFromToken(IN HANDLE TokenHandle)
     RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedSids);
     return PSiteSid;
 }
-
-
-BOOL
-WINAPI
-CreateProcessWithTokenW(IN HANDLE hToken,
-                        IN DWORD dwLogonFlags,
-                        IN LPCWSTR lpApplicationName OPTIONAL,
-                        IN OUT LPWSTR lpCommandLine OPTIONAL,
-                        IN DWORD dwCreationFlags,
-                        IN LPVOID lpEnvironment OPTIONAL,
-                        IN LPCWSTR lpCurrentDirectory OPTIONAL,
-                        IN LPSTARTUPINFOW lpStartupInfo,
-                        OUT LPPROCESS_INFORMATION lpProcessInfo)
-{
-    UNIMPLEMENTED;
-    return FALSE;
-}
index 130f6e5..7dd5849 100644 (file)
@@ -313,6 +313,212 @@ static const RECORD SidTable[] =
 
 /* Exported functions */
 
+/*
+ * @implemented
+ */
+BOOL WINAPI
+OpenProcessToken(HANDLE ProcessHandle,
+                 DWORD DesiredAccess,
+                 PHANDLE TokenHandle)
+{
+    NTSTATUS Status;
+
+    TRACE("%p, %x, %p.\n", ProcessHandle, DesiredAccess, TokenHandle);
+
+    Status = NtOpenProcessToken(ProcessHandle,
+                                DesiredAccess,
+                                TokenHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("NtOpenProcessToken failed! Status %08x.\n", Status);
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    TRACE("Returning token %p.\n", *TokenHandle);
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+OpenThreadToken(HANDLE ThreadHandle,
+                DWORD DesiredAccess,
+                BOOL OpenAsSelf,
+                PHANDLE TokenHandle)
+{
+    NTSTATUS Status;
+
+    Status = NtOpenThreadToken(ThreadHandle,
+                               DesiredAccess,
+                               OpenAsSelf,
+                               TokenHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+AdjustTokenGroups(HANDLE TokenHandle,
+                  BOOL ResetToDefault,
+                  PTOKEN_GROUPS NewState,
+                  DWORD BufferLength,
+                  PTOKEN_GROUPS PreviousState,
+                  PDWORD ReturnLength)
+{
+    NTSTATUS Status;
+
+    Status = NtAdjustGroupsToken(TokenHandle,
+                                 ResetToDefault,
+                                 NewState,
+                                 BufferLength,
+                                 PreviousState,
+                                 (PULONG)ReturnLength);
+    if (!NT_SUCCESS(Status))
+    {
+       SetLastError(RtlNtStatusToDosError(Status));
+       return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+AdjustTokenPrivileges(HANDLE TokenHandle,
+                      BOOL DisableAllPrivileges,
+                      PTOKEN_PRIVILEGES NewState,
+                      DWORD BufferLength,
+                      PTOKEN_PRIVILEGES PreviousState,
+                      PDWORD ReturnLength)
+{
+    NTSTATUS Status;
+
+    Status = NtAdjustPrivilegesToken(TokenHandle,
+                                     DisableAllPrivileges,
+                                     NewState,
+                                     BufferLength,
+                                     PreviousState,
+                                     (PULONG)ReturnLength);
+    if (STATUS_NOT_ALL_ASSIGNED == Status)
+    {
+        SetLastError(ERROR_NOT_ALL_ASSIGNED);
+        return TRUE;
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    /* AdjustTokenPrivileges is documented to do this */
+    SetLastError(ERROR_SUCCESS);
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+GetTokenInformation(HANDLE TokenHandle,
+                    TOKEN_INFORMATION_CLASS TokenInformationClass,
+                    LPVOID TokenInformation,
+                    DWORD TokenInformationLength,
+                    PDWORD ReturnLength)
+{
+    NTSTATUS Status;
+
+    Status = NtQueryInformationToken(TokenHandle,
+                                     TokenInformationClass,
+                                     TokenInformation,
+                                     TokenInformationLength,
+                                     (PULONG)ReturnLength);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+SetTokenInformation(HANDLE TokenHandle,
+                    TOKEN_INFORMATION_CLASS TokenInformationClass,
+                    LPVOID TokenInformation,
+                    DWORD TokenInformationLength)
+{
+    NTSTATUS Status;
+
+    Status = NtSetInformationToken(TokenHandle,
+                                   TokenInformationClass,
+                                   TokenInformation,
+                                   TokenInformationLength);
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+SetThreadToken(IN PHANDLE ThreadHandle  OPTIONAL,
+               IN HANDLE TokenHandle)
+{
+    NTSTATUS Status;
+    HANDLE hThread;
+
+    hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread();
+
+    Status = NtSetInformationThread(hThread,
+                                    ThreadImpersonationToken,
+                                    &TokenHandle,
+                                    sizeof(HANDLE));
+    if (!NT_SUCCESS(Status))
+    {
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+BOOL WINAPI
+CreateRestrictedToken(HANDLE TokenHandle,
+                      DWORD Flags,
+                      DWORD DisableSidCount,
+                      PSID_AND_ATTRIBUTES pSidAndAttributes,
+                      DWORD DeletePrivilegeCount,
+                      PLUID_AND_ATTRIBUTES pLUIDAndAttributes,
+                      DWORD RestrictedSidCount,
+                      PSID_AND_ATTRIBUTES pSIDAndAttributes,
+                      PHANDLE NewTokenHandle)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
 /*
  * @implemented
  */
@@ -593,6 +799,81 @@ GetLengthSid(PSID pSid)
     return (DWORD)RtlLengthSid(pSid);
 }
 
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
+            IN HANDLE ClientToken,
+            IN DWORD DesiredAccess,
+            IN PGENERIC_MAPPING GenericMapping,
+            OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
+            IN OUT LPDWORD PrivilegeSetLength,
+            OUT LPDWORD GrantedAccess,
+            OUT LPBOOL AccessStatus)
+{
+    NTSTATUS Status;
+    NTSTATUS NtAccessStatus;
+
+    /* Do the access check */
+    Status = NtAccessCheck(pSecurityDescriptor,
+                           ClientToken,
+                           DesiredAccess,
+                           GenericMapping,
+                           PrivilegeSet,
+                           (PULONG)PrivilegeSetLength,
+                           (PACCESS_MASK)GrantedAccess,
+                           &NtAccessStatus);
+
+    /* See if the access check operation succeeded */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Check failed */
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    /* Now check the access status  */
+    if (!NT_SUCCESS(NtAccessStatus))
+    {
+        /* Access denied */
+        SetLastError(RtlNtStatusToDosError(NtAccessStatus));
+        *AccessStatus = FALSE;
+    }
+    else
+    {
+        /* Access granted */
+        *AccessStatus = TRUE;
+    }
+
+    /* Check succeeded */
+    return TRUE;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL WINAPI AccessCheckByType(
+    PSECURITY_DESCRIPTOR pSecurityDescriptor, 
+    PSID PrincipalSelfSid,
+    HANDLE ClientToken, 
+    DWORD DesiredAccess, 
+    POBJECT_TYPE_LIST ObjectTypeList,
+    DWORD ObjectTypeListLength,
+    PGENERIC_MAPPING GenericMapping,
+    PPRIVILEGE_SET PrivilegeSet,
+    LPDWORD PrivilegeSetLength, 
+    LPDWORD GrantedAccess,
+    LPBOOL AccessStatus)
+{
+       FIXME("stub\n");
+
+       *AccessStatus = TRUE;
+
+       return !*AccessStatus;
+}
+
 /**********************************************************************
  *     PrivilegeCheck                                  EXPORTED
  *
@@ -1801,6 +2082,98 @@ ConvertSidToStringSidA(PSID Sid,
     return TRUE;
 }
 
+BOOL
+WINAPI
+CreateProcessWithTokenW(IN HANDLE hToken,
+                        IN DWORD dwLogonFlags,
+                        IN LPCWSTR lpApplicationName OPTIONAL,
+                        IN OUT LPWSTR lpCommandLine OPTIONAL,
+                        IN DWORD dwCreationFlags,
+                        IN LPVOID lpEnvironment OPTIONAL,
+                        IN LPCWSTR lpCurrentDirectory OPTIONAL,
+                        IN LPSTARTUPINFOW lpStartupInfo,
+                        OUT LPPROCESS_INFORMATION lpProcessInfo)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
+                 IN DWORD dwDesiredAccess,
+                 IN LPSECURITY_ATTRIBUTES lpTokenAttributes  OPTIONAL,
+                 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+                 IN TOKEN_TYPE TokenType,
+                 OUT PHANDLE DuplicateTokenHandle)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    SECURITY_QUALITY_OF_SERVICE Sqos;
+
+    TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
+        ImpersonationLevel, TokenType, DuplicateTokenHandle);
+
+    Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+    Sqos.ImpersonationLevel = ImpersonationLevel;
+    Sqos.ContextTrackingMode = 0;
+    Sqos.EffectiveOnly = FALSE;
+
+    if (lpTokenAttributes != NULL)
+    {
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   NULL,
+                                   lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
+                                   NULL,
+                                   lpTokenAttributes->lpSecurityDescriptor);
+    }
+    else
+    {
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   NULL,
+                                   0,
+                                   NULL,
+                                   NULL);
+    }
+
+    ObjectAttributes.SecurityQualityOfService = &Sqos;
+
+    Status = NtDuplicateToken(ExistingTokenHandle,
+                              dwDesiredAccess,
+                              &ObjectAttributes,
+                              FALSE,
+                              TokenType,
+                              DuplicateTokenHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("NtDuplicateToken failed: Status %08x\n", Status);
+        SetLastError(RtlNtStatusToDosError(Status));
+        return FALSE;
+    }
+
+    TRACE("Returning token %p.\n", *DuplicateTokenHandle);
+
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL WINAPI
+DuplicateToken(IN HANDLE ExistingTokenHandle,
+               IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+               OUT PHANDLE DuplicateTokenHandle)
+{
+    return DuplicateTokenEx(ExistingTokenHandle,
+                            TOKEN_IMPERSONATE | TOKEN_QUERY,
+                            NULL,
+                            ImpersonationLevel,
+                            TokenImpersonation,
+                            DuplicateTokenHandle);
+}
+
 /*
  * @implemented
  */