|
|
/*++
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 <stdio.h>
#include <stdlib.h>
#include <wbemcore.h>
// ==========================================================================
// 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; }
|