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 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
70 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
72 /***********************************************************************
73 * static string constants
75 static WCHAR
const interface_keyname
[10] = {
76 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
77 static WCHAR
const base_ifa_keyname
[14] = {
78 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
80 static WCHAR
const num_methods_keyname
[11] = {
81 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
82 static WCHAR
const ps_clsid_keyname
[15] = {
83 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
85 static WCHAR
const ps_clsid32_keyname
[17] = {
86 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
87 'i', 'd', '3', '2', 0 };
88 static WCHAR
const clsid_keyname
[6] = {
89 'C', 'L', 'S', 'I', 'D', 0 };
90 static WCHAR
const curver_keyname
[7] = {
91 'C', 'u', 'r', 'V', 'e', 'r', 0 };
92 static WCHAR
const ips_keyname
[13] = {
93 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
95 static WCHAR
const ips32_keyname
[15] = {
96 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
98 static WCHAR
const progid_keyname
[7] = {
99 'P', 'r', 'o', 'g', 'I', 'D', 0 };
100 static WCHAR
const viprogid_keyname
[25] = {
101 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
102 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
104 static char const tmodel_valuename
[] = "ThreadingModel";
105 static WCHAR
const lcs32_keyname
[] = {
106 'L','o','c','a','l','S','e','r','v','e','r','3','2',0 };
107 static const WCHAR szIERelPath
[] = {
108 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
109 'i','e','x','p','l','o','r','e','.','e','x','e',0 };
111 /***********************************************************************
112 * static helper functions
114 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
115 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
117 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
119 static LONG
register_progid(WCHAR
const *clsid
,
120 char const *progid
, char const *curver_progid
,
121 char const *name
, char const *extra
);
122 static LONG
recursive_delete_key(HKEY key
);
123 static LONG
recursive_delete_keyA(HKEY base
, char const *name
);
124 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
);
126 /***********************************************************************
127 * register_interfaces
129 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
131 LONG res
= ERROR_SUCCESS
;
134 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
135 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
136 if (res
!= ERROR_SUCCESS
) goto error_return
;
138 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
142 StringFromGUID2(list
->iid
, buf
, 39);
143 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
144 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
145 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
148 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
149 (CONST BYTE
*)(list
->name
),
150 strlen(list
->name
) + 1);
151 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
154 if (list
->base_iid
) {
155 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
156 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
159 if (0 <= list
->num_methods
) {
160 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
163 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
164 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
165 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
167 wsprintfW(buf
, fmt
, list
->num_methods
);
168 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
170 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
173 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
176 if (list
->ps_clsid
) {
177 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
178 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
181 if (list
->ps_clsid32
) {
182 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
183 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
187 RegCloseKey(iid_key
);
190 error_close_interface_key
:
191 RegCloseKey(interface_key
);
193 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
196 /***********************************************************************
197 * unregister_interfaces
199 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
201 LONG res
= ERROR_SUCCESS
;
204 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
205 KEY_READ
| KEY_WRITE
, &interface_key
);
206 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
207 if (res
!= ERROR_SUCCESS
) goto error_return
;
209 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
212 StringFromGUID2(list
->iid
, buf
, 39);
213 res
= recursive_delete_keyW(interface_key
, buf
);
216 RegCloseKey(interface_key
);
218 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
221 /***********************************************************************
224 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
226 LONG res
= ERROR_SUCCESS
;
229 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
230 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
231 if (res
!= ERROR_SUCCESS
) goto error_return
;
233 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
237 StringFromGUID2(list
->clsid
, buf
, 39);
238 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
239 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
240 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
243 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
244 (CONST BYTE
*)(list
->name
),
245 strlen(list
->name
) + 1);
246 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
250 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
251 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
257 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
258 KEY_READ
| KEY_WRITE
, NULL
,
260 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
262 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
263 (CONST BYTE
*)list
->ips32
,
264 lstrlenA(list
->ips32
) + 1);
265 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
266 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
267 (CONST BYTE
*)list
->ips32_tmodel
,
268 strlen(list
->ips32_tmodel
) + 1);
269 RegCloseKey(ips32_key
);
270 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
274 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
276 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
278 res
= register_progid(buf
, list
->progid
, NULL
,
279 list
->name
, list
->progid_extra
);
280 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
283 if (list
->viprogid
) {
284 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
286 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
288 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
289 list
->name
, list
->progid_extra
);
290 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
293 error_close_clsid_key
:
294 RegCloseKey(clsid_key
);
297 error_close_coclass_key
:
298 RegCloseKey(coclass_key
);
300 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
303 /***********************************************************************
304 * unregister_coclasses
306 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
308 LONG res
= ERROR_SUCCESS
;
311 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
312 KEY_READ
| KEY_WRITE
, &coclass_key
);
313 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
314 if (res
!= ERROR_SUCCESS
) goto error_return
;
316 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
319 StringFromGUID2(list
->clsid
, buf
, 39);
320 res
= recursive_delete_keyW(coclass_key
, buf
);
321 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
324 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->progid
);
325 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
328 if (list
->viprogid
) {
329 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->viprogid
);
330 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
334 error_close_coclass_key
:
335 RegCloseKey(coclass_key
);
337 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
340 /***********************************************************************
343 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
347 StringFromGUID2(guid
, buf
, 39);
348 return register_key_defvalueW(base
, name
, buf
);
351 /***********************************************************************
352 * regsvr_key_defvalueW
354 static LONG
register_key_defvalueW(
362 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
363 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
364 if (res
!= ERROR_SUCCESS
) return res
;
365 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
366 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
371 /***********************************************************************
372 * regsvr_key_defvalueA
374 static LONG
register_key_defvalueA(
382 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
383 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
384 if (res
!= ERROR_SUCCESS
) return res
;
385 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
386 lstrlenA(value
) + 1);
391 /***********************************************************************
394 static LONG
register_progid(
397 char const *curver_progid
,
404 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
405 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
407 if (res
!= ERROR_SUCCESS
) return res
;
410 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
411 (CONST BYTE
*)name
, strlen(name
) + 1);
412 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
416 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
417 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
421 res
= register_key_defvalueA(progid_key
, curver_keyname
,
423 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
429 res
= RegCreateKeyExA(progid_key
, extra
, 0,
430 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
432 if (res
== ERROR_SUCCESS
)
433 RegCloseKey(extra_key
);
436 error_close_progid_key
:
437 RegCloseKey(progid_key
);
441 /***********************************************************************
442 * recursive_delete_key
444 static LONG
recursive_delete_key(HKEY key
)
447 WCHAR subkey_name
[MAX_PATH
];
452 cName
= sizeof(subkey_name
) / sizeof(WCHAR
);
453 res
= RegEnumKeyExW(key
, 0, subkey_name
, &cName
,
454 NULL
, NULL
, NULL
, NULL
);
455 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) {
456 res
= ERROR_SUCCESS
; /* presumably we're done enumerating */
459 res
= RegOpenKeyExW(key
, subkey_name
, 0,
460 KEY_READ
| KEY_WRITE
, &subkey
);
461 if (res
== ERROR_FILE_NOT_FOUND
) continue;
462 if (res
!= ERROR_SUCCESS
) break;
464 res
= recursive_delete_key(subkey
);
466 if (res
!= ERROR_SUCCESS
) break;
469 if (res
== ERROR_SUCCESS
) res
= RegDeleteKeyW(key
, 0);
473 /***********************************************************************
474 * recursive_delete_keyA
476 static LONG
recursive_delete_keyA(HKEY base
, char const *name
)
481 res
= RegOpenKeyExA(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
482 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
483 if (res
!= ERROR_SUCCESS
) return res
;
484 res
= recursive_delete_key(key
);
489 /***********************************************************************
490 * recursive_delete_keyW
492 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
)
497 res
= RegOpenKeyExW(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
498 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
499 if (res
!= ERROR_SUCCESS
) return res
;
500 res
= recursive_delete_key(key
);
506 static const GUID CLSID_MicrosoftBrowserArchitecture
=
507 {0xa5e46e3a, 0x8849, 0x11d1, {0x9d, 0x8c, 0x00, 0xc0, 0x4f, 0xc9, 0x9d, 0x61}};
509 /***********************************************************************
512 static struct regsvr_coclass
const coclass_list
[] = {
513 { &CLSID_WebBrowser_V1
,
514 "Microsoft Web Browser Version 1",
522 "Microsoft Web Browser",
529 { &CLSID_InternetExplorer
,
530 "Internet Explorer(Ver 1.0)",
534 "InternetExplorer.Application.1",
535 "InternetExplorer.Application"
537 { &CLSID_ShellSearchAssistantOC
,
542 "SearchAssistantOC.SearchAssistantOC.1",
543 "SearchAssistantOC.SearchAssistantOC"
545 { &CLSID_ShellShellNameSpace
,
550 "ShellNameSpace.ShellNameSpace.1",
551 "ShellNameSpace.ShellNameSpace"
553 { &CLSID_ShellNameSpace
,
558 "ShellNameSpace.ShellNameSpace.1",
559 "ShellNameSpace.ShellNameSpace"
561 { &CLSID_ShellUIHelper
,
562 "Microsoft Shell UI Helper",
569 { &CLSID_ShellWindows
,
577 { &CLSID_SearchAssistantOC
,
582 "SearchAssistantOC.SearchAssistantOC.1",
583 "SearchAssistantOC.SearchAssistantOC"
586 &CLSID_MicrosoftBrowserArchitecture
,
587 "Microsoft Browser Architecture",
594 { NULL
} /* list terminator */
597 /***********************************************************************
601 static struct regsvr_interface
const interface_list
[] = {
602 { NULL
} /* list terminator */
605 static HRESULT
register_localserver(void)
607 HKEY coclass_key
= 0, clsid_key
= 0;
608 WCHAR buf
[39], path
[MAX_PATH
];
612 res
= SHGetFolderPathW(NULL
, CSIDL_FLAG_CREATE
|CSIDL_PROGRAM_FILES
,
613 NULL
, SHGFP_TYPE_CURRENT
, path
);
617 len
= lstrlenW(path
);
618 if ((len
+ (sizeof szIERelPath
/sizeof(WCHAR
)) + 1) > MAX_PATH
)
622 lstrcpyW(&path
[len
+1], szIERelPath
);
624 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
625 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
626 if (res
!= ERROR_SUCCESS
) goto err
;
628 StringFromGUID2(&CLSID_InternetExplorer
, buf
, 39);
629 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
630 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
631 if (res
!= ERROR_SUCCESS
) goto err
;
633 res
= register_key_defvalueW(clsid_key
, lcs32_keyname
, path
);
634 if (res
!= ERROR_SUCCESS
) goto err
;
637 if (clsid_key
) RegCloseKey(clsid_key
);
638 if (coclass_key
) RegCloseKey(coclass_key
);
639 return (res
== ERROR_SUCCESS
) ? S_OK
: E_FAIL
;
642 /***********************************************************************
643 * DllRegisterServer (SHDOCVW.@)
645 HRESULT WINAPI
DllRegisterServer(void)
651 hr
= register_coclasses(coclass_list
);
653 hr
= register_interfaces(interface_list
);
655 hr
= register_localserver();
659 /***********************************************************************
660 * DllUnregisterServer (SHDOCVW.@)
662 HRESULT WINAPI
DllUnregisterServer(void)
668 hr
= unregister_coclasses(coclass_list
);
670 hr
= unregister_interfaces(interface_list
);