Need help with my subroutine in C++

Discussion in 'Mixed Languages' started by Jachra, Dec 12, 2018.

Tags:
  1. Jachra

    Jachra MDL Member

    Apr 5, 2010
    180
    54
    10
    Hello

    I tried to convert the following from VBS to C++. I keep getting error "Failed to Initialize COM. Error code = 0x80010106" on my CoInitializeEx(NULL, COINIT_MULTITHREADED) call. What do I do wrong?
    Thanks in advance for any help.

    Code:
    strComputer = "."
    
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    Set colItems = objWMIService.ExecQuery("Select * from SoftwareLicensingProduct")
    
    For Each objItem in colItems
        If NOT objItem.ProductKeyID = "null" Then
            Wscript.Echo "Extend PID: " & objItem.ProductKeyID
            Wscript.Echo "Windows Family: " & objItem.LicenseFamily
            Wscript.Echo "Windows Type: " & objItem.ProductKeyChannel
            Wscript.Echo "Activation ID: " & objItem.ID
            Exit For
        End If
    Next
    My function in C++:

    Code:
    private: std::string GetActIDFromSystem()
        {
            HRESULT hres;
            hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    
            if (FAILED(hres))
            {
                //std::string format_error(unsigned __int32 hres);
                std::stringstream ss;
                ss << "Failed to Initialize COM. Error code = 0x" << std::hex << hres << std::endl;
                return ss.str();
            }
    
            hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    
            if (FAILED(hres))
            {
                CoUninitialize();
                //std::string format_error(unsigned __int32 hres);
                std::stringstream ss;
                ss << "Failed to initialize security. Error code = 0x" << std::hex << hres << std::endl;
                return ss.str();
            }
    
            IWbemLocator *pLoc = NULL;
            hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);
    
            if (FAILED(hres))
            {
                CoUninitialize();
                //std::string format_error(unsigned __int32 hres);
                std::stringstream ss;
                ss << "Failed to create IWbemLocator object. Error code = 0x" << std::hex << hres << std::endl;
                return ss.str();
            }
    
            IWbemServices *pSvc = NULL;
    
            // Connect to the root\cimv2 namespace with
            // the current user and obtain pointer pSvc
            // to make IWbemServices calls.
            hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
    
            if (FAILED(hres))
            {
                pLoc->Release();
                CoUninitialize();
                //std::string format_error(unsigned __int32 hres);
                std::stringstream ss;
                ss << "Could not connect. Error code = 0x" << std::hex << hres << std::endl;
                return ss.str();
            }
    
            //cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
    
            hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
    
            if (FAILED(hres))
            {
                pSvc->Release();
                pLoc->Release();
                CoUninitialize();
                //std::string format_error(unsigned __int32 hres);
                std::stringstream ss;
                ss << "Could not set proxy blanket. Error code = 0x" << std::hex << hres << std::endl;
                return ss.str();
            }
    
            // For example, get the name of the operating system
            IEnumWbemClassObject* pEnumerator = NULL;
            hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM SoftwareLicensingProduct"),
                WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
    
            if (FAILED(hres))
            {
                pSvc->Release();
                pLoc->Release();
                CoUninitialize();
                //std::string format_error(unsigned __int32 hres);
                std::stringstream ss;
                ss << "Query for SoftwareLicensingProduct failed. Error code = 0x" << std::hex << hres << std::endl;
                return ss.str();
            }
    
            IWbemClassObject *pclsObj = NULL;
            ULONG uReturn = 0;
    
            while (pEnumerator)
            {
                HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
    
                if (0 == uReturn)
                {
                    break;
                }
    
                VARIANT vtProp;
    
                // Get the value of the Name property
                hr = pclsObj->Get(L"ProductKeyID", 0, &vtProp, 0, 0);
                std::stringstream ss;
                ss << vtProp.bstrVal;
                VariantClear(&vtProp);
    
                pclsObj->Release();
            }
    
            // Cleanup
            // ========
            pSvc->Release();
            pLoc->Release();
            pEnumerator->Release();
            CoUninitialize();
            return "0";
        }
     
  2. Michaela Joy

    Michaela Joy MDL Crazy Lady

    Jul 26, 2012
    3,855
    4,259
    120
    #2 Michaela Joy, Dec 12, 2018
    Last edited: Dec 12, 2018
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. Jachra

    Jachra MDL Member

    Apr 5, 2010
    180
    54
    10
    Thank you for your answer. I tried that, but did get an error on CoInitializeSecurity. I disabled that part of code and then it worked.
     
  4. Michaela Joy

    Michaela Joy MDL Crazy Lady

    Jul 26, 2012
    3,855
    4,259
    120
    @Jachra: I'm glad I was able to help. :)

    Please describe the error that you're getting, and We'll try to figure out what's needed to fix it.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. QuantumBug

    QuantumBug MDL Developer

    Mar 7, 2012
    1,629
    1,606
    60
    #5 QuantumBug, Dec 12, 2018
    Last edited: Dec 14, 2018
    With 0x80010106 you're calling your com initialization in the wrong thread. A DLL should NOT call CoInitializeEx() on a thread it did not create.

    You may want to add the below code before main()
    Code:
    [System::STAThread]
    Or, create your own thread in the threadpool.

    And here is some reading:
    Code:
    #include "stdafx.h"
    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <comdef.h>
    #include <Wbemidl.h>
    # pragma comment(lib, "wbemuuid.lib")
    
    //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)
    
    // This class exposes product-specific properties and methods of the Software
    // Licensing service.
    
    #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(
           _bstr_t(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(
           _bstr_t(strNetworkResource),  // Object path of WMI namespace
           _bstr_t(pszName),             // User name
           _bstr_t(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 SoftwareLicensingProduct",
           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"ID", 0, &vtProp, 0, 0);// String
           if (!FAILED(hr))
           {
               if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
                   wcout << "ID : " << ((vtProp.vt == VT_NULL) ? "NULL" : "EMPTY") << endl;
               else
                   if ((vtProp.vt & VT_ARRAY))
                       wcout << "ID : " << "Array types not supported (yet)" << endl;
                   else
                       wcout << "ID : " << vtProp.bstrVal << endl;
           }
           VariantClear(&vtProp);
    
           hr = pclsObj->Get(L"LicenseFamily", 0, &vtProp, 0, 0);// String
           if (!FAILED(hr))
           {
               if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
                   wcout << "LicenseFamily : " << ((vtProp.vt == VT_NULL) ? "NULL" : "EMPTY") << endl;
               else
                   if ((vtProp.vt & VT_ARRAY))
                       wcout << "LicenseFamily : " << "Array types not supported (yet)" << endl;
                   else
                       wcout << "LicenseFamily : " << vtProp.bstrVal << endl;
           }
           VariantClear(&vtProp);
    
           hr = pclsObj->Get(L"ProductKeyChannel", 0, &vtProp, 0, 0);// String
           if (!FAILED(hr))
           {
               if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
                   wcout << "ProductKeyChannel : " << ((vtProp.vt == VT_NULL) ? "NULL" : "EMPTY") << endl;
               else
                   if ((vtProp.vt & VT_ARRAY))
                       wcout << "ProductKeyChannel : " << "Array types not supported (yet)" << endl;
                   else
                       wcout << "ProductKeyChannel : " << vtProp.bstrVal << endl;
           }
           VariantClear(&vtProp);
    
           hr = pclsObj->Get(L"ProductKeyID", 0, &vtProp, 0, 0);// String
           if (!FAILED(hr))
           {
               if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
                   wcout << "ProductKeyID : " << ((vtProp.vt == VT_NULL) ? "NULL" : "EMPTY") << endl;
               else
                   if ((vtProp.vt & VT_ARRAY))
                       wcout << "ProductKeyID : " << "Array types not supported (yet)" << endl;
                   else
                       wcout << "ProductKeyID : " << vtProp.bstrVal << 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.
    }
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...