2025-04-27 07:49:33 -04:00

457 lines
13 KiB
C++

// **************************************************************************
//
// Copyright (c) 2001 Microsoft Corporation, All Rights Reserved
//
// File: QueryParser.cpp
//
// Description:
// WMI Query Parser Sample.
// This sample shows how to use the Query Parser. It takes a query as a command
// line argument and passes it off to the parser to be parsed and then uses various
// functions to get pieces of the path.
//
// **************************************************************************
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <stdio.h>
#include <wmiutils.h>
LPWSTR g_pQuery = 0;
//***************************************************************************
//
// DumpFeatureMasks
//
// Purpose: Outputs the mask in readable format
//
//***************************************************************************
void DumpFeatureMasks(ULONG mask1, ULONG mask2)
{
printf("Query Features:\n");
if (mask1 & WMIQ_RPNF_WHERE_CLAUSE_PRESENT)
printf("WMIQ_RPNF_WHERE_CLAUSE_PRESENT\n");
if (mask1 & WMIQ_RPNF_QUERY_IS_CONJUNCTIVE)
printf("WMIQ_RPNF_QUERY_IS_CONJUNCTIVE\n");
if (mask1 & WMIQ_RPNF_QUERY_IS_DISJUNCTIVE)
printf("WMIQ_RPNF_QUERY_IS_DISJUNCTIVE\n");
if (mask1 & WMIQ_RPNF_PROJECTION)
printf("WMIQ_RPNF_PROJECTION\n");
if (mask1 & WMIQ_RPNF_FEATURE_SELECT_STAR)
printf("WMIQ_RPNF_FEATURE_SELECT_STAR\n");
if (mask1 & WMIQ_RPNF_EQUALITY_TESTS_ONLY)
printf("WMIQ_RPNF_EQUALITY_TESTS_ONLY\n");
if (mask1 & WMIQ_RPNF_COUNT_STAR)
printf("WMIQ_RPNF_COUNT_STAR\n");
if (mask1 & WMIQ_RPNF_QUALIFIED_NAMES_IN_SELECT)
printf("WMIQ_RPNF_QUALIFIED_NAMES_IN_SELECT\n");
if (mask1 & WMIQ_RPNF_QUALIFIED_NAMES_IN_WHERE)
printf("WMIQ_RPNF_QUALIFIED_NAMES_IN_WHERE\n");
if (mask1 & WMIQ_RPNF_PROP_TO_PROP_TESTS)
printf("WMIQ_RPNF_PROP_TO_PROP_TESTS\n");
if (mask1 & WMIQ_RPNF_ORDER_BY)
printf("WMIQ_RPNF_ORDER_BY\n");
if (mask1 & WMIQ_RPNF_ISA_USED)
printf("WMIQ_RPNF_ISA_USED\n");
if (mask1 & WMIQ_RPNF_ISNOTA_USED)
printf("WMIQ_RPNF_ISNOTA_USED\n");
if (mask1 & WMIQ_RPNF_GROUP_BY_HAVING)
printf("WMIQ_RPNF_GROUP_BY_HAVING\n");
if (mask1 & WMIQ_RPNF_WITHIN_INTERVAL)
printf("WMIQ_RPNF_WITHIN_INTERVAL\n");
if (mask1 & WMIQ_RPNF_WITHIN_AGGREGATE)
printf("WMIQ_RPNF_WITHIN_AGGREGATE\n");
if (mask1 & WMIQ_RPNF_SYSPROP_CLASS)
printf("WMIQ_RPNF_SYSPROP_CLASS\n");
if (mask1 & WMIQ_RPNF_REFERENCE_TESTS)
printf("WMIQ_RPNF_REFERENCE_TESTS\n");
if (mask1 & WMIQ_RPNF_DATETIME_TESTS)
printf("WMIQ_RPNF_DATETIME_TESTS\n");
if (mask1 & WMIQ_RPNF_ARRAY_ACCESS)
printf("WMIQ_RPNF_ARRAY_ACCESS\n");
if (mask1 & WMIQ_RPNF_QUALIFIER_FILTER)
printf("WMIQ_RPNF_QUALIFIER_FILTER\n");
if (mask1 & WMIQ_RPNF_SELECTED_FROM_PATH)
printf("WMIQ_RPNF_SELECTED_FROM_PATH\n");
}
//***************************************************************************
//
// DumpSelectList
//
// Purpose: Lists the selected columns
//
//***************************************************************************
void DumpSelectList(ULONG uCount, SWbemQueryQualifiedName **pNames)
{
unsigned u;
printf("----BEGIN SELECT CLAUSE---\n");
printf("Selected target columns/props = ");
for (u = 0; u < uCount; u++)
{
SWbemQueryQualifiedName *p = pNames[u];
// Print out current name.
// Note that we support qualified names,
// like p1.a, p2.b, etc.
// For simple cases, the m_uNameListSize is 1.
// ===========================================
for (unsigned u2 = 0; u2 < p->m_uNameListSize; u2++)
{
if (u2 > 0)
printf(".");
printf("%S", p->m_ppszNameList[u2]);
}
printf(", ");
}
printf("\n");
printf("---END SELECT CLAUSE-----\n");
}
//***************************************************************************
//
// DumpSubexpression
//
// Purpose: dumps out one of the subexpressions that make up the where clause
//
//***************************************************************************
void DumpSubexpression(SWbemRpnQueryToken *pTemp)
{
printf("---SUBEXPRESSION TOKEN---\n");
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_LEFT_PROPERTY_NAME)
{
printf(" WMIQ_RPN_LEFT_PROPERTY_NAME\n");
}
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_RIGHT_PROPERTY_NAME)
{
printf(" WMIQ_RPN_RIGHT_PROPERTY_NAME\n");
}
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_CONST2)
{
printf(" WMIQ_RPN_CONST2\n");
}
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_CONST)
{
printf(" WMIQ_RPN_CONST\n");
}
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_RELOP)
{
printf(" WMIQ_RPN_RELOP\n");
}
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_LEFT_FUNCTION)
{
printf(" WMIQ_RPN_LEFT_FUNCTION\n");
}
if (pTemp->m_uSubexpressionShape & WMIQ_RPN_RIGHT_FUNCTION)
{
printf(" WMIQ_RPN_RIGHT_FUNCTION\n");
}
switch (pTemp->m_uOperator)
{
case WMIQ_RPN_OP_UNDEFINED: printf(" Operator (Invalid) WMIQ_RPN_OP_UNDEFINED\n"); break;
case WMIQ_RPN_OP_EQ : printf(" Operator = (WMIQ_RPN_OP_EQ)\n"); break;
case WMIQ_RPN_OP_NE : printf(" Operator != (WMIQ_RPN_OP_NE)\n"); break;
case WMIQ_RPN_OP_GE : printf(" Operator >= (WMIQ_RPN_OP_GE)\n"); break;
case WMIQ_RPN_OP_LE : printf(" Operator <= (WMIQ_RPN_OP_LE)\n"); break;
case WMIQ_RPN_OP_LT : printf(" Operator < (WMIQ_RPN_OP_LT)\n"); break;
case WMIQ_RPN_OP_GT : printf(" Operator > (WMIQ_RPN_OP_GT)\n"); break;
case WMIQ_RPN_OP_LIKE : printf(" Operator LIKE (WMIQ_RPN_OP_LIKE)\n"); break;
case WMIQ_RPN_OP_ISA : printf(" Operator ISA (WMIQ_RPN_OP_ISA)\n"); break;
case WMIQ_RPN_OP_ISNOTA : printf(" Operator ISNOTA (WMIQ_RPN_OP_ISNOTA)\n"); break;
default:
printf(" Operator <INVALID -- Internal Error>\n");
break;
}
// Dump identifiers (propety names)
if (pTemp->m_pRightIdent)
{
printf(" Right side identifier = ");
SWbemQueryQualifiedName *p = pTemp->m_pRightIdent;
for (unsigned u = 0; u < p->m_uNameListSize; u++)
{
if (u > 0)
printf(".");
printf("%S", p->m_ppszNameList[u]);
}
printf("\n");
}
if (pTemp->m_pLeftIdent)
{
printf(" Left side identifier = ");
SWbemQueryQualifiedName *p = pTemp->m_pLeftIdent;
for (unsigned u = 0; u < p->m_uNameListSize; u++)
{
if (u > 0)
printf(".");
printf("%S", p->m_ppszNameList[u]);
}
printf("\n");
}
printf(" Apparent Type of Query Constant is ");
switch(pTemp->m_uConstApparentType)
{
case VT_NULL:
printf("VT_NULL");
break;
case VT_I4:
printf("VT_I4, Value = %d\n", pTemp->m_Const.m_lLongVal);
break;
case VT_UI4:
printf("VT_UI4, Value = %u\n", pTemp->m_Const.m_uLongVal);
break;
case VT_BOOL:
printf("VT_BOOL, Value = %d\n", pTemp->m_Const.m_bBoolVal);
break;
case VT_R8:
printf("VT_R8, Value = %f\n", pTemp->m_Const.m_dblVal);
break;
case VT_LPWSTR:
printf("VT_LPWSTR, Value = %S\n", pTemp->m_Const.m_pszStrVal);
break;
}
printf(" Function name applied to Left Side = %S\n", pTemp->m_pszLeftFunc);
printf(" Function name applied to Right Side = %S\n", pTemp->m_pszRightFunc);
printf("----END SUBEXPRESSION TOKEN---\n");
}
//***************************************************************************
//
// DumpWhereClause
//
// Purpose: Dumps out the where clause
//
//***************************************************************************
void DumpWhereClause(ULONG uCount, SWbemRpnQueryToken **pWhere)
{
printf("---BEGIN WHERE CLAUSE---\n");
unsigned u;
for (u = 0; u < uCount; u++)
{
SWbemRpnQueryToken *pTemp = pWhere[u];
switch(pTemp->m_uTokenType)
{
case WMIQ_RPN_TOKEN_EXPRESSION:
DumpSubexpression(pTemp);
break;
case WMIQ_RPN_TOKEN_AND:
printf(" Operator: AND\n");
break;
case WMIQ_RPN_TOKEN_OR:
printf(" Operator: OR\n");
break;
case WMIQ_RPN_TOKEN_NOT:
printf(" Operator: NOT\n");
default:
printf(" Operator: INVALID\n");
}
}
printf("---END WHERE CLAUSE---\n");
}
//***************************************************************************
//
// DumpFromClause
//
// Purpose: Dumps out the from clause
//
//***************************************************************************
void DumpFromClause(SWbemRpnEncodedQuery *pQuery)
{
printf("---FROM clause---\n");
if (pQuery->m_uFromTargetType & WMIQ_RPN_FROM_PATH)
{
printf(" Selected from container/scope [%S]\n", pQuery->m_pszOptionalFromPath);
}
if (pQuery->m_uFromTargetType & WMIQ_RPN_FROM_UNARY)
{
printf(" Single class select = %S\n", pQuery->m_ppszFromList[0]);
}
else if (pQuery->m_uFromTargetType & WMIQ_RPN_FROM_CLASS_LIST)
{
for (unsigned u = 0; u < pQuery->m_uFromListSize; u++)
{
printf(" Selected class = %S\n", pQuery->m_ppszFromList[u]);
}
}
else
{
printf(" No target classes selected; select ALL\n");
}
printf("---END FROM clause\n");
}
//***************************************************************************
//
// DumpRpn
//
// Purpose: Mainly calls the other routines which dump out the specific parts
//
//***************************************************************************
void DumpRpn(SWbemRpnEncodedQuery *pRpn)
{
printf("------------RPN Encoded Query-----------------\n");
printf("RPN Version = %d\n", pRpn->m_uVersion);
printf("RPN Token Type = %d\n", pRpn->m_uTokenType);
printf("Total detected features = %d Feature Set = { ", pRpn->m_uDetectedArraySize);
for (unsigned i = 0; i < pRpn->m_uDetectedArraySize; i++)
printf("%d ", pRpn->m_puDetectedFeatures[i]);
printf("}\n\n");
DumpFeatureMasks(pRpn->m_uParsedFeatureMask1, pRpn->m_uParsedFeatureMask2);
DumpSelectList(pRpn->m_uSelectListSize, pRpn->m_ppSelectList);
DumpFromClause(pRpn);
DumpWhereClause(pRpn->m_uWhereClauseSize, pRpn->m_ppRpnWhereClause);
}
//***************************************************************************
//
// TestQuery
//
// Purpose: Calls the parser to parse the query, and if all is well, calls
// the other routines to dump out the results.
//
//***************************************************************************
void TestQuery(IWbemQuery *pQuery)
{
HRESULT hRes;
ULONG uFeatures[] =
{
WMIQ_LF1_BASIC_SELECT,
WMIQ_LF2_CLASS_NAME_IN_QUERY
};
hRes = pQuery->SetLanguageFeatures(0, sizeof(uFeatures)/sizeof(ULONG), uFeatures);
hRes = pQuery->Parse(L"SQL", g_pQuery, 0);
if (FAILED(hRes))
{
printf("Parse failed with error 0x%X\n", hRes);
return;
}
SWbemRpnEncodedQuery *pRpn = 0;
hRes = pQuery->GetAnalysis(
WMIQ_ANALYSIS_RPN_SEQUENCE,
0,
(LPVOID *) &pRpn
);
if (SUCCEEDED(hRes))
{
printf("\n\nGot RPN Output\n");
DumpRpn(pRpn);
pQuery->FreeMemory(pRpn);
}
}
//***************************************************************************
//
// main
//
// Purpose: Entry point for the application.
//
//***************************************************************************
void main(int argc, char *argv[])
{
if (argc < 2)
{
printf("\nusage: QueryParser \"query\"");
printf("\nexample; c:>QueryParser \"select RowA, RowB from tableName where propz=3\"");
return;
}
printf("Query = %s\n", argv[1]);
wchar_t buf[512];
swprintf(buf, L"%S", argv[1]);
g_pQuery = buf;
// Standard COM initialization stuff.
// ===================================
CoInitializeEx(0, COINIT_MULTITHREADED);
// Get the QueryParser object call the test code
// =============================================
IWbemQuery *pQuery = 0;
DWORD dwRes = CoCreateInstance(CLSID_WbemQuery, 0, CLSCTX_INPROC_SERVER,
IID_IWbemQuery, (LPVOID *) &pQuery);
if (dwRes != S_OK)
printf("Failed to create Query object.\n");
else
{
printf("Got a query parser object\n");
TestQuery(pQuery);
pQuery->Release();
}
CoUninitialize();
}