2726 lines
88 KiB
C++
2726 lines
88 KiB
C++
// **************************************************************************
|
|
|
|
//Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// File: wbemdump.cpp
|
|
//
|
|
// Description:
|
|
// dumps the contents of the cimom repository
|
|
// see wbemdump /? for command line switches
|
|
//
|
|
// History:
|
|
//
|
|
// **************************************************************************
|
|
|
|
#pragma warning(disable:4201) // nonstandard extension nameless struct (used in windows.h)
|
|
#pragma warning(disable:4514) // unreferenced inline function has been removed (used in windows.h)
|
|
#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
|
|
#pragma warning(disable:4100) // unreferenced formal parameter warning
|
|
#pragma warning(disable:4701) // local variable may be used without having been initialized
|
|
#pragma warning(disable:4710) // function not inlined
|
|
|
|
#define TIMEOUT 150
|
|
#define UNICODE_SIGNATURE "\xff\xfe"
|
|
#define _WIN32_DCOM
|
|
#define WIN32_LEAN_AND_MEAN 1
|
|
#define UNREFERENCED(x)
|
|
|
|
//#include <windows.h> not needed since it is re-included in wbemidl.h
|
|
#include <wbemidl.h> // wbem interface declarations
|
|
#include <stdio.h> // fprintf
|
|
#include <locale.h>
|
|
#include <sys/timeb.h>
|
|
#include <wbemsec.h>
|
|
#include <utillib.h>
|
|
#include "wbemdump.h"
|
|
|
|
// Function declarations
|
|
void DoIndent();
|
|
BOOL CtrlHandler(DWORD fdwCtrlType);
|
|
HRESULT ShowInstancesSync(IWbemServices *pIWbemServices, IEnumWbemClassObject *IEnumWbemClassObject, DWORD &dwCount, LPCWSTR pwszClassName);
|
|
void EnumClasses(IWbemServices *pIWbemServices, LPCWSTR pwcsClass);
|
|
void EnumClassesSync(IWbemServices *pIWbemServices, LPCWSTR pwcsClass);
|
|
void EnumInstances(IWbemServices *pIWbemServices, LPCWSTR pwcsClassName );
|
|
void EnumNamespaces(IWbemServices *pIWbemServices, LPCWSTR pwcsClassName);
|
|
WCHAR *EnumProperties(IWbemClassObject *pIWbemClassObject);
|
|
void Init(IWbemServices **ppIWbemServices, LPCWSTR pNamespace);
|
|
IWbemClassObject *GetObj(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject);
|
|
DWORD ProcessCommandLine(int argc, wchar_t *argv[]);
|
|
void ExecuteQuery(IWbemServices *pIWbemServices, LPCWSTR pwcsQueryLanguage, LPCWSTR pwcsQuery);
|
|
void PrintMof(IWbemClassObject *pIWbemClassObject);
|
|
void ShowClass(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject);
|
|
BOOL CheckQualifiers(IWbemClassObject *pIWbemClassObject);
|
|
void ShowInstance(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject);
|
|
void CheckAssocEndPoints(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject);
|
|
int __cdecl BstrCmp(const void *arg1,const void *arg2);
|
|
WCHAR *EscapeChars(LPCWSTR szInBuf);
|
|
WCHAR *MyValueToString(VARIANT *pv);
|
|
void ShowInstanceHeader(LPCWSTR pwcsClassName);
|
|
void ResetGlobalFlags();
|
|
bool ParseCommandLine(int *numargs, wchar_t **p);
|
|
static void __cdecl wparse_cmdline (
|
|
WCHAR *cmdstart,
|
|
WCHAR **argv,
|
|
WCHAR *args,
|
|
int *numargs,
|
|
int *numchars
|
|
);
|
|
|
|
// Global flags
|
|
BOOL g_bShowSystem = FALSE; // Show system objects
|
|
BOOL g_bShowSystem1 = FALSE; // Show system objects except __SERVER or __PATH
|
|
BOOL g_bShowInstance = FALSE; // Show instance from ObjectPath
|
|
BOOL g_bShowProperties = TRUE; // Show properties
|
|
BOOL g_bRecurseClass = FALSE; // Recurse down class tree
|
|
BOOL g_bRecurseNS = FALSE; // Recurse down ns's
|
|
BOOL g_bCheckGet = FALSE; // Check the GetObject function
|
|
BOOL g_bCheckAssoc = FALSE; // Check Association endpoints
|
|
BOOL g_bDoQuery = FALSE; // Run a query instead of doing an enum
|
|
BOOL g_bClassMofs = FALSE; // Show mofs for classes
|
|
BOOL g_bInstanceMofs = FALSE; // Show mofs for instances
|
|
BOOL g_bMofTemplate = FALSE; // Show instance mof templates
|
|
BOOL g_bUnicodeCmdFile = FALSE; // Whether the cmd file is unicode
|
|
BOOL g_bTime1 = FALSE; // Show timings for /Q queries
|
|
BOOL g_bTime2 = FALSE; // Alternate show timings for /Q queries
|
|
BOOL g_bWarningContinue = FALSE; // Show warning and continue
|
|
BOOL g_bWarning = FALSE; // Show warning and ask
|
|
BOOL g_bASync = FALSE; // Use Async functions for instances
|
|
|
|
volatile bool g_bExit = false; // Control C handling
|
|
long g_lSFlags = 0; // Security flags for ConnectServer
|
|
long g_lImpFlag = RPC_C_IMP_LEVEL_IMPERSONATE; // Impersonation level (-1 means use default)
|
|
long g_lAuthFlag = -1; // Impersonation level (-1 means use default)
|
|
long g_lEFlags = 0; // Flags for CreateXxxEnum
|
|
long g_lGFlags = 0; // Flags for GetObject
|
|
DWORD g_dwErrorFlags = 0; // Flags for error printing
|
|
|
|
//
|
|
FILE *g_fOut = NULL; // Handle for unicode file
|
|
FILE *g_fCmdFile = NULL; // Handle for command file
|
|
|
|
LPCWSTR g_pwcsNewLine = L"\n"; // Used to delimit lines
|
|
LPCWSTR g_pwcsNamespace = NULL; // NameSpace to start from
|
|
LPCWSTR g_pwcsObjectPath = NULL; // ObjectPath to show
|
|
LPCWSTR g_pwcsQuery = NULL; // Query (for /q commands)
|
|
LPWSTR g_pwcsUserID = NULL; // Userid for ConnectServer
|
|
LPWSTR g_pwcsPassword = NULL; // PW for ConnectServer
|
|
LPWSTR g_pwcsAuthority = NULL; // Authority for ConnectServer
|
|
LPCWSTR g_pwcsLocale = NULL; // Locale for ConnectServer
|
|
BSTR g_bstrQualifierName = NULL; // Class Qualifier to filter on
|
|
BSTR g_bstrQualifierValue = NULL; // Class Qualifier value to filter on
|
|
DWORD g_dwLoopCnt = 1; // Loop count
|
|
DWORD g_dwIndent = 0; // Current indention level
|
|
|
|
IWbemContext *g_pContext; // Pointer to ClassContext object
|
|
|
|
//***************************************************************************
|
|
//
|
|
// wmain - used wmain since the command line parameters come in as wchar_t
|
|
//
|
|
//***************************************************************************
|
|
extern "C" int __cdecl wmain(int argc, wchar_t *argv[])
|
|
{
|
|
setlocale(LC_ALL, "");
|
|
|
|
// Init Com
|
|
int iRet = 0;
|
|
|
|
SCODE sc = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("OleInitialize Failed", sc, g_dwErrorFlags); //exits program
|
|
}
|
|
|
|
sc = CoInitializeSecurity(NULL, -1, NULL, NULL,
|
|
RPC_C_AUTHN_LEVEL_DEFAULT,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);
|
|
|
|
if (ProcessCommandLine(argc, argv) == S_OK)
|
|
{
|
|
// Catch control-c
|
|
SetConsoleCtrlHandler(
|
|
(PHANDLER_ROUTINE) CtrlHandler, // handler function
|
|
TRUE);
|
|
|
|
IWbemServicesPtr pIWbemServices;
|
|
Init(&pIWbemServices, g_pwcsNamespace); // Connect to wbem
|
|
|
|
try
|
|
{
|
|
if (g_fCmdFile)
|
|
{
|
|
wchar_t *largv;
|
|
int largc;
|
|
|
|
while (!feof(g_fCmdFile))
|
|
{
|
|
ResetGlobalFlags();
|
|
|
|
if (ParseCommandLine(&largc, &largv))
|
|
{
|
|
ProcessCommandLine(largc, (wchar_t **)largv);
|
|
if (g_bDoQuery)
|
|
{
|
|
ExecuteQuery(pIWbemServices, g_pwcsObjectPath, g_pwcsQuery);
|
|
}
|
|
else
|
|
{
|
|
EnumNamespaces(pIWbemServices, g_pwcsObjectPath); // Enumerate Namespaces
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (g_bDoQuery)
|
|
{
|
|
ExecuteQuery(pIWbemServices, g_pwcsObjectPath, g_pwcsQuery);
|
|
}
|
|
else
|
|
{
|
|
EnumNamespaces(pIWbemServices, g_pwcsObjectPath); // Enumerate Namespaces
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
iRet = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iRet = 1;
|
|
}
|
|
|
|
// Wrapup and exit
|
|
if (g_fOut)
|
|
{
|
|
fclose(g_fOut);
|
|
}
|
|
|
|
if (g_fCmdFile)
|
|
{
|
|
fclose(g_fCmdFile);
|
|
}
|
|
|
|
if (g_bstrQualifierName != NULL)
|
|
{
|
|
SysFreeString(g_bstrQualifierName);
|
|
}
|
|
|
|
if (g_bstrQualifierValue != NULL)
|
|
{
|
|
SysFreeString(g_bstrQualifierValue);
|
|
}
|
|
|
|
if (g_pContext != NULL)
|
|
{
|
|
g_pContext->Release();
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return iRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: Init
|
|
//
|
|
// Purpose: 1 - Create an instance of the WbemLocator interface
|
|
// 2 - Use the pointer returned in step two to connect to
|
|
// the server using the specified namespace.
|
|
//***************************************************************************
|
|
void Init(IWbemServices **ppIWbemServices, LPCWSTR pNamespace)
|
|
{
|
|
SCODE sc;
|
|
|
|
// Use the IWbemLocatorEx? Or IWbemLocator?
|
|
IWbemLocatorPtr pIWbemLocator;
|
|
|
|
sc = CoCreateInstance(CLSID_WbemLocator,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(LPVOID *) &pIWbemLocator);
|
|
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("Failed to create IWbemLocator object", sc, g_dwErrorFlags); // exits program
|
|
}
|
|
|
|
sc = pIWbemLocator->ConnectServer(
|
|
|
|
bstr_t(pNamespace), // Namespace
|
|
bstr_t(g_pwcsUserID), // Userid
|
|
bstr_t(g_pwcsPassword), // PW
|
|
bstr_t(g_pwcsLocale), // Locale
|
|
g_lSFlags, // flags
|
|
g_pwcsAuthority, // Authority
|
|
g_pContext, // Context
|
|
ppIWbemServices
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Connect failed", sc, g_dwErrorFlags); //exits program
|
|
}
|
|
|
|
DWORD dwAuthLevel, dwImpLevel;
|
|
sc = GetAuthImp(*ppIWbemServices, &dwAuthLevel, &dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("GetAuthImp Failed on ConnectServer", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
if (g_lImpFlag != -1)
|
|
{
|
|
dwImpLevel = g_lImpFlag;
|
|
}
|
|
|
|
if (g_lAuthFlag != -1)
|
|
{
|
|
dwAuthLevel = g_lAuthFlag;
|
|
}
|
|
|
|
sc = SetInterfaceSecurity(*ppIWbemServices, g_pwcsAuthority, g_pwcsUserID, g_pwcsPassword, dwAuthLevel, dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("SetInterfaceSecurity Failed on ConnectServer", sc, g_dwErrorFlags);
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Function: EnumClasses
|
|
//
|
|
// Purpose: Using either the sync or async CreateClassEnum call, walk
|
|
// the classes.
|
|
//***************************************************************************
|
|
void EnumClasses(IWbemServices *pIWbemServices, LPCWSTR pwcsClass)
|
|
{
|
|
if (!g_bASync)
|
|
{
|
|
EnumClassesSync(pIWbemServices, pwcsClass);
|
|
}
|
|
else
|
|
{
|
|
ClassQuerySinkPtr pMySink(new ClassQuerySink(pIWbemServices), false);
|
|
|
|
SCODE sc = pIWbemServices->CreateClassEnumAsync(
|
|
|
|
bstr_t(pwcsClass),
|
|
WBEM_FLAG_SHALLOW | g_lEFlags,
|
|
g_pContext,
|
|
pMySink
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not create Class enumerator", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
do
|
|
{
|
|
sc = WaitForSingleObject(pMySink->GetEvent(), TIMEOUT);
|
|
if (g_bExit)
|
|
{
|
|
sc = pIWbemServices->CancelAsyncCall(pMySink);
|
|
throw 1;
|
|
}
|
|
} while (sc == WAIT_TIMEOUT);
|
|
|
|
sc = pMySink->GetResult();
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not enum instances", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: EnumClassesSync
|
|
// Purpose: Used by the Sync version of walking classes
|
|
//*****************************************************************************
|
|
void EnumClassesSync(IWbemServices *pIWbemServices, LPCWSTR pwcsClass)
|
|
{
|
|
IEnumWbemClassObjectPtr pIEnumWbemClassObject;
|
|
|
|
// Create an enumeration of all subclasses of pwcsClass
|
|
SCODE sc = pIWbemServices->CreateClassEnum(
|
|
|
|
bstr_t(pwcsClass),
|
|
WBEM_FLAG_SHALLOW | g_lEFlags,
|
|
g_pContext,
|
|
&pIEnumWbemClassObject
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not create Class enumerator", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
DWORD dwAuthLevel, dwImpLevel;
|
|
sc = GetAuthImp(pIWbemServices, &dwAuthLevel, &dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("GetAuthImp Failed on CreateClassEnum", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
if (g_lImpFlag != -1)
|
|
{
|
|
dwImpLevel = g_lImpFlag;
|
|
}
|
|
|
|
if (g_lAuthFlag != -1)
|
|
{
|
|
dwAuthLevel = g_lAuthFlag;
|
|
}
|
|
|
|
sc = SetInterfaceSecurity(pIEnumWbemClassObject, g_pwcsAuthority, g_pwcsUserID, g_pwcsPassword, dwAuthLevel, dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("SetInterfaceSecurity Failed on CreateClassEnum", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
ULONG uReturned;
|
|
IWbemClassObjectPtr pIWbemClassObject;
|
|
|
|
do
|
|
{
|
|
do
|
|
{
|
|
sc = pIEnumWbemClassObject->Next(
|
|
|
|
TIMEOUT,
|
|
1,
|
|
&pIWbemClassObject,
|
|
&uReturned
|
|
);
|
|
|
|
if (g_bExit)
|
|
{
|
|
throw 1;
|
|
}
|
|
} while (sc == WBEM_S_TIMEDOUT);
|
|
|
|
if (sc == S_OK)
|
|
{
|
|
ShowClass(pIWbemServices, pIWbemClassObject);
|
|
}
|
|
} while (sc == S_OK);
|
|
|
|
// Make sure we ended on a positive note
|
|
if (sc != S_FALSE)
|
|
{
|
|
PrintErrorAndExit("Could not get next class", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ShowClass
|
|
// Purpose: Calls the appropriate functions to show the passed in class
|
|
// Note: This routine calls EnumClasses, which leads to recursion
|
|
//*****************************************************************************
|
|
void ShowClass(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject)
|
|
{
|
|
variant_t varString;
|
|
|
|
// Get the __class property
|
|
SCODE sc = pIWbemClassObject->Get(CLASSPROP, 0L, &varString, NULL, NULL);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not get __Class property for class", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// we are showing system objs or this is not a system obj
|
|
if ((g_bShowSystem) || (wcsncmp(V_BSTR(&varString), SYSTEMPREFIX, 2) != 0))
|
|
{
|
|
if (CheckQualifiers(pIWbemClassObject))
|
|
{
|
|
// Either show the class mof, or show the instances
|
|
if (g_bClassMofs)
|
|
{
|
|
PrintMof(pIWbemClassObject);
|
|
if (g_bInstanceMofs)
|
|
{
|
|
EnumInstances(pIWbemServices, V_BSTR(&varString));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnumInstances(pIWbemServices, V_BSTR(&varString));
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we are supposed to recurse
|
|
if (g_bRecurseClass)
|
|
{
|
|
if ((!g_bMofTemplate) && (g_bstrQualifierName == NULL))
|
|
{
|
|
g_dwIndent++; // Increase indention level
|
|
}
|
|
|
|
EnumClasses(pIWbemServices, V_BSTR(&varString)); // Enumerate all classes under this class
|
|
if ((!g_bMofTemplate) && (g_bstrQualifierName == NULL))
|
|
{
|
|
g_dwIndent--; // Decrease indention level
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: EnumInstances
|
|
// Purpose: Enumerates all instances of the class passed in pwcsClassName
|
|
// and calls EnumProperties with each one.
|
|
// Note: Shows instances in one of four ways.
|
|
// 1) Show the instance mof
|
|
// 2) Show the instance values
|
|
// 3) Show the wbemdump command line needed to dump this instance
|
|
// 4) Show a template instance mof
|
|
//*****************************************************************************
|
|
void EnumInstances(IWbemServices *pIWbemServices, LPCWSTR pwcsClassName)
|
|
{
|
|
SCODE sc;
|
|
|
|
if (g_bMofTemplate)
|
|
{
|
|
IWbemClassObjectPtr pIWbemClassObject;
|
|
IWbemClassObjectPtr clObject;
|
|
|
|
// For a template, all I need is a blank instance, so get the object...
|
|
sc = pIWbemServices->GetObject(
|
|
|
|
bstr_t(pwcsClassName),
|
|
g_lGFlags,
|
|
g_pContext,
|
|
&pIWbemClassObject,
|
|
NULL
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Failed to GetObject in EnumInstances", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
// ... And spawn a blank one
|
|
sc = pIWbemClassObject->SpawnInstance(0L, &clObject);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Failed to SpawnInstance in EnumInstances", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
// Now, print the properties
|
|
ShowInstance(pIWbemServices, clObject);
|
|
|
|
}
|
|
else
|
|
{
|
|
// Put this here so we can see what class we were
|
|
// working on if we get stuck.
|
|
ShowInstanceHeader(pwcsClassName);
|
|
|
|
if (g_bShowProperties)
|
|
{
|
|
IEnumWbemClassObjectPtr IEnumWbemClassObject;
|
|
InstanceQuerySinkPtr pMySink;
|
|
|
|
struct _timeb start, finish;
|
|
LARGE_INTEGER freq, start2;
|
|
QueryPerformanceFrequency(&freq);
|
|
|
|
|
|
for (DWORD dwLoop = 0; dwLoop < g_dwLoopCnt; dwLoop++)
|
|
{
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&start);
|
|
}
|
|
else
|
|
{
|
|
memset(&start, 0, sizeof(start));
|
|
}
|
|
|
|
if (!g_bTime2)
|
|
{
|
|
start2.QuadPart = 0;
|
|
}
|
|
else
|
|
{
|
|
QueryPerformanceCounter(&start2);
|
|
}
|
|
|
|
if (!g_bASync)
|
|
{
|
|
// Create the enum
|
|
sc = pIWbemServices->CreateInstanceEnum(
|
|
|
|
bstr_t(pwcsClassName), // with this name
|
|
WBEM_FLAG_SHALLOW | g_lEFlags,
|
|
g_pContext,
|
|
&IEnumWbemClassObject // using this enumerator
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pMySink.Attach(new InstanceQuerySink(pIWbemServices, pwcsClassName));
|
|
sc = pIWbemServices->CreateInstanceEnumAsync(
|
|
|
|
bstr_t(pwcsClassName), // with this name
|
|
WBEM_FLAG_SHALLOW | g_lEFlags,
|
|
g_pContext,
|
|
pMySink
|
|
);
|
|
}
|
|
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&finish);
|
|
fprintf(stdout, "CreateInstanceEnum: %6.4f seconds.\n", difftime(finish, start));
|
|
}
|
|
if (g_bTime2)
|
|
{
|
|
LARGE_INTEGER finish2;
|
|
QueryPerformanceCounter(&finish2);
|
|
fprintf(stdout, "CreateInstanceEnum: %I64d (%6.4f)\n", finish2.QuadPart - start2.QuadPart, (double)(finish2.QuadPart - start2.QuadPart)/freq.QuadPart);
|
|
}
|
|
|
|
if (sc == WBEM_NO_ERROR)
|
|
{
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&start);
|
|
}
|
|
else
|
|
{
|
|
memset(&start, 0, sizeof(start));
|
|
}
|
|
|
|
if (!g_bTime2)
|
|
{
|
|
start2.QuadPart = 0;
|
|
}
|
|
else
|
|
{
|
|
QueryPerformanceCounter(&start2);
|
|
}
|
|
|
|
DWORD dwCount = 0;
|
|
|
|
if (!g_bASync)
|
|
{
|
|
sc = ShowInstancesSync(pIWbemServices, IEnumWbemClassObject, dwCount, pwcsClassName);
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
sc = WaitForSingleObject(pMySink->GetEvent(), TIMEOUT);
|
|
if (g_bExit)
|
|
{
|
|
sc = pIWbemServices->CancelAsyncCall(pMySink);
|
|
throw 1;
|
|
}
|
|
} while (sc == WAIT_TIMEOUT);
|
|
|
|
dwCount = pMySink->GetCount();
|
|
sc = pMySink->GetResult();
|
|
if (sc == WBEM_S_NO_ERROR)
|
|
{
|
|
sc = S_FALSE;
|
|
}
|
|
}
|
|
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&finish);
|
|
fprintf(stdout, "ShowInstances: %6.4f seconds, %d instances.\n", difftime(finish, start), dwCount);
|
|
}
|
|
|
|
if (g_bTime2)
|
|
{
|
|
LARGE_INTEGER finish2;
|
|
QueryPerformanceCounter(&finish2);
|
|
fprintf(stdout, "ShowInstances: %I64d (%6.4f), %d instances.\n", finish2.QuadPart - start2.QuadPart, (double)(finish2.QuadPart - start2.QuadPart)/freq.QuadPart, dwCount);
|
|
}
|
|
|
|
// Make sure we ended on a positive note
|
|
if (sc != S_FALSE)
|
|
{
|
|
PrintErrorAndExit("Could not get next instance", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Couldn't create instance enum", sc, g_dwErrorFlags);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: EnumProperties
|
|
// Purpose: Shows all property names of specified class
|
|
//*****************************************************************************
|
|
WCHAR *EnumProperties(IWbemClassObject *pIWbemClassObject)
|
|
{
|
|
SCODE sc;
|
|
SAFEARRAY *psaNames = NULL;
|
|
long lLower, lUpper, lCount;
|
|
IWbemQualifierSetPtr pQualSet;
|
|
MyString clMyBuff;
|
|
|
|
// Get the property names
|
|
if (g_bShowSystem)
|
|
{
|
|
sc = pIWbemClassObject->GetNames(NULL, WBEM_FLAG_ALWAYS, NULL, &psaNames);
|
|
}
|
|
else
|
|
{
|
|
sc = pIWbemClassObject->GetNames(NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames);
|
|
}
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Couldn't GetNames", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// Get the upper and lower bounds of the Names array
|
|
sc = SafeArrayGetLBound(psaNames, 1, &lLower);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Couldn't get safe array lbound", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
sc = SafeArrayGetUBound(psaNames, 1, &lUpper);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Couldn't get safe array ubound", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
// Sort the array
|
|
qsort(psaNames->pvData, lUpper - lLower + 1, sizeof(BSTR), BstrCmp);
|
|
|
|
// For an instance template, print the 'INSTANCE OF <CLASS>' header
|
|
if (g_bMofTemplate)
|
|
{
|
|
variant_t varString;
|
|
|
|
sc = pIWbemClassObject->Get(CLASSPROP, 0L, &varString, NULL, NULL);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Couldn't get class property in enumproperties", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
for (DWORD x=0; x < g_dwIndent; x++)
|
|
{
|
|
clMyBuff += L"\t";
|
|
}
|
|
|
|
clMyBuff += L"instance of ";
|
|
clMyBuff += V_BSTR(&varString);
|
|
clMyBuff += L" {";
|
|
clMyBuff += g_pwcsNewLine;
|
|
g_dwIndent++;
|
|
}
|
|
|
|
BSTR PropName = NULL;
|
|
variant_t varString, varVal;
|
|
CIMTYPE dwType;
|
|
WCHAR *pBuf = NULL;
|
|
bool bKey = false;
|
|
BSTR bstrCimType = NULL;
|
|
IWbemClassObjectPtr clObject1, clObject2;
|
|
|
|
// For all properties...
|
|
for (lCount = lLower; lCount <= lUpper; lCount++)
|
|
{
|
|
// get the property name for this element
|
|
sc = SafeArrayGetElement(psaNames, &lCount, &PropName);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Couldn't get safe array element", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
// Only print the property if
|
|
// we are showing all properties except __SERVER and __PATH and this is not them
|
|
if (!((g_bShowSystem1) && ((_wcsicmp(PropName, SERVERPROP) == 0) || _wcsicmp(PropName, PATHPROP) == 0)))
|
|
{
|
|
for (DWORD x=0; x < g_dwIndent; x++)
|
|
{
|
|
clMyBuff += L"\t";
|
|
}
|
|
|
|
clMyBuff += PropName;
|
|
sc = pIWbemClassObject->Get(PropName, 0L, &varString, &dwType, NULL); // Get the value for the property
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Couldn't get Property Value", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
// Get pointer to property qualifiers
|
|
sc = pIWbemClassObject->GetPropertyQualifierSet(PropName, &pQualSet);
|
|
|
|
// Get the QualifierSet
|
|
if (sc == WBEM_NO_ERROR)
|
|
{
|
|
// Get CIMTYPE attribute (if any)
|
|
sc = pQualSet->Get(CIMTYPEQUAL, 0L, &varVal, NULL);
|
|
if (sc == WBEM_NO_ERROR)
|
|
{
|
|
bstrCimType = SysAllocString(V_BSTR(&varVal));
|
|
varVal.Clear();
|
|
}
|
|
else if (sc != WBEM_E_NOT_FOUND)
|
|
{ // some other error
|
|
PrintErrorAndExit("Could not get CIMTYPE qualifier", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// Determine if this is a key property
|
|
sc = pQualSet->Get(KEYQUAL, 0L, &varVal, NULL);
|
|
if (sc == WBEM_NO_ERROR)
|
|
{
|
|
bKey = (bool)varVal.boolVal;
|
|
}
|
|
else if (sc == WBEM_E_NOT_FOUND)
|
|
{ // not a key qualifier
|
|
bKey = false;
|
|
}
|
|
else
|
|
{ // some other error
|
|
PrintErrorAndExit("Could not get key qualifier", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// this mess is due to the fact that system properties don't have qualifiers
|
|
}
|
|
else if (sc != WBEM_E_SYSTEM_PROPERTY)
|
|
{
|
|
PrintErrorAndExit("Could not GetPropertyQualifierSet", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
else
|
|
{
|
|
bstrCimType = SysAllocString(L"");
|
|
}
|
|
|
|
// print variable type and key indicatory for property value
|
|
if (!g_bMofTemplate)
|
|
{
|
|
clMyBuff += L" (";
|
|
clMyBuff += TypeToString(dwType);
|
|
|
|
if (bstrCimType != NULL)
|
|
{
|
|
clMyBuff += L"/";
|
|
clMyBuff += bstrCimType;
|
|
}
|
|
|
|
// Mark the key fields
|
|
if (bKey)
|
|
{
|
|
clMyBuff += L")* ";
|
|
}
|
|
else
|
|
{
|
|
clMyBuff += L") ";
|
|
}
|
|
}
|
|
|
|
// If we are showing a mof template, and this property is an embedded object and
|
|
// there is no default object, we will need to create a blank one.
|
|
if ((g_bMofTemplate) &&
|
|
(V_VT(&varString) == VT_NULL) &&
|
|
((dwType == CIM_OBJECT) || (dwType == (CIM_OBJECT | CIM_FLAG_ARRAY))))
|
|
{
|
|
IWbemServicesPtr pIWbemServices;
|
|
|
|
Init(&pIWbemServices, g_pwcsNamespace); // Connect to wbem
|
|
|
|
// Get the object
|
|
sc = pIWbemServices->GetObject(
|
|
|
|
bstr_t(&bstrCimType[7]),
|
|
g_lGFlags,
|
|
g_pContext,
|
|
&clObject1,
|
|
NULL
|
|
);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Failed to GetObject in EnumProperties", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
// and spawn an instance of it
|
|
sc = clObject1->SpawnInstance(0L, &clObject2);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Failed to SpawnInstance in EnumProperties", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
// If this is an array, create a safearray object
|
|
if (dwType & CIM_FLAG_ARRAY)
|
|
{
|
|
// Create the array
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
rgsabound[0].cElements = 1;
|
|
rgsabound[0].lLbound = 0;
|
|
|
|
V_ARRAY(&varString) = SafeArrayCreate((VARTYPE)(dwType & (~CIM_FLAG_ARRAY)), 1, rgsabound);
|
|
|
|
// Put the object into the safearray
|
|
void *vptr;
|
|
|
|
SafeArrayAccessData(V_ARRAY(&varString), &vptr);
|
|
clObject2->QueryInterface(IID_IUnknown, (void **)vptr);
|
|
SafeArrayUnaccessData(V_ARRAY(&varString));
|
|
|
|
}
|
|
else
|
|
{
|
|
clObject2->QueryInterface(IID_IUnknown, (void **)&V_UNKNOWN(&varString));
|
|
}
|
|
|
|
// Reset the type from null to dwType
|
|
V_VT(&varString) = (VARTYPE)dwType;
|
|
}
|
|
|
|
// Print the value
|
|
clMyBuff += L" = ";
|
|
if ((V_VT(&varString) == VT_UNKNOWN) || (V_VT(&varString) == (VT_UNKNOWN | VT_ARRAY)))
|
|
{
|
|
clMyBuff += g_pwcsNewLine;
|
|
clMyBuff += ValueToString(dwType, &varString, &pBuf, MyValueToString);
|
|
}
|
|
else
|
|
{
|
|
// For mof templates, if this is an array, add the braces
|
|
if ((g_bMofTemplate) && ((V_VT(&varString) & VT_ARRAY) != 0))
|
|
{
|
|
clMyBuff += L"{";
|
|
}
|
|
clMyBuff += ValueToString(dwType, &varString, &pBuf, MyValueToString);
|
|
if ((g_bMofTemplate) && (V_VT(&varString) & VT_ARRAY) != 0)
|
|
{
|
|
clMyBuff += L"}";
|
|
}
|
|
// For mof templates, add the cimtype et al as a comment
|
|
if (g_bMofTemplate)
|
|
{
|
|
clMyBuff += L"\t//\t";
|
|
clMyBuff += TypeToString(dwType);
|
|
clMyBuff += L"\t";
|
|
clMyBuff += bstrCimType;
|
|
clMyBuff += L"\t";
|
|
BSTR bstrOrigin = NULL;
|
|
pIWbemClassObject->GetPropertyOrigin(PropName, &bstrOrigin);
|
|
clMyBuff += bstrOrigin;
|
|
if (bKey)
|
|
{
|
|
clMyBuff += L"\t*";
|
|
}
|
|
SysFreeString(bstrOrigin);
|
|
}
|
|
clMyBuff += g_pwcsNewLine;
|
|
}
|
|
|
|
// Release and reset for next pass
|
|
if (bstrCimType != NULL)
|
|
{
|
|
SysFreeString(bstrCimType);
|
|
bstrCimType = NULL;
|
|
}
|
|
bKey = false;
|
|
|
|
free(pBuf);
|
|
|
|
varString.Clear();
|
|
varVal.Clear();
|
|
}
|
|
SysFreeString(PropName);
|
|
}
|
|
|
|
SafeArrayDestroy(psaNames);
|
|
|
|
if (g_bMofTemplate)
|
|
{
|
|
g_dwIndent--;
|
|
for (DWORD x=0; x < g_dwIndent; x++)
|
|
{
|
|
clMyBuff += L"\t";
|
|
}
|
|
|
|
clMyBuff += L"};";
|
|
clMyBuff += g_pwcsNewLine;
|
|
}
|
|
|
|
return clMyBuff.GetCloneString();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: EnumNamespaces
|
|
// Purpose: Enumerate NameSpaces
|
|
//*****************************************************************************
|
|
void EnumNamespaces(IWbemServices *pIWbemServices, LPCWSTR pwcsClassName)
|
|
{
|
|
SCODE sc;
|
|
|
|
// If we aren't showing mofs or command lines
|
|
if (!((g_bClassMofs) || (g_bInstanceMofs) || (g_bShowInstance) || (g_bMofTemplate)))
|
|
{
|
|
variant_t varString;
|
|
IWbemClassObjectPtr pIWbemClassObject;
|
|
|
|
// Do this to get the right casing for the NameSpace
|
|
// Call GetObject with a known-to-exist class
|
|
sc = pIWbemServices->GetObject(
|
|
|
|
bstr_t(SYSTEMCLASS),
|
|
g_lGFlags,
|
|
g_pContext,
|
|
&pIWbemClassObject,
|
|
NULL
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not GetObject of __SystemClass in EnumNamespaces", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
sc = pIWbemClassObject->Get(NAMESPACEPROP, 0L, &varString, NULL, NULL);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not get __NameSpace property for class", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// Indent appropriate number of spaces and print namespace
|
|
DoIndent();
|
|
FWPRINTF(g_fOut, L"<%wS>%wS", V_BSTR(&varString), g_pwcsNewLine);
|
|
|
|
// Everything under this should be indented one more level
|
|
g_dwIndent++;
|
|
}
|
|
|
|
// If we are enumerating a specific class or instance, specify the class else pass null
|
|
if (pwcsClassName != NULL)
|
|
{
|
|
IWbemClassObjectPtr pIWbemClassObject;
|
|
|
|
// See if we are dealing with a single instance
|
|
if (wcschr(pwcsClassName, L'=') != NULL)
|
|
{
|
|
variant_t varString;
|
|
|
|
for (DWORD x=0; x < g_dwLoopCnt; x++)
|
|
{
|
|
sc = pIWbemServices->GetObject(
|
|
|
|
bstr_t(pwcsClassName),
|
|
g_lGFlags,
|
|
g_pContext,
|
|
&pIWbemClassObject,
|
|
NULL
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
fprintf(stderr, "%S\n", pwcsClassName);
|
|
PrintErrorAndExit("Could not GetObject of specified class in EnumNamespaces", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
sc = pIWbemClassObject->Get(CLASSPROP, 0L, &varString, NULL, NULL);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not get __Class property for class", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
ShowInstanceHeader(V_BSTR(&varString));
|
|
ShowInstance(pIWbemServices, pIWbemClassObject);
|
|
varString.Clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sc = pIWbemServices->GetObject(
|
|
|
|
bstr_t(pwcsClassName),
|
|
g_lGFlags,
|
|
g_pContext,
|
|
&pIWbemClassObject,
|
|
NULL
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
fprintf(stderr, "%S\n", pwcsClassName);
|
|
PrintErrorAndExit("Could not GetObject of specified class in EnumNamespaces", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
ShowClass(pIWbemServices, pIWbemClassObject);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EnumClasses(pIWbemServices, L"");
|
|
}
|
|
|
|
// If the user did not specify /S on the command line, we're done
|
|
if (!g_bRecurseNS)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IEnumWbemClassObjectPtr IEnumWbemClassObject;
|
|
|
|
//Find any namespaces under the current namespace
|
|
sc = pIWbemServices->CreateInstanceEnum(
|
|
|
|
bstr_t(NAMESPACEPROP), // with this name
|
|
WBEM_FLAG_DEEP | g_lEFlags,
|
|
g_pContext,
|
|
&IEnumWbemClassObject // using this enumerator
|
|
);
|
|
|
|
// If we find any namespaces, we'll want to enumerate them too
|
|
if (sc == WBEM_NO_ERROR)
|
|
{
|
|
DWORD dwAuthLevel, dwImpLevel;
|
|
sc = GetAuthImp(pIWbemServices, &dwAuthLevel, &dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("GetAuthImp Failed on CreateInstanceEnum (ns)", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
if (g_lImpFlag != -1)
|
|
{
|
|
dwImpLevel = g_lImpFlag;
|
|
}
|
|
|
|
if (g_lAuthFlag != -1)
|
|
{
|
|
dwAuthLevel = g_lAuthFlag;
|
|
}
|
|
|
|
sc = SetInterfaceSecurity(IEnumWbemClassObject, g_pwcsAuthority, g_pwcsUserID, g_pwcsPassword, dwAuthLevel, dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("SetInterfaceSecurity Failed on CreateInstanceEnum (ns)", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
ULONG uReturned;
|
|
IWbemClassObjectPtr pIWbemClassObject;
|
|
variant_t varString;
|
|
|
|
do
|
|
{
|
|
do
|
|
{
|
|
// Get the name of the next namespace
|
|
sc = IEnumWbemClassObject->Next(
|
|
|
|
TIMEOUT,
|
|
1,
|
|
&pIWbemClassObject,
|
|
&uReturned
|
|
);
|
|
|
|
if (g_bExit)
|
|
{
|
|
throw 1;
|
|
}
|
|
} while (sc == WBEM_S_TIMEDOUT);
|
|
|
|
if (sc == S_OK)
|
|
{
|
|
// Get the name
|
|
sc = pIWbemClassObject->Get(NAMEPROP, 0L, &varString, NULL, NULL);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not get name property", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
IWbemServicesPtr pNewIWbemServices;
|
|
|
|
// Open it
|
|
sc = pIWbemServices->OpenNamespace(
|
|
|
|
V_BSTR(&varString),
|
|
0L,
|
|
NULL,
|
|
&pNewIWbemServices,
|
|
NULL
|
|
);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Failed to Open Namespace", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// Now show all the classes/instances in the new Namespace
|
|
EnumNamespaces(pNewIWbemServices, pwcsClassName);
|
|
|
|
// Release
|
|
varString.Clear();
|
|
}
|
|
} while (sc == S_OK);
|
|
|
|
// Make sure we ended on a positive note
|
|
if (sc != S_FALSE)
|
|
{
|
|
PrintErrorAndExit("Could not get next namespace", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Failed to CreateInstanceEnum", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// Back up one level of indention
|
|
g_dwIndent--;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: GetObj
|
|
// Purpose: This is useful to test both enumerate and getobject
|
|
//*****************************************************************************
|
|
IWbemClassObject *GetObj(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject)
|
|
{
|
|
SCODE sc;
|
|
variant_t varString;
|
|
IWbemClassObject *clObject = NULL;
|
|
|
|
// Get the relative path of the current instance
|
|
sc = pIWbemClassObject->Get(RELPATHPROP, 0L, &varString, NULL, NULL);
|
|
if ((sc != WBEM_NO_ERROR) || (V_VT(&varString) != VT_BSTR))
|
|
{
|
|
if (g_bWarningContinue)
|
|
{
|
|
PrintError("Could not get path of class", sc, g_dwErrorFlags);
|
|
}
|
|
else if (g_bWarning)
|
|
{
|
|
PrintErrorAndAsk("Could not get path of class", sc, g_dwErrorFlags); // might exit program
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Could not get path of class", sc, g_dwErrorFlags); // might exit program
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Call GetObject with this path. Obviously, this should succeed.
|
|
sc = pIWbemServices->GetObject(
|
|
|
|
V_BSTR(&varString),
|
|
g_lGFlags,
|
|
g_pContext,
|
|
&clObject,
|
|
NULL
|
|
);
|
|
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
if (g_bWarningContinue)
|
|
{
|
|
PrintError("Could not GetObject on class", sc, g_dwErrorFlags);
|
|
}
|
|
else if (g_bWarning)
|
|
{
|
|
PrintErrorAndAsk("Could not GetObject on class", sc, g_dwErrorFlags); // might exit program
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Could not GetObject on class", sc, g_dwErrorFlags); // will exit program
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
return clObject;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ExecuteQuery
|
|
// Purpose:
|
|
//*****************************************************************************
|
|
void ExecuteQuery(IWbemServices *pIWbemServices, LPCWSTR pwcsQueryLanguage, LPCWSTR pwcsQuery)
|
|
{
|
|
SCODE sc;
|
|
IEnumWbemClassObjectPtr IEnumWbemClassObject;
|
|
InstanceQuerySinkPtr pMySink;
|
|
|
|
struct _timeb start, finish;
|
|
LARGE_INTEGER freq, start2;
|
|
QueryPerformanceFrequency(&freq);
|
|
|
|
DoIndent(); // Indent
|
|
FWPRINTF(g_fOut, L"(%wS) %wS%wS", pwcsQueryLanguage, pwcsQuery, g_pwcsNewLine); //Print class name
|
|
|
|
for (DWORD dwLoop = 0; dwLoop < g_dwLoopCnt; dwLoop++)
|
|
{
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&start);
|
|
}
|
|
|
|
if (!g_bTime2)
|
|
{
|
|
start2.QuadPart = 0;
|
|
}
|
|
else
|
|
{
|
|
QueryPerformanceCounter(&start2);
|
|
}
|
|
|
|
if (!g_bASync)
|
|
{
|
|
sc = pIWbemServices->ExecQuery(
|
|
|
|
bstr_t(pwcsQueryLanguage),
|
|
bstr_t(pwcsQuery),
|
|
0L | g_lEFlags,
|
|
g_pContext,
|
|
&IEnumWbemClassObject // using this enumerator
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pMySink.Attach(new InstanceQuerySink(pIWbemServices, false));
|
|
sc = pIWbemServices->ExecQueryAsync(
|
|
|
|
bstr_t(pwcsQueryLanguage),
|
|
bstr_t(pwcsQuery),
|
|
0L | g_lEFlags,
|
|
g_pContext,
|
|
pMySink
|
|
);
|
|
}
|
|
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&finish);
|
|
fprintf(stdout, "ExecQuery %6.4f seconds.\n", difftime(finish, start));
|
|
}
|
|
if (g_bTime2)
|
|
{
|
|
LARGE_INTEGER finish2;
|
|
QueryPerformanceCounter(&finish2);
|
|
fprintf(stdout, "ExecQuery: %I64d (%6.4f)\n", finish2.QuadPart - start2.QuadPart, (double)(finish2.QuadPart - start2.QuadPart)/freq.QuadPart);
|
|
}
|
|
|
|
if (sc == WBEM_NO_ERROR)
|
|
{
|
|
DWORD dwCount;
|
|
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&start);
|
|
}
|
|
|
|
if (!g_bTime2)
|
|
{
|
|
start2.QuadPart = 0;
|
|
}
|
|
else
|
|
{
|
|
QueryPerformanceCounter(&start2);
|
|
}
|
|
|
|
if (!g_bASync)
|
|
{
|
|
sc = ShowInstancesSync(pIWbemServices, IEnumWbemClassObject, dwCount, false);
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
sc = WaitForSingleObject(pMySink->GetEvent(), TIMEOUT);
|
|
if (g_bExit)
|
|
{
|
|
sc = pIWbemServices->CancelAsyncCall(pMySink);
|
|
throw 1;
|
|
}
|
|
} while (sc == WAIT_TIMEOUT);
|
|
|
|
dwCount = pMySink->GetCount();
|
|
sc = pMySink->GetResult();
|
|
if (sc == WBEM_S_NO_ERROR)
|
|
{
|
|
sc = S_FALSE;
|
|
}
|
|
}
|
|
|
|
// If we are doing timings
|
|
if (g_bTime1)
|
|
{
|
|
_ftime(&finish);
|
|
fprintf(stdout, "ShowInstances %6.4f seconds, %d instances.\n", difftime(finish, start), dwCount);
|
|
}
|
|
|
|
if (g_bTime2)
|
|
{
|
|
LARGE_INTEGER finish2;
|
|
QueryPerformanceCounter(&finish2);
|
|
fprintf(stdout, "ShowInstances: %I64d (%6.4f), %d instances.\n", finish2.QuadPart - start2.QuadPart, (double)(finish2.QuadPart - start2.QuadPart)/freq.QuadPart, dwCount);
|
|
}
|
|
|
|
// Make sure we ended on a positive note
|
|
if (sc != S_FALSE)
|
|
{
|
|
PrintErrorAndExit("Could not get next query instance", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Error on query", sc, g_dwErrorFlags);
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ShowInstancesSync
|
|
// Purpose:
|
|
//*****************************************************************************
|
|
HRESULT ShowInstancesSync(IWbemServices *pIWbemServices, IEnumWbemClassObject *IEnumWbemClassObject, DWORD &dwCount, LPCWSTR pwcsClassName)
|
|
{
|
|
dwCount = 0;
|
|
|
|
DWORD dwAuthLevel, dwImpLevel;
|
|
SCODE sc = GetAuthImp(pIWbemServices, &dwAuthLevel, &dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("GetAuthImp Failed on ExecQuery", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
if (g_lImpFlag != -1)
|
|
{
|
|
dwImpLevel = g_lImpFlag;
|
|
}
|
|
|
|
if (g_lAuthFlag != -1)
|
|
{
|
|
dwAuthLevel = g_lAuthFlag;
|
|
}
|
|
|
|
sc = SetInterfaceSecurity(IEnumWbemClassObject, g_pwcsAuthority, g_pwcsUserID, g_pwcsPassword, dwAuthLevel, dwImpLevel);
|
|
if (sc != S_OK)
|
|
{
|
|
PrintErrorAndExit("SetInterfaceSecurity Failed on ExecQuery", sc, g_dwErrorFlags);
|
|
}
|
|
|
|
ULONG uReturned;
|
|
IWbemClassObjectPtr pIWbemClassObject;
|
|
|
|
do
|
|
{
|
|
// Get the next instance
|
|
do
|
|
{
|
|
sc = IEnumWbemClassObject->Next(
|
|
|
|
TIMEOUT,
|
|
1,
|
|
&pIWbemClassObject,
|
|
&uReturned
|
|
);
|
|
|
|
if (g_bExit)
|
|
{
|
|
throw 1;
|
|
}
|
|
} while (sc == WBEM_S_TIMEDOUT);
|
|
|
|
if(sc == S_OK)
|
|
{
|
|
if (pwcsClassName != NULL)
|
|
{
|
|
ShowInstanceHeader(pwcsClassName);
|
|
}
|
|
else
|
|
{
|
|
pwcsClassName = NULL;
|
|
}
|
|
|
|
ShowInstance(pIWbemServices, pIWbemClassObject);
|
|
dwCount++;
|
|
}
|
|
} while (sc == S_OK);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: PrintMof
|
|
// Purpose: Prints the mof file for the class that was passed in
|
|
// Note:
|
|
//*****************************************************************************
|
|
void PrintMof(IWbemClassObject *clObject)
|
|
{
|
|
SCODE sc;
|
|
BSTR pObjectText = NULL;
|
|
|
|
// Get the mof
|
|
sc = clObject->GetObjectText(0L, &pObjectText);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Failed to print mof", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
|
|
// Print it
|
|
FWPRINTF(g_fOut, L"%wS", pObjectText);
|
|
|
|
// Clean up
|
|
SysFreeString(pObjectText);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ShowInstance
|
|
// Purpose: Shows the appropriate info for one specific instance
|
|
// Note:
|
|
//*****************************************************************************
|
|
void ShowInstance(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject)
|
|
{
|
|
IWbemClassObjectPtr clObject;
|
|
WCHAR *buf;
|
|
MyString clMyBuff;
|
|
SCODE sc;
|
|
variant_t varVal;
|
|
bool bGotOne = false;
|
|
|
|
// Get Object (useful to test both enumerate and getobject)
|
|
if (g_bCheckGet)
|
|
{
|
|
clObject = GetObj(pIWbemServices, pIWbemClassObject);
|
|
if (clObject == NULL)
|
|
{
|
|
clObject = pIWbemClassObject;
|
|
}
|
|
else
|
|
{
|
|
bGotOne = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
clObject = pIWbemClassObject;
|
|
}
|
|
|
|
if (g_bCheckAssoc)
|
|
{
|
|
CheckAssocEndPoints(pIWbemServices, pIWbemClassObject);
|
|
}
|
|
|
|
// If we are just showing the mof for each instance
|
|
if (g_bInstanceMofs)
|
|
{
|
|
PrintMof(clObject);
|
|
|
|
// If we are just printing the command line to show this instance
|
|
}
|
|
else if (g_bShowInstance)
|
|
{
|
|
// Start building the command line
|
|
clMyBuff += L" \"";
|
|
|
|
// Get the ns
|
|
sc = clObject->Get(NAMESPACEPROP, 0L, &varVal, NULL, NULL);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not get __namespace", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
varVal.Clear();
|
|
|
|
// Add the relpath
|
|
sc = clObject->Get(RELPATHPROP, 0L, &varVal, NULL, NULL);
|
|
if (sc != WBEM_NO_ERROR)
|
|
{
|
|
PrintErrorAndExit("Could not get __relpath", sc, g_dwErrorFlags); // Exits program
|
|
}
|
|
WCHAR *pW;
|
|
pW = wcschr(V_BSTR(&varVal), L'=') + 1;
|
|
buf = EscapeChars(pW);
|
|
*(pW) = L'\0';
|
|
clMyBuff += V_BSTR(&varVal);
|
|
clMyBuff += buf;
|
|
clMyBuff += L"\"";
|
|
|
|
free(buf);
|
|
|
|
// Print it and we're done
|
|
FWPRINTF(g_fOut, L"%wS%wS", clMyBuff.GetString(), g_pwcsNewLine); // Print the command line
|
|
clMyBuff.Empty();
|
|
|
|
}
|
|
else
|
|
{
|
|
// Otherwise we want to show the instance details
|
|
if (!g_bMofTemplate)
|
|
{
|
|
g_dwIndent++; // Increase indention level
|
|
}
|
|
buf = EnumProperties(clObject);
|
|
FWPRINTF(g_fOut, L"%wS%wS", buf, g_pwcsNewLine); // Print the properties
|
|
free(buf);
|
|
if (!g_bMofTemplate)
|
|
{
|
|
g_dwIndent--; // Decrease the indention level
|
|
}
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: BstrCmp
|
|
// Purpose: Compares 2 bstr arguments
|
|
// Note: Used by the qsort routine
|
|
//*****************************************************************************
|
|
int __cdecl BstrCmp(const void *arg1,const void *arg2)
|
|
{
|
|
return _wcsicmp( *(WCHAR **)arg1, *(WCHAR **)arg2 );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: DoIndent
|
|
// Purpose: Indents g_dwIndent tabs
|
|
//*****************************************************************************
|
|
void DoIndent()
|
|
{
|
|
for (DWORD x=0; x < g_dwIndent; x++)
|
|
{
|
|
fputws(L"\t", g_fOut);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ProcessCommandLine
|
|
// Purpose: This function processes the command line for the program,
|
|
// filling in the global variables determining what the program
|
|
// will do.
|
|
//*****************************************************************************
|
|
DWORD ProcessCommandLine(int argc, wchar_t *argv[])
|
|
{
|
|
int iLoop, iPlace;
|
|
char *z;
|
|
WCHAR *pwcsName, *pwcsValue;
|
|
SCODE sc;
|
|
variant_t vValue;
|
|
char *szHelp = "WBEMDUMP - Dumps the contents of the CIMOM database.\n\n"
|
|
"Syntax: wbemdump [switches] [Namespace [Class|ObjectPath] ]\n"
|
|
" wbemdump /Q [switches] Namespace QueryLanguage Query\n\n"
|
|
"Where: 'Namespace' is the namespace to dump (defaults to root\\default)\n"
|
|
" 'Class' is the name of a specific class to dump (defaults to none)\n"
|
|
" 'ObjectPath' is one instance (ex \"SClassA.KeyProp=\\\"foobar\\\"\")\n"
|
|
" 'QueryLanguage' is any WBEM supported query language (currently only\n"
|
|
" \"WQL\" is supported).\n"
|
|
" 'Query' is a valid query for the specified language, enclosed in quotes\n"
|
|
" 'switches' is one of\n"
|
|
" /S Recurse down the tree\n"
|
|
" /S2 Recurse down Namespaces (implies /S)\n"
|
|
" /E Show system classes and properties\n"
|
|
" /E1 Like /E except don't show __SERVER or __PATH property\n"
|
|
" /E2 Shows command lines for dumping instances (test mode)\n"
|
|
" /D Don't show properties\n"
|
|
" /G Do a GetObject on all enumerated instances\n"
|
|
" /G2 Do a GetObject on all reference properties\n"
|
|
" /G:<x> Like /G using x for flags (Amended=131072)\n"
|
|
" /M Get Class MOFS instead of data values\n"
|
|
" /M2 Get Instance MOFS instead of data values\n"
|
|
" /M3 Produce instance template\n"
|
|
" /B:<num> CreateEnum flags (SemiSync=16; Forward=32)\n"
|
|
" /AS Use Async functions\n"
|
|
" /W Prompt to continue on warning errors\n"
|
|
" /WY Print warnings and continue\n"
|
|
" /W:1 Use IWbemClassObject::GetObjectText to show errors\n"
|
|
" /H:<name>:<value> Specify context object value (test mode)\n"
|
|
" /CQV:<name>[:value] Specify a class qualifier on which to filter\n"
|
|
" /T Print times on enumerations\n"
|
|
" /T2 Print times on enumerations using alternate timer\n"
|
|
" /O:<file> File name for output (creates Unicode file)\n"
|
|
" /C:<file> Command file containing multiple WBEMDUMP command lines\n"
|
|
" /U:<UserID> UserID to connect with (default: NULL)\n"
|
|
" /P:<Password> Password to connect with (default: NULL)\n"
|
|
" /A:<Authority> Authority to connect with\n"
|
|
" /I:<ImpLevel> Anonymous=1 Identify=2 Impersonate=3(dflt) Delegate=4\n"
|
|
" /AL:<AuthenticationLevel> None=1 Conn=2 Call=3 Pkt=4 PktI=5 PktP=6\n"
|
|
" /Locale:<localid> Locale to pass to ConnectServer\n"
|
|
" /L:<LoopCnt> Number of times to enumerate instances (leak check)\n"
|
|
"\n"
|
|
"Notes: - You can redirect the output to a file using standard redirection.\n"
|
|
" - If the /C switch is used, the namespace on the command line must\n"
|
|
" be the same namespace that is used for each of the command lines.\n"
|
|
" It is not possible to use different namespaces on the different lines\n"
|
|
" in the command file.\n"
|
|
"\n"
|
|
"EXAMPLES:\n"
|
|
"\n"
|
|
" WBEMDUMP /S /E root\\default - Dumps everything in root\\default\n"
|
|
" WBEMDUMP /S /E /M /M2 root\\default - Dump all class & instance mofs\n"
|
|
" WBEMDUMP root\\default foo - Dumps all instances of the foo class\n"
|
|
" WBEMDUMP root\\default foo.name=\\\"bar\\\" - Dumps one instance of the foo class\n"
|
|
" WBEMDUMP /S2 /M root - Dumps mofs for all non-system classes in all NS's\n"
|
|
" WBEMDUMP /Q root\\default WQL \"SELECT * FROM Environment WHERE Name=\\\"Path\\\"\""
|
|
"\n";
|
|
|
|
// Process all the arguments.
|
|
// ==========================
|
|
if (g_pwcsNamespace != NULL)
|
|
{
|
|
// Only applies to scripts
|
|
iPlace = 1;
|
|
}
|
|
else
|
|
{
|
|
iPlace = 0;
|
|
}
|
|
|
|
// Set global flags depending on command line arguments
|
|
for (iLoop = 1; iLoop < argc; ++iLoop)
|
|
{
|
|
if (_wcsicmp(argv[iLoop], L"/HELP") == 0 || _wcsicmp(argv[iLoop],L"-HELP") == 0 ||
|
|
(wcscmp(argv[iLoop], L"/?") == 0) || (wcscmp(argv[iLoop], L"-?") == 0))
|
|
{
|
|
fputs(szHelp, stdout);
|
|
return(S_FALSE);
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/S") == 0 || _wcsicmp(argv[iLoop],L"-S") == 0)
|
|
{
|
|
g_bRecurseClass = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/S2") == 0 || _wcsicmp(argv[iLoop],L"-S2") == 0)
|
|
{
|
|
g_bRecurseClass = TRUE;
|
|
g_bRecurseNS = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/Q") == 0 || _wcsicmp(argv[iLoop],L"-Q") == 0)
|
|
{
|
|
g_bDoQuery = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/E") == 0 || _wcsicmp(argv[iLoop],L"-E") == 0)
|
|
{
|
|
g_bShowSystem = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/E1") == 0 || _wcsicmp(argv[iLoop],L"-E1") == 0)
|
|
{
|
|
g_bShowSystem = TRUE;
|
|
g_bShowSystem1 = TRUE;
|
|
g_bShowInstance = FALSE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/E2") == 0 || _wcsicmp(argv[iLoop],L"-E2") == 0)
|
|
{
|
|
g_bShowSystem1 = FALSE;
|
|
g_bShowInstance = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/D") == 0 || _wcsicmp(argv[iLoop],L"-D") == 0)
|
|
{
|
|
g_bShowProperties = FALSE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/G") == 0 || _wcsicmp(argv[iLoop],L"-G") == 0)
|
|
{
|
|
g_bCheckGet = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/G2") == 0 || _wcsicmp(argv[iLoop],L"-G2") == 0)
|
|
{
|
|
g_bCheckAssoc = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/M") == 0 || _wcsicmp(argv[iLoop],L"-M") == 0)
|
|
{
|
|
g_bClassMofs = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/M2") == 0 || _wcsicmp(argv[iLoop],L"-M2") == 0)
|
|
{
|
|
g_bInstanceMofs = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/M3") == 0 || _wcsicmp(argv[iLoop],L"-M3") == 0)
|
|
{
|
|
g_bMofTemplate = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/W") == 0 || _wcsicmp(argv[iLoop],L"-W") == 0)
|
|
{
|
|
g_bWarning = TRUE;
|
|
g_bWarningContinue = FALSE;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/W:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-W:", 3) == 0)
|
|
{
|
|
g_dwErrorFlags = _wtoi((argv[iLoop])+3);
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/WY") == 0 || _wcsicmp(argv[iLoop],L"-WY") == 0)
|
|
{
|
|
g_bWarningContinue = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/T") == 0 || _wcsicmp(argv[iLoop],L"-T") == 0)
|
|
{
|
|
g_bTime1 = TRUE;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/T2", 3) == 0 || _wcsnicmp(argv[iLoop],L"-T2", 3) == 0)
|
|
{
|
|
g_bTime2 = TRUE;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/G:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-G:", 3) == 0)
|
|
{
|
|
g_lGFlags = _wtoi((argv[iLoop])+3);
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/H:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-H:", 3) == 0)
|
|
{
|
|
if (g_pContext == NULL)
|
|
{
|
|
sc = CoCreateInstance(CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER, IID_IWbemContext, (void **)&g_pContext);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Can't create context object", sc, g_dwErrorFlags);
|
|
}
|
|
}
|
|
pwcsName = (argv[iLoop])+3;
|
|
pwcsValue = wcschr(pwcsName, L':');
|
|
if (pwcsValue == NULL)
|
|
{
|
|
PrintErrorAndExit("Can't parse Context value", 0, g_dwErrorFlags);
|
|
}
|
|
*pwcsValue = L'\0';
|
|
pwcsValue++;
|
|
vValue = pwcsValue;
|
|
sc = g_pContext->SetValue(pwcsName, 0L, &vValue);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Failed to SetValue on context object", 0, g_dwErrorFlags);
|
|
}
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/U:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-U:", 3) == 0)
|
|
{
|
|
g_pwcsUserID = (argv[iLoop])+3;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/P:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-P:", 3) == 0)
|
|
{
|
|
g_pwcsPassword = (argv[iLoop])+3;
|
|
// Currently not implemented.
|
|
// }
|
|
// else if (_wcsnicmp(argv[iLoop], L"/F:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-F:", 3) == 0)
|
|
// {
|
|
// g_lSFlags = _wtoi((argv[iLoop])+3);
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/I:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-F:", 3) == 0)
|
|
{
|
|
g_lImpFlag = _wtoi((argv[iLoop])+3);
|
|
}
|
|
else if (_wcsicmp(argv[iLoop], L"/AS") == 0 || _wcsicmp(argv[iLoop],L"-AS") == 0)
|
|
{
|
|
g_bASync = TRUE;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/AL:", 4) == 0 || _wcsnicmp(argv[iLoop],L"-AL:", 4) == 0)
|
|
{
|
|
g_lAuthFlag = _wtoi((argv[iLoop])+4);
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/B:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-B:", 3) == 0)
|
|
{
|
|
g_lEFlags = _wtoi((argv[iLoop])+3);
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/Locale:", 8) == 0 || _wcsnicmp(argv[iLoop],L"-Locale:", 8) == 0)
|
|
{
|
|
g_pwcsLocale = (argv[iLoop])+8;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/L:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-L:", 3) == 0)
|
|
{
|
|
g_dwLoopCnt = _wtoi((argv[iLoop])+3);
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/A:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-A:", 3) == 0)
|
|
{
|
|
g_pwcsAuthority = (argv[iLoop])+3;
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/O:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-O:", 3) == 0)
|
|
{
|
|
g_pwcsNewLine = L"\r\n";
|
|
// must convert to oem string since w95 doesn't support _wfopen
|
|
// g_fOut = _wfopen(argv[iLoop], L"wb");
|
|
g_fOut = fopen(cvt((argv[iLoop])+3, &z), "wb");
|
|
free(z);
|
|
if (g_fOut == NULL)
|
|
{
|
|
fprintf(stdout, "Can't open output file: %S (%d)\n", (argv[iLoop])+3, GetLastError());
|
|
return(S_FALSE);
|
|
}
|
|
fputs(UNICODE_SIGNATURE, g_fOut);
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/C:", 3) == 0 || _wcsnicmp(argv[iLoop],L"-C:", 3) == 0)
|
|
{
|
|
// must convert to oem string since w95 doesn't support _wfopen
|
|
g_fCmdFile = fopen(cvt((argv[iLoop])+3, &z), "rb");
|
|
free(z);
|
|
if (g_fCmdFile == NULL)
|
|
{
|
|
fprintf(stdout, "Can't open command file: %S (%d)\n", (argv[iLoop])+3, GetLastError());
|
|
return(S_FALSE);
|
|
}
|
|
|
|
// Now, let's see if we are dealing with a unicode file here
|
|
char buff[2];
|
|
fread(buff, 2, 1, g_fCmdFile);
|
|
|
|
if (memcmp(buff, UNICODE_SIGNATURE, 2) != 0)
|
|
{
|
|
g_bUnicodeCmdFile = false;
|
|
fseek(g_fCmdFile, 0, SEEK_SET);
|
|
}
|
|
else
|
|
{
|
|
g_bUnicodeCmdFile = true;
|
|
}
|
|
}
|
|
else if (_wcsnicmp(argv[iLoop], L"/CQV:", 5) == 0 || _wcsnicmp(argv[iLoop],L"-CQV:", 5) == 0)
|
|
{
|
|
if (g_bstrQualifierName != NULL)
|
|
{
|
|
PrintErrorAndExit("Only 1 qualifer name can be filtered on", 0, g_dwErrorFlags);
|
|
}
|
|
pwcsName = (argv[iLoop])+5;
|
|
pwcsValue = wcschr(pwcsName, L':');
|
|
|
|
// all values
|
|
if (pwcsValue == NULL)
|
|
{
|
|
g_bstrQualifierName = SysAllocString(pwcsName);
|
|
}
|
|
else
|
|
{
|
|
// Only specified value
|
|
*pwcsValue = L'\0';
|
|
pwcsValue++;
|
|
g_bstrQualifierValue = SysAllocString(pwcsValue);
|
|
g_bstrQualifierName = SysAllocString(pwcsName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (iPlace)
|
|
{
|
|
case 0:
|
|
{
|
|
g_pwcsNamespace = argv[iLoop];
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
g_pwcsObjectPath = argv[iLoop];
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
g_pwcsQuery = argv[iLoop];
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
++iPlace;
|
|
}
|
|
}
|
|
|
|
// See if we got enough arguments.
|
|
// ===============================
|
|
|
|
if (((iPlace > 2) && !g_bDoQuery) || ((iPlace != 3) && g_bDoQuery))
|
|
{
|
|
fputs(szHelp, stdout);
|
|
return(S_FALSE);
|
|
}
|
|
|
|
if (!g_fOut)
|
|
{
|
|
g_fOut = stdout;
|
|
}
|
|
|
|
if (iPlace == 0)
|
|
{
|
|
g_pwcsNamespace = L"root\\default";
|
|
}
|
|
|
|
// Finished.
|
|
// =========
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: EscapeChars
|
|
// Purpose: 'Escapes' characters in a string by placing '\' in front of
|
|
// the " and \ characters.
|
|
// Notes: Caller must free returned buffer
|
|
//*****************************************************************************
|
|
WCHAR *EscapeChars(LPCWSTR szInBuf)
|
|
{
|
|
WCHAR *szOutBuf = NULL;
|
|
int x;
|
|
|
|
// Adding escape characters can't do more than double the string size
|
|
szOutBuf = (WCHAR *)malloc(((wcslen(szInBuf) + 1) * sizeof(WCHAR)) * 2);
|
|
x = 0;
|
|
if(szOutBuf)
|
|
{
|
|
while (*szInBuf != 0)
|
|
{
|
|
if ((*szInBuf == L'\\') && (*(szInBuf + 1) == L'\"'))
|
|
{
|
|
szOutBuf[x++] = '\\';
|
|
}
|
|
else if (*szInBuf == L'"')
|
|
{
|
|
szOutBuf[x++] = '\\';
|
|
}
|
|
szOutBuf[x++] = *(szInBuf ++);
|
|
}
|
|
szOutBuf[x] = L'\0';
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
return szOutBuf;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: MyValueToString
|
|
// Purpose: A callback routine from utillib. It is designed to handle any
|
|
// variant types that ValueToString doesn't. Specifically it
|
|
// handles embedded objects.
|
|
//*****************************************************************************
|
|
WCHAR *MyValueToString(VARIANT *pv)
|
|
{
|
|
WCHAR *buf = NULL;
|
|
WCHAR *vbuf = NULL;
|
|
|
|
switch (V_VT(pv))
|
|
{
|
|
case VT_UNKNOWN: // Currently only used for embedded objects
|
|
{
|
|
extern DWORD g_dwIndent;
|
|
g_dwIndent++;
|
|
buf = EnumProperties((IWbemClassObject *)pv->punkVal); // May result in recursion
|
|
g_dwIndent--;
|
|
break;
|
|
}
|
|
|
|
case VT_UNKNOWN | VT_ARRAY:
|
|
{
|
|
g_dwIndent++; // Increase indention level
|
|
|
|
SAFEARRAY *pVec = pv->parray;
|
|
long iLBound, iUBound;
|
|
|
|
SafeArrayGetLBound(pVec, 1, &iLBound);
|
|
SafeArrayGetUBound(pVec, 1, &iUBound);
|
|
if ((iUBound - iLBound + 1) == 0)
|
|
{
|
|
buf = (WCHAR *)calloc(1, BLOCKSIZE);
|
|
if (buf)
|
|
{
|
|
for (DWORD x=0; x < g_dwIndent; x++)
|
|
{
|
|
buf[x] = L'\t';
|
|
}
|
|
wcscat(buf, L"<empty array>");
|
|
wcscat(buf, g_pwcsNewLine);
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
g_dwIndent--; // Decrease indention level
|
|
break;
|
|
}
|
|
|
|
buf = (WCHAR *)calloc(BLOCKSIZE, sizeof(WCHAR));
|
|
|
|
if (buf)
|
|
{
|
|
IUnknownPtr v;
|
|
IWbemClassObjectPtr pCO;
|
|
variant_t varString;
|
|
|
|
for (long i = iLBound; i <= iUBound; i++)
|
|
{
|
|
SafeArrayGetElement(pVec, &i, &v);
|
|
|
|
pCO = v; // QI to IWbemClassObject
|
|
MyString clMyBuff;
|
|
|
|
HRESULT sc = pCO->Get(CLASSPROP, 0L, &varString, NULL, NULL);
|
|
if (S_OK != sc)
|
|
{
|
|
PrintErrorAndExit("Couldn't get class property in enumproperties", sc, g_dwErrorFlags); //Exits program
|
|
}
|
|
|
|
//clMyBuff += g_pwcsNewLine;
|
|
for (DWORD x=0; x < g_dwIndent; x++)
|
|
{
|
|
clMyBuff += L"\t";
|
|
}
|
|
clMyBuff += L"instance of ";
|
|
clMyBuff += V_BSTR(&varString);
|
|
clMyBuff += L" {";
|
|
clMyBuff += g_pwcsNewLine;
|
|
g_dwIndent++;
|
|
|
|
varString.Clear();
|
|
|
|
vbuf = clMyBuff.GetCloneString();
|
|
|
|
// Copy into buffer
|
|
buf = (WCHAR *)realloc(buf, (wcslen(buf) + wcslen(vbuf) + 1) * sizeof(WCHAR));
|
|
if (buf)
|
|
{
|
|
wcscat(buf, vbuf);
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
vbuf = EnumProperties(pCO);
|
|
|
|
// Copy into buffer
|
|
buf = (WCHAR *)realloc(buf, (wcslen(buf) + wcslen(vbuf) + 1) * sizeof(WCHAR));
|
|
if (buf)
|
|
{
|
|
wcscat(buf, vbuf);
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
// Add }
|
|
MyString clMyBuff2;
|
|
|
|
for (x=0; x < g_dwIndent-1; x++)
|
|
{
|
|
clMyBuff2 += L"\t";
|
|
}
|
|
clMyBuff2 += L" }";
|
|
clMyBuff2 += g_pwcsNewLine;
|
|
vbuf = clMyBuff2.GetCloneString();
|
|
|
|
// Copy into buffer
|
|
buf = (WCHAR *)realloc(buf, (wcslen(buf) + wcslen(vbuf) + 1) * sizeof(WCHAR));
|
|
if (buf)
|
|
{
|
|
wcscat(buf, vbuf);
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
g_dwIndent--;
|
|
|
|
free(vbuf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
g_dwIndent--; // Decrease indention level
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
buf = (WCHAR *)malloc(BLOCKSIZE);
|
|
if (buf)
|
|
{
|
|
wcscpy(buf, L"<conversion error>");
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
}
|
|
}
|
|
return buf;
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ShowInstanceHeader
|
|
// Purpose: Prints the header at the top of each instance, unless we are
|
|
// printing instance mofs
|
|
//*****************************************************************************
|
|
void ShowInstanceHeader(LPCWSTR pwcsClassName)
|
|
{
|
|
if ((!g_bInstanceMofs) && (!g_bShowInstance))
|
|
{
|
|
DoIndent(); // Indent
|
|
FWPRINTF(g_fOut, L"%wS%wS", pwcsClassName, g_pwcsNewLine); //Print class name
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ResetGlobalFlags
|
|
// Purpose: Resets the global flags to their default values. This is
|
|
// called in between command lines in a command file.
|
|
//*****************************************************************************
|
|
void ResetGlobalFlags()
|
|
{
|
|
g_bShowSystem = FALSE;
|
|
g_bShowSystem1 = FALSE;
|
|
g_bShowInstance = FALSE;
|
|
g_bShowProperties = TRUE;
|
|
g_bRecurseClass = FALSE;
|
|
g_bRecurseNS = FALSE;
|
|
g_bCheckGet = FALSE;
|
|
g_bCheckAssoc = FALSE;
|
|
g_bDoQuery = FALSE;
|
|
g_bClassMofs = FALSE;
|
|
g_bInstanceMofs = FALSE;
|
|
|
|
g_dwIndent = 0; // Current indention level
|
|
g_lGFlags = 0;
|
|
|
|
g_pwcsObjectPath = NULL; // ObjectPath to show
|
|
g_pwcsQuery = NULL; // Query (for /q commands)
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: ParseCommandLine
|
|
// Purpose: Reads the command line from a file and sends it to the parsing
|
|
// routine.
|
|
//*****************************************************************************
|
|
bool ParseCommandLine(int *numargs, wchar_t **argv)
|
|
{
|
|
WCHAR wszLine[4096];
|
|
char szLine[4096];
|
|
int numchars;
|
|
WCHAR *p;
|
|
|
|
// The parsing routine expects to find a program name as the first arg, so
|
|
// give it one
|
|
wcscpy(wszLine, L"xx ");
|
|
|
|
// If this is a unicode command file, read a wcs
|
|
if (g_bUnicodeCmdFile)
|
|
{
|
|
if (!fgetws(wszLine + 3, sizeof(wszLine)/sizeof(WCHAR), g_fCmdFile))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// else convert to wcs
|
|
szLine[0] = '\0';
|
|
// If no more command lines
|
|
if (!fgets(szLine, sizeof(szLine), g_fCmdFile))
|
|
{
|
|
return false;
|
|
}
|
|
swprintf(wszLine + 3, L"%S", szLine);
|
|
}
|
|
|
|
// Trim trailing cr, lf, space, and eof markers
|
|
p = &wszLine[wcslen(wszLine)-1];
|
|
while ((*p == L'\n') || (*p == L'\r') || (*p == L' ') || (*p == L'\x1a'))
|
|
{
|
|
*p = L'\0';
|
|
p = &wszLine[wcslen(wszLine)-1];
|
|
}
|
|
|
|
// If we read a blank line
|
|
if (wcscmp(wszLine, L"xx") == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* first find out how much space is needed to store args */
|
|
wparse_cmdline(wszLine, NULL, NULL, numargs, &numchars);
|
|
|
|
/* allocate space for argv[] vector and strings */
|
|
p = (WCHAR *)malloc(*numargs * sizeof(WCHAR *) + numchars * sizeof(WCHAR));
|
|
|
|
if (!p)
|
|
{
|
|
PrintErrorAndExit("Out of memory", 0, g_dwErrorFlags);
|
|
}
|
|
|
|
/* store args and argv ptrs in just allocated block */
|
|
wparse_cmdline(wszLine, (wchar_t **)p, (wchar_t *)(((char *)p) + *numargs * sizeof(wchar_t *)), numargs, &numchars);
|
|
|
|
*argv = p;
|
|
(*numargs)--;
|
|
|
|
return true;
|
|
}
|
|
|
|
/***
|
|
*static void parse_cmdline(cmdstart, argv, args, numargs, numchars)
|
|
*
|
|
*Purpose:
|
|
* Parses the command line and sets up the argv[] array.
|
|
* On entry, cmdstart should point to the command line,
|
|
* argv should point to memory for the argv array, args
|
|
* points to memory to place the text of the arguments.
|
|
* If these are NULL, then no storing (only coujting)
|
|
* is done. On exit, *numargs has the number of
|
|
* arguments (plus one for a final NULL argument),
|
|
* and *numchars has the number of bytes used in the buffer
|
|
* pointed to by args.
|
|
*
|
|
*Entry:
|
|
* _TSCHAR *cmdstart - pointer to command line of the form
|
|
* <progname><nul><args><nul>
|
|
* _TSCHAR **argv - where to build argv array; NULL means don't
|
|
* build array
|
|
* _TSCHAR *args - where to place argument text; NULL means don't
|
|
* store text
|
|
*
|
|
*Exit:
|
|
* no return value
|
|
* int *numargs - returns number of argv entries created
|
|
* int *numchars - number of characters used in args buffer
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#define DQUOTECHAR L'\"'
|
|
#define NULCHAR L'\0'
|
|
#define SPACECHAR L' '
|
|
#define TABCHAR L'\t'
|
|
#define SLASHCHAR L'\\'
|
|
static void __cdecl wparse_cmdline (
|
|
WCHAR *cmdstart,
|
|
WCHAR **argv,
|
|
WCHAR *args,
|
|
int *numargs,
|
|
int *numchars
|
|
)
|
|
{
|
|
WCHAR *p;
|
|
WCHAR c;
|
|
int inquote; /* 1 = inside quotes */
|
|
int copychar; /* 1 = copy char to *args */
|
|
unsigned numslash; /* num of backslashes seen */
|
|
|
|
*numchars = 0;
|
|
*numargs = 1; /* the program name at least */
|
|
|
|
/* first scan the program name, copy it, and count the bytes */
|
|
p = cmdstart;
|
|
if (argv)
|
|
*argv++ = args;
|
|
|
|
/* A quoted program name is handled here. The handling is much
|
|
simpler than for other arguments. Basically, whatever lies
|
|
between the leading double-quote and next one, or a terminal null
|
|
character is simply accepted. Fancier handling is not required
|
|
because the program name must be a legal NTFS/HPFS file name.
|
|
Note that the double-quote characters are not copied, nor do they
|
|
contribute to numchars. */
|
|
if ( *p == DQUOTECHAR )
|
|
{
|
|
/* scan from just past the first double-quote through the next
|
|
double-quote, or up to a null, whichever comes first */
|
|
while ( (*(++p) != DQUOTECHAR) && (*p != NULCHAR) )
|
|
{
|
|
|
|
++*numchars;
|
|
if ( args )
|
|
*args++ = *p;
|
|
}
|
|
/* append the terminating null */
|
|
++*numchars;
|
|
if ( args )
|
|
*args++ = NULCHAR;
|
|
|
|
/* if we stopped on a double-quote (usual case), skip over it */
|
|
if ( *p == DQUOTECHAR )
|
|
p++;
|
|
}
|
|
else
|
|
{
|
|
/* Not a quoted program name */
|
|
do
|
|
{
|
|
++*numchars;
|
|
if (args)
|
|
*args++ = *p;
|
|
|
|
c = (WCHAR) *p++;
|
|
|
|
} while ( c != SPACECHAR && c != NULCHAR && c != TABCHAR );
|
|
|
|
if ( c == NULCHAR )
|
|
{
|
|
p--;
|
|
}
|
|
else
|
|
{
|
|
if (args)
|
|
*(args-1) = NULCHAR;
|
|
}
|
|
}
|
|
|
|
inquote = 0;
|
|
|
|
/* loop on each argument */
|
|
for(;;)
|
|
{
|
|
if ( *p )
|
|
{
|
|
while (*p == SPACECHAR || *p == TABCHAR)
|
|
++p;
|
|
}
|
|
|
|
if (*p == NULCHAR)
|
|
break; /* end of args */
|
|
|
|
/* scan an argument */
|
|
if (argv)
|
|
*argv++ = args; /* store ptr to arg */
|
|
++*numargs;
|
|
|
|
/* loop through scanning one argument */
|
|
for (;;)
|
|
{
|
|
copychar = 1;
|
|
/* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
|
|
2N+1 backslashes + " ==> N backslashes + literal "
|
|
N backslashes ==> N backslashes */
|
|
numslash = 0;
|
|
while (*p == SLASHCHAR)
|
|
{
|
|
/* count number of backslashes for use below */
|
|
++p;
|
|
++numslash;
|
|
}
|
|
if (*p == DQUOTECHAR)
|
|
{
|
|
/* if 2N backslashes before, start/end quote, otherwise
|
|
copy literally */
|
|
if (numslash % 2 == 0)
|
|
{
|
|
if (inquote)
|
|
{
|
|
if (p[1] == DQUOTECHAR)
|
|
p++; /* Double quote inside quoted string */
|
|
else /* skip first quote char and copy second */
|
|
copychar = 0;
|
|
} else
|
|
copychar = 0; /* don't copy quote */
|
|
|
|
inquote = !inquote;
|
|
}
|
|
numslash /= 2; /* divide numslash by two */
|
|
}
|
|
|
|
/* copy slashes */
|
|
while (numslash--)
|
|
{
|
|
if (args)
|
|
*args++ = SLASHCHAR;
|
|
++*numchars;
|
|
}
|
|
|
|
/* if at end of arg, break loop */
|
|
if (*p == NULCHAR || (!inquote && (*p == SPACECHAR || *p == TABCHAR)))
|
|
break;
|
|
|
|
/* copy character into argument */
|
|
if (copychar)
|
|
{
|
|
if (args)
|
|
*args++ = *p;
|
|
++*numchars;
|
|
}
|
|
++p;
|
|
}
|
|
|
|
/* null-terminate the argument */
|
|
|
|
if (args)
|
|
*args++ = NULCHAR; /* terminate string */
|
|
++*numchars;
|
|
}
|
|
|
|
/* We put one last argument in -- a null ptr */
|
|
if (argv)
|
|
*argv++ = NULL;
|
|
++*numargs;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: CheckQualifiers
|
|
// Purpose: Checks to see if we are filtering on class qualifiers. If
|
|
// so, checks to see if the specified qualifier/value is present.
|
|
//*****************************************************************************
|
|
BOOL CheckQualifiers(IWbemClassObject *pIWbemClassObject)
|
|
{
|
|
// If we are not filtering on qualifiers
|
|
if (g_bstrQualifierName == NULL)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL bRet = TRUE;
|
|
variant_t vValue;
|
|
|
|
IWbemQualifierSet *pQualSet = NULL;
|
|
HRESULT hr = pIWbemClassObject->GetQualifierSet(&pQualSet);
|
|
|
|
// This should always work
|
|
if (FAILED(hr))
|
|
{
|
|
PrintErrorAndExit("Failed to get class qualifier set", hr, g_dwErrorFlags); // exits program
|
|
}
|
|
|
|
// However, this might reasonably fail
|
|
hr = pQualSet->Get(g_bstrQualifierName, 0L, &vValue, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Ok, the qualifier is there. Did they request a specific value?
|
|
if (g_bstrQualifierValue == NULL)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Check to see if the value match
|
|
if (VariantChangeType(&vValue, &vValue, 0, VT_BSTR) == S_OK)
|
|
bRet = _wcsicmp(V_BSTR(&vValue), g_bstrQualifierValue) == 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We failed to Get the qualifier. Was it because the thing just wasn't there?
|
|
if (hr == WBEM_E_NOT_FOUND)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// Some other error
|
|
PrintErrorAndExit("Failed to Get class qualifier value", hr, g_dwErrorFlags); // exits program
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: CheckAssocEndPoints
|
|
// Purpose: Checks to see if the references pointed to by the reference
|
|
// properties of this class really exist.
|
|
//*****************************************************************************
|
|
void CheckAssocEndPoints(IWbemServices *pIWbemServices, IWbemClassObject *pIWbemClassObject)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr = pIWbemClassObject->BeginEnumeration(WBEM_FLAG_REFS_ONLY)))
|
|
{
|
|
PrintErrorAndExit("Failed to get Refs Enumeration", hr, g_dwErrorFlags); // exits program
|
|
}
|
|
|
|
BSTR bstrPropertyName = NULL;
|
|
variant_t vVal;
|
|
|
|
while (SUCCEEDED(hr = pIWbemClassObject->Next(0, &bstrPropertyName, &vVal, NULL, NULL)) &&
|
|
(hr != WBEM_S_NO_MORE_DATA) )
|
|
{
|
|
if ( (V_VT(&vVal) == VT_BSTR) && (V_BSTR(&vVal) != NULL) )
|
|
{
|
|
if (FAILED(hr = pIWbemServices->GetObject(V_BSTR(&vVal), 0, NULL, NULL, NULL)))
|
|
{
|
|
char szBuff[_MAX_PATH];
|
|
|
|
sprintf(szBuff, "Could not get endpoint for property %S", bstrPropertyName);
|
|
|
|
if (g_bWarningContinue)
|
|
{
|
|
PrintError(szBuff, hr, g_dwErrorFlags);
|
|
}
|
|
else if (g_bWarning)
|
|
{
|
|
PrintErrorAndAsk(szBuff, hr, g_dwErrorFlags); // might exit program
|
|
}
|
|
else
|
|
{
|
|
PrintErrorAndExit(szBuff, hr, g_dwErrorFlags); // will exit program
|
|
}
|
|
}
|
|
}
|
|
|
|
SysFreeString(bstrPropertyName);
|
|
vVal.Clear();
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Function: CtrlHandler
|
|
// Purpose: Checks to see if the references pointed to by the reference
|
|
// properties of this class really exist.
|
|
//*****************************************************************************
|
|
BOOL CtrlHandler(DWORD fdwCtrlType)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
switch (fdwCtrlType)
|
|
{
|
|
// Handle the CTRL+C signal.
|
|
|
|
case CTRL_CLOSE_EVENT:
|
|
case CTRL_C_EVENT:
|
|
{
|
|
g_bExit = true;
|
|
bRet = TRUE;
|
|
}
|
|
|
|
// Pass other signals to the next handler.
|
|
|
|
case CTRL_BREAK_EVENT:
|
|
case CTRL_LOGOFF_EVENT:
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
default:
|
|
{
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Class: QuerySink
|
|
// Purpose: Generic class to be used as the sink to wbem's async functions
|
|
//*****************************************************************************
|
|
QuerySink::QuerySink()
|
|
{
|
|
m_lRef = 1;
|
|
m_hResult = S_OK;
|
|
m_hDone = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
}
|
|
|
|
QuerySink::~QuerySink()
|
|
{
|
|
CloseHandle(m_hDone);
|
|
}
|
|
|
|
ULONG QuerySink::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_lRef);
|
|
}
|
|
|
|
ULONG QuerySink::Release()
|
|
{
|
|
LONG lRef = InterlockedDecrement(&m_lRef);
|
|
if(lRef == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
return lRef;
|
|
}
|
|
|
|
HRESULT QuerySink::QueryInterface(REFIID riid, void** ppv)
|
|
{
|
|
if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
|
|
{
|
|
*ppv = (IWbemObjectSink *) this;
|
|
AddRef();
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
|
|
HRESULT QuerySink::SetStatus(
|
|
/* [in] */ LONG lFlags,
|
|
/* [in] */ HRESULT hResult,
|
|
/* [in] */ BSTR strParam,
|
|
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
|
|
)
|
|
{
|
|
UNREFERENCED(pObjParam);
|
|
UNREFERENCED(strParam);
|
|
|
|
if (WBEM_STATUS_COMPLETE == lFlags)
|
|
{
|
|
m_hResult = hResult;
|
|
SetEvent(m_hDone);
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Class: InstanceQuerySink (derives from QuerySink)
|
|
// Purpose: processes instances sent back from ExecQueryAsync
|
|
// and CreateInstanceEnumAsync
|
|
//*****************************************************************************
|
|
InstanceQuerySink::InstanceQuerySink(IWbemServices *pIWbemServices, LPCWSTR pwszClassName) : QuerySink()
|
|
{
|
|
m_pIWbemServices = pIWbemServices;
|
|
m_pwszClassName = pwszClassName;
|
|
m_bFirst = true;
|
|
}
|
|
|
|
InstanceQuerySink::~InstanceQuerySink()
|
|
{
|
|
}
|
|
|
|
HRESULT InstanceQuerySink::Indicate(long lObjCount, IWbemClassObject **pArray)
|
|
{
|
|
for (long i = 0; i < lObjCount; i++)
|
|
{
|
|
IWbemClassObject *pObj = pArray[i];
|
|
|
|
if (m_pwszClassName != NULL)
|
|
{
|
|
if (!m_bFirst)
|
|
{
|
|
ShowInstanceHeader(m_pwszClassName);
|
|
}
|
|
else
|
|
{
|
|
m_bFirst = false;
|
|
}
|
|
}
|
|
|
|
ShowInstance(m_pIWbemServices, pObj);
|
|
m_dwCount++;
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Class: ClassQuerySink (derives from QuerySink)
|
|
// Purpose: processes classes sent back from CreateClassEnum
|
|
//*****************************************************************************
|
|
ClassQuerySink::ClassQuerySink(IWbemServices *pIWbemServices) : QuerySink()
|
|
{
|
|
m_pIWbemServices = pIWbemServices;
|
|
}
|
|
|
|
ClassQuerySink::~ClassQuerySink()
|
|
{
|
|
}
|
|
|
|
HRESULT ClassQuerySink::Indicate(long lObjCount, IWbemClassObject **pArray)
|
|
{
|
|
for (long i = 0; i < lObjCount; i++)
|
|
{
|
|
IWbemClassObject *pObj = pArray[i];
|
|
|
|
ShowClass(m_pIWbemServices, pObj);
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|