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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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";
106 /***********************************************************************
107 * static helper functions
109 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
110 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
112 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
114 static LONG register_progid(WCHAR const *clsid,
115 char const *progid, char const *curver_progid,
116 char const *name, char const *extra);
117 static LONG recursive_delete_key(HKEY key);
118 static LONG recursive_delete_keyA(HKEY base, char const *name);
119 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
121 /***********************************************************************
122 * register_interfaces
124 static HRESULT register_interfaces(struct regsvr_interface const *list)
126 LONG res = ERROR_SUCCESS;
129 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
130 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
131 if (res != ERROR_SUCCESS) goto error_return;
133 for (; res == ERROR_SUCCESS && list->iid; ++list) {
137 StringFromGUID2(list->iid, buf, 39);
138 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
139 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
140 if (res != ERROR_SUCCESS) goto error_close_interface_key;
143 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
144 (CONST BYTE*)(list->name),
145 strlen(list->name) + 1);
146 if (res != ERROR_SUCCESS) goto error_close_iid_key;
149 if (list->base_iid) {
150 register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
151 if (res != ERROR_SUCCESS) goto error_close_iid_key;
154 if (0 <= list->num_methods) {
155 static WCHAR const fmt[3] = { '%', 'd', 0 };
158 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
159 KEY_READ | KEY_WRITE, NULL, &key, NULL);
160 if (res != ERROR_SUCCESS) goto error_close_iid_key;
162 wsprintfW(buf, fmt, list->num_methods);
163 res = RegSetValueExW(key, NULL, 0, REG_SZ,
165 (lstrlenW(buf) + 1) * sizeof(WCHAR));
168 if (res != ERROR_SUCCESS) goto error_close_iid_key;
171 if (list->ps_clsid) {
172 register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
173 if (res != ERROR_SUCCESS) goto error_close_iid_key;
176 if (list->ps_clsid32) {
177 register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
178 if (res != ERROR_SUCCESS) goto error_close_iid_key;
182 RegCloseKey(iid_key);
185 error_close_interface_key:
186 RegCloseKey(interface_key);
188 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
191 /***********************************************************************
192 * unregister_interfaces
194 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
196 LONG res = ERROR_SUCCESS;
199 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
200 KEY_READ | KEY_WRITE, &interface_key);
201 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
202 if (res != ERROR_SUCCESS) goto error_return;
204 for (; res == ERROR_SUCCESS && list->iid; ++list) {
207 StringFromGUID2(list->iid, buf, 39);
208 res = recursive_delete_keyW(interface_key, buf);
211 RegCloseKey(interface_key);
213 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
216 /***********************************************************************
219 static HRESULT register_coclasses(struct regsvr_coclass const *list)
221 LONG res = ERROR_SUCCESS;
224 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
225 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
226 if (res != ERROR_SUCCESS) goto error_return;
228 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
232 StringFromGUID2(list->clsid, buf, 39);
233 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
234 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
235 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
238 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
239 (CONST BYTE*)(list->name),
240 strlen(list->name) + 1);
241 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
245 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
246 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
252 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
253 KEY_READ | KEY_WRITE, NULL,
255 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
257 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
258 (CONST BYTE*)list->ips32,
259 lstrlenA(list->ips32) + 1);
260 if (res == ERROR_SUCCESS && list->ips32_tmodel)
261 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
262 (CONST BYTE*)list->ips32_tmodel,
263 strlen(list->ips32_tmodel) + 1);
264 RegCloseKey(ips32_key);
265 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
269 res = register_key_defvalueA(clsid_key, progid_keyname,
271 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
273 res = register_progid(buf, list->progid, NULL,
274 list->name, list->progid_extra);
275 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
278 if (list->viprogid) {
279 res = register_key_defvalueA(clsid_key, viprogid_keyname,
281 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
283 res = register_progid(buf, list->viprogid, list->progid,
284 list->name, list->progid_extra);
285 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
288 error_close_clsid_key:
289 RegCloseKey(clsid_key);
292 error_close_coclass_key:
293 RegCloseKey(coclass_key);
295 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
298 /***********************************************************************
299 * unregister_coclasses
301 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
303 LONG res = ERROR_SUCCESS;
306 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
307 KEY_READ | KEY_WRITE, &coclass_key);
308 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
309 if (res != ERROR_SUCCESS) goto error_return;
311 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
314 StringFromGUID2(list->clsid, buf, 39);
315 res = recursive_delete_keyW(coclass_key, buf);
316 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
319 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
320 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
323 if (list->viprogid) {
324 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
325 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
329 error_close_coclass_key:
330 RegCloseKey(coclass_key);
332 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
335 /***********************************************************************
338 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
342 StringFromGUID2(guid, buf, 39);
343 return register_key_defvalueW(base, name, buf);
346 /***********************************************************************
347 * regsvr_key_defvalueW
349 static LONG register_key_defvalueW(
357 res = RegCreateKeyExW(base, name, 0, NULL, 0,
358 KEY_READ | KEY_WRITE, NULL, &key, NULL);
359 if (res != ERROR_SUCCESS) return res;
360 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
361 (lstrlenW(value) + 1) * sizeof(WCHAR));
366 /***********************************************************************
367 * regsvr_key_defvalueA
369 static LONG register_key_defvalueA(
377 res = RegCreateKeyExW(base, name, 0, NULL, 0,
378 KEY_READ | KEY_WRITE, NULL, &key, NULL);
379 if (res != ERROR_SUCCESS) return res;
380 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
381 lstrlenA(value) + 1);
386 /***********************************************************************
389 static LONG register_progid(
392 char const *curver_progid,
399 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
400 NULL, 0, KEY_READ | KEY_WRITE, NULL,
402 if (res != ERROR_SUCCESS) return res;
405 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
406 (CONST BYTE*)name, strlen(name) + 1);
407 if (res != ERROR_SUCCESS) goto error_close_progid_key;
411 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
412 if (res != ERROR_SUCCESS) goto error_close_progid_key;
416 res = register_key_defvalueA(progid_key, curver_keyname,
418 if (res != ERROR_SUCCESS) goto error_close_progid_key;
424 res = RegCreateKeyExA(progid_key, extra, 0,
425 NULL, 0, KEY_READ | KEY_WRITE, NULL,
427 if (res == ERROR_SUCCESS)
428 RegCloseKey(extra_key);
431 error_close_progid_key:
432 RegCloseKey(progid_key);
436 /***********************************************************************
437 * recursive_delete_key
439 static LONG recursive_delete_key(HKEY key)
442 WCHAR subkey_name[MAX_PATH];
447 cName = sizeof(subkey_name) / sizeof(WCHAR);
448 res = RegEnumKeyExW(key, 0, subkey_name, &cName,
449 NULL, NULL, NULL, NULL);
450 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
451 res = ERROR_SUCCESS; /* presumably we're done enumerating */
454 res = RegOpenKeyExW(key, subkey_name, 0,
455 KEY_READ | KEY_WRITE, &subkey);
456 if (res == ERROR_FILE_NOT_FOUND) continue;
457 if (res != ERROR_SUCCESS) break;
459 res = recursive_delete_key(subkey);
461 if (res != ERROR_SUCCESS) break;
464 if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
468 /***********************************************************************
469 * recursive_delete_keyA
471 static LONG recursive_delete_keyA(HKEY base, char const *name)
476 res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
477 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
478 if (res != ERROR_SUCCESS) return res;
479 res = recursive_delete_key(key);
484 /***********************************************************************
485 * recursive_delete_keyW
487 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
492 res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
493 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
494 if (res != ERROR_SUCCESS) return res;
495 res = recursive_delete_key(key);
500 /***********************************************************************
503 static struct regsvr_coclass const coclass_list[] = {
505 "Microsoft Web Browser",
512 { NULL } /* list terminator */
515 /***********************************************************************
519 static struct regsvr_interface const interface_list[] = {
520 { NULL } /* list terminator */
523 /***********************************************************************
524 * DllRegisterServer (SHDOCVW.@)
526 HRESULT WINAPI SHDOCVW_DllRegisterServer(void)
532 hr = register_coclasses(coclass_list);
534 hr = register_interfaces(interface_list);
538 /***********************************************************************
539 * DllUnregisterServer (SHDOCVW.@)
541 HRESULT WINAPI SHDOCVW_DllUnregisterServer(void)
547 hr = unregister_coclasses(coclass_list);
549 hr = unregister_interfaces(interface_list);