493 lines
12 KiB
C++
493 lines
12 KiB
C++
/*++
|
|
|
|
Copyright (C) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// REFRESH.CPP
|
|
//
|
|
// Contains a single sample global refresher
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#include <stdio.h>
|
|
#include <wbemidl.h>
|
|
|
|
#include <wbemint.h>
|
|
|
|
#include "refresh.h"
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Local globals (!)
|
|
//
|
|
//***************************************************************************
|
|
|
|
static DWORD g_dwNumObjects = 0;
|
|
static IWbemRefresher *g_pRefresher = 0;
|
|
|
|
static IWbemClassObject *g_aObjects[MAX_OBJECTS];
|
|
static LONG g_aObjIDs[MAX_OBJECTS];
|
|
|
|
static IWbemConfigureRefresher *g_pCfgRef = 0;
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CreateRefresher
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CreateRefresher()
|
|
{
|
|
if (g_pCfgRef != 0)
|
|
{
|
|
printf("Refresher already created\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Create an empty refresher.
|
|
// ===========================
|
|
|
|
DWORD dwRes = CoCreateInstance(CLSID_WbemRefresher, 0, CLSCTX_SERVER,
|
|
IID_IWbemRefresher, (LPVOID *) &g_pRefresher);
|
|
|
|
if (dwRes != S_OK)
|
|
{
|
|
printf("Failed to create a new refresher.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Create the refresher manager.
|
|
// =============================
|
|
|
|
dwRes = g_pRefresher->QueryInterface(IID_IWbemConfigureRefresher,
|
|
(LPVOID *) &g_pCfgRef);
|
|
|
|
|
|
if (dwRes)
|
|
{
|
|
g_pRefresher->Release();
|
|
g_pRefresher = 0;
|
|
printf("Failed to create the refresher manager\n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Refresh
|
|
//
|
|
// Called to refresh all the objects in the refresher.
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
|
|
BOOL Refresh()
|
|
{
|
|
if (g_pRefresher == 0)
|
|
{
|
|
printf("No active refresher!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT hRes = g_pRefresher->Refresh(0);
|
|
if (hRes)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DestroyRefresher
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
|
|
BOOL DestroyRefresher()
|
|
{
|
|
if (g_pRefresher == 0)
|
|
{
|
|
printf("No active refresher!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
g_pRefresher->Release();
|
|
g_pRefresher = 0;
|
|
|
|
g_pCfgRef->Release();
|
|
g_pCfgRef = 0;
|
|
|
|
for (DWORD i = 0; i < g_dwNumObjects; i++)
|
|
{
|
|
g_aObjIDs[i] = 0;
|
|
g_aObjects[i]->Release();
|
|
g_aObjects[i] = 0;
|
|
}
|
|
|
|
g_dwNumObjects = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// AddObject
|
|
//
|
|
// Adds an object to the refresher and returns its ID. The ID is
|
|
// refresher specific (if more than one refresher is used, the
|
|
// IDs can overlap).
|
|
//
|
|
// Parameters:
|
|
// pSvc IWbemServices pointing to the correct namespace
|
|
// pszPath The path to the object
|
|
//
|
|
// Return value:
|
|
// TRUE on success, FALSE on fail.
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
|
|
BOOL AddObject(
|
|
IN IWbemServices *pSvc,
|
|
IN LPWSTR pszPath
|
|
)
|
|
{
|
|
LONG lObjId;
|
|
|
|
if (g_pRefresher == 0)
|
|
{
|
|
printf("No active refresher!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Make sure there is room.
|
|
// ========================
|
|
|
|
if (g_dwNumObjects == MAX_OBJECTS)
|
|
{
|
|
printf("No more room in object array\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Add the object to the refresher.
|
|
// =================================
|
|
|
|
IWbemClassObject *pRefreshableCopy = 0;
|
|
|
|
HRESULT hRes = g_pCfgRef->AddObjectByPath(
|
|
pSvc,
|
|
pszPath,
|
|
0,
|
|
0,
|
|
&pRefreshableCopy,
|
|
&lObjId
|
|
);
|
|
|
|
// See if we succeeded.
|
|
// ====================
|
|
if (hRes)
|
|
{
|
|
printf("Failed to add object %S to refresher. WBEM error code = 0x%X\n",
|
|
pszPath,
|
|
hRes
|
|
);
|
|
return FALSE;
|
|
}
|
|
|
|
// Record the object and its id.
|
|
// =============================
|
|
g_aObjects[g_dwNumObjects] = pRefreshableCopy;
|
|
g_aObjIDs[g_dwNumObjects] = lObjId;
|
|
|
|
g_dwNumObjects++; // Keeps track of how many objects we have
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RemoveObject
|
|
//
|
|
// Removes an object from the refresher.
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
|
|
BOOL RemoveObject(IN LONG lObjId)
|
|
{
|
|
if (g_pRefresher == 0)
|
|
{
|
|
printf("No active refresher!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Remove the obejct from our local bookkeeping.
|
|
// =============================================
|
|
|
|
for (DWORD i = 0; i < g_dwNumObjects; i++)
|
|
{
|
|
if (g_aObjIDs[i] == lObjId)
|
|
{
|
|
g_aObjIDs[i] = 0; // Remove the ID
|
|
g_aObjects[i]->Release(); // Release the object
|
|
g_aObjects[i] = 0; // Zero it for purity
|
|
|
|
// Remove this element from the two arrays.
|
|
// ========================================
|
|
|
|
for (DWORD i2 = i; i2 < g_dwNumObjects - 1; i2++)
|
|
{
|
|
g_aObjIDs[i2] = g_aObjIDs[i2 + 1];
|
|
g_aObjects[i2] = g_aObjects[i2 + 1];
|
|
}
|
|
|
|
g_dwNumObjects--;
|
|
}
|
|
}
|
|
|
|
// Officially remove the object from the WBEM refresher.
|
|
// =====================================================
|
|
|
|
HRESULT hRes = g_pCfgRef->Remove(
|
|
lObjId,
|
|
0
|
|
);
|
|
|
|
if (hRes)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// ShowObjectList
|
|
//
|
|
// Shows all the objects in the refresher.
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL ShowObjectList()
|
|
{
|
|
if (g_pRefresher == 0)
|
|
{
|
|
printf("No active refresher!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
BSTR PropName = SysAllocString(L"__RELPATH");
|
|
|
|
for (DWORD i = 0; i < g_dwNumObjects; i++)
|
|
{
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
g_aObjects[i]->Get(PropName, 0, &v, 0, 0);
|
|
|
|
printf("Object ID = %u Path = %S\n", g_aObjIDs[i], V_BSTR(&v));
|
|
|
|
VariantClear(&v);
|
|
}
|
|
|
|
SysFreeString(PropName);
|
|
|
|
printf("---Total of %u object(s)\n", g_dwNumObjects);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DumpObjectById
|
|
//
|
|
// Dumps the object's contents.
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL DumpObjectById(LONG lObjId)
|
|
{
|
|
for (DWORD i = 0; i < g_dwNumObjects; i++)
|
|
{
|
|
if (g_aObjIDs[i] == lObjId)
|
|
{
|
|
DumpObject(g_aObjects[i]);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DumpObject
|
|
//
|
|
// Dumps out the contents of the object.
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL DumpObject(IWbemClassObject *pObj)
|
|
{
|
|
DWORD i;
|
|
BSTR PropNames[64] = {0};
|
|
DWORD dwNumPropNames = 0;
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
|
|
printf("----Object Dump----\n");
|
|
|
|
// Print out the object path to identify it.
|
|
// =========================================
|
|
|
|
BSTR PropName = SysAllocString(L"__RELPATH");
|
|
|
|
pObj->Get(PropName, 0, &v, 0, 0);
|
|
printf("Path = %S\n", V_BSTR(&v));
|
|
|
|
VariantClear(&v);
|
|
SysFreeString(PropName);
|
|
|
|
// Enumerate through the 'real' properties, ignoring
|
|
// standard WBEM system properties.
|
|
// =================================================
|
|
|
|
pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
|
|
|
|
BSTR bstrName = 0;
|
|
LONG vt = 0;
|
|
|
|
while (WBEM_NO_ERROR == pObj->Next(0, &bstrName, &v, &vt, 0))
|
|
{
|
|
printf("Property = %S\t", bstrName);
|
|
|
|
PropNames[dwNumPropNames++] = bstrName; // Save the name for later use
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_I4:
|
|
printf("\tType = VT_I4\tValue = %d\n", V_I4(&v));
|
|
break;
|
|
|
|
case VT_UI4:
|
|
printf("\tType = VT_UI4\tValue = %u\n", V_I4(&v));
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
printf("\tType = VT_BSTR\tValue = %S\n", V_BSTR(&v));
|
|
break;
|
|
|
|
// Note that VARIANTs can't hold 64-bit integers,
|
|
// so we have to use BSTRs for this.
|
|
// ==============================================
|
|
|
|
case VT_I8:
|
|
printf("\tType = VT_I8\tValue = %S\n", V_BSTR(&v));
|
|
break;
|
|
|
|
case VT_UI8:
|
|
printf("\tType = VT_UI8\tValue = %S\n", V_BSTR(&v));
|
|
break;
|
|
|
|
default:
|
|
printf("\tType = complex\n");
|
|
}
|
|
|
|
}
|
|
|
|
pObj->EndEnumeration();
|
|
|
|
|
|
// Next, we can get the property values if we know the names
|
|
// ahead of time through a more efficient access mechanism.
|
|
// Since we saved all the property names, we can use these
|
|
// to get handles to the properties of interest. In this
|
|
// case, we get handles for all the properties. In real life,
|
|
// you would just use this for properties of interest to
|
|
// the end user.
|
|
// ==========================================================
|
|
|
|
IWbemObjectAccess *pAccess = 0;
|
|
pObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pAccess);
|
|
|
|
LONG Handles[64] = {0};
|
|
LONG Types[64] = {0};
|
|
|
|
for (i = 0; i < dwNumPropNames; i++)
|
|
{
|
|
// Get handles for each of the properties. We actually
|
|
// only have to do this once and could reuse the handles
|
|
// in the future between refreshes for all instances of
|
|
// this class.
|
|
// =====================================================
|
|
|
|
pAccess->GetPropertyHandle(PropNames[i], &Types[i], &Handles[i]);
|
|
}
|
|
|
|
|
|
// We can now pull in the values by the handles.
|
|
// Note that these handles can be 'saved' for use
|
|
// with other instances or a newly refreshed generation
|
|
// of the same instance.
|
|
// =====================================================
|
|
|
|
DWORD dwValue;
|
|
unsigned __int64 qwValue;
|
|
|
|
for (i = 0; i < dwNumPropNames; i++)
|
|
{
|
|
|
|
switch (Types[i])
|
|
{
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
pAccess->ReadDWORD(Handles[i], &dwValue);
|
|
printf("Property %S has value %u\n", PropNames[i], dwValue);
|
|
break;
|
|
|
|
case VT_I8:
|
|
case VT_UI8:
|
|
pAccess->ReadQWORD(Handles[i], &qwValue);
|
|
printf("Property %S has value %lu\n", PropNames[i], qwValue);
|
|
break;
|
|
|
|
// Other types
|
|
// ===========
|
|
default:
|
|
printf("Property %S is Non integral type.\n", PropNames[i]);
|
|
// We could have used pAccess->ReadPropertyValue for this.
|
|
}
|
|
}
|
|
|
|
|
|
// Done with the dump. Cleanup time.
|
|
// ==================================
|
|
|
|
pAccess->Release(); // Done with this interface
|
|
|
|
for (i = 0; i < dwNumPropNames; i++)
|
|
SysFreeString(PropNames[i]); // Free prop names
|
|
|
|
// Go home.
|
|
// ========
|
|
|
|
return TRUE;
|
|
}
|