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"
40 WINE_DEFAULT_DEBUG_CHANNEL(objsel);
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 {
51 IID const *iid; /* NULL for end of list */
52 LPCSTR name; /* can be NULL to omit */
53 IID const *base_iid; /* can be NULL to omit */
54 int num_methods; /* can be <0 to omit */
55 CLSID const *ps_clsid; /* can be NULL to omit */
56 CLSID const *ps_clsid32; /* can be NULL to omit */
59 static HRESULT register_interfaces(struct regsvr_interface const *list);
60 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
63 * @todo: maybe adding typelibs support here
64 * [Software\\Classes\\CLSID\\{000C1090-0000-0000-C000-000000000046}\\TypeLib] 1080380217
65 * @="{000C1092-0000-0000-C000-000000000046}"
67 struct regsvr_coclass {
68 CLSID const *clsid; /* NULL for end of list */
69 LPCSTR name; /* can be NULL to omit */
70 LPCSTR iph32; /* can be NULL to omit */
71 LPCSTR ips; /* can be NULL to omit */
72 LPCSTR ips32; /* can be NULL to omit */
73 LPCSTR ips32_tmodel; /* can be NULL to omit, if apartment, iph32 must be set */
74 LPCSTR progid; /* can be NULL to omit */
75 LPCSTR viprogid; /* can be NULL to omit */
76 LPCSTR progid_extra; /* can be NULL to omit */
79 static HRESULT register_coclasses(struct regsvr_coclass const *list);
80 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
82 /***********************************************************************
83 * static string constants
85 static WCHAR const interface_keyname[10] = {
86 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
87 static WCHAR const base_ifa_keyname[14] = {
88 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
90 static WCHAR const num_methods_keyname[11] = {
91 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
92 static WCHAR const ps_clsid_keyname[15] = {
93 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
95 static WCHAR const ps_clsid32_keyname[17] = {
96 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
97 'i', 'd', '3', '2', 0 };
98 static WCHAR const clsid_keyname[6] = {
99 'C', 'L', 'S', 'I', 'D', 0 };
100 static WCHAR const curver_keyname[7] = {
101 'C', 'u', 'r', 'V', 'e', 'r', 0 };
102 static WCHAR const iph32_keyname[] = {
103 'I', 'n', 'P', 'r', 'o', 'c', 'H', 'a', 'n', 'd', 'l', 'e', 'r',
105 static WCHAR const ips_keyname[13] = {
106 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
108 static WCHAR const ips32_keyname[15] = {
109 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
111 static WCHAR const progid_keyname[7] = {
112 'P', 'r', 'o', 'g', 'I', 'D', 0 };
113 static WCHAR const viprogid_keyname[25] = {
114 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
115 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
117 static char const tmodel_valuename[] = "ThreadingModel";
119 /***********************************************************************
120 * static helper functions
122 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
123 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
125 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
127 static LONG register_progid(WCHAR const *clsid,
128 char const *progid, char const *curver_progid,
129 char const *name, char const *extra);
131 /***********************************************************************
132 * register_interfaces
134 static HRESULT register_interfaces(struct regsvr_interface const *list) {
135 LONG res = ERROR_SUCCESS;
138 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
139 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
140 if (res != ERROR_SUCCESS) goto error_return;
142 for (; res == ERROR_SUCCESS && list->iid; ++list) {
146 StringFromGUID2(list->iid, buf, 39);
147 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
148 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
149 if (res != ERROR_SUCCESS) goto error_close_interface_key;
152 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
153 (CONST BYTE*)(list->name),
154 strlen(list->name) + 1);
155 if (res != ERROR_SUCCESS) goto error_close_iid_key;
158 if (list->base_iid) {
159 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
160 if (res != ERROR_SUCCESS) goto error_close_iid_key;
163 if (0 <= list->num_methods) {
164 static WCHAR const fmt[3] = { '%', 'd', 0 };
167 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
168 KEY_READ | KEY_WRITE, NULL, &key, NULL);
169 if (res != ERROR_SUCCESS) goto error_close_iid_key;
171 wsprintfW(buf, fmt, list->num_methods);
172 res = RegSetValueExW(key, NULL, 0, REG_SZ,
174 (lstrlenW(buf) + 1) * sizeof(WCHAR));
177 if (res != ERROR_SUCCESS) goto error_close_iid_key;
180 if (list->ps_clsid) {
181 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
182 if (res != ERROR_SUCCESS) goto error_close_iid_key;
185 if (list->ps_clsid32) {
186 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
187 if (res != ERROR_SUCCESS) goto error_close_iid_key;
191 RegCloseKey(iid_key);
194 error_close_interface_key:
195 RegCloseKey(interface_key);
197 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
200 /***********************************************************************
201 * unregister_interfaces
203 static HRESULT unregister_interfaces(struct regsvr_interface const *list) {
204 LONG res = ERROR_SUCCESS;
207 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
208 KEY_READ | KEY_WRITE, &interface_key);
209 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
210 if (res != ERROR_SUCCESS) goto error_return;
212 for (; res == ERROR_SUCCESS && list->iid; ++list) {
215 StringFromGUID2(list->iid, buf, 39);
216 res = RegDeleteTreeW(interface_key, buf);
217 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
220 RegCloseKey(interface_key);
222 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
225 /***********************************************************************
228 static HRESULT register_coclasses(struct regsvr_coclass const *list) {
229 LONG res = ERROR_SUCCESS;
232 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
233 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
234 if (res != ERROR_SUCCESS) goto error_return;
236 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
240 StringFromGUID2(list->clsid, buf, 39);
241 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
242 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
243 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
246 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
247 (CONST BYTE*)(list->name),
248 strlen(list->name) + 1);
249 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
255 res = RegCreateKeyExW(clsid_key, iph32_keyname, 0, NULL, 0,
256 KEY_READ | KEY_WRITE, NULL,
258 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
260 res = RegSetValueExA(iph32_key, NULL, 0, REG_SZ,
261 (CONST BYTE*)list->iph32,
262 lstrlenA(list->iph32) + 1);
263 RegCloseKey(iph32_key);
264 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
268 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
269 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
275 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
276 KEY_READ | KEY_WRITE, NULL,
278 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
280 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
281 (CONST BYTE*)list->ips32,
282 lstrlenA(list->ips32) + 1);
283 if (res == ERROR_SUCCESS && list->ips32_tmodel)
284 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
285 (CONST BYTE*)list->ips32_tmodel,
286 strlen(list->ips32_tmodel) + 1);
287 RegCloseKey(ips32_key);
288 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
292 res = register_key_defvalueA(clsid_key, progid_keyname,
294 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
296 res = register_progid(buf, list->progid, NULL,
297 list->name, list->progid_extra);
298 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
301 if (list->viprogid) {
302 res = register_key_defvalueA(clsid_key, viprogid_keyname,
304 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
306 res = register_progid(buf, list->viprogid, list->progid,
307 list->name, list->progid_extra);
308 if (res != ERROR_SUCCESS) goto error_close_clsid_key;
311 error_close_clsid_key:
312 RegCloseKey(clsid_key);
315 error_close_coclass_key:
316 RegCloseKey(coclass_key);
318 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
321 /***********************************************************************
322 * unregister_coclasses
324 static HRESULT unregister_coclasses(struct regsvr_coclass const *list) {
325 LONG res = ERROR_SUCCESS;
328 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
329 KEY_READ | KEY_WRITE, &coclass_key);
330 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
331 if (res != ERROR_SUCCESS) goto error_return;
333 for (; res == ERROR_SUCCESS && list->clsid; ++list) {
336 StringFromGUID2(list->clsid, buf, 39);
337 res = RegDeleteTreeW(coclass_key, buf);
338 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
339 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
342 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
343 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
344 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
347 if (list->viprogid) {
348 res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
349 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
350 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
354 error_close_coclass_key:
355 RegCloseKey(coclass_key);
357 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
360 /***********************************************************************
363 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) {
366 StringFromGUID2(guid, buf, 39);
367 return register_key_defvalueW(base, name, buf);
370 /***********************************************************************
371 * regsvr_key_defvalueW
373 static LONG register_key_defvalueW(
376 WCHAR const *value) {
380 res = RegCreateKeyExW(base, name, 0, NULL, 0,
381 KEY_READ | KEY_WRITE, NULL, &key, NULL);
382 if (res != ERROR_SUCCESS) return res;
383 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
384 (lstrlenW(value) + 1) * sizeof(WCHAR));
389 /***********************************************************************
390 * regsvr_key_defvalueA
392 static LONG register_key_defvalueA(
399 res = RegCreateKeyExW(base, name, 0, NULL, 0,
400 KEY_READ | KEY_WRITE, NULL, &key, NULL);
401 if (res != ERROR_SUCCESS) return res;
402 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
403 lstrlenA(value) + 1);
408 /***********************************************************************
411 static LONG register_progid(
414 char const *curver_progid,
420 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
421 NULL, 0, KEY_READ | KEY_WRITE, NULL,
423 if (res != ERROR_SUCCESS) return res;
426 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
427 (CONST BYTE*)name, strlen(name) + 1);
428 if (res != ERROR_SUCCESS) goto error_close_progid_key;
432 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
433 if (res != ERROR_SUCCESS) goto error_close_progid_key;
437 res = register_key_defvalueA(progid_key, curver_keyname,
439 if (res != ERROR_SUCCESS) goto error_close_progid_key;
445 res = RegCreateKeyExA(progid_key, extra, 0,
446 NULL, 0, KEY_READ | KEY_WRITE, NULL,
448 if (res == ERROR_SUCCESS)
449 RegCloseKey(extra_key);
452 error_close_progid_key:
453 RegCloseKey(progid_key);
457 /***********************************************************************
460 static struct regsvr_coclass const coclass_list[] = {
462 &CLSID_DsObjectPicker,
471 { NULL } /* list terminator */
474 /***********************************************************************
477 static struct regsvr_interface const interface_list[] = {
478 { NULL } /* list terminator */
481 /***********************************************************************
484 HRESULT WINAPI DllRegisterServer(void) {
489 hr = register_coclasses(coclass_list);
491 hr = register_interfaces(interface_list);
495 /***********************************************************************
496 * DllUnregisterServer
498 HRESULT WINAPI DllUnregisterServer(void) {
503 hr = unregister_coclasses(coclass_list);
505 hr = unregister_interfaces(interface_list);