2 * self-registerable dll functions for objsel.dll
4 * Copyright (C) 2004 Raphael Junqueira
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
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(objsel);
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 {
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);
64 * @todo: maybe adding typelibs support here
65 * [Software\\Classes\\CLSID\\{000C1090-0000-0000-C000-000000000046}\\TypeLib] 1080380217
66 * @="{000C1092-0000-0000-C000-000000000046}"
68 struct regsvr_coclass {
69 CLSID const *clsid; /* NULL for end of list */
70 LPCSTR name; /* can be NULL to omit */
71 LPCSTR iph32; /* can be NULL to omit */
72 LPCSTR ips; /* can be NULL to omit */
73 LPCSTR ips32; /* can be NULL to omit */
74 LPCSTR ips32_tmodel; /* can be NULL to omit, if apartment, iph32 must be set */
75 LPCSTR progid; /* can be NULL to omit */
76 LPCSTR viprogid; /* can be NULL to omit */
77 LPCSTR progid_extra; /* can be NULL to omit */
80 static HRESULT register_coclasses(struct regsvr_coclass const *list);
81 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
83 /***********************************************************************
84 * static string constants
86 static WCHAR const interface_keyname[10] = {
87 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
88 static WCHAR const base_ifa_keyname[14] = {
89 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
91 static WCHAR const num_methods_keyname[11] = {
92 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
93 static WCHAR const ps_clsid_keyname[15] = {
94 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
96 static WCHAR const ps_clsid32_keyname[17] = {
97 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
98 'i', 'd', '3', '2', 0 };
99 static WCHAR const clsid_keyname[6] = {
100 'C', 'L', 'S', 'I', 'D', 0 };
101 static WCHAR const curver_keyname[7] = {
102 'C', 'u', 'r', 'V', 'e', 'r', 0 };
103 static WCHAR const iph32_keyname[] = {
104 'I', 'n', 'P', 'r', 'o', 'c', 'H', 'a', 'n', 'd', 'l', 'e', 'r',
106 static WCHAR const ips_keyname[13] = {
107 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
109 static WCHAR const ips32_keyname[15] = {
110 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
112 static WCHAR const progid_keyname[7] = {
113 'P', 'r', 'o', 'g', 'I', 'D', 0 };
114 static WCHAR const viprogid_keyname[25] = {
115 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
116 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
118 static char const tmodel_valuename[] = "ThreadingModel";
120 /***********************************************************************
121 * static helper functions
123 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
124 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
126 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
128 static LONG register_progid(WCHAR const *clsid,
129 char const *progid, char const *curver_progid,
130 char const *name, char const *extra);
132 /***********************************************************************
133 * register_interfaces
135 static HRESULT register_interfaces(struct regsvr_interface const *list) {
136 LONG res = ERROR_SUCCESS;
139 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
140 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
141 if (res != ERROR_SUCCESS) goto error_return;
143 for (; res == ERROR_SUCCESS && list->iid; ++list) {
147 StringFromGUID2(list->iid, buf, 39);
148 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
149 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
150 if (res != ERROR_SUCCESS) goto error_close_interface_key;
153 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
154 (CONST BYTE*)(list->name),
155 strlen(list->name) + 1);
156 if (res != ERROR_SUCCESS) goto error_close_iid_key;
159 if (list->base_iid) {
160 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
161 if (res != ERROR_SUCCESS) goto error_close_iid_key;
164 if (0 <= list->num_methods) {
165 static WCHAR const fmt[3] = { '%', 'd', 0 };
168 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
169 KEY_READ | KEY_WRITE, NULL, &key, NULL);
170 if (res != ERROR_SUCCESS) goto error_close_iid_key;
172 sprintfW(buf, fmt, list->num_methods);
173 res = RegSetValueExW(key, NULL, 0, REG_SZ,
175 (lstrlenW(buf) + 1) * sizeof(WCHAR));
178 if (res != ERROR_SUCCESS) goto error_close_iid_key;
181 if (list->ps_clsid) {
182 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
183 if (res != ERROR_SUCCESS) goto error_close_iid_key;
186 if (list->ps_clsid32) {
187 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
188 if (res != ERROR_SUCCESS) goto error_close_iid_key;
192 RegCloseKey(iid_key);
195 error_close_interface_key:
196 RegCloseKey(interface_key);
198 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
201 /***********************************************************************
202 * unregister_interfaces
204 static HRESULT unregister_interfaces(struct regsvr_interface const *list) {
205 LONG res = ERROR_SUCCESS;
208 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
209 KEY_READ | KEY_WRITE, &interface_key);
210 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
211 if (res != ERROR_SUCCESS) goto error_return;
213 for (; res == ERROR_SUCCESS && list->iid; ++list) {
216 StringFromGUID2(list->iid, buf, 39);
217 res = RegDeleteTreeW(interface_key, buf);
218 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
221 RegCloseKey(interface_key);
223 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
226 /***********************************************************************
229 static HRESULT register_coclasses(struct regsvr_coclass const *list) {
230 LONG res = ERROR_SUCCESS;
233 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
234 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
235 if (res != ERROR_SUCCESS) goto error_return;
237 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
241 StringFromGUID2(list->clsid, buf, 39);
242 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
243 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
244 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
247 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
248 (CONST BYTE*)(list->name),
249 strlen(list->name) + 1);
250 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
256 res = RegCreateKeyExW(clsid_key, iph32_keyname, 0, NULL, 0,
257 KEY_READ | KEY_WRITE, NULL,
259 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
261 res = RegSetValueExA(iph32_key, NULL, 0, REG_SZ,
262 (CONST BYTE*)list->iph32,
263 lstrlenA(list->iph32) + 1);
264 RegCloseKey(iph32_key);
265 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
269 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
270 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
276 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
277 KEY_READ | KEY_WRITE, NULL,
279 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
281 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
282 (CONST BYTE*)list->ips32,
283 lstrlenA(list->ips32) + 1);
284 if (res == ERROR_SUCCESS && list->ips32_tmodel)
285 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
286 (CONST BYTE*)list->ips32_tmodel,
287 strlen(list->ips32_tmodel) + 1);
288 RegCloseKey(ips32_key);
289 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
293 res = register_key_defvalueA(clsid_key, progid_keyname,
295 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
297 res = register_progid(buf, list->progid, NULL,
298 list->name, list->progid_extra);
299 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
302 if (list->viprogid) {
303 res = register_key_defvalueA(clsid_key, viprogid_keyname,
305 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
307 res = register_progid(buf, list->viprogid, list->progid,
308 list->name, list->progid_extra);
309 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
312 error_close_clsid_key:
313 RegCloseKey(clsid_key);
316 error_close_coclass_key:
317 RegCloseKey(coclass_key);
319 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
322 /***********************************************************************
323 * unregister_coclasses
325 static HRESULT unregister_coclasses(struct regsvr_coclass const *list) {
326 LONG res = ERROR_SUCCESS;
329 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
330 KEY_READ | KEY_WRITE, &coclass_key);
331 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
332 if (res != ERROR_SUCCESS) goto error_return;
334 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
337 StringFromGUID2(list->clsid, buf, 39);
338 res = RegDeleteTreeW(coclass_key, buf);
339 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
340 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
343 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
344 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
345 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
348 if (list->viprogid) {
349 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
350 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
351 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
355 error_close_coclass_key:
356 RegCloseKey(coclass_key);
358 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
361 /***********************************************************************
364 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) {
367 StringFromGUID2(guid, buf, 39);
368 return register_key_defvalueW(base, name, buf);
371 /***********************************************************************
372 * regsvr_key_defvalueW
374 static LONG register_key_defvalueW(
377 WCHAR const *value) {
381 res = RegCreateKeyExW(base, name, 0, NULL, 0,
382 KEY_READ | KEY_WRITE, NULL, &key, NULL);
383 if (res != ERROR_SUCCESS) return res;
384 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
385 (lstrlenW(value) + 1) * sizeof(WCHAR));
390 /***********************************************************************
391 * regsvr_key_defvalueA
393 static LONG register_key_defvalueA(
400 res = RegCreateKeyExW(base, name, 0, NULL, 0,
401 KEY_READ | KEY_WRITE, NULL, &key, NULL);
402 if (res != ERROR_SUCCESS) return res;
403 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
404 lstrlenA(value) + 1);
409 /***********************************************************************
412 static LONG register_progid(
415 char const *curver_progid,
421 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
422 NULL, 0, KEY_READ | KEY_WRITE, NULL,
424 if (res != ERROR_SUCCESS) return res;
427 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
428 (CONST BYTE*)name, strlen(name) + 1);
429 if (res != ERROR_SUCCESS) goto error_close_progid_key;
433 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
434 if (res != ERROR_SUCCESS) goto error_close_progid_key;
438 res = register_key_defvalueA(progid_key, curver_keyname,
440 if (res != ERROR_SUCCESS) goto error_close_progid_key;
446 res = RegCreateKeyExA(progid_key, extra, 0,
447 NULL, 0, KEY_READ | KEY_WRITE, NULL,
449 if (res == ERROR_SUCCESS)
450 RegCloseKey(extra_key);
453 error_close_progid_key:
454 RegCloseKey(progid_key);
458 /***********************************************************************
461 static struct regsvr_coclass const coclass_list[] = {
463 &CLSID_DsObjectPicker,
472 { NULL } /* list terminator */
475 /***********************************************************************
478 static struct regsvr_interface const interface_list[] = {
479 { NULL } /* list terminator */
482 /***********************************************************************
485 HRESULT WINAPI DllRegisterServer(void) {
490 hr = register_coclasses(coclass_list);
492 hr = register_interfaces(interface_list);
496 /***********************************************************************
497 * DllUnregisterServer
499 HRESULT WINAPI DllUnregisterServer(void) {
504 hr = unregister_coclasses(coclass_list);
506 hr = unregister_interfaces(interface_list);