2 * self-registerable dll functions for urlmon.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
37 #include "wine/debug.h"
39 #include "urlmon_main.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
44 * Near the bottom of this file are the exported DllRegisterServer and
45 * DllUnregisterServer, which make all this worthwhile.
48 /***********************************************************************
49 * interface for self-registering
51 struct regsvr_interface
53 IID const *iid; /* NULL for end of list */
54 LPCSTR name; /* can be NULL to omit */
55 IID const *base_iid; /* can be NULL to omit */
56 int num_methods; /* can be <0 to omit */
57 CLSID const *ps_clsid; /* can be NULL to omit */
58 CLSID const *ps_clsid32; /* can be NULL to omit */
61 static HRESULT register_interfaces(struct regsvr_interface const *list);
62 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
66 CLSID const *clsid; /* NULL for end of list */
67 LPCSTR name; /* can be NULL to omit */
68 LPCSTR ips; /* can be NULL to omit */
69 LPCSTR ips32; /* can be NULL to omit */
70 LPCSTR ips32_tmodel; /* can be NULL to omit */
71 LPCSTR progid; /* can be NULL to omit */
72 LPCSTR viprogid; /* can be NULL to omit */
73 LPCSTR progid_extra; /* can be NULL to omit */
76 static HRESULT register_coclasses(struct regsvr_coclass const *list);
77 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
79 /***********************************************************************
80 * static string constants
82 static WCHAR const interface_keyname[10] = {
83 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
84 static WCHAR const base_ifa_keyname[14] = {
85 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
87 static WCHAR const num_methods_keyname[11] = {
88 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
89 static WCHAR const ps_clsid_keyname[15] = {
90 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
92 static WCHAR const ps_clsid32_keyname[17] = {
93 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
94 'i', 'd', '3', '2', 0 };
95 static WCHAR const clsid_keyname[6] = {
96 'C', 'L', 'S', 'I', 'D', 0 };
97 static WCHAR const curver_keyname[7] = {
98 'C', 'u', 'r', 'V', 'e', 'r', 0 };
99 static WCHAR const ips_keyname[13] = {
100 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
102 static WCHAR const ips32_keyname[15] = {
103 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
105 static WCHAR const progid_keyname[7] = {
106 'P', 'r', 'o', 'g', 'I', 'D', 0 };
107 static WCHAR const viprogid_keyname[25] = {
108 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
109 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
111 static char const tmodel_valuename[] = "ThreadingModel";
113 /***********************************************************************
114 * static helper functions
116 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
117 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
119 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
121 static LONG register_progid(WCHAR const *clsid,
122 char const *progid, char const *curver_progid,
123 char const *name, char const *extra);
125 /***********************************************************************
126 * register_interfaces
128 static HRESULT register_interfaces(struct regsvr_interface const *list)
130 LONG res = ERROR_SUCCESS;
133 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
134 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
135 if (res != ERROR_SUCCESS) goto error_return;
137 for (; res == ERROR_SUCCESS && list->iid; ++list) {
141 StringFromGUID2(list->iid, buf, 39);
142 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
143 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
144 if (res != ERROR_SUCCESS) goto error_close_interface_key;
147 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
148 (CONST BYTE*)(list->name),
149 strlen(list->name) + 1);
150 if (res != ERROR_SUCCESS) goto error_close_iid_key;
153 if (list->base_iid) {
154 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
155 if (res != ERROR_SUCCESS) goto error_close_iid_key;
158 if (0 <= list->num_methods) {
159 static WCHAR const fmt[3] = { '%', 'd', 0 };
162 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
163 KEY_READ | KEY_WRITE, NULL, &key, NULL);
164 if (res != ERROR_SUCCESS) goto error_close_iid_key;
166 wsprintfW(buf, fmt, list->num_methods);
167 res = RegSetValueExW(key, NULL, 0, REG_SZ,
169 (lstrlenW(buf) + 1) * sizeof(WCHAR));
172 if (res != ERROR_SUCCESS) goto error_close_iid_key;
175 if (list->ps_clsid) {
176 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
177 if (res != ERROR_SUCCESS) goto error_close_iid_key;
180 if (list->ps_clsid32) {
181 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
182 if (res != ERROR_SUCCESS) goto error_close_iid_key;
186 RegCloseKey(iid_key);
189 error_close_interface_key:
190 RegCloseKey(interface_key);
192 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
195 /***********************************************************************
196 * unregister_interfaces
198 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
200 LONG res = ERROR_SUCCESS;
203 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
204 KEY_READ | KEY_WRITE, &interface_key);
205 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
206 if (res != ERROR_SUCCESS) goto error_return;
208 for (; res == ERROR_SUCCESS && list->iid; ++list) {
211 StringFromGUID2(list->iid, buf, 39);
212 res = RegDeleteTreeW(interface_key, buf);
213 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
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 = RegDeleteTreeW(coclass_key, buf);
321 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
322 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
325 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
326 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
327 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
330 if (list->viprogid) {
331 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
332 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
333 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
337 error_close_coclass_key:
338 RegCloseKey(coclass_key);
340 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
343 /***********************************************************************
346 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
350 StringFromGUID2(guid, buf, 39);
351 return register_key_defvalueW(base, name, buf);
354 /***********************************************************************
355 * regsvr_key_defvalueW
357 static LONG register_key_defvalueW(
365 res = RegCreateKeyExW(base, name, 0, NULL, 0,
366 KEY_READ | KEY_WRITE, NULL, &key, NULL);
367 if (res != ERROR_SUCCESS) return res;
368 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
369 (lstrlenW(value) + 1) * sizeof(WCHAR));
374 /***********************************************************************
375 * regsvr_key_defvalueA
377 static LONG register_key_defvalueA(
385 res = RegCreateKeyExW(base, name, 0, NULL, 0,
386 KEY_READ | KEY_WRITE, NULL, &key, NULL);
387 if (res != ERROR_SUCCESS) return res;
388 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
389 lstrlenA(value) + 1);
394 /***********************************************************************
397 static LONG register_progid(
400 char const *curver_progid,
407 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
408 NULL, 0, KEY_READ | KEY_WRITE, NULL,
410 if (res != ERROR_SUCCESS) return res;
413 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
414 (CONST BYTE*)name, strlen(name) + 1);
415 if (res != ERROR_SUCCESS) goto error_close_progid_key;
419 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
420 if (res != ERROR_SUCCESS) goto error_close_progid_key;
424 res = register_key_defvalueA(progid_key, curver_keyname,
426 if (res != ERROR_SUCCESS) goto error_close_progid_key;
432 res = RegCreateKeyExA(progid_key, extra, 0,
433 NULL, 0, KEY_READ | KEY_WRITE, NULL,
435 if (res == ERROR_SUCCESS)
436 RegCloseKey(extra_key);
439 error_close_progid_key:
440 RegCloseKey(progid_key);
444 /***********************************************************************
447 static struct regsvr_coclass const coclass_list[] = {
448 { &CLSID_StdURLMoniker,
454 { &CLSID_CdlProtocol,
455 "CDL: Asynchronous Pluggable Protocol Handler",
460 { &CLSID_FileProtocol,
461 "file:, local: Asynchronous Pluggable Protocol Handler",
466 { &CLSID_FtpProtocol,
467 "ftp: Asynchronous Pluggable Protocol Handler",
472 { &CLSID_GopherProtocol,
473 "gopher: Asynchronous Pluggable Protocol Handler",
478 { &CLSID_HttpProtocol,
479 "http: Asynchronous Pluggable Protocol Handler",
484 { &CLSID_HttpSProtocol,
485 "https: Asynchronous Pluggable Protocol Handler",
491 "mk: Asynchronous Pluggable Protocol Handler",
496 { &CLSID_InternetSecurityManager,
502 { &CLSID_InternetZoneManager,
508 { NULL } /* list terminator */
511 /***********************************************************************
515 static struct regsvr_interface const interface_list[] = {
516 { NULL } /* list terminator */
519 /***********************************************************************
523 #define INF_SET_CLSID(clsid) \
526 static CHAR name[] = "CLSID_" #clsid; \
528 pse[i].pszName = name; \
529 clsids[i++] = &CLSID_ ## clsid; \
532 static HRESULT register_inf(BOOL doregister)
536 typeof(RegInstallA) *pRegInstall;
539 static CLSID const *clsids[34];
542 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
544 INF_SET_CLSID(CdlProtocol);
545 INF_SET_CLSID(FileProtocol);
546 INF_SET_CLSID(FtpProtocol);
547 INF_SET_CLSID(GopherProtocol);
548 INF_SET_CLSID(HttpProtocol);
549 INF_SET_CLSID(HttpSProtocol);
550 INF_SET_CLSID(MkProtocol);
552 for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++) {
553 pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39);
554 sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
555 clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
556 clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
557 clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
560 strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
563 hAdvpack = LoadLibraryW(wszAdvpack);
564 pRegInstall = (typeof(RegInstallA)*)GetProcAddress(hAdvpack, "RegInstall");
566 hres = pRegInstall(URLMON_hInstance, doregister ? "RegisterDll" : "UnregisterDll", &strtable);
568 for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
569 HeapFree(GetProcessHeap(), 0, pse[i].pszValue);
576 /***********************************************************************
577 * DllRegisterServer (URLMON.@)
579 HRESULT WINAPI DllRegisterServer(void)
585 hr = register_coclasses(coclass_list);
587 hr = register_interfaces(interface_list);
590 return register_inf(TRUE);
593 /***********************************************************************
594 * DllUnregisterServer (URLMON.@)
596 HRESULT WINAPI DllUnregisterServer(void)
602 hr = unregister_coclasses(coclass_list);
604 hr = unregister_interfaces(interface_list);
607 return register_inf(FALSE);