/*++ Copyright (c) 1989 Microsoft Corporation Module Name: psimpers.c Abstract: This module implements the NtImpersonateThread() service. Author: Jim Kelly (JimK) 20-Apr-1991 Revision History: --*/ #include "psp.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, NtImpersonateThread) #endif //ALLOC_PRAGMA NTSTATUS NtImpersonateThread( IN HANDLE ServerThreadHandle, IN HANDLE ClientThreadHandle, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos ) /*++ Routine Description: This routine is used to cause the server thread to impersonate the client thread. The impersonation is done according to the specified quality of service parameters. Arguments: ServerThreadHandle - Is a handle to the server thread (the impersonator, or doing the impersonation). This handle must be open for THREAD_IMPERSONATE access. ClientThreadHandle - Is a handle to the Client thread (the impersonatee, or one being impersonated). This handle must be open for THREAD_DIRECT_IMPERSONATION access. SecurityQos - A pointer to security quality of service information indicating what form of impersonation is to be performed. Return Value: STATUS_SUCCESS - Indicates the call completed successfully. --*/ { KPROCESSOR_MODE PreviousMode; NTSTATUS Status; PETHREAD ClientThread, ServerThread; SECURITY_QUALITY_OF_SERVICE CapturedQos; SECURITY_CLIENT_CONTEXT ClientSecurityContext; // // Get previous processor mode and probe and capture arguments if necessary // PreviousMode = KeGetPreviousMode(); try { if (PreviousMode != KernelMode) { ProbeForReadSmallStructure (SecurityQos, sizeof (SECURITY_QUALITY_OF_SERVICE), sizeof (ULONG)); } CapturedQos = *SecurityQos; } except (ExSystemExceptionFilter ()) { return GetExceptionCode (); } // // Reference the client thread, checking for appropriate access. // Status = ObReferenceObjectByHandle (ClientThreadHandle, // Handle THREAD_DIRECT_IMPERSONATION, // DesiredAccess PsThreadType, // ObjectType PreviousMode, // AccessMode &ClientThread, // Object NULL); // GrantedAccess if (!NT_SUCCESS (Status)) { return Status; } // // Reference the client thread, checking for appropriate access. // Status = ObReferenceObjectByHandle (ServerThreadHandle, // Handle THREAD_IMPERSONATE, // DesiredAccess PsThreadType, // ObjectType PreviousMode, // AccessMode &ServerThread, // Object NULL); // GrantedAccess if (!NT_SUCCESS (Status)) { ObDereferenceObject (ClientThread); return Status; } // // Get the client's security context // Status = SeCreateClientSecurity (ClientThread, // ClientThread &CapturedQos, // SecurityQos FALSE, // ServerIsRemote &ClientSecurityContext); // ClientContext if (!NT_SUCCESS (Status)) { ObDereferenceObject (ServerThread); ObDereferenceObject (ClientThread); return Status; } // // Impersonate the client // Status = SeImpersonateClientEx (&ClientSecurityContext, ServerThread); SeDeleteClientSecurity (&ClientSecurityContext); // // Done. // ObDereferenceObject (ServerThread); ObDereferenceObject (ClientThread); return Status ; }