VirtualBox

source: vbox/trunk/src/VBox/Main/glue/com.cpp@ 44545

最後變更 在這個檔案從44545是 44545,由 vboxsync 提交於 12 年 前

Main: prefer <HOME>/.config/VirtualBox over <HOME>/.VirtualBox for new users on platforms where XDG is relevant.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.8 KB
 
1/* $Id: com.cpp 44545 2013-02-05 14:19:49Z vboxsync $ */
2/** @file
3 * MS COM / XPCOM Abstraction Layer
4 */
5
6/*
7 * Copyright (C) 2005-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#if !defined (VBOX_WITH_XPCOM)
19
20# include <objbase.h>
21
22#else /* !defined (VBOX_WITH_XPCOM) */
23# include <stdlib.h>
24# include <nsCOMPtr.h>
25# include <nsIServiceManagerUtils.h>
26# include <nsIComponentManager.h>
27# include <ipcIService.h>
28# include <ipcCID.h>
29# include <ipcIDConnectService.h>
30# include <nsIInterfaceInfo.h>
31# include <nsIInterfaceInfoManager.h>
32// official XPCOM headers don't define it yet
33#define IPC_DCONNECTSERVICE_CONTRACTID \
34 "@mozilla.org/ipc/dconnect-service;1"
35#endif /* !defined (VBOX_WITH_XPCOM) */
36
37#include "VBox/com/com.h"
38#include "VBox/com/assert.h"
39
40#include "VBox/com/Guid.h"
41#include "VBox/com/array.h"
42
43#include <package-generated.h>
44
45#include <iprt/buildconfig.h>
46#include <iprt/param.h>
47#include <iprt/path.h>
48#include <iprt/dir.h>
49#include <iprt/env.h>
50#include <iprt/string.h>
51#include <iprt/system.h>
52#include <iprt/process.h>
53
54#include <VBox/err.h>
55#include <VBox/version.h>
56
57const char *apcszUserHome[] =
58#ifdef RT_OS_DARWIN
59{ "Library/VirtualBox" };
60#elif defined RT_OS_WINDOWS
61{ ".VirtualBox" };
62#else
63{ ".config/VirtualBox", ".VirtualBox" };
64#endif
65
66#include "Logging.h"
67
68namespace com
69{
70
71void GetInterfaceNameByIID(const GUID &aIID, BSTR *aName)
72{
73 Assert(aName);
74 if (!aName)
75 return;
76
77 *aName = NULL;
78
79#if !defined(VBOX_WITH_XPCOM)
80
81 LONG rc;
82 LPOLESTR iidStr = NULL;
83 if (StringFromIID(aIID, &iidStr) == S_OK)
84 {
85 HKEY ifaceKey;
86 rc = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Interface",
87 0, KEY_QUERY_VALUE, &ifaceKey);
88 if (rc == ERROR_SUCCESS)
89 {
90 HKEY iidKey;
91 rc = RegOpenKeyExW(ifaceKey, iidStr, 0, KEY_QUERY_VALUE, &iidKey);
92 if (rc == ERROR_SUCCESS)
93 {
94 /* determine the size and type */
95 DWORD sz, type;
96 rc = RegQueryValueExW(iidKey, NULL, NULL, &type, NULL, &sz);
97 if (rc == ERROR_SUCCESS && type == REG_SZ)
98 {
99 /* query the value to BSTR */
100 *aName = SysAllocStringLen(NULL, (sz + 1) / sizeof(TCHAR) + 1);
101 rc = RegQueryValueExW(iidKey, NULL, NULL, NULL, (LPBYTE) *aName, &sz);
102 if (rc != ERROR_SUCCESS)
103 {
104 SysFreeString(*aName);
105 aName = NULL;
106 }
107 }
108 RegCloseKey(iidKey);
109 }
110 RegCloseKey(ifaceKey);
111 }
112 CoTaskMemFree(iidStr);
113 }
114
115#else /* !defined (VBOX_WITH_XPCOM) */
116
117 nsresult rv;
118 nsCOMPtr<nsIInterfaceInfoManager> iim =
119 do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv);
120 if (NS_SUCCEEDED(rv))
121 {
122 nsCOMPtr<nsIInterfaceInfo> iinfo;
123 rv = iim->GetInfoForIID(&aIID, getter_AddRefs(iinfo));
124 if (NS_SUCCEEDED(rv))
125 {
126 const char *iname = NULL;
127 iinfo->GetNameShared(&iname);
128 char *utf8IName = NULL;
129 if (RT_SUCCESS(RTStrCurrentCPToUtf8(&utf8IName, iname)))
130 {
131 PRTUTF16 utf16IName = NULL;
132 if (RT_SUCCESS(RTStrToUtf16(utf8IName, &utf16IName)))
133 {
134 *aName = SysAllocString((OLECHAR *) utf16IName);
135 RTUtf16Free(utf16IName);
136 }
137 RTStrFree(utf8IName);
138 }
139 }
140 }
141
142#endif /* !defined (VBOX_WITH_XPCOM) */
143}
144
145#ifdef VBOX_WITH_XPCOM
146
147HRESULT GlueCreateObjectOnServer(const CLSID &clsid,
148 const char *serverName,
149 const nsIID &id,
150 void** ppobj)
151{
152 HRESULT rc;
153 nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
154 if (SUCCEEDED(rc))
155 {
156 PRUint32 serverID = 0;
157 rc = ipcServ->ResolveClientName(serverName, &serverID);
158 if (SUCCEEDED (rc))
159 {
160 nsCOMPtr<ipcIDConnectService> dconServ = do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
161 if (SUCCEEDED(rc))
162 rc = dconServ->CreateInstance(serverID,
163 clsid,
164 id,
165 ppobj);
166 }
167 }
168 return rc;
169}
170
171HRESULT GlueCreateInstance(const CLSID &clsid,
172 const nsIID &id,
173 void** ppobj)
174{
175 nsCOMPtr<nsIComponentManager> manager;
176 HRESULT rc = NS_GetComponentManager(getter_AddRefs(manager));
177 if (SUCCEEDED(rc))
178 rc = manager->CreateInstance(clsid,
179 nsnull,
180 id,
181 ppobj);
182 return rc;
183}
184
185#endif // VBOX_WITH_XPCOM
186
187static int composeHomePath(char *aDir, size_t aDirLen,
188 const char *pcszBase)
189{
190 int vrc;
191 if (RTPathStartsWithRoot(pcszBase))
192 vrc = RTStrCopy(aDir, aDirLen, pcszBase);
193 else
194 {
195 /* compose the config directory (full path) */
196 /** @todo r=bird: RTPathUserHome doesn't necessarily return a
197 * full (abs) path like the comment above seems to indicate. */
198 vrc = RTPathUserHome(aDir, aDirLen);
199 if (RT_SUCCESS(vrc))
200 vrc = RTPathAppend(aDir, aDirLen, pcszBase);
201 }
202 return vrc;
203}
204
205int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen, bool fCreateDir)
206{
207 AssertReturn(aDir, VERR_INVALID_POINTER);
208 AssertReturn(aDirLen > 0, VERR_BUFFER_OVERFLOW);
209
210 /* start with null */
211 *aDir = 0;
212
213 char szTmp[RTPATH_MAX];
214 int vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_USER_HOME", szTmp, sizeof(szTmp), NULL);
215 if (RT_SUCCESS(vrc) || vrc == VERR_ENV_VAR_NOT_FOUND)
216 {
217 bool fFound = false;
218 if (RT_SUCCESS(vrc))
219 {
220 /* get the full path name */
221 vrc = RTPathAbs(szTmp, aDir, aDirLen);
222 }
223 else
224 {
225#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_DARWIN)
226 const char *pcszConfigHome = RTEnvGet("XDG_CONFIG_HOME");
227 if (pcszConfigHome && pcszConfigHome[0])
228 apcszUserHome[0] = pcszConfigHome;
229#endif
230 for (unsigned i = 0; i < RT_ELEMENTS(apcszUserHome); ++i)
231 {
232 vrc = composeHomePath(aDir, aDirLen, apcszUserHome[i]);
233 if (RTDirExists(aDir))
234 {
235 fFound = true;
236 break;
237 }
238 }
239 if (!fFound)
240 vrc = composeHomePath(aDir, aDirLen, apcszUserHome[0]);
241 }
242
243 /* ensure the home directory exists */
244 if (RT_SUCCESS(vrc))
245 if (!fFound && fCreateDir)
246 vrc = RTDirCreateFullPath(aDir, 0700);
247 }
248
249 return vrc;
250}
251
252static const char *g_pszLogEntity = NULL;
253
254static void vboxHeaderFooter(PRTLOGGER pReleaseLogger, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
255{
256 /* some introductory information */
257 static RTTIMESPEC s_TimeSpec;
258 char szTmp[256];
259 if (enmPhase == RTLOGPHASE_BEGIN)
260 RTTimeNow(&s_TimeSpec);
261 RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp));
262
263 switch (enmPhase)
264 {
265 case RTLOGPHASE_BEGIN:
266 {
267 bool fOldBuffered = RTLogSetBuffering(pReleaseLogger, true /*fBuffered*/);
268 pfnLog(pReleaseLogger,
269 "VirtualBox %s %s r%u %s (%s %s) release log\n"
270#ifdef VBOX_BLEEDING_EDGE
271 "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
272#endif
273 "Log opened %s\n",
274 g_pszLogEntity, VBOX_VERSION_STRING, RTBldCfgRevision(),
275 RTBldCfgTargetDotArch(), __DATE__, __TIME__, szTmp);
276
277 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
278 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
279 pfnLog(pReleaseLogger, "OS Product: %s\n", szTmp);
280 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
281 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
282 pfnLog(pReleaseLogger, "OS Release: %s\n", szTmp);
283 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
284 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
285 pfnLog(pReleaseLogger, "OS Version: %s\n", szTmp);
286 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
287 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
288 pfnLog(pReleaseLogger, "OS Service Pack: %s\n", szTmp);
289
290 vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szTmp, sizeof(szTmp));
291 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
292 pfnLog(pReleaseLogger, "DMI Product Name: %s\n", szTmp);
293 vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_VERSION, szTmp, sizeof(szTmp));
294 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
295 pfnLog(pReleaseLogger, "DMI Product Version: %s\n", szTmp);
296
297 uint64_t cbHostRam = 0, cbHostRamAvail = 0;
298 vrc = RTSystemQueryTotalRam(&cbHostRam);
299 if (RT_SUCCESS(vrc))
300 vrc = RTSystemQueryAvailableRam(&cbHostRamAvail);
301 if (RT_SUCCESS(vrc))
302 pfnLog(pReleaseLogger, "Host RAM: %lluMB total, %lluMB available\n",
303 cbHostRam / _1M, cbHostRamAvail / _1M);
304
305 /* the package type is interesting for Linux distributions */
306 char szExecName[RTPATH_MAX];
307 char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
308 pfnLog(pReleaseLogger,
309 "Executable: %s\n"
310 "Process ID: %u\n"
311 "Package type: %s"
312#ifdef VBOX_OSE
313 " (OSE)"
314#endif
315 "\n",
316 pszExecName ? pszExecName : "unknown",
317 RTProcSelf(),
318 VBOX_PACKAGE_STRING);
319 RTLogSetBuffering(pReleaseLogger, fOldBuffered);
320 break;
321 }
322 case RTLOGPHASE_PREROTATE:
323 pfnLog(pReleaseLogger, "Log rotated - Log started %s\n", szTmp);
324 break;
325
326 case RTLOGPHASE_POSTROTATE:
327 pfnLog(pReleaseLogger, "Log continuation - Log started %s\n", szTmp);
328 break;
329
330 case RTLOGPHASE_END:
331 pfnLog(pReleaseLogger, "End of log file - Log started %s\n", szTmp);
332 break;
333
334 default:
335 /* nothing */;
336 }
337}
338
339int VBoxLogRelCreate(const char *pcszEntity, const char *pcszLogFile,
340 uint32_t fFlags, const char *pcszGroupSettings,
341 const char *pcszEnvVarBase, uint32_t fDestFlags,
342 uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
343 uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
344 char *pszError, size_t cbError)
345{
346 Assert(cbError >= RTPATH_MAX + 128);
347
348 /* create release logger */
349 PRTLOGGER pReleaseLogger;
350 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
351#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
352 fFlags |= RTLOGFLAGS_USECRLF;
353#endif
354 g_pszLogEntity = pcszEntity;
355 int vrc = RTLogCreateEx(&pReleaseLogger, fFlags, pcszGroupSettings,
356 pcszEnvVarBase, RT_ELEMENTS(s_apszGroups), s_apszGroups, fDestFlags,
357 vboxHeaderFooter, cHistory, uHistoryFileSize, uHistoryFileTime,
358 pszError, cbError, pcszLogFile);
359 if (RT_SUCCESS(vrc))
360 {
361 /* make sure that we don't flood logfiles */
362 RTLogSetGroupLimit(pReleaseLogger, cMaxEntriesPerGroup);
363
364 /* explicitly flush the log, to have some info when buffering */
365 RTLogFlush(pReleaseLogger);
366
367 /* register this logger as the release logger */
368 RTLogRelSetDefaultInstance(pReleaseLogger);
369 }
370 return vrc;
371}
372
373
374/* static */
375const Guid Guid::Empty; /* default ctor is OK */
376
377#if defined (VBOX_WITH_XPCOM)
378
379/* static */
380const nsID *SafeGUIDArray::nsIDRef::Empty = (const nsID *)Guid::Empty.raw();
381
382#endif /* (VBOX_WITH_XPCOM) */
383
384/**
385 * Used by ComPtr and friends to log details about reference counting.
386 * @param pcszFormat
387 */
388void LogRef(const char *pcszFormat, ...)
389{
390 char *pszNewMsg;
391 va_list args;
392 va_start(args, pcszFormat);
393 RTStrAPrintfV(&pszNewMsg, pcszFormat, args);
394 LogDJ((pszNewMsg));
395 RTStrFree(pszNewMsg);
396 va_end(args);
397}
398
399} /* namespace com */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette