//*************************************************************************** // // VPTASKSH.CPP // // Module: WBEM VIEW PROVIDER // // Purpose: Contains the helper taskobject implementation // // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #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 HRESULT SetSecurityLevelAndCloaking(IUnknown* pInterface, const wchar_t* prncpl); extern BOOL bAreWeLocal(WCHAR* pServerMachine); HelperTaskObject::HelperTaskObject(CViewProvServ *a_Provider, const wchar_t *a_ObjectPath, ULONG a_Flag, IWbemObjectSink *a_NotificationHandler , IWbemContext *pCtx, IWbemServices* a_Serv, const wchar_t* prncpl, CWbemServerWrap* a_ServWrap) : WbemTaskObject (a_Provider, a_NotificationHandler, a_Flag, pCtx, a_Serv, a_ServWrap), m_ObjectPath(NULL), m_ParsedObjectPath(NULL), m_principal(NULL) { if (prncpl) { m_principal = UnicodeStringDuplicate(prncpl); } m_ObjectPath = UnicodeStringDuplicate(a_ObjectPath); } HelperTaskObject::~HelperTaskObject () { if (m_ObjectPath != NULL) { delete [] m_ObjectPath; } if (NULL != m_ParsedObjectPath) { delete m_ParsedObjectPath; } if (m_principal) { delete [] m_principal; } } BOOL HelperTaskObject::Validate(CMap* parentMap) { CObjectPathParser objectPathParser; BOOL t_Status = ! objectPathParser.Parse ( m_ObjectPath , &m_ParsedObjectPath ) ; if ( t_Status ) { t_Status = SetClass(m_ParsedObjectPath->m_pClass) ; if ( t_Status ) { t_Status = ParseAndProcessClassQualifiers(m_ErrorObject, NULL, parentMap); } } return t_Status; } //Get the view object given the namespace and object path of the source and the namespace BOOL HelperTaskObject::DoQuery(ParsedObjectPath* parsedObjectPath, IWbemClassObject** pInst, int indx) { if (pInst == NULL) { return FALSE; } else { *pInst = NULL; } BOOL retVal = TRUE; //Create the query string SQL_LEVEL_1_RPN_EXPRESSION tmpRPN; tmpRPN.bsClassName = SysAllocString(m_ClassName); //need enough tokens to handle association work-around serverpath or dotpath or relpath SQL_LEVEL_1_TOKEN* tokArray = new SQL_LEVEL_1_TOKEN[(parsedObjectPath->m_dwNumKeys) * 6]; DWORD dwToks = 0; for (int i = 0; retVal && (i < parsedObjectPath->m_dwNumKeys); i++) { POSITION pos = m_PropertyMap.GetStartPosition(); while (retVal && pos) { CStringW key; CPropertyQualifierItem* propItem; m_PropertyMap.GetNextAssoc(pos, key, propItem); if (!propItem->m_SrcPropertyNames[indx].IsEmpty()) { if (propItem->m_SrcPropertyNames[indx].CompareNoCase(parsedObjectPath->m_paKeys[i]->m_pName) == 0) { tokArray[dwToks].nTokenType = SQL_LEVEL_1_TOKEN::OP_EXPRESSION; tokArray[dwToks].nOperator = SQL_LEVEL_1_TOKEN::OP_EQUAL; tokArray[dwToks].pPropertyName = propItem->GetViewPropertyName().AllocSysString(); if (m_bAssoc && (propItem->GetCimType() == CIM_REFERENCE)) { retVal = TransposeReference(propItem, parsedObjectPath->m_paKeys[i]->m_vValue, &(tokArray[dwToks].vConstValue), TRUE, &m_ServerWrap); if (retVal) { //add the extra tokens if neccessary //for the association work-around wchar_t *t_pChar = tokArray[dwToks].vConstValue.bstrVal; //must be \\server\namespace and not \\.\namespace or relpath if ( (*t_pChar == L'\\') && (*(t_pChar+1) == L'\\') && (*(t_pChar+2) != L'.') ) { //add the dotted version tokArray[dwToks + 1] = tokArray[dwToks++]; t_pChar = tokArray[dwToks].vConstValue.bstrVal + 2; while (*t_pChar != L'\\') { t_pChar++; } --t_pChar; *t_pChar = L'.'; --t_pChar; *t_pChar = L'\\'; --t_pChar; *t_pChar = L'\\'; BSTR t_strtmp = SysAllocString(t_pChar); VariantClear(&(tokArray[dwToks].vConstValue)); VariantInit(&(tokArray[dwToks].vConstValue)); tokArray[dwToks].vConstValue.vt = VT_BSTR; tokArray[dwToks].vConstValue.bstrVal = t_strtmp; dwToks++; tokArray[dwToks].nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR; //add the relpath version tokArray[dwToks + 1] = tokArray[dwToks - 1]; dwToks++; t_pChar = tokArray[dwToks].vConstValue.bstrVal + 4; while (*t_pChar != L':') { t_pChar++; } //exclude the ':' t_pChar++; t_strtmp = SysAllocString(t_pChar); VariantClear(&(tokArray[dwToks].vConstValue)); VariantInit(&(tokArray[dwToks].vConstValue)); tokArray[dwToks].vConstValue.vt = VT_BSTR; tokArray[dwToks].vConstValue.bstrVal = t_strtmp; dwToks++; tokArray[dwToks].nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_OR; } } } else { VariantInit(&(tokArray[dwToks].vConstValue)); if (FAILED(VariantCopy(&(tokArray[dwToks].vConstValue), &(parsedObjectPath->m_paKeys[i]->m_vValue)))) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } } //after every key add an AND //except if this is the first key since there is no where clause dwToks++; if (i != 0) { tokArray[dwToks++].nTokenType = SQL_LEVEL_1_TOKEN::TOKEN_AND; } } } } } BSTR queryStr = NULL; if ( retVal && ((dwToks > 0) || (parsedObjectPath->m_dwNumKeys == 0)) ) { CStringW qStr = GetStringFromRPN(&tmpRPN, dwToks, tokArray); queryStr = qStr.AllocSysString(); } retVal = FALSE; if (queryStr != NULL) { //ExecQuery and test the results IEnumWbemClassObject *pEnum = NULL; HRESULT t_hr = WBEM_E_FAILED; BSTR queryLBStr = SysAllocString(WBEM_QUERY_LANGUAGE_SQL1); if (m_ServerWrap) { IWbemContext * t_pCtx = m_Ctx; if (m_principal != NULL) { t_pCtx = NULL; //don't use context for remote calls } IWbemServices *ptmpServ = m_ServerWrap->GetServerOrProxy(); if (ptmpServ) { t_hr = ptmpServ->ExecQuery(queryLBStr, queryStr, 0, t_pCtx, &pEnum); } if ( FAILED(t_hr) && (HRESULT_FACILITY(t_hr) != FACILITY_ITF) && m_ServerWrap->IsRemote()) { if ( SUCCEEDED(UpdateConnection(&m_ServerWrap, &ptmpServ)) ) { if (ptmpServ) { t_hr = ptmpServ->ExecQuery(queryLBStr, queryStr, 0, t_pCtx, &pEnum); } } } if (ptmpServ) { m_ServerWrap->ReturnServerOrProxy(ptmpServ); } } if (SUCCEEDED(t_hr)) { //set cloaking if remote //============================ if ((m_principal == NULL) || ((m_principal != NULL) && (S_OK == SetSecurityLevelAndCloaking(pEnum, m_principal))) ) { if ( (m_principal != NULL) || ((m_principal == NULL) && SUCCEEDED(SetSecurityLevelAndCloaking(pEnum, COLE_DEFAULT_PRINCIPAL))) ) { ULONG uCount = 0; IWbemClassObject* pObjs[2]; pObjs[0] = NULL; pObjs[1] = NULL; //must be exactly one result... if ( SUCCEEDED(pEnum->Next(WBEM_INFINITE, 2, pObjs, &uCount)) ) { //There should only be one result if (uCount == 1) { if (pObjs[0] != NULL) { *pInst = pObjs[0]; retVal = TRUE; } else { if (pObjs[1] != NULL) { (pObjs[1])->Release(); } } } else { if (pObjs[1] != NULL) { pObjs[1]->Release(); if (pObjs[0] != NULL) { pObjs[0]->Release(); } } } } } } pEnum->Release(); } SysFreeString(queryLBStr); } delete [] tokArray; if (queryStr != NULL) { SysFreeString(queryStr); } return retVal; } //Get a view object given a source path BOOL HelperTaskObject::GetViewObject(const wchar_t* path, IWbemClassObject** pInst, CWbemServerWrap **a_ns) { if ((pInst == NULL) || (path == NULL) || (a_ns == NULL) || (*a_ns == NULL)) { return FALSE; } else { *pInst = NULL; } CObjectPathParser objectPathParser; wchar_t* tmpPath = UnicodeStringDuplicate(path); ParsedObjectPath* parsedObjectPath = NULL; BOOL retVal = !objectPathParser.Parse(tmpPath, &parsedObjectPath); if (retVal && !parsedObjectPath->IsInstance()) { retVal = FALSE; } if (retVal) { retVal = FALSE; if (Validate(NULL)) { //try for all possible classes in namespaces that match //and return as soon as the first view instance is found... //========================================================== for (DWORD i = 0; (i < m_NSpaceArray.GetSize()) && (*pInst == NULL); i++) { CWbemServerWrap** t_pSrvs = m_NSpaceArray[i]->GetServerPtrs(); CStringW* t_pathArray = m_NSpaceArray[i]->GetNamespacePaths(); for (DWORD j = 0; (j < m_NSpaceArray[i]->GetCount()) && (*pInst == NULL); j++) { if (t_pSrvs[j] == NULL) { continue; } BOOL t_bCont = FALSE; //check that the servers match //============================= if ((parsedObjectPath->m_pServer == NULL) || (_wcsicmp(parsedObjectPath->m_pServer, L".") == 0)) { if ((*a_ns)->IsRemote() && t_pSrvs[j]->IsRemote() && (_wcsicmp((*a_ns)->GetPrincipal(), t_pSrvs[j]->GetPrincipal()) == 0)) { t_bCont = TRUE; } else if (!(*a_ns)->IsRemote() && !t_pSrvs[j]->IsRemote()) { t_bCont = TRUE; } } else { BOOL t_Local = bAreWeLocal(parsedObjectPath->m_pServer); if (t_Local && !t_pSrvs[j]->IsRemote()) { t_bCont = TRUE; } else { if (t_pSrvs[j]->IsRemote()) { if (_wcsicmp(t_pSrvs[j]->GetPrincipal(), parsedObjectPath->m_pServer) == 0) { t_bCont = TRUE; } else { DWORD t_len1 = wcslen(parsedObjectPath->m_pServer); DWORD t_len2 = wcslen(t_pSrvs[j]->GetPrincipal()); if ((t_len2 > 0) && (t_len1 > 0) && (t_len1 < t_len2)) { //machine.domain if ((_wcsnicmp(t_pSrvs[j]->GetPrincipal(), parsedObjectPath->m_pServer, t_len1) == 0) && (((const wchar_t*)t_pSrvs[j]->GetPrincipal())[t_len1] == L'.')) { t_bCont = TRUE; } else { //could be the principal is domain\machine wchar_t *slash = wcschr(t_pSrvs[j]->GetPrincipal(), L'\\'); if ((slash != NULL) && (_wcsicmp(parsedObjectPath->m_pServer, (slash+1)) == 0)) { t_bCont = TRUE; } } } } } } } //check the namespace paths now //============================== if (t_bCont) { wchar_t *t_ns1 = parsedObjectPath->GetNamespacePart(); BOOL t_bDel = TRUE; if (t_ns1 == NULL) { t_ns1 = (*a_ns)->GetPath(); t_bDel = FALSE; } wchar_t *t_ns2 = t_pSrvs[j]->GetPath(); if (!t_ns1 || !t_ns2) { t_bCont = FALSE; } else { //normalise...NOTE: no error checking since connection worked or parser worked //============================================================================= if (*t_ns1 == L'\\') { //skip the next slash t_ns1 += 2; while (*t_ns1 != L'\\') { t_ns1++; } t_ns1++; } if (*t_ns2 == L'\\') { //skip the next slash t_ns2 += 2; while (*t_ns2 != L'\\') { t_ns2++; } t_ns2++; } if (_wcsicmp(t_ns1, t_ns2) != 0) { t_bCont = FALSE; } } if (t_bDel && (t_ns1 != NULL)) { delete [] t_ns1; } if (t_bCont) { //check that the class matches //============================= if (_wcsicmp(parsedObjectPath->m_pClass, m_SourceArray[i]->GetClassName()) == 0) { retVal = DoQuery(parsedObjectPath, pInst, j); break; } else { //uh-oh try classes derived from the source, i.e. do the query... //select * from meta_class where __this isa "m_SourceArray[i]->GetClassName()" // and __class = "parsedObjectPath->m_pClass" 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(parsedObjectPath->m_pClass)); 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, parsedObjectPath->m_pClass); wcscat(queryBStr, END_QUOTE); IWbemContext * t_pCtx = m_Ctx; if (t_pSrvs[j]->IsRemote()) { t_pCtx = NULL; //don't use context for remote calls } IWbemServices *ptmpServ = t_pSrvs[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) && t_pSrvs[j]->IsRemote()) { if ( SUCCEEDED(UpdateConnection(&(t_pSrvs[j]), &ptmpServ)) ) { if (ptmpServ) { t_hr = ptmpServ->ExecQuery(queryLBStr, queryBStr, 0, t_pCtx, &t_pEnum); } } } if (ptmpServ) { t_pSrvs[j]->ReturnServerOrProxy(ptmpServ); } if (SUCCEEDED(t_hr)) { if (t_pSrvs[j]->IsRemote()) { t_hr = SetSecurityLevelAndCloaking(t_pEnum, t_pSrvs[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 each class in the derivation chain... if ( S_OK == t_pEnum->Next(WBEM_INFINITE, 1, &t_pClsObj, &t_count) ) { if (t_pClsObj) { retVal = DoQuery(parsedObjectPath, pInst, j); t_pClsObj->Release(); } } } t_pEnum->Release(); } } } } } } } } } delete [] tmpPath; if (parsedObjectPath != NULL) { delete parsedObjectPath; } return retVal; }