VirtualBox

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

Last change on this file since 60682 was 59228, checked in by vboxsync, 9 years ago

GetVBoxUserHomeDirectory: Use RTEnvGetEx when reading XDG_CONFIG_HOME just like we do already for VBOX_USER_HOME. Also, should it or the following path append fail in anyway, fall back on .config/VirtualBox

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