windows-nt/Source/XPSP1/NT/admin/wmi/wbem/common/wmiutils/assocqp.cpp
2020-09-26 16:20:57 +08:00

467 lines
13 KiB
C++

/*++
// 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 <stdio.h>
#include <stdlib.h>
#include <wmiutils.h>
#include <genlex.h>
#include <assocqp.h>
#include <wbemcli.h>
#include <helpers.h>
#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;
}