VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/win/dllmain.cpp@ 50874

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

removeOldClassIDs: Close the right handle, 2nd attempt.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
Line 
1/* $Id: dllmain.cpp 48351 2013-09-06 11:43:43Z vboxsync $ */
2/** @file
3 * VBoxC - COM DLL exports and DLL init/term.
4 */
5
6/*
7 * Copyright (C) 2006-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
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include "VBox/com/defs.h"
23
24#include <SessionImpl.h>
25#include <VirtualBoxClientImpl.h>
26
27#include <atlbase.h>
28#include <atlcom.h>
29
30#include <iprt/initterm.h>
31#include <iprt/assert.h>
32#include <iprt/string.h>
33
34
35/*******************************************************************************
36* Global Variables *
37*******************************************************************************/
38CComModule _Module;
39
40BEGIN_OBJECT_MAP(ObjectMap)
41 OBJECT_ENTRY(CLSID_Session, Session)
42 OBJECT_ENTRY(CLSID_VirtualBoxClient, VirtualBoxClient)
43END_OBJECT_MAP()
44
45
46/** @def WITH_MANUAL_CLEANUP
47 * Manually clean up the registry. */
48#if defined(DEBUG) && !defined(VBOX_IN_32_ON_64_MAIN_API)
49//# define WITH_MANUAL_CLEANUP
50#endif
51
52
53#ifdef WITH_MANUAL_CLEANUP
54/** Type library GUIDs to clean up manually. */
55static const char * const g_apszTypelibGuids[] =
56{
57 "{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}",
58 "{d7569351-1750-46f0-936e-bd127d5bc264}",
59};
60
61/** Same as above but with a "Typelib\\" prefix. */
62static const char * const g_apszTypelibGuidKeys[] =
63{
64 "TypeLib\\{46137EEC-703B-4FE5-AFD4-7C9BBBBA0259}",
65 "TypeLib\\{d7569351-1750-46f0-936e-bd127d5bc264}",
66};
67
68/** Type library version to clean up manually. */
69static const char * const g_apszTypelibVersions[] =
70{
71 "1.0",
72 "1.3",
73};
74#endif
75
76
77/*******************************************************************************
78* Internal Functions *
79*******************************************************************************/
80#ifdef WITH_MANUAL_CLEANUP
81static void removeOldMess(void);
82#endif
83
84
85/////////////////////////////////////////////////////////////////////////////
86// DLL Entry Point
87
88extern "C"
89BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
90{
91 if (dwReason == DLL_PROCESS_ATTACH)
92 {
93 _Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox);
94 DisableThreadLibraryCalls(hInstance);
95
96 // idempotent, so doesn't harm, and needed for COM embedding scenario
97 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
98 }
99 else if (dwReason == DLL_PROCESS_DETACH)
100 {
101 _Module.Term();
102 }
103 return TRUE;
104}
105
106/////////////////////////////////////////////////////////////////////////////
107// Used to determine whether the DLL can be unloaded by OLE
108
109STDAPI DllCanUnloadNow(void)
110{
111 return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
112}
113
114/////////////////////////////////////////////////////////////////////////////
115// Returns a class factory to create an object of the requested type
116
117STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
118{
119 return _Module.GetClassObject(rclsid, riid, ppv);
120}
121
122/////////////////////////////////////////////////////////////////////////////
123// DllRegisterServer - Adds entries to the system registry
124
125STDAPI DllRegisterServer(void)
126{
127 // registers object, typelib and all interfaces in typelib
128 return _Module.RegisterServer(TRUE);
129}
130
131/////////////////////////////////////////////////////////////////////////////
132// DllUnregisterServer - Removes entries from the system registry
133
134STDAPI DllUnregisterServer(void)
135{
136 HRESULT hrc = _Module.UnregisterServer(TRUE);
137#ifdef WITH_MANUAL_CLEANUP
138 removeOldMess();
139#endif
140 return hrc;
141}
142
143#ifdef WITH_MANUAL_CLEANUP
144
145/**
146 * Checks if the typelib GUID is one of the ones we wish to clean up.
147 *
148 * @returns true if it should be cleaned up, false if not.
149 * @param pszTypelibGuid The typelib GUID as bracketed string.
150 */
151static bool isTypelibGuidToRemove(const char *pszTypelibGuid)
152{
153 unsigned i = RT_ELEMENTS(g_apszTypelibGuids);
154 while (i-- > 0)
155 if (!stricmp(g_apszTypelibGuids[i], pszTypelibGuid))
156 return true;
157 return false;
158}
159
160
161/**
162 * Checks if the typelib version is one of the ones we wish to clean up.
163 *
164 * @returns true if it should be cleaned up, false if not.
165 * @param pszTypelibVer The typelib version as string.
166 */
167static bool isTypelibVersionToRemove(const char *pszTypelibVer)
168{
169 unsigned i = RT_ELEMENTS(g_apszTypelibVersions);
170 while (i-- > 0)
171 if (!strcmp(g_apszTypelibVersions[i], pszTypelibVer))
172 return true;
173 return false;
174}
175
176
177/**
178 * Hack to clean out the class IDs belonging to obsolete typelibs on development
179 * boxes and such likes.
180 */
181static void removeOldClassIDs(HKEY hkeyClassesRoot)
182{
183 HKEY hkeyClsId;
184 LONG rc = RegOpenKeyExA(hkeyClassesRoot, "CLSID", NULL, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
185 &hkeyClsId);
186 if (rc == ERROR_SUCCESS)
187 {
188 for (DWORD idxKey = 0;; idxKey++)
189 {
190 char szCurNm[128 + 128];
191 DWORD cbCurNm = 128;
192 rc = RegEnumKeyExA(hkeyClsId, idxKey, szCurNm, &cbCurNm, NULL, NULL, NULL, NULL);
193 if (rc == ERROR_NO_MORE_ITEMS)
194 break;
195
196 /*
197 * Get the typelib GUID and program ID with the class ID.
198 */
199 AssertBreak(rc == ERROR_SUCCESS);
200 strcpy(&szCurNm[cbCurNm], "\\TypeLib");
201 HKEY hkeyIfTypelib;
202 rc = RegOpenKeyExA(hkeyClsId, szCurNm, NULL, KEY_QUERY_VALUE, &hkeyIfTypelib);
203 if (rc != ERROR_SUCCESS)
204 continue;
205
206 char szTypelibGuid[128];
207 DWORD cbValue = sizeof(szTypelibGuid) - 1;
208 rc = RegQueryValueExA(hkeyIfTypelib, NULL, NULL, NULL, (PBYTE)&szTypelibGuid[0], &cbValue);
209 if (rc != ERROR_SUCCESS)
210 cbValue = 0;
211 szTypelibGuid[cbValue] = '\0';
212 RegCloseKey(hkeyIfTypelib);
213 if (!isTypelibGuidToRemove(szTypelibGuid))
214 continue;
215
216 /* ProgId */
217 strcpy(&szCurNm[cbCurNm], "\\ProgId");
218 HKEY hkeyIfProgId;
219 rc = RegOpenKeyExA(hkeyClsId, szCurNm, NULL, KEY_QUERY_VALUE, &hkeyIfProgId);
220 if (rc != ERROR_SUCCESS)
221 continue;
222
223 char szProgId[64];
224 cbValue = sizeof(szProgId) - 1;
225 rc = RegQueryValueExA(hkeyIfProgId, NULL, NULL, NULL, (PBYTE)&szProgId[0], &cbValue);
226 if (rc != ERROR_SUCCESS)
227 cbValue = 0;
228 szProgId[cbValue] = '\0';
229 RegCloseKey(hkeyIfProgId);
230 if (strnicmp(szProgId, RT_STR_TUPLE("VirtualBox.")))
231 continue;
232
233 /*
234 * Ok, it's an orphaned VirtualBox interface. Delete it.
235 */
236 szCurNm[cbCurNm] = '\0';
237 RTAssertMsg2("Should delete HCR/CLSID/%s\n", szCurNm);
238 //rc = SHDeleteKeyA(hkeyClsId, szCurNm);
239 Assert(rc == ERROR_SUCCESS);
240 }
241
242 RegCloseKey(hkeyClsId);
243 }
244}
245
246
247/**
248 * Hack to clean out the interfaces belonging to obsolete typelibs on
249 * development boxes and such likes.
250 */
251static void removeOldInterfaces(HKEY hkeyClassesRoot)
252{
253 HKEY hkeyInterface;
254 LONG rc = RegOpenKeyExA(hkeyClassesRoot, "Interface", NULL, DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
255 &hkeyInterface);
256 if (rc == ERROR_SUCCESS)
257 {
258 for (DWORD idxKey = 0;; idxKey++)
259 {
260 char szCurNm[128 + 128];
261 DWORD cbCurNm = 128;
262 rc = RegEnumKeyExA(hkeyInterface, idxKey, szCurNm, &cbCurNm, NULL, NULL, NULL, NULL);
263 if (rc == ERROR_NO_MORE_ITEMS)
264 break;
265
266 /*
267 * Get the typelib GUID and version associated with the interface.
268 */
269 AssertBreak(rc == ERROR_SUCCESS);
270 strcpy(&szCurNm[cbCurNm], "\\TypeLib");
271 HKEY hkeyIfTypelib;
272 rc = RegOpenKeyExA(hkeyInterface, szCurNm, NULL, KEY_QUERY_VALUE, &hkeyIfTypelib);
273 if (rc != ERROR_SUCCESS)
274 continue;
275
276 char szTypelibGuid[128];
277 DWORD cbValue = sizeof(szTypelibGuid) - 1;
278 rc = RegQueryValueExA(hkeyIfTypelib, NULL, NULL, NULL, (PBYTE)&szTypelibGuid[0], &cbValue);
279 if (rc != ERROR_SUCCESS)
280 cbValue = 0;
281 szTypelibGuid[cbValue] = '\0';
282 if (!isTypelibGuidToRemove(szTypelibGuid))
283 {
284 RegCloseKey(hkeyIfTypelib);
285 continue;
286 }
287
288 char szTypelibVer[64];
289 cbValue = sizeof(szTypelibVer) - 1;
290 rc = RegQueryValueExA(hkeyIfTypelib, "Version", NULL, NULL, (PBYTE)&szTypelibVer[0], &cbValue);
291 if (rc != ERROR_SUCCESS)
292 cbValue = 0;
293 szTypelibVer[cbValue] = '\0';
294
295 RegCloseKey(hkeyIfTypelib);
296
297 if (!isTypelibVersionToRemove(szTypelibVer))
298 continue;
299
300
301 /*
302 * Ok, it's an orphaned VirtualBox interface. Delete it.
303 */
304 szCurNm[cbCurNm] = '\0';
305 //RTAssertMsg2("Should delete HCR/Interface/%s\n", szCurNm);
306 rc = SHDeleteKeyA(hkeyInterface, szCurNm);
307 Assert(rc == ERROR_SUCCESS);
308 }
309
310 RegCloseKey(hkeyInterface);
311 }
312}
313
314
315/**
316 * Hack to clean obsolete typelibs on development boxes and such.
317 */
318static void removeOldTypelib(HKEY hkeyClassesRoot)
319{
320 /*
321 * Open it and verify the identity.
322 */
323 unsigned i = RT_ELEMENTS(g_apszTypelibGuidKeys);
324 while (i-- > 0)
325 {
326 HKEY hkeyTyplib;
327 LONG rc = RegOpenKeyExA(hkeyClassesRoot, g_apszTypelibGuidKeys[i], NULL,
328 DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkeyTyplib);
329 if (rc == ERROR_SUCCESS)
330 {
331 unsigned iVer = RT_ELEMENTS(g_apszTypelibVersions);
332 while (iVer-- > 0)
333 {
334 HKEY hkeyVer;
335 rc = RegOpenKeyExA(hkeyTyplib, g_apszTypelibVersions[iVer], NULL, KEY_READ, &hkeyVer);
336 if (rc == ERROR_SUCCESS)
337 {
338 char szValue[128];
339 DWORD cbValue = sizeof(szValue) - 1;
340 rc = RegQueryValueExA(hkeyVer, NULL, NULL, NULL, (PBYTE)&szValue[0], &cbValue);
341 if (rc == ERROR_SUCCESS)
342 {
343 szValue[cbValue] = '\0';
344 if (!strcmp(szValue, "VirtualBox Type Library"))
345 {
346 RegCloseKey(hkeyVer);
347 hkeyVer = NULL;
348
349 /*
350 * Delete the type library.
351 */
352 //RTAssertMsg2("Should delete HCR\\%s\\%s\n", g_apszTypelibGuidKeys[i], g_apszTypelibVersions[iVer]);
353 rc = SHDeleteKeyA(hkeyTyplib, g_apszTypelibVersions[iVer]);
354 Assert(rc == ERROR_SUCCESS);
355 }
356 }
357
358 if (hkeyVer != NULL)
359 RegCloseKey(hkeyVer);
360 }
361 }
362 RegCloseKey(hkeyTyplib);
363
364 /*
365 * The typelib key should be empty now, so we can try remove it (non-recursively).
366 */
367 rc = RegDeleteKeyA(hkeyClassesRoot, g_apszTypelibGuidKeys[i]);
368 Assert(rc == ERROR_SUCCESS);
369 }
370 }
371}
372
373
374/**
375 * Hack to clean out obsolete typelibs on development boxes and such.
376 */
377static void removeOldMess(void)
378{
379 /*
380 * The standard location.
381 */
382 removeOldTypelib(HKEY_CLASSES_ROOT);
383 removeOldInterfaces(HKEY_CLASSES_ROOT);
384 removeOldClassIDs(HKEY_CLASSES_ROOT);
385
386 /*
387 * Wow64 if present.
388 */
389 HKEY hkeyWow64;
390 LONG rc = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Wow6432Node", NULL,
391 DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkeyWow64);
392 if (rc == ERROR_SUCCESS)
393 {
394 removeOldTypelib(hkeyWow64);
395 removeOldInterfaces(hkeyWow64);
396 removeOldClassIDs(hkeyWow64);
397
398 RegCloseKey(hkeyWow64);
399 }
400}
401
402#endif /* WITH_MANUAL_CLEANUP */
403
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