Index: trunk/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp
===================================================================
--- trunk/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp	(revision 27614)
+++ trunk/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp	(revision 27618)
@@ -33,4 +33,8 @@
 *   Header Files                                                               *
 *******************************************************************************/
+#define _WIN32_DCOM
+#include <Windows.h>
+#include <WbemCli.h>
+
 #include <iprt/system.h>
 #include "internal/iprt.h"
@@ -40,29 +44,33 @@
 #include <iprt/string.h>
 
-#define _WIN32_DCOM
-#include <comdef.h>
-#include <Wbemidl.h>
-
-
-HRESULT rtSystemInitializeDmiLookup()
-{
-    HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
-    if (SUCCEEDED(hr))
-    {
-        hr = CoInitializeSecurity(NULL,
-                                  -1,                          /* COM authentication. */
-                                  NULL,                        /* Which 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. */
-    }
-    return hr;
-}
-
-
-void rtSystemShutdownDmiLookup()
+
+/**
+ * Initialize COM.
+ *
+ * @returns COM status code.
+ */
+static HRESULT rtSystemDmiWinInitialize(void)
+{
+    HRESULT hrc = CoInitializeEx(0, COINIT_MULTITHREADED);
+    if (SUCCEEDED(hrc))
+    {
+        hrc = CoInitializeSecurity(NULL,
+                                   -1,                          /* COM authentication. */
+                                   NULL,                        /* Which 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. */
+    }
+    return hrc;
+}
+
+
+/**
+ * Undo what rtSystemDmiWinInitialize did.
+ */
+static void rtSystemDmiWinTerminate(void)
 {
     CoUninitialize();
@@ -70,5 +78,31 @@
 
 
-HRESULT rtSystemConnectToDmiServer(IWbemLocator *pLocator, const char *pszServer, IWbemServices **ppServices)
+/**
+ * Convert a UTF-8 string to a BSTR.
+ *
+ * @returns BSTR pointer.
+ * @param   psz                 The UTF-8 string.
+ */
+static BSTR rtSystemWinBstrFromUtf8(const char *psz)
+{
+    PRTUTF16 pwsz = NULL;
+    int rc = RTStrToUtf16(psz, &pwsz);
+    if (RT_FAILURE(rc))
+        return NULL;
+    BSTR pBStr = SysAllocString((const OLECHAR *)pwsz);
+    RTUtf16Free(pwsz);
+    return pBStr;
+}
+
+
+/**
+ * Connect to the DMI server.
+ *
+ * @returns COM status code.
+ * @param   pLocator            The locator.
+ * @param   pszServer           The server name.
+ * @param   ppServices          Where to return the services interface.
+ */
+static HRESULT rtSystemDmiWinConnectToServer(IWbemLocator *pLocator, const char *pszServer, IWbemServices **ppServices)
 {
     AssertPtr(pLocator);
@@ -76,24 +110,31 @@
     AssertPtr(ppServices);
 
-    HRESULT hr = pLocator->ConnectServer(_bstr_t(TEXT(pszServer)),
-                                         NULL,
-                                         NULL,
-                                         0,
-                                         NULL,
-                                         0,
-                                         0,
-                                         ppServices);
-    if (SUCCEEDED(hr))
-    {
-        hr = CoSetProxyBlanket(*ppServices,
-                               RPC_C_AUTHN_WINNT,
-                               RPC_C_AUTHZ_NONE,
-                               NULL,
-                               RPC_C_AUTHN_LEVEL_CALL,
-                               RPC_C_IMP_LEVEL_IMPERSONATE,
-                               NULL,
-                               EOAC_NONE);
-    }
-    return hr;
+    BSTR pBStrServer = rtSystemWinBstrFromUtf8(pszServer);
+    if (!pBStrServer)
+        return E_OUTOFMEMORY;
+
+    HRESULT hrc = pLocator->ConnectServer(pBStrServer,
+                                          NULL,
+                                          NULL,
+                                          0,
+                                          NULL,
+                                          0,
+                                          0,
+                                          ppServices);
+    if (SUCCEEDED(hrc))
+    {
+        hrc = CoSetProxyBlanket(*ppServices,
+                                RPC_C_AUTHN_WINNT,
+                                RPC_C_AUTHZ_NONE,
+                                NULL,
+                                RPC_C_AUTHN_LEVEL_CALL,
+                                RPC_C_IMP_LEVEL_IMPERSONATE,
+                                NULL,
+                                EOAC_NONE);
+        if (FAILED(hrc))
+            (*ppServices)->Release();
+    }
+    SysFreeString(pBStrServer);
+    return hrc;
 }
 
@@ -106,73 +147,106 @@
     AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER);
 
-    HRESULT hr = rtSystemInitializeDmiLookup();
-    if (FAILED(hr))
+    /*
+     * Figure the property name before we start.
+     */
+    const char *pszPropName;
+    switch (enmString)
+    {
+        case RTSYSDMISTR_PRODUCT_NAME:      pszPropName = "Name"; break;
+        case RTSYSDMISTR_PRODUCT_VERSION:   pszPropName = "Version"; break;
+        case RTSYSDMISTR_PRODUCT_UUID:      pszPropName = "UUID"; break;
+        case RTSYSDMISTR_PRODUCT_SERIAL:    pszPropName = "IdentifyingNumber"; break;
+        default:
+            return VERR_NOT_SUPPORTED;
+    }
+
+    /*
+     * Before we do anything with COM, we have to initalize it.
+     */
+    HRESULT hrc = rtSystemDmiWinInitialize();
+    if (FAILED(hrc))
         return VERR_NOT_SUPPORTED;
 
-    IWbemLocator *pLoc;
-    hr = CoCreateInstance(CLSID_WbemLocator,
-                          0,
-                          CLSCTX_INPROC_SERVER,
-                          IID_IWbemLocator, (LPVOID *)&pLoc);
-    int rc = VINF_SUCCESS;
-    if (SUCCEEDED(hr))
-    {
-        IWbemServices *pServices;
-        hr = rtSystemConnectToDmiServer(pLoc, "ROOT\\CIMV2", &pServices);
-        if (SUCCEEDED(hr))
+    int rc = VERR_NOT_SUPPORTED;
+    BSTR pBstrPropName = rtSystemWinBstrFromUtf8(pszPropName);
+    if (pBstrPropName)
+    {
+        /*
+         * Instantiate the IWbemLocator, whatever that is and connect to the
+         * DMI serve.
+         */
+        IWbemLocator *pLoc;
+        hrc = CoCreateInstance(CLSID_WbemLocator,
+                               0,
+                               CLSCTX_INPROC_SERVER,
+                               IID_IWbemLocator,
+                               (LPVOID *)&pLoc);
+        if (SUCCEEDED(hrc))
         {
-            IEnumWbemClassObject *pEnum;
-            hr = pServices->CreateInstanceEnum(L"Win32_ComputerSystemProduct", 0, NULL, &pEnum);
-            if (SUCCEEDED(hr))
+            IWbemServices *pServices;
+            hrc = rtSystemDmiWinConnectToServer(pLoc, "ROOT\\CIMV2", &pServices);
+            if (SUCCEEDED(hrc))
             {
-                IWbemClassObject *pObj;
-                ULONG uCount;
-
-                do
+                /*
+                 * Enumerate whatever it is we're looking at and try get
+                 * the desired property.
+                 */
+                BSTR pBstrFilter = rtSystemWinBstrFromUtf8("Win32_ComputerSystemProduct");
+                if (pBstrFilter)
                 {
-                    hr = pEnum->Next(WBEM_INFINITE,
-                                     1,
-                                     &pObj,
-                                     &uCount);
-                    if (   SUCCEEDED(hr)
-                        && uCount > 0)
+                    IEnumWbemClassObject *pEnum;
+                    hrc = pServices->CreateInstanceEnum(pBstrFilter, 0, NULL, &pEnum);
+                    if (SUCCEEDED(hrc))
                     {
-                        const char *pszPropName;
-                        switch (enmString)
+                        do
                         {
-                            case RTSYSDMISTR_PRODUCT_NAME:      pszPropName = "Name"; break;
-                            case RTSYSDMISTR_PRODUCT_VERSION:   pszPropName = "Version"; break;
-                            case RTSYSDMISTR_PRODUCT_UUID:      pszPropName = "UUID"; break;
-                            case RTSYSDMISTR_PRODUCT_SERIAL:    pszPropName = "IdentifyingNumber"; break;
-                            default:
-                                rc = VERR_NOT_SUPPORTED;
-                        }
-
-                        if (RT_SUCCESS(rc))
-                        {
-                            _variant_t v;
-                            hr = pObj->Get(_bstr_t(TEXT(pszPropName)), 0, &v, 0, 0);
-                            if (   SUCCEEDED(hr)
-                                && V_VT(&v) == VT_BSTR)
+                            IWbemClassObject *pObj;
+                            ULONG cObjRet;
+                            hrc = pEnum->Next(WBEM_INFINITE, 1, &pObj, &cObjRet);
+                            if (   SUCCEEDED(hrc)
+                                && cObjRet >= 1)
                             {
-                                RTStrPrintf(pszBuf, cbBuf, "%s", (char*)_bstr_t(v.bstrVal));
-                                VariantClear(&v);
+                                VARIANT Var;
+                                VariantInit(&Var);
+                                hrc = pObj->Get(pBstrPropName, 0, &Var, 0, 0);
+                                if (   SUCCEEDED(hrc)
+                                    && V_VT(&Var) == VT_BSTR)
+                                {
+                                    /*
+                                     * Convert the BSTR to UTF-8 and copy it
+                                     * into the return buffer.
+                                     */
+                                    char *pszValue;
+                                    rc = RTUtf16ToUtf8(Var.bstrVal, &pszValue);
+                                    if (RT_SUCCESS(rc))
+                                    {
+                                        rc = RTStrCopy(pszBuf, cbBuf, pszValue);
+                                        RTStrFree(pszValue);
+                                        hrc = WBEM_S_FALSE;
+                                    }
+                                }
+                                VariantClear(&Var);
+                                pObj->Release();
                             }
-                        }
-                        pObj->Release();
+                        } while (hrc != WBEM_S_FALSE);
+
+                        pEnum->Release();
                     }
-                } while(hr != WBEM_S_FALSE);
-                pEnum->Release();
+                    SysFreeString(pBstrFilter);
+                }
+                else
+                    hrc = E_OUTOFMEMORY;
+                pServices->Release();
             }
-            pServices->Release();
+            pLoc->Release();
         }
-        pLoc->Release();
-    }
-
-    rtSystemShutdownDmiLookup();
-    if (FAILED(hr))
-        rc = VERR_NOT_FOUND; /** @todo Find a better error, since neither of the RTErrConvert* can do the conversion here. */
+        SysFreeString(pBstrPropName);
+    }
+    else
+        hrc = E_OUTOFMEMORY;
+    rtSystemDmiWinTerminate();
+    if (FAILED(hrc) && rc == VERR_NOT_SUPPORTED)
+        rc = VERR_NOT_SUPPORTED;
     return rc;
 }
-RT_EXPORT_SYMBOL(RTSystemQueryDmiString);
-
+
