/*++ Copyright (C) 1999-2001 Microsoft Corporation Module Name: ASSOCQP.CPP Abstract: Association query parser History: raymcc 04-Jul-99 Created. raymcc 14-Aug-99 Resubmit due to VSS problem. --*/ #include "precomp.h" #include #include #include // ========================================================================== // 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; // SEC:REVIEWED 2002-03-22 : Enforce max query limit length here with a wcslen in an EH // ... // SEC:REVIEWED 2002-03-22 : Needs EH around these contructors in case they throw 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(); // SEC:REVIEWED 2002-03-22 : Assume lexer enforces limit if (nTok != QASSOC_TOK_IDENT) goto Error; // REFERENCES or ASSOCIATORS // ========================= if (wbem_wcsicmp(L"References", Lexer.GetTokenText()) == 0) // SEC:REVIEWED 2002-03-22 : This and following occurrences are ok *pdwQueryType |= QUERY_TYPE_GETREFS; else if (wbem_wcsicmp(L"Associators", Lexer.GetTokenText()) == 0) *pdwQueryType |= QUERY_TYPE_GETASSOCS; else goto Error; // OF // == nTok = Lexer.NextToken(); if (nTok != QASSOC_TOK_IDENT) goto Error; if (wbem_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 (NULL == *pTargetObj) goto Error; // WHERE // ===== nTok = Lexer.NextToken(); if (nTok == QASSOC_TOK_EOF) goto Completed; if (nTok != QASSOC_TOK_IDENT) goto Error; if (wbem_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 (wbem_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()); } else if (wbem_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()); } else if (wbem_wcsicmp(L"RESULTROLE", Lexer.GetTokenText()) == 0) { if(*pResultRole) goto Error; if(*pdwQueryType & QUERY_TYPE_GETREFS) 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()); } else if (wbem_wcsicmp(L"ASSOCCLASS", Lexer.GetTokenText()) == 0) { if(*pAssocClass) goto Error; if(*pdwQueryType & QUERY_TYPE_GETREFS) 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()); } else if (wbem_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()); } else if (wbem_wcsicmp(L"REQUIREDASSOCQUALIFIER", Lexer.GetTokenText()) == 0) { if(*pRequiredAssocQualifier) goto Error; if(*pdwQueryType & QUERY_TYPE_GETREFS) 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()); } else if (wbem_wcsicmp(L"CLASSDEFSONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= QUERY_TYPE_CLASSDEFS_ONLY; } else if (wbem_wcsicmp(L"KEYSONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= QUERY_TYPE_KEYSONLY; } else if (wbem_wcsicmp(L"SCHEMAONLY", Lexer.GetTokenText()) == 0) { *pdwQueryType |= QUERY_TYPE_SCHEMA_ONLY; } else { goto Error; } } Completed: if( (*pdwQueryType & QUERY_TYPE_SCHEMA_ONLY) && (*pdwQueryType & QUERY_TYPE_CLASSDEFS_ONLY)) { 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_pszQueryText = 0; m_pszTargetObjPath = 0; m_pszResultClass = 0; m_pszAssocClass= 0; m_pszRole = 0; m_pszResultRole = 0; m_pszRequiredQual = 0; m_pszRequiredAssocQual = 0; m_dwType = 0; m_pPath = 0; } //*************************************************************************** // //*************************************************************************** CAssocQueryParser::~CAssocQueryParser() { delete m_pszQueryText; delete m_pszTargetObjPath; delete m_pszResultClass; delete m_pszAssocClass; delete m_pszRole; delete m_pszResultRole; delete m_pszRequiredQual; delete m_pszRequiredAssocQual; if (m_pPath) m_PathParser.Free(m_pPath); } //*************************************************************************** // //*************************************************************************** HRESULT CAssocQueryParser::Parse(LPWSTR pszQuery) { if (pszQuery == NULL) return WBEM_E_INVALID_QUERY; // Clone the query text for debugging. // =================================== DUP_STRING_NEW(m_pszQueryText, pszQuery); if (m_pszQueryText == NULL) return WBEM_E_OUT_OF_MEMORY; // Parse it. // ========= BOOL bRes = ParseAssocQuery( m_pszQueryText, &m_pszTargetObjPath, &m_pszResultClass, &m_pszAssocClass, &m_pszRole, &m_pszResultRole, &m_pszRequiredQual, &m_pszRequiredAssocQual, &m_dwType ); if (bRes == FALSE) return WBEM_E_INVALID_QUERY; // Parse the object path. // ====================== if (m_pszTargetObjPath) { int nStatus = m_PathParser.Parse(m_pszTargetObjPath, &m_pPath); if (nStatus != 0) return WBEM_E_INVALID_OBJECT_PATH; } return WBEM_S_NO_ERROR; }