1719 lines
46 KiB
C++
1719 lines
46 KiB
C++
|
// *********************************************************************************
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation
|
||
|
//
|
||
|
// Module Name:
|
||
|
//
|
||
|
// WMI.cpp
|
||
|
//
|
||
|
// Abstract:
|
||
|
//
|
||
|
// Common functionlity for dealing with WMI
|
||
|
//
|
||
|
// Author:
|
||
|
//
|
||
|
// Sunil G.V.N. Murali (murali.sunil@wipro.com) 22-Dec-2000
|
||
|
//
|
||
|
// Revision History:
|
||
|
//
|
||
|
// Sunil G.V.N. Murali (murali.sunil@wipro.com) 22-Dec-2000 : Created It.
|
||
|
//
|
||
|
// *********************************************************************************
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "wmi.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
//
|
||
|
// messages
|
||
|
//
|
||
|
#define INPUT_PASSWORD GetResString( IDS_STR_INPUT_PASSWORD )
|
||
|
|
||
|
// error constants
|
||
|
#define E_SERVER_NOTFOUND 0x800706ba
|
||
|
|
||
|
//
|
||
|
// private function prototype(s)
|
||
|
//
|
||
|
BOOL IsValidUserEx( LPCWSTR pwszUser );
|
||
|
HRESULT GetSecurityArguments( IUnknown* pInterface,
|
||
|
DWORD& dwAuthorization, DWORD& dwAuthentication );
|
||
|
HRESULT SetInterfaceSecurity( IUnknown* pInterface,
|
||
|
LPCWSTR pwszServer, LPCWSTR pwszUser,
|
||
|
LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity );
|
||
|
HRESULT WINAPI SetProxyBlanket( IUnknown* pInterface,
|
||
|
DWORD dwAuthnSvc, DWORD dwAuthzSvc,
|
||
|
LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
|
||
|
RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities );
|
||
|
HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
|
||
|
LPCWSTR pwszDomain, COAUTHIDENTITY** ppAuthIdent );
|
||
|
HRESULT RegQueryValueWMI( IWbemServices* pWbemServices,
|
||
|
LPCWSTR pwszMethod, DWORD dwHDefKey,
|
||
|
LPCWSTR pwszSubKeyName, LPCWSTR pwszValueName, _variant_t& varValue );
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL IsValidUserEx( LPCWSTR pwszUser )
|
||
|
{
|
||
|
// local variables
|
||
|
CHString strUser;
|
||
|
LONG lPos = 0;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get user into local memory
|
||
|
strUser = pwszUser;
|
||
|
|
||
|
// user name should not be just '\'
|
||
|
if ( strUser.CompareNoCase( L"\\" ) == 0 )
|
||
|
return FALSE;
|
||
|
|
||
|
// user name should not contain invalid characters
|
||
|
if ( strUser.FindOneOf( L"/[]:|<>+=;,?*" ) != -1 )
|
||
|
return FALSE;
|
||
|
|
||
|
// SPECIAL CHECK
|
||
|
// check for multiple '\' characters in the user name
|
||
|
lPos = strUser.Find( L'\\' );
|
||
|
if ( lPos != -1 )
|
||
|
{
|
||
|
// '\' character exists in the user name
|
||
|
// strip off the user info upto first '\' character
|
||
|
// check for one more '\' in the remaining string
|
||
|
// if it exists, invalid user
|
||
|
strUser = strUser.Mid( lPos + 1 );
|
||
|
lPos = strUser.Find( L'\\' );
|
||
|
if ( lPos != -1 )
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// user name is valid
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL IsValidServerEx( LPCWSTR pwszServer, BOOL& bLocalSystem )
|
||
|
{
|
||
|
// local variables
|
||
|
CHString strTemp;
|
||
|
|
||
|
// kick-off
|
||
|
bLocalSystem = FALSE;
|
||
|
|
||
|
// get a local copy
|
||
|
strTemp = pwszServer;
|
||
|
|
||
|
// remove the forward slashes (UNC) if exist in the begining of the server name
|
||
|
if ( IsUNCFormat( strTemp ) == TRUE )
|
||
|
{
|
||
|
strTemp = strTemp.Mid( 2 );
|
||
|
if ( strTemp.GetLength() == 0 )
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// now check if any '\' character appears in the server name. If so error
|
||
|
if ( strTemp.Find( L'\\' ) != -1 )
|
||
|
return FALSE;
|
||
|
|
||
|
// now check if server name is '.' only which represent local system in WMI
|
||
|
// else determine whether this is a local system or not
|
||
|
bLocalSystem = TRUE;
|
||
|
if ( strTemp.CompareNoCase( L"." ) != 0 )
|
||
|
{
|
||
|
// validate the server
|
||
|
if ( IsValidServer( strTemp ) == FALSE )
|
||
|
return FALSE;
|
||
|
|
||
|
// check whether this is a local system or not
|
||
|
bLocalSystem = IsLocalSystem( strTemp );
|
||
|
}
|
||
|
|
||
|
// inform that server name is valid
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL InitializeCom( IWbemLocator** ppLocator )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
BOOL bResult = FALSE;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// assume that connection to WMI namespace is failed
|
||
|
bResult = FALSE;
|
||
|
|
||
|
// initialize the COM library
|
||
|
SAFE_EXECUTE( CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ) );
|
||
|
|
||
|
// initialize the security
|
||
|
SAFE_EXECUTE( CoInitializeSecurity( NULL, -1, NULL, NULL,
|
||
|
RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0 ) );
|
||
|
|
||
|
// create the locator and get the pointer to the interface of IWbemLocator
|
||
|
SAFE_RELEASE( *ppLocator ); // safe side
|
||
|
SAFE_EXECUTE( CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
|
||
|
IID_IWbemLocator, ( LPVOID* ) ppLocator ) );
|
||
|
|
||
|
// initialization successful
|
||
|
bResult = TRUE;
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
// save the WMI error
|
||
|
WMISaveError( e );
|
||
|
}
|
||
|
|
||
|
// return the result;
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL ConnectWmi( IWbemLocator* pLocator,
|
||
|
IWbemServices** ppServices,
|
||
|
LPCWSTR pwszServer, LPCWSTR pwszUser, LPCWSTR pwszPassword,
|
||
|
COAUTHIDENTITY** ppAuthIdentity, BOOL bCheckWithNullPwd,
|
||
|
LPCWSTR pwszNamespace, HRESULT* phr, BOOL* pbLocalSystem )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
BOOL bResult = FALSE;
|
||
|
BOOL bLocalSystem = FALSE;
|
||
|
_bstr_t bstrServer;
|
||
|
_bstr_t bstrNamespace;
|
||
|
_bstr_t bstrUser, bstrPassword;
|
||
|
|
||
|
// kick-off
|
||
|
if ( pbLocalSystem != NULL )
|
||
|
*pbLocalSystem = FALSE;
|
||
|
|
||
|
// ...
|
||
|
if ( phr != NULL )
|
||
|
*phr = NO_ERROR;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// clear the error
|
||
|
SetLastError( WBEM_S_NO_ERROR );
|
||
|
|
||
|
// assume that connection to WMI namespace is failed
|
||
|
bResult = FALSE;
|
||
|
|
||
|
// check whether locator object exists or not
|
||
|
// if not exists, return
|
||
|
if ( pLocator == NULL )
|
||
|
{
|
||
|
if ( phr != NULL )
|
||
|
*phr = WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
// return failure
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// validate the server name
|
||
|
if ( IsValidServerEx( pwszServer, bLocalSystem ) == FALSE )
|
||
|
_com_issue_error( ERROR_BAD_NETPATH );
|
||
|
|
||
|
// validate the user name
|
||
|
if ( IsValidUserEx( pwszUser ) == FALSE )
|
||
|
_com_issue_error( ERROR_NO_SUCH_USER );
|
||
|
|
||
|
// prepare namespace
|
||
|
bstrNamespace = pwszNamespace; // name space
|
||
|
if ( pwszServer != NULL && bLocalSystem == FALSE )
|
||
|
{
|
||
|
// get the server name
|
||
|
bstrServer = pwszServer;
|
||
|
|
||
|
// prepare the namespace
|
||
|
// NOTE: check for the UNC naming format of the server and do
|
||
|
if ( IsUNCFormat( pwszServer ) == TRUE )
|
||
|
bstrNamespace = bstrServer + L"\\" + pwszNamespace;
|
||
|
else
|
||
|
bstrNamespace = L"\\\\" + bstrServer + L"\\" + pwszNamespace;
|
||
|
|
||
|
// user credentials
|
||
|
if ( pwszUser != NULL && lstrlen( pwszUser ) != 0 )
|
||
|
{
|
||
|
// copy the user name
|
||
|
bstrUser = pwszUser;
|
||
|
|
||
|
// if password is empty string and if we need to check with
|
||
|
// null password, then do not set the password and try
|
||
|
bstrPassword = pwszPassword;
|
||
|
if ( bCheckWithNullPwd == TRUE && bstrPassword.length() == 0 )
|
||
|
bstrPassword = (LPWSTR) NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// release the existing services object ( to be in safer side )
|
||
|
SAFE_RELEASE( *ppServices );
|
||
|
|
||
|
// connect to the remote system's WMI
|
||
|
// there is a twist here ...
|
||
|
// do not trap the ConnectServer function failure into exception
|
||
|
// instead handle that action manually
|
||
|
// by default try the ConnectServer function as the information which we have
|
||
|
// in our hands at this point. If the ConnectServer is failed,
|
||
|
// check whether password variable has any contents are not ... if no contents
|
||
|
// check with "" (empty) password ... this might pass in this situation ..
|
||
|
// if this call is also failed ... nothing is there that we can do ... throw the exception
|
||
|
hr = pLocator->ConnectServer( bstrNamespace,
|
||
|
bstrUser, bstrPassword, 0L, 0L, NULL, NULL, ppServices );
|
||
|
if ( FAILED( hr ) )
|
||
|
{
|
||
|
//
|
||
|
// special case ...
|
||
|
|
||
|
// check whether password exists or not
|
||
|
// NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
|
||
|
// this error code says that user with the current credentials is not
|
||
|
// having access permisions to the 'namespace'
|
||
|
if ( hr == E_ACCESSDENIED )
|
||
|
{
|
||
|
// check if we tried to connect to the system using null password
|
||
|
// if so, then try connecting to the remote system with empty string
|
||
|
if ( bCheckWithNullPwd == TRUE &&
|
||
|
bstrUser.length() != 0 && bstrPassword.length() == 0 )
|
||
|
{
|
||
|
// now invoke with ...
|
||
|
hr = pLocator->ConnectServer( bstrNamespace,
|
||
|
bstrUser, _bstr_t( L"" ), 0L, 0L, NULL, NULL, ppServices );
|
||
|
}
|
||
|
}
|
||
|
else if ( hr == WBEM_E_LOCAL_CREDENTIALS )
|
||
|
{
|
||
|
// credentials were passed to the local system.
|
||
|
// So ignore the credentials and try to reconnect
|
||
|
bLocalSystem = TRUE;
|
||
|
bstrUser = (LPWSTR) NULL;
|
||
|
bstrPassword = (LPWSTR) NULL;
|
||
|
bstrNamespace = pwszNamespace; // name space
|
||
|
hr = pLocator->ConnectServer( bstrNamespace,
|
||
|
NULL, NULL, 0L, 0L, NULL, NULL, ppServices );
|
||
|
}
|
||
|
|
||
|
// now check the result again .. if failed .. ummmm..
|
||
|
if ( FAILED( hr ) )
|
||
|
_com_issue_error( hr );
|
||
|
else
|
||
|
bstrPassword = L"";
|
||
|
}
|
||
|
|
||
|
// set the security at the interface level also
|
||
|
SAFE_EXECUTE( SetInterfaceSecurity( *ppServices,
|
||
|
pwszServer, bstrUser, bstrPassword, ppAuthIdentity ) );
|
||
|
|
||
|
// connection to WMI is successful
|
||
|
bResult = TRUE;
|
||
|
|
||
|
// save the hr value if needed by the caller
|
||
|
if ( phr != NULL )
|
||
|
*phr = WBEM_S_NO_ERROR;
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
// save the error
|
||
|
WMISaveError( e );
|
||
|
|
||
|
// save the hr value if needed by the caller
|
||
|
if ( phr != NULL )
|
||
|
*phr = e.Error();
|
||
|
}
|
||
|
|
||
|
// ...
|
||
|
if ( pbLocalSystem != NULL )
|
||
|
*pbLocalSystem = bLocalSystem;
|
||
|
|
||
|
// return the result
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL ConnectWmiEx( IWbemLocator* pLocator,
|
||
|
IWbemServices** ppServices,
|
||
|
LPCWSTR pwszServer, CHString& strUserName, CHString& strPassword,
|
||
|
COAUTHIDENTITY** ppAuthIdentity,
|
||
|
BOOL bNeedPassword, LPCWSTR pwszNamespace, BOOL* pbLocalSystem )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
DWORD dwSize = 0;
|
||
|
BOOL bResult = FALSE;
|
||
|
LPWSTR pwszPassword = NULL;
|
||
|
CHString strBuffer = NULL_STRING;
|
||
|
|
||
|
// clear the error .. if any
|
||
|
SetLastError( WBEM_S_NO_ERROR );
|
||
|
|
||
|
// sometime users want the utility to prompt for the password
|
||
|
// check what user wants the utility to do
|
||
|
if ( bNeedPassword == TRUE && strPassword.Compare( L"*" ) == 0 )
|
||
|
{
|
||
|
// user wants the utility to prompt for the password
|
||
|
// so skip this part and let the flow directly jump the password acceptance part
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// try to establish connection to the remote system with the credentials supplied
|
||
|
if ( strUserName.GetLength() == 0 )
|
||
|
{
|
||
|
// user name is empty
|
||
|
// so, it is obvious that password will also be empty
|
||
|
// even if password is specified, we have to ignore that
|
||
|
bResult = ConnectWmi( pLocator, ppServices,
|
||
|
pwszServer, NULL, NULL, ppAuthIdentity, FALSE, pwszNamespace, &hr, pbLocalSystem );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// credentials were supplied
|
||
|
// but password might not be specified ... so check and act accordingly
|
||
|
LPCWSTR pwszTemp = NULL;
|
||
|
BOOL bCheckWithNull = TRUE;
|
||
|
if ( bNeedPassword == FALSE )
|
||
|
{
|
||
|
pwszTemp = strPassword;
|
||
|
bCheckWithNull = FALSE;
|
||
|
}
|
||
|
|
||
|
// ...
|
||
|
bResult = ConnectWmi( pLocator, ppServices, pwszServer,
|
||
|
strUserName, pwszTemp, ppAuthIdentity, bCheckWithNull, pwszNamespace, &hr, pbLocalSystem );
|
||
|
}
|
||
|
|
||
|
// check the result ... if successful in establishing connection ... return
|
||
|
if ( bResult == TRUE )
|
||
|
return TRUE;
|
||
|
|
||
|
// now check the kind of error occurred
|
||
|
switch( hr )
|
||
|
{
|
||
|
case E_ACCESSDENIED:
|
||
|
break;
|
||
|
|
||
|
case WBEM_E_LOCAL_CREDENTIALS:
|
||
|
// needs to do special processing
|
||
|
break;
|
||
|
|
||
|
case WBEM_E_ACCESS_DENIED:
|
||
|
default:
|
||
|
// NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
|
||
|
// this error code says that user with the current credentials is not
|
||
|
// having access permisions to the 'namespace'
|
||
|
WMISaveError( hr );
|
||
|
return FALSE; // no use of accepting the password .. return failure
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// if failed in establishing connection to the remote terminal
|
||
|
// even if the password is specifed, then there is nothing to do ... simply return failure
|
||
|
if ( bNeedPassword == FALSE )
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// check whether user name is specified or not
|
||
|
// if not, get the local system's current user name under whose credentials, the process
|
||
|
// is running
|
||
|
if ( strUserName.GetLength() == 0 )
|
||
|
{
|
||
|
// sub-local variables
|
||
|
LPWSTR pwszUserName = NULL;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get the required buffer
|
||
|
pwszUserName = strUserName.GetBufferSetLength( MAX_STRING_LENGTH );
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
SaveLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// get the user name
|
||
|
DWORD dwUserLength = MAX_STRING_LENGTH;
|
||
|
if ( GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength ) == FALSE )
|
||
|
{
|
||
|
// error occured while trying to get the current user info
|
||
|
SaveLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// release the extra buffer allocated
|
||
|
strUserName.ReleaseBuffer();
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get the required buffer
|
||
|
pwszPassword = strPassword.GetBufferSetLength( MAX_STRING_LENGTH );
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
SaveLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// accept the password from the user
|
||
|
strBuffer.Format( INPUT_PASSWORD, strUserName );
|
||
|
WriteConsoleW( GetStdHandle( STD_ERROR_HANDLE ),
|
||
|
strBuffer, strBuffer.GetLength(), &dwSize, NULL );
|
||
|
GetPassword( pwszPassword, MAX_PASSWORD_LENGTH );
|
||
|
|
||
|
// release the buffer allocated for password
|
||
|
strPassword.ReleaseBuffer();
|
||
|
|
||
|
// now again try to establish the connection using the currently
|
||
|
// supplied credentials
|
||
|
bResult = ConnectWmi( pLocator, ppServices, pwszServer,
|
||
|
strUserName, strPassword, ppAuthIdentity, FALSE, pwszNamespace, NULL, pbLocalSystem );
|
||
|
|
||
|
// return the failure
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT GetSecurityArguments( IUnknown* pInterface,
|
||
|
DWORD& dwAuthorization, DWORD& dwAuthentication )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
DWORD dwAuthnSvc = 0, dwAuthzSvc = 0;
|
||
|
IClientSecurity* pClientSecurity = NULL;
|
||
|
|
||
|
// try to get the client security services values if possible
|
||
|
hr = pInterface->QueryInterface( IID_IClientSecurity, (void**) &pClientSecurity );
|
||
|
if ( SUCCEEDED( hr ) )
|
||
|
{
|
||
|
// got the client security interface
|
||
|
// now try to get the security services values
|
||
|
hr = pClientSecurity->QueryBlanket( pInterface,
|
||
|
&dwAuthnSvc, &dwAuthzSvc, NULL, NULL, NULL, NULL, NULL );
|
||
|
if ( SUCCEEDED( hr ) )
|
||
|
{
|
||
|
// we've got the values from the interface
|
||
|
dwAuthentication = dwAuthnSvc;
|
||
|
dwAuthorization = dwAuthzSvc;
|
||
|
}
|
||
|
|
||
|
// release the client security interface
|
||
|
SAFE_RELEASE( pClientSecurity );
|
||
|
}
|
||
|
|
||
|
// return always success
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT SetInterfaceSecurity( IUnknown* pInterface,
|
||
|
LPCWSTR pwszServer, LPCWSTR pwszUser,
|
||
|
LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
CHString strUser;
|
||
|
CHString strDomain;
|
||
|
LPCWSTR pwszUserArg = NULL;
|
||
|
LPCWSTR pwszDomainArg = NULL;
|
||
|
DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
|
||
|
DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
|
||
|
|
||
|
// check the interface
|
||
|
if ( pInterface == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
// check the authentity strcuture ... if authentity structure is already ready
|
||
|
// simply invoke the 2nd version of SetInterfaceSecurity
|
||
|
if ( *ppAuthIdentity != NULL )
|
||
|
return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
|
||
|
|
||
|
// get the current security argument value
|
||
|
// GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
|
||
|
|
||
|
// If we are doing trivial case, just pass in a null authenication structure
|
||
|
// for which the current logged in user's credentials will be considered
|
||
|
if ( pwszUser == NULL && pwszPassword == NULL )
|
||
|
{
|
||
|
// set the security
|
||
|
hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
|
||
|
NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
|
||
|
|
||
|
// return the result
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// parse and find out if the user name contains the domain name
|
||
|
// if contains, extract the domain value from it
|
||
|
LONG lPos = -1;
|
||
|
strDomain = L"";
|
||
|
strUser = pwszUser;
|
||
|
if ( ( lPos = strUser.Find( L'\\' ) ) != -1 )
|
||
|
{
|
||
|
// user name contains domain name ... domain\user format
|
||
|
strDomain = strUser.Left( lPos );
|
||
|
strUser = strUser.Mid( lPos + 1 );
|
||
|
}
|
||
|
else if ( ( lPos = strUser.Find( L'@' ) ) != -1 )
|
||
|
{
|
||
|
// NEED TO IMPLEMENT THIS ... IF NEEDED
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// server itself is the domain
|
||
|
// NOTE: NEED TO DO SOME R & D ON BELOW COMMENTED LINE
|
||
|
// strDomain = pwszServer;
|
||
|
}
|
||
|
|
||
|
// get the domain info if it exists only
|
||
|
if ( strDomain.GetLength() != 0 )
|
||
|
pwszDomainArg = strDomain;
|
||
|
|
||
|
// get the user info if it exists only
|
||
|
if ( strUser.GetLength() != 0 )
|
||
|
pwszUserArg = strUser;
|
||
|
|
||
|
// check if authenication info is available or not ...
|
||
|
// initialize the security authenication information ... UNICODE VERSION STRUCTURE
|
||
|
if ( ppAuthIdentity == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
else if ( *ppAuthIdentity == NULL )
|
||
|
{
|
||
|
hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
|
||
|
if ( hr != S_OK )
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// set the security information to the interface
|
||
|
hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
|
||
|
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
|
||
|
|
||
|
// return the result
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT SetInterfaceSecurity( IUnknown* pInterface, COAUTHIDENTITY* pAuthIdentity )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
LPWSTR pwszDomain = NULL;
|
||
|
DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
|
||
|
DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
|
||
|
|
||
|
// check the interface
|
||
|
if ( pInterface == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
// get the current security argument value
|
||
|
// GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
|
||
|
|
||
|
// set the security information to the interface
|
||
|
hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
|
||
|
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
|
||
|
|
||
|
// return the result
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT WINAPI SetProxyBlanket( IUnknown* pInterface,
|
||
|
DWORD dwAuthnSvc, DWORD dwAuthzSvc,
|
||
|
LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
|
||
|
RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
IUnknown * pUnknown = NULL;
|
||
|
IClientSecurity * pClientSecurity = NULL;
|
||
|
|
||
|
// get the IUnknown interface ... to check whether this is a valid interface or not
|
||
|
hr = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
|
||
|
if ( hr != S_OK )
|
||
|
return hr;
|
||
|
|
||
|
// now get the client security interface
|
||
|
hr = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
|
||
|
if ( hr != S_OK )
|
||
|
{
|
||
|
SAFE_RELEASE( pUnknown );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Can't set pAuthInfo if cloaking requested, as cloaking implies
|
||
|
// that the current proxy identity in the impersonated thread (rather
|
||
|
// than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
|
||
|
// is to be used.
|
||
|
// See MSDN info on CoSetProxyBlanket for more details.
|
||
|
//
|
||
|
if ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) )
|
||
|
pAuthInfo = NULL;
|
||
|
|
||
|
// now set the security
|
||
|
hr = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
|
||
|
dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
|
||
|
|
||
|
// release the security interface
|
||
|
SAFE_RELEASE( pClientSecurity );
|
||
|
|
||
|
// we should check the auth identity structure. if exists .. set for IUnknown also
|
||
|
if ( pAuthInfo != NULL )
|
||
|
{
|
||
|
hr = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
|
||
|
if ( hr == S_OK )
|
||
|
{
|
||
|
// set security authentication
|
||
|
hr = pClientSecurity->SetBlanket(
|
||
|
pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
|
||
|
dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
|
||
|
|
||
|
// release
|
||
|
SAFE_RELEASE( pClientSecurity );
|
||
|
}
|
||
|
else if ( hr == E_NOINTERFACE )
|
||
|
hr = S_OK; // ignore no interface errors
|
||
|
}
|
||
|
|
||
|
// release the IUnknown
|
||
|
SAFE_RELEASE( pUnknown );
|
||
|
|
||
|
// return the result
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
|
||
|
LPCWSTR pwszDomain, COAUTHIDENTITY** ppAuthIdent )
|
||
|
{
|
||
|
// local variables
|
||
|
COAUTHIDENTITY* pAuthIdent = NULL;
|
||
|
|
||
|
// validate the input parameter
|
||
|
if ( ppAuthIdent == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
// allocation thru COM API
|
||
|
pAuthIdent = ( COAUTHIDENTITY* ) CoTaskMemAlloc( sizeof( COAUTHIDENTITY ) );
|
||
|
if ( NULL == pAuthIdent )
|
||
|
return WBEM_E_OUT_OF_MEMORY;
|
||
|
|
||
|
// init with 0's
|
||
|
ZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
|
||
|
|
||
|
//
|
||
|
// Allocate needed memory and copy in data. Cleanup if anything goes wrong
|
||
|
|
||
|
// user
|
||
|
if ( pwszUser != NULL )
|
||
|
{
|
||
|
// allocate memory for user
|
||
|
LONG lLength = wcslen( pwszUser );
|
||
|
pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
|
||
|
if ( pAuthIdent->User == NULL )
|
||
|
{
|
||
|
WbemFreeAuthIdentity( &pAuthIdent );
|
||
|
return WBEM_E_OUT_OF_MEMORY;
|
||
|
}
|
||
|
|
||
|
// set the length and do copy contents
|
||
|
pAuthIdent->UserLength = lLength;
|
||
|
wcscpy( pAuthIdent->User, pwszUser );
|
||
|
}
|
||
|
|
||
|
// domain
|
||
|
if ( pwszDomain != NULL )
|
||
|
{
|
||
|
// allocate memory for domain
|
||
|
LONG lLength = wcslen( pwszDomain );
|
||
|
pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
|
||
|
if ( pAuthIdent->Domain == NULL )
|
||
|
{
|
||
|
WbemFreeAuthIdentity( &pAuthIdent );
|
||
|
return WBEM_E_OUT_OF_MEMORY;
|
||
|
}
|
||
|
|
||
|
// set the length and do copy contents
|
||
|
pAuthIdent->DomainLength = lLength;
|
||
|
wcscpy( pAuthIdent->Domain, pwszDomain );
|
||
|
}
|
||
|
|
||
|
// passsord
|
||
|
if ( pwszPassword != NULL )
|
||
|
{
|
||
|
// allocate memory for passsord
|
||
|
LONG lLength = wcslen( pwszPassword );
|
||
|
pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
|
||
|
if ( pAuthIdent->Password == NULL )
|
||
|
{
|
||
|
WbemFreeAuthIdentity( &pAuthIdent );
|
||
|
return WBEM_E_OUT_OF_MEMORY;
|
||
|
}
|
||
|
|
||
|
// set the length and do copy contents
|
||
|
pAuthIdent->PasswordLength = lLength;
|
||
|
wcscpy( pAuthIdent->Password, pwszPassword );
|
||
|
}
|
||
|
|
||
|
// type of the structure
|
||
|
pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
||
|
|
||
|
// final set the address to out parameter
|
||
|
*ppAuthIdent = pAuthIdent;
|
||
|
|
||
|
// return result
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
VOID WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY** ppAuthIdentity )
|
||
|
{
|
||
|
// make sure we have a pointer, then walk the structure members and cleanup.
|
||
|
if ( *ppAuthIdentity != NULL )
|
||
|
{
|
||
|
// free the memory allocated for user
|
||
|
if ( (*ppAuthIdentity)->User != NULL )
|
||
|
CoTaskMemFree( (*ppAuthIdentity)->User );
|
||
|
|
||
|
// free the memory allocated for password
|
||
|
if ( (*ppAuthIdentity)->Password != NULL )
|
||
|
CoTaskMemFree( (*ppAuthIdentity)->Password );
|
||
|
|
||
|
// free the memory allocated for domain
|
||
|
if ( (*ppAuthIdentity)->Domain != NULL )
|
||
|
CoTaskMemFree( (*ppAuthIdentity)->Domain );
|
||
|
|
||
|
// final the structure
|
||
|
CoTaskMemFree( *ppAuthIdentity );
|
||
|
}
|
||
|
|
||
|
// set to NULL
|
||
|
*ppAuthIdentity = NULL;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
VOID WMISaveError( HRESULT hrError )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
CHString strBuffer = NULL_STRING;
|
||
|
IWbemStatusCodeText* pWbemStatus = NULL;
|
||
|
|
||
|
// if the error is win32 based, choose FormatMessage to get the message
|
||
|
switch( hrError )
|
||
|
{
|
||
|
case E_ACCESSDENIED: // Message: "Access Denied"
|
||
|
case ERROR_NO_SUCH_USER: // Message: "The specified user does not exist."
|
||
|
{
|
||
|
// change the error message to "Logon failure: unknown user name or bad password."
|
||
|
if ( hrError == E_ACCESSDENIED )
|
||
|
hrError = ERROR_LOGON_FAILURE;
|
||
|
|
||
|
// ...
|
||
|
SetLastError( hrError );
|
||
|
SaveLastError();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get the pointer to buffer
|
||
|
LPWSTR pwszBuffer = NULL;
|
||
|
pwszBuffer = strBuffer.GetBufferSetLength( MAX_STRING_LENGTH );
|
||
|
|
||
|
// get the wbem specific status code text
|
||
|
hr = CoCreateInstance( CLSID_WbemStatusCodeText,
|
||
|
NULL, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, (LPVOID*) &pWbemStatus );
|
||
|
|
||
|
// check whether we got the interface or not
|
||
|
if ( SUCCEEDED( hr ) )
|
||
|
{
|
||
|
// get the error message
|
||
|
BSTR bstr = NULL;
|
||
|
hr = pWbemStatus->GetErrorCodeText( hrError, 0, 0, &bstr );
|
||
|
if ( SUCCEEDED( hr ) )
|
||
|
{
|
||
|
// get the error message in proper format
|
||
|
GetCompatibleStringFromUnicode( bstr, pwszBuffer, MAX_STRING_LENGTH );
|
||
|
|
||
|
//
|
||
|
// supress all the new-line characters and add '.' at the end ( if not exists )
|
||
|
LPWSTR pwszTemp = NULL;
|
||
|
pwszTemp = wcstok( pwszBuffer, L"\r\n" );
|
||
|
if ( *( pwszTemp + lstrlenW( pwszTemp ) - 1 ) != L'.' )
|
||
|
lstrcatW( pwszTemp, L"." );
|
||
|
|
||
|
// free the BSTR
|
||
|
SysFreeString( bstr );
|
||
|
bstr = NULL;
|
||
|
|
||
|
// now release status code interface
|
||
|
SAFE_RELEASE( pWbemStatus );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// failed to get the error message ... get the com specific error message
|
||
|
_com_issue_error( hrError );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// failed to get the error message ... get the com specific error message
|
||
|
_com_issue_error( hrError );
|
||
|
}
|
||
|
|
||
|
// release the buffer
|
||
|
strBuffer.ReleaseBuffer();
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
// get the error message
|
||
|
strBuffer.ReleaseBuffer();
|
||
|
if ( e.ErrorMessage() != NULL )
|
||
|
strBuffer = e.ErrorMessage();
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
SaveLastError();
|
||
|
}
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
SaveLastError();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// set the reason
|
||
|
strBuffer += L"\n";
|
||
|
SetReason( strBuffer );
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [ in ] pWmiObject : pointer to the WBEM class object
|
||
|
// [ in ] szProperty : property name
|
||
|
// [ out ] varValue : value of the property
|
||
|
//
|
||
|
// Return Value:
|
||
|
// HRESULT - result of the operation
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, VARIANT* pvarValue )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL || pvarValue == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// initialize the variant and then get the value of the specified property
|
||
|
hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, pvarValue, NULL, NULL );
|
||
|
if ( FAILED( hr ) )
|
||
|
{
|
||
|
// clear the variant variable
|
||
|
VariantClear( pvarValue );
|
||
|
|
||
|
// failed to get the value for the property
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
return e.Error();
|
||
|
}
|
||
|
|
||
|
// inform success
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [ in ] pWmiObject : pointer to the WBEM class object
|
||
|
// [ in ] szProperty : property name
|
||
|
// [ out ] varValue : value of the property
|
||
|
//
|
||
|
// Return Value:
|
||
|
// HRESULT - result of the operation
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, _variant_t& varValue )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
VARIANT vtValue;
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// initialize the variant and then get the value of the specified property
|
||
|
VariantInit( &vtValue );
|
||
|
hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, &vtValue, NULL, NULL );
|
||
|
if ( FAILED( hr ) )
|
||
|
{
|
||
|
// clear the variant variable
|
||
|
VariantClear( &vtValue );
|
||
|
|
||
|
// failed to get the value for the property
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// set the value
|
||
|
varValue = vtValue;
|
||
|
|
||
|
// clear the variant variable
|
||
|
VariantClear( &vtValue );
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
return e.Error();
|
||
|
}
|
||
|
|
||
|
// inform success
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object in string format
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE - if operation is successfull, otherwise FALSE
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL PropertyGet( IWbemClassObject* pWmiObject,
|
||
|
LPCWSTR pwszProperty, CHString& strValue, LPCWSTR pwszDefault )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
_variant_t var;
|
||
|
|
||
|
// first copy the default value
|
||
|
strValue = pwszDefault;
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the property value
|
||
|
hr = PropertyGet( pWmiObject, pwszProperty, var );
|
||
|
if ( FAILED( hr ) )
|
||
|
return FALSE;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get the value
|
||
|
if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
|
||
|
strValue = (LPCWSTR) _bstr_t( var );
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
SaveLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// return
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object in string format
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [ in ] pWmiObject : pointer to the WBEM class object
|
||
|
// [ in ] pwszProperty : property name
|
||
|
// [ out ] pdwValue : value of the property
|
||
|
// [ in ] dwDefault : default in case failed in getting property value
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE - if operation is successfull, otherwise FALSE
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL PropertyGet( IWbemClassObject* pWmiObject,
|
||
|
LPCWSTR pwszProperty, DWORD& dwValue, DWORD dwDefault )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
_variant_t var;
|
||
|
|
||
|
// first set the defaul value
|
||
|
dwValue = dwDefault;
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the value of the property
|
||
|
hr = PropertyGet( pWmiObject, pwszProperty, var );
|
||
|
if ( FAILED( hr ) )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the process id from the variant
|
||
|
if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
|
||
|
dwValue = (LONG) var;
|
||
|
|
||
|
// return
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object in string format
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE - if operation is successfull, otherwise FALSE
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, ULONGLONG& ullValue )
|
||
|
{
|
||
|
// local variables
|
||
|
CHString str;
|
||
|
|
||
|
// first set the default value
|
||
|
ullValue = 1;
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the value of the property
|
||
|
if ( PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) == FALSE )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the 64-bit value
|
||
|
ullValue = _wtoi64( str );
|
||
|
|
||
|
// return
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object in string format
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE - if operation is successfull, otherwise FALSE
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, WBEMTime& wbemtime )
|
||
|
{
|
||
|
// local variables
|
||
|
CHString str;
|
||
|
|
||
|
// Clear method sets the time in the WBEMTime object to an invalid time.
|
||
|
wbemtime.Clear();
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the value of the property
|
||
|
if ( PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) == FALSE )
|
||
|
return FALSE;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// convert into the time value
|
||
|
wbemtime = _bstr_t( str );
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// return
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object in string format
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE - if operation is successfull, otherwise FALSE
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, SYSTEMTIME& systime )
|
||
|
{
|
||
|
// local variables
|
||
|
CHString strTime;
|
||
|
|
||
|
// check with object and property passed to the function are valid or not
|
||
|
// if not, return failure
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the value of the property
|
||
|
// 16010101000000.000000+000 is the default time
|
||
|
if ( PropertyGet( pWmiObject, pwszProperty, strTime, _T( "16010101000000.000000+000" ) ) == FALSE )
|
||
|
return FALSE;
|
||
|
|
||
|
// prepare the systemtime structure
|
||
|
// yyyymmddHHMMSS.mmmmmmsUUU
|
||
|
systime.wYear = (WORD) AsLong( strTime.Left( 4 ), 10 );
|
||
|
systime.wMonth = (WORD) AsLong( strTime.Mid( 4, 2 ), 10 );
|
||
|
systime.wDayOfWeek = 0;
|
||
|
systime.wDay = (WORD) AsLong( strTime.Mid( 6, 2 ), 10 );
|
||
|
systime.wHour = (WORD) AsLong( strTime.Mid( 8, 2 ), 10 );
|
||
|
systime.wMinute = (WORD) AsLong( strTime.Mid( 10, 2 ), 10 );
|
||
|
systime.wSecond = (WORD) AsLong( strTime.Mid( 12, 2 ), 10 );
|
||
|
systime.wMilliseconds = (WORD) AsLong( strTime.Mid( 15, 6 ), 10 );
|
||
|
|
||
|
// return
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Gets the value of the property from the WMI class object in string format
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
// TRUE - if operation is successfull, otherwise FALSE
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, TARRAY arr )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
VARIANT vtValue;
|
||
|
LONG lIndex = 0;
|
||
|
LONG lLBound = 0;
|
||
|
LONG lUBound = 0;
|
||
|
VARTYPE vartype;
|
||
|
SAFEARRAY* pSafeArray = NULL;
|
||
|
|
||
|
// check the inputs
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL || arr == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// initialize the variant
|
||
|
VariantInit( &vtValue );
|
||
|
|
||
|
// now get the property value
|
||
|
hr = PropertyGet( pWmiObject, pwszProperty, &vtValue );
|
||
|
if ( FAILED( hr ) )
|
||
|
return FALSE;
|
||
|
|
||
|
if ( V_VT( &vtValue ) == VT_NULL )
|
||
|
return TRUE;
|
||
|
|
||
|
// confirm that the propety value is of array type .. if not return
|
||
|
if ( ( V_VT( &vtValue ) & VT_ARRAY ) == 0 )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the safearray value
|
||
|
pSafeArray = V_ARRAY( &vtValue );
|
||
|
|
||
|
// get the bounds of the array
|
||
|
SafeArrayGetLBound( pSafeArray, 1, &lLBound );
|
||
|
SafeArrayGetUBound( pSafeArray, 1, &lUBound );
|
||
|
|
||
|
// get the type of the elements in the safe array
|
||
|
vartype = V_VT( &vtValue ) & ~VT_ARRAY;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// traverse thru the values in the safe array and update into dynamic array
|
||
|
for( lIndex = lLBound; lIndex <= lUBound; lIndex++ )
|
||
|
{
|
||
|
// sub-local variables
|
||
|
VARIANT var;
|
||
|
CHString strValue;
|
||
|
|
||
|
// get the value
|
||
|
V_VT( &var ) = vartype;
|
||
|
SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
|
||
|
|
||
|
// add the information to the dynamic array
|
||
|
switch( vartype )
|
||
|
{
|
||
|
case VT_BSTR:
|
||
|
strValue = V_BSTR( &var );
|
||
|
DynArrayAppendString( arr, strValue, 0 );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
// clear the variant
|
||
|
VariantClear( &vtValue );
|
||
|
return FALSE; // failure
|
||
|
}
|
||
|
|
||
|
// clear the variant
|
||
|
VariantClear( &vtValue );
|
||
|
|
||
|
// return
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Sets the value of the property to the WMI class object
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [ in ] pWmiObject : pointer to the WBEM class object
|
||
|
// [ in ] szProperty : property name
|
||
|
// [ in ] varValue : value of the property
|
||
|
//
|
||
|
// Return Value:
|
||
|
// HRESULT - result of the operation
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, _variant_t& varValue )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
VARIANT var;
|
||
|
|
||
|
// check the input value
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// put the value
|
||
|
var = varValue;
|
||
|
hr = pWmiObject->Put( _bstr_t( pwszProperty ), 0, &var, 0 );
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
hr = e.Error();
|
||
|
}
|
||
|
|
||
|
// return the result
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Sets the value of the property to the WMI class object
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, LPCWSTR pwszValue )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
_variant_t varValue;
|
||
|
|
||
|
// check the input value
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL || pwszValue == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
varValue = pwszValue;
|
||
|
hr = PropertyPut( pWmiObject, pwszProperty, varValue );
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
hr = e.Error();
|
||
|
}
|
||
|
|
||
|
// return
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
// Sets the value of the property to the WMI class object
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, DWORD dwValue )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
_variant_t varValue;
|
||
|
|
||
|
// check the input value
|
||
|
if ( pWmiObject == NULL || pwszProperty == NULL )
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
varValue = ( LONG ) dwValue;
|
||
|
hr = PropertyPut( pWmiObject, pwszProperty, varValue );
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
hr = e.Error();
|
||
|
}
|
||
|
|
||
|
// return
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
HRESULT RegQueryValueWMI( IWbemServices* pWbemServices,
|
||
|
LPCWSTR pwszMethod, DWORD dwHDefKey,
|
||
|
LPCWSTR pwszSubKeyName, LPCWSTR pwszValueName, _variant_t& varValue )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
BOOL bResult = FALSE;
|
||
|
DWORD dwReturnValue = 0;
|
||
|
IWbemClassObject* pClass = NULL;
|
||
|
IWbemClassObject* pMethod = NULL;
|
||
|
IWbemClassObject* pInParams = NULL;
|
||
|
IWbemClassObject* pInParamsInstance = NULL;
|
||
|
IWbemClassObject* pOutParamsInstance = NULL;
|
||
|
|
||
|
// check the input value
|
||
|
if (pWbemServices == NULL || pwszMethod == NULL || pwszSubKeyName == NULL || pwszValueName == NULL)
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get the registry class object
|
||
|
SAFE_EXECUTE( pWbemServices->GetObject(
|
||
|
_bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
|
||
|
if ( pClass == NULL ) // check the object .. safety sake
|
||
|
_com_issue_error( STG_E_UNKNOWN );
|
||
|
|
||
|
// get the method reference required
|
||
|
SAFE_EXECUTE( pClass->GetMethod( pwszMethod, 0, &pInParams, NULL ) );
|
||
|
if ( pInParams == NULL ) // check the object .. safety sake
|
||
|
_com_issue_error( STG_E_UNKNOWN );
|
||
|
|
||
|
// create the instance for the in parameters
|
||
|
SAFE_EXECUTE( pInParams->SpawnInstance( 0, &pInParamsInstance ) );
|
||
|
if ( pInParamsInstance == NULL )
|
||
|
_com_issue_error( STG_E_UNKNOWN );
|
||
|
|
||
|
// set the input values
|
||
|
PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_HDEFKEY ), dwHDefKey );
|
||
|
PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_SUBKEY ), pwszSubKeyName );
|
||
|
PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_VALUENAME ), pwszValueName );
|
||
|
|
||
|
// now execute the method
|
||
|
SAFE_EXECUTE( pWbemServices->ExecMethod( _bstr_t( WMI_REGISTRY ),
|
||
|
_bstr_t( pwszMethod ), 0, NULL, pInParamsInstance, &pOutParamsInstance, NULL ) );
|
||
|
if ( pOutParamsInstance == NULL ) // check the object .. safety sake
|
||
|
_com_issue_error( STG_E_UNKNOWN );
|
||
|
|
||
|
// now check the return value of the method from the output params object
|
||
|
bResult = PropertyGet( pOutParamsInstance,
|
||
|
_bstr_t( WMI_REGISTRY_OUT_RETURNVALUE ), dwReturnValue );
|
||
|
if ( bResult == FALSE || dwReturnValue != 0 )
|
||
|
_com_issue_error( STG_E_UNKNOWN );
|
||
|
|
||
|
// now everything is sucess .. get the required value
|
||
|
PropertyGet( pOutParamsInstance, _bstr_t( WMI_REGISTRY_OUT_VALUE ), varValue );
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
return e.Error();
|
||
|
}
|
||
|
|
||
|
// release the interfaces
|
||
|
SAFE_RELEASE( pClass );
|
||
|
SAFE_RELEASE( pMethod );
|
||
|
SAFE_RELEASE( pInParams );
|
||
|
SAFE_RELEASE( pInParamsInstance );
|
||
|
SAFE_RELEASE( pOutParamsInstance );
|
||
|
|
||
|
// return success
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
BOOL RegQueryValueWMI( IWbemServices* pWbemServices,
|
||
|
DWORD dwHDefKey, LPCWSTR pwszSubKeyName,
|
||
|
LPCWSTR pwszValueName, CHString& strValue, LPCWSTR pwszDefault )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
_variant_t varValue;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// set the default value
|
||
|
if ( pwszDefault != NULL )
|
||
|
strValue = pwszDefault;
|
||
|
|
||
|
// check the input
|
||
|
if ( pWbemServices == NULL || pwszSubKeyName == NULL || pwszValueName == NULL )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the value
|
||
|
hr = RegQueryValueWMI( pWbemServices,
|
||
|
WMI_REGISTRY_M_STRINGVALUE, dwHDefKey, pwszSubKeyName, pwszValueName, varValue );
|
||
|
if ( FAILED( hr ) )
|
||
|
return FALSE;
|
||
|
|
||
|
// get the value from the variant
|
||
|
// get the value
|
||
|
if ( varValue.vt != VT_NULL && varValue.vt != VT_EMPTY )
|
||
|
strValue = (LPCWSTR) _bstr_t( varValue );
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
SetLastError( E_OUTOFMEMORY );
|
||
|
SaveLastError();
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// return success
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// ***************************************************************************
|
||
|
DWORD GetTargetVersionEx( IWbemServices* pWbemServices, COAUTHIDENTITY* pAuthIdentity )
|
||
|
{
|
||
|
// local variables
|
||
|
HRESULT hr;
|
||
|
LONG lPos = 0;
|
||
|
DWORD dwMajor = 0;
|
||
|
DWORD dwMinor = 0;
|
||
|
DWORD dwVersion = 0;
|
||
|
ULONG ulReturned = 0;
|
||
|
CHString strVersion;
|
||
|
IWbemClassObject* pWbemObject = NULL;
|
||
|
IEnumWbemClassObject* pWbemInstances = NULL;
|
||
|
|
||
|
// check the input value
|
||
|
if ( pWbemServices == NULL )
|
||
|
return 0;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
// get the OS information
|
||
|
SAFE_EXECUTE( pWbemServices->CreateInstanceEnum(
|
||
|
_bstr_t( CLASS_CIMV2_Win32_OperatingSystem ), 0, NULL, &pWbemInstances ) );
|
||
|
|
||
|
// set the security on the enumerated object
|
||
|
SAFE_EXECUTE( SetInterfaceSecurity( pWbemInstances, pAuthIdentity ) );
|
||
|
|
||
|
// get the enumerated objects information
|
||
|
// NOTE: This needs to be traversed only one time.
|
||
|
SAFE_EXECUTE( pWbemInstances->Next( WBEM_INFINITE, 1, &pWbemObject, &ulReturned ) );
|
||
|
|
||
|
// to be on safer side ... check the count of objects returned
|
||
|
if ( ulReturned == 0 )
|
||
|
{
|
||
|
// release the interfaces
|
||
|
SAFE_RELEASE( pWbemObject );
|
||
|
SAFE_RELEASE( pWbemInstances );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// now get the os version value
|
||
|
if ( PropertyGet( pWbemObject, L"Version", strVersion ) == FALSE )
|
||
|
{
|
||
|
// release the interfaces
|
||
|
SAFE_RELEASE( pWbemObject );
|
||
|
SAFE_RELEASE( pWbemInstances );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// release the interfaces .. we dont need them furthur
|
||
|
SAFE_RELEASE( pWbemObject );
|
||
|
SAFE_RELEASE( pWbemInstances );
|
||
|
|
||
|
//
|
||
|
// now determine the os version
|
||
|
dwMajor = dwMinor = 0;
|
||
|
|
||
|
// get the major version
|
||
|
lPos = strVersion.Find( L'.' );
|
||
|
if ( lPos == -1 )
|
||
|
{
|
||
|
// the version string itself is version ... THIS WILL NEVER HAPPEN
|
||
|
dwMajor = AsLong( strVersion, 10 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// major version
|
||
|
dwMajor = AsLong( strVersion.Mid( 0, lPos ), 10 );
|
||
|
|
||
|
// get the minor version
|
||
|
strVersion = strVersion.Mid( lPos + 1 );
|
||
|
lPos = strVersion.Find( L'.' );
|
||
|
if ( lPos == -1 )
|
||
|
dwMinor = AsLong( strVersion, 10 );
|
||
|
else
|
||
|
dwMinor = AsLong( strVersion.Mid( 0, lPos ), 10 );
|
||
|
}
|
||
|
|
||
|
// mix the version info
|
||
|
dwVersion = dwMajor * 1000 + dwMinor;
|
||
|
}
|
||
|
catch( _com_error& e )
|
||
|
{
|
||
|
WMISaveError( e );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// return
|
||
|
return dwVersion;
|
||
|
}
|