|
|
/*++
Copyright (c) Microsoft Corporation
Module Name: CONNECTWMI.cpp
Abstract: Contains functions to connect to wmi.
Author: Vasundhara .G
Revision History: Vasundhara .G 26-sep-2k : Created It. --*/
// Include files
#include "pch.h"
#include "getmac.h"
#include "resource.h"
// messages
#define INPUT_PASSWORD GetResString( IDS_STR_INPUT_PASSWORD )
// error constants
#define E_SERVER_NOTFOUND 0x800706ba
// function prototypes
BOOL IsValidUserEx( IN LPCWSTR pwszUser );
HRESULT GetSecurityArguments( IN IUnknown *pInterface, OUT DWORD& dwAuthorization, OUT DWORD& dwAuthentication );
HRESULT SetInterfaceSecurity( IN IUnknown *pInterface, IN LPCWSTR pwszUser, IN LPCWSTR pwszPassword, OUT COAUTHIDENTITY **ppAuthIdentity );
HRESULT WINAPI SetProxyBlanket( IN IUnknown *pInterface, IN DWORD dwAuthnSvc, IN DWORD dwAuthzSvc, IN LPWSTR pwszPrincipal, IN DWORD dwAuthLevel, IN DWORD dwImpLevel, IN RPC_AUTH_IDENTITY_HANDLE pAuthInfo, IN DWORD dwCapabilities );
HRESULT WINAPI WbemAllocAuthIdentity( IN LPCWSTR pwszUser, IN LPCWSTR pwszPassword, IN LPCWSTR pwszDomain, OUT COAUTHIDENTITY **ppAuthIdent );
BOOL PropertyGet( IN IWbemClassObject *pWmiObject, IN LPCWSTR pwszProperty, OUT CHString& strValue, IN LPCWSTR pwszDefault = V_NOT_AVAILABLE );
BOOL PropertyGet( IN IWbemClassObject* pWmiObject, IN LPCWSTR pwszProperty, OUT CHString& strValue, IN LPCWSTR pwszDefault );
HRESULT PropertyGet( IN IWbemClassObject* pWmiObject, IN LPCWSTR pwszProperty, OUT _variant_t& varValue );
BOOL IsValidUserEx( IN LPCWSTR pwszUser ) /*++
Routine Description: Validates the user name.
Arguments: [IN] pwszUser - Holds the user name to be validated.
Return Value: returns TRUE if user name is a valid user else FALSE. --*/ { // local variables
CHString strUser; LONG lPos = 0;
if ( ( NULL == pwszUser ) ) { return TRUE; } if( 0 == StringLength( pwszUser, 0 ) ) { return TRUE; }
try { // get user into local memory
strUser = pwszUser;
// user name should not be just '\'
if ( 0 == strUser.CompareNoCase( L"\\" ) ) { return FALSE; } // user name should not contain invalid characters
if ( -1 != strUser.FindOneOf( L"/[]:|<>+=;,?*" ) ) { return FALSE; } 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( IN LPCWSTR pwszServer, OUT BOOL &bLocalSystem ) /*++
Routine Description: Checks whether the server name is a valid server name or not.
Arguments: [IN] pwszServer - Server name to be validated. [OUT] bLocalSystem - Set to TRUE if server specified is local system.
Return Value: TRUE if server is valid else FALSE. --*/ { // local variables
CHString strTemp;
if( NULL == pwszServer ) { return FALSE; }
if( 0 == StringLength( pwszServer, 0 ) ) { bLocalSystem = TRUE; return TRUE; } bLocalSystem = FALSE; try { // get a local copy
strTemp = pwszServer;
if( TRUE == IsNumeric( pwszServer, 10, FALSE ) ) { return FALSE; }
// remove the forward slashes (UNC) if exist in the begining of the server name
if ( TRUE == IsUNCFormat( strTemp ) ) { strTemp = strTemp.Mid( 2 ); if ( 0 == strTemp.GetLength() ) { return FALSE; } } if ( -1 != strTemp.FindOneOf( L"`~!@#$^&*()+=[]{}|\\<>,?/\"':;" ) ) { return FALSE; }
// now check if any '\' character appears in the server name. If so error
if ( -1 != strTemp.Find( L'\\' ) ) { 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 ( 0 == strTemp.CompareNoCase( L"." ) ) { bLocalSystem = TRUE; } else { bLocalSystem = IsLocalSystem( strTemp ); } } catch( CHeap_Exception ) { WMISaveError( WBEM_E_OUT_OF_MEMORY ); return FALSE; }
// valid server name
return TRUE; }
BOOL ConnectWmi( IN IWbemLocator *pLocator, OUT IWbemServices **ppServices, IN LPCWSTR pwszServer, OUT LPCWSTR pwszUser, OUT LPCWSTR pwszPassword, OUT COAUTHIDENTITY **ppAuthIdentity, IN BOOL bCheckWithNullPwd, IN LPCWSTR pwszNamespace, OUT HRESULT *phRes, OUT BOOL *pbLocalSystem ) /*++
Routine Description: Connects to wmi.
Arguments: [IN] pLocator - Pointer to the IWbemLocator object. [OUT] ppServics - Pointer to IWbemServices object. [IN] pwszServer - Holds the server name to connect to. [OUT] pwszUser - Holds the user name. [OUT] pwszPassword - Holds the password. [OUT] ppAuthIdentity - Pointer to authentication structure. [IN] bCheckWithNullPwd - Specifies whether to connect through null password. [IN] pwszNamespace - Specifies the namespace to connect to. [OUT] hRes - Holds the error value. [OUT] pbLocalSystem - Holds the boolean value to represent whether the server name is local or not. Return Value: TRUE if successfully connected, FALSE if not. --*/ { // local variables
HRESULT hRes = 0; BOOL bResult = FALSE; BOOL bLocalSystem = FALSE; _bstr_t bstrServer; _bstr_t bstrNamespace; _bstr_t bstrUser; _bstr_t bstrPassword;
// clear the error
SetLastError( WBEM_S_NO_ERROR );
if ( NULL != pbLocalSystem ) { *pbLocalSystem = FALSE; } if ( NULL != phRes ) { *phRes = WBEM_S_NO_ERROR; }
// check whether locator object exists or not
// if not exists, return
if ( ( NULL == pLocator ) || ( NULL == ppServices ) || ( NULL != *ppServices ) || ( NULL == pwszNamespace ) || ( NULL == pbLocalSystem ) ) { if ( NULL != phRes ) { *phRes = WBEM_E_INVALID_PARAMETER; } // return failure
return FALSE; }
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 ( FALSE == IsValidServerEx( pwszServer, bLocalSystem ) ) { _com_issue_error( E_SERVER_NOTFOUND ); } // validate the user name
if ( FALSE == IsValidUserEx( pwszUser ) ) { _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 ( TRUE == IsUNCFormat( pwszServer ) ) { 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; } } }
// 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
hRes = pLocator->ConnectServer( bstrNamespace, bstrUser, bstrPassword, 0L, 0L, NULL, NULL, ppServices ); if ( FAILED( hRes ) ) { //
// 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 ( E_ACCESSDENIED == hRes ) { // 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 ...
hRes = pLocator->ConnectServer( bstrNamespace, bstrUser, _bstr_t( L"" ), 0L, 0L, NULL, NULL, ppServices ); } } else if ( WBEM_E_LOCAL_CREDENTIALS == hRes ) { // 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
hRes = pLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, ppServices ); // check the result
if ( SUCCEEDED( hRes ) && NULL != phRes ) { // set the last error
*phRes = WBEM_E_LOCAL_CREDENTIALS; } } else if ( REGDB_E_CLASSNOTREG == hRes ) { SetReason( ERROR_REMOTE_INCOMPATIBLE ); *phRes = REGDB_E_CLASSNOTREG; bResult = FALSE; return bResult; }
// now check the result again .. if failed .. ummmm..
if ( FAILED( hRes ) ) { _com_issue_error( hRes ); } else { bstrPassword = L""; } }
// set the security at the interface level also
SAFE_EXECUTE( SetInterfaceSecurity( *ppServices, bstrUser, bstrPassword, ppAuthIdentity ) );
// connection to WMI is successful
bResult = TRUE;
// save the hr value if needed by the caller
if ( NULL != phRes ) { *phRes = WBEM_S_NO_ERROR; } if ( NULL != pbLocalSystem ) { *pbLocalSystem = bLocalSystem; } bResult = TRUE; } catch( _com_error& e ) { // save the error
WMISaveError( e );
// save the hr value if needed by the caller
if ( NULL != phRes ) { *phRes = e.Error(); } SAFE_RELEASE( *ppServices ); bResult = FALSE;
}
return bResult; }
BOOL ConnectWmiEx( IN IWbemLocator *pLocator, OUT IWbemServices **ppServices, IN LPCWSTR strServer, OUT CHString &strUserName, OUT CHString &strPassword, OUT COAUTHIDENTITY **ppAuthIdentity, IN BOOL bNeedPassword, IN LPCWSTR pwszNamespace, OUT BOOL *pbLocalSystem ) /*++
Routine Description: Connects to wmi.
Arguments: [IN] pLocator - Pointer to the IWbemLocator object. [OUT] ppServices - Pointer to IWbemServices object. [IN] strServer - Holds the server name to connect to. [OUT] strUserName - Holds the user name. [OUT] strPassword - Holds the password. [OUT] ppAuthIdentity - Pointer to authentication structure. [IN] bNeedPassword - Specifies whether to prompt for password. [IN] pwszNamespace - Specifies the namespace to connect to. [OUT] pbLocalSystem - Holds the boolean value to represent whether the server name is local or not. Return Value: TRUE if successfully connected, FALSE if not. --*/ { // local variables
HRESULT hRes = 0; DWORD dwSize = 0; BOOL bResult = FALSE; LPWSTR pwszPassword = NULL;
try {
CHString strBuffer = L"\0";
// 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 ( 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, strServer, NULL, NULL, ppAuthIdentity, FALSE, pwszNamespace, &hRes, pbLocalSystem ); } else { // credentials were supplied
// but password might not be specified ... so check and act accordingly
LPCWSTR pwszTemp = NULL; BOOL bCheckWithNull = TRUE; if ( FALSE == bNeedPassword ) { pwszTemp = strPassword; bCheckWithNull = FALSE; }
// ...
bResult = ConnectWmi( pLocator, ppServices, strServer, strUserName, pwszTemp, ppAuthIdentity, bCheckWithNull, pwszNamespace, &hRes, pbLocalSystem ); }
// check the result ... if successful in establishing connection ... return
if ( TRUE == bResult ) { SetLastError( hRes ); // set the error code
return TRUE; } // now check the kind of error occurred
switch( hRes ) { 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( hRes ); return FALSE; // no use of accepting the password .. return failure
}
// 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 ( FALSE == bNeedPassword ) { 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;
// get the required buffer
pwszUserName = strUserName.GetBufferSetLength( MAX_STRING_LENGTH );
// get the user name
DWORD dwUserLength = MAX_STRING_LENGTH; if ( FALSE == GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength ) ) { // error occured while trying to get the current user info
SaveLastError(); return( FALSE ); }
// release the extra buffer allocated
strUserName.ReleaseBuffer(); }
// get the required buffer
pwszPassword = strPassword.GetBufferSetLength( MAX_STRING_LENGTH );
// accept the password from the user
strBuffer.Format( INPUT_PASSWORD, strUserName ); WriteConsoleW( GetStdHandle( STD_OUTPUT_HANDLE ), strBuffer, strBuffer.GetLength(), &dwSize, NULL ); bResult = GetPassword( pwszPassword, 256 ); 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, strServer, strUserName, strPassword, ppAuthIdentity, FALSE, pwszNamespace, &hRes, pbLocalSystem );
} catch(CHeap_Exception) { WMISaveError( WBEM_E_OUT_OF_MEMORY ); return FALSE; } // return the success
return bResult;
}
HRESULT GetSecurityArguments( IN IUnknown *pInterface, OUT DWORD& dwAuthorization, OUT DWORD& dwAuthentication ) /*++
Routine Description: Gets the security arguments for an interface.
Arguments: [IN] pInterface - Pointer to interface stucture. [OUT] dwAuthorization - Holds Authorization value. [OUT] dwAuthentication - Holds the Authentication value.
Return Value: Returns HRESULT value. --*/ { // local variables
HRESULT hRes = 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
hRes = pInterface->QueryInterface( IID_IClientSecurity, (void**) &pClientSecurity ); if ( SUCCEEDED( hRes ) ) { // got the client security interface
// now try to get the security services values
hRes = pClientSecurity->QueryBlanket( pInterface, &dwAuthnSvc, &dwAuthzSvc, NULL, NULL, NULL, NULL, NULL ); if ( SUCCEEDED( hRes ) ) { // we've got the values from the interface
dwAuthentication = dwAuthnSvc; dwAuthorization = dwAuthzSvc; }
// release the client security interface
SAFE_RELEASE( pClientSecurity ); }
// return always success
return hRes; }
HRESULT SetInterfaceSecurity( IN IUnknown *pInterface, IN LPCWSTR pwszUser, IN LPCWSTR pwszPassword, OUT COAUTHIDENTITY **ppAuthIdentity ) /*++
Routine Description: Sets interface security.
Arguments: [IN] pInterface - Pointer to the interface to which security has to be set. [IN] pwszUser - Holds the user name of the server. [IN] pwszPassword - Hold the password of the user. [OUT] ppAuthIdentity - Pointer to authentication structure.
Return Value: returns HRESULT value. --*/ { // local variables
HRESULT hRes = 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 ); } // 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 ( NULL == pwszUser && NULL == pwszPassword ) { // set the security
hRes = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
// return the result
return hRes; }
// 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 ); }
// 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; } // check if authenication info is available or not ...
// initialize the security authenication information ... UNICODE VERSION STRUCTURE
if ( NULL == ppAuthIdentity ) { return WBEM_E_INVALID_PARAMETER; } else if ( NULL == *ppAuthIdentity ) { hRes = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity ); if ( FAILED(hRes) ) { return hRes; } }
// set the security information to the interface
hRes = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
} catch(CHeap_Exception) { hRes = WBEM_E_OUT_OF_MEMORY; } // return the result
return hRes;
}
HRESULT SetInterfaceSecurity( IN IUnknown *pInterface, IN COAUTHIDENTITY *pAuthIdentity ) /*++
Routine Description: Sets the interface security for the interface.
Arguments: [IN] pInterface - pointer to the interface. [IN] pAuthIdentity - pointer to authentication structure.
Return Value: returns HRESULT value. --*/ { // local variables
HRESULT hRes = S_OK; DWORD dwAuthorization = RPC_C_AUTHZ_NONE; DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
// check the interface
if ( NULL == pInterface ) { return WBEM_E_INVALID_PARAMETER; } // get the current security argument value
hRes = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication ); if ( FAILED( hRes ) ) { return hRes; } // set the security information to the interface
hRes = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
// return the result
return hRes; }
HRESULT WINAPI SetProxyBlanket( IN IUnknown *pInterface, IN DWORD dwAuthnSvc, IN DWORD dwAuthzSvc, IN LPWSTR pwszPrincipal, IN DWORD dwAuthLevel, IN DWORD dwImpLevel, IN RPC_AUTH_IDENTITY_HANDLE pAuthInfo, IN DWORD dwCapabilities ) /*++
Routine Description: Sets proxy blanket for the interface.
Arguments: [IN] pInterface - pointer to the inteface. [IN] dwAuthnsvc - Authentication service to use. [IN] dwAuthzSvc - Authorization service to use. [IN] pwszPricipal - Server principal name to use with the authentication service. [IN] dwAuthLevel - Authentication level to use. [IN] dwImpLevel - Impersonation level to use. [IN] pAuthInfo - Identity of the client. [IN] dwCapabilities - Capability flags.
Return Value: Return HRESULT value. --*/ { // local variables
HRESULT hRes = 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
hRes = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown ); if ( FAILED( hRes ) ) { return hRes; } // now get the client security interface
hRes = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity ); if ( FAILED( hRes ) ) { SAFE_RELEASE( pUnknown ); return hRes; }
// now set the security
hRes = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal, dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
if( FAILED( hRes ) ) { SAFE_RELEASE( pUnknown ); SAFE_RELEASE( pClientSecurity ); return hRes; }
// release the security interface
SAFE_RELEASE( pClientSecurity );
// we should check the auth identity structure. if exists .. set for IUnknown also
if ( NULL != pAuthInfo ) { hRes = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity ); if ( SUCCEEDED( hRes ) ) { // set security authentication
hRes = pClientSecurity->SetBlanket( pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal, dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
// release
SAFE_RELEASE( pClientSecurity ); } else if ( E_NOINTERFACE == hRes ) { hRes = S_OK; // ignore no interface errors
} }
// release the IUnknown
SAFE_RELEASE( pUnknown );
// return the result
return hRes; }
HRESULT WINAPI WbemAllocAuthIdentity( IN LPCWSTR pwszUser, IN LPCWSTR pwszPassword, IN LPCWSTR pwszDomain, OUT COAUTHIDENTITY **ppAuthIdent ) /*++
Routine Description: Allocate memory for authentication variables.
Arguments: [IN] pwszUser - User name. [IN] pwszPassword - Password. [IN] pwszDomain - Domain name. [OUT] ppAuthIdent - Pointer to authentication structure.
Return Value: Returns HRESULT value. --*/ { // 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 ( pAuthIdent == NULL ) { 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( IN COAUTHIDENTITY** ppAuthIdentity ) /*++
Routine Description: Frees the memory of authentication stucture variable.
Arguments: [IN] ppAuthIdentity - Pointer to authentication structure.
Return Value: none. --*/ { // make sure we have a pointer, then walk the structure members and cleanup.
if ( NULL != *ppAuthIdentity ) { // 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( IN HRESULT hResError ) /*++
Routine Description: Gets WMI error description.
Arguments: [IN] hResError - Contain error value.
Return Value: none. --*/ { // local variables
HRESULT hRes; IWbemStatusCodeText *pWbemStatus = NULL;
CHString strBuffer = L"\0";
// if the error is win32 based, choose FormatMessage to get the message
switch( hResError ) { 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 ( E_ACCESSDENIED == hResError ) { hResError = ERROR_LOGON_FAILURE; } // ...
SetLastError( hResError ); SaveLastError(); return; } case REGDB_E_CLASSNOTREG: // Message: Class not registered.
{ SetLastError( hResError ); SetReason( ERROR_REMOTE_INCOMPATIBLE ); return; }
}
try { // get the pointer to buffer
LPWSTR pwszBuffer = NULL; pwszBuffer = strBuffer.GetBufferSetLength( MAX_STRING_LENGTH );
// get the wbem specific status code text
hRes = CoCreateInstance( CLSID_WbemStatusCodeText, NULL, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, ( LPVOID* ) &pWbemStatus );
// check whether we got the interface or not
if ( SUCCEEDED( hRes ) ) { // get the error message
BSTR bstr = NULL; hRes = pWbemStatus->GetErrorCodeText( hResError, 0, 0, &bstr ); if ( SUCCEEDED( hRes ) ) { // get the error message in proper format
StringCopyW( pwszBuffer, bstr, MAX_STRING_LENGTH );
// 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( hResError ); } } else { // failed to get the error message ... get the com specific error message
_com_issue_error( hResError ); }
// release the buffer
strBuffer.ReleaseBuffer(); // set the reason
strBuffer += L"\n"; SetReason( strBuffer );
} catch( _com_error& e ) { try { // get the error message
strBuffer.ReleaseBuffer(); if ( NULL != e.ErrorMessage() ) { strBuffer = e.ErrorMessage(); } } catch( CHeap_Exception ) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); SaveLastError(); } } catch(CHeap_Exception) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); SaveLastError(); return; } }
DWORD GetTargetVersionEx( IN IWbemServices* pWbemServices, IN COAUTHIDENTITY* pAuthIdentity ) /*++
Routine Description: Get the OS version of the target machine. Arguments: [IN] pWbemServices - Pointer to IWbemServices object. [IN] pAuthIdentity - Poointer to authentication structure. Return Value: 0 if failed to get version number, else non-zero value. --*/ { // local variables
HRESULT hRes = S_OK; LONG lPos = 0; DWORD dwMajor = 0; DWORD dwMinor = 0; DWORD dwVersion = 0; ULONG ulReturned = 0; IWbemClassObject* pWbemObject = NULL; IEnumWbemClassObject* pWbemInstances = NULL; CHString strVersion;
// 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
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; }
// return
return dwVersion; }
BOOL PropertyGet( IN IWbemClassObject* pWmiObject, IN LPCWSTR pwszProperty, OUT CHString& strValue, IN LPCWSTR pwszDefault ) /*++
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 : the name of the property to retrieve [OUT] strValue : variable to hold the retrieved property [IN] pwszDefault : 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 hRes = 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
hRes = PropertyGet( pWmiObject, pwszProperty, var ); if ( FAILED( hRes ) ) { _com_issue_error( hRes ); }
// 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; }
HRESULT PropertyGet( IN IWbemClassObject* pWmiObject, IN LPCWSTR pwszProperty, OUT _variant_t& varValue ) /*++
Routine Description: Gets the value of the property from the WMI class object Arguments: [IN] pWmiObject : pointer to the WBEM class object [IN] pwszProperty : property name [OUT] varValue : value of the property Return Value: HRESULT --*/ { // local variables
HRESULT hRes = 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.
hRes = pWmiObject->Get( _bstr_t( pwszProperty ), 0, &vtValue, NULL, NULL ); if ( FAILED( hRes ) ) { // Clear the variant variable
VariantClear( &vtValue ); // Return error.
return hRes; }
// set the value
varValue = vtValue; } catch( _com_error& e ) { hRes = e.Error(); }
// Clear the variables.
VariantClear( &vtValue ); // Return.
return hRes; }
|