/*++ // Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved Module Name: ASSOCQP.CPP Abstract: Association query parser History: raymcc 04-Jul-99 Created. raymcc 14-Aug-99 Resubmit due to VSS problem. raymcc 11-Apr-00 Reworked for WMIUTILS --*/ #include "precomp.h" #include #include #include #include #include #include #include #define ASSOC_QUERY_VERSION 2 // ========================================================================== // ASSOCIATION QUERY PARSER. // ========================================================================== #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 // DFA State Table for Assoc query tokens. // ======================================= 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, }; /*---------------------------------------------------- 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 ------------------------------------------------------*/ static BOOL ParseAssocQuery( IN LPWSTR Query, OUT LPWSTR *pTargetObj, OUT LPWSTR *pResultClass, OUT LPWSTR *pAssocClass, OUT LPWSTR *pRole, OUT LPWSTR *pResultRole, OUT LPWSTR *pRequiredQualifier, OUT LPWSTR *pRequiredAssocQualifier, OUT DWORD *pdwQueryType ) { *pTargetObj = 0; *pResultClass = 0; *pAssocClass = 0; *pRole = 0; *pResultRole = 0; *pRequiredQualifier = 0; *pRequiredAssocQualifier = 0; *pdwQueryType = 0; // TBD: Check for out-of-memory here CTextLexSource src(Query); CGenLexer Lexer(AssocQuery_LexTable, &src); int nTok = 0; BOOL bHadTokens = FALSE; // Get first token. // TBD: Check for out-of-memory // ============================= nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; // REFERENCES or ASSOCIATORS // ========================= if (_wcsicmp(L"References", Lexer.GetTokenText()) == 0) *pdwQueryType |= WMIQ_ASSOCQ_REFERENCES; else if (_wcsicmp(L"Associators", Lexer.GetTokenText()) == 0) *pdwQueryType |= WMIQ_ASSOCQ_ASSOCIATORS; else goto Error; // OF // == nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; if (_wcsicmp(L"of", Lexer.GetTokenText()) != 0) goto Error; // {OBJECTPATH} // ============ nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_STRING) goto Error; *pTargetObj = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pTargetObj)) goto Error; // WHERE // ===== nTok = Lexer.NextToken(); if (nTok == QASSOC_TOK_EOF) goto Completed; if (nTok != QASSOC_TOK_IDENT) goto Error; if (_wcsicmp(L"where", Lexer.GetTokenText()) != 0) goto Error; // Check for RESULTCLASS, ROLE, ASSOCCLASS, CLASSDEFSONLY, // REQUIREDQUALIFIER, REQUIREDASSOCQUALIFIER // ====================================================== for (;;) { nTok = Lexer.NextToken(); if (nTok == QASSOC_TOK_ERROR) goto Error; if (nTok == QASSOC_TOK_EOF) { if(!bHadTokens) goto Error; else goto Completed; } if (nTok != QASSOC_TOK_IDENT) goto Error; bHadTokens = TRUE; if (_wcsicmp(L"RESULTCLASS", Lexer.GetTokenText()) == 0) { if(*pResultClass) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_EQU) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; *pResultClass = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pResultClass)) goto Error; *pdwQueryType |= WMIQ_ASSOCQ_RESULTCLASS; } else if (_wcsicmp(L"ROLE", Lexer.GetTokenText()) == 0) { if(*pRole) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_EQU) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; *pRole = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pRole)) goto Error; *pdwQueryType |= WMIQ_ASSOCQ_ROLE; } else if (_wcsicmp(L"RESULTROLE", Lexer.GetTokenText()) == 0) { if(*pResultRole) goto Error; if(*pdwQueryType & WMIQ_ASSOCQ_ASSOCIATORS) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_EQU) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; *pResultRole = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pResultRole)) goto Error; *pdwQueryType |= WMIQ_ASSOCQ_RESULTROLE; } else if (_wcsicmp(L"ASSOCCLASS", Lexer.GetTokenText()) == 0) { if(*pAssocClass) goto Error; if(*pdwQueryType & WMIQ_ASSOCQ_REFERENCES) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_EQU) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; *pAssocClass = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pAssocClass)) goto Error; *pdwQueryType |= WMIQ_ASSOCQ_ASSOCCLASS; } else if (_wcsicmp(L"REQUIREDQUALIFIER", Lexer.GetTokenText()) == 0) { if(*pRequiredQualifier) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_EQU) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; *pRequiredQualifier = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pRequiredQualifier)) goto Error; *pdwQueryType |= WMIQ_ASSOCQ_REQUIREDQUALIFIER; } else if (_wcsicmp(L"REQUIREDASSOCQUALIFIER", Lexer.GetTokenText()) == 0) { if(*pRequiredAssocQualifier) goto Error; if(*pdwQueryType & WMIQ_ASSOCQ_REFERENCES) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_EQU) goto Error; nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; *pRequiredAssocQualifier = Macro_CloneLPWSTR(Lexer.GetTokenText()); if (!(*pRequiredAssocQualifier)) goto Error; *pdwQueryType |= WMIQ_ASSOCQ_REQUIREDASSOCQUALIFIER; } else if (_wcsicmp(L"CLASSDEFSONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= WMIQ_ASSOCQ_CLASSDEFSONLY; } else if (_wcsicmp(L"KEYSONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= WMIQ_ASSOCQ_KEYSONLY; } else if (_wcsicmp(L"SCHEMAONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= WMIQ_ASSOCQ_SCHEMAONLY; } else if (_wcsicmp(L"CLASSREFSONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= WMIQ_ASSOCQ_CLASSREFSONLY; } else { goto Error; } } Completed: if( (*pdwQueryType & WMIQ_ASSOCQ_SCHEMAONLY) && (*pdwQueryType & WMIQ_ASSOCQ_CLASSDEFSONLY)) { goto Error; } return TRUE; Error: delete *pTargetObj; delete *pResultClass; delete *pAssocClass; delete *pRole; delete *pResultRole; delete *pRequiredQualifier; delete *pRequiredAssocQualifier; *pTargetObj = 0; *pResultClass = 0; *pAssocClass = 0; *pRole = 0; *pResultRole = 0; *pdwQueryType = 0; *pRequiredQualifier = 0; *pRequiredAssocQualifier = 0; return FALSE; } //*************************************************************************** // //*************************************************************************** CAssocQueryParser::CAssocQueryParser() { m_uVersion = ASSOC_QUERY_VERSION; m_uFeatureMask = 0; m_uAnalysisType = WMIQ_ANALYSIS_ASSOC_QUERY; m_pPath = 0; m_pszPath = 0; m_pszQueryText = 0; m_pszResultClass = 0; m_pszAssocClass = 0; m_pszRole = 0; m_pszResultRole = 0; m_pszRequiredQualifier = 0; m_pszRequiredAssocQualifier = 0; } //*************************************************************************** // //*************************************************************************** CAssocQueryParser::~CAssocQueryParser() { delete m_pszPath; delete m_pszQueryText; delete m_pszResultClass; delete m_pszAssocClass; delete m_pszRole; delete m_pszResultRole; delete m_pszRequiredQualifier; delete m_pszRequiredAssocQualifier; if (m_pPath) m_pPath->Release(); } //*************************************************************************** // //*************************************************************************** HRESULT CAssocQueryParser::Parse(LPCWSTR pszQuery) { if (pszQuery == NULL) return WBEM_E_INVALID_QUERY; // Clone the query text for debugging. // =================================== int nLen = wcslen(pszQuery) + 1; m_pszQueryText = new wchar_t[nLen]; if (m_pszQueryText == NULL) return WBEM_E_OUT_OF_MEMORY; wcscpy(m_pszQueryText, pszQuery); // Parse it. // ========= BOOL bRes = ParseAssocQuery( m_pszQueryText, &m_pszPath, &m_pszResultClass, &m_pszAssocClass, &m_pszRole, &m_pszResultRole, &m_pszRequiredQualifier, &m_pszRequiredAssocQualifier, &m_uFeatureMask ); if (bRes == FALSE) return WBEM_E_INVALID_QUERY; // Parse the object path. // ====================== if (m_pszPath) { HRESULT hRes= CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &m_pPath); if (FAILED(hRes)) return WBEM_E_FAILED; hRes = m_pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, m_pszPath); if (FAILED(hRes)) return WBEM_E_FAILED; } else return WBEM_E_INVALID_QUERY; return WBEM_S_NO_ERROR; }