//*************************************************************************** // // (c) 1999-2001 by Microsoft Corp. All Rights Reserved. // // wqltoese.cpp // // cvadai 19-Mar-99 Created as prototype for Quasar. // //*************************************************************************** #define _WQLTOESE_CPP_ #pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the #include "precomp.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //*************************************************************************** // // GetNumeric // GetString // GetDouble // //*************************************************************************** SQL_ID GetNumeric(SWQLTypedConst *pExpr) { SQL_ID dRet = 0; if (pExpr) { switch (pExpr->m_dwType) { case VT_LPWSTR: dRet = _wtoi64(pExpr->m_Value.m_pString); break; case VT_I4: dRet = pExpr->m_Value.m_lValue; break; case VT_R4: dRet = pExpr->m_Value.m_dblValue; break; case VT_BOOL: dRet = pExpr->m_Value.m_bValue; default: dRet = 0; break; } } return dRet; } LPWSTR GetString(SWQLTypedConst *pExpr) { LPWSTR lpRet = 0; if (pExpr) { switch (pExpr->m_dwType) { case VT_LPWSTR: lpRet = StripQuotes(pExpr->m_Value.m_pString); break; case VT_I4: lpRet = GetStr((SQL_ID)pExpr->m_Value.m_lValue); break; case VT_R4: lpRet = GetStr(pExpr->m_Value.m_dblValue); break; case VT_BOOL: lpRet = GetStr((SQL_ID)pExpr->m_Value.m_bValue); default: lpRet = 0; break; } } return lpRet; } double GetDouble(SWQLTypedConst *pExpr) { double dRet = 0; wchar_t *pEnd = NULL; if (pExpr) { switch (pExpr->m_dwType) { case VT_LPWSTR: dRet = wcstod(pExpr->m_Value.m_pString, &pEnd); break; case VT_I4: dRet = pExpr->m_Value.m_lValue; break; case VT_R4: dRet = pExpr->m_Value.m_dblValue; break; case VT_BOOL: dRet = pExpr->m_Value.m_bValue; default: dRet = 0; break; } } return dRet; } //*************************************************************************** // // GetESEFunction // //*************************************************************************** ESEFUNCTION GetESEFunction(LPWSTR lpFuncName, SWQLNode *pFunction, LPWSTR * lpColName) { ESEFUNCTION func = ESE_FUNCTION_NONE; if (!lpColName) return func; if (lpFuncName && pFunction) { if (!_wcsicmp(lpFuncName, L"upper")) func = ESE_FUNCTION_UPPER; else if (!_wcsicmp(lpFuncName, L"lower")) func = ESE_FUNCTION_LOWER; else if (!_wcsicmp(lpFuncName, L"datepart")) { if (pFunction->m_dwNodeType == TYPE_SWQLNode_Datepart) { switch(((SWQLNode_Datepart *)pFunction)->m_nDatepart) { case WQL_TOK_YEAR: func = ESE_FUNCTION_DATEPART_YEAR; break; case WQL_TOK_MONTH: func = ESE_FUNCTION_DATEPART_MONTH; break; case WQL_TOK_DAY: func = ESE_FUNCTION_DATEPART_DAY; break; case WQL_TOK_HOUR: func = ESE_FUNCTION_DATEPART_HOUR; break; case WQL_TOK_MINUTE: func = ESE_FUNCTION_DATEPART_MINUTE; break; case WQL_TOK_SECOND: func = ESE_FUNCTION_DATEPART_SECOND; break; case WQL_TOK_MILLISECOND: func = ESE_FUNCTION_DATEPART_MILLISECOND; break; } if (func) { *lpColName = ((SWQLNode_Datepart *)pFunction)->m_pColRef->m_pColName; } } } } return func; } //*************************************************************************** // // GetESEOperator // //*************************************************************************** int GetESEOperator(DWORD dwOp, DWORD StorageType) { int iRet = 0; switch(dwOp) { case WQL_TOK_IN_SUBSELECT: case WQL_TOK_NOT_IN_SUBSELECT: case WQL_TOK_NOT_IN: case WQL_TOK_IN: case WQL_TOK_IN_CONST_LIST: case WQL_TOK_NOT_IN_CONST_LIST: iRet = 0; // not supported break; case WQL_TOK_GT: case WQL_TOK_AFTER: case WQL_TOK_NOT_AFTER: iRet = WQL_TOK_GT; break; case WQL_TOK_LT: case WQL_TOK_BEFORE: case WQL_TOK_NOT_BEFORE: iRet = WQL_TOK_LT; break; case WQL_TOK_LE: case WQL_TOK_GE: case WQL_TOK_EQ: case WQL_TOK_NE: case WQL_TOK_ISNULL: case WQL_TOK_NOT_NULL: case WQL_TOK_LIKE: case WQL_TOK_NOT_LIKE: iRet = dwOp; break; case WQL_TOK_ISA: if (StorageType == WMIDB_STORAGE_REFERENCE || StorageType == WMIDB_STORAGE_COMPACT) iRet = dwOp; break; case WQL_TOK_BETWEEN: if (StorageType != WMIDB_STORAGE_REFERENCE) iRet = dwOp; break; default: iRet = 0; } return iRet; } //*************************************************************************** // // CESETokens::AddToken // //*************************************************************************** HRESULT CESETokens::AddToken(ESEToken *pTok, ESETOKENTYPE type, int *iNumAdded, int iPos ) { HRESULT hr = 0; if (pTok) { if (iPos != -1) m_arrToks.InsertAt(iPos, pTok); else m_arrToks.Add(pTok); if (iNumAdded) (*iNumAdded)++; } if (type && m_arrToks.Size() > 1) { ESEToken *pTok = new ESEToken(type); if (pTok) { m_arrToks.Add(pTok); if (iNumAdded) *iNumAdded++; } else hr = WBEM_E_OUT_OF_MEMORY; } return hr; } //*************************************************************************** // // CESETokens::AddNumericExpr // //*************************************************************************** HRESULT CESETokens::AddNumericExpr (SQL_ID dClassId, SQL_ID dPropertyId, SQL_ID dValue, ESETOKENTYPE type, int op, BOOL bIndexed, SQL_ID dCompValue , ESEFUNCTION func , int *iNumAdded, BOOL bSys) { HRESULT hr = 0; ESEWQLToken *pToken = new ESEWQLToken(type); if (pToken) { pToken->Value.valuetype = ESE_VALUE_TYPE_SQL_ID; pToken->Value.dValue = dValue; pToken->Value.dwFunc = func; pToken->CompValue.valuetype = ESE_VALUE_TYPE_SQL_ID; pToken->CompValue.dValue = dCompValue; pToken->tokentype = ESE_EXPR_TYPE_EXPR; pToken->optype = op; pToken->dScopeId = 0; pToken->dClassId = dClassId; pToken->dPropertyId = dPropertyId; pToken->bIndexed = bIndexed; pToken->bSysProp = bSys; hr = AddToken(pToken, type, iNumAdded); } else hr = WBEM_E_OUT_OF_MEMORY; return hr; } //*************************************************************************** // // CESETokens::AddReferenceExpr // //*************************************************************************** HRESULT CESETokens::AddReferenceExpr (SQL_ID dClassId, SQL_ID dPropertyId, SQL_ID dValue, ESETOKENTYPE type, int op,BOOL bIndexed, SQL_ID dCompValue, ESEFUNCTION func , int *iNumAdded) { HRESULT hr = 0; ESEWQLToken *pToken = new ESEWQLToken(type); if (pToken) { pToken->Value.valuetype = ESE_VALUE_TYPE_REF; pToken->Value.dRefValue = dValue; pToken->Value.dwFunc = func; pToken->CompValue.valuetype = ESE_VALUE_TYPE_REF; pToken->CompValue.dValue = dCompValue; pToken->tokentype = ESE_EXPR_TYPE_EXPR; pToken->optype = op; pToken->dScopeId = 0; pToken->dClassId = dClassId; pToken->dPropertyId = dPropertyId; pToken->bIndexed = bIndexed; hr = AddToken(pToken, type, iNumAdded); } else hr = WBEM_E_OUT_OF_MEMORY; return hr; } //*************************************************************************** // // CESETokens::AddStringExpr // //*************************************************************************** HRESULT CESETokens::AddStringExpr (SQL_ID dClassId, SQL_ID dPropertyId, LPWSTR lpValue, ESETOKENTYPE type, int op,BOOL bIndexed, LPWSTR lpCompValue , ESEFUNCTION func, int *iNumAdded, BOOL bSys) { HRESULT hr = 0; ESEWQLToken *pToken = new ESEWQLToken(type); if (pToken) { pToken->Value.valuetype = ESE_VALUE_TYPE_STRING; pToken->Value.sValue = SysAllocString(lpValue); pToken->Value.dwFunc = func; pToken->CompValue.valuetype = ESE_VALUE_TYPE_STRING; pToken->CompValue.sValue = SysAllocString(lpCompValue); pToken->tokentype = ESE_EXPR_TYPE_EXPR; pToken->optype = op; pToken->dScopeId = 0; pToken->dClassId = dClassId; pToken->dPropertyId = dPropertyId; pToken->bIndexed = bIndexed; pToken->bSysProp = bSys; hr = AddToken(pToken, type, iNumAdded); } else hr = WBEM_E_OUT_OF_MEMORY; return hr; } //*************************************************************************** // // CESETokens::AddRealExpr // //*************************************************************************** HRESULT CESETokens::AddRealExpr (SQL_ID dClassId, SQL_ID dPropertyId, double rValue, ESETOKENTYPE type, int op,BOOL bIndexed, double dCompValue, ESEFUNCTION func , int *iNumAdded) { HRESULT hr = 0; ESEWQLToken *pToken = new ESEWQLToken(type); if (pToken) { pToken->Value.valuetype = ESE_VALUE_TYPE_REAL; pToken->Value.rValue = rValue; pToken->Value.dwFunc = func; pToken->CompValue.valuetype = ESE_VALUE_TYPE_REAL; pToken->CompValue.rValue = dCompValue; pToken->tokentype = ESE_EXPR_TYPE_EXPR; pToken->optype = op; pToken->dScopeId = 0; pToken->dClassId = dClassId; pToken->dPropertyId = dPropertyId; pToken->bIndexed = bIndexed; hr = AddToken(pToken, type, iNumAdded); } else hr = WBEM_E_OUT_OF_MEMORY; return hr; } //*************************************************************************** // // CESETokens::AddPropExpr // //*************************************************************************** HRESULT CESETokens::AddPropExpr (SQL_ID dClassId, SQL_ID dPropertyId, SQL_ID dPropertyId2, DWORD StorageType, ESETOKENTYPE type, int op, BOOL bIndexed , ESEFUNCTION func, ESEFUNCTION func2, int *iNumAdded) { HRESULT hr = 0; ESEWQLToken *pToken = new ESEWQLToken(type); if (pToken) { switch(StorageType) { case WMIDB_STORAGE_STRING: pToken->Value.valuetype = ESE_VALUE_TYPE_STRING; break; case WMIDB_STORAGE_REAL: pToken->Value.valuetype = ESE_VALUE_TYPE_REAL; break; case WMIDB_STORAGE_REFERENCE: pToken->Value.valuetype = ESE_VALUE_TYPE_REF; break; case WMIDB_STORAGE_NUMERIC: pToken->Value.valuetype = ESE_VALUE_TYPE_SQL_ID; break; default: hr = WBEM_E_PROVIDER_NOT_CAPABLE; break; } if (SUCCEEDED(hr)) { pToken->tokentype = ESE_EXPR_TYPE_EXPR; pToken->optype = op; pToken->dScopeId = 0; pToken->dClassId = dClassId; pToken->dPropertyId = dPropertyId; pToken->dCompPropertyId = dPropertyId2; pToken->bIndexed = bIndexed; pToken->Value.dwFunc = func; pToken->CompValue.dwFunc = func2; hr = AddToken(pToken, type, iNumAdded); } } else hr = WBEM_E_OUT_OF_MEMORY; return hr; } //*************************************************************************** // // CESETokens::AddTempQlExpr // //*************************************************************************** HRESULT CESETokens::AddTempQlExpr (TEMPQLTYPE type, SQL_ID dTargetID, SQL_ID dResultClass, LPWSTR lpRole, LPWSTR lpResultRole, SQL_ID dQfr, SQL_ID dAssocQfr, SQL_ID dAssocClass, int *iNumAdded) { HRESULT hr = 0; ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_TARGETID; pToken->dValue = dTargetID; hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } if (dResultClass) { ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_RESULTCLASS; pToken->dValue = dResultClass; hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } if (lpRole) { ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_ROLE; pToken->sValue = SysAllocString(lpRole); hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } if (lpResultRole) { ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_RESULTROLE; pToken->sValue = SysAllocString(lpResultRole); hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } if (dQfr) { ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_REQQUALIFIER; pToken->dValue = dQfr; hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } if (dAssocQfr) { ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_ASSOCQUALIFIER; pToken->dValue = dAssocQfr; hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } if (dAssocClass) { ESETempQLToken *pToken = new ESETempQLToken(ESE_EXPR_TYPE_EXPR, type); if (pToken) { pToken->token = TEMPQL_TOKEN_ASSOCCLASS; pToken->dValue = dAssocClass; hr = AddToken((ESEToken *)pToken, ESE_EXPR_TYPE_AND, iNumAdded); } else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } Exit: return hr; } //*************************************************************************** // // CESETokens::AddSysExpr // //*************************************************************************** HRESULT CESETokens::AddSysExpr (SQL_ID dScopeId, SQL_ID dClassId, int *iNumAdded) { HRESULT hr = 0; if (dScopeId) { m_dScopeId = dScopeId; ESEWQLToken *pTok = new ESEWQLToken (ESE_EXPR_TYPE_EXPR); if (pTok) { pTok->Value.valuetype = ESE_VALUE_TYPE_SYSPROP; pTok->dScopeId = dScopeId; hr = AddToken(pTok, ESE_EXPR_INVALID, iNumAdded, 0); } else hr = WBEM_E_OUT_OF_MEMORY; } if (dClassId) { ESEWQLToken *pTok = new ESEWQLToken (ESE_EXPR_TYPE_EXPR); if (pTok) { pTok->Value.valuetype = ESE_VALUE_TYPE_SYSPROP; pTok->dClassId = dClassId; hr = AddToken(pTok, ESE_EXPR_INVALID, iNumAdded, 0); } else hr = WBEM_E_OUT_OF_MEMORY; } return hr; } //*************************************************************************** // // CESETokens::UnIndexTokens // //*************************************************************************** HRESULT CESETokens::UnIndexTokens(int iNum) { HRESULT hr = 0; int i = GetNumTokens() - iNum; int iStop = GetNumTokens(); // Reset the bIndexed flag on the last iNum tokens for (; i < iStop; i++) { ESEToken *pTok = GetToken(i); if (pTok->tokentype == ESE_EXPR_TYPE_EXPR) { ESEWQLToken *pTok2 = (ESEWQLToken *)pTok; pTok2->bIndexed = FALSE; } } return hr; } //*************************************************************************** // // TempQL Lex Table // //*************************************************************************** /*---------------------------------------------------- References of {objpath} where ResultClass=XXX Role=YYY RequiredQualifier=QualifierName ClassDefsOnly Associators of {objpath} where ResultClass=XXX AssocClass=YYY Role=PPP RequiredQualifier=QualifierName RequiredAssocQualifier=QualifierName ClassDefsOnly ------------------------------------------------------*/ #define QASSOC_TOK_STRING 101 #define QASSOC_TOK_IDENT 102 #define QASSOC_TOK_DOT 103 #define QASSOC_TOK_EQU 104 #define QASSOC_TOK_COLON 105 #define QASSOC_TOK_ERROR 1 #define QASSOC_TOK_EOF 0 #define ST_IDENT 13 #define ST_STRING 19 #define ST_QSTRING 26 #define ST_QSTRING_ESC 30 LexEl AssocQuery_LexTable[] = { // State First Last New state, Return tok, Instructions // ======================================================================= /* 0 */ L'A', L'Z', ST_IDENT, 0, GLEX_ACCEPT, /* 1 */ L'a', L'z', ST_IDENT, 0, GLEX_ACCEPT, /* 2 */ L'_', GLEX_EMPTY, ST_IDENT, 0, GLEX_ACCEPT, /* 3 */ L'{', GLEX_EMPTY, ST_STRING, 0, GLEX_CONSUME, /* 4 */ L'=', GLEX_EMPTY, 0, QASSOC_TOK_EQU, GLEX_ACCEPT|GLEX_RETURN, /* 5 */ L'.', GLEX_EMPTY, 0, QASSOC_TOK_DOT, GLEX_ACCEPT|GLEX_RETURN, /* 6 */ L':', GLEX_EMPTY, 0, QASSOC_TOK_COLON, GLEX_ACCEPT|GLEX_RETURN, /* 7 */ L' ', GLEX_EMPTY, 0, 0, GLEX_CONSUME, /* 8 */ L'\t', GLEX_EMPTY, 0, 0, GLEX_CONSUME, /* 9 */ L'\n', GLEX_EMPTY, 0, 0, GLEX_CONSUME|GLEX_LINEFEED, /* 10 */ L'\r', GLEX_EMPTY, 0, 0, GLEX_CONSUME, /* 11 */ 0, GLEX_EMPTY, 0, QASSOC_TOK_EOF, GLEX_CONSUME|GLEX_RETURN, // Note forced return /* 12 */ GLEX_ANY, GLEX_EMPTY, 0, QASSOC_TOK_ERROR, GLEX_ACCEPT|GLEX_RETURN, /* ST_IDENT */ /* 13 */ L'a', L'z', ST_IDENT, 0, GLEX_ACCEPT, /* 14 */ L'A', L'Z', ST_IDENT, 0, GLEX_ACCEPT, /* 15 */ L'_', GLEX_EMPTY, ST_IDENT, 0, GLEX_ACCEPT, /* 16 */ L'0', L'9', ST_IDENT, 0, GLEX_ACCEPT, /* 17 */ GLEX_ANY, GLEX_EMPTY, 0, QASSOC_TOK_IDENT, GLEX_PUSHBACK|GLEX_RETURN, /* ST_STRING */ /* 18 */ 0, GLEX_EMPTY, 0, QASSOC_TOK_ERROR, GLEX_ACCEPT|GLEX_RETURN, /* 19 */ L'"', GLEX_EMPTY, ST_QSTRING, 0, GLEX_ACCEPT, /* 20 */ L'}', GLEX_EMPTY, 0, QASSOC_TOK_STRING, GLEX_RETURN, /* 21 */ L' ', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT, /* 22 */ L'\r', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT, /* 23 */ L'\n', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT, /* 24 */ L'\t', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT, /* 25 */ GLEX_ANY, GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT, /* ST_QSTRING */ /* 26 */ 0, GLEX_EMPTY, 0, QASSOC_TOK_ERROR, GLEX_ACCEPT|GLEX_RETURN, /* 27 */ L'"', GLEX_EMPTY, ST_STRING, 0, GLEX_ACCEPT, /* 28 */ L'\\', GLEX_EMPTY, ST_QSTRING_ESC, 0, GLEX_ACCEPT, /* 29 */ GLEX_ANY, GLEX_EMPTY, ST_QSTRING, 0, GLEX_ACCEPT, /* ST_QSTRING_ESC */ /* 30 */ GLEX_ANY, GLEX_EMPTY, ST_QSTRING, 0, GLEX_ACCEPT, }; //*************************************************************************** // // CESEBuilder::FormatSQL // //*************************************************************************** HRESULT CESEBuilder::FormatSQL (SQL_ID dScopeId, SQL_ID dScopeClassId, SQL_ID dSuperScope, IWbemQuery *pQuery, CESETokens **ppTokens, DWORD dwFlags, DWORD dwHandleType, SQL_ID *dClassId, BOOL *bHierarchyQuery, BOOL *pIndexCols, BOOL *pSuperSet, BOOL *bDeleteQuery) { // This needs to convert an entire query // into a set of ESE tokens. HRESULT hr = WBEM_S_NO_ERROR; if (!m_pSchema) return WBEM_E_NOT_FOUND; if (pSuperSet) *pSuperSet = FALSE; char szTmpNum[25]; m_dwTableCount = 1; m_bClassSpecified = false; BOOL bDelete = FALSE; m_dNamespace = dScopeId; if (bHierarchyQuery) *bHierarchyQuery = FALSE; CESETokens *pTokens = new CESETokens; if (!pTokens) return WBEM_E_OUT_OF_MEMORY; if (m_dNamespace) { // Scope is an __Instances container // This is shallow by definition. if (dScopeClassId == INSTANCESCLASSID) pTokens->AddSysExpr(dSuperScope, dScopeId); else { // Shallow enumeration if (!(dwFlags & WMIDB_FLAG_QUERY_DEEP)) { if (!(dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER)) pTokens->AddSysExpr(dScopeId, 0); } else { // Deep enumeration; // Enumerate all possible subscopes. SQL_ID dScopeToUse = dScopeId; if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) dScopeToUse = dSuperScope; pTokens->AddSysExpr(dScopeToUse, 0); SQL_ID *pIds = NULL; int iNumScopes = 0; hr = m_pSchema->GetSubScopes(dScopeToUse, &pIds, iNumScopes); if (SUCCEEDED(hr)) { for (int i = 0; i < iNumScopes; i++) { pTokens->AddSysExpr(pIds[i], 0); } delete pIds; } } } } if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) m_dNamespace = dSuperScope; // Containers are not valid scopes. if (pQuery) { SWQLNode *pTop = NULL, *pRoot = NULL; pQuery->GetAnalysis(WMIQ_ANALYSIS_RESERVED, 0, (void **)&pTop); if (pTop) { // Select or Delete... doesn't matter since we have // to fire events for each item ANYWAY. if (pTop->m_pLeft != NULL) { pRoot = pTop->m_pLeft; if (pRoot->m_dwNodeType == TYPE_SWQLNode_Delete) bDelete = TRUE; if (pRoot->m_pLeft != NULL) { // Load the class information hr = GetClassFromNode(pRoot->m_pLeft); if (SUCCEEDED(hr)) { if (m_dClassID == INSTANCESCLASSID) pTokens->AddSysExpr(0, 1); else pTokens->AddSysExpr(0, m_dClassID); } } else hr = WBEM_E_INVALID_SYNTAX; } if (SUCCEEDED(hr)) { // Now we parse the where clause. if (pRoot->m_pRight && pRoot->m_pRight->m_pLeft) { if (pRoot->m_pRight->m_pRight) // group by, having, order by { if (pSuperSet) { *pSuperSet = TRUE; hr = WBEM_S_NO_ERROR; } else hr = WBEM_E_PROVIDER_NOT_CAPABLE; } if (SUCCEEDED(hr)) { BOOL IndexCols = FALSE; _bstr_t sNewSQL; hr = FormatWhereClause((SWQLNode_RelExpr *)pRoot->m_pRight->m_pLeft, pTokens, IndexCols, NULL, NULL, pSuperSet); if (SUCCEEDED(hr) || hr == WBEM_E_PROVIDER_NOT_CAPABLE) { // Make sure the results are limited to instances of the requested class // (Safeguard) if (!m_bClassSpecified) { // __Instances is automatically a shallow hierarchy query if (m_dClassID != INSTANCESCLASSID) { if (bHierarchyQuery) *bHierarchyQuery = TRUE; } } if (hr == WBEM_E_PROVIDER_NOT_CAPABLE) { if (pSuperSet) { *pSuperSet = TRUE; hr = WBEM_S_NO_ERROR; } } } if (pIndexCols) *pIndexCols = IndexCols; } } else { // __Instances is automatically a shallow hierarchy query if (m_dClassID != INSTANCESCLASSID) { if (bHierarchyQuery) *bHierarchyQuery = TRUE; } } if (dClassId) { if (m_dClassID == INSTANCESCLASSID) *dClassId = 1; else *dClassId = m_dClassID; } } if (ppTokens) *ppTokens = pTokens; } else hr = WBEM_E_INVALID_QUERY; } else hr = WBEM_E_INVALID_PARAMETER; if (bDeleteQuery) *bDeleteQuery = bDelete; return hr; } //*************************************************************************** // // CESEBuilder::FormatSQL // //*************************************************************************** HRESULT CESEBuilder::FormatSQL (SQL_ID dScopeId, SQL_ID dScopeClassId, SQL_ID dSuperScope, SQL_ID dTargetObjID, LPWSTR pResultClass, LPWSTR pAssocClass, LPWSTR pRole, LPWSTR pResultRole, LPWSTR pRequiredQualifier, LPWSTR pRequiredAssocQualifier, DWORD dwQueryType, CESETokens **ppTokens, DWORD dwFlags,DWORD dwHandleType, SQL_ID *_dAssocClass, SQL_ID *_dResultClass, BOOL *pSuperSet) { HRESULT hr = WBEM_S_NO_ERROR; DWORD dwRoleID = 0, dwResultRole = 0, dwAssocQfr = 0, dwQfrID = 0; SQL_ID dResultClass = 0; SQL_ID dAssocClass = 0, dTargetObj = 0; _bstr_t sName; SQL_ID dwSuperClassID; DWORD dwTemp; SQL_ID dwScopeID; TEMPQLTYPE type = ESE_TEMPQL_TYPE_ASSOC; if (pSuperSet) *pSuperSet = FALSE; // Containers are not valid scopes. if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) m_dNamespace = dSuperScope; else m_dNamespace = dScopeId; m_pSession->LoadClassInfo(m_pConn, sName, m_dNamespace); hr = m_pSchema->GetClassInfo(dTargetObjID, sName, dwSuperClassID, dwScopeID, dwTemp); CESETokens *pToks = new CESETokens; if (!pToks) return WBEM_E_OUT_OF_MEMORY; if (dwQueryType & QUERY_TYPE_CLASSDEFS_ONLY) { if (pSuperSet) *pSuperSet = TRUE; else { hr = WBEM_E_PROVIDER_NOT_CAPABLE; delete pToks; goto Exit; } } if (m_dNamespace) { if (dScopeClassId == INSTANCESCLASSID) pToks->AddSysExpr(dSuperScope, dScopeId); else { if (!(dwFlags & WMIDB_FLAG_QUERY_DEEP)) { if (!(dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER)) pToks->AddSysExpr(dScopeId, 0); } else hr = E_NOTIMPL; } } // RESULTCLASS if (pResultClass != NULL) { // Get the class ID of this class m_pSession->LoadClassInfo(m_pConn, pResultClass, m_dNamespace); hr = m_pSchema->GetClassID(pResultClass, m_dNamespace, dResultClass); if (FAILED(hr)) goto Exit; if (_dResultClass) *_dResultClass = dResultClass; } // REQUIREDQUALIFIER if (pRequiredQualifier != NULL) { if (pSuperSet) *pSuperSet = TRUE; // Since we are no longer storing class qualifiers as properties, // we have no way of prefiltering this information. //DWORD dwPropId = 0; //hr = m_pSchema->GetPropertyID(pRequiredQualifier, 1, // REPDRVR_FLAG_QUALIFIER, REPDRVR_IGNORE_CIMTYPE, dwQfrID, NULL, NULL, NULL, TRUE); //if (FAILED(hr)) // goto Exit; } // REQUIREDASSOCQUALIFIER if (pRequiredAssocQualifier) { if (pSuperSet) *pSuperSet = TRUE; // Since we are no longer storing class qualifiers as properties, // we have no way of prefiltering this information. //hr = m_pSchema->GetPropertyID(pRequiredAssocQualifier, 1, // REPDRVR_FLAG_QUALIFIER, REPDRVR_IGNORE_CIMTYPE, dwAssocQfr, NULL, NULL, NULL, TRUE); //if (FAILED(hr)) // goto Exit; } // ASSOCCLASS if (pAssocClass) { m_pSession->LoadClassInfo(m_pConn, pAssocClass, m_dNamespace); hr = m_pSchema->GetClassID(pAssocClass, m_dNamespace, dAssocClass); if (FAILED(hr)) goto Exit; if (_dAssocClass) *_dAssocClass = dAssocClass; } if (dwQueryType & QUERY_TYPE_GETREFS) type = ESE_TEMPQL_TYPE_REF; hr = pToks->AddTempQlExpr(type, dTargetObjID, dResultClass, pRole, pResultRole, dwQfrID, dwAssocQfr, dAssocClass); *ppTokens = pToks; Exit: return hr; } //*************************************************************************** // // CESEBuilder::FormatWhereClause // //*************************************************************************** HRESULT CESEBuilder::FormatWhereClause (SWQLNode_RelExpr *pNode, CESETokens *pTokens, BOOL &IndexCols, BOOL *bOrCrit, int *iNumToksAdded, BOOL *pSuperSet) { HRESULT hr = WBEM_S_NO_ERROR; BOOL bDone = FALSE; SQL_ID dClassId = 0; if (pNode) { DWORD dwType = pNode->m_dwExprType; BOOL bOrLeft = FALSE, bOrRight = FALSE; BOOL bIndexLeft = FALSE, bIndexRight = FALSE; int iNumAdded = 0; switch(dwType) { case WQL_TOK_OR: case WQL_TOK_AND: if (pNode->m_pLeft) { hr = FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pLeft, pTokens, bIndexLeft, &bOrLeft, &iNumAdded, pSuperSet); if (hr == WBEM_E_PROVIDER_NOT_CAPABLE) { if (pSuperSet) *pSuperSet = TRUE; else goto Exit; } else if (FAILED(hr)) goto Exit; } if (pNode->m_pRight) { hr = FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pRight, pTokens, bIndexRight, &bOrRight, &iNumAdded, pSuperSet); if (hr == WBEM_E_PROVIDER_NOT_CAPABLE) { if (pSuperSet) *pSuperSet = TRUE; else goto Exit; } else if (FAILED(hr)) goto Exit; } // Indexing logic. If we have an AND token, see if there are // any ORs underneath it. If there are ORs on both sides, we // can't use this criteria as an index, or we will get // possible duplicates. if (SUCCEEDED(hr)) { if (dwType == WQL_TOK_AND) { if (!(bOrLeft && bOrRight)) { if (bIndexLeft || bIndexRight) IndexCols = TRUE; } else { pTokens->UnIndexTokens(iNumAdded); IndexCols = FALSE; } } else // WQL_TOK_OR { pTokens->UnIndexTokens(iNumAdded); IndexCols = FALSE; if (bOrCrit) *bOrCrit = TRUE; } pTokens->AddToken(NULL, (ESETOKENTYPE)dwType, iNumToksAdded); } hr = WBEM_S_NO_ERROR; break; case WQL_TOK_NOT: // Supposedly, only a left clause follows not... if (pNode->m_pLeft) { hr = FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pLeft, pTokens, IndexCols, pSuperSet); if (hr == WBEM_E_PROVIDER_NOT_CAPABLE) { if (pSuperSet) *pSuperSet = TRUE; else goto Exit; } else if (FAILED(hr)) goto Exit; } if (SUCCEEDED(hr)) { m_bClassSpecified = false; // whatever we've done probably negated the class qualifier. pTokens->AddToken(NULL, (ESETOKENTYPE)dwType, iNumToksAdded); IndexCols = FALSE; // They have negated the index criteria. } hr = WBEM_S_NO_ERROR; break; default: // Typed expression m_dwTableCount++; SWQLTypedExpr *pExpr = ((SWQLNode_RelExpr *)pNode)->m_pTypedExpr; if (pExpr != NULL) { DWORD dwProp1 = 0, dwProp2 = 0, dwOp = 0; DWORD dwStorage1 = 0, dwStorage2 = 0; DWORD dwKey1 = 0, dwKey2 = 0; ESEFUNCTION func1, func2; LPWSTR lpColName = pExpr->m_pColRef; func1 = GetESEFunction(pExpr->m_pIntrinsicFuncOnColRef, pExpr->m_pLeftFunction, &lpColName); hr = GetPropertyID(m_dClassID, pExpr->m_pQNLeft, lpColName, dwProp1, dwStorage1, dwKey1); if (SUCCEEDED(hr)) { // Can't query anything stored as image if (dwStorage1 == WMIDB_STORAGE_IMAGE || dwStorage2 == WMIDB_STORAGE_IMAGE) { hr = WBEM_E_QUERY_NOT_IMPLEMENTED; goto Exit; } dwOp = GetESEOperator(pExpr->m_dwRelOperator, dwStorage1); if (!dwOp) hr = WBEM_E_PROVIDER_NOT_CAPABLE; else { // Property to property comparisons BOOL bSysProp = FALSE; if (dwStorage1 == WMIDB_STORAGE_COMPACT) { bSysProp = TRUE; if (dwOp == WQL_TOK_ISA) dwOp = WQL_TOK_EQ; if ((dwOp != WQL_TOK_EQ) && (dwOp != WQL_TOK_NE)) { hr = WBEM_E_PROVIDER_NOT_CAPABLE; goto Exit; } } if ((dwKey1 & 12) && dwOp == WQL_TOK_EQ) IndexCols = TRUE; if (SUCCEEDED(hr) && pExpr->m_pJoinColRef != NULL) { LPWSTR lpColName2 = pExpr->m_pJoinColRef; func2 = GetESEFunction(pExpr->m_pIntrinsicFuncOnJoinColRef, pExpr->m_pRightFunction, &lpColName2); hr = GetPropertyID(m_dClassID, pExpr->m_pQNRight, lpColName2, dwProp2, dwStorage2, dwKey2); if (SUCCEEDED(hr)) { if (dwStorage1 != dwStorage2) { hr = WBEM_E_INVALID_QUERY; goto Exit; } if (dwStorage1 == WMIDB_STORAGE_COMPACT || dwStorage2 == WMIDB_STORAGE_COMPACT) { hr = WBEM_E_PROVIDER_NOT_CAPABLE; goto Exit; } } hr = pTokens->AddPropExpr (m_dClassID, dwProp1, dwProp2, dwStorage1, ESE_EXPR_INVALID, dwOp, IndexCols, func1,func2, iNumToksAdded); } else if (SUCCEEDED(hr) && pExpr->m_pConstValue) { if (pExpr->m_pConstValue->m_dwType == VT_LPWSTR) { if (dwStorage1 == WMIDB_STORAGE_NUMERIC) { SQL_ID dValue = _wtoi64(pExpr->m_pConstValue->m_Value.m_pString); SQL_ID dValue2 = GetNumeric(pExpr->m_pConstValue2); hr = pTokens->AddNumericExpr(m_dClassID, dwProp1, dValue, ESE_EXPR_INVALID, dwOp, IndexCols, dValue2, func1, iNumToksAdded, bSysProp); } else if (dwStorage1 == WMIDB_STORAGE_REFERENCE) { if (dwOp != WQL_TOK_ISA) hr = WBEM_E_PROVIDER_NOT_CAPABLE; else { SQL_ID dRefClassId; m_pSession->LoadClassInfo(m_pConn, pExpr->m_pConstValue->m_Value.m_pString, m_dNamespace); hr = m_pSchema->GetClassID(pExpr->m_pConstValue->m_Value.m_pString, m_dNamespace, dRefClassId); if (SUCCEEDED(hr)) { hr = pTokens->AddReferenceExpr(m_dClassID, dwProp1, dRefClassId, ESE_EXPR_INVALID, dwOp, FALSE, 0, func1, iNumToksAdded); } } } else { LPWSTR lpTemp = StripQuotes(pExpr->m_pConstValue->m_Value.m_pString); LPWSTR lpTemp2 = GetString(pExpr->m_pConstValue2); CDeleteMe r (lpTemp), r2 (lpTemp2); // See if this is a potential caching problem. if (m_dClassID == 1) m_pSession->LoadClassInfo(m_pConn, lpTemp, m_dNamespace); CIMTYPE ct=0; m_pSchema->GetPropertyInfo(dwProp1, NULL, NULL, NULL, (DWORD *)&ct); if (ct != CIM_DATETIME) { hr = pTokens->AddStringExpr(m_dClassID, dwProp1, lpTemp, ESE_EXPR_INVALID, dwOp, IndexCols, lpTemp2, func1, iNumToksAdded, bSysProp); } else { if (pSuperSet) *pSuperSet = TRUE; } } } else if (pExpr->m_pConstValue->m_dwType == VT_NULL) hr = WBEM_E_INVALID_QUERY; else if (pExpr->m_pConstValue->m_dwType == VT_I4) { SQL_ID lVal1 = (long)pExpr->m_pConstValue->m_Value.m_lValue; SQL_ID lVal2 = GetNumeric(pExpr->m_pConstValue2); hr = pTokens->AddNumericExpr(m_dClassID, dwProp1, lVal1, ESE_EXPR_INVALID, dwOp, IndexCols, lVal2, func1, iNumToksAdded, bSysProp); } else if (pExpr->m_pConstValue->m_dwType == VT_R8) { double lVal1 = (double)pExpr->m_pConstValue->m_Value.m_dblValue; double lVal2 = GetDouble(pExpr->m_pConstValue2); hr = pTokens->AddRealExpr(m_dClassID, dwProp1, lVal1, ESE_EXPR_INVALID, dwOp, IndexCols, lVal2, func1, iNumToksAdded); } else if (pExpr->m_pConstValue->m_dwType == VT_BOOL) { SQL_ID lVal1 = (SQL_ID)pExpr->m_pConstValue->m_Value.m_bValue; SQL_ID lVal2 = GetNumeric(pExpr->m_pConstValue2); hr = pTokens->AddNumericExpr(m_dClassID, dwProp1, lVal1, ESE_EXPR_INVALID, dwOp, IndexCols, lVal2, func1, iNumToksAdded, bSysProp); } } } } } } } Exit: return hr; } //*************************************************************************** // // CESEBuilder::GetPropertyID // //*************************************************************************** HRESULT CESEBuilder::GetPropertyID (SQL_ID dClassID, SWQLQualifiedName *pQN, LPCWSTR pColRef, DWORD &PropID, DWORD &Storage, DWORD &Flags) { // If this is an embedded object property, // we need the actual class ID. The only way // to do that is the walk through all the properties, // and reconcile each layer. HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dRefClassId = dClassID; if (pQN != NULL) { hr = WBEM_E_PROVIDER_NOT_CAPABLE; // This is too tricky, since we would have to // find the objects that match the query, // find all objects that have that object as // an embedded object, and so on. Too much // work, for now. /* for (int i = pQN->GetNumNames() - 1; i >= 0; i--) { SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pQN->m_aFields[i]; if (pNF) { hr = m_pSchema->GetPropertyID(pNF->m_pName, dRefClassId, PropID, &dClassID, NULL, NULL, TRUE); if (SUCCEEDED(hr)) { // Look up the property ID for this class. hr = m_pSchema->GetPropertyInfo(PropID, NULL, NULL, &Storage, NULL, &Flags); } } } */ } else if (pColRef != NULL) { wchar_t wName[1024]; if (!_wcsicmp(pColRef, L"__this")) wcscpy(wName, L"__Derivation"); else wcscpy(wName, pColRef); // Look up the property ID for this class. hr = m_pSchema->GetPropertyID(wName, m_dClassID, 0, REPDRVR_IGNORE_CIMTYPE, PropID, &dClassID, NULL, NULL, TRUE); if (SUCCEEDED(hr)) hr = m_pSchema->GetPropertyInfo(PropID, NULL, NULL, &Storage, NULL, &Flags); } else hr = WBEM_E_INVALID_PARAMETER; if (m_dClassID == dClassID) m_bClassSpecified = true; if (Flags & REPDRVR_FLAG_SYSTEM) Storage = WMIDB_STORAGE_COMPACT; return hr; } //*************************************************************************** // // CESEBuilder::GetClassFromNode // //*************************************************************************** HRESULT CESEBuilder::GetClassFromNode (SWQLNode *pNode) { HRESULT hr = WBEM_S_NO_ERROR; LPWSTR lpTableName = NULL; switch(pNode->m_dwNodeType) { case TYPE_SWQLNode_TableRefs: if (((SWQLNode_TableRefs *)pNode)->m_nSelectType == WQL_FLAG_COUNT) return WBEM_E_PROVIDER_NOT_CAPABLE; if (pNode->m_pRight != NULL) { if (pNode->m_pRight->m_pLeft->m_dwNodeType != TYPE_SWQLNode_TableRef) hr = WBEM_E_PROVIDER_NOT_CAPABLE; else { SWQLNode_TableRef *pRef = (SWQLNode_TableRef *)pNode->m_pRight->m_pLeft; lpTableName = pRef->m_pTableName; } } else return WBEM_E_INVALID_SYNTAX; break; case TYPE_SWQLNode_TableRef: if (pNode->m_dwNodeType != TYPE_SWQLNode_TableRef) hr = WBEM_E_INVALID_SYNTAX; else lpTableName = ((SWQLNode_TableRef *)pNode)->m_pTableName; break; default: return WBEM_E_NOT_SUPPORTED; break; } // Query = "select * from __Instances" : fudge it so they get all classes in this namespace. m_pSession->LoadClassInfo(m_pConn, lpTableName, m_dNamespace); hr = m_pSchema->GetClassID(lpTableName, m_dNamespace, m_dClassID); if (FAILED(hr)) hr = WBEM_E_INVALID_QUERY; return hr; }