VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/* $Id: RTSystemQueryDmiString-win.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - RTSystemQueryDmiString, windows ring-3.
4 */
5
6/*
7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define _WIN32_DCOM
42#include <iprt/win/windows.h>
43#include <WbemCli.h>
44
45#include <iprt/system.h>
46#include "internal/iprt.h"
47
48#include <iprt/errcore.h>
49#include <iprt/assert.h>
50#include <iprt/string.h>
51#include <iprt/utf16.h>
52
53
54/**
55 * Initialize COM.
56 *
57 * @returns COM status code.
58 */
59static HRESULT rtSystemDmiWinInitialize(void)
60{
61 HRESULT hrc = CoInitializeEx(0, COINIT_MULTITHREADED);
62 if (SUCCEEDED(hrc))
63 {
64 hrc = CoInitializeSecurity(NULL,
65 -1, /* COM authentication. */
66 NULL, /* Which authentication services. */
67 NULL, /* Reserved. */
68 RPC_C_AUTHN_LEVEL_DEFAULT, /* Default authentication. */
69 RPC_C_IMP_LEVEL_IMPERSONATE, /* Default impersonation. */
70 NULL, /* Authentication info. */
71 EOAC_NONE, /* Additional capabilities. */
72 NULL); /* Reserved. */
73 if (hrc == RPC_E_TOO_LATE)
74 hrc = S_OK;
75 else if (FAILED(hrc))
76 CoUninitialize();
77 }
78 return hrc;
79}
80
81
82/**
83 * Undo what rtSystemDmiWinInitialize did.
84 */
85static void rtSystemDmiWinTerminate(void)
86{
87 CoUninitialize();
88}
89
90
91/**
92 * Convert a UTF-8 string to a BSTR.
93 *
94 * @returns BSTR pointer.
95 * @param psz The UTF-8 string.
96 */
97static BSTR rtSystemWinBstrFromUtf8(const char *psz)
98{
99 PRTUTF16 pwsz = NULL;
100 int rc = RTStrToUtf16(psz, &pwsz);
101 if (RT_FAILURE(rc))
102 return NULL;
103 BSTR pBStr = SysAllocString((const OLECHAR *)pwsz);
104 RTUtf16Free(pwsz);
105 return pBStr;
106}
107
108
109/**
110 * Connect to the DMI server.
111 *
112 * @returns COM status code.
113 * @param pLocator The locator.
114 * @param pszServer The server name.
115 * @param ppServices Where to return the services interface.
116 */
117static HRESULT rtSystemDmiWinConnectToServer(IWbemLocator *pLocator, const char *pszServer, IWbemServices **ppServices)
118{
119 AssertPtr(pLocator);
120 AssertPtrNull(pszServer);
121 AssertPtr(ppServices);
122
123 BSTR pBStrServer = rtSystemWinBstrFromUtf8(pszServer);
124 if (!pBStrServer)
125 return E_OUTOFMEMORY;
126
127 HRESULT hrc = pLocator->ConnectServer(pBStrServer,
128 NULL,
129 NULL,
130 0,
131 NULL,
132 0,
133 0,
134 ppServices);
135 if (SUCCEEDED(hrc))
136 {
137 hrc = CoSetProxyBlanket(*ppServices,
138 RPC_C_AUTHN_WINNT,
139 RPC_C_AUTHZ_NONE,
140 NULL,
141 RPC_C_AUTHN_LEVEL_CALL,
142 RPC_C_IMP_LEVEL_IMPERSONATE,
143 NULL,
144 EOAC_NONE);
145 if (FAILED(hrc))
146 (*ppServices)->Release();
147 }
148 SysFreeString(pBStrServer);
149 return hrc;
150}
151
152
153RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf)
154{
155 AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
156 AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER);
157 *pszBuf = '\0';
158 AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER);
159
160 /*
161 * Figure the property name before we start.
162 */
163 const char *pszPropName;
164 switch (enmString)
165 {
166 case RTSYSDMISTR_PRODUCT_NAME: pszPropName = "Name"; break;
167 case RTSYSDMISTR_PRODUCT_VERSION: pszPropName = "Version"; break;
168 case RTSYSDMISTR_PRODUCT_UUID: pszPropName = "UUID"; break;
169 case RTSYSDMISTR_PRODUCT_SERIAL: pszPropName = "IdentifyingNumber"; break;
170 case RTSYSDMISTR_MANUFACTURER: pszPropName = "Vendor"; break;
171
172 default:
173 return VERR_NOT_SUPPORTED;
174 }
175
176 /*
177 * Before we do anything with COM, we have to initialize it.
178 */
179 bool fUninit = true;
180 HRESULT hrc = rtSystemDmiWinInitialize();
181 if (hrc == RPC_E_CHANGED_MODE)
182 fUninit = false; /* don't fail if already initialized */
183 else if (FAILED(hrc))
184 return VERR_NOT_SUPPORTED;
185
186 int rc = VERR_NOT_SUPPORTED;
187 BSTR pBstrPropName = rtSystemWinBstrFromUtf8(pszPropName);
188 if (pBstrPropName)
189 {
190 /*
191 * Instantiate the IWbemLocator, whatever that is and connect to the
192 * DMI serve.
193 */
194 IWbemLocator *pLoc;
195 hrc = CoCreateInstance(CLSID_WbemLocator,
196 0,
197 CLSCTX_INPROC_SERVER,
198 IID_IWbemLocator,
199 (LPVOID *)&pLoc);
200 if (SUCCEEDED(hrc))
201 {
202 IWbemServices *pServices;
203 hrc = rtSystemDmiWinConnectToServer(pLoc, "ROOT\\CIMV2", &pServices);
204 if (SUCCEEDED(hrc))
205 {
206 /*
207 * Enumerate whatever it is we're looking at and try get
208 * the desired property.
209 */
210 BSTR pBstrFilter = rtSystemWinBstrFromUtf8("Win32_ComputerSystemProduct");
211 if (pBstrFilter)
212 {
213 IEnumWbemClassObject *pEnum;
214 hrc = pServices->CreateInstanceEnum(pBstrFilter, 0, NULL, &pEnum);
215 if (SUCCEEDED(hrc))
216 {
217 do
218 {
219 IWbemClassObject *pObj;
220 ULONG cObjRet;
221 hrc = pEnum->Next(WBEM_INFINITE, 1, &pObj, &cObjRet);
222 if ( SUCCEEDED(hrc)
223 && cObjRet >= 1)
224 {
225 VARIANT Var;
226 VariantInit(&Var);
227 hrc = pObj->Get(pBstrPropName, 0, &Var, 0, 0);
228 if ( SUCCEEDED(hrc)
229 && V_VT(&Var) == VT_BSTR)
230 {
231 /*
232 * Convert the BSTR to UTF-8 and copy it
233 * into the return buffer.
234 */
235 char *pszValue;
236 rc = RTUtf16ToUtf8(Var.bstrVal, &pszValue);
237 if (RT_SUCCESS(rc))
238 {
239 rc = RTStrCopy(pszBuf, cbBuf, pszValue);
240 RTStrFree(pszValue);
241 hrc = WBEM_S_FALSE;
242 }
243 }
244 VariantClear(&Var);
245 pObj->Release();
246 }
247 } while (hrc != WBEM_S_FALSE);
248
249 pEnum->Release();
250 }
251 SysFreeString(pBstrFilter);
252 }
253 else
254 hrc = E_OUTOFMEMORY;
255 pServices->Release();
256 }
257 pLoc->Release();
258 }
259 SysFreeString(pBstrPropName);
260 }
261 else
262 hrc = E_OUTOFMEMORY;
263 if (fUninit)
264 rtSystemDmiWinTerminate();
265 if (FAILED(hrc) && rc == VERR_NOT_SUPPORTED)
266 rc = VERR_NOT_SUPPORTED;
267 return rc;
268}
269
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use