2 * self-registerable dll functions for shdocvw.dll
4 * Copyright (C) 2003 John K. Hohm
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
37 * Near the bottom of this file are the exported DllRegisterServer and
38 * DllUnregisterServer, which make all this worthwhile.
41 /***********************************************************************
42 * interface for self-registering
44 struct regsvr_interface
46 IID const *iid; /* NULL for end of list */
47 LPCSTR name; /* can be NULL to omit */
48 IID const *base_iid; /* can be NULL to omit */
49 int num_methods; /* can be <0 to omit */
50 CLSID const *ps_clsid; /* can be NULL to omit */
51 CLSID const *ps_clsid32; /* can be NULL to omit */
54 static HRESULT register_interfaces(struct regsvr_interface const *list);
55 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
59 CLSID const *clsid; /* NULL for end of list */
60 LPCSTR name; /* can be NULL to omit */
61 LPCSTR ips; /* can be NULL to omit */
62 LPCSTR ips32; /* can be NULL to omit */
63 LPCSTR ips32_tmodel; /* can be NULL to omit */
64 LPCSTR progid; /* can be NULL to omit */
65 LPCSTR viprogid; /* can be NULL to omit */
66 LPCSTR progid_extra; /* can be NULL to omit */
69 DWORD dwCallForAttributes;
72 /* flags for regsvr_coclass.flags */
73 #define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001
74 #define SHELLFOLDER_WANTSFORPARSING 0x00000002
75 #define SHELLFOLDER_ATTRIBUTES 0x00000004
76 #define SHELLFOLDER_CALLFORATTRIBUTES 0x00000008
78 static HRESULT register_coclasses(struct regsvr_coclass const *list);
79 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
81 /***********************************************************************
82 * static string constants
84 static WCHAR const interface_keyname[10] = {
85 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
86 static WCHAR const base_ifa_keyname[14] = {
87 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
89 static WCHAR const num_methods_keyname[11] = {
90 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
91 static WCHAR const ps_clsid_keyname[15] = {
92 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
94 static WCHAR const ps_clsid32_keyname[17] = {
95 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
96 'i', 'd', '3', '2', 0 };
97 static WCHAR const clsid_keyname[6] = {
98 'C', 'L', 'S', 'I', 'D', 0 };
99 static WCHAR const curver_keyname[7] = {
100 'C', 'u', 'r', 'V', 'e', 'r', 0 };
101 static WCHAR const ips_keyname[13] = {
102 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
104 static WCHAR const ips32_keyname[15] = {
105 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
107 static WCHAR const progid_keyname[7] = {
108 'P', 'r', 'o', 'g', 'I', 'D', 0 };
109 static WCHAR const viprogid_keyname[25] = {
110 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
111 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
113 static WCHAR const shellex_keyname[8] = {
114 's', 'h', 'e', 'l', 'l', 'e', 'x', 0 };
115 static WCHAR const shellfolder_keyname[12] = {
116 'S', 'h', 'e', 'l', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 0 };
117 static WCHAR const mcdm_keyname[21] = {
118 'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f',
119 'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 };
120 static char const tmodel_valuename[] = "ThreadingModel";
121 static char const wfparsing_valuename[] = "WantsFORPARSING";
122 static char const attributes_valuename[] = "Attributes";
123 static char const cfattributes_valuename[] = "CallForAttributes";
124 static WCHAR const lcs32_keyname[] = {
125 'L','o','c','a','l','S','e','r','v','e','r','3','2',0 };
126 static const WCHAR szIERelPath[] = {
127 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
128 'i','e','x','p','l','o','r','e','.','e','x','e',0 };
130 /***********************************************************************
131 * static helper functions
133 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
134 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
136 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
138 static LONG register_progid(WCHAR const *clsid,
139 char const *progid, char const *curver_progid,
140 char const *name, char const *extra);
142 /***********************************************************************
143 * register_interfaces
145 static HRESULT register_interfaces(struct regsvr_interface const *list)
147 LONG res = ERROR_SUCCESS;
150 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
151 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
152 if (res != ERROR_SUCCESS) goto error_return;
154 for (; res == ERROR_SUCCESS && list->iid; ++list) {
158 StringFromGUID2(list->iid, buf, 39);
159 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
160 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
161 if (res != ERROR_SUCCESS) goto error_close_interface_key;
164 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
165 (CONST BYTE*)(list->name),
166 strlen(list->name) + 1);
167 if (res != ERROR_SUCCESS) goto error_close_iid_key;
170 if (list->base_iid) {
171 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
172 if (res != ERROR_SUCCESS) goto error_close_iid_key;
175 if (0 <= list->num_methods) {
176 static WCHAR const fmt[3] = { '%', 'd', 0 };
179 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
180 KEY_READ | KEY_WRITE, NULL, &key, NULL);
181 if (res != ERROR_SUCCESS) goto error_close_iid_key;
183 wsprintfW(buf, fmt, list->num_methods);
184 res = RegSetValueExW(key, NULL, 0, REG_SZ,
186 (lstrlenW(buf) + 1) * sizeof(WCHAR));
189 if (res != ERROR_SUCCESS) goto error_close_iid_key;
192 if (list->ps_clsid) {
193 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
194 if (res != ERROR_SUCCESS) goto error_close_iid_key;
197 if (list->ps_clsid32) {
198 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
199 if (res != ERROR_SUCCESS) goto error_close_iid_key;
203 RegCloseKey(iid_key);
206 error_close_interface_key:
207 RegCloseKey(interface_key);
209 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
212 /***********************************************************************
213 * unregister_interfaces
215 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
217 LONG res = ERROR_SUCCESS;
220 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
221 KEY_READ | KEY_WRITE, &interface_key);
222 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
223 if (res != ERROR_SUCCESS) goto error_return;
225 for (; res == ERROR_SUCCESS && list->iid; ++list) {
228 StringFromGUID2(list->iid, buf, 39);
229 res = RegDeleteTreeW(interface_key, buf);
230 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
233 RegCloseKey(interface_key);
235 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
238 /***********************************************************************
241 static HRESULT register_coclasses(struct regsvr_coclass const *list)
243 LONG res = ERROR_SUCCESS;
246 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
247 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
248 if (res != ERROR_SUCCESS) goto error_return;
250 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
254 StringFromGUID2(list->clsid, buf, 39);
255 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
256 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
257 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
260 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
261 (CONST BYTE*)(list->name),
262 strlen(list->name) + 1);
263 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
267 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
268 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
274 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
275 KEY_READ | KEY_WRITE, NULL,
277 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
279 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
280 (CONST BYTE*)list->ips32,
281 lstrlenA(list->ips32) + 1);
282 if (res == ERROR_SUCCESS && list->ips32_tmodel)
283 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
284 (CONST BYTE*)list->ips32_tmodel,
285 strlen(list->ips32_tmodel) + 1);
286 RegCloseKey(ips32_key);
287 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
290 if (list->flags & SHELLEX_MAYCHANGEDEFAULTMENU) {
291 HKEY shellex_key, mcdm_key;
293 res = RegCreateKeyExW(clsid_key, shellex_keyname, 0, NULL, 0,
294 KEY_READ | KEY_WRITE, NULL,
296 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
297 res = RegCreateKeyExW(shellex_key, mcdm_keyname, 0, NULL, 0,
298 KEY_READ | KEY_WRITE, NULL,
300 RegCloseKey(shellex_key);
301 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
302 RegCloseKey(mcdm_key);
306 (SHELLFOLDER_WANTSFORPARSING|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES))
308 HKEY shellfolder_key;
310 res = RegCreateKeyExW(clsid_key, shellfolder_keyname, 0, NULL, 0,
311 KEY_READ | KEY_WRITE, NULL,
312 &shellfolder_key, NULL);
313 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
314 if (list->flags & SHELLFOLDER_WANTSFORPARSING)
315 res = RegSetValueExA(shellfolder_key, wfparsing_valuename, 0, REG_SZ, (const BYTE *)"", 1);
316 if (list->flags & SHELLFOLDER_ATTRIBUTES)
317 res = RegSetValueExA(shellfolder_key, attributes_valuename, 0, REG_DWORD,
318 (const BYTE *)&list->dwAttributes, sizeof(DWORD));
319 if (list->flags & SHELLFOLDER_CALLFORATTRIBUTES)
320 res = RegSetValueExA(shellfolder_key, cfattributes_valuename, 0, REG_DWORD,
321 (const BYTE *)&list->dwCallForAttributes, sizeof(DWORD));
322 RegCloseKey(shellfolder_key);
323 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
327 res = register_key_defvalueA(clsid_key, progid_keyname,
329 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
331 res = register_progid(buf, list->progid, NULL,
332 list->name, list->progid_extra);
333 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
336 if (list->viprogid) {
337 res = register_key_defvalueA(clsid_key, viprogid_keyname,
339 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
341 res = register_progid(buf, list->viprogid, list->progid,
342 list->name, list->progid_extra);
343 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
346 error_close_clsid_key:
347 RegCloseKey(clsid_key);
350 error_close_coclass_key:
351 RegCloseKey(coclass_key);
353 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
356 /***********************************************************************
357 * unregister_coclasses
359 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
361 LONG res = ERROR_SUCCESS;
364 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
365 KEY_READ | KEY_WRITE, &coclass_key);
366 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
367 if (res != ERROR_SUCCESS) goto error_return;
369 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
372 StringFromGUID2(list->clsid, buf, 39);
373 res = RegDeleteTreeW(coclass_key, buf);
374 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
375 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
378 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
379 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
380 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
383 if (list->viprogid) {
384 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
385 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
386 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
390 error_close_coclass_key:
391 RegCloseKey(coclass_key);
393 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
396 /***********************************************************************
399 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
403 StringFromGUID2(guid, buf, 39);
404 return register_key_defvalueW(base, name, buf);
407 /***********************************************************************
408 * regsvr_key_defvalueW
410 static LONG register_key_defvalueW(
418 res = RegCreateKeyExW(base, name, 0, NULL, 0,
419 KEY_READ | KEY_WRITE, NULL, &key, NULL);
420 if (res != ERROR_SUCCESS) return res;
421 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
422 (lstrlenW(value) + 1) * sizeof(WCHAR));
427 /***********************************************************************
428 * regsvr_key_defvalueA
430 static LONG register_key_defvalueA(
438 res = RegCreateKeyExW(base, name, 0, NULL, 0,
439 KEY_READ | KEY_WRITE, NULL, &key, NULL);
440 if (res != ERROR_SUCCESS) return res;
441 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
442 lstrlenA(value) + 1);
447 /***********************************************************************
450 static LONG register_progid(
453 char const *curver_progid,
460 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
461 NULL, 0, KEY_READ | KEY_WRITE, NULL,
463 if (res != ERROR_SUCCESS) return res;
466 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
467 (CONST BYTE*)name, strlen(name) + 1);
468 if (res != ERROR_SUCCESS) goto error_close_progid_key;
472 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
473 if (res != ERROR_SUCCESS) goto error_close_progid_key;
477 res = register_key_defvalueA(progid_key, curver_keyname,
479 if (res != ERROR_SUCCESS) goto error_close_progid_key;
485 res = RegCreateKeyExA(progid_key, extra, 0,
486 NULL, 0, KEY_READ | KEY_WRITE, NULL,
488 if (res == ERROR_SUCCESS)
489 RegCloseKey(extra_key);
492 error_close_progid_key:
493 RegCloseKey(progid_key);
497 static const GUID CLSID_MicrosoftBrowserArchitecture =
498 {0xa5e46e3a, 0x8849, 0x11d1, {0x9d, 0x8c, 0x00, 0xc0, 0x4f, 0xc9, 0x9d, 0x61}};
499 static const GUID CLSID_MruLongList =
500 {0x53bd6b4e, 0x3780, 0x4693, {0xaf, 0xc3, 0x71, 0x61, 0xc2, 0xf3, 0xee, 0x9c}};
502 /***********************************************************************
505 static struct regsvr_coclass const coclass_list[] = {
506 { &CLSID_WebBrowser_V1,
507 "Microsoft Web Browser Version 1",
515 "Microsoft Web Browser",
522 { &CLSID_InternetExplorer,
523 "Internet Explorer(Ver 1.0)",
527 "InternetExplorer.Application.1",
528 "InternetExplorer.Application"
530 { &CLSID_ShellSearchAssistantOC,
535 "SearchAssistantOC.SearchAssistantOC.1",
536 "SearchAssistantOC.SearchAssistantOC"
538 { &CLSID_ShellShellNameSpace,
543 "ShellNameSpace.ShellNameSpace.1",
544 "ShellNameSpace.ShellNameSpace"
546 { &CLSID_ShellNameSpace,
551 "ShellNameSpace.ShellNameSpace.1",
552 "ShellNameSpace.ShellNameSpace"
554 { &CLSID_ShellUIHelper,
555 "Microsoft Shell UI Helper",
562 { &CLSID_ShellWindows,
570 { &CLSID_SearchAssistantOC,
575 "SearchAssistantOC.SearchAssistantOC.1",
576 "SearchAssistantOC.SearchAssistantOC"
579 &CLSID_MicrosoftBrowserArchitecture,
580 "Microsoft Browser Architecture",
598 "Microsoft Url History Service",
614 SHELLFOLDER_ATTRIBUTES,
615 SFGAO_CANDELETE|SFGAO_CANLINK
617 { NULL } /* list terminator */
620 /***********************************************************************
624 static struct regsvr_interface const interface_list[] = {
625 { NULL } /* list terminator */
628 static HRESULT register_localserver(void)
630 HKEY coclass_key = 0, clsid_key = 0;
631 WCHAR buf[39], path[MAX_PATH];
635 res = SHGetFolderPathW(NULL, CSIDL_FLAG_CREATE|CSIDL_PROGRAM_FILES,
636 NULL, SHGFP_TYPE_CURRENT, path);
640 len = lstrlenW(path);
641 if ((len + (sizeof szIERelPath/sizeof(WCHAR)) + 1) > MAX_PATH)
645 lstrcpyW(&path[len+1], szIERelPath);
647 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
648 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
649 if (res != ERROR_SUCCESS) goto err;
651 StringFromGUID2(&CLSID_InternetExplorer, buf, 39);
652 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
653 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
654 if (res != ERROR_SUCCESS) goto err;
656 res = register_key_defvalueW(clsid_key, lcs32_keyname, path);
657 if (res != ERROR_SUCCESS) goto err;
660 if (clsid_key) RegCloseKey(clsid_key);
661 if (coclass_key) RegCloseKey(coclass_key);
662 return (res == ERROR_SUCCESS) ? S_OK : E_FAIL;
665 static HRESULT register_typelib(void)
670 static const WCHAR wszSHDocVw[] = {'s','h','d','o','c','v','w','.','d','l','l',0};
672 hres = LoadTypeLibEx(wszSHDocVw, REGKIND_REGISTER, &typelib);
674 ERR("Could not load typelib: %08x\n", hres);
678 ITypeLib_Release(typelib);
683 static HRESULT unregister_typelib(void)
685 return UnRegisterTypeLib(&LIBID_SHDocVw, 1, 1, LOCALE_SYSTEM_DEFAULT, SYS_WIN32);
688 /***********************************************************************
689 * DllRegisterServer (SHDOCVW.@)
691 HRESULT WINAPI DllRegisterServer(void)
697 hr = register_coclasses(coclass_list);
699 hr = register_interfaces(interface_list);
701 hr = register_localserver();
703 hr = register_typelib();
708 /***********************************************************************
709 * DllUnregisterServer (SHDOCVW.@)
711 HRESULT WINAPI DllUnregisterServer(void)
717 hr = unregister_coclasses(coclass_list);
719 hr = unregister_interfaces(interface_list);
721 hr = unregister_typelib();