You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
734 lines
20 KiB
734 lines
20 KiB
#include "testwmi.h"
|
|
|
|
//
|
|
// The function connects to the namespace.
|
|
//
|
|
|
|
IWbemServices *ConnectToNamespace (VOID)
|
|
{
|
|
IWbemServices *pIWbemServices = NULL;
|
|
IWbemLocator *pIWbemLocator = NULL;
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Create an instance of WbemLocator interface.
|
|
//
|
|
|
|
hr = CoCreateInstance( CLSID_WbemLocator,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(LPVOID *)&pIWbemLocator );
|
|
if ( hr == S_OK ) {
|
|
|
|
//
|
|
// Using the locator, connect to COM in the given namespace.
|
|
//
|
|
|
|
hr = pIWbemLocator->ConnectServer( (BSTR)((PVOID)DEFAULT_NAMESPACE),
|
|
NULL, // current account.
|
|
NULL, // current password.
|
|
0L, // locale
|
|
0L, // securityFlags
|
|
NULL, // domain for NTLM
|
|
NULL, // context
|
|
&pIWbemServices );
|
|
|
|
if ( hr == WBEM_S_NO_ERROR) {
|
|
|
|
//
|
|
// Switch the security level to IMPERSONATE so that provider(s)
|
|
// will grant access to system-level objects, and so that
|
|
// CALL authorization will be used.
|
|
//
|
|
|
|
hr = CoSetProxyBlanket( (IUnknown *)pIWbemServices, // proxy
|
|
RPC_C_AUTHN_WINNT, // authentication service
|
|
RPC_C_AUTHZ_NONE, // authorization service
|
|
NULL, // server principle name
|
|
RPC_C_AUTHN_LEVEL_CALL, // authentication level
|
|
RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation
|
|
NULL, // identity of the client
|
|
EOAC_NONE ); // capability flags
|
|
|
|
if ( hr != S_OK ) {
|
|
|
|
pIWbemServices->Release();
|
|
pIWbemServices = NULL;
|
|
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't impersonate, program exiting...") );
|
|
}
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't connect to root\\wmi, program exiting...") );
|
|
}
|
|
|
|
//
|
|
// Done with IWbemLocator.
|
|
//
|
|
|
|
pIWbemLocator->Release();
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't create an instance of ")
|
|
TEXT("IWbemLocator interface, programm exiting...") );
|
|
}
|
|
|
|
return pIWbemServices;
|
|
}
|
|
|
|
//
|
|
// Given a class name, the function populates the combo box with all
|
|
// the instances of the class.
|
|
//
|
|
|
|
VOID EnumInstances (IWbemServices *pIWbemServices,
|
|
LPTSTR lpszClass,
|
|
HWND hwndInstTree)
|
|
{
|
|
IEnumWbemClassObject *pEnumInst;
|
|
IWbemClassObject *pInst;
|
|
VARIANT varInstanceName;
|
|
BSTR bstrClass;
|
|
LPTSTR lpszInstance;
|
|
ULONG ulFound;
|
|
HRESULT hr;
|
|
|
|
|
|
bstrClass = StringToBstr( lpszClass,
|
|
-1 );
|
|
if ( !bstrClass ) {
|
|
|
|
PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Not enough memory to enumerate instances of %s"),
|
|
lpszClass );
|
|
|
|
return;
|
|
}
|
|
|
|
hr = pIWbemServices->CreateInstanceEnum(
|
|
bstrClass, // Name of the root class.
|
|
WBEM_FLAG_SHALLOW | // Enumerate at current root only.
|
|
WBEM_FLAG_FORWARD_ONLY, // Forward-only enumeration.
|
|
NULL, // Context.
|
|
&pEnumInst ); // pointer to class enumerator
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
|
|
//
|
|
// Begin enumerating instances.
|
|
//
|
|
|
|
ulFound = 0;
|
|
|
|
hr = pEnumInst->Next( 2000, // two seconds timeout
|
|
1, // return just one instance.
|
|
&pInst, // pointer to instance.
|
|
&ulFound); // Number of instances returned.
|
|
|
|
while ( (hr == WBEM_S_NO_ERROR) && (ulFound == 1) ) {
|
|
|
|
VariantInit( &varInstanceName );
|
|
|
|
//
|
|
// Get the instance name stored in __RELPATH property.
|
|
//
|
|
|
|
hr = pInst->Get( L"__RELPATH", // property name
|
|
0L, // Reserved, must be zero.
|
|
&varInstanceName, // property value returned.
|
|
NULL, // CIM type not needed.
|
|
NULL ); // Flavor not needed.
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
|
|
lpszInstance = BstrToString( V_BSTR(&varInstanceName),
|
|
-1 );
|
|
if ( lpszInstance ) {
|
|
|
|
InsertItem( hwndInstTree,
|
|
lpszInstance );
|
|
|
|
SysFreeString( (BSTR)((PVOID)lpszInstance) );
|
|
}
|
|
else {
|
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Out of memory while enumerating instaces of")
|
|
TEXT(" %s, no more instances will")
|
|
TEXT(" be listed."),
|
|
lpszClass );
|
|
}
|
|
|
|
VariantClear( &varInstanceName );
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't retrieve __RELPATH of an instance")
|
|
TEXT(" of %s, no more instances will be listed."),
|
|
lpszClass );
|
|
}
|
|
|
|
//
|
|
// Done with this instance.
|
|
//
|
|
|
|
pInst->Release();
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
|
|
hr = pEnumInst->Next( 2000, // two seconds timeout.
|
|
1, // return just one class.
|
|
&pInst, // pointer to returned class.
|
|
&ulFound); // Number of classes returned.
|
|
}
|
|
}
|
|
|
|
pEnumInst->Release();
|
|
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't create an instance of ")
|
|
TEXT("IEnumWbemClassObject interface, instances of %s ")
|
|
TEXT("will not be listed."),
|
|
lpszClass );
|
|
}
|
|
|
|
SysFreeString( bstrClass );
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Given a class name and __RELPATH of an instance, the function lists all the
|
|
// local non-system properties in a tree list.
|
|
//
|
|
|
|
VOID EnumProperties (IWbemServices *pIWbemServices,
|
|
LPTSTR lpszClass,
|
|
LPTSTR lpszInstance,
|
|
HWND hwndPropTree)
|
|
{
|
|
IWbemClassObject *pInst;
|
|
SAFEARRAY *psaPropNames;
|
|
BSTR bstrProperty;
|
|
long lLower;
|
|
long lUpper;
|
|
long i;
|
|
HRESULT hr;
|
|
LPTSTR lpszProperty;
|
|
|
|
//
|
|
// Get a pointer to the instance.
|
|
//
|
|
|
|
pInst = GetInstanceReference( pIWbemServices,
|
|
lpszClass,
|
|
lpszInstance );
|
|
|
|
if ( pInst ) {
|
|
|
|
//
|
|
// psaPropNames must be null prior to making the call.
|
|
//
|
|
|
|
psaPropNames = NULL;
|
|
|
|
//
|
|
// Get all the properties.
|
|
//
|
|
|
|
hr = pInst->GetNames( NULL, // No qualifier names.
|
|
WBEM_FLAG_ALWAYS | // All non-system properties
|
|
WBEM_FLAG_LOCAL_ONLY,
|
|
NULL, // No qualifier values.
|
|
&psaPropNames); // Returned property names
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
|
|
//
|
|
// Get the number of properties returned.
|
|
//
|
|
|
|
SafeArrayGetLBound( psaPropNames, 1, &lLower );
|
|
SafeArrayGetUBound( psaPropNames, 1, &lUpper );
|
|
|
|
//
|
|
// List all properties or stop when encountered an error.
|
|
//
|
|
|
|
for (i=lLower; (hr == WBEM_S_NO_ERROR) && (i <= lUpper); i++) {
|
|
|
|
//
|
|
// Add the property name into the list box.
|
|
//
|
|
|
|
bstrProperty = NULL;
|
|
|
|
hr = SafeArrayGetElement( psaPropNames,
|
|
&i,
|
|
&bstrProperty);
|
|
|
|
if ( SUCCEEDED(hr) ) {
|
|
|
|
lpszProperty = BstrToString( bstrProperty,
|
|
-1 );
|
|
|
|
if ( lpszProperty ) {
|
|
|
|
InsertItem( hwndPropTree,
|
|
lpszProperty );
|
|
|
|
SysFreeString( (BSTR)((PVOID)lpszProperty) );
|
|
}
|
|
else {
|
|
PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Out of memory while enumerating")
|
|
TEXT(" properties of %s, no more properties")
|
|
TEXT(" will be listed"),
|
|
lpszInstance );
|
|
}
|
|
|
|
//
|
|
// Done with the property name.
|
|
//
|
|
|
|
SysFreeString( bstrProperty );
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't get the name of a property(%d). ")
|
|
TEXT("No more properties will be listed."),
|
|
i );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Done with the array of properties.
|
|
//
|
|
|
|
SafeArrayDestroy( psaPropNames );
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't retrieve the properties of %s, ")
|
|
TEXT("an instance of class %s. Properties will not be ")
|
|
TEXT("listed."),
|
|
lpszInstance, lpszClass );
|
|
}
|
|
|
|
}
|
|
else {
|
|
PrintError( HRESULT_FROM_WIN32(ERROR_WMI_INSTANCE_NOT_FOUND),
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't retrieve a pointer to instance %s of class %s.")
|
|
TEXT("Its properties will not be listed."),
|
|
lpszInstance, lpszClass );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Given a class name and __RELPATH of an instance, the function returns a
|
|
// pointer to the instance.
|
|
//
|
|
|
|
IWbemClassObject *GetInstanceReference (IWbemServices *pIWbemServices,
|
|
LPTSTR lpszClass,
|
|
LPTSTR lpszInstance)
|
|
{
|
|
IWbemClassObject *pInst;
|
|
IEnumWbemClassObject *pEnumInst;
|
|
ULONG ulCount;
|
|
BSTR bstrClass;
|
|
BOOL bFound;
|
|
HRESULT hr;
|
|
|
|
|
|
hr = 0;
|
|
|
|
bstrClass = StringToBstr( lpszClass,
|
|
-1 );
|
|
if ( !bstrClass ) {
|
|
|
|
PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Not enough memory to get a pointer to %s."),
|
|
lpszInstance );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// pInst pointer must be NULL initially,
|
|
//
|
|
|
|
pInst = NULL;
|
|
|
|
//
|
|
// Get Instance Enumerator Interface.
|
|
//
|
|
|
|
pEnumInst = NULL;
|
|
|
|
hr = pIWbemServices->CreateInstanceEnum(bstrClass,
|
|
WBEM_FLAG_SHALLOW |
|
|
WBEM_FLAG_FORWARD_ONLY,
|
|
NULL,
|
|
&pEnumInst );
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
|
|
//
|
|
// Get a pointer to the instance.
|
|
//
|
|
// We enumerate all the instances and compare their __RELPATH with
|
|
// the specified __RELPATH. If we find a match then, that is the one
|
|
// we are looking for.
|
|
//
|
|
// The other more efficient way is to create a WQL query and execute
|
|
// it.
|
|
//
|
|
|
|
hr = WBEM_S_NO_ERROR;
|
|
bFound = FALSE;
|
|
|
|
while ( (hr == WBEM_S_NO_ERROR) && (bFound == FALSE) ) {
|
|
|
|
hr = pEnumInst->Next( 2000, // two seconds timeout
|
|
1, // return just one instance.
|
|
&pInst, // pointer to instance.
|
|
&ulCount); // Number of instances returned.
|
|
|
|
if ( ulCount > 0 ) {
|
|
|
|
bFound = IsInstance( pInst,
|
|
lpszInstance );
|
|
|
|
if ( bFound == FALSE ) {
|
|
pInst->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( bFound == FALSE )
|
|
pInst = NULL;
|
|
|
|
//
|
|
// Done with the instance enumerator.
|
|
//
|
|
|
|
pEnumInst->Release();
|
|
}
|
|
|
|
SysFreeString( bstrClass );
|
|
return pInst;
|
|
}
|
|
|
|
//
|
|
// Given a pointer, the function returns TRUE if the pointer points to
|
|
// the instance specified by lpszInstance.
|
|
//
|
|
|
|
BOOL IsInstance (IWbemClassObject *pInst,
|
|
LPTSTR lpszInstance)
|
|
{
|
|
VARIANT varPropVal;
|
|
LPTSTR lpInstance;
|
|
BOOL bRet;
|
|
|
|
bRet = GetPropertyValue( pInst,
|
|
TEXT("__RELPATH"),
|
|
&varPropVal,
|
|
NULL );
|
|
|
|
if ( bRet == TRUE ) {
|
|
|
|
lpInstance = BstrToString( V_BSTR(&varPropVal),
|
|
-1 );
|
|
if ( !lpInstance ) {
|
|
|
|
PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Not enough memory to search for an instance.") );
|
|
|
|
bRet = FALSE;
|
|
}
|
|
else {
|
|
bRet = _tcsicmp( lpszInstance, lpInstance ) == 0;
|
|
|
|
SysFreeString( (BSTR)((PVOID)lpInstance) );
|
|
}
|
|
|
|
VariantClear( &varPropVal );
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//
|
|
// The function returns property value and its type of a given class/instance.
|
|
//
|
|
|
|
BOOL GetPropertyValue (IWbemClassObject *pRef,
|
|
LPTSTR lpszProperty,
|
|
VARIANT *pvaPropertyValue,
|
|
LPTSTR *lppszPropertyType)
|
|
{
|
|
IWbemQualifierSet *pQual;
|
|
VARIANT vaQual;
|
|
BSTR bstrProperty;
|
|
HRESULT hr;
|
|
BOOL bRet;
|
|
|
|
|
|
//
|
|
// Get the property value.
|
|
//
|
|
|
|
bstrProperty = StringToBstr( lpszProperty,
|
|
-1 );
|
|
|
|
if ( !bstrProperty ) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
bRet = FALSE;
|
|
|
|
if ( lppszPropertyType ) {
|
|
|
|
//
|
|
// Get the textual name of the property type.
|
|
//
|
|
|
|
hr = pRef->GetPropertyQualifierSet( bstrProperty,
|
|
&pQual );
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
|
|
//
|
|
// Get the textual name of the property type.
|
|
//
|
|
|
|
hr = pQual->Get( L"CIMTYPE",
|
|
0,
|
|
&vaQual,
|
|
NULL );
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
*lppszPropertyType = BstrToString( V_BSTR(&vaQual),
|
|
-1 );
|
|
|
|
VariantClear( &vaQual );
|
|
}
|
|
|
|
pQual->Release();
|
|
}
|
|
}
|
|
|
|
VariantInit( pvaPropertyValue );
|
|
|
|
hr = pRef->Get( bstrProperty,
|
|
0,
|
|
pvaPropertyValue,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
bRet = TRUE;
|
|
}
|
|
else {
|
|
if ( lppszPropertyType && *lppszPropertyType ) {
|
|
SysFreeString( (BSTR)((PVOID)*lppszPropertyType) );
|
|
}
|
|
}
|
|
|
|
SysFreeString( bstrProperty );
|
|
return bRet;
|
|
}
|
|
|
|
//
|
|
// Given a pointer to an instance, its property and and variant specifying
|
|
// the value for the property, the function updates the property and the
|
|
// instance.
|
|
//
|
|
|
|
HRESULT UpdatePropertyValue (IWbemServices *pIWbemServices,
|
|
IWbemClassObject *pInstance,
|
|
LPTSTR lpszProperty,
|
|
LPVARIANT pvaNewValue)
|
|
{
|
|
BSTR bstrProperty;
|
|
HRESULT hr;
|
|
|
|
|
|
bstrProperty = StringToBstr( lpszProperty,
|
|
-1 );
|
|
|
|
if ( !bstrProperty ) {
|
|
|
|
PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Not enough memory to update %s."),
|
|
lpszProperty );
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
hr = pInstance->Put( bstrProperty,
|
|
0,
|
|
pvaNewValue,
|
|
0 );
|
|
|
|
if ( hr == WBEM_S_NO_ERROR ) {
|
|
hr = pIWbemServices->PutInstance( pInstance,
|
|
WBEM_FLAG_UPDATE_ONLY,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( hr != WBEM_S_NO_ERROR ) {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Failed to save the instance,")
|
|
TEXT(" %s will not be updated."),
|
|
lpszProperty );
|
|
}
|
|
}
|
|
else {
|
|
PrintError( hr,
|
|
__LINE__,
|
|
TEXT(__FILE__),
|
|
TEXT("Couldn't update %s."),
|
|
lpszProperty );
|
|
}
|
|
|
|
SysFreeString( bstrProperty );
|
|
|
|
return hr;
|
|
}
|
|
|
|
BSTR StringToBstr (LPTSTR lpSrc,
|
|
int nLenSrc)
|
|
{
|
|
BSTR lpDest;
|
|
|
|
//
|
|
// In case of ANSI version, we need to change the ANSI string to UNICODE since
|
|
// BSTRs are essentially UNICODE strings.
|
|
//
|
|
|
|
#if !defined(UNICODE) || !defined(_UNICODE)
|
|
|
|
int nLenDest;
|
|
|
|
nLenDest = MultiByteToWideChar( CP_ACP, 0, lpSrc, nLenSrc, NULL, 0);
|
|
|
|
lpDest = SysAllocStringLen( NULL, nLenDest );
|
|
|
|
if ( lpDest ) {
|
|
MultiByteToWideChar( CP_ACP, 0, lpSrc, nLenSrc, lpDest, nLenDest );
|
|
}
|
|
|
|
//
|
|
// In case of UNICODE version, we simply allocate memory and copy the string.
|
|
//
|
|
|
|
#else
|
|
if ( lpSrc == NULL ) {
|
|
nLenSrc = 0;
|
|
}
|
|
else {
|
|
if ( nLenSrc == -1 ) {
|
|
nLenSrc = _tcslen( lpSrc ) + 1;
|
|
}
|
|
}
|
|
|
|
lpDest = SysAllocStringLen( lpSrc, nLenSrc );
|
|
#endif
|
|
|
|
return lpDest;
|
|
}
|
|
|
|
//
|
|
// The function converts a BSTR string into ANSI and returns it in an allocated
|
|
// memory. The memory must be freed by the caller using SysFreeString()
|
|
// function. If nLenSrc is -1, the string is null terminated.
|
|
//
|
|
|
|
LPTSTR BstrToString (BSTR lpSrc,
|
|
int nLenSrc)
|
|
{
|
|
LPTSTR lpDest;
|
|
|
|
//
|
|
// In case of ANSI version, we need to change BSTRs which are UNICODE strings
|
|
// into ANSI version.
|
|
//
|
|
|
|
#if !defined(UNICODE) || !defined(_UNICODE)
|
|
|
|
int nLenDest;
|
|
|
|
nLenDest = WideCharToMultiByte( CP_ACP, 0, lpSrc, nLenSrc, NULL,
|
|
0, NULL, NULL );
|
|
lpDest = (LPTSTR)SysAllocStringLen( NULL, (size_t)nLenDest );
|
|
|
|
if ( lpDest ) {
|
|
WideCharToMultiByte( CP_ACP, 0, lpSrc, nLenSrc, lpDest,
|
|
nLenDest, NULL, NULL );
|
|
}
|
|
//
|
|
// In case of UNICODE version, we simply allocate memory and copy the BSTR
|
|
// into allocate memory and return its address.
|
|
//
|
|
|
|
#else
|
|
if ( lpSrc ) {
|
|
if ( nLenSrc == -1 ) {
|
|
nLenSrc = _tcslen( lpSrc ) + 1;
|
|
}
|
|
}
|
|
else {
|
|
nLenSrc = 0;
|
|
}
|
|
|
|
lpDest = (LPTSTR)SysAllocStringLen( lpSrc, nLenSrc );
|
|
#endif
|
|
|
|
return lpDest;
|
|
}
|