00034                    :
00035 
00036     This routine 
is used to cause 
the server thread to impersonate 
the client
00037     thread.  The impersonation 
is done according to 
the specified quality
00038     of service parameters.
00039 
00040 
00041 
00042 Arguments:
00043 
00044     ServerThreadHandle - Is a handle to 
the server thread (the impersonator, or
00045         doing the impersonation).  This handle must be open 
for
00046         THREAD_IMPERSONATE access.
00047 
00048     ClientThreadHandle - Is a handle to 
the Client thread (the impersonatee, or
00049         one being impersonated).   This handle must be open 
for
00050         THREAD_DIRECT_IMPERSONATION access.
00051 
00052 
00053     
SecurityQos - 
A pointer to security quality of service information
00054         indicating what form of impersonation 
is to be performed.
00055 
00056 
00057 
00058 Return Value:
00059 
00060     STATUS_SUCCESS - Indicates 
the call completed successfully.
00061 
00062 
00063 --*/
00064 
00065 {
00066 
00067 
00068     
KPROCESSOR_MODE PreviousMode;
00069     
NTSTATUS Status;
00070     
PETHREAD ClientThread, 
ServerThread;
00071     SECURITY_QUALITY_OF_SERVICE CapturedQos;
00072     
SECURITY_CLIENT_CONTEXT ClientSecurityContext;
00073 
00074     
00075     
00076     
00077 
00078     PreviousMode = KeGetPreviousMode();
00079     
if (PreviousMode != 
KernelMode) {
00080 
00081         
try {
00082 
00083             
ProbeForRead( SecurityQos,
00084                           
sizeof( SECURITY_QUALITY_OF_SERVICE ),
00085                           
sizeof( ULONG )
00086                           );
00087             CapturedQos = (*SecurityQos);
00088 
00089         } except( EXCEPTION_EXECUTE_HANDLER ) {
00090             
return( GetExceptionCode() );
00091         }
00092 
00093     } 
else {
00094 
00095         CapturedQos = *
SecurityQos;
00096 
00097     }
00098 
00099 
00100     
00101     
00102     
00103 
00104     
Status = 
ObReferenceObjectByHandle(
00105                  ClientThreadHandle,           
00106                  THREAD_DIRECT_IMPERSONATION,  
00107                  PsThreadType,                
00108                  PreviousMode,                 
00109                  (PVOID *)&ClientThread,       
00110                  NULL                          
00111                  );
00112 
00113     
if ( !
NT_SUCCESS(Status) ) {
00114         
return Status;
00115     }
00116 
00117     
00118     
00119     
00120 
00121     
Status = 
ObReferenceObjectByHandle(
00122                  ServerThreadHandle,           
00123                  THREAD_IMPERSONATE,           
00124                  PsThreadType,                
00125                  PreviousMode,                 
00126                  (PVOID *)&ServerThread,       
00127                  NULL                          
00128                  );
00129 
00130     
if ( !
NT_SUCCESS(Status) ) {
00131         
ObDereferenceObject( ClientThread );
00132         
return Status;
00133     }
00134 
00135 
00136     
00137     
00138     
00139 
00140     
Status = 
SeCreateClientSecurity (
00141                  ClientThread,          
00142                  &CapturedQos,          
00143                  FALSE,                 
00144                  &ClientSecurityContext  
00145                  );
00146 
00147     
if ( !
NT_SUCCESS(Status) ) {
00148         
ObDereferenceObject( ServerThread );
00149         
ObDereferenceObject( ClientThread );
00150         
return Status;
00151     }
00152 
00153 
00154     
00155     
00156     
00157 
00158     
Status = 
SeImpersonateClientEx( &ClientSecurityContext, ServerThread );
00159 
00160     
SeDeleteClientSecurity( &ClientSecurityContext );
00161 
00162     
00163     
00164     
00165 
00166 
00167     
ObDereferenceObject( ServerThread );
00168     
ObDereferenceObject( ClientThread );
00169 
00170     
return Status ;
00171 }
}