Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

974 lines
26 KiB

//=================================================================
//
// ImpLogonUser.CPP -- Class to perform impersonation of logged on user.
//
// Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
//
// Revisions: 09/09/97 a-sanjes Created
//
//=================================================================
//#define _WIN32_DCOM // For CoImpersonateUser and CoRevertToSelf
//#include <objbase.h>
#include "precomp.h"
#ifdef NTONLY
#include <tchar.h>
#include <winerror.h>
#include <cominit.h>
#include <lockwrap.h>
#include "Sid.h"
#include "AccessEntry.h" // CAccessEntry class
#include "AccessEntryList.h"
#include "DACL.h" // CDACL class
#include "SACL.h"
#include "securitydescriptor.h"
#include "CToken.h"
#include "SecureKernelObj.h"
#include "implogonuser.h"
#include "cluidhelper.h"
static DWORD s_dwProcessID = 0;
static CCritSec g_csImpersonate;
//////////////////////////////////////////////////////////////////////////////
//
// implogonuser.cpp - Class implementation of CImpersonateLoggedOnUser.
//
// This class is intended to provide a way for a process to identify the shell
// process on a Windows NT system, and using the access token of that process
// to attempt to impersonate the user logged onto the Interactive Desktop of
// a workstation.
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::CImpersonateLoggedOnUser
//
// DESCRIPTION : Constructor
//
// INPUTS : NONE
//
// OUTPUTS : none
//
// RETURNS : nothing
//
// COMMENTS : Constructs empty instance to prepare for impersonation of user.
//
//////////////////////////////////////////////////////////////////////////////
CImpersonateLoggedOnUser::CImpersonateLoggedOnUser() :
m_hShellProcess(NULL),
m_hUserToken(NULL),
m_fImpersonatingUser(FALSE) ,
m_hThreadToken ( INVALID_HANDLE_VALUE )
{
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::~CImpersonateLoggedOnUser
//
// DESCRIPTION : Destructor
//
// INPUTS : none
//
// OUTPUTS : none
//
// RETURNS : nothing
//
// COMMENTS : Class destructor
//
//////////////////////////////////////////////////////////////////////////////
CImpersonateLoggedOnUser::~CImpersonateLoggedOnUser( void )
{
// Stop any current impersonation
End();
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::Begin
//
// DESCRIPTION : Attempts to begin impersonation of user.
//
// INPUTS : none
//
// OUTPUTS : none
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Uses helper functions to try to impersonate the
// currently logged on user. The process must have
// the proper level of access to perform the operation.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::Begin( void )
{
BOOL fReturn = FALSE;
TCHAR szShellProcessName[256];
LogMessage(_T("CImpersonateLoggedOnUser::Begin"));
// Only continue if we are not already impersonating a user
if (!m_fImpersonatingUser )
{
//Store the current thread token, assuming that the thread is impersonating somebody (DCOM client)
if ( !OpenThreadToken ( GetCurrentThread(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, TRUE, &m_hThreadToken ) )
{
m_hThreadToken = INVALID_HANDLE_VALUE;
}
// We will need a copy of PSAPI.DLL and a bunch of entry point
// addresses before we can continue, so let our base class take
// care of this.
// We need a handle for the Shell Process in order to
// successfully impersonate the user.
if ( NULL == m_hShellProcess )
{
if ( LoadShellName( szShellProcessName, sizeof(szShellProcessName) ) )
FindShellProcess( szShellProcessName);
else
LogErrorMessage(_T("LoadShellName failed"));
}
if ( NULL != m_hShellProcess )
{
fReturn = ImpersonateUser();
}
else
{
// We didn't find the Shell Process Name that we extracted from the
// registry. We saw this happening on Alphas that seem to get "fx32strt.exe"
// dumped in the shell. In these cases, it seems to cause explorer to run.
// So with that in mind, if we drop down in this branch of code, we're going
// to retry the locate shell process operation using Explorer.Exe.
if ( IsErrorLoggingEnabled() )
{
CHString sTemp;
sTemp.Format(_T("Shell Name %s in Registry not found in process list."), szShellProcessName);
LogErrorMessage(sTemp);
}
FindShellProcess( IDS_WINNT_SHELLNAME_EXPLORER ) ;
// m_hShellProcess will be non-NULL if and only if we got one.
if ( NULL != m_hShellProcess )
{
fReturn = ImpersonateUser();
}
else
{
LogErrorMessage(_T("Unable to locate Shell Process, Impersonation failed."));
SetLastError(0);
}
}
}
else
{
LogMessage(_T("CImpersonateLoggedOnUser::Begin - Already impersonated"));
fReturn = TRUE; // Already initialized
}
// We don't yet have a way to know whether explorer is really alive
// because we're impersonating someone and I can't find a way to
// revert back to LocalSystem. So, for now just set it to 0.
SetLastError(0);
return fReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::End
//
// DESCRIPTION : Ends impersonation of logged on user
//
// INPUTS : none
//
// OUTPUTS : none
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Ends impersonation of logged on user. Clears all elements
// of class as a byproduct.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::End( void )
{
BOOL fReturn = FALSE;
// Only initiate a Revert if we are impersonating the user.
if ( m_fImpersonatingUser )
{
LogMessage(_T("CImpersonateLoggedOnUser::End"));
fReturn = Revert();
}
else
{
fReturn = TRUE;
}
// Clear the handles out
if ( NULL != m_hUserToken )
{
CloseHandle( m_hUserToken );
m_hUserToken = NULL;
}
if ( NULL != m_hShellProcess )
{
CloseHandle( m_hShellProcess );
m_hShellProcess = NULL;
}
if ( m_hThreadToken != INVALID_HANDLE_VALUE )
{
CloseHandle( m_hThreadToken );
m_hThreadToken = INVALID_HANDLE_VALUE ;
}
return fReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::LoadShellName
//
// DESCRIPTION : Loads Windows NT Shell name from registry
//
// INPUTS : DWORD cbShellNameBuffer - Shell Name Buffer Size (in bytes)
//
// OUTPUTS : LPTSTR pszShellName - Buffer to contain shell name.
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Jumps into Windows Registry and attempts to determine the
// NT Shell Name.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::LoadShellName( LPTSTR pszShellName, DWORD cbShellNameBuffer )
{
BOOL fReturn = FALSE;
LONG lErrReturn = ERROR_SUCCESS;
// Only continue if we have a buffer to work with first
if ( NULL != pszShellName )
{
HKEY hReg = NULL;
// Open the key in HKEY_LOCAL_MACHINE, if that succeeds, get the
// value associated with "Shell".
if ( ( lErrReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WINNT_WINLOGON_KEY,
0,
KEY_READ,
&hReg ) ) == ERROR_SUCCESS )
{
try
{
DWORD dwType = REG_SZ;
if ( ( lErrReturn = RegQueryValueEx( hReg,
WINNT_SHELL_VALUE,
0,
&dwType,
(LPBYTE) pszShellName,
&cbShellNameBuffer ) ) == ERROR_SUCCESS )
{
fReturn = TRUE;
}
else
{
LogErrorMessage(_T("RegQueryValueEx FAILED"));
}
}
catch ( ... )
{
RegCloseKey( hReg );
throw ;
}
RegCloseKey( hReg );
} // RegOpenKeyEx
else
{
LogErrorMessage(_T("RegOpenKeyEx FAILED"));
}
} // NULL != pszShellName
return fReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::FindShellProcess
//
// DESCRIPTION : Enumerates the processes to locate the Shell Process.
//
// INPUTS : LPCTSTR pszShellName - Name of the process to locate.
//
// OUTPUTS : None.
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Enumerates the processes on the local system using PSAPI.DLL
// functions, attempting to locate the one that corresponds to
// the WINNT Shell passed into this function.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::FindShellProcess( LPCTSTR pszShellName )
{
BOOL fReturn = FALSE;
HANDLE hProcess = NULL;
HMODULE *phModules = NULL;
DWORD dwModuleArraySize = 0;
DWORD* pdwProcessIds = NULL;
if ( NULL != pszShellName )
{
CPSAPI *t_psapi = (CPSAPI*) CResourceManager::sm_TheResourceManager.GetResource ( guidPSAPI, NULL ) ;
if ( t_psapi )
{
try
{
CLuidHelper luid ;
LUID processLUID ;
// This locks access to the s_dwProcessID value. WATCH THE SCOPING HERE!
CLockWrapper t_lockImp(g_csImpersonate);
// First check to see if we have a cached value. If so, check to see if it's still valid.
if (s_dwProcessID != 0)
{
if ( ( hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
s_dwProcessID ) )
!= NULL )
{
try
{
// Now search the process modules for a match to the supplied
// shell name.
fReturn = FindShellModuleInProcess( pszShellName, hProcess, phModules, dwModuleArraySize, t_psapi );
if ( TRUE == fReturn )
{
if ( STATUS_SUCCESS == luid.GetLUIDFromProcess ( hProcess, &processLUID ) )
{
if ( ! luid.IsInteractiveSession ( &processLUID ) )
{
fReturn = FALSE ;
}
}
else
{
fReturn = FALSE ;
}
}
}
catch ( ... )
{
CloseHandle (hProcess);
throw ;
}
// Close the process handle if it's not the shell (in which
// case we'll save the value and close it as part of the
// Clear() function.
if ( !fReturn )
{
CloseHandle( hProcess );
hProcess = NULL;
// Not valid anymore
s_dwProcessID = 0;
}
else
{
m_hShellProcess = hProcess;
LogMessage(L"Using cached handle for impersonation");
hProcess = NULL;
}
} // if OpenProcess
else
{
// We didn't open the process, so we need to set the value to zero so that
// we will look for a new process below.
s_dwProcessID = 0;
}
}
// Did we find a cached value?
if (s_dwProcessID == 0)
{
// Nope. Scan all processes to see if we can find the explorer
DWORD dwProcessIdArraySize = 0,
dwNumProcesses = 0,
cbDataReturned = 0;
BOOL fEnumSucceeded = FALSE;
// Perform initial allocations of our arrays. Since
// pointers and values are 0, this will just fill out
// said values.
do
{
ReallocProcessIdArray( pdwProcessIds, dwProcessIdArraySize );
fEnumSucceeded = t_psapi->EnumProcesses( pdwProcessIds, dwProcessIdArraySize, &cbDataReturned );
} while ( (dwProcessIdArraySize == cbDataReturned) && fEnumSucceeded);
// Only walk the array if we sucessfully populated it
if ( fEnumSucceeded )
{
// Count of Bytes returned / sizeof(DWORD) tells us how many
// processes are out in the world.
dwNumProcesses = cbDataReturned / sizeof(DWORD);
DWORD dwId = 0;
// Enum processes until we obtain a shell process or run out
// of processes to query.
while ( dwId < dwNumProcesses && !fReturn )
{
if ( ( hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
pdwProcessIds[dwId] ) )
!= NULL )
{
try
{
// Now search the process modules for a match to the supplied
// shell name.
fReturn = FindShellModuleInProcess( pszShellName, hProcess, phModules, dwModuleArraySize, t_psapi );
if ( TRUE == fReturn )
{
if ( STATUS_SUCCESS == luid.GetLUIDFromProcess ( hProcess, &processLUID ) )
{
if ( ! luid.IsInteractiveSession ( &processLUID ) )
{
fReturn = FALSE ;
}
}
else
{
fReturn = FALSE ;
}
}
}
catch ( ... )
{
CloseHandle (hProcess);
throw ;
}
// Close the process handle if it's not the shell (in which
// case we'll save the value and close it as part of the
// Clear() function.
if ( !fReturn )
{
CloseHandle( hProcess );
hProcess = NULL;
}
else
{
m_hShellProcess = hProcess;
s_dwProcessID = pdwProcessIds[dwId];
hProcess = NULL;
}
} // if OpenProcess
// Increment the Id counter
++dwId;
} // While OpenProcesses
} // If !fRetryEnumProcesses
}
}
catch ( ... )
{
if (phModules)
{
delete [] phModules;
}
if (pdwProcessIds)
{
delete [] pdwProcessIds;
}
if ( t_psapi )
{
CResourceManager::sm_TheResourceManager.ReleaseResource ( guidPSAPI, t_psapi ) ;
t_psapi = NULL ;
}
throw ;
}
}
if (pdwProcessIds)
{
delete [] pdwProcessIds;
}
if (phModules)
{
delete [] phModules;
}
if ( t_psapi )
{
CResourceManager::sm_TheResourceManager.ReleaseResource ( guidPSAPI, t_psapi ) ;
// t_psapi = NULL ;
}
}
return fReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::FindShellModuleInProcess
//
// DESCRIPTION : Enumerates the modules in a process to find our
// shell.
//
// INPUTS : LPCTSTR pszShellName - Name of the process to locate.
// HANDLE hProcess - Process we are enumerating modules in.
//
// OUTPUTS : HMODULE*& phModules - Array of module handle pointers.
// DWORD& dwModuleArraySize - Size of Module Array (in bytes)
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Enumerates the modules specified by a process identifier and
// attemptsto locate the one that corresponds to the WINNT Shell
// passed into this function.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::FindShellModuleInProcess( LPCTSTR pszShellName, HANDLE hProcess, HMODULE*& phModules, DWORD& dwModuleArraySize, CPSAPI *a_psapi )
{
BOOL fReturn = FALSE,
fRetryEnumModules = FALSE;
DWORD cbDataReturned = 0;
TCHAR szModuleName[MAX_PATH];
if (dwModuleArraySize == 0)
{
ReallocModuleHandleArray( phModules, dwModuleArraySize );
}
do
{
// Get a list of the process HMODULEs and for each HMODULE, get
// the base file name.
if ( a_psapi->EnumProcessModules( hProcess, phModules, dwModuleArraySize, &cbDataReturned ) )
{
// Because m_pfnEnumProcessModules will NOT fail if there are more process
// modules than bytes available in the array, if the amount returned is
// the same size as the array, realloc the array and retry the Enum.
if ( dwModuleArraySize == cbDataReturned )
{
fRetryEnumModules = ReallocModuleHandleArray( phModules, dwModuleArraySize );
}
else
{
fRetryEnumModules = FALSE;
}
// Only walk the array if we don't need to retry the enum
if ( !fRetryEnumModules )
{
DWORD dwModuleCtr = 0;
// Executable name always returned in entry 0
if ( a_psapi->GetModuleBaseName( hProcess, phModules[dwModuleCtr], szModuleName, sizeof(szModuleName) ) )
{
fReturn = ( lstrcmpi( pszShellName, szModuleName ) == 0 );
}
} // If !fRetryEnumModules
} // if EnumProcessModules
}
while ( fRetryEnumModules );
return fReturn;
}
DWORD CImpersonateLoggedOnUser::AdjustSecurityDescriptorOfImpersonatedToken(
CSid& csidSidOfCurrentProcess )
{
DWORD dwRet = E_FAIL;
// Get the thread token...
CThreadToken ctt;
if ( ctt.IsValidToken () )
{
// Obtain access to its security descriptor...
CSecureKernelObj sko(ctt.GetTokenHandle(), FALSE);
// Modify the security descriptor...
if(sko.AddDACLEntry(
csidSidOfCurrentProcess,
ENUM_ACCESS_ALLOWED_ACE_TYPE,
TOKEN_ALL_ACCESS,
0,
NULL,
NULL))
{
dwRet = sko.ApplySecurity(
DACL_SECURITY_INFORMATION);
}
}
return dwRet ;
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::ImpersonateUser
//
// DESCRIPTION : Attempts to impersonate the user.
//
// INPUTS : None.
//
// OUTPUTS : None.
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Opens the security token of the Shell Process and
// uses it to try to impersonate the user.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::ImpersonateUser( void )
{
BOOL fRet = FALSE;
// Make sure we have a shell process
if (m_hShellProcess)
{
CSid csidCurrentProcess;
if(GetCurrentProcessSid(csidCurrentProcess))
{
// Get the Process User token if we don't have one (token of the explorer process).
//Removed the TOKEN_ALL_ACCESS desired access mask to this call as Winmgmt(Local system) can't open the token of the
//shell process (with all access rights)if the logged-in user is an Admin. So open the token with 'desired access' sufficient
//enough to use it for impersonation only.
if (m_hUserToken ||
OpenProcessToken(m_hShellProcess, TOKEN_READ | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, &m_hUserToken))
{
// Now we should have what we need. Impersonate the user.
HANDLE hCurThread = ::GetCurrentThread () ;
CProcessToken cpt ( m_hUserToken );
if ( cpt.IsValidToken () )
{
TOKEN_TYPE type;
if ( cpt.GetTokenType ( type ) )
{
if ( TokenPrimary == type )
{
CToken ct;
if ( ct.Duplicate ( cpt, FALSE ) )
{
if( ::SetThreadToken ( &hCurThread, ct.GetTokenHandle () ) )
{
m_fImpersonatingUser = TRUE ;
}
}
}
else
{
if( ::SetThreadToken ( &hCurThread, cpt.GetTokenHandle () ) )
{
m_fImpersonatingUser = TRUE ;
}
}
if ( m_fImpersonatingUser )
{
if(AdjustSecurityDescriptorOfImpersonatedToken ( csidCurrentProcess ) == ERROR_SUCCESS)
{
fRet = TRUE;
}
else
{
Revert () ;
}
}
}
}
}
}
}
return (m_fImpersonatingUser = fRet);
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::Revert
//
// DESCRIPTION : Attempts to revert to self.
//
// INPUTS : None.
//
// OUTPUTS : None.
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : If we're impersonating a user, we now revert to
// ourselves.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::Revert( void )
{
HRESULT hRes = WBEM_E_FAILED ;
BOOL bRet = FALSE ;
// See if we're currently impersonating prior to reverting.
if (m_fImpersonatingUser)
{
// Now get back to to the previous impersonation or impersonate the DCOM client.
if ( m_hThreadToken != INVALID_HANDLE_VALUE )
{
HANDLE hCurThread = ::GetCurrentThread () ;
CThreadToken cpt ( m_hThreadToken );
if ( cpt.IsValidToken () )
{
TOKEN_TYPE type;
if ( cpt.GetTokenType ( type ) )
{
if ( TokenPrimary == type )
{
CToken ct;
if ( ct.Duplicate ( cpt, FALSE ) )
{
bRet = ::SetThreadToken ( &hCurThread, ct.GetTokenHandle () );
}
}
else
{
bRet = ::SetThreadToken ( &hCurThread, cpt.GetTokenHandle () ) ;
}
if (!bRet)
{
throw CFramework_Exception(L"SetThreadToken failed", GetLastError());
}
}
}
}
else
{
hRes = WbemCoImpersonateClient();
if (FAILED(hRes))
{
throw CFramework_Exception(L"WbemCoImpersonateClient failed", hRes);
}
}
if (SUCCEEDED(hRes) || hRes == E_NOTIMPL || bRet )
{
m_fImpersonatingUser = FALSE;
}
}
return ( !m_fImpersonatingUser );
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::ReallocProcessIdArray
//
// DESCRIPTION : Helper function to alloc a process id array.
//
// INPUTS : None.
//
// OUTPUTS : PDWORD& pdwProcessIds - Process Id Array pointer
// DWORD& dwArraySize - Size of array in bytes
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Call when we need to realloc our process id array.
// This will grow the array by a fixed size, but not
// preserve values.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::ReallocProcessIdArray( PDWORD& pdwProcessIds, DWORD& dwArraySize )
{
DWORD dwNewArraySize = dwArraySize + ( PROCESSID_ARRAY_BLOCKSIZE * sizeof(DWORD) );
PDWORD pdwNewArray = new DWORD[dwNewArraySize];
// Make sure the allocation succeeded before overwriting any existing values.
if ( NULL != pdwNewArray )
{
if ( NULL != pdwProcessIds )
{
delete [] pdwProcessIds;
}
pdwProcessIds = pdwNewArray;
dwArraySize = dwNewArraySize;
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
return ( NULL != pdwNewArray );
}
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION : CImpersonateLoggedOnUser::ReallocModuleHandleArray
//
// DESCRIPTION : Helper function to alloc a module handle array.
//
// INPUTS : None.
//
// OUTPUTS : HMODULE*& phModules - Module Handle Array pointer
// DWORD& dwArraySize - size of array in bytes
//
// RETURNS : BOOL TRUE/FALSE - Success/Failure
//
// COMMENTS : Call when we need to realloc our module handle array.
// This will grow the array by a fixed size, but not
// preserve values.
//
//////////////////////////////////////////////////////////////////////////////
BOOL CImpersonateLoggedOnUser::ReallocModuleHandleArray( HMODULE*& phModules, DWORD& dwArraySize )
{
DWORD dwNewArraySize = dwArraySize + ( HMODULE_ARRAY_BLOCKSIZE * sizeof(HMODULE) );
HMODULE* phNewArray = new HMODULE[dwNewArraySize];
// Make sure the allocation succeeded before overwriting any existing values.
if ( NULL != phNewArray )
{
if ( NULL != phModules )
{
delete [] phModules;
}
phModules = phNewArray;
dwArraySize = dwNewArraySize;
}
else
{
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
}
return ( NULL != phNewArray );
}
bool CImpersonateLoggedOnUser::GetCurrentProcessSid(CSid& sidCurrentProcess)
{
bool fRet = false;
PBYTE pbuff = NULL;
// I am going to revert here in order to access the process's
// sid. This is not privileged information, so this doesn't
// present a security breach.
WbemCoRevertToSelf();
try
{
CProcessToken cpt(NULL, true, TOKEN_QUERY);
DWORD dwLen = 0;
if(!::GetTokenInformation(
cpt.GetTokenHandle(), // the PR0CESS token
TokenUser,
NULL,
0L,
&dwLen) && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
pbuff = new BYTE[dwLen];
if(pbuff)
{
if(::GetTokenInformation(
cpt.GetTokenHandle(),
TokenUser,
pbuff,
dwLen,
&dwLen))
{
PTOKEN_USER ptu = (PTOKEN_USER)pbuff;
CSid sidTemp(ptu->User.Sid);
if(sidTemp.IsOK() &&
sidTemp.IsValid())
{
sidCurrentProcess = sidTemp;
fRet = true;
}
}
delete pbuff;
pbuff = NULL;
}
}
}
catch(...)
{
//on our way out not returning anything to user except failure
//can't do anything on this impersonation failure...
WbemCoImpersonateClient();
delete pbuff;
pbuff = NULL;
throw;
}
HRESULT hr = WbemCoImpersonateClient() ;
if (FAILED(hr))
{
throw CFramework_Exception(L"WbemCoImpersonateClient failed", hr);
}
return fRet;
}
#endif