VirtualBox

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

Last change on this file since 44552 was 44552, checked in by vboxsync, 12 years ago

Main: prefer <HOME>/.config/VirtualBox over <HOME>/.VirtualBox for new users on platforms where XDG is relevant, fix to handle XDG_CONFIG_HOME right.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1/* $Id: com.cpp 44552 2013-02-05 19:49:41Z 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.virtualbox.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" };
64char szXdgConfigHome[RTPATH_MAX];
65#endif
66
67#include "Logging.h"
68
69namespace com
70{
71
72void GetInterfaceNameByIID(const GUID &aIID, BSTR *aName)
73{
74 Assert(aName);
75 if (!aName)
76 return;
77
78 *aName = NULL;
79
80#if !defined(VBOX_WITH_XPCOM)
81
82 LONG rc;
83 LPOLESTR iidStr = NULL;
84 if (StringFromIID(aIID, &iidStr) == S_OK)
85 {
86 HKEY ifaceKey;
87 rc = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Interface",
88 0, KEY_QUERY_VALUE, &ifaceKey);
89 if (rc == ERROR_SUCCESS)
90 {
91 HKEY iidKey;
92 rc = RegOpenKeyExW(ifaceKey, iidStr, 0, KEY_QUERY_VALUE, &iidKey);
93 if (rc == ERROR_SUCCESS)
94 {
95 /* determine the size and type */
96 DWORD sz, type;
97 rc = RegQueryValueExW(iidKey, NULL, NULL, &type, NULL, &sz);
98 if (rc == ERROR_SUCCESS && type == REG_SZ)
99 {
100 /* query the value to BSTR */
101 *aName = SysAllocStringLen(NULL, (sz + 1) / sizeof(TCHAR) + 1);
102 rc = RegQueryValueExW(iidKey, NULL, NULL, NULL, (LPBYTE) *aName, &sz);
103 if (rc != ERROR_SUCCESS)
104 {
105 SysFreeString(*aName);
106 aName = NULL;
107 }
108 }
109 RegCloseKey(iidKey);
110 }
111 RegCloseKey(ifaceKey);
112 }
113 CoTaskMemFree(iidStr);
114 }
115
116#else /* !defined (VBOX_WITH_XPCOM) */
117
118 nsresult rv;
119 nsCOMPtr<nsIInterfaceInfoManager> iim =
120 do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv);
121 if (NS_SUCCEEDED(rv))
122 {
123 nsCOMPtr<nsIInterfaceInfo> iinfo;
124 rv = iim->GetInfoForIID(&aIID, getter_AddRefs(iinfo));
125 if (NS_SUCCEEDED(rv))
126 {
127 const char *iname = NULL;
128 iinfo->GetNameShared(&iname);
129 char *utf8IName = NULL;
130 if (RT_SUCCESS(RTStrCurrentCPToUtf8(&utf8IName, iname)))
131 {
132 PRTUTF16 utf16IName = NULL;
133 if (RT_SUCCESS(RTStrToUtf16(utf8IName, &utf16IName)))
134 {
135 *aName = SysAllocString((OLECHAR *) utf16IName);
136 RTUtf16Free(utf16IName);
137 }
138 RTStrFree(utf8IName);
139 }
140 }
141 }
142
143#endif /* !defined (VBOX_WITH_XPCOM) */
144}
145
146#ifdef VBOX_WITH_XPCOM
147
148HRESULT GlueCreateObjectOnServer(const CLSID &clsid,
149 const char *serverName,
150 const nsIID &id,
151 void** ppobj)
152{
153 HRESULT rc;
154 nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
155 if (SUCCEEDED(rc))
156 {
157 PRUint32 serverID = 0;
158 rc = ipcServ->ResolveClientName(serverName, &serverID);
159 if (SUCCEEDED (rc))
160 {
161 nsCOMPtr<ipcIDConnectService> dconServ = do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
162 if (SUCCEEDED(rc))
163 rc = dconServ->CreateInstance(serverID,
164 clsid,
165 id,
166 ppobj);
167 }
168 }
169 return rc;
170}
171
172HRESULT GlueCreateInstance(const CLSID &clsid,
173 const nsIID &id,
174 void** ppobj)
175{
176 nsCOMPtr<nsIComponentManager> manager;
177 HRESULT rc = NS_GetComponentManager(getter_AddRefs(manager));
178 if (SUCCEEDED(rc))
179 rc = manager->CreateInstance(clsid,
180 nsnull,
181 id,
182 ppobj);
183 return rc;
184}
185
186#endif // VBOX_WITH_XPCOM
187
188static int composeHomePath(char *aDir, size_t aDirLen,
189 const char *pcszBase)
190{
191 int vrc;
192 if (RTPathStartsWithRoot(pcszBase))
193 vrc = RTStrCopy(aDir, aDirLen, pcszBase);
194 else
195 {
196 /* compose the config directory (full path) */
197 /** @todo r=bird: RTPathUserHome doesn't necessarily return a
198 * full (abs) path like the comment above seems to indicate. */
199 vrc = RTPathUserHome(aDir, aDirLen);
200 if (RT_SUCCESS(vrc))
201 vrc = RTPathAppend(aDir, aDirLen, pcszBase);
202 }
203 return vrc;
204}
205
206int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen, bool fCreateDir)
207{
208 AssertReturn(aDir, VERR_INVALID_POINTER);
209 AssertReturn(aDirLen > 0, VERR_BUFFER_OVERFLOW);
210
211 /* start with null */
212 *aDir = 0;
213
214 char szTmp[RTPATH_MAX];
215 int vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_USER_HOME", szTmp, sizeof(szTmp), NULL);
216 if (RT_SUCCESS(vrc) || vrc == VERR_ENV_VAR_NOT_FOUND)
217 {
218 bool fFound = false;
219 if (RT_SUCCESS(vrc))
220 {
221 /* get the full path name */
222 vrc = RTPathAbs(szTmp, aDir, aDirLen);
223 }
224 else
225 {
226#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_DARWIN)
227 const char *pcszConfigHome = RTEnvGet("XDG_CONFIG_HOME");
228 if (pcszConfigHome && pcszConfigHome[0])
229 {
230 vrc = RTStrCopy(szXdgConfigHome,
231 sizeof(szXdgConfigHome),
232 pcszConfigHome);
233 if (RT_SUCCESS(vrc))
234 vrc = RTPathAppend(szXdgConfigHome,
235 sizeof(szXdgConfigHome),
236 "VirtualBox");
237 apcszUserHome[0] = szXdgConfigHome;
238 }
239#endif
240 for (unsigned i = 0; i < RT_ELEMENTS(apcszUserHome); ++i)
241 {
242 vrc = composeHomePath(aDir, aDirLen, apcszUserHome[i]);
243 if (RTDirExists(aDir))
244 {
245 fFound = true;
246 break;
247 }
248 }
249 if (!fFound)
250 vrc = composeHomePath(aDir, aDirLen, apcszUserHome[0]);
251 }
252
253 /* ensure the home directory exists */
254 if (RT_SUCCESS(vrc))
255 if (!fFound && fCreateDir)
256 vrc = RTDirCreateFullPath(aDir, 0700);
257 }
258
259 return vrc;
260}
261
262static const char *g_pszLogEntity = NULL;
263
264static void vboxHeaderFooter(PRTLOGGER pReleaseLogger, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
265{
266 /* some introductory information */
267 static RTTIMESPEC s_TimeSpec;
268 char szTmp[256];
269 if (enmPhase == RTLOGPHASE_BEGIN)
270 RTTimeNow(&s_TimeSpec);
271 RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp));
272
273 switch (enmPhase)
274 {
275 case RTLOGPHASE_BEGIN:
276 {
277 bool fOldBuffered = RTLogSetBuffering(pReleaseLogger, true /*fBuffered*/);
278 pfnLog(pReleaseLogger,
279 "VirtualBox %s %s r%u %s (%s %s) release log\n"
280#ifdef VBOX_BLEEDING_EDGE
281 "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
282#endif
283 "Log opened %s\n",
284 g_pszLogEntity, VBOX_VERSION_STRING, RTBldCfgRevision(),
285 RTBldCfgTargetDotArch(), __DATE__, __TIME__, szTmp);
286
287 int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
288 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
289 pfnLog(pReleaseLogger, "OS Product: %s\n", szTmp);
290 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
291 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
292 pfnLog(pReleaseLogger, "OS Release: %s\n", szTmp);
293 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
294 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
295 pfnLog(pReleaseLogger, "OS Version: %s\n", szTmp);
296 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
297 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
298 pfnLog(pReleaseLogger, "OS Service Pack: %s\n", szTmp);
299
300 vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szTmp, sizeof(szTmp));
301 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
302 pfnLog(pReleaseLogger, "DMI Product Name: %s\n", szTmp);
303 vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_VERSION, szTmp, sizeof(szTmp));
304 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
305 pfnLog(pReleaseLogger, "DMI Product Version: %s\n", szTmp);
306
307 uint64_t cbHostRam = 0, cbHostRamAvail = 0;
308 vrc = RTSystemQueryTotalRam(&cbHostRam);
309 if (RT_SUCCESS(vrc))
310 vrc = RTSystemQueryAvailableRam(&cbHostRamAvail);
311 if (RT_SUCCESS(vrc))
312 pfnLog(pReleaseLogger, "Host RAM: %lluMB total, %lluMB available\n",
313 cbHostRam / _1M, cbHostRamAvail / _1M);
314
315 /* the package type is interesting for Linux distributions */
316 char szExecName[RTPATH_MAX];
317 char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
318 pfnLog(pReleaseLogger,
319 "Executable: %s\n"
320 "Process ID: %u\n"
321 "Package type: %s"
322#ifdef VBOX_OSE
323 " (OSE)"
324#endif
325 "\n",
326 pszExecName ? pszExecName : "unknown",
327 RTProcSelf(),
328 VBOX_PACKAGE_STRING);
329 RTLogSetBuffering(pReleaseLogger, fOldBuffered);
330 break;
331 }
332 case RTLOGPHASE_PREROTATE:
333 pfnLog(pReleaseLogger, "Log rotated - Log started %s\n", szTmp);
334 break;
335
336 case RTLOGPHASE_POSTROTATE:
337 pfnLog(pReleaseLogger, "Log continuation - Log started %s\n", szTmp);
338 break;
339
340 case RTLOGPHASE_END:
341 pfnLog(pReleaseLogger, "End of log file - Log started %s\n", szTmp);
342 break;
343
344 default:
345 /* nothing */;
346 }
347}
348
349int VBoxLogRelCreate(const char *pcszEntity, const char *pcszLogFile,
350 uint32_t fFlags, const char *pcszGroupSettings,
351 const char *pcszEnvVarBase, uint32_t fDestFlags,
352 uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
353 uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
354 char *pszError, size_t cbError)
355{
356 Assert(cbError >= RTPATH_MAX + 128);
357
358 /* create release logger */
359 PRTLOGGER pReleaseLogger;
360 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
361#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
362 fFlags |= RTLOGFLAGS_USECRLF;
363#endif
364 g_pszLogEntity = pcszEntity;
365 int vrc = RTLogCreateEx(&pReleaseLogger, fFlags, pcszGroupSettings,
366 pcszEnvVarBase, RT_ELEMENTS(s_apszGroups), s_apszGroups, fDestFlags,
367 vboxHeaderFooter, cHistory, uHistoryFileSize, uHistoryFileTime,
368 pszError, cbError, pcszLogFile);
369 if (RT_SUCCESS(vrc))
370 {
371 /* make sure that we don't flood logfiles */
372 RTLogSetGroupLimit(pReleaseLogger, cMaxEntriesPerGroup);
373
374 /* explicitly flush the log, to have some info when buffering */
375 RTLogFlush(pReleaseLogger);
376
377 /* register this logger as the release logger */
378 RTLogRelSetDefaultInstance(pReleaseLogger);
379 }
380 return vrc;
381}
382
383
384/* static */
385const Guid Guid::Empty; /* default ctor is OK */
386
387#if defined (VBOX_WITH_XPCOM)
388
389/* static */
390const nsID *SafeGUIDArray::nsIDRef::Empty = (const nsID *)Guid::Empty.raw();
391
392#endif /* (VBOX_WITH_XPCOM) */
393
394/**
395 * Used by ComPtr and friends to log details about reference counting.
396 * @param pcszFormat
397 */
398void LogRef(const char *pcszFormat, ...)
399{
400 char *pszNewMsg;
401 va_list args;
402 va_start(args, pcszFormat);
403 RTStrAPrintfV(&pszNewMsg, pcszFormat, args);
404 LogDJ((pszNewMsg));
405 RTStrFree(pszNewMsg);
406 va_end(args);
407}
408
409} /* namespace com */
Note: See TracBrowser for help on using the repository browser.

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