Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1120 lines
33 KiB

//***************************************************************************
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include "wmicom.h"
#include "wmimof.h"
#include "wmimap.h"
#include <stdlib.h>
#include <winerror.h>
#include <TCHAR.h>
////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************
// Global Utility Functions
//**********************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////
BOOL IsBinaryMofResourceEvent(LPOLESTR pGuid, GUID gGuid)
{
HRESULT hr;
GUID Guid;
hr = CLSIDFromString(pGuid,&Guid);
if( SUCCEEDED(hr) )
{
if( gGuid == Guid)
{
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////
BOOL GetParsedPropertiesAndClass( BSTR Query,WCHAR * wcsClass )
{
ParsedObjectPath * pParsedPath = NULL; // stdlibrary API
CObjectPathParser Parser;
BOOL fRc = FALSE;
if( CObjectPathParser::NoError == Parser.Parse(Query, &pParsedPath))
{
try
{
// NTRaid:136400
// 07/12/00
if(pParsedPath && !IsBadReadPtr( pParsedPath, sizeof(ParsedObjectPath)))
{
KeyRef * pKeyRef = NULL;
pKeyRef = *(pParsedPath->m_paKeys);
if(!IsBadReadPtr( pKeyRef, sizeof(KeyRef)))
{
wcscpy(wcsClass,pParsedPath->m_pClass);
fRc = TRUE;
}
}
Parser.Free(pParsedPath);
}
catch(...)
{
Parser.Free(pParsedPath);
throw;
}
}
return fRc;
}
////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CheckIfThisIsAValidKeyProperty(WCHAR * wcsClass, WCHAR * wcsProperty, IWbemServices * p)
{
HRESULT hr = WBEM_E_FAILED;
IWbemClassObject * pIHCO = NULL;
IWbemQualifierSet * pIWbemQualifierSet = NULL;
long lType = 0L;
BSTR strPath = NULL;
strPath = SysAllocString(wcsClass);
if(strPath == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
hr = p->GetObject(strPath, 0,NULL, &pIHCO, NULL);
SysFreeString(strPath);
if (WBEM_S_NO_ERROR != hr)
return WBEM_E_INVALID_CLASS;
if(wcsProperty){
hr = pIHCO->GetPropertyQualifierSet(wcsProperty,&pIWbemQualifierSet);
if( SUCCEEDED(hr) ){
CVARIANT v;
hr = pIWbemQualifierSet->Get(L"key", 0, &v, 0);
SAFE_RELEASE_PTR(pIWbemQualifierSet);
}
else{
hr = WBEM_E_INVALID_OBJECT_PATH;
}
}
//============================================================
// Cleanup
//============================================================
SAFE_RELEASE_PTR(pIHCO);
}
return hr;
}
//====================================================================
HRESULT GetParsedPath( BSTR ObjectPath,WCHAR * wcsClass, WCHAR * wcsInstance,IWbemServices * p )
{
//============================================================
// Get the path and instance name and check to make sure it
// is valid
//============================================================
ParsedObjectPath * pParsedPath = NULL; // stdlibrary API
CObjectPathParser Parser;
HRESULT hr = WBEM_E_FAILED;
if( 0 == Parser.Parse(ObjectPath, &pParsedPath))
{
try
{
// NTRaid:136395
// 07/12/00
if(pParsedPath && !IsBadReadPtr( pParsedPath, sizeof(ParsedObjectPath)))
{
KeyRef * pKeyRef = NULL;
pKeyRef = *(pParsedPath->m_paKeys);
if( !IsBadReadPtr( pKeyRef, sizeof(KeyRef)))
{
hr = CheckIfThisIsAValidKeyProperty(pParsedPath->m_pClass, pKeyRef->m_pName,p );
if( SUCCEEDED(hr) )
{
wcscpy(wcsClass,pParsedPath->m_pClass);
wcscpy(wcsInstance,pKeyRef->m_vValue.bstrVal);
}
}
}
Parser.Free(pParsedPath);
}
catch(...)
{
hr = WBEM_E_UNEXPECTED;
Parser.Free(pParsedPath);
throw;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL GetUserThreadToken(HANDLE * phThreadTok)
{
BOOL fRc = FALSE;
HRESULT hRes = WbemCoImpersonateClient();
if (SUCCEEDED(hRes))
{
// Now, let's check the impersonation level. First, get the thread token
if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, phThreadTok))
{
// If the CoImpersonate works, but the OpenThreadToken fails, we are running under the
// process token (either local system, or if we are running with /exe, the rights of
// the logged in user). In either case, impersonation rights don't apply. We have the
// full rights of that user.
if(GetLastError() == ERROR_NO_TOKEN)
{
// Try getting the thread token. If it fails it's because we're a system thread and
// we don't yet have a thread token, so just impersonate self and try again.
if( ImpersonateSelf(SecurityImpersonation) )
{
if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, phThreadTok))
{
fRc = FALSE;
}
else
{
fRc = TRUE;
}
}
else
{
ERRORTRACE((THISPROVIDER,"ImpersonateSelf(SecurityImpersonation)failed"));
}
}
}
else
{
fRc = TRUE;
}
}
if( !fRc )
{
ERRORTRACE((THISPROVIDER,IDS_ImpersonationFailed));
}
return fRc;
}
////////////////////////////////////////////////////////////////////////////////////////////////
SAFEARRAY * OMSSafeArrayCreate( IN VARTYPE vt, IN int iNumElements)
{
if(iNumElements < 1)
{
return NULL;
}
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = iNumElements;
return SafeArrayCreate(vt,1,rgsabound);
}
////////////////////////////////////////////////////////////////////////////////////////////////
void TranslateAndLog( WCHAR * wcsMsg )
{
CAnsiUnicode XLate;
char * pStr = NULL;
if( SUCCEEDED(XLate.UnicodeToAnsi(wcsMsg,pStr)))
{
ERRORTRACE((THISPROVIDER,pStr));
ERRORTRACE((THISPROVIDER,"\n"));
SAFE_DELETE_ARRAY(pStr);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
bool IsNT(void)
{
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(!GetVersionEx(&os))
return FALSE; // should never happen
return os.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
////////////////////////////////////////////////////////////////////
BOOL SetGuid(WCHAR * pwcsGuidString, CLSID & Guid)
{
BOOL fRc = FALSE;
CAutoWChar wcsGuid(MAX_PATH+2);
if( wcsGuid.Valid() )
{
fRc = TRUE;
swprintf(wcsGuid,L"{%s}",pwcsGuidString );
if(FAILED(CLSIDFromString(wcsGuid, &Guid)))
{
if( FAILED(CLSIDFromString(pwcsGuidString, &Guid)))
{
fRc = FALSE;
}
}
}
return fRc;
}
////////////////////////////////////////////////////////////////////
HRESULT AllocAndCopy(WCHAR * wcsSource, WCHAR ** pwcsDest )
{
HRESULT hr = WBEM_E_FAILED;
int nLen = wcslen(wcsSource);
if( nLen > 0 )
{
*pwcsDest = new WCHAR[nLen + 2 ];
if( *pwcsDest )
{
wcscpy(*pwcsDest,wcsSource);
hr = S_OK;
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************
// Utility Classes
//**********************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
void _WMIHandleMap::AddRef()
{
InterlockedIncrement((long*)&RefCount);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
long _WMIHandleMap::Release()
{
ULONG cRef = InterlockedDecrement( (long*) &RefCount);
if ( !cRef ){
WmiCloseBlock(WMIHandle);
return 0;
}
return cRef;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_WMIEventRequest::_WMIEventRequest()
{
pwcsClass = NULL ;
pHandler = NULL;
pServices = NULL;
pCtx = NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_WMIEventRequest::~_WMIEventRequest()
{
SAFE_RELEASE_PTR(pServices);
SAFE_RELEASE_PTR(pCtx);
SAFE_DELETE_ARRAY(pwcsClass);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
void _WMIEventRequest::AddPtrs( IWbemObjectSink __RPC_FAR * Handler,IWbemServices __RPC_FAR * Services,IWbemContext __RPC_FAR * Ctx)
{
pHandler = Handler;
pServices = Services;
pCtx = Ctx;
if( pServices ){
pServices->AddRef();
}
if( pCtx ){
pCtx->AddRef();
}
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_AccessList::~_AccessList()
{
for( int i = 0; i < m_List.Size(); i++ )
{
IWbemObjectAccess * pPtr = (IWbemObjectAccess *)m_List[i];
SAFE_RELEASE_PTR(pPtr);
}
m_List.Empty();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_IdList::~_IdList()
{
for( int i = 0; i < m_List.Size(); i++ )
{
ULONG_PTR* pPtr = (ULONG_PTR*)m_List[i];
SAFE_DELETE_PTR(pPtr);
}
m_List.Empty();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_HandleList::~_HandleList()
{
for( int i = 0; i < m_List.Size(); i++ )
{
HANDLE * pPtr = (HANDLE*)m_List[i];
SAFE_DELETE_PTR(pPtr);
}
m_List.Empty();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_InstanceList::~_InstanceList()
{
for( int i = 0; i < m_List.Size(); i++ )
{
WCHAR * p = (WCHAR*)m_List[i];
SAFE_DELETE_ARRAY(p);
}
m_List.Empty();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
_OldClassInfo::~_OldClassInfo()
{
SAFE_DELETE_ARRAY(m_pClass);
SAFE_DELETE_ARRAY(m_pPath);
m_pClass = m_pPath = NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_OldClassList::~_OldClassList()
{
for( int i = 0; i < m_List.Size(); i++ )
{
OldClassInfo * p = (OldClassInfo*)m_List[i];
SAFE_DELETE_PTR(p);
}
m_List.Empty();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_WMIHiPerfHandleMap::_WMIHiPerfHandleMap(CWMIProcessClass * p, IWbemHiPerfEnum * pEnum)
{
m_pEnum = pEnum;
if( pEnum )
{
pEnum->AddRef();
}
m_pClass = p;
m_fEnumerator = FALSE;
lHiPerfId = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
_WMIHiPerfHandleMap::~_WMIHiPerfHandleMap()
{
SAFE_RELEASE_PTR(m_pEnum);
lHiPerfId = 0;
SAFE_DELETE_PTR(m_pClass);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// Hi Perf Handle Map = Handles are addref'd and when released, then the block is closed
// Critical Sections are handled elsewhere
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CHiPerfHandleMap::Add( HANDLE hCurrent, ULONG_PTR lHiPerfId, CWMIProcessClass * p, IWbemHiPerfEnum * pEnum)
{
HRESULT hr = S_OK;
WMIHiPerfHandleMap * pWMIMap = new WMIHiPerfHandleMap(p,pEnum);
if( pWMIMap )
{
try
{
pWMIMap->WMIHandle = hCurrent;
pWMIMap->lHiPerfId = lHiPerfId;
// 170635
if(CFlexArray::out_of_memory == m_List.Add(pWMIMap))
{
SAFE_DELETE_PTR(pWMIMap);
hr = E_OUTOFMEMORY;
}
}
catch(...)
{
hr = WBEM_E_UNEXPECTED;
SAFE_DELETE_PTR(pWMIMap);
throw;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CHiPerfHandleMap::FindHandleAndGetClassPtr( HANDLE & hCurrent, ULONG_PTR lHiPerfId,CWMIProcessClass *& p)
{
HRESULT hr = WBEM_E_NOT_FOUND;
for( int i=0; i<m_List.Size(); i++)
{
//===================================================
//
//===================================================
WMIHiPerfHandleMap * pMap = (WMIHiPerfHandleMap *) m_List[i];
if( pMap->lHiPerfId == lHiPerfId )
{
hCurrent = pMap->WMIHandle;
p = pMap->m_pClass;
hr = S_OK;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CHiPerfHandleMap::GetFirstHandle(HANDLE & hCurrent,CWMIProcessClass *& p, IWbemHiPerfEnum *& pEnum)
{
m_nIndex=0;
return GetNextHandle(hCurrent,p,pEnum);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CHiPerfHandleMap::GetNextHandle(HANDLE & hCurrent,CWMIProcessClass *& p, IWbemHiPerfEnum *& pEnum)
{
HRESULT hr = WBEM_S_NO_MORE_DATA;
if( m_nIndex < m_List.Size() )
{
WMIHiPerfHandleMap * pMap = (WMIHiPerfHandleMap *) m_List[m_nIndex];
hCurrent = pMap->WMIHandle;
p = pMap->m_pClass;
pEnum = pMap->m_pEnum;
m_nIndex++;
hr = S_OK;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CHiPerfHandleMap::Delete( HANDLE & hCurrent, ULONG_PTR lHiPerfId )
{
HRESULT hr = WBEM_E_NOT_FOUND;
for( int i=0; i<m_List.Size(); i++)
{
//===================================================
//
//===================================================
WMIHiPerfHandleMap * pMap = (WMIHiPerfHandleMap *) m_List[i];
if( pMap->lHiPerfId == lHiPerfId )
{
hCurrent = pMap->WMIHandle;
SAFE_DELETE_PTR(pMap);
m_List.RemoveAt(i);
hr = S_OK;
break;
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// When this function is called, release all the handles kept
// THis function is called in the destructor of the class to release all teh WMIHiPerfHandleMap
// classes allocated
////////////////////////////////////////////////////////////////////////////////////////////////
void CHiPerfHandleMap::CloseAndReleaseHandles()
{
//===================================
// Go through the handles one at
// a time and close them, then
// delete the records from the
// array
//===================================
CAutoBlock((CCriticalSection *)&m_HandleCs);
if( m_List.Size() > 0 ){
for(int i = 0; i < m_List.Size(); i++){
WMIHiPerfHandleMap * pWMIMap = (WMIHiPerfHandleMap *) m_List[i];
SAFE_DELETE_PTR(pWMIMap);
}
//==================================================
// Remove it and deallocate memory
//==================================================
m_List.Empty();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// Regular Handle Map = Expensize handles are always kept open - by default we, dont' know the lifetime
// of these handles
///////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CHandleMap::Add(CLSID Guid, HANDLE hCurrent, ULONG uDesiredAccess)
{
// Critical section is called elsewhere
HRESULT hr = S_OK;
WMIHandleMap * pWMIMap = new WMIHandleMap();
if( pWMIMap )
{
try
{
pWMIMap->AddRef(); // Used for HiPerf counts, otherwise not referenced
pWMIMap->WMIHandle = hCurrent;
pWMIMap->Guid = Guid;
pWMIMap->uDesiredAccess = uDesiredAccess;
// 170635
if(CFlexArray::out_of_memory == m_List.Add(pWMIMap))
{
hr = E_OUTOFMEMORY;
SAFE_DELETE_PTR(pWMIMap);
}
}
catch(...)
{
hr = WBEM_E_UNEXPECTED;
SAFE_DELETE_PTR(pWMIMap);
throw;
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////
int CHandleMap::ExistingHandleAlreadyExistsForThisGuidUseIt(CLSID Guid,
HANDLE & hCurrentWMIHandle,
BOOL & fCloseHandle,
ULONG uDesiredAccess)
{
int nRc = ERROR_NOT_SUPPORTED;
// Critical section is called elsewhere
//=====================================================
// Initialize stuff
//=====================================================
hCurrentWMIHandle = 0;
fCloseHandle = TRUE;
for(int i = 0; i < m_List.Size(); i++){
WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
//==================================================
// Compare and see if this guid already has a
// handle assigned for it with the access permissions
// that we want to use
//==================================================
if( pWMIMap->Guid == Guid ){
if( pWMIMap->uDesiredAccess == uDesiredAccess ){
hCurrentWMIHandle = pWMIMap->WMIHandle;
pWMIMap->AddRef(); // Used for HiPerf Handles, otherwise not needed
nRc = ERROR_SUCCESS;
fCloseHandle = FALSE;
break;
}
}
}
return nRc;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// When this function is called, we need to close all of the handles that may have been kept
// open for accumulation purposes
////////////////////////////////////////////////////////////////////////////////////////////////
void CHandleMap::CloseAllOutstandingWMIHandles()
{
//===================================
// Go through the handles one at
// a time and close them, then
// delete the records from the
// array
//===================================
CAutoBlock((CCriticalSection *)&m_HandleCs);
if( m_List.Size() > 0 ){
for(int i = 0; i < m_List.Size(); i++){
WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
//==================================================
// Inform WMI we are done with this guy
//==================================================
try
{
WmiCloseBlock(pWMIMap->WMIHandle);
}
catch(...)
{
// don't throw
}
SAFE_DELETE_PTR(pWMIMap);
}
//==================================================
// Remove it and deallocate memory
//==================================================
m_List.Empty();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Used when we know the handles lifetimes
////////////////////////////////////////////////////////////////////////////////////////////////
int CHandleMap::ReleaseHandle( HANDLE hCurrentWMIHandle )
{
int nRc = ERROR_NOT_SUPPORTED;
CAutoBlock((CCriticalSection *)&m_HandleCs);
for(int i = 0; i < m_List.Size(); i++){
WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
if( pWMIMap->WMIHandle == hCurrentWMIHandle )
{
long RefCount = pWMIMap->Release(); // Used for HiPerf Handles, otherwise not needed
if( !RefCount )
{
// WmiCloseBlock(hCurrentWMIHandle);
SAFE_DELETE_PTR( pWMIMap);
m_List.RemoveAt(i);
}
nRc = ERROR_SUCCESS;
break;
}
}
return nRc;
}
////////////////////////////////////////////////////////////////////////////////////////////////
int CHandleMap::GetHandle(CLSID Guid, HANDLE & hCurrentWMIHandle )
{
int nRc = ERROR_NOT_SUPPORTED;
CAutoBlock((CCriticalSection *)&m_HandleCs);
//=====================================================
// Initialize stuff
//=====================================================
hCurrentWMIHandle = 0;
for(int i = 0; i < m_List.Size(); i++){
WMIHandleMap * pWMIMap = (WMIHandleMap*) m_List[i];
if( pWMIMap->Guid == Guid ){
hCurrentWMIHandle = pWMIMap->WMIHandle;
pWMIMap->AddRef(); // Used for HiPerf Handles, otherwise not needed
nRc = ERROR_SUCCESS;
break;
}
}
return nRc;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************
// Utility Classes: CANSIUNICODE
//**********************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CAnsiUnicode::AllocateAndConvertAnsiToUnicode(char * pstr, WCHAR *& pszW)
{
HRESULT hr = WBEM_E_FAILED;
pszW = NULL;
int nSize = strlen(pstr);
if (nSize != 0 ){
// Determine number of wide characters to be allocated for the
// Unicode string.
nSize++;
pszW = new WCHAR[nSize * 2];
if (NULL != pszW){
try
{
// Covert to Unicode.
MultiByteToWideChar(CP_ACP, 0, pstr, nSize,pszW,nSize);
hr = S_OK;
}
catch(...)
{
SAFE_DELETE_ARRAY(pszW);
hr = WBEM_E_UNEXPECTED;
throw;
}
}
}
return hr;
}
////////////////////////////////////////////////////////////////////
HRESULT CAnsiUnicode::UnicodeToAnsi(WCHAR * pszW, char *& pAnsi)
{
ULONG cbAnsi, cCharacters;
HRESULT hr = WBEM_E_FAILED;
pAnsi = NULL;
if (pszW != NULL){
cCharacters = wcslen(pszW)+1;
// Determine number of bytes to be allocated for ANSI string. An
// ANSI string can have at most 2 bytes per character (for Double
// Byte Character Strings.)
cbAnsi = cCharacters*2;
pAnsi = new char[cbAnsi];
if (NULL != pAnsi)
{
try
{
// Convert to ANSI.
if (0 != WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, pAnsi, cbAnsi, NULL, NULL)){
hr = S_OK;
}
}
catch(...)
{
SAFE_DELETE_ARRAY(pAnsi);
hr = WBEM_E_UNEXPECTED;
throw;
}
}
}
return hr;
}
//************************************************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CWMIManagement
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//************************************************************************************************************
CWMIManagement::CWMIManagement( )
{
m_pHandler = NULL;
m_pServices = NULL;
m_pCtx = NULL;
m_pHandleMap = NULL;
}
//////////////////////////////////////////////////////////////////////////////////////
CWMIManagement::~CWMIManagement()
{
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CWMIManagement::SendPrivilegeExtendedErrorObject( HRESULT hrToReturn,WCHAR * wcsClass)
{
HRESULT hr,hRes;
IWbemClassObject * pClass = NULL, *pInst=NULL;
BOOL fSetStatus = FALSE;
if( hrToReturn == WBEM_E_ACCESS_DENIED ){
TOKEN_PRIVILEGES * ptPriv = NULL;
hr = GetListOfUserPrivileges(ptPriv);
if( SUCCEEDED(hr ) ){
BSTR strPrivelegeStat = NULL;
strPrivelegeStat = SysAllocString(L"Win32_PrivilegesStatus");
if(strPrivelegeStat != NULL)
{
hr = m_pServices->GetObject(strPrivelegeStat, 0,m_pCtx, &pClass, NULL);
if( hr == S_OK){
//=============================================================
// Get an instance of the extended class
//=============================================================
hr = pClass->SpawnInstance(0,&pInst);
SAFE_RELEASE_PTR(pClass);
if( pInst ){
CVARIANT varTmp;
WCHAR * pwcsStr = NULL;
CAnsiUnicode XLate;
//=========================================================
// Fill in description
//=========================================================
XLate.AllocateAndConvertAnsiToUnicode(IDS_ImpersonationFailed,pwcsStr);
varTmp.SetStr(pwcsStr);
hr = pInst->Put(L"Description", 0, &varTmp, NULL);
SAFE_DELETE_ARRAY( pwcsStr );
//======================================================
// Initialize all of the necessary stuff and get the
// definition of the class we are working with
//======================================================
CWMIProcessClass ClassInfo(0);
if( SUCCEEDED(ClassInfo.Initialize()) )
{
ClassInfo.WMI()->SetWMIPointers(m_pHandleMap,m_pServices,m_pHandler,m_pCtx);
ClassInfo.SetClass(wcsClass);
SAFEARRAY *psaPrivNotHeld=NULL;
SAFEARRAY *psaPrivReq=NULL;
//=========================================================
// Get PrivilegesRequired
// The only place to get this, if possible, is from the
// class
//=========================================================
hRes = ClassInfo.GetPrivilegesQualifer(&psaPrivReq);
if( hRes == WBEM_S_NO_ERROR){
//=========================================================
// Get PrivilegesNotHeld
//=========================================================
ProcessPrivileges(ptPriv,psaPrivNotHeld,psaPrivReq);
//=========================================================
// Send it off
//=========================================================
VARIANT v;
if( psaPrivReq ){
VariantInit(&v);
SAFEARRAY *pSafeArray = NULL;
if ( SUCCEEDED ( SafeArrayCopy ((SAFEARRAY*)psaPrivReq , &pSafeArray ) ) ){
v.vt = VT_BSTR | VT_ARRAY;
v.parray = pSafeArray;
pInst->Put(L"PrivilegesRequired", 0, &v, NULL);
VariantClear(&v);
}
}
if( psaPrivNotHeld ){
VariantInit(&v);
SAFEARRAY *pSafeArray = NULL;
if ( SUCCEEDED ( SafeArrayCopy ((SAFEARRAY*)psaPrivNotHeld , &pSafeArray ) ) ){
v.vt = VT_BSTR | VT_ARRAY;
v.parray = pSafeArray;
pInst->Put(L"PrivilegesNotHeld", 0, &v, NULL);
VariantClear(&v);
}
}
}
//=========================================================
// Now, send this guy off...
//=========================================================
fSetStatus = TRUE;
hr = m_pHandler->SetStatus(0,hrToReturn,NULL,pInst);
if (psaPrivNotHeld)
SafeArrayDestroy(psaPrivNotHeld);
if (psaPrivReq)
SafeArrayDestroy(psaPrivReq);
}
}
SAFE_RELEASE_PTR(pInst);
}
SysFreeString(strPrivelegeStat);
}
}
SAFE_DELETE_ARRAY(ptPriv);
}
if( !fSetStatus ){
hr = m_pHandler->SetStatus(0,hrToReturn,NULL,NULL);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CWMIManagement::SetErrorMessage(HRESULT hrToReturn,WCHAR * wcsClass,WCHAR * wcsMsg)
{
HRESULT hr;
IWbemClassObject * pClass = NULL, *pInst=NULL;
BOOL fSetStatus = FALSE;
if( m_pHandler )
{
BSTR strExtendedStat = NULL;
switch( hrToReturn ){
case WBEM_E_ACCESS_DENIED:
SendPrivilegeExtendedErrorObject(hrToReturn,wcsClass);
break;
case S_OK :
hr = m_pHandler->SetStatus(0,hrToReturn,NULL,NULL);
break;
default:
strExtendedStat = SysAllocString(L"__ExtendedStatus");
if(strExtendedStat != NULL)
{
hr = m_pServices->GetObject(strExtendedStat, 0,m_pCtx, &pClass, NULL);
if( hr == S_OK){
hr = pClass->SpawnInstance(0,&pInst);
if( pInst ){
CVARIANT varTmp;
varTmp.SetStr(wcsMsg);
hr = pInst->Put(L"Description", 0, &varTmp, NULL);
hr = m_pHandler->SetStatus(0,hrToReturn,NULL,pInst);
fSetStatus = TRUE;
// Now log the error in the error log
if( hrToReturn != S_OK ){
TranslateAndLog(varTmp.GetStr());
}
}
}
if( !fSetStatus ){
hr = m_pHandler->SetStatus(0,hrToReturn,NULL,NULL);
}
SAFE_RELEASE_PTR(pClass);
SAFE_RELEASE_PTR(pInst);
SysFreeString(strExtendedStat);
}
else
{
hr = E_OUTOFMEMORY;
}
break;
}
}
return hrToReturn;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CWMIManagement::GetListOfUserPrivileges(TOKEN_PRIVILEGES *& ptPriv)
{
HRESULT hr = WBEM_E_FAILED;
// Get the privileges this user has
DWORD dwTokenInfoLength = 0;
DWORD dwSize = 0;
HANDLE hThreadTok;
if (IsNT()){
if( GetUserThreadToken(&hThreadTok) ){
// get information
if (!GetTokenInformation(hThreadTok, TokenPrivileges, NULL, dwTokenInfoLength, &dwSize)){
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER){
ptPriv = new TOKEN_PRIVILEGES[dwSize+2];
if( ptPriv )
{
try
{
dwTokenInfoLength = dwSize;
if(GetTokenInformation(hThreadTok, TokenPrivileges, (LPVOID)ptPriv, dwTokenInfoLength, &dwSize))
{
hr = WBEM_NO_ERROR;
}
}
catch(...)
{
SAFE_DELETE_ARRAY(ptPriv);
hr = WBEM_E_UNEXPECTED;
throw;
}
}
}
}
// Done with this handle
CloseHandle(hThreadTok);
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CWMIManagement::ProcessPrivileges(TOKEN_PRIVILEGES *ptPriv, SAFEARRAY *& psaPrivNotHeld, SAFEARRAY * psaPrivReq )
{
CAnsiUnicode XLate;
BOOL fFound = FALSE;
//==============================================================
// Create a temporary working array, we know the MAX can be
// the number of priv held + the number of priv req, so
// allocate it for that
//==============================================================
CSAFEARRAY PrivReq( psaPrivReq );
long lMax = PrivReq.GetNumElements()+ptPriv->PrivilegeCount;
psaPrivNotHeld = OMSSafeArrayCreate(VT_BSTR,lMax);
long nCurrentIndex = 0;
//==============================================================
// Get how many privs are not held
//==============================================================
for( long n = 0; n < PrivReq.GetNumElements(); n++ ){
//==============================================================
// Now, get the privileges held array ready to put stuff in
//==============================================================
TCHAR * pPrivReq = NULL;
CBSTR bstr;
if( S_OK != PrivReq.Get(n, &bstr)){
return;
}
fFound = FALSE;
#ifndef UNICODE
XLate.UnicodeToAnsi(bstr,pPrivReq);
#else
pPrivReq = (TCHAR *)bstr;
#endif
// NTRaid:136384
// 07/12/00
if(pPrivReq)
{
for(int i=0;i < (int)ptPriv->PrivilegeCount;i++){
DWORD dwPriv=128;
TCHAR szPriv[NAME_SIZE*2];
if( LookupPrivilegeName( NULL, &ptPriv->Privileges[i].Luid, szPriv, &dwPriv)){
//==============================================
// If we found the privilege, then the user has
// it. break out
//==============================================
if( _tcscmp( pPrivReq,pPrivReq ) == 0 ){
fFound = TRUE;
break;
}
}
//==================================================
// If we didn't find it, then we need to add it to
// the list so we can notify the user
//==================================================
if( !fFound ){
if( S_OK == SafeArrayPutElement(psaPrivNotHeld, &nCurrentIndex, bstr))
{
nCurrentIndex++;
}
}
}
}
#ifndef UNICODE
SAFE_DELETE_ARRAY(pPrivReq);
#else
pPrivReq = NULL;
#endif
}
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nCurrentIndex;
HRESULT hr = SafeArrayRedim(psaPrivNotHeld, rgsabound);
PrivReq.Unbind();
}