Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Connect System using WMI Services

0.00/5 (No votes)
22 Apr 2014 1  
Connect Systems using WMI Services, Remote as well as Local
WMI behaves different on various Operating Systems. The code presented in this Tip/Trick was tested with Window XP SP2, SP3 (both Domain and Workgroup), Windows 7 SP1 (Domain), Windows Server 2003 SP2 and Windows 8 (Domain).

Introduction

Apologies for any grammatical mistakes in this tip. This tip is all about connecting WMI Services to local and remote computer.

Background

Well, first I thought of not writing the tip, as there were 'N' number of codes present on the internet. But many times, the codes were not upto the mark. This eventually led to me writing this article. Hope I have achieved it.

Using the Code

Many times while connecting to WMI Services, I used to get Access Denied as the Error Message. But, I did not lose faith on VC++, Thanks to MSDN for that.

Here is a simple program to connect to Remote System using WMI Services.

On Every Step, I checked for the Security for the Remote System.

I found the code to get the Host Name, and Domain Name from:

http://msdn.microsoft.com/en-us/library/ms992621%28v=EXCHG.65%29.aspx

The above part is necessary as we do not know whether, accidentally, we give the Local Computer Name because unlike the Explorer, the connection to local computer with WMI classes cannot be done. Hence for precaution, I have used this. Also we do not know if the entered value is Computer Name or IP Address. Hence, we used the Is3Dots. If IP Address is provided, get the host (computer) name of the provided IP, and then perform the comparison.

CREDUI_INFO structure is used to pass the structure used for "CredUIPromptForCredentials". This provides the credential dialog box extract the User Name and Password. Once we have the User Name, and Password, we can preserve it for future use. The Important thing to note over here is-

slash = _tcschr ( pszName , L'\\' ) ;
if ( slash == NULL )
{
    AfxMessageBox ( _T("Could not create Auth identity. No domain specified\nEnter the Credentails as \"DomainName\\UserName\"") ) ;
                        
    continue ;
}  

This is ensure that we get the User Name and Domain Name in one shot.

Run the window till the User name and Password provided matches with the Windows credentials of the remote computer or the process is cancelled. After we get the User Name and Password, we validate the credential, we first cancel all the credentials set for the Remote Computer using WNetCancelConnection2 (http://msdn.microsoft.com/en-us/library/windows/desktop/aa385427%28v=vs.85%29.aspx), and use WNetUseConnection (http://msdn.microsoft.com/en-us/library/windows/desktop/aa385482%28v=vs.85%29.aspx) which validates for the connection details by the User Name and Password. Unlike WNetAddConnection (http://msdn.microsoft.com/en-us/library/windows/desktop/aa385413%28v=vs.85%29.aspx) this will use the credentials earlier provided.

This is put in a loop till either Success of Cancel Operation is performed.

After we are validated with the Remote System, we can connect to the WMI Services of the Remote System by the Step-4:

 hres = pLoc->ConnectServer(
        _bstr_t ( strServer ),
        _bstr_t ( useToken ? NULL : pszName ) ,   // User name
        _bstr_t ( useToken ? NULL : pszPwd  ) ,   // User password
        NULL,                              // Locale             
        NULL,                              // Security flags
        _bstr_t ( useNTLM ? NULL : pszAuthority ) ,// Authority        
        NULL,                              // Context object 
        &pSvc                              // IWbemServices proxy
        ); 

The strServer for Local Computer would be-

strServer = _T("\\\\.\\root\\cimv2") ;  

The strServer for Remote System would be-

strServer = _T("\\\\<Computer_Name> or <IP Address>\\root\\cimv2") ;  

The COAUTHIDENTITY plays an important part in Step-5 that can be used for setting security on proxy.

The main issue will be in connection and with proper logic to swing the ball in air. This can be achieved by "CoSetProxyBlanket" (http://msdn.microsoft.com/en-us/library/aa910618.aspx). This makes the Half Battle Win right at the start, with proper use only. This is done in Step-6 and Step 8:

CoSetProxyBlanket(
        pSvc,                           // Indicates the proxy to set
        RPC_C_AUTHN_DEFAULT,            // RPC_C_AUTHN_xxx
        RPC_C_AUTHZ_DEFAULT,            // RPC_C_AUTHZ_xxx
        COLE_DEFAULT_PRINCIPAL,         // Server principal name 
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,  // RPC_C_AUTHN_LEVEL_xxx 
        RPC_C_IMP_LEVEL_IMPERSONATE,    // RPC_C_IMP_LEVEL_xxx
        userAcct,                       // client identity
        EOAC_NONE                       // proxy capabilities 
    );  

Like every other language, C++ too maintains the security with WMI classes, which not only helps users for proper validation of credentials on the Remote system, but also developers to maintain the Security to avoid any kind of flaw or leak in the Credential Validation.

After binding with the credentials, we are all set to go for getting all the required information in ExecQuery, which is done in Step-7. The Function looks like-

IEnumWbemClassObject* pEnumerator = NULL ;
hres = pSvc->ExecQuery ( SysAllocString(L"WQL"),  SysAllocString(L"Select * from Win32_LogicalDisk"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_WBEM_COMPLETE , 
        NULL , &pEnumerator ) ; 

The Important part after the Credentials is the running of the Query. In this sample, I used-Win32_LogicalDisk. This function is Case In-sensitive.

Step 7 deals with the extraction of data that is required. In this example, I only needed the Logical Disk Name and its Drive Letter.

I used the GetErrorMessage function after every step, so as to get an idea where the code generation has failed and get the error Message appropriately from the system.

void GetErrorMessage ( HRESULT hresRet = NULL, CString strText = _T("") )
{
    LPVOID lpMsgBuf = NULL ;
    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL , hresRet , 0, (LPTSTR) &lpMsgBuf, 0, NULL ) ;
    
    strText = (LPCTSTR)lpMsgBuf + strText ;
    
    AfxMessageBox ( strText , MB_OK | MB_ICONERROR ) ;

    LocalFree ( lpMsgBuf ) ;
} 

After the Output is received in the List Control, do not forget to release all the resources used before the program comes to an end. A good programmer always uses the computer and code resources wisely.

For getting the correct information, go to Run Command, type "wbemtest", and connect for the required computer.

Other WMI classes and reference can be found at:

http://msdn.microsoft.com/en-us/library/aa394554%28v=vs.85%29.aspx

Once you are through the WMI classes, it is eventually easy to get across the line.

The WMI Classes Tools can be downloaded from-

http://www.microsoft.com/en-us/download/details.aspx?id=24045

Points of Interest

I searched hundreds of code(s), but couldn't get the correct way to connect. This eventually led to crack Microsoft Windows Security Division for WMI classes. Hope this will help to get through WMI class and extract the required information.

History

I will post some stuff in the future like enumerating all properties/ captions and information from WMI classes. Until then, best of luck.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here