VirtualBox

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

Last change on this file since 50247 was 50247, checked in by vboxsync, 11 years ago

VBoxLogRelCreate: avoid uncontrolled format string attack. This
function takes pcszLogFile argument that appears to be intended as the
literal file name. Don't pass it as pszFilenameFmt format string to
RTLogCreateEx(). Instead format it with "%s".

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

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