//*************************************************************************** // // VPTASKS.CPP // // Module: WBEM VIEW PROVIDER // // Purpose: Contains the common methods taskobject implementation // // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved // //*************************************************************************** //need the following three lines //to get the security stuff to work #include "precomp.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern BOOL bAreWeLocal(WCHAR* pServerMachine); #ifdef VP_BUILD_AS_EXE HRESULT EnableAllPrivileges(BOOL bProcess) { // Open thread token // ================= HANDLE hToken = NULL; BOOL bRes = FALSE; if (bProcess) { bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken); } else { bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &hToken); } if(!bRes) return WBEM_E_ACCESS_DENIED; // Get the privileges // ================== DWORD dwLen; TOKEN_USER tu; memset(&tu,0,sizeof(TOKEN_USER)); bRes = GetTokenInformation(hToken, TokenPrivileges, &tu, sizeof(TOKEN_USER), &dwLen); BYTE* pBuffer = new BYTE[dwLen]; if(pBuffer == NULL) { CloseHandle(hToken); return WBEM_E_OUT_OF_MEMORY; } bRes = GetTokenInformation(hToken, TokenPrivileges, pBuffer, dwLen, &dwLen); if(!bRes) { CloseHandle(hToken); delete [] pBuffer; return WBEM_E_ACCESS_DENIED; } // Iterate through all the privileges and enable them all // ====================================================== TOKEN_PRIVILEGES* pPrivs = (TOKEN_PRIVILEGES*)pBuffer; for(DWORD i = 0; i < pPrivs->PrivilegeCount; i++) { pPrivs->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED; } // Store the information back into the token // ========================================= bRes = AdjustTokenPrivileges(hToken, FALSE, pPrivs, 0, NULL, NULL); delete [] pBuffer; CloseHandle(hToken); if(!bRes) return WBEM_E_ACCESS_DENIED; else return WBEM_S_NO_ERROR; } #endif #ifdef UNICODE HRESULT GetCurrentSecuritySettings(DWORD *pdwAuthnSvc, DWORD *pdwAuthzSvc, DWORD *pdwAuthLevel, DWORD *pdwImpLevel, DWORD *pdwCapabilities) { HRESULT hr = WBEM_E_FAILED; IServerSecurity * pss = NULL; hr = WbemCoGetCallContext(IID_IServerSecurity, (void**)&pss); #if 0 DWORD dwBuffSz = 1024; wchar_t strBuff[1024]; GetUserName(strBuff, &dwBuffSz); #endif if(S_OK == hr) { pss->QueryBlanket(pdwAuthnSvc, pdwAuthzSvc, NULL, pdwAuthLevel, NULL, NULL, pdwCapabilities); pss->Release(); } else { if (SUCCEEDED(hr)) { hr = WBEM_E_FAILED; } } if (SUCCEEDED(hr)) { DWORD dwVersion = GetVersion(); if (dwVersion < 0x80000000) { if ( 4 < (DWORD)(LOBYTE(LOWORD(dwVersion))) ) { //we're on win2k force static cloaking... *pdwCapabilities = EOAC_STATIC_CLOAKING; } } //get implevel... HANDLE hThreadTok = NULL; hr = WBEM_E_FAILED; if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hThreadTok) ) { DWORD dwBytesReturned = 0; DWORD dwThreadImpLevel = 0; if (GetTokenInformation(hThreadTok, TokenImpersonationLevel, &dwThreadImpLevel, sizeof(DWORD), &dwBytesReturned)) { hr = WBEM_NO_ERROR; switch(dwThreadImpLevel) { case SecurityAnonymous: { *pdwImpLevel = RPC_C_IMP_LEVEL_ANONYMOUS; } break; case SecurityIdentification: { *pdwImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; } break; case SecurityImpersonation: { *pdwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; } break; case SecurityDelegation: { *pdwImpLevel = RPC_C_IMP_LEVEL_DELEGATE; } break; default: { hr = WBEM_E_FAILED; } } #ifdef VP_BUILD_AS_EXE if (*pdwImpLevel < RPC_C_IMP_LEVEL_IMPERSONATE) { *pdwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; } #endif } CloseHandle(hThreadTok); } } return hr; } #endif HRESULT SetSecurityLevelAndCloaking(IUnknown* pInterface, const wchar_t* prncpl) { #ifdef UNICODE //first get current security info then set it on the proxy... DWORD dwAuthnSvc = 0; DWORD dwAuthzSvc = 0; DWORD dwAuthLevel = 0; DWORD dwImpLevel = 0; DWORD dwCapabilities = 0; HRESULT hr = GetCurrentSecuritySettings(&dwAuthnSvc, &dwAuthzSvc, &dwAuthLevel, &dwImpLevel, &dwCapabilities); if (SUCCEEDED(hr)) { #ifdef VP_BUILD_AS_EXE EnableAllPrivileges(FALSE); #endif DWORD dwVersion = GetVersion(); OLECHAR *t_pname = NULL; if (dwVersion < 0x80000000) { if ( 4 < (DWORD)(LOBYTE(LOWORD(dwVersion))) ) { //we're on win2k force COLE_DEFAULT_PRINCIPAL... t_pname = COLE_DEFAULT_PRINCIPAL; if ((dwImpLevel > 3) && (prncpl != COLE_DEFAULT_PRINCIPAL)) { dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS; } } } hr = WbemSetProxyBlanket(pInterface, dwAuthnSvc,//16 dwAuthzSvc,//RPC_C_AUTHZ_NONE t_pname, //prncpl, dwAuthLevel, //RPC_C_AUTHN_LEVEL_CONNECT dwImpLevel, //RPC_C_IMP_LEVEL_IMPERSONATE NULL, dwCapabilities); //0x20 //there is no IClientSecurity, we must be running inproc! if (hr == E_NOINTERFACE) { hr = S_OK; } #if 0 if (SUCCEEDED(hr)) { IClientSecurity *t_pCliSec = NULL; HRESULT t_hr = pInterface->QueryInterface(IID_IClientSecurity, (void **) &t_pCliSec); if (SUCCEEDED(t_hr)) { DWORD t_AuthnSvc = 0; DWORD t_AuthzSvc = 0; wchar_t *t_pServerPrincName = NULL; DWORD t_AuthnLevel = 0; DWORD t_ImpLevel = 0; DWORD t_Capabilities = 0; t_hr = t_pCliSec->QueryBlanket(pInterface, &t_AuthnSvc, &t_AuthzSvc, &t_pServerPrincName, &t_AuthnLevel, &t_ImpLevel, NULL, &t_Capabilities); if (SUCCEEDED(t_hr)) { if (t_pServerPrincName) { CoTaskMemFree(t_pServerPrincName); } } t_pCliSec->Release(); } } #endif } #else HRESULT hr = WBEM_NO_ERROR; #endif return hr; } BOOL IsInObjectPath(ParsedObjectPath *a_ParsedObjectPath, const wchar_t *a_key) { if ( (!a_ParsedObjectPath->IsInstance()) || (a_ParsedObjectPath->m_bSingletonObj) || (a_ParsedObjectPath->m_paKeys == NULL) ) { return FALSE; } for (int x = 0; x < a_ParsedObjectPath->m_dwNumKeys; x++) { if ((a_ParsedObjectPath->m_paKeys[x]->m_pName != NULL) && (_wcsicmp(a_key, a_ParsedObjectPath->m_paKeys[x]->m_pName) == 0)) { return TRUE; } } return FALSE; } //returns TRUE if VARIANTs are equal BOOL CompareKeyValueVariants(const VARIANT &a_v1, const VARIANT &a_v2) { BOOL retVal = FALSE; if (a_v1.vt == a_v2.vt) { switch (a_v1.vt) { case VT_BSTR: { retVal = (_wcsicmp(a_v1.bstrVal, a_v2.bstrVal) == 0); break; } case VT_I4: { retVal = (a_v1.lVal == a_v2.lVal); break; } case VT_I2: { retVal = (a_v1.iVal == a_v2.iVal); break; } case VT_UI1: { retVal = (a_v1.bVal == a_v2.bVal); break; } case VT_BOOL: { retVal = (V_BOOL(&a_v1) == V_BOOL(&a_v2)); break; } default: { } } } return retVal; } //this function assumes class 1 is derived from class2 or vice versa //returns TRUE if paths are equal BOOL CompareInstPaths(const wchar_t *a_path1, const wchar_t *a_path2) { BOOL retVal = FALSE; if ((a_path1 == NULL) || (a_path2 == NULL)) { return retVal; } CObjectPathParser t_objectPathParser; wchar_t* t_objPath1 = UnicodeStringDuplicate(a_path1); wchar_t* t_objPath2 = UnicodeStringDuplicate(a_path2); ParsedObjectPath *t_parsedpath1 = NULL; ParsedObjectPath *t_parsedpath2 = NULL; if ( (t_objectPathParser.Parse(t_objPath1, &t_parsedpath1) == 0) && (t_objectPathParser.Parse(t_objPath2, &t_parsedpath2) == 0) && t_parsedpath1->IsInstance() && t_parsedpath2->IsInstance()) { if (t_parsedpath1->m_dwNumKeys == t_parsedpath2->m_dwNumKeys) { retVal = TRUE; //single properties if ((t_parsedpath1->m_dwNumKeys == 1) && ((t_parsedpath1->m_paKeys[0]->m_pName == NULL) || (t_parsedpath2->m_paKeys[0]->m_pName == NULL))) { //compare the values... retVal = CompareKeyValueVariants(t_parsedpath1->m_paKeys[0]->m_vValue, t_parsedpath2->m_paKeys[0]->m_vValue); } else { //any property mismatch set retVal FALSE! for (DWORD i = 0; retVal && (i < t_parsedpath1->m_dwNumKeys); i++) { retVal = FALSE; if(t_parsedpath1->m_paKeys[i]->m_pName == NULL) { break; } for (DWORD j = 0; j < t_parsedpath2->m_dwNumKeys; j++) { if(t_parsedpath2->m_paKeys[j]->m_pName == NULL) { break; } if (_wcsicmp(t_parsedpath1->m_paKeys[i]->m_pName, t_parsedpath2->m_paKeys[j]->m_pName) == 0) { //compare the values... retVal = CompareKeyValueVariants(t_parsedpath1->m_paKeys[i]->m_vValue, t_parsedpath2->m_paKeys[j]->m_vValue); } } } } } } delete [] t_objPath1; delete [] t_objPath2; if (t_parsedpath1 != NULL) { delete t_parsedpath1; } if (t_parsedpath2 != NULL) { delete t_parsedpath2; } return retVal; } WbemTaskObject :: WbemTaskObject ( CViewProvServ *a_Provider , IWbemObjectSink *a_NotificationHandler , ULONG a_OperationFlag , IWbemContext *a_Ctx, IWbemServices *a_Serv, CWbemServerWrap *a_ServerWrap ) :m_OperationFlag ( a_OperationFlag ) , m_Provider ( NULL ) , m_NotificationHandler ( NULL ) , m_Ctx ( NULL ) , m_ClassObject ( NULL ), m_RPNPostFilter( NULL), m_ClassName(NULL), m_Ref ( 1 ), m_iQueriesAnswered ( 0 ), m_iQueriesAsked ( 0 ), m_StatusHandle(NULL), m_bAssoc ( FALSE ), m_bSingleton ( FALSE ), m_Serv ( NULL ), m_bIndicate ( TRUE ) , m_ResultReceived ( FALSE ), m_ServerWrap (NULL) { m_Provider = a_Provider ; m_Provider->AddRef () ; m_Serv = a_Serv; if (m_Serv != NULL) { m_Serv->AddRef(); } m_ServerWrap = a_ServerWrap; if (m_ServerWrap != NULL) { m_ServerWrap->AddRef(); } if ((m_Serv == NULL) && (m_ServerWrap == NULL)) { m_Serv = m_Provider->GetServer(); } m_NotificationHandler = a_NotificationHandler ; m_NotificationHandler->AddRef () ; if (a_Ctx) { m_Ctx = a_Ctx ; m_Ctx->AddRef () ; } } WbemTaskObject :: ~WbemTaskObject () { if (m_NotificationHandler) { m_NotificationHandler->Release () ; } if (m_Ctx) { m_Ctx->Release () ; } if (m_ClassName) { SysFreeString(m_ClassName); } if ( m_ClassObject ) { m_ClassObject->Release () ; } if (m_Serv != NULL) { m_Serv->Release(); } if (m_ServerWrap != NULL) { m_ServerWrap->Release(); } int isrc = m_SourceArray.GetSize(); int ins = m_NSpaceArray.GetSize(); int i = isrc; if (isrc > ins) { i = ins; for (int x = ins; x < isrc; x++) { delete m_SourceArray[x]; } } else if (isrc < ins) { for (int x = isrc; x < ins; x++) { delete m_NSpaceArray[x]; } } for (int x = 0; x < i; x++) { delete m_SourceArray[x]; delete m_NSpaceArray[x]; } m_SourceArray.RemoveAll(); m_NSpaceArray.RemoveAll(); for (x = 0; x < m_ObjSinkArray.GetSize(); x++) { if (m_ObjSinkArray[x] != NULL) { m_ObjSinkArray[x]->Release(); } } m_ObjSinkArray.RemoveAll(); m_ClassToIndexMap.RemoveAll(); m_EnumerateClasses.RemoveAll(); //this decrements objectsinprogress so MUST be done LAST!! if (m_Provider) m_Provider->Release (); } WbemProvErrorObject &WbemTaskObject :: GetErrorObject () { return m_ErrorObject ; } BOOL WbemTaskObject :: SetClass(const wchar_t* a_Class) { m_ClassName = SysAllocString(a_Class); BOOL ret = GetClassObject(m_Serv, m_ClassName, &m_ClassObject, &m_ServerWrap); return ret; } BOOL WbemTaskObject :: GetClassObject ( IWbemServices* pServ, BSTR a_Class, IWbemClassObject** ppClass, CWbemServerWrap **a_pServWrap) { if ((NULL == a_Class) || (NULL == ppClass) || ((NULL == pServ) && ((NULL == a_pServWrap) || (NULL == (*a_pServWrap)))) ) { return FALSE; } else { *ppClass = NULL; } HRESULT t_Result = WBEM_E_FAILED; if (*a_pServWrap) { IWbemServices *ptmpServ = (*a_pServWrap)->GetServerOrProxy(); if (ptmpServ) { t_Result = ptmpServ->GetObject(a_Class, 0, m_Ctx, ppClass, NULL); if ( FAILED(t_Result) && (HRESULT_FACILITY(t_Result) != FACILITY_ITF) && (*a_pServWrap)->IsRemote()) { if ( SUCCEEDED(UpdateConnection(a_pServWrap, &ptmpServ)) ) { if (ptmpServ) { t_Result = ptmpServ->GetObject(a_Class, 0, m_Ctx, ppClass, NULL); } } } if (ptmpServ) { (*a_pServWrap)->ReturnServerOrProxy(ptmpServ); } } } else { t_Result = pServ->GetObject(a_Class, 0, m_Ctx, ppClass, NULL); } if (FAILED(t_Result)) { *ppClass = NULL; return FALSE; } return TRUE; } BOOL WbemTaskObject :: GetExtendedNotifyStatusObject ( IWbemClassObject **a_NotifyObject ) { IWbemClassObject *t_NotificationClassObject = NULL ; IWbemClassObject *t_ErrorObject = NULL ; BOOL t_Status = TRUE ; WbemProvErrorObject t_ErrorStatusObject ; if ( t_NotificationClassObject = m_Provider->GetExtendedNotificationObject ( t_ErrorStatusObject, m_Ctx ) ) { HRESULT t_Result = t_NotificationClassObject->SpawnInstance ( 0 , a_NotifyObject ) ; if ( SUCCEEDED ( t_Result ) ) { VARIANT t_Variant ; VariantInit ( &t_Variant ) ; t_Variant.vt = VT_I4 ; t_Variant.lVal = m_ErrorObject.GetWbemStatus () ; t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_STATUSCODE , 0 , &t_Variant , 0 ) ; VariantClear ( &t_Variant ) ; if ( SUCCEEDED ( t_Result ) ) { t_Variant.vt = VT_I4 ; t_Variant.lVal = m_ErrorObject.GetStatus () ; t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_PROVSTATUSCODE , 0 , &t_Variant , 0 ) ; VariantClear ( &t_Variant ) ; if ( SUCCEEDED ( t_Result ) ) { if ( m_ErrorObject.GetMessage () ) { t_Variant.vt = VT_BSTR ; t_Variant.bstrVal = SysAllocString ( m_ErrorObject.GetMessage () ) ; t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_PROVSTATUSMESSAGE , 0 , &t_Variant , 0 ) ; VariantClear ( &t_Variant ) ; if ( ! SUCCEEDED ( t_Result ) ) { (*a_NotifyObject)->Release () ; t_Status = GetNotifyStatusObject ( a_NotifyObject ) ; } } } else { (*a_NotifyObject)->Release () ; t_Status = GetNotifyStatusObject ( a_NotifyObject ) ; } } else { (*a_NotifyObject)->Release () ; t_Status = GetNotifyStatusObject ( a_NotifyObject ) ; } t_NotificationClassObject->Release () ; } else { t_Status = GetNotifyStatusObject ( a_NotifyObject ) ; } } else { t_Status = GetNotifyStatusObject ( a_NotifyObject ) ; } return t_Status ; } BOOL WbemTaskObject :: GetNotifyStatusObject ( IWbemClassObject **a_NotifyObject ) { IWbemClassObject *t_NotificationClassObject = NULL ; BOOL t_Status = TRUE ; WbemProvErrorObject t_ErrorStatusObject ; if ( t_NotificationClassObject = m_Provider->GetNotificationObject ( t_ErrorStatusObject, m_Ctx ) ) { HRESULT t_Result = t_NotificationClassObject->SpawnInstance ( 0 , a_NotifyObject ) ; if ( SUCCEEDED ( t_Result ) ) { VARIANT t_Variant ; VariantInit ( &t_Variant ) ; t_Variant.vt = VT_I4 ; t_Variant.lVal = m_ErrorObject.GetWbemStatus () ; t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_STATUSCODE , 0 , &t_Variant , 0 ) ; if ( SUCCEEDED ( t_Result ) ) { if ( m_ErrorObject.GetMessage () ) { t_Variant.vt = VT_BSTR ; t_Variant.bstrVal = SysAllocString ( m_ErrorObject.GetMessage () ) ; t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_PROVSTATUSMESSAGE , 0 , &t_Variant , 0 ) ; VariantClear ( &t_Variant ) ; if ( ! SUCCEEDED ( t_Result ) ) { t_Status = FALSE ; (*a_NotifyObject)->Release () ; (*a_NotifyObject)=NULL ; } } } else { (*a_NotifyObject)->Release () ; (*a_NotifyObject)=NULL ; t_Status = FALSE ; } VariantClear ( &t_Variant ) ; t_NotificationClassObject->Release () ; } else { t_Status = FALSE ; } } else { t_Status = FALSE ; } return t_Status ; } BOOL WbemTaskObject :: ParseAndProcessClassQualifiers(WbemProvErrorObject &a_ErrorObject, ParsedObjectPath *a_ParsedObjectPath, CMap *parentMap) { if (m_ClassObject == NULL) { a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Failed to get class object representing this class." ) ; return FALSE; } IWbemQualifierSet *pQuals = NULL; if ( FAILED(m_ClassObject->GetQualifierSet(&pQuals)) ) { a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Failed to get qualifiers for this class." ) ; return FALSE; } VARIANT v; VariantInit(&v); BOOL bUnion = FALSE; BOOL retVal = TRUE; if (SUCCEEDED(pQuals->Get(VIEW_QUAL_PROVIDER, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { m_ProviderName = v.bstrVal; } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Provider qualifier is incorrect for this class." ) ; } } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Provider qualifier should be present for this class." ) ; } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_FILTER, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { CTextLexSource querySource(v.bstrVal); SQL1_Parser sqlParser(&querySource); if (SQL1_Parser::SUCCESS == sqlParser.Parse(&m_RPNPostFilter)) { if (_wcsicmp(m_ClassName, m_RPNPostFilter->bsClassName) == 0) { if (m_RPNPostFilter->nNumberOfProperties != 0) { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"PostJoinFilter qualifier may not limit the properties returned." ) ; } } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"PostJoinFilter qualifier does not match this class." ) ; } } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Failed to parse PostJoinFilter qualifier." ) ; } } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"PostJoinFilter qualifier should be a single WQL string." ) ; } } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_JOIN, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { retVal = m_JoinOnArray.Set(v.bstrVal); if (!retVal) { a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Failed to parse JoinOn qualifier." ) ; } } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"JoinOn qualifier should be a single string." ) ; } } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_UNION, 0, &v, NULL)) ) { if (v.vt == VT_BOOL) { bUnion = (v.boolVal == VARIANT_TRUE) ? TRUE : FALSE; } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Union qualifier should be a boolean." ) ; } } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_ASSOC, 0, &v, NULL)) ) { if (v.vt == VT_BOOL) { m_bAssoc = (v.boolVal == VARIANT_TRUE) ? TRUE : FALSE; } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Association qualifier should be a boolean." ) ; } } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_SNGLTN, 0, &v, NULL)) ) { if (v.vt == VT_BOOL) { m_bSingleton = (v.boolVal == VARIANT_TRUE) ? TRUE : FALSE; } else { retVal = FALSE; a_ErrorObject.SetStatus ( WBEM_PROV_E_INVALID_CLASS ) ; a_ErrorObject.SetWbemStatus ( WBEM_E_FAILED ) ; a_ErrorObject.SetMessage ( L"Singleton qualifier should be a boolean." ) ; } } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_ENUM_CLASS, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { m_EnumerateClasses.SetAt(v.bstrVal, 0); } else if (v.vt == (VT_BSTR | VT_ARRAY)) { if (SafeArrayGetDim(v.parray) == 1) { LONG count = v.parray->rgsabound[0].cElements; BSTR HUGEP *pbstr; if ( SUCCEEDED(SafeArrayAccessData(v.parray, (void HUGEP**)&pbstr)) ) { for (LONG x = 0; x < count; x++) { m_EnumerateClasses.SetAt(pbstr[x], 0); } SafeArrayUnaccessData(v.parray); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to access EnumerateClasses array."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"EnumerateClasses array qualifier has incorrect dimensions."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"EnumerateClasses qualifier should be an array of strings."); } } VariantClear(&v); VariantInit(&v); if (retVal && ((bUnion && !m_bAssoc && !m_JoinOnArray.IsValid()) || (!bUnion && m_bAssoc && !m_JoinOnArray.IsValid()) || (!bUnion && !m_bAssoc && m_JoinOnArray.IsValid()))) { if (m_JoinOnArray.IsValid()) { if (!m_JoinOnArray.ValidateJoin()) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Join validation failed"); } } if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_SOURCES, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { CSourceQualifierItem* srcItem = new CSourceQualifierItem(v.bstrVal); if (srcItem->IsValid()) { int indx = m_SourceArray.Add(srcItem); m_ClassToIndexMap.SetAt(srcItem->GetClassName(), indx); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid source query."); delete srcItem; } } else if (v.vt == (VT_BSTR | VT_ARRAY)) { if (SafeArrayGetDim(v.parray) == 1) { LONG count = v.parray->rgsabound[0].cElements; BSTR HUGEP *pbstr; if ( SUCCEEDED(SafeArrayAccessData(v.parray, (void HUGEP**)&pbstr)) ) { for (LONG x = 0; x < count; x++) { CSourceQualifierItem* srcItem = new CSourceQualifierItem(pbstr[x]); if (srcItem->IsValid()) { int indx = m_SourceArray.Add(srcItem); m_ClassToIndexMap.SetAt(srcItem->GetClassName(), indx); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid source query."); delete srcItem; break; } } SafeArrayUnaccessData(v.parray); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid source array qualifier."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid source array qualifier dimensions."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid source array qualifier type."); } } else { if (retVal) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Source array qualifier not found."); } } VariantClear(&v); VariantInit(&v); if (retVal && SUCCEEDED(pQuals->Get(VIEW_QUAL_NAMESPACES, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { CNSpaceQualifierItem* nsItem = new CNSpaceQualifierItem(v.bstrVal); if (nsItem->IsValid()) { m_NSpaceArray.Add(nsItem); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid Namespace in namespaces array."); delete nsItem; } } else if (v.vt == (VT_BSTR | VT_ARRAY)) { if (SafeArrayGetDim(v.parray) == 1) { LONG count = v.parray->rgsabound[0].cElements; BSTR HUGEP *pbstr; if ( SUCCEEDED(SafeArrayAccessData(v.parray, (void HUGEP**)&pbstr)) ) { for (LONG x = 0; x < count; x++) { CNSpaceQualifierItem* nsItem = new CNSpaceQualifierItem(pbstr[x]); if (nsItem->IsValid()) { m_NSpaceArray.Add(nsItem); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Invalid Namespace in namespaces array qualifier."); delete nsItem; break; } } SafeArrayUnaccessData(v.parray); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to access Namespace array qualifier."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Namespace array qualifier has invalid dimensions."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Namespace array qualifier has invalid type."); } } else { if (retVal) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Namespace array qualifier not found."); } } VariantClear(&v); if (retVal && (m_NSpaceArray.GetSize() != m_SourceArray.GetSize())) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Namespace array qualifier does not match source array qualifier size."); } if (retVal && m_bAssoc && m_SourceArray.GetSize() != 1) { if (retVal) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Association views may only have a single source."); } } } else { if (retVal) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"ONE class qualifier out of \"JoinOn\", \"Union\" or \"Association\" MUST be specified."); } } pQuals->Release(); //connect and get classes! if (retVal) { IWbemClassObject*** arrayOfArrayOfObjs = new IWbemClassObject**[m_NSpaceArray.GetSize()]; for (int x = 0; x < m_NSpaceArray.GetSize(); x++) { UINT nsCount = m_NSpaceArray[x]->GetCount(); CWbemServerWrap** servArray = new CWbemServerWrap*[nsCount]; IWbemClassObject** classArray = new IWbemClassObject*[nsCount]; IWbemClassObject* classObj = NULL; CStringW* pathArray = m_NSpaceArray[x]->GetNamespacePaths(); for (UINT i = 0; i < nsCount; i++) { classArray[i] = NULL; if ( FAILED(Connect(pathArray[i], &(servArray[i]))) ) { servArray[i] = NULL; } else if (servArray[i] != NULL) { if (GetClassObject(NULL, m_SourceArray[x]->GetClassName(), &classArray[i], &servArray[i]) && (classObj == NULL)) { classObj = classArray[i]; } } } if (NULL != classObj) { m_SourceArray[x]->SetClassObject(classObj); } arrayOfArrayOfObjs[x] = classArray; m_NSpaceArray[x]->SetServerPtrs(servArray); } //check properties and keys SAFEARRAY* pNames = NULL; DWORD dwKeyCount = 0; BOOL bKeysOK = TRUE; if (retVal && SUCCEEDED(m_ClassObject->GetNames(NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &pNames)) ) { if (SafeArrayGetDim(pNames) == 1) { LONG arraylen = pNames->rgsabound[0].cElements; BSTR HUGEP *pbstr; if ( SUCCEEDED(SafeArrayAccessData(pNames, (void HUGEP**)&pbstr)) ) { for (LONG i = 0; retVal && (i < arraylen); i++) { IWbemQualifierSet* pPropQuals = NULL; if ( SUCCEEDED(m_ClassObject->GetPropertyQualifierSet(pbstr[i], &pPropQuals)) ) { BOOL bHidden = FALSE; BOOL bKey = FALSE; CIMTYPE ct = 0; if ( SUCCEEDED(pPropQuals->Get(VIEW_QUAL_HIDDEN, 0, &v, NULL)) ) { if (v.vt == VT_BOOL) { bHidden = (v.boolVal == VARIANT_TRUE) ? TRUE : FALSE; } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Hidden qualifier should be boolean."); } } VariantInit(&v); if ( SUCCEEDED(pPropQuals->Get(VIEW_QUAL_KEY, 0, &v, NULL)) ) { if (v.vt == VT_BOOL) { if (v.boolVal == VARIANT_TRUE) { bKey = TRUE; dwKeyCount++; if (bKeysOK && (a_ParsedObjectPath != NULL)) { bKeysOK = IsInObjectPath(a_ParsedObjectPath, pbstr[i]); if ((!bKeysOK) && (dwKeyCount > 1)) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_PARAMETER); a_ErrorObject.SetWbemStatus (WBEM_E_INVALID_OBJECT_PATH); a_ErrorObject.SetMessage (L"Keys of class do not match those in the object path passed."); } } } else { bKey = FALSE; } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Key qualifier should be boolean."); } } VariantClear(&v); CStringW refStr; BOOL bDirect = FALSE; if ( SUCCEEDED(m_ClassObject->Get(pbstr[i], 0, NULL, &ct, NULL)) ) { if (ct == CIM_REFERENCE) { VariantInit(&v); if ( SUCCEEDED(pPropQuals->Get(VIEW_QUAL_TYPE, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { //bstrVal is either "ref" OR ref:classname wchar_t* tmp = v.bstrVal; tmp += 4; if (*tmp != '\0') { refStr = tmp; } VARIANT vDirect; VariantInit(&vDirect); if ( SUCCEEDED(pPropQuals->Get(VIEW_QUAL_DIRECT, 0, &vDirect, NULL)) ) { if (vDirect.vt == VT_BOOL) { bDirect = (vDirect.boolVal == VARIANT_TRUE) ? TRUE : FALSE; } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Direct qualifier should be boolean"); } VariantClear(&vDirect); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Cimtype qualifier should be a string"); } VariantClear(&v); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to get the property type from the class definition"); } } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to get a property type from the class definition"); } VariantInit(&v); if ( retVal && SUCCEEDED(pPropQuals->Get(VIEW_QUAL_PROPERTY, 0, &v, NULL)) ) { CPropertyQualifierItem* propItem = new CPropertyQualifierItem(pbstr[i], bHidden, bKey, ct, refStr, bDirect); if (v.vt == VT_BSTR) { if (1 != m_SourceArray.GetSize()) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Property sources qualifier array size does not match source list."); } else { CStringW t_propNameEntry(v.bstrVal); t_propNameEntry.TrimLeft(); t_propNameEntry.TrimRight(); if (t_propNameEntry.IsEmpty()) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Property sources qualifier must name at least one source property."); } else { propItem->m_SrcPropertyNames.Add(t_propNameEntry); } } } else if (v.vt == (VT_BSTR | VT_ARRAY)) { if (SafeArrayGetDim(v.parray) == 1) { LONG count = v.parray->rgsabound[0].cElements; BSTR HUGEP *pPropbstr; if (count != m_SourceArray.GetSize()) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Property sources qualifier array size does not match source list."); } else { if ( SUCCEEDED(SafeArrayAccessData(v.parray, (void HUGEP**)&pPropbstr)) ) { BOOL bNoName = TRUE; for (LONG x = 0; retVal && (x < count); x++) { if ((pPropbstr[x] != NULL) && (*(pPropbstr[x]) != L'\0')) { IWbemClassObject* t_srcObj = m_SourceArray[x]->GetClassObject(); if (t_srcObj != NULL) { CIMTYPE src_ct; if (SUCCEEDED(t_srcObj->Get(pPropbstr[x], 0, NULL, &src_ct, NULL))) { if (src_ct != ct) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Source property type does not match view class."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Source property not found in source class."); } t_srcObj->Release(); } } CStringW t_propNameEntry(pPropbstr[x]); t_propNameEntry.TrimLeft(); t_propNameEntry.TrimRight(); propItem->m_SrcPropertyNames.Add(t_propNameEntry); if (bNoName && !t_propNameEntry.IsEmpty()) { bNoName = FALSE; } } if (bNoName) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Property sources qualifier must name at least one source property."); } SafeArrayUnaccessData(v.parray); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Property sources qualifier array has incorrect dimensions."); } } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to access property sources array qualifier."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Property sources qualifier has incorrect type."); } VariantClear(&v); m_PropertyMap.SetAt(pbstr[i], propItem); } else { if (retVal) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to get property sources qualifier."); } } pPropQuals->Release(); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to access property qualifiers."); } } SafeArrayUnaccessData(pNames); } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Could not access class property names array."); } } else { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Class property names array has invalid dimensions."); } SafeArrayDestroy(pNames); } else { if (retVal) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"Failed to get class property names."); } } if (retVal) { if (a_ParsedObjectPath != NULL) { if (bKeysOK) { if (dwKeyCount != a_ParsedObjectPath->m_dwNumKeys) { retVal = FALSE; } } else { if ((dwKeyCount != 1) || (a_ParsedObjectPath->m_dwNumKeys != 1) || (a_ParsedObjectPath->m_paKeys[0]->m_pName != NULL)) { retVal = FALSE; } } if (!retVal) { a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_PARAMETER); a_ErrorObject.SetWbemStatus (WBEM_E_INVALID_OBJECT_PATH); a_ErrorObject.SetMessage (L"Keys of class do not match those in the object path passed."); } } } //final verifications //=================== if (retVal) { //make sure all enumeration classes exist POSITION pos = m_EnumerateClasses.GetStartPosition(); while (pos) { int val; CStringW tmpStr; m_EnumerateClasses.GetNextAssoc(pos, tmpStr, val); if (!m_ClassToIndexMap.Lookup(tmpStr, val)) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"EnumerateClasses qualifier contains an entry not found in the source list."); break; } } } if (retVal) { if (m_EnumerateClasses.GetCount() == m_SourceArray.GetSize()) { //pointless qualifier if all classes mentioned m_EnumerateClasses.RemoveAll(); } if (m_JoinOnArray.IsValid()) { if (!ValidateJoin()) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); a_ErrorObject.SetMessage (L"JoinOn qualifier is semantically invalid."); } } #if 0 else { //check all union and assoc source keys are view //keys this is done in ValidateClassDependencies //since both checks need to loop through the arrays //of class objects } #endif } //must delete each sub-array in ValidateClassDependencies //as well as release all the ClassObjects!! if (retVal) { if (!ValidateClassDependencies(arrayOfArrayOfObjs, parentMap)) { retVal = FALSE; a_ErrorObject.SetStatus (WBEM_PROV_E_INVALID_CLASS); a_ErrorObject.SetWbemStatus (WBEM_E_FAILED); if (m_JoinOnArray.IsValid()) { a_ErrorObject.SetMessage (L"Loop in provided classes detected."); } else { a_ErrorObject.SetMessage (L"Loop in provided classes detected or key mismatch between view and source class."); } } } else { for (int x = 0; x < m_NSpaceArray.GetSize(); x++) { UINT nsCount = m_NSpaceArray[x]->GetCount(); for (UINT i = 0; i < nsCount; i++) { if (arrayOfArrayOfObjs[x][i] != NULL) { arrayOfArrayOfObjs[x][i]->Release(); } } delete [] arrayOfArrayOfObjs[x]; } } delete [] arrayOfArrayOfObjs; } return retVal; } //takes an object path to a view class and translates it //to the object path of the source instance requested and optionally //returns the object. BSTR WbemTaskObject::MapFromView(BSTR path, const wchar_t* src, IWbemClassObject** pInst, BOOL bAllprops) { BSTR retVal = NULL; if (path == NULL) { return retVal; } CObjectPathParser objectPathParser; wchar_t* objPath = UnicodeStringDuplicate(path); ParsedObjectPath *parsedObjectPath = NULL; if (objectPathParser.Parse(objPath, &parsedObjectPath) == 0) { wchar_t* tmp = parsedObjectPath->GetNamespacePart(); CWbemServerWrap *pServ = NULL; if (tmp != NULL) { BOOL bServOK = TRUE; if (parsedObjectPath->m_pServer != NULL) { if (wcscmp(parsedObjectPath->m_pServer, L".") != 0) { bServOK = FALSE; VARIANT v; if ( SUCCEEDED(m_ClassObject->Get(WBEM_PROPERTY_SERVER, 0, &v, NULL, NULL))) { if ((v.vt == VT_BSTR) && (_wcsicmp(v.bstrVal, parsedObjectPath->m_pServer) == 0)) { bServOK = TRUE; } } VariantClear(&v); } } if (bServOK) { wchar_t* tmppath = m_Provider->GetNamespacePath()->GetNamespacePath(); if (tmppath != NULL) { if (_wcsicmp(tmppath, tmp) == 0) { Connect(tmppath, &pServ); } delete [] tmppath; } } delete [] tmp; } else { wchar_t* tmppath = m_Provider->GetNamespacePath()->GetNamespacePath(); if (tmppath != NULL) { Connect(tmppath, &pServ); delete [] tmppath; } } if (pServ != NULL) { GetObjectTaskObject *t_AsyncEvent = new GetObjectTaskObject (m_Provider, path, 0, m_NotificationHandler, m_Ctx, NULL, pServ); IWbemClassObject* pInstObj = NULL; if (t_AsyncEvent->GetSourceObject(src, &pInstObj, bAllprops) && pInstObj != NULL) { VARIANT v; if (SUCCEEDED(pInstObj->Get(WBEM_PROPERTY_PATH, 0, &v, NULL, NULL)) ) { if (v.vt == VT_BSTR) { retVal = SysAllocString(v.bstrVal); if (pInst != NULL) { pInstObj->AddRef(); *pInst = pInstObj; } } } VariantClear(&v); pInstObj->Release(); } t_AsyncEvent->Release(); pServ->Release(); } } delete [] objPath; if (parsedObjectPath != NULL) { delete parsedObjectPath; } return retVal; } //takes an object path to a source and translates it //to the object path of the view instance requested. BSTR WbemTaskObject::MapToView(BSTR path, const wchar_t* src, CWbemServerWrap **a_ns) { BSTR retVal = NULL; wchar_t* tmppath = m_Provider->GetNamespacePath()->GetNamespacePath(); CWbemServerWrap *pServ = NULL; if (tmppath != NULL) { Connect(tmppath, &pServ); delete [] tmppath; } if (pServ != NULL) { BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1); if (queryLBStr == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } BSTR queryBStr = SysAllocStringLen(NULL, 45 + wcslen(src)); if (queryBStr == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } wcscpy(queryBStr, META_CLASS_QUERY_START); wcscat(queryBStr, src); wcscat(queryBStr, END_QUOTE); IWbemContext * t_pCtx = m_Ctx; if (pServ->IsRemote()) { t_pCtx = NULL; //don't use context for remote calls } IWbemServices *ptmpServ = pServ->GetServerOrProxy(); if (ptmpServ) { IEnumWbemClassObject *t_pEnum = NULL; HRESULT t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0, t_pCtx, &t_pEnum); if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && pServ->IsRemote()) { if ( SUCCEEDED(UpdateConnection(&pServ, &ptmpServ)) ) { if (ptmpServ) { t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0, t_pCtx, &t_pEnum); } } } if (ptmpServ) { pServ->ReturnServerOrProxy(ptmpServ); } if (SUCCEEDED(t_hr)) { if (pServ->IsRemote()) { t_hr = SetSecurityLevelAndCloaking(t_pEnum, pServ->GetPrincipal()); } if (SUCCEEDED(t_hr)) { //now use the enumerator and see if there is a result... ULONG t_count = 0; IWbemClassObject* t_pClsObj = NULL; BOOL t_bContinueEnum = TRUE; //test each class in the derivation chain... while (t_bContinueEnum && (S_OK == t_pEnum->Next(WBEM_INFINITE, 1, &t_pClsObj, &t_count)) ) { if (t_pClsObj) { //get the class name and use the helper object... VARIANT vCls; VariantInit(&vCls); if ( SUCCEEDED(t_pClsObj->Get(WBEM_PROPERTY_CLASS, 0, &vCls, NULL, NULL)) ) { if (vCls.vt == VT_BSTR) { //do this for src and all classes derived from src... //==================================================== HelperTaskObject* validationObj = new HelperTaskObject(m_Provider, vCls.bstrVal, 0, m_NotificationHandler, m_Ctx, NULL, NULL, pServ); IWbemClassObject* pInst = NULL; try { if (validationObj->GetViewObject(path, &pInst, a_ns)) { VARIANT v; if (SUCCEEDED(pInst->Get(WBEM_PROPERTY_PATH, 0, &v, NULL, NULL)) ) { if (v.vt == VT_BSTR) { if (retVal == NULL) { retVal = SysAllocString(v.bstrVal); } else { //make sure they are the //same object else fail //TO DO: Use the most derived instance //too expensive for little gain since //traversal will still get correct instance //========================================== if (!CompareInstPaths(retVal, v.bstrVal)) { SysFreeString(retVal); retVal = NULL; //ambiguous results, quit! t_bContinueEnum = FALSE; } } } } VariantClear(&v); pInst->Release(); } } catch (...) { validationObj->Release(); VariantClear(&vCls); t_pClsObj->Release(); t_pEnum->Release(); pServ->Release(); SysFreeString(queryLBStr); SysFreeString(queryBStr); throw; } validationObj->Release(); } VariantClear(&vCls); } t_pClsObj->Release(); t_pClsObj = NULL; } t_count = 0; } } t_pEnum->Release(); } } SysFreeString(queryLBStr); SysFreeString(queryBStr); if (pServ) { pServ->Release(); } } return retVal; } //takes a reference and maps to the "real world" or to a view //------------------------------------------------------------ BOOL WbemTaskObject::TransposeReference(CPropertyQualifierItem* pItm, VARIANT vSrc, VARIANT* pvDst, BOOL bMapToView, CWbemServerWrap **a_ns) { //make sure reference normalisation/non-normalisation is OK. //Done the best I can..... //========================================================== if (pvDst != NULL) { VariantInit(pvDst); } else { return FALSE; } if (vSrc.vt != VT_BSTR) { return FALSE; } BOOL retVal = FALSE; //associations are the only classes that this //method gets called for, therefore, only a //single source class to interrogate! //============================================= IWbemClassObject* pCls = m_SourceArray[0]->GetClassObject(); if (pCls != NULL) { CIMTYPE ct; //associations are the only classes that this //method gets called for, therefore, only a //single source class to interrogate! //============================================= BSTR strClass = pItm->m_SrcPropertyNames[0].AllocSysString(); if ( SUCCEEDED(pCls->Get(strClass, 0, NULL, &ct, NULL)) ) { if (ct == CIM_REFERENCE) { IWbemQualifierSet* pQuals = NULL; if ( SUCCEEDED(pCls->GetPropertyQualifierSet(strClass, &pQuals)) ) { VARIANT v; if ( SUCCEEDED(pQuals->Get(VIEW_QUAL_TYPE, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { //bstrVal is either "ref" OR ref:classname wchar_t* tmp = v.bstrVal; tmp += 4; if (*tmp != '\0') { if (!pItm->GetReferenceClass().IsEmpty()) { if (pItm->IsDirect()) { if (FAILED(VariantCopy(pvDst, &vSrc))) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } retVal = TRUE; } else { if (bMapToView) { BSTR refStr = MapToView(vSrc.bstrVal, pItm->GetReferenceClass(), a_ns); if (refStr != NULL) { pvDst->vt = VT_BSTR; pvDst->bstrVal = refStr; retVal = TRUE; } } else { //map reference back to source class BSTR refStr = MapFromView(vSrc.bstrVal, tmp); if (refStr != NULL) { pvDst->vt = VT_BSTR; pvDst->bstrVal = refStr; retVal = TRUE; } } } } } else { if (pItm->GetReferenceClass().IsEmpty()) { if (FAILED(VariantCopy(pvDst, &vSrc))) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } retVal = TRUE; } } } VariantClear(&v); } pQuals->Release(); } } } SysFreeString(strClass); pCls->Release(); } return retVal; } //Must release all ClassObjects and free all sub-arrays //===================================================== BOOL WbemTaskObject::ValidateClassDependencies(IWbemClassObject*** arrayofArrayOfObjs, CMap* parentMap) { CMap namespaceClassMap; if (parentMap != NULL) { POSITION pos = parentMap->GetStartPosition(); while (pos) { CStringW tmpStr; int tmpInt; parentMap->GetNextAssoc(pos, tmpStr, tmpInt); namespaceClassMap.SetAt(tmpStr, tmpInt); } } BOOL retVal = TRUE; VARIANT v; VariantInit(&v); if (SUCCEEDED(m_ClassObject->Get(WBEM_PROPERTY_PATH, 0, &v, NULL, NULL)) ) { if (v.vt != VT_BSTR) { retVal = FALSE; } else { int dummyInt; if (namespaceClassMap.Lookup(v.bstrVal, dummyInt)) { retVal = FALSE; } else { namespaceClassMap.SetAt(v.bstrVal, 0); } } } else { retVal = FALSE; } VariantClear(&v); for (int x = 0; x < m_NSpaceArray.GetSize(); x++) { UINT nsCount = m_NSpaceArray[x]->GetCount(); for (UINT i = 0; i < nsCount; i++) { if (arrayofArrayOfObjs[x][i] != NULL) { IWbemQualifierSet* pQuals = NULL; if (retVal && SUCCEEDED(arrayofArrayOfObjs[x][i]->GetQualifierSet(&pQuals)) ) { VariantInit(&v); if (SUCCEEDED(pQuals->Get(VIEW_QUAL_PROVIDER, 0, &v, NULL)) ) { if (v.vt == VT_BSTR) { if (m_ProviderName.CompareNoCase(v.bstrVal) == 0) { VariantClear(&v); VariantInit(&v); if ( SUCCEEDED(arrayofArrayOfObjs[x][i]->Get(WBEM_PROPERTY_PATH, 0, &v, NULL, NULL)) ) { if (v.vt == VT_BSTR) { HelperTaskObject* validationObj = new HelperTaskObject(m_Provider, v.bstrVal, 0, m_NotificationHandler, m_Ctx, NULL, m_NSpaceArray[x]->GetServerPtrs()[i]->GetPrincipal(), m_NSpaceArray[x]->GetServerPtrs()[i]); try { retVal = validationObj->Validate(&namespaceClassMap); } catch (...) { validationObj->Release(); throw; } validationObj->Release(); } else { retVal = FALSE; } } else { retVal = FALSE; } VariantClear(&v); } } else { retVal = FALSE; } } VariantClear(&v); pQuals->Release(); } else { retVal = FALSE; } //Check union, assoc key properties here SAFEARRAY* pNames = NULL; if (retVal && !m_JoinOnArray.IsValid()) { if ( SUCCEEDED(arrayofArrayOfObjs[x][i]->GetNames(NULL, WBEM_FLAG_KEYS_ONLY, NULL, &pNames)) ) { if (SafeArrayGetDim(pNames) == 1) { LONG arraylen = pNames->rgsabound[0].cElements; BSTR HUGEP *pbstr; if ( SUCCEEDED(SafeArrayAccessData(pNames, (void HUGEP**)&pbstr)) ) { for (LONG i = 0; retVal && (i < arraylen); i++) { //find pbstr[i] as a key in the view class //as the xth property name ('cos we're checking the //xth source class) in the property arrays //of m_PropertyMap... retVal = FALSE; POSITION pos = m_PropertyMap.GetStartPosition(); while (pos) { CPropertyQualifierItem* pItm; CStringW itmName; m_PropertyMap.GetNextAssoc(pos, itmName, pItm); if (pItm->IsKey() && (_wcsicmp(pbstr[i], pItm->m_SrcPropertyNames[x]) == 0) ) { retVal = TRUE; break; } } } SafeArrayUnaccessData(pNames); } else { retVal = FALSE; } } else { retVal = FALSE; } SafeArrayDestroy(pNames); } else { retVal = FALSE; } } arrayofArrayOfObjs[x][i]->Release(); } } delete [] arrayofArrayOfObjs[x]; } namespaceClassMap.RemoveAll(); return retVal; } LONG WbemTaskObject::AddRef() { return InterlockedIncrement(&m_Ref); } LONG WbemTaskObject::Release() { LONG t_Ref; if ( (t_Ref = InterlockedDecrement(&m_Ref)) == 0 ) { delete this ; return 0 ; } else { return t_Ref ; } } HRESULT WbemTaskObject :: UpdateConnection(CWbemServerWrap **a_pServ, IWbemServices **a_proxy) { HRESULT retVal = WBEM_NO_ERROR; #ifdef UNICODE if ((*a_pServ)->IsRemote()) { if ((*a_pServ)->ProxyBelongsTo(*a_proxy)) { retVal = Connect((*a_pServ)->GetPath(), a_pServ, TRUE); } (*a_proxy)->Release(); if ( SUCCEEDED(retVal) && (*a_pServ) ) { *a_proxy = (*a_pServ)->GetServerOrProxy(); } else { *a_proxy = NULL; } } #endif return retVal; } HRESULT WbemTaskObject :: Connect(const wchar_t* path, CWbemServerWrap** ppServ, BOOL a_bUpdate) { //this function must lock the critsec and unlock it in a balnaced way //and must also not be locked when calling back into CIMOM... if (ppServ == NULL) { return WBEM_E_INVALID_PARAMETER; } else { if (!a_bUpdate) { *ppServ = NULL; } } if ((m_Provider->sm_ConnectionMade == NULL) || !m_Provider->sm_ServerMap.Lock()) { return WBEM_E_UNEXPECTED; } //possibility of deadlock if ObjectsInProgress == 0 at this point! //therefore Connect should never be called by an object which hasn't //previously incremented ObjectsInProgress!!! BOOL bFound = FALSE; if (!a_bUpdate && !m_Provider->sm_ServerMap.IsEmpty() && m_Provider->sm_ServerMap.Lookup(path, *ppServ) ) { (*ppServ)->AddRef(); bFound = TRUE; } HRESULT hr = WBEM_NO_ERROR; if (!bFound) { //check the map of outstanding connections... int dummyInt = 0; if (!m_Provider->sm_OutStandingConnections.IsEmpty() && m_Provider->sm_OutStandingConnections.Lookup(path, dummyInt) ) { bFound = TRUE; } else { m_Provider->sm_OutStandingConnections[path] = 0; } m_Provider->sm_ServerMap.Unlock(); BOOL t_bWait = TRUE; while (bFound && t_bWait) { DWORD dwWait = WbemWaitForSingleObject(m_Provider->sm_ConnectionMade, VP_CONNECTION_TIMEOUT); if (dwWait == WAIT_OBJECT_0) { if (m_Provider->sm_ServerMap.Lock()) { if (!m_Provider->sm_OutStandingConnections.IsEmpty() && m_Provider->sm_OutStandingConnections.Lookup(path, dummyInt) ) { ResetEvent(m_Provider->sm_ConnectionMade); } else { //no longer outstanding! t_bWait = FALSE;; } m_Provider->sm_ServerMap.Unlock(); } else { //error hr = WBEM_E_FAILED; bFound = FALSE; } } else { //error hr = WBEM_E_FAILED; bFound = FALSE; } } if (SUCCEEDED (hr)) { if (bFound) { if (a_bUpdate) { //another thread did the update on this clear this pointer //chances is are it is the same one and use the one in the map (*ppServ)->Release(); *ppServ = NULL; } if (m_Provider->sm_ServerMap.Lock()) { if ( !m_Provider->sm_ServerMap.IsEmpty() && m_Provider->sm_ServerMap.Lookup(path, *ppServ) ) { (*ppServ)->AddRef(); } else { //it just failed in another thread //don't try it again this time.... hr = WBEM_E_FAILED; } m_Provider->sm_ServerMap.Unlock(); } else { hr = WBEM_E_FAILED; } } else { BSTR bstrPath = SysAllocString(path); //calling back into winmgmt cannot have a lock... hr = DoConnectServer(bstrPath, ppServ, a_bUpdate); SysFreeString(bstrPath); if (FAILED(hr)) { if (a_bUpdate) { //we failed to update, remove the item from the map if (m_Provider->sm_ServerMap.Lock()) { m_Provider->sm_ServerMap.RemoveKey(path); m_Provider->sm_ServerMap.Unlock(); } (*ppServ)->Release(); } *ppServ = NULL; } else { if (m_Provider->sm_ServerMap.Lock()) { if (!a_bUpdate) { (*ppServ)->AddRef(); m_Provider->sm_ServerMap[path] = *ppServ; } else { //has the object been removed in another thread CWbemServerWrap *t_pSrvInMap = NULL; if (m_Provider->sm_ServerMap.IsEmpty() || !m_Provider->sm_ServerMap.Lookup(path, t_pSrvInMap)) { (*ppServ)->AddRef(); m_Provider->sm_ServerMap[path] = *ppServ; } } m_Provider->sm_ServerMap.Unlock(); } else { (*ppServ)->Release(); *ppServ = NULL; hr = WBEM_E_FAILED; } } if (m_Provider->sm_ServerMap.Lock()) { m_Provider->sm_OutStandingConnections.RemoveKey(path); SetEvent(m_Provider->sm_ConnectionMade); m_Provider->sm_ServerMap.Unlock(); } } } else { if (a_bUpdate) { //we failed to update, remove the item from the map if (m_Provider->sm_ServerMap.Lock()) { m_Provider->sm_ServerMap.RemoveKey(path); m_Provider->sm_ServerMap.Unlock(); } (*ppServ)->Release(); *ppServ = NULL; } } } else { m_Provider->sm_ServerMap.Unlock(); } return hr; } //Remote connections for NT4+ only, //Delegation connections for NT5 only. HRESULT WbemTaskObject :: DoConnectServer (BSTR bstrPath, CWbemServerWrap **a_ppServ, BOOL a_bUpdate) { WCHAR wszMachine[MAX_PATH]; wszMachine[0] = L'\0'; // Determine if it is local if (bstrPath != NULL) { if ( (wcslen(bstrPath) > 4) && (bstrPath[0] == L'\\') && (bstrPath[1] == L'\\') ) { WCHAR *t_ServerMachine = &bstrPath[2]; while (*t_ServerMachine) { if ( L'\\' == *t_ServerMachine ) { break ; } t_ServerMachine++; } if ((*t_ServerMachine != L'\\') || (t_ServerMachine == &bstrPath[2])) { return WBEM_E_FAILED; } *t_ServerMachine = L'\0'; wcscpy(wszMachine, &bstrPath[2]); *t_ServerMachine = L'\\'; } } BOOL t_Local = bAreWeLocal ( wszMachine ) ; IWbemServices* pServ = NULL; HRESULT retVal = WBEM_NO_ERROR; wchar_t *prncpl = NULL; if (!t_Local) { //Are we on NT5? DWORD dwVersion = GetVersion(); if (dwVersion < 0x80000000) { #ifdef UNICODE // we are on Windows 2000+ if ( 5 <= (DWORD)(LOBYTE(LOWORD(dwVersion))) ) { if (a_bUpdate) { prncpl = new wchar_t[wcslen((*a_ppServ)->GetPrincipal()) + 1]; wcscpy(prncpl, (*a_ppServ)->GetPrincipal()); } else { // set up the security structures for a remote connection // Setup the authentication structures HINSTANCE t_LibraryInstance = LoadLibrary ( CONST_NETAPI_LIBRARY ) ; if ( t_LibraryInstance ) { NETAPI_PROC_DsGetDcName t_DsGetDcNameW = ( NETAPI_PROC_DsGetDcName ) GetProcAddress ( t_LibraryInstance , CONST_NETAPI_DSPROC ) ; NETAPI_PROC_NetApiBufferFree t_NetApiBufferFree = ( NETAPI_PROC_NetApiBufferFree ) GetProcAddress ( t_LibraryInstance , CONST_NETAPI_NETPROC ) ; if ( t_DsGetDcNameW && t_NetApiBufferFree ) { //get the principal name PDOMAIN_CONTROLLER_INFO pDomInfo = NULL; DWORD dwRet = t_DsGetDcNameW ((const wchar_t*)wszMachine, NULL, NULL, NULL, 0, &pDomInfo); if (dwRet == NO_ERROR) { if (pDomInfo->DomainName != NULL) { prncpl = new wchar_t[wcslen(pDomInfo->DomainName) + wcslen(wszMachine) + 2]; wcscpy(prncpl, pDomInfo->DomainName); wcscat(prncpl, L"\\"); wcscat(prncpl, wszMachine); } t_NetApiBufferFree ((void*)pDomInfo); } } FreeLibrary ( t_LibraryInstance ) ; } } //just try the machine name for the principal if (prncpl == NULL) { prncpl = new wchar_t[wcslen(wszMachine) + 1]; wcscpy(prncpl, wszMachine); } if (prncpl != NULL) { COAUTHIDENTITY authident; memset((void *)&authident,0,sizeof(COAUTHIDENTITY)); authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; COSERVERINFO si; si.pwszName = wszMachine; si.dwReserved1 = 0; si.dwReserved2 = 0; si.pAuthInfo = NULL; COAUTHINFO ai; si.pAuthInfo = &ai; ai.pwszServerPrincName = prncpl; ai.pAuthIdentityData = NULL; retVal = GetCurrentSecuritySettings(&ai.dwAuthnSvc, &ai.dwAuthzSvc, &ai.dwAuthnLevel, &ai.dwImpersonationLevel, &ai.dwCapabilities); //ai.dwAuthnSvc = 16; //ai.dwAuthzSvc = RPC_C_AUTHZ_NONE ; //ai.dwAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT; //ai.dwImpersonationLevel = RPC_C_IMP_LEVEL_DELEGATE; //ai.dwCapabilities = 0X20; if (SUCCEEDED(retVal)) { retVal = CoCreateForConnectServer(bstrPath, &si, &authident, &pServ); } } else { retVal = WBEM_E_FAILED; } } else #endif //UNICODE { retVal = WBEM_E_FAILED; } } else { retVal = WBEM_E_FAILED; } } else { retVal = LocalConnectServer(bstrPath, &pServ); } if (SUCCEEDED(retVal) && pServ != NULL) { if (!a_bUpdate) { *a_ppServ = new CWbemServerWrap(pServ, prncpl, bstrPath); (*a_ppServ)->AddRef(); } else { (*a_ppServ)->SetMainServer(pServ); } pServ->Release(); } else { if (!a_bUpdate) { *a_ppServ = NULL; } } if (prncpl != NULL) { delete [] prncpl; } return retVal; } #ifdef UNICODE HRESULT WbemTaskObject :: CoCreateForConnectServer(BSTR bstrPath, COSERVERINFO* psi, COAUTHIDENTITY* pauthid, IWbemServices** ppServ) { MULTI_QI mqi; mqi.pIID = &IID_IWbemLevel1Login; mqi.pItf = 0; mqi.hr = 0; //delegation doesn't really work with CoCreateInstance.... DWORD dwImp = psi->pAuthInfo->dwImpersonationLevel; if (dwImp > RPC_C_IMP_LEVEL_IMPERSONATE) { psi->pAuthInfo->dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE; } HRESULT retVal = g_pfnCoCreateInstanceEx ( CLSID_WbemLevel1Login, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, psi , 1, &mqi ); psi->pAuthInfo->dwImpersonationLevel = dwImp; if ( retVal == S_OK ) { IWbemLevel1Login* t_pLevel1 = (IWbemLevel1Login*) mqi.pItf ; // If remote, do the security negotiation if (psi) { retVal = SetSecurityLevelAndCloaking(t_pLevel1, psi->pAuthInfo->pwszServerPrincName); } if(retVal == S_OK) { //use null context for remote cimoms... retVal = t_pLevel1->NTLMLogin(bstrPath, 0, 0, 0, ppServ); if(retVal == S_OK) { if (psi) { retVal = SetSecurityLevelAndCloaking(*ppServ, psi->pAuthInfo->pwszServerPrincName); if (retVal != S_OK) { (*ppServ)->Release(); (*ppServ) = NULL; } } } } t_pLevel1->Release(); } else { retVal = WBEM_E_FAILED; } return retVal; } #endif //UNICODE HRESULT WbemTaskObject :: LocalConnectServer(BSTR bstrPath, IWbemServices** ppServ) { IWbemLocator *pLoc = NULL; HRESULT retVal = m_Provider->GetLocator(&pLoc); if (SUCCEEDED (retVal)) { #ifdef UNICODE retVal = pLoc->ConnectServer(bstrPath, NULL, NULL, NULL, 0, NULL, m_Ctx, ppServ); #else retVal = pLoc->ConnectServer(bstrPath, m_Provider->GetUserName(), NULL, NULL, 0, NULL, m_Ctx, ppServ); #endif pLoc->Release(); } if (SUCCEEDED(retVal)) { retVal = SetSecurityLevelAndCloaking(*ppServ, COLE_DEFAULT_PRINCIPAL); if (FAILED(retVal)) { (*ppServ)->Release(); *ppServ = NULL; } } return retVal; } void WbemTaskObject::SetResultReceived() { if (m_ArrayLock.Lock()) { m_ResultReceived = TRUE; m_ArrayLock.Unlock(); } } void WbemTaskObject::SetStatus(HRESULT hr, DWORD index) { if (m_ArrayLock.Lock()) { m_ResultReceived = TRUE; m_iQueriesAnswered++; if (m_iQueriesAsked == m_iQueriesAnswered) { SetEvent(m_StatusHandle); } m_ArrayLock.Unlock(); } } void WbemTaskObject::CleanUpObjSinks(BOOL a_bDisconnect) { for (int x = 0; x < m_ObjSinkArray.GetSize(); x++) { if (m_ObjSinkArray[x] != NULL) { if (a_bDisconnect) { m_ObjSinkArray[x]->Disconnect(); } m_ObjSinkArray[x]->Release(); } } m_ObjSinkArray.RemoveAll(); } DWORD WbemTaskObject::GetIndexList(const wchar_t* a_src, DWORD** a_pdwArray) { if (NULL == a_pdwArray) { return 0; } DWORD retVal = 0; for (DWORD i = 0; i < m_SourceArray.GetSize(); i++) { BOOL t_bAdd = FALSE; if (_wcsicmp(m_SourceArray[i]->GetClassName(), a_src) == 0) { //try classname match... //======================= t_bAdd = TRUE; } else { //try parentclass match... //======================== IWbemClassObject *t_pCls = m_SourceArray[i]->GetClassObject(); if (t_pCls) { VARIANT v; VariantInit(&v); if ( SUCCEEDED(t_pCls->Get(WBEM_PROPERTY_DERIVATION, 0, &v, NULL, NULL)) ) { if (v.vt == VT_BSTR) { if (_wcsicmp(v.bstrVal, a_src) == 0) { t_bAdd = TRUE; } } else if (v.vt == (VT_ARRAY | VT_BSTR)) { if (SafeArrayGetDim(v.parray) == 1) { LONG count = v.parray->rgsabound[0].cElements; BSTR HUGEP *pbstr; if ( SUCCEEDED(SafeArrayAccessData(v.parray, (void HUGEP**)&pbstr)) ) { for (LONG x = 0; x < count; x++) { if (_wcsicmp(pbstr[x], a_src) == 0) { t_bAdd = TRUE; break; } } SafeArrayUnaccessData(v.parray); } } } VariantClear(&v); } t_pCls->Release(); } } if (!t_bAdd) { //try derived class match...i.e. execute the query... //select * from meta_class where __this isa "classname" AND __class = "a_src" //====================================================================================== CWbemServerWrap** nsPtrs = m_NSpaceArray[i]->GetServerPtrs(); for (DWORD j = 0; j < m_NSpaceArray[i]->GetCount(); j++) { if (nsPtrs[j] != NULL) { BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1); if (queryLBStr == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } BSTR queryBStr = SysAllocStringLen(NULL, 61 + wcslen(m_SourceArray[i]->GetClassName()) + wcslen(a_src)); if (queryBStr == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } wcscpy(queryBStr, META_CLASS_QUERY_START); wcscat(queryBStr, m_SourceArray[i]->GetClassName()); wcscat(queryBStr, META_CLASS_QUERY_MID); wcscat(queryBStr, a_src); wcscat(queryBStr, END_QUOTE); IWbemContext * t_pCtx = m_Ctx; if (nsPtrs[j]->IsRemote()) { t_pCtx = NULL; //don't use context for remote calls } IWbemServices *ptmpServ = nsPtrs[j]->GetServerOrProxy(); if (ptmpServ) { IEnumWbemClassObject *t_pEnum = NULL; HRESULT t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0, t_pCtx, &t_pEnum); if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && nsPtrs[j]->IsRemote()) { if ( SUCCEEDED(UpdateConnection(&(nsPtrs[j]), &ptmpServ)) ) { if (ptmpServ) { t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0, t_pCtx, &t_pEnum); } } } if (ptmpServ) { nsPtrs[j]->ReturnServerOrProxy(ptmpServ); } if (SUCCEEDED(t_hr)) { if (nsPtrs[j]->IsRemote()) { t_hr = SetSecurityLevelAndCloaking(t_pEnum, nsPtrs[j]->GetPrincipal()); } if (SUCCEEDED(t_hr)) { //now use the enumerator and see if there is a result... IWbemClassObject* t_pClsObj = NULL; ULONG t_count = 0; //test that a class was returned... if ( S_OK == t_pEnum->Next(WBEM_INFINITE, 1, &t_pClsObj, &t_count) ) { if (t_pClsObj) { t_bAdd = TRUE; t_pClsObj->Release(); } } } t_pEnum->Release(); } } //only check one namespace, class defns should match break; } } } if (t_bAdd) { if (*a_pdwArray == NULL) { *a_pdwArray = new DWORD[m_SourceArray.GetSize() - i]; } (*a_pdwArray)[retVal] = i; retVal++; } } return retVal; }