2 * self-registerable dll functions for inseng.dll
4 * Copyright (C) 2003 John K. Hohm
5 * Copyright (C) 2004 Steven Edwards for ReactOS
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(inseng);
39 DEFINE_GUID(CLSID_ActiveSetupEng, 0x6e449686,0xc509,0x11cf,0xaa,0xfa,0x00,0xaa,0x00,0xb6,0x01,0x5c );
40 DEFINE_GUID(CLSID_DLManager, 0xBFC880F1,0x7484,0x11D0,0x83,0x09,0x00,0xAA,0x00,0xB6,0x01,0x5C);
43 * Near the bottom of this file are the exported DllRegisterServer and
44 * DllUnregisterServer, which make all this worthwhile.
47 /***********************************************************************
48 * interface for self-registering
50 struct regsvr_interface
52 IID const *iid; /* NULL for end of list */
53 LPCSTR name; /* can be NULL to omit */
54 IID const *base_iid; /* can be NULL to omit */
55 int num_methods; /* can be <0 to omit */
56 CLSID const *ps_clsid; /* can be NULL to omit */
57 CLSID const *ps_clsid32; /* can be NULL to omit */
60 static HRESULT register_interfaces(struct regsvr_interface const *list);
61 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
65 CLSID const *clsid; /* NULL for end of list */
66 LPCSTR name; /* can be NULL to omit */
67 LPCSTR ips; /* can be NULL to omit */
68 LPCSTR ips32; /* can be NULL to omit */
69 LPCSTR ips32_tmodel; /* can be NULL to omit */
70 LPCSTR progid; /* can be NULL to omit */
71 LPCSTR viprogid; /* can be NULL to omit */
72 LPCSTR progid_extra; /* can be NULL to omit */
75 static HRESULT register_coclasses(struct regsvr_coclass const *list);
76 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
78 /***********************************************************************
79 * static string constants
81 static WCHAR const interface_keyname[10] = {
82 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
83 static WCHAR const base_ifa_keyname[14] = {
84 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
86 static WCHAR const num_methods_keyname[11] = {
87 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
88 static WCHAR const ps_clsid_keyname[15] = {
89 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91 static WCHAR const ps_clsid32_keyname[17] = {
92 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
93 'i', 'd', '3', '2', 0 };
94 static WCHAR const clsid_keyname[6] = {
95 'C', 'L', 'S', 'I', 'D', 0 };
96 static WCHAR const curver_keyname[7] = {
97 'C', 'u', 'r', 'V', 'e', 'r', 0 };
98 static WCHAR const ips_keyname[13] = {
99 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
101 static WCHAR const ips32_keyname[15] = {
102 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
104 static WCHAR const progid_keyname[7] = {
105 'P', 'r', 'o', 'g', 'I', 'D', 0 };
106 static WCHAR const viprogid_keyname[25] = {
107 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
108 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
110 static char const tmodel_valuename[] = "ThreadingModel";
112 /***********************************************************************
113 * static helper functions
115 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
116 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
118 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
120 static LONG register_progid(WCHAR const *clsid,
121 char const *progid, char const *curver_progid,
122 char const *name, char const *extra);
123 static LONG recursive_delete_key(HKEY key);
124 static LONG recursive_delete_keyA(HKEY base, char const *name);
125 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
127 /***********************************************************************
128 * register_interfaces
130 static HRESULT register_interfaces(struct regsvr_interface const *list)
132 LONG res = ERROR_SUCCESS;
135 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
136 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
137 if (res != ERROR_SUCCESS) goto error_return;
139 for (; res == ERROR_SUCCESS && list->iid; ++list) {
143 StringFromGUID2(list->iid, buf, 39);
144 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
145 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
146 if (res != ERROR_SUCCESS) goto error_close_interface_key;
149 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
150 (CONST BYTE*)(list->name),
151 strlen(list->name) + 1);
152 if (res != ERROR_SUCCESS) goto error_close_iid_key;
155 if (list->base_iid) {
156 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
157 if (res != ERROR_SUCCESS) goto error_close_iid_key;
160 if (0 <= list->num_methods) {
161 static WCHAR const fmt[3] = { '%', 'd', 0 };
164 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
165 KEY_READ | KEY_WRITE, NULL, &key, NULL);
166 if (res != ERROR_SUCCESS) goto error_close_iid_key;
168 wsprintfW(buf, fmt, list->num_methods);
169 res = RegSetValueExW(key, NULL, 0, REG_SZ,
171 (lstrlenW(buf) + 1) * sizeof(WCHAR));
174 if (res != ERROR_SUCCESS) goto error_close_iid_key;
177 if (list->ps_clsid) {
178 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
179 if (res != ERROR_SUCCESS) goto error_close_iid_key;
182 if (list->ps_clsid32) {
183 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
184 if (res != ERROR_SUCCESS) goto error_close_iid_key;
188 RegCloseKey(iid_key);
191 error_close_interface_key:
192 RegCloseKey(interface_key);
194 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
197 /***********************************************************************
198 * unregister_interfaces
200 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
202 LONG res = ERROR_SUCCESS;
205 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
206 KEY_READ | KEY_WRITE, &interface_key);
207 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
208 if (res != ERROR_SUCCESS) goto error_return;
210 for (; res == ERROR_SUCCESS && list->iid; ++list) {
213 StringFromGUID2(list->iid, buf, 39);
214 res = recursive_delete_keyW(interface_key, buf);
217 RegCloseKey(interface_key);
219 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
222 /***********************************************************************
225 static HRESULT register_coclasses(struct regsvr_coclass const *list)
227 LONG res = ERROR_SUCCESS;
230 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
231 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
232 if (res != ERROR_SUCCESS) goto error_return;
234 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
238 StringFromGUID2(list->clsid, buf, 39);
239 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
240 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
241 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
244 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
245 (CONST BYTE*)(list->name),
246 strlen(list->name) + 1);
247 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
251 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
252 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
258 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
259 KEY_READ | KEY_WRITE, NULL,
261 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
263 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
264 (CONST BYTE*)list->ips32,
265 lstrlenA(list->ips32) + 1);
266 if (res == ERROR_SUCCESS && list->ips32_tmodel)
267 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
268 (CONST BYTE*)list->ips32_tmodel,
269 strlen(list->ips32_tmodel) + 1);
270 RegCloseKey(ips32_key);
271 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
275 res = register_key_defvalueA(clsid_key, progid_keyname,
277 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
279 res = register_progid(buf, list->progid, NULL,
280 list->name, list->progid_extra);
281 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
284 if (list->viprogid) {
285 res = register_key_defvalueA(clsid_key, viprogid_keyname,
287 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
289 res = register_progid(buf, list->viprogid, list->progid,
290 list->name, list->progid_extra);
291 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
294 error_close_clsid_key:
295 RegCloseKey(clsid_key);
298 error_close_coclass_key:
299 RegCloseKey(coclass_key);
301 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
304 /***********************************************************************
305 * unregister_coclasses
307 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
309 LONG res = ERROR_SUCCESS;
312 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
313 KEY_READ | KEY_WRITE, &coclass_key);
314 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
315 if (res != ERROR_SUCCESS) goto error_return;
317 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
320 StringFromGUID2(list->clsid, buf, 39);
321 res = recursive_delete_keyW(coclass_key, buf);
322 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
325 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
326 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
329 if (list->viprogid) {
330 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
331 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
335 error_close_coclass_key:
336 RegCloseKey(coclass_key);
338 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
341 /***********************************************************************
344 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
348 StringFromGUID2(guid, buf, 39);
349 return register_key_defvalueW(base, name, buf);
352 /***********************************************************************
353 * regsvr_key_defvalueW
355 static LONG register_key_defvalueW(
363 res = RegCreateKeyExW(base, name, 0, NULL, 0,
364 KEY_READ | KEY_WRITE, NULL, &key, NULL);
365 if (res != ERROR_SUCCESS) return res;
366 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
367 (lstrlenW(value) + 1) * sizeof(WCHAR));
372 /***********************************************************************
373 * regsvr_key_defvalueA
375 static LONG register_key_defvalueA(
383 res = RegCreateKeyExW(base, name, 0, NULL, 0,
384 KEY_READ | KEY_WRITE, NULL, &key, NULL);
385 if (res != ERROR_SUCCESS) return res;
386 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
387 lstrlenA(value) + 1);
392 /***********************************************************************
395 static LONG register_progid(
398 char const *curver_progid,
405 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
406 NULL, 0, KEY_READ | KEY_WRITE, NULL,
408 if (res != ERROR_SUCCESS) return res;
411 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
412 (CONST BYTE*)name, strlen(name) + 1);
413 if (res != ERROR_SUCCESS) goto error_close_progid_key;
417 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
418 if (res != ERROR_SUCCESS) goto error_close_progid_key;
422 res = register_key_defvalueA(progid_key, curver_keyname,
424 if (res != ERROR_SUCCESS) goto error_close_progid_key;
430 res = RegCreateKeyExA(progid_key, extra, 0,
431 NULL, 0, KEY_READ | KEY_WRITE, NULL,
433 if (res == ERROR_SUCCESS)
434 RegCloseKey(extra_key);
437 error_close_progid_key:
438 RegCloseKey(progid_key);
442 /***********************************************************************
443 * recursive_delete_key
445 static LONG recursive_delete_key(HKEY key)
448 WCHAR subkey_name[MAX_PATH];
453 cName = sizeof(subkey_name) / sizeof(WCHAR);
454 res = RegEnumKeyExW(key, 0, subkey_name, &cName,
455 NULL, NULL, NULL, NULL);
456 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
457 res = ERROR_SUCCESS; /* presumably we're done enumerating */
460 res = RegOpenKeyExW(key, subkey_name, 0,
461 KEY_READ | KEY_WRITE, &subkey);
462 if (res == ERROR_FILE_NOT_FOUND) continue;
463 if (res != ERROR_SUCCESS) break;
465 res = recursive_delete_key(subkey);
467 if (res != ERROR_SUCCESS) break;
470 if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
474 /***********************************************************************
475 * recursive_delete_keyA
477 static LONG recursive_delete_keyA(HKEY base, char const *name)
482 res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
483 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
484 if (res != ERROR_SUCCESS) return res;
485 res = recursive_delete_key(key);
490 /***********************************************************************
491 * recursive_delete_keyW
493 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
498 res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
499 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
500 if (res != ERROR_SUCCESS) return res;
501 res = recursive_delete_key(key);
506 /***********************************************************************
509 static struct regsvr_coclass const coclass_list[] = {
511 &CLSID_ActiveSetupEng,
512 "Microsoft Active Setup Engine",
519 "Download Site Manager",
524 { NULL } /* list terminator */
527 /***********************************************************************
531 static struct regsvr_interface const interface_list[] = {
532 { NULL } /* list terminator */
535 /***********************************************************************
536 * DllRegisterServer (INSENG.@)
538 HRESULT WINAPI DllRegisterServer(void)
544 hr = register_coclasses(coclass_list);
546 hr = register_interfaces(interface_list);
550 /***********************************************************************
551 * DllUnregisterServer (INSENG.@)
553 HRESULT WINAPI DllUnregisterServer(void)
559 hr = unregister_coclasses(coclass_list);
561 hr = unregister_interfaces(interface_list);