//*************************************************************************** // // VPQUALS.CPP // // Module: WBEM VIEW PROVIDER // // Purpose: Contains the implementation of qualifier storage classes // // 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 CStringW GetStringFromRPNToken(SQL_LEVEL_1_TOKEN* pRPNToken) { CStringW ret; if (NULL != pRPNToken->pPropertyName) { ret = L'('; ret += pRPNToken->pPropertyName; switch(pRPNToken->nOperator) { case SQL_LEVEL_1_TOKEN::OP_EQUAL: { ret += L'='; } break; case SQL_LEVEL_1_TOKEN::OP_NOT_EQUAL: { ret += L"<>"; } break; case SQL_LEVEL_1_TOKEN::OP_EQUALorGREATERTHAN: { ret += L">="; } break; case SQL_LEVEL_1_TOKEN::OP_EQUALorLESSTHAN: { ret += L"<="; } break; case SQL_LEVEL_1_TOKEN::OP_LESSTHAN: { ret += L'<'; } break; case SQL_LEVEL_1_TOKEN::OP_GREATERTHAN: { ret += L'>'; } break; case SQL_LEVEL_1_TOKEN::OP_LIKE: { ret += L" like "; } break; default: { ret.Empty(); } } if (!ret.IsEmpty()) { switch (pRPNToken->vConstValue.vt) { case VT_NULL: { ret += L"null)"; } break; case VT_BSTR: { if (pRPNToken->bConstIsStrNumeric) { ret += pRPNToken->vConstValue.bstrVal; ret += L')'; } else { ret += L'\"'; wchar_t* buff = new wchar_t[(wcslen(pRPNToken->vConstValue.bstrVal)*2) + 1]; wchar_t* tmp = pRPNToken->vConstValue.bstrVal; wchar_t* tmpBuff = buff; while (*tmp != NULL) { if ((*tmp == L'\\') || (*tmp == L'"')) { *tmpBuff = L'\\'; *tmpBuff++; } *tmpBuff = *tmp; *tmpBuff++; *tmp++; } *tmpBuff = 0; ret += buff; delete [] buff; ret += L"\")"; } } break; case VT_BOOL: { if (pRPNToken->vConstValue.boolVal == VARIANT_TRUE) { ret += L"TRUE)"; } else { ret += L"FALSE)"; } } break ; case VT_I4: { WCHAR tmpBuff[20]; tmpBuff[0] = L'\0'; if ( swprintf(tmpBuff, L"%d", pRPNToken->vConstValue.lVal) ) { ret += tmpBuff; ret += ')'; } else { ret.Empty(); } } break; case VT_I2: { WCHAR tmpBuff[20]; tmpBuff[0] = L'\0'; if ( swprintf(tmpBuff, L"%d", (int)pRPNToken->vConstValue.iVal) ) { ret += tmpBuff; ret += ')'; } else { ret.Empty(); } } break; case VT_UI1: { WCHAR tmpBuff[20]; tmpBuff[0] = L'\0'; if ( swprintf(tmpBuff, L"%d", (int)pRPNToken->vConstValue.bVal) ) { ret += tmpBuff; ret += ')'; } else { ret.Empty(); } } break; case VT_R4: { WCHAR tmpBuff[25]; tmpBuff[0] = L'\0'; if ( swprintf(tmpBuff, L"%G", pRPNToken->vConstValue.fltVal) ) { ret += tmpBuff; ret += ')'; } else { ret.Empty(); } } break; case VT_R8: { WCHAR tmpBuff[25]; tmpBuff[0] = L'\0'; if ( swprintf(tmpBuff, L"%lG", pRPNToken->vConstValue.dblVal) ) { ret += tmpBuff; ret += ')'; } else { ret.Empty(); } } break; default: { ret.Empty(); } } } } return ret; } CStringW GetStringFromRPN(SQL_LEVEL_1_RPN_EXPRESSION* pRPN, DWORD num_extra, SQL_LEVEL_1_TOKEN* pExtraTokens, BOOL bAllprops) { CStringW ret; if (NULL == pRPN) { return ret; } if (NULL != pRPN->bsClassName) { CStringW props; if ((bAllprops) || (0 == pRPN->nNumberOfProperties)) { props = L'*'; } else { props = pRPN->pbsRequestedPropertyNames[0]; for (int x = 1; x < pRPN->nNumberOfProperties; x++) { props += L", "; props += pRPN->pbsRequestedPropertyNames[x]; } props += L", "; props += WBEM_PROPERTY_PATH; props += L", "; props += WBEM_PROPERTY_SERVER; } ret = L"Select "; ret += props; ret += L" From "; ret += pRPN->bsClassName; if ((0 != pRPN->nNumTokens) || (0 != num_extra)) { CStringW whereStr; CArray exprStack; //not likely to get more than five expressions in a row! //if we do, we'll grow the array! exprStack.SetSize(0, 5); DWORD stack_count = 0; for (int x = 0; x < (pRPN->nNumTokens + num_extra); x++) { SQL_LEVEL_1_TOKEN* pToken; if (x < pRPN->nNumTokens) { pToken = &(pRPN->pArrayOfTokens[x]); } else { pToken = &(pExtraTokens[x - pRPN->nNumTokens]); } if (SQL_LEVEL_1_TOKEN::OP_EXPRESSION == pToken->nTokenType) { if (whereStr.IsEmpty()) { whereStr = GetStringFromRPNToken(pToken); if (whereStr.IsEmpty()) { ret.Empty(); break; } } else { exprStack.SetAtGrow(stack_count, GetStringFromRPNToken(pToken)); if (exprStack[stack_count].IsEmpty()) { ret.Empty(); break; } stack_count++; } } else if (SQL_LEVEL_1_TOKEN::TOKEN_NOT == pToken->nTokenType) { CStringW tempStr(L"(Not "); if (stack_count > 0) { tempStr += exprStack[stack_count-1]; tempStr += L')'; exprStack.SetAt(stack_count-1, tempStr); } else if (!whereStr.IsEmpty()) { tempStr += whereStr; tempStr += L')'; whereStr = tempStr; } else { ret.Empty(); break; } } else { CStringW opStr; if (SQL_LEVEL_1_TOKEN::TOKEN_AND == pToken->nTokenType) { opStr = L" And "; } else if (SQL_LEVEL_1_TOKEN::TOKEN_OR == pToken->nTokenType) { opStr = L" Or "; } else { ret.Empty(); break; } CStringW tempStr(L'('); if (stack_count > 1) { tempStr += exprStack[stack_count-2]; tempStr += opStr; tempStr += exprStack[stack_count-1]; tempStr += L')'; exprStack.SetAt(stack_count-2, tempStr); stack_count = stack_count--; } else if (stack_count == 1) { tempStr += whereStr; tempStr += opStr; tempStr += exprStack[0]; tempStr += L')'; whereStr = tempStr; stack_count = 0; } else { ret.Empty(); whereStr.Empty(); break; } } } exprStack.RemoveAll(); if (whereStr.IsEmpty() || (stack_count != 0)) { ret.Empty(); } else { ret += L" Where "; ret += whereStr; } } } return ret; } CSourceQualifierItem::CSourceQualifierItem(wchar_t* qry, IWbemClassObject* obj) : m_pClassObj(NULL), m_RPNExpr(NULL) { m_isValid = FALSE; m_QueryStr = qry; if (NULL != qry) { CTextLexSource querySource(qry); SQL1_Parser sqlParser(&querySource); m_isValid = SQL1_Parser::SUCCESS == sqlParser.Parse(&m_RPNExpr); } m_pClassObj = obj; if (NULL != m_pClassObj) { m_pClassObj->AddRef(); } } CSourceQualifierItem::~CSourceQualifierItem() { if (NULL != m_RPNExpr) { delete m_RPNExpr; } if (NULL != m_pClassObj) { m_pClassObj->Release(); } } void CSourceQualifierItem::SetClassObject(IWbemClassObject* pObj) { if (NULL != m_pClassObj) { m_pClassObj->Release(); } if (NULL != pObj) { pObj->AddRef(); } m_pClassObj = pObj; } IWbemClassObject* CSourceQualifierItem::GetClassObject() { if (NULL != m_pClassObj) { m_pClassObj->AddRef(); } return m_pClassObj; } BSTR CSourceQualifierItem::GetClassName() { if (NULL != m_RPNExpr) { return m_RPNExpr->bsClassName; } return NULL; } CNSpaceQualifierItem::CNSpaceQualifierItem(const wchar_t* ns_path) { m_Valid = FALSE; m_ServObjs = NULL; m_NSPaths = NULL; m_Count = 0; if (NULL != ns_path) { Parse(ns_path); } } CNSpaceQualifierItem::~CNSpaceQualifierItem() { if (NULL != m_ServObjs) { for (UINT x = 0; x < m_Count; x++) { if (NULL != m_ServObjs[x]) { m_ServObjs[x]->Release(); } } delete [] m_ServObjs; } if (m_NSPaths != NULL) { delete [] m_NSPaths; } } void CNSpaceQualifierItem::Parse(const wchar_t* ns_path) { wchar_t* buff = _wcsdup(ns_path); if (buff == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } wchar_t* tmp = wcsstr(buff, NS_DELIMIT); CFreeBuff _1(buff); if (tmp == NULL) { m_NSPaths = new CStringW[1]; m_NSPaths[0] = buff; m_NSPaths[0].TrimLeft(); if (m_NSPaths[0].IsEmpty()) { delete [] m_NSPaths; m_NSPaths = NULL; } else { m_Count = 1; m_Valid = TRUE; m_NSPaths[0].TrimRight(); } } else { wchar_t** tmpbuff = (wchar_t**)malloc(MAX_QUERIES*sizeof(wchar_t*)); if (tmpbuff == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } CFreeBuff _2(tmpbuff); if (tmp != buff) { tmpbuff[0] = buff; m_Count++; } while (TRUE) { *tmp = L'\0'; tmp = tmp + 2; if (*tmp != L'\0') { tmpbuff[m_Count] = tmp; tmp = wcsstr(tmpbuff[m_Count], NS_DELIMIT); m_Count++; if (tmp == NULL) { break; } if ( (m_Count > 0) && (0 == (m_Count%MAX_QUERIES)) ) { UINT x = _msize(tmpbuff); tmpbuff = (wchar_t**)realloc(tmpbuff, x+(MAX_QUERIES*sizeof(wchar_t*))); _2.SetBuff(tmpbuff); if (tmpbuff == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } } } else { break; } } if (m_Count > 0) { m_NSPaths = new CStringW[m_Count]; for (UINT x=0; x < m_Count; x++) { m_NSPaths[x] = tmpbuff[x]; m_NSPaths[x].TrimLeft(); if (m_NSPaths[x].IsEmpty()) { break; } else { m_NSPaths[x].TrimRight(); } } if (!m_NSPaths[m_Count-1].IsEmpty()) { m_Valid = TRUE; } } } } CJoinOnQualifierArray::CJoinOnQualifierArray() { m_Count = 0; m_AClasses = NULL; m_AProps = NULL; m_BClasses = NULL; m_BProps = NULL; m_Ops = NULL; m_Buff = NULL; m_Valid = FALSE; m_bDone = NULL; } CJoinOnQualifierArray::~CJoinOnQualifierArray() { if (NULL != m_AClasses) { free(m_AClasses); } if (NULL != m_BClasses) { free(m_BClasses); } if (NULL != m_AProps) { free(m_AProps); } if (NULL != m_BProps) { free(m_BProps); } if (NULL != m_Ops) { free(m_Ops); } if (NULL != m_Buff) { free(m_Buff); } if (NULL != m_bDone) { delete [] m_bDone; } m_AllClasses.RemoveAll(); } BOOL CJoinOnQualifierArray::Set(const wchar_t* jStr) { if (NULL != jStr) { Parse(jStr); } return m_Valid; } void CJoinOnQualifierArray::Parse(const wchar_t* qualStr) { m_Buff = _wcsdup(qualStr); wchar_t* tmp = m_Buff; m_Valid = TRUE; m_AClasses = (wchar_t**)malloc(MAX_QUERIES*sizeof(wchar_t*)); if (m_AClasses == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_BClasses = (wchar_t**)malloc(MAX_QUERIES*sizeof(wchar_t*)); if (m_BClasses == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_AProps = (wchar_t**)malloc(MAX_QUERIES*sizeof(wchar_t*)); if (m_AProps == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_BProps = (wchar_t**)malloc(MAX_QUERIES*sizeof(wchar_t*)); if (m_BProps == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_Ops = (UINT*)malloc(MAX_QUERIES*sizeof(UINT)); if (m_Ops == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } while ((tmp != NULL) && (L'\0' != *tmp) && (m_Valid)) { m_AClasses[m_Count] = GetClassStr(tmp); if ((NULL != m_AClasses[m_Count]) && (L'\0' != *(m_AClasses[m_Count]))) { m_AllClasses.SetAt(m_AClasses[m_Count], 0); m_AProps[m_Count] = GetPropertyStrAndOperator(tmp, m_Ops[m_Count]); if ((NULL != m_AProps[m_Count]) && (L'\0' != *(m_AProps[m_Count])) && (0 != m_Ops[m_Count])) { m_BClasses[m_Count] = GetClassStr(tmp); if ((NULL != m_BClasses[m_Count]) && (L'\0' != *(m_BClasses[m_Count]))) { m_AllClasses.SetAt(m_BClasses[m_Count], 0); m_BProps[m_Count] = GetPropertyStr(tmp); if ((NULL != m_BProps[m_Count]) && (L'\0' != *(m_BProps[m_Count])) && StripAnd(tmp)) { m_Count++; if ((tmp != NULL) && (L'\0' != *tmp) && (m_Count > 0) && (0 == (m_Count%MAX_QUERIES)) ) { UINT x = _msize(m_AClasses); m_AClasses = (wchar_t**)realloc(m_AClasses, x+(MAX_QUERIES*sizeof(wchar_t*))); if (m_AClasses == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_BClasses = (wchar_t**)realloc(m_BClasses, x+(MAX_QUERIES*sizeof(wchar_t*))); if (m_BClasses == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_AProps = (wchar_t**)realloc(m_AProps, x+(MAX_QUERIES*sizeof(wchar_t*))); if (m_AProps == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } m_BProps = (wchar_t**)realloc(m_BProps, x+(MAX_QUERIES*sizeof(wchar_t*))); if (m_BProps == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } x = _msize(m_Ops); m_Ops = (UINT*)realloc(m_Ops, x+(MAX_QUERIES*sizeof(UINT))); if (m_Ops == NULL) { throw Heap_Exception(Heap_Exception::HEAP_ERROR::E_ALLOCATION_ERROR); } } } else { m_Valid = FALSE; } } else { m_Valid = FALSE; } } else { m_Valid = FALSE; } } else { m_Valid = FALSE; } } if (0 == m_Count) { m_Valid = FALSE; } if (!m_Valid) { if (NULL != m_AClasses) { free(m_AClasses); m_AClasses = NULL; } if (NULL != m_BClasses) { free(m_BClasses); m_BClasses = NULL; } if (NULL != m_AProps) { free(m_AProps); m_AProps = NULL; } if (NULL != m_BProps) { free(m_BProps); m_BProps = NULL; } if (NULL != m_Ops) { free(m_Ops); m_Ops = NULL; } if (NULL != m_Buff) { free(m_Buff); m_Buff = NULL; } } else { m_bDone = new BOOL[m_Count]; memset((void *)m_bDone, 0, sizeof(BOOL)*m_Count); } } wchar_t* CJoinOnQualifierArray::SkipSpace(wchar_t*& src) { while (iswspace(*src)) { if (*src != L'\0') { *src = L'\0'; src++; } } return ((*src == L'\0') ? NULL : src); } wchar_t* CJoinOnQualifierArray::SkipToSpecial(wchar_t*& src) { while ((*src != L'.') && (*src != L'=') && (*src != L'!') && (*src != L'<') && !iswspace(*src) && (*src != L'\0')) { src++; } return ((*src == L'\0') ? NULL : src); } wchar_t* CJoinOnQualifierArray::GetClassStr(wchar_t*& src) { wchar_t* ret = SkipSpace(src); if (NULL != ret) { src = SkipToSpecial(src); if ((NULL != src) && (src != ret) && ((*src == L'.'))) { *src = L'\0'; src++; } else { ret = NULL; } } return ret; } wchar_t* CJoinOnQualifierArray::GetPropertyStrAndOperator(wchar_t*& src, UINT& op) { wchar_t* ret = src; op = NO_OPERATOR; src = SkipToSpecial(src); src = SkipSpace(src); if ((NULL != src) && (src != ret)) { if (*src == L'=') { *src = L'\0'; op = EQUALS_OPERATOR; src++; } else if (*src == L'!') { wchar_t* prev = src; src++; if (*src == L'=') { *prev = L'\0'; op = NOT_EQUALS_OPERATOR; src++; } else { ret = NULL; } } else if (*src == L'<') { wchar_t* prev = src; src++; if (*src == L'>') { *prev = L'\0'; op = NOT_EQUALS_OPERATOR; src++; } else { ret = NULL; } } } else { ret = NULL; } return ret; } wchar_t* CJoinOnQualifierArray::GetPropertyStr(wchar_t*& src) { wchar_t* ret = src; src = SkipToSpecial(src); if (NULL != src) { if ( (src != ret) && iswspace(*src) ) { if (*src != L'\0') { *src = L'\0'; src++; } } else { ret = NULL; } } return ret; } BOOL CJoinOnQualifierArray::StripAnd(wchar_t*& src) { if (NULL == src) { return TRUE; } src = SkipSpace(src); if (NULL == src) { return TRUE; } if ((*src == L'a') || (*src == L'A')) { src++; if ((*src == L'n') || (*src == L'N')) { src++; if ((*src == L'd') || (*src == L'D')) { src++; wchar_t* tmp = src; src = SkipSpace(src); if ((NULL != src) && (tmp != src)) { return TRUE; } } } } return FALSE; } BOOL CJoinOnQualifierArray::ValidateJoin() { if (!m_Valid) { return m_Valid; } CMap validatedClasses; CArray spareClasses; UINT x = 0; if (_wcsicmp(m_AClasses[x], m_BClasses[x]) == 0) { m_Valid = FALSE; } else { validatedClasses.SetAt(m_AClasses[x], 0); validatedClasses.SetAt(m_BClasses[x], 0); x++; } while ((m_Valid) && (x < m_Count)) { if (_wcsicmp(m_AClasses[x], m_BClasses[x]) == 0) { m_Valid = FALSE; } else { UINT val; if (validatedClasses.Lookup(m_AClasses[x], val)) { validatedClasses.SetAt(m_BClasses[x], 0); } else { if (validatedClasses.Lookup(m_BClasses[x], val)) { validatedClasses.SetAt(m_AClasses[x], 0); } else { spareClasses.Add(m_AClasses[x]); spareClasses.Add(m_BClasses[x]); } } } x++; } while ( m_Valid && (0 != spareClasses.GetSize()) ) { m_Valid = FALSE; for (int i = 0; i < spareClasses.GetSize(); i++) { UINT val; if (validatedClasses.Lookup(spareClasses[i], val)) { if (0 == (i%2)) { validatedClasses.SetAt(spareClasses[i+1], 0); spareClasses.RemoveAt(i, 2); i -= 1; } else { validatedClasses.SetAt(spareClasses[i-1], 0); spareClasses.RemoveAt(i-1, 2); i -= 2; } m_Valid = TRUE; } } } spareClasses.RemoveAll(); validatedClasses.RemoveAll(); return m_Valid; } CPropertyQualifierItem::CPropertyQualifierItem(const wchar_t* prop, BOOL bHD, BOOL bKy, CIMTYPE ct, CStringW rfto, BOOL bDt) { if (NULL != prop) { m_ViewPropertyName = prop; } m_bDirect = bDt; m_HiddenDefault = bHD; m_bKey = bKy; m_CimType = ct; m_RefTo = rfto; } CPropertyQualifierItem::~CPropertyQualifierItem() { m_SrcPropertyNames.RemoveAll(); }