After a lots of tests, I can officially announce which the WMI Delphi Code Creator now can create C++ Code compatible with the Borland/Embarcadero compilers. This new feature will be very helpful for developers using Borland/Embarcadero C++ compilers because exist very few documentation about accessing the WMI from these compilers. The generated code can be compiled without any changes using the very old C++ Builder 5 until the modern C++ Builder XE2. The generated code uses the wbemcli.h library which is included in all the versions of C++ builder. Another feature of this release is which the generated C++ code include all the security settings needed to establish local and remote WMI connections.
As always all your suggestions and comments are very welcome.
You can download the application from the WMI Delphi Code Creator page.
C++ Code generated for the tool to access a WMI Class
#pragma hdrstop #include <iostream> using namespace std; #include <wbemcli.h> #include <comdef.h> //CREDENTIAL structure //http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788%28v=vs.85%29.aspx #define CRED_MAX_USERNAME_LENGTH 513 #define CRED_MAX_CREDENTIAL_BLOB_SIZE 512 #define CREDUI_MAX_USERNAME_LENGTH CRED_MAX_USERNAME_LENGTH #define CREDUI_MAX_PASSWORD_LENGTH (CRED_MAX_CREDENTIAL_BLOB_SIZE / 2) // The Win32_Process class represents a sequence of events on a Win32 system. Any sequence consisting of the interaction of one or more processors or interpreters, some executable code, and a set of inputs, is a descendent (or member) of this class. // Example: A client application running on a Win32 system. #pragma argsused int main(int argc, char* argv[]) { wchar_t pszName[CREDUI_MAX_USERNAME_LENGTH+1] = L"user"; wchar_t pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1] = L"password"; BSTR strNetworkResource; //To use a WMI remote connection set localconn to false and configure the values of the pszName, pszPwd and the name of the remote machine in strNetworkResource bool localconn = true; strNetworkResource = localconn ? L"\\\\.\\root\\CIMV2" : L"\\\\remote--machine\\root\\CIMV2"; COAUTHIDENTITY *userAcct = NULL ; COAUTHIDENTITY authIdent; // Initialize COM. ------------------------------------------ HRESULT hres; hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Set general COM security levels -------------------------- if (localconn) hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); else hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IDENTIFY, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Obtain the initial locator to WMI ------------------------- IWbemLocator *pLoc = NULL; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices *pSvc = NULL; if (localconn) hres = pLoc->ConnectServer( strNetworkResource, // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); else hres = pLoc->ConnectServer( strNetworkResource, // Object path of WMI namespace pszName, // User name pszPwd, // User password NULL, // Locale NULL, // Security flags NULL, // Authority NULL, // Context object &pSvc // IWbemServices proxy ); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } cout << "Connected to root\\CIMV2 WMI namespace" << endl; // Set security levels on the proxy ------------------------- if (localconn) hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); else { // Create COAUTHIDENTITY that can be used for setting security on proxy memset(&authIdent, 0, sizeof(COAUTHIDENTITY)); authIdent.PasswordLength = wcslen (pszPwd); authIdent.Password = (USHORT*)pszPwd; authIdent.User = (USHORT*)pszName; authIdent.UserLength = wcslen(pszName); authIdent.Domain = 0; authIdent.DomainLength = 0; authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; userAcct = &authIdent; hres = 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 ); } if (FAILED(hres)) { cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Use the IWbemServices pointer to make requests of WMI ---- IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( L"WQL", L"SELECT * FROM Win32_Process", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { cout << "ExecQuery failed" << " Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Secure the enumerator proxy if (!localconn) { hres = CoSetProxyBlanket( pEnumerator, // 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 ); if (FAILED(hres)) { cout << "Could not set proxy blanket on enumerator. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; pEnumerator->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } } // Get the data from the WQL sentence IWbemClassObject *pclsObj = NULL; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn || FAILED(hr)) break; VARIANT vtProp; hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);// String if (!FAILED(hr)) { if ((vtProp.vt==VT_NULL) || (vtProp.vt==VT_EMPTY)) wcout << "Name : " << ((vtProp.vt==VT_NULL) ? "NULL" : "EMPTY") << endl; else if ((vtProp.vt & VT_ARRAY)) wcout << "Name : " << "Array types not supported (yet)" << endl; else wcout << "Name : " << vtProp.bstrVal << endl; } VariantClear(&vtProp); hr = pclsObj->Get(L"ProcessId", 0, &vtProp, 0, 0);// Uint32 if (!FAILED(hr)) { if ((vtProp.vt==VT_NULL) || (vtProp.vt==VT_EMPTY)) wcout << "ProcessId : " << ((vtProp.vt==VT_NULL) ? "NULL" : "EMPTY") << endl; else if ((vtProp.vt & VT_ARRAY)) wcout << "ProcessId : " << "Array types not supported (yet)" << endl; else wcout << "ProcessId : " << vtProp.uintVal << endl; } VariantClear(&vtProp); pclsObj->Release(); pclsObj=NULL; } // Cleanup pSvc->Release(); pLoc->Release(); pEnumerator->Release(); if (pclsObj!=NULL) pclsObj->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 0; // Program successfully completed. }
C++ Code generated for the tool to execute a WMI Method
#pragma hdrstop #include <iostream> using namespace std; #include <wbemcli.h> #include <comdef.h> //CREDENTIAL structure //http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788%28v=vs.85%29.aspx #define CRED_MAX_USERNAME_LENGTH 513 #define CRED_MAX_CREDENTIAL_BLOB_SIZE 512 #define CREDUI_MAX_USERNAME_LENGTH CRED_MAX_USERNAME_LENGTH #define CREDUI_MAX_PASSWORD_LENGTH (CRED_MAX_CREDENTIAL_BLOB_SIZE / 2) // The Create method creates a new process. // The method returns an integer value that can be interpretted as follows: // 0 - Successful completion. // 2 - The user does not have access to the requested information. // 3 - The user does not have sufficient privilge. // 8 - Unknown failure. // 9 - The path specified does not exist. // 21 - The specified parameter is invalid. // Other - For integer values other than those listed above, refer to Win32 error code documentation. #pragma argsused int main(int argc, char* argv[]) { wchar_t pszName[CREDUI_MAX_USERNAME_LENGTH+1] = L"user"; wchar_t pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1] = L"password"; BSTR strNetworkResource; //To use a WMI remote connection set localconn to false and configure the values of the pszName, pszPwd and the name of the remote machine in strNetworkResource bool localconn = true; strNetworkResource = localconn ? L"\\\\.\\root\\CIMV2" : L"\\\\remote--machine\\root\\CIMV2"; COAUTHIDENTITY *userAcct = NULL ; COAUTHIDENTITY authIdent; HRESULT hres; // Initialize COM. ------------------------------------------ hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Set general COM security levels -------------------------- if (localconn) hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); else hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IDENTIFY, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Obtain the initial locator to WMI ------------------------- IWbemLocator *pLoc = NULL; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { cout << "Failed to create IWbemLocator object. " << "Err code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices *pSvc = NULL; // Connect to the root\\CIMV2 namespace // and obtain pointer pSvc to make IWbemServices calls. if (localconn) hres = pLoc->ConnectServer( strNetworkResource, // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); else hres = pLoc->ConnectServer( strNetworkResource, // Object path of WMI namespace pszName, // User name pszPwd, // User password NULL, // Locale NULL, // Security flags NULL, // Authority NULL, // Context object &pSvc // IWbemServices proxy ); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } cout << "Connected to root\\CIMV2 WMI namespace" << endl; // Set security levels on the proxy ------------------------- if (localconn) hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); else { // Create COAUTHIDENTITY that can be used for setting security on proxy memset(&authIdent, 0, sizeof(COAUTHIDENTITY)); authIdent.PasswordLength = wcslen (pszPwd); authIdent.Password = (USHORT*)pszPwd; authIdent.User = (USHORT*)pszName; authIdent.UserLength = wcslen(pszName); authIdent.Domain = 0; authIdent.DomainLength = 0; authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; userAcct = &authIdent; hres = 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 ); } if (FAILED(hres)) { cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } // Use the IWbemServices pointer to make requests of WMI ---- BSTR MethodName = SysAllocString(L"Create"); BSTR ClassName = SysAllocString(L"Win32_Process"); IWbemClassObject* pClass = NULL; hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL); IWbemClassObject* pInParamsDefinition = NULL; hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL); IWbemClassObject* pClassInstance = NULL; hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance); VARIANT varCommand; varCommand.vt = VT_BSTR; varCommand.bstrVal = L"cmd.exe"; hres = pClassInstance->Put(L"CommandLine", 0, &varCommand, 0); VariantClear(&varCommand); // Execute Method IWbemClassObject* pOutParams = NULL; hres = pSvc->ExecMethod(ClassName, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL); if (FAILED(hres)) { cout << "Could not execute method. Error code = 0x" << hex << hres << endl; cout << _com_error(hres).ErrorMessage() << endl; SysFreeString(ClassName); SysFreeString(MethodName); if (pClass) pClass->Release(); if (pInParamsDefinition) pInParamsDefinition->Release(); if (pOutParams) pOutParams->Release(); if (pSvc) pSvc->Release(); if (pLoc) pLoc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 1; // Program has failed. } VARIANT varReturnValue; hres = pOutParams->Get(L"ProcessId", 0, &varReturnValue, NULL, 0); if (!FAILED(hres)) { if ((varReturnValue.vt==VT_NULL) || (varReturnValue.vt==VT_EMPTY)) wcout << "ProcessId : " << ((varReturnValue.vt==VT_NULL) ? "NULL" : "EMPTY") << endl; else if ((varReturnValue.vt & VT_ARRAY)) wcout << "ProcessId : " << "Array types not supported (yet)" << endl; else wcout << "ProcessId : " << varReturnValue.uintVal << endl; } VariantClear(&varReturnValue); hres = pOutParams->Get(L"ReturnValue", 0, &varReturnValue, NULL, 0); if (!FAILED(hres)) { if ((varReturnValue.vt==VT_NULL) || (varReturnValue.vt==VT_EMPTY)) wcout << "ReturnValue : " << ((varReturnValue.vt==VT_NULL) ? "NULL" : "EMPTY") << endl; else if ((varReturnValue.vt & VT_ARRAY)) wcout << "ReturnValue : " << "Array types not supported (yet)" << endl; else wcout << "ReturnValue : " << varReturnValue.uintVal << endl; } VariantClear(&varReturnValue); // Clean up SysFreeString(ClassName); SysFreeString(MethodName); pClass->Release(); pInParamsDefinition->Release(); pOutParams->Release(); pLoc->Release(); pSvc->Release(); CoUninitialize(); cout << "press enter to exit" << endl; cin.get(); return 0; }