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 ) , _bstr_t ( useToken ? NULL : pszPwd ) , NULL, NULL, _bstr_t ( useNTLM ? NULL : pszAuthority ) , NULL, &pSvc );
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 C
OAUTHIDENTITY
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, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, userAcct, EOAC_NONE );
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.