Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2792 lines
76 KiB

/*********************************************************************************************
Copyright (c) Microsoft Corporation
Module Name:
WMI.cpp
Abstract:
Common functionlity for dealing with WMI.
Author:
Wipro Technologies
Revision History:
22-Dec-2000 : Created It.
24-Apr-2001 : Closing the review comments given by client.
*********************************************************************************************/
#include "pch.h"
#include "wmi.h"
#include "resource.h"
//
// messages
//
#define INPUT_PASSWORD GetResString( IDS_STR_INPUT_PASSWORD )
#define INPUT_PASSWORD_LEN 256
// 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 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 );
BOOL
IsValidUserEx(
LPCWSTR pwszUser
)
/*++
Routine Description:
Checks wether the User name is a valid one or not
Arguments:
[in] LPCWSTR : String containing the user name
Return Value:
TRUE on success
FALSE on failure
--*/
{
// local variables
CHString strUser;
LONG lPos = 0;
if ( ( NULL == pwszUser ) || ( 0 == StringLength( pwszUser, 0 ) ) )
{
return TRUE;
}
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 ( -1 != lPos )
{
// '\' 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 ( -1 != lPos )
{
return FALSE;
}
}
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// user name is valid
return TRUE;
}
BOOL
IsValidServerEx(
LPCWSTR pwszServer,
BOOL& bLocalSystem
)
/*++
Routine Description:
Checks wether the Server name is a valid one or not
Arguments:
[in] LPCWSTR : String containing the user name
[out] BOOL : Is set to TRUE if the local system is being queried.
Return Value:
TRUE on success
FALSE on failure
--*/
{
// local variables
CHString strTemp;
// Validate input arguments.
if ( ( NULL == pwszServer ) || ( 0 == StringLength( pwszServer, 0 ) ) )
{
bLocalSystem = TRUE;
return TRUE;
}
try
{
// kick-off
bLocalSystem = FALSE;
if( IsNumeric( pwszServer, 10, FALSE ) == TRUE )
{
return 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;
}
}
if ( strTemp.FindOneOf( L"`~!@#$^&*()+=[]{}|\\<>,?/\"':;" ) != -1 )
{
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
if ( strTemp.CompareNoCase( L"." ) == 0 )
{
bLocalSystem = TRUE;
}
else
{
bLocalSystem = IsLocalSystem( strTemp );
}
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// inform that server name is valid
return TRUE;
}
BOOL
InitializeCom(
IWbemLocator** ppLocator
)
/*++
Routine Description:
Initializes the COM library
Arguments:
[in] IWbemLocator : pointer to the IWbemLocator
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
HRESULT hr = S_OK;
BOOL bResult = FALSE;
try
{
// Validate input arguments.
if( ( NULL == ppLocator ) ||
( NULL != *ppLocator ) )
{
_com_issue_error( WBEM_E_INVALID_PARAMETER );
}
// initialize the COM library
SAFE_EXECUTE( CoInitializeEx( NULL, COINIT_MULTITHREADED ) );
// 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_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 );
// Error is returned. Release any interface pointers.
SAFE_RELEASE( *ppLocator );
}
// return the result;
return bResult;
}
BOOL
ConnectWmi(
IWbemLocator* pLocator,
IWbemServices** ppServices,
LPCWSTR pwszServer,
LPCWSTR pwszUser,
LPCWSTR pwszPassword,
COAUTHIDENTITY** ppAuthIdentity,
BOOL bCheckWithNullPwd,
LPCWSTR pwszNamespace,
HRESULT* phr,
BOOL* pbLocalSystem,
IWbemContext* pWbemContext
)
/*++
Routine Description:
This function makes a connection to WMI.
Arguments:
[in] IWbemLocator : pointer to the IWbemLocator
[in] IWbemServices : pointer to the IWbemServices
[in] LPCWSTR : string containing the server name
[in] LPCWSTR : string containing the User name
[in] LPCWSTR : string containing the password
[in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
[in] BOOL : set to TRUE if we should try to connect with
current credentials
[in] LPCWSTR : string containing the namespace to connect to
[out] HRESULT : the hResult value returned
[out] BOOL : set to TRUE if we are querying for the local system
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
HRESULT hr = S_OK;
BOOL bResult = FALSE;
BOOL bLocalSystem = FALSE;
_bstr_t bstrServer;
_bstr_t bstrNamespace;
_bstr_t bstrUser, bstrPassword;
// clear the error
SetLastError( WBEM_S_NO_ERROR );
// check whether locator object exists or not
// if not exists, return
if ( ( NULL == pLocator ) ||
( NULL == ppServices ) ||
( NULL != *ppServices ) ||
( NULL == pwszNamespace ) )
{
if ( NULL != phr )
{
*phr = WBEM_E_INVALID_PARAMETER;
}
// return failure
return FALSE;
}
// kick-off
if ( NULL != pbLocalSystem )
{
*pbLocalSystem = FALSE;
}
// ...
if ( NULL != phr )
{
*phr = WBEM_S_NO_ERROR;
}
try
{
// assume that connection to WMI namespace is failed
bResult = FALSE;
// validate the server name
// NOTE: The error being raised in custom define for '0x800706ba' value
// The message that will be displayed in "The RPC server is unavailable."
if ( IsValidServerEx( pwszServer, bLocalSystem ) == FALSE )
{
_com_issue_error( E_SERVER_NOTFOUND );
}
// validate the user name
if ( IsValidUserEx( pwszUser ) == FALSE )
{
_com_issue_error( ERROR_NO_SUCH_USER );
}
// prepare namespace
bstrNamespace = pwszNamespace; // name space
if ( ( NULL != pwszServer ) && ( FALSE == bLocalSystem ) )
{
// 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 ( ( NULL != pwszUser ) && ( 0 != StringLength( 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 ( ( TRUE == bCheckWithNullPwd ) && ( 0 == bstrPassword.length() ) )
{
bstrPassword = (LPWSTR) NULL;
}
}
}
else
{ // Display warning message, credentials not required for local system.
if( ( TRUE == bLocalSystem ) && ( NULL != pwszUser ) &&
( 0 != StringLength( pwszUser, 0 ) ) )
{
// got the credentials for the local system
if ( NULL != phr )
{
*phr = WBEM_E_LOCAL_CREDENTIALS;
}
}
}
// 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, pWbemContext, 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, pWbemContext, ppServices );
}
}
else
{
if ( WBEM_E_LOCAL_CREDENTIALS == hr )
{
// 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, pWbemContext, 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,
bstrUser, bstrPassword, ppAuthIdentity ) );
// ...
if ( NULL != pbLocalSystem )
{
*pbLocalSystem = bLocalSystem;
}
// connection to WMI is successful
bResult = TRUE;
}
catch( _com_error& e )
{
// save the error
WMISaveError( e );
// save the hr value if needed by the caller
if ( NULL != phr )
{
*phr = e.Error();
}
SAFE_RELEASE( *ppServices );
bResult = FALSE;
}
// return the result
return bResult;
}
BOOL
ConnectWmiEx(
IWbemLocator* pLocator,
IWbemServices** ppServices,
LPCWSTR pwszServer,
CHString& strUserName,
CHString& strPassword,
COAUTHIDENTITY** ppAuthIdentity,
BOOL bNeedPassword,
LPCWSTR pwszNamespace,
BOOL* pbLocalSystem,
DWORD dwPasswordLen,
IWbemContext* pWbemContext
)
/*++
Routine Description:
This function is a wrapper function for the ConnectWmi function.
Arguments:
[in] IWbemLocator : pointer to the IWbemLocator
[in] IWbemServices : pointer to the IWbemServices
[in] LPCWSTR : string containing the server name
[in] LPCWSTR : string containing the User name
[in] LPCWSTR : string containing the password
[in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
[in] BOOL : set to TRUE if we should try to connect with
current credentials
[in] LPCWSTR : string containing the namespace to connect to
[out] HRESULT : the hResult value returned
[out] BOOL : set to TRUE if we are querying for the local system
[ in ] DWORD : Contains maximum password buffer length.
Return Value:
TRUE on success
FALSE on failure
NOTE: 'dwPasswordLen' WILL BE TAKEN AS 'MAX_STRING_LENGTH' IF NOT SPECIFIED.
IT IS USER RESPOSIBILITY TO SET THIS PARAMETER TO LIMITING VALUE.
--*/
{
// local variables
HRESULT hr = S_OK;
DWORD dwSize = 0;
BOOL bResult = FALSE;
LPWSTR pwszPassword = NULL;
CHString strBuffer;
// clear the error .. if any
SetLastError( WBEM_S_NO_ERROR );
try
{
// sometime users want the utility to prompt for the password
// check what user wants the utility to do
if ( ( TRUE == bNeedPassword ) &&
( 0 == strPassword.Compare( L"*" ) ) )
{
// 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 ( 0 == strUserName.GetLength() )
{
// 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, pWbemContext );
}
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, pWbemContext );
}
SetLastError (hr);
// check the result ... if successful in establishing connection ... return
if ( TRUE == bResult )
{
return TRUE;
}
// now check the kind of error occurred
switch( hr )
{
case E_ACCESSDENIED:
SetLastError( hr );
break;
case WBEM_E_LOCAL_CREDENTIALS:
SetLastError( hr );
// 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 ( 0 == strUserName.GetLength() )
{
// sub-local variables
LPWSTR pwszUserName = NULL;
DWORD dwUserLength = 0; // Username buffer length.
// Retrieve the buffer length need to store username.
GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength );
// get the required buffer
pwszUserName = strUserName.GetBufferSetLength( dwUserLength );
if ( FALSE == GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength ) )
{
// error occured while trying to get the current user info
SaveLastError();
return FALSE;
}
// No need to call 'ReleaseBuffer' since only sufficient memory is allocated.
}
// get the required buffer
if( 0 == dwPasswordLen )
{
dwPasswordLen = INPUT_PASSWORD_LEN;
}
pwszPassword = strPassword.GetBufferSetLength( dwPasswordLen );
// accept the password from the user
strBuffer.Format( INPUT_PASSWORD, strUserName );
WriteConsoleW( GetStdHandle( STD_OUTPUT_HANDLE ),
strBuffer, strBuffer.GetLength(), &dwSize, NULL );
bResult = GetPassword( pwszPassword, dwPasswordLen );
if ( TRUE != bResult )
{
return FALSE;
}
// 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, pWbemContext );
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// return the failure
return bResult;
}
HRESULT
GetSecurityArguments(
IUnknown* pInterface,
DWORD& dwAuthorization,
DWORD& dwAuthentication
)
/*++
Routine Description:
This function gets the values for the security services.
Arguments:
[in] IUnknown : pointer to the IUnkown interface
[out] DWORD : to hold the authentication service value
[out] DWORD : to hold the authorization service value
Return Value:
HRESULT
--*/
{
// local variables
HRESULT hr = S_OK;
DWORD dwAuthnSvc = 0, dwAuthzSvc = 0;
IClientSecurity* pClientSecurity = NULL;
if ( NULL == pInterface )
{
return WBEM_E_INVALID_PARAMETER;
}
// 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 hr;
}
HRESULT
SetInterfaceSecurity(
IUnknown* pInterface,
LPCWSTR pwszUser,
LPCWSTR pwszPassword,
COAUTHIDENTITY** ppAuthIdentity
)
/*++
Routine Description:
This function sets the interface security parameters.
Arguments:
[in] IUnknown : pointer to the IUnkown interface
[in] LPCWSTR : string containing the User name
[in] LPCWSTR : string containing the password
[in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
Return Value:
HRESULT
--*/
{
// local variables
HRESULT hr = S_OK;
CHString strUser;
CHString strDomain;
LPCWSTR pwszUserArg = NULL;
LPCWSTR pwszDomainArg = NULL;
DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
try
{
// check the interface
if ( NULL == pInterface )
{
return WBEM_E_INVALID_PARAMETER;
}
// check the authentity strcuture ... if authentity structure is already ready
// simply invoke the 2nd version of SetInterfaceSecurity
if ( NULL != *ppAuthIdentity )
{
return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
}
// 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 ( ( NULL == pwszUser ) &&
( NULL == pwszPassword ) )
{
// set the security
hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY , RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
// return the result
return hr;
}
// if authority srtucture is NULL then no need to proceed
if ( NULL == ppAuthIdentity )
{
return WBEM_E_INVALID_PARAMETER;
}
// check if authenication info is available or not ...
// initialize the security authenication information ... UNICODE VERSION STRUCTURE
if ( NULL == *ppAuthIdentity )
{
// 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 ( -1 != ( lPos = strUser.Find( L'\\' ) ) )
{
// user name contains domain name ... domain\user format
strDomain = strUser.Left( lPos );
strUser = strUser.Mid( lPos + 1 );
}
else
{
if ( -1 != ( lPos = strUser.Find( L'@' ) ) )
{
// NEED TO IMPLEMENT THIS ... IF NEEDED
// This implementation needs to be done if WMI does not support
// UPN name formats directly and if we have to split the
// name(user@domain)
}
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 ( 0 != strDomain.GetLength() )
{
pwszDomainArg = strDomain;
}
// get the user info if it exists only
if ( 0 != strUser.GetLength() )
{
pwszUserArg = strUser;
}
hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
if ( FAILED(hr) )
{
return hr;
}
}
// set the security information to the interface
hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY , RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
}
catch( CHeap_Exception )
{
hr = WBEM_E_OUT_OF_MEMORY;
}
// return the result
return hr;
}
HRESULT
SetInterfaceSecurity(
IUnknown* pInterface,
COAUTHIDENTITY* pAuthIdentity
)
/*++
Routine Description:
This function sets the interface security parameters.
Arguments:
[in] IUnknown : pointer to the IUnkown interface
[in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
Return Value:
HRESULT
--*/
{
// local variables
HRESULT hr = S_OK;
DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
// check the interface
// 'pAuthIdentity' can be NULL or not, so need to check.
if ( NULL == pInterface )
{
return WBEM_E_INVALID_PARAMETER;
}
// get the current security argument value
hr = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
if ( FAILED( hr ) )
{
return hr;
}
// set the security information to the interface
hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY , RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
// return the result
return hr;
}
HRESULT
WINAPI SetProxyBlanket(
IUnknown* pInterface,
DWORD dwAuthnSvc,
DWORD dwAuthzSvc,
LPWSTR pwszPrincipal,
DWORD dwAuthLevel,
DWORD dwImpLevel,
RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
DWORD dwCapabilities
)
/*++
Routine Description:
This function sets the authentication information (the security blanket)
that will be used to make calls.
Arguments:
[in] IUnknown : pointer to the IUnkown interface
[in] DWORD : contains the authentication service to use
[in] DWORD : contains the authorization service to use
[in] LPWSTR : the server principal name to use
[in] DWORD : contains the authentication level to use
[in] DWORD : contains the impersonation level to use
[in] RPC_AUTH_IDENTITY_HANDLE : pointer to the identity of the client
[in] DWORD : contains the capability flags
Return Value:
HRESULT
--*/
{
// local variables
HRESULT hr = S_OK;
IUnknown * pUnknown = NULL;
IClientSecurity * pClientSecurity = NULL;
// Validate input arguments.
//
// 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( ( NULL == pInterface ) ||
( ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) ) &&
( NULL != pAuthInfo ) )
)
{
return( WBEM_E_INVALID_PARAMETER );
}
// get the IUnknown interface ... to check whether this is a valid interface or not
hr = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
if ( FAILED(hr) )
{
return hr;
}
// now get the client security interface
hr = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
if ( FAILED(hr) )
{
SAFE_RELEASE( pUnknown );
return hr;
}
// now set the security
hr = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
if( FAILED( hr ) )
{
SAFE_RELEASE( pUnknown );
SAFE_RELEASE( pClientSecurity );
return hr;
}
// release the security interface
SAFE_RELEASE( pClientSecurity );
// we should check the auth identity structure. if exists .. set for IUnknown also
if ( NULL != pAuthInfo )
{
hr = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
if ( SUCCEEDED(hr) )
{
// set security authentication
hr = pClientSecurity->SetBlanket( pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
// release
SAFE_RELEASE( pClientSecurity );
}
else
{
if ( E_NOINTERFACE == hr )
{
hr = S_OK; // ignore no interface errors
}
}
}
// release the IUnknown
SAFE_RELEASE( pUnknown );
// return the result
return hr;
}
HRESULT
WINAPI WbemAllocAuthIdentity(
LPCWSTR pwszUser,
LPCWSTR pwszPassword,
LPCWSTR pwszDomain,
COAUTHIDENTITY** ppAuthIdent
)
/*++
Routine Description:
This function allocates memory for the AUTHIDENTITY structure.
Arguments:
[in] LPCWSTR : string containing the user name
[in] LPCWSTR : string containing the password
[in] LPCWSTR : string containing the domain name
[out] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
Return Value:
HRESULT
NOTE: 'ppAuthIdent' should be freed by calling 'WbemFreeAuthIdentity' by the user after
their work is done.
--*/
{
// local variables
COAUTHIDENTITY* pAuthIdent = NULL;
// validate the input parameter
if ( NULL == ppAuthIdent )
{
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
SecureZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
//
// Allocate needed memory and copy in data. Cleanup if anything goes wrong
// user
if ( NULL != pwszUser )
{
// allocate memory for user
LONG lLength = StringLength( pwszUser, 0 );
pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
if ( NULL == pAuthIdent->User )
{
WbemFreeAuthIdentity( &pAuthIdent );
return WBEM_E_OUT_OF_MEMORY;
}
// set the length and do copy contents
pAuthIdent->UserLength = lLength;
StringCopy( pAuthIdent->User, pwszUser, (lLength + 1) );
}
// domain
if ( NULL != pwszDomain )
{
// allocate memory for domain
LONG lLength = StringLength( pwszDomain, 0 );
pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
if ( NULL == pAuthIdent->Domain )
{
WbemFreeAuthIdentity( &pAuthIdent );
return WBEM_E_OUT_OF_MEMORY;
}
// set the length and do copy contents
pAuthIdent->DomainLength = lLength;
StringCopy( pAuthIdent->Domain, pwszDomain, (lLength + 1) );
}
// passsord
if ( NULL != pwszPassword )
{
// allocate memory for passsord
LONG lLength = StringLength( pwszPassword, 0 );
pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
if ( NULL == pAuthIdent->Password )
{
WbemFreeAuthIdentity( &pAuthIdent );
return WBEM_E_OUT_OF_MEMORY;
}
// set the length and do copy contents
pAuthIdent->PasswordLength = lLength;
StringCopy( pAuthIdent->Password, pwszPassword, (lLength + 1) );
}
// 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;
}
VOID
WINAPI WbemFreeAuthIdentity(
COAUTHIDENTITY** ppAuthIdentity
)
/*++
Routine Description:
This function releases the memory allocated for the AUTHIDENTITY structure.
Arguments:
[in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
Return Value:
None
--*/
{
// make sure we have a pointer, then walk the structure members and cleanup.
if ( *ppAuthIdentity != NULL )
{
// free the memory allocated for user
if ( NULL != (*ppAuthIdentity)->User )
{
CoTaskMemFree( (*ppAuthIdentity)->User );
(*ppAuthIdentity)->User = NULL;
}
// free the memory allocated for password
if ( NULL != (*ppAuthIdentity)->Password )
{
CoTaskMemFree( (*ppAuthIdentity)->Password );
(*ppAuthIdentity)->Password = NULL;
}
// free the memory allocated for domain
if ( NULL != (*ppAuthIdentity)->Domain )
{
CoTaskMemFree( (*ppAuthIdentity)->Domain );
(*ppAuthIdentity)->Domain = NULL;
}
// final the structure
CoTaskMemFree( *ppAuthIdentity );
*ppAuthIdentity = NULL;
}
}
VOID
WMISaveError(
HRESULT hrError
)
/*++
Routine Description:
This function saves the description of the last error returned by WMI
Arguments:
HRESULT : The last return value from WMI
Return Value:
NONE
--*/
{
// local variables
HRESULT hr = S_OK;
IWbemStatusCodeText* pWbemStatus = NULL;
_bstr_t bstrErrorString;
try
{
// Set error to different value.
if ( E_ACCESSDENIED == hrError )
{
// change the error message to "Logon failure: unknown user name or bad password."
hrError = ERROR_LOGON_FAILURE;
}
//Set the reason to incompatible os when no class is registered on remote mechine
if( 0x80040154 == hrError )
{
bstrErrorString = _bstr_t( GetResString(IDS_ERROR_REMOTE_INCOMPATIBLE));
SetReason( bstrErrorString );
return;
}
else
{ // Get error string.
hr = CoCreateInstance( CLSID_WbemStatusCodeText,
NULL, CLSCTX_INPROC_SERVER,
IID_IWbemStatusCodeText,
(LPVOID*) &pWbemStatus );
if( SUCCEEDED( hr ) )
{
BSTR bstrString = NULL;
// Get error string from error code.
hr = pWbemStatus->GetErrorCodeText( hrError, 0, 0,
&bstrString );
if( NULL != bstrString )
{
bstrErrorString = _bstr_t( bstrString );
SysFreeString( bstrString );
}
if( FAILED( hr ) )
{
_com_issue_error( hrError );
}
}
else
{
_com_issue_error( hrError );
}
}
}
catch( _com_error& e )
{ // We have got the error. Needs to handle carefully.
LPWSTR lpwszGetString = NULL;
try
{ // ErrorMessage() can throw an exception.
DWORD dwLength = StringLength( e.ErrorMessage(), 0 ) + 5 ;
lpwszGetString = ( LPWSTR )AllocateMemory( dwLength * sizeof( WCHAR ) );
if( NULL != lpwszGetString )
{
StringCopy( lpwszGetString, e.ErrorMessage(), dwLength );
StringConcat( lpwszGetString, L"\n", dwLength );
SetReason( ( LPCWSTR )lpwszGetString );
FreeMemory( (LPVOID*) &lpwszGetString );
}
else
{ // Failed to know the exact error occured
// due to insufficient memory.
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
SaveLastError();
}
}
catch( ... )
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
SaveLastError();
}
return;
}
SetReason( (LPCWSTR) bstrErrorString );
return;
}
HRESULT
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
_variant_t& varValue
)
/*++
Routine Description:
Gets the value of the property from the WMI class object
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : property name
[out] _variant_t : value of the property
Return Value:
HRESULT
--*/
{
// local variables
HRESULT hr = S_OK;
VARIANT vtValue;
// Validate input arguments.
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
return WBEM_E_INVALID_PARAMETER;
}
try
{
// initialize the variant and then get the value of the specified property
VariantInit( &vtValue );
// Call 'Get' method to retireve the value from WMI.
hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, &vtValue, NULL, NULL );
if ( FAILED( hr ) )
{
// Clear the variant variable
VariantClear( &vtValue );
// Return error.
return hr;
}
// set the value
varValue = vtValue;
}
catch( _com_error& e )
{
hr = e.Error();
}
// Clear the variables.
VariantClear( &vtValue );
// Return.
return hr;
}
HRESULT PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
VARIANT* pvarValue )
/*++
// 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
//
--*/
{
// 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;
}
BOOL PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
TARRAY arr )
/*++
Routine Description:
Gets the value of the property from the WMI class object in string format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : property name
[out] arr : value of the property
Return Value:
BOOL
--*/
{
// 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 = (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;
}
BOOL
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
CHString& strValue,
LPCWSTR pwszDefault
)
/*++
Routine Description:
Gets the value of the property from the WMI class object in string format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[out] CHString : variable to hold the retrieved property
[in] LPCWSTR : string containing the default value for the property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
HRESULT hr = S_OK;
_variant_t var;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
strValue.Empty();
try
{
// first copy the default value
strValue = pwszDefault;
// Validate input arguments.
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
_com_issue_error( WBEM_E_INVALID_PARAMETER );
}
// get the property value
hr = PropertyGet( pWmiObject, pwszProperty, var );
if ( FAILED( hr ) )
{
_com_issue_error( hr );
}
// Get the value
// If 'var' does not contain value of requested type
// then default value is returned.
if ( VT_BSTR == V_VT( &var ) )
{
strValue = (LPCWSTR) _bstr_t( var );
}
}
catch( _com_error& e )
{
WMISaveError( e );
return FALSE;
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// return
return TRUE;
}
BOOL
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
DWORD& dwValue,
DWORD dwDefault
)
/*++
Routine Description:
Gets the value of the property from the WMI class object in dword format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[out] DWORD : variable to hold the retrieved property
[in] DWORD : dword containing the default value for the property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// 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;
}
BOOL
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
BOOL& bValue,
BOOL bDefault
)
/*++
Routine Description:
Gets the value of the property from the WMI class object in bool format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[out] BOOL : variable to hold the retrieved property
[in] BOOL : bool containing the default value for the property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
HRESULT hr = S_OK;
_variant_t var;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
try
{
// first set the default value
bValue = bDefault;
// Validate input arguments.
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
_com_issue_error( WBEM_E_INVALID_PARAMETER );
}
// get the value of the property
hr = PropertyGet( pWmiObject, pwszProperty, var );
if ( FAILED( hr ) )
{
_com_issue_error( hr );
}
// Save value obtained.
// If 'var' does not contain value of requested type
// then default value is returned.
if ( VT_BOOL == V_VT( &var ) )
{
bValue = var.boolVal;
}
}
catch( _com_error& e )
{
WMISaveError( e );
return FALSE;
}
// return
return TRUE;
}
BOOL
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
ULONGLONG& ullValue
)
/*++
Routine Description:
Gets the value of the property from the WMI class object in ulongulong format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[out] ULONGULONG : variable to hold the retrieved property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// Local variables
CHString str;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
str.Empty();
try
{
// first set the default value
ullValue = 1;
// Validate input arguments.
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
// get the value of the property
if ( FALSE == PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) )
{ // Error is already set in 'PropertyGet' function.
return FALSE;
}
// get the 64-bit value
ullValue = _wtoi64( str );
// Check for error condition.
if( 0 == ullValue )
{
ullValue = 1;
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// return
return TRUE;
}
BOOL
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
WBEMTime& wbemtime )
/*++
Routine Description:
Gets the value of the property from the WMI class object in wbemtime format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[out] WBEMTime : variable to hold the retrieved property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
CHString str;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// Clear method sets the time in the WBEMTime object to an invalid time.
wbemtime.Clear();
try
{
// Validate input arguments.
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
// get the value of the property
if ( FALSE == PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) )
{ // Error is already set in 'PropertyGet' function.
return FALSE;
}
// convert into the time value
wbemtime = _bstr_t( str );
}
catch( _com_error& e )
{
WMISaveError( e );
return FALSE;
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// return
return TRUE;
}
BOOL
PropertyGet(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
SYSTEMTIME& systime )
/*++
Routine Description:
Gets the value of the property from the WMI class object in systemtime format
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[out] WBEMTime : variable to hold the retrieved property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
CHString strTime;
// Validate input arguments.
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
try
{
// get the value of the property
// 16010101000000.000000+000 is the default time
if ( FALSE == PropertyGet( pWmiObject, pwszProperty, strTime, _T( "16010101000000.000000+000" ) ) )
{ // Error is already set.
return FALSE;
}
// prepare the systemtime structure
// yyyymmddHHMMSS.mmmmmmsUUU
// NOTE: NO NEED CALL 'IsNumeric()' BEFORE 'AsLong'.
// Left and MID methods can throw an exception.
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 );
}
catch( _com_error& e )
{
WMISaveError( e );
return FALSE;
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
return FALSE;
}
// return
return TRUE;
}
HRESULT
PropertyPut(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
_variant_t& varValue
)
/*++
Routine Description:
Sets the value of the property to the WMI class object
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[in] WBEMTime : variable holding the property to set
Return Value:
TRUE on success
FALSE on failure
--*/
{
// local variables
VARIANT var;
HRESULT hr = S_OK;
// check the input value
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
return WBEM_E_INVALID_PARAMETER;
}
try
{
// put the value
var = varValue;
hr = pWmiObject->Put( _bstr_t( pwszProperty ), 0, &var, 0 );
}
catch( _com_error& e )
{
hr = e.Error();
}
// return the result
return hr;
}
HRESULT
PropertyPut(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
LPCWSTR pwszValue
)
/*++
Routine Description:
Sets the string value of the property to the WMI class object
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[in] LPCWSTR : variable holding the property to set
Return Value:
TRUE on success
FALSE on failure
--*/
{
// local variables
_variant_t varValue;
HRESULT hr = S_OK;
// check the input value
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) ||
( NULL == pwszValue ) )
{
return WBEM_E_INVALID_PARAMETER;
}
try
{
varValue = pwszValue;
SAFE_EXECUTE( PropertyPut( pWmiObject, pwszProperty, varValue ) );
}
catch( _com_error& e )
{
hr = e.Error();
}
// return
return hr;
}
HRESULT
PropertyPut(
IWbemClassObject* pWmiObject,
LPCWSTR pwszProperty,
DWORD dwValue
)
/*++
Routine Description:
Sets the dword value of the property to the WMI class object.
Arguments:
[in] IWbemClassObject : pointer to the WBEM class object
[in] LPCWSTR : the name of the property to retrieve
[in] DWORD : variable holding the property to set
Return Value:
TRUE on success
FALSE on failure
--*/
{
// local variables
_variant_t varValue;
HRESULT hr = S_OK;
// check the input value
if ( ( NULL == pWmiObject ) ||
( NULL == pwszProperty ) )
{
return WBEM_E_INVALID_PARAMETER;
}
try
{
varValue = ( LONG )dwValue;
SAFE_EXECUTE( PropertyPut( pWmiObject, pwszProperty, varValue ) );
}
catch( _com_error& e )
{
return e.Error();
}
// return
return S_OK;
}
HRESULT
RegQueryValueWMI(
IWbemServices* pWbemServices,
LPCWSTR pwszMethod,
DWORD dwHDefKey,
LPCWSTR pwszSubKeyName,
LPCWSTR pwszValueName,
_variant_t& varValue
)
/*++
Routine Description:
This function retrieves the value of the property from the specified registry key.
Arguments:
[in] IWbemServices : pointer to the IWbemServices object
[in] LPCWSTR : the name of the method to execute
[in] DWORD : the key in the registry whose value has to be retrieved
[in] LPCWSTR : the name of the subkey to retrieve
[in] LPCWSTR : the name of the value to retrieve
[in] _variant_t : variable holding the property value retrieved
Return Value:
TRUE on success
FALSE on failure
NOTE: Pass arguments of type mentioned in declaration of this function.
EX: Don't pass 'CHString' argument if 'LPWSTR' is expected.
Reason: 'CHString' can throw an exception of type 'CHEAP_EXCEPTION'
which is not handled by this function.
--*/
{
// local variables
HRESULT hr = S_OK;
BOOL bResult = FALSE;
DWORD dwReturnValue = 0;
IWbemClassObject* pClass = NULL;
IWbemClassObject* pMethod = NULL;
IWbemClassObject* pInParams = NULL;
IWbemClassObject* pInParamsInstance = NULL;
IWbemClassObject* pOutParamsInstance = NULL;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// check the input value
if ( ( NULL == pWbemServices ) ||
( NULL == pwszMethod ) ||
( NULL == pwszSubKeyName ) ||
( NULL == pwszValueName ) )
{
return WBEM_E_INVALID_PARAMETER;
}
// NOTE: If SAFE_EXECUTE( pWbemServices->GetObject(
// _bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
// is executed then,
// NO NEED TO CHECK FOR ( PCLASS == NULL ) SINCE IN ALL CASES
// OF ERROR THIS VARIABLE WILL BE NULL.
try
{
// get the registry class object
SAFE_EXECUTE( pWbemServices->GetObject(
_bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
// get the method reference required
SAFE_EXECUTE( pClass->GetMethod( pwszMethod, 0, &pInParams, NULL ) );
// create the instance for the in parameters
SAFE_EXECUTE( pInParams->SpawnInstance( 0, &pInParamsInstance ) );
// set the input values
SAFE_EXECUTE(PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_HDEFKEY ), dwHDefKey ) );
SAFE_EXECUTE(PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_SUBKEY ), pwszSubKeyName ) );
SAFE_EXECUTE(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 ( NULL == pOutParamsInstance ) // 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 ( ( FALSE == bResult ) ||
( 0 != dwReturnValue ) )
{
_com_issue_error( STG_E_UNKNOWN );
}
// Comapre string and take appropriate action.
if ( 0 == StringCompare( pwszMethod, WMI_REGISTRY_M_DWORDVALUE, TRUE, 0 ) )
{
SAFE_EXECUTE( PropertyGet( pOutParamsInstance,
_bstr_t( WMI_REGISTRY_OUT_VALUE_DWORD ), varValue ) );
}
else
{
SAFE_EXECUTE( PropertyGet( pOutParamsInstance,
_bstr_t( WMI_REGISTRY_OUT_VALUE ), varValue ) );
}
}
catch( _com_error& e )
{
hr = e.Error();
}
// release the interfaces
SAFE_RELEASE( pClass );
SAFE_RELEASE( pMethod );
SAFE_RELEASE( pInParams );
SAFE_RELEASE( pInParamsInstance );
SAFE_RELEASE( pOutParamsInstance );
// return success
return hr;
}
BOOL
RegQueryValueWMI(
IWbemServices* pWbemServices,
DWORD dwHDefKey,
LPCWSTR pwszSubKeyName,
LPCWSTR pwszValueName,
CHString& strValue,
LPCWSTR pwszDefault
)
/*++
Routine Description:
This function retrieves the string value of the property from the specified registry key.
Arguments:
[in] IWbemServices : pointer to the IWbemServices object
[in] DWORD : the key in the registry whose value has to be retrieved
[in] LPCWSTR : the name of the subkey to retrieve
[in] LPCWSTR : the name of the value to retrieve
[out] CHString : variable holding the property value retrieved
[in] LPCWSTR : the default value for this property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF '0' IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
This function won't return values if they are obtained as reference
from WMI.
EX: 'VARTYPE' recieved is of type 'VT_BSTR | VT_BYREF' then FALSE is
returned.
--*/
{
// local variables
HRESULT hr = S_OK;
_variant_t varValue;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// Check the input
if ( ( NULL == pWbemServices ) ||
( NULL == pwszSubKeyName ) ||
( NULL == pwszValueName ) )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
try
{
// Set the default value
if ( NULL != pwszDefault )
{
strValue = pwszDefault;
}
// Get the value
hr = RegQueryValueWMI( pWbemServices,
WMI_REGISTRY_M_STRINGVALUE, dwHDefKey, pwszSubKeyName, pwszValueName, varValue );
if ( FAILED( hr ) )
{
WMISaveError( hr );
return FALSE;
}
// Get the value from the variant
// Get the value
if ( VT_BSTR == V_VT( &varValue ) )
{
strValue = (LPCWSTR)_bstr_t( varValue );
}
else
{
// Requested type is not found.
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
}
catch( _com_error& e )
{ // Exception throw by '_variant_t'.
WMISaveError( e );
return FALSE;
}
// return success
return TRUE;
}
BOOL
RegQueryValueWMI(
IWbemServices* pWbemServices,
DWORD dwHDefKey,
LPCWSTR pwszSubKeyName,
LPCWSTR pwszValueName,
DWORD& dwValue,
DWORD dwDefault
)
/*++
Routine Description:
This function retrieves the dword value of the property from the specified registry key.
Arguments:
[in] IWbemServices : pointer to the IWbemServices object
[in] DWORD : the key in the registry whose value has to be retrieved
[in] LPCWSTR : the name of the subkey to retrieve
[in] LPCWSTR : the name of the value to retrieve
[out] DWORD : variable holding the property value retrieved
[in] DWORD : the default value for this property
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF '0' IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
This function won't return values if they are obtained as reference
from WMI.
EX: 'VARTYPE' recieved is of type 'VT_I4 | VT_BYREF' then FALSE is
returned.
--*/
{
// local variables
HRESULT hr = S_OK;
_variant_t varValue;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// Check the input.
if ( ( NULL == pWbemServices ) ||
( NULL == pwszSubKeyName ) ||
( NULL == pwszValueName ) ||
( NULL == dwValue ) )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
try
{
// Set the default value.
dwValue = dwDefault;
// Get the value.
hr = RegQueryValueWMI( pWbemServices, WMI_REGISTRY_M_DWORDVALUE, dwHDefKey,
pwszSubKeyName, pwszValueName, varValue );
if ( FAILED( hr ) )
{
WMISaveError( hr );
return FALSE;
}
// get the value from the variant
switch( V_VT( &varValue ) )
{
case VT_I2:
dwValue = V_I2( &varValue );
break;
case VT_I4:
dwValue = V_I4( &varValue );
break;
case VT_UI2:
dwValue = V_UI2( &varValue );
break;
case VT_UI4:
dwValue = V_UI4( &varValue );
break;
case VT_INT:
dwValue = V_INT( &varValue );
break;
case VT_UINT:
dwValue = V_UINT( &varValue );
break;
default:
// Requested type is not found.
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
}
catch( _com_error& e )
{ // Exception thrown by _variant_t
WMISaveError( e );
return FALSE;
}
// return success
return TRUE;
}
DWORD
GetTargetVersionEx(
IWbemServices* pWbemServices,
COAUTHIDENTITY* pAuthIdentity
)
/*++
Routine Description:
This function gets the version of the system from which we are trying to retrieve
information from.
Arguments:
[in] IWbemServices : pointer to the IWbemServices object
[in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
Return Value:
DWORD - Target version of the machine if found else 0.
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF '0' IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// local variables
HRESULT hr = S_OK;
LONG lPos = 0;
DWORD dwMajor = 0;
DWORD dwMinor = 0;
DWORD dwVersion = 0;
ULONG ulReturned = 0;
CHString strVersion;
IWbemClassObject* pWbemObject = NULL;
IEnumWbemClassObject* pWbemInstances = NULL;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// Check the input value
if ( NULL == pWbemServices )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return 0;
}
try
{
// get the OS information
SAFE_EXECUTE( pWbemServices->CreateInstanceEnum(
_bstr_t( CLASS_CIMV2_Win32_OperatingSystem ),
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, 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 ( 0 == ulReturned )
{
// release the interfaces
WMISaveError( WBEM_S_FALSE );
SAFE_RELEASE( pWbemObject );
SAFE_RELEASE( pWbemInstances );
return 0;
}
// now get the os version value
if ( FALSE == PropertyGet( pWbemObject, L"Version", strVersion ) )
{
// release the interfaces
// Error is already set in the called function.
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 ( -1 == lPos )
{
// The version string itself is version ... THIS WILL NEVER HAPPEN
if( FALSE == IsNumeric( strVersion, 10, FALSE ) )
{
return 0;
}
dwMajor = AsLong( strVersion, 10 );
}
else
{
// major version
if( FALSE == IsNumeric( strVersion.Mid( 0, lPos ), 10, FALSE ) )
{
return 0;
}
dwMajor = AsLong( strVersion.Mid( 0, lPos ), 10 );
// get the minor version
strVersion = strVersion.Mid( lPos + 1 );
lPos = strVersion.Find( L'.' );
if ( -1 == lPos)
{
if( FALSE == IsNumeric( strVersion, 10, FALSE ) )
{
return 0;
}
dwMinor = AsLong( strVersion, 10 );
}
else
{
if( FALSE == IsNumeric( strVersion.Mid( 0, lPos ), 10, FALSE ) )
{
return 0;
}
dwMinor = AsLong( strVersion.Mid( 0, lPos ), 10 );
}
}
// mix the version info
dwVersion = dwMajor * 1000 + dwMinor;
}
catch( _com_error& e )
{
WMISaveError( e );
SAFE_RELEASE( pWbemObject );
SAFE_RELEASE( pWbemInstances );
return 0;
}
catch( CHeap_Exception )
{
WMISaveError( WBEM_E_OUT_OF_MEMORY );
SAFE_RELEASE( pWbemObject );
SAFE_RELEASE( pWbemInstances );
return 0;
}
// If successful then 'pWbemObject' and 'pWbemInstances' are already released.
// return
return dwVersion;
}
BOOL
GetPropertyFromSafeArray(
SAFEARRAY *pSafeArray,
LONG lIndex,
CHString& strValue,
VARTYPE vartype
)
/*++
Routine Description:
This function retrieves a property from the safe array.
Arguments:
[in] SAFEARRAY : pointer to the array of elements
[in] LONG : index to retrieve the data from
[out] CHString : variable to hold the return value
[in] VARTYPE : The type of variable to retrieve from the array
Return Value:
TRUE on success
FALSE on failure
NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
--*/
{
// Local variables.
VARIANT var;
HRESULT hRes = S_OK;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// Check the inputs.
if ( NULL == pSafeArray )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
// Initialize variant.
VariantInit( &var );
try
{
// get the value
V_VT( &var ) = vartype;
hRes = SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
if( FAILED( hRes ) )
{ // Set error occured.
WMISaveError( hRes );
VariantClear( &var );
return FALSE;
}
// Store requested information in
switch( vartype )
{
case VT_BSTR:
strValue = (LPCWSTR)_bstr_t( var );
break;
default:
WMISaveError( WBEM_E_INVALID_PARAMETER );
VariantClear( &var );
return FALSE;
}
}
catch( CHeap_Exception )
{ // Exception thrown from 'strValue'.
WMISaveError( WBEM_E_OUT_OF_MEMORY );
VariantClear( &var );
return FALSE; // failure
}
// Clean-Up and return.
VariantClear( &var );
return TRUE;
}
BOOL
GetPropertyFromSafeArray(
SAFEARRAY *pSafeArray,
LONG lIndex,
IWbemClassObject **pScriptObject,
VARTYPE vartype
)
/*++
Routine Description:
This function retrieves a property from the safe array.
Arguments:
[in] SAFEARRAY : pointer to the array of elements
[in] LONG : index to retrieve the data from
[out] IWbemClassObject : variable to hold the return value
[in] VARTYPE : The type of variable to retrieve from the array
Return Value:
TRUE on success
FALSE on failure
NOTE: CALLED FUNCTION HAS TO MAKE SURE THAT '*pScriptObject' DOES NOT CONTAIN ANY
VALUE WHICH MAY CAUSE MEMORY LEAK.
THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
NOTE: If TRUE is returned then 'VariantClear' is not called over 'var' since if
a call is made to 'Variantcler' we will loose Interface pointer. Not calling
'VariantClear' will free 'var' when its out of scope and leaving
the interface pointer in memory which can be used by the called function.
IT IS CALLING FUNCTION RESPONSIBILITY TO RELEASE THE INTERFACE POINTER.
--*/
{
// Local variables.
VARIANT var;
HRESULT hRes = S_OK;
// Clear any errors.
SetLastError( WBEM_S_NO_ERROR );
// Validate the inputs
if ( ( NULL == pSafeArray ) ||
( NULL == pScriptObject ) )
{
WMISaveError( WBEM_E_INVALID_PARAMETER );
return FALSE;
}
// Initialize variant.
VariantInit( &var );
// Set type of value expected.
V_VT( &var ) = vartype;
hRes = SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
// check for return value.
if( FAILED( hRes ) )
{ // Set error occured.
WMISaveError( hRes );
VariantClear( &var );
return FALSE;
}
// Store information requested.
switch( vartype )
{
case VT_UNKNOWN:
*pScriptObject = (IWbemClassObject *) var.punkVal;
break;
default:
WMISaveError( WBEM_E_INVALID_PARAMETER );
VariantClear( &var );
return FALSE;
}
// return
return TRUE;
}