2 * self-registerable dll functions for browseui.dll
4 * Copyright (C) 2004 Stefan Leichter
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
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(browseui
);
41 * Near the bottom of this file are the exported DllRegisterServer and
42 * DllUnregisterServer, which make all this worthwhile.
45 /***********************************************************************
46 * interface for self-registering
48 struct regsvr_interface
50 IID
const *iid
; /* NULL for end of list */
51 LPCSTR name
; /* can be NULL to omit */
52 IID
const *base_iid
; /* can be NULL to omit */
53 int num_methods
; /* can be <0 to omit */
54 CLSID
const *ps_clsid
; /* can be NULL to omit */
55 CLSID
const *ps_clsid32
; /* can be NULL to omit */
58 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
59 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
63 CLSID
const *clsid
; /* NULL for end of list */
64 LPCSTR name
; /* can be NULL to omit */
65 LPCSTR ips
; /* can be NULL to omit */
66 LPCSTR ips32
; /* can be NULL to omit */
67 LPCSTR ips32_tmodel
; /* can be NULL to omit */
68 LPCSTR progid
; /* can be NULL to omit */
69 LPCSTR viprogid
; /* can be NULL to omit */
70 LPCSTR progid_extra
; /* can be NULL to omit */
73 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
74 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
76 /***********************************************************************
77 * static string constants
79 static WCHAR
const interface_keyname
[10] = {
80 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
81 static WCHAR
const base_ifa_keyname
[14] = {
82 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
84 static WCHAR
const num_methods_keyname
[11] = {
85 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
86 static WCHAR
const ps_clsid_keyname
[15] = {
87 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
89 static WCHAR
const ps_clsid32_keyname
[17] = {
90 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91 'i', 'd', '3', '2', 0 };
92 static WCHAR
const clsid_keyname
[6] = {
93 'C', 'L', 'S', 'I', 'D', 0 };
94 static WCHAR
const curver_keyname
[7] = {
95 'C', 'u', 'r', 'V', 'e', 'r', 0 };
96 static WCHAR
const ips_keyname
[13] = {
97 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
99 static WCHAR
const ips32_keyname
[15] = {
100 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
102 static WCHAR
const progid_keyname
[7] = {
103 'P', 'r', 'o', 'g', 'I', 'D', 0 };
104 static WCHAR
const viprogid_keyname
[25] = {
105 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
106 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
108 static char const tmodel_valuename
[] = "ThreadingModel";
110 /***********************************************************************
111 * static helper functions
113 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
114 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
116 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
118 static LONG
register_progid(WCHAR
const *clsid
,
119 char const *progid
, char const *curver_progid
,
120 char const *name
, char const *extra
);
122 /***********************************************************************
123 * register_interfaces
125 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
127 LONG res
= ERROR_SUCCESS
;
130 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
131 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
132 if (res
!= ERROR_SUCCESS
) goto error_return
;
134 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
138 StringFromGUID2(list
->iid
, buf
, 39);
139 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
140 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
141 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
144 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
145 (CONST BYTE
*)(list
->name
),
146 strlen(list
->name
) + 1);
147 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
150 if (list
->base_iid
) {
151 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
152 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
155 if (0 <= list
->num_methods
) {
156 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
159 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
160 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
161 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
163 sprintfW(buf
, fmt
, list
->num_methods
);
164 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
166 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
169 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
172 if (list
->ps_clsid
) {
173 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
174 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
177 if (list
->ps_clsid32
) {
178 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
179 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
183 RegCloseKey(iid_key
);
186 error_close_interface_key
:
187 RegCloseKey(interface_key
);
189 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
192 /***********************************************************************
193 * unregister_interfaces
195 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
197 LONG res
= ERROR_SUCCESS
;
200 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
201 KEY_READ
| KEY_WRITE
, &interface_key
);
202 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
203 if (res
!= ERROR_SUCCESS
) goto error_return
;
205 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
208 StringFromGUID2(list
->iid
, buf
, 39);
209 res
= RegDeleteTreeW(interface_key
, buf
);
210 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
213 RegCloseKey(interface_key
);
215 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
218 /***********************************************************************
221 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
223 LONG res
= ERROR_SUCCESS
;
226 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
227 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
228 if (res
!= ERROR_SUCCESS
) goto error_return
;
230 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
234 StringFromGUID2(list
->clsid
, buf
, 39);
235 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
236 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
237 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
240 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
241 (CONST BYTE
*)(list
->name
),
242 strlen(list
->name
) + 1);
243 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
247 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
248 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
254 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
255 KEY_READ
| KEY_WRITE
, NULL
,
257 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
259 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
260 (CONST BYTE
*)list
->ips32
,
261 lstrlenA(list
->ips32
) + 1);
262 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
263 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
264 (CONST BYTE
*)list
->ips32_tmodel
,
265 strlen(list
->ips32_tmodel
) + 1);
266 RegCloseKey(ips32_key
);
267 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
271 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
273 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
275 res
= register_progid(buf
, list
->progid
, NULL
,
276 list
->name
, list
->progid_extra
);
277 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
280 if (list
->viprogid
) {
281 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
283 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
285 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
286 list
->name
, list
->progid_extra
);
287 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
290 error_close_clsid_key
:
291 RegCloseKey(clsid_key
);
294 error_close_coclass_key
:
295 RegCloseKey(coclass_key
);
297 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
300 /***********************************************************************
301 * unregister_coclasses
303 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
305 LONG res
= ERROR_SUCCESS
;
308 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
309 KEY_READ
| KEY_WRITE
, &coclass_key
);
310 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
311 if (res
!= ERROR_SUCCESS
) goto error_return
;
313 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
316 StringFromGUID2(list
->clsid
, buf
, 39);
317 res
= RegDeleteTreeW(coclass_key
, buf
);
318 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
319 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
322 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
323 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
324 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
327 if (list
->viprogid
) {
328 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
329 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
330 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
334 error_close_coclass_key
:
335 RegCloseKey(coclass_key
);
337 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
340 /***********************************************************************
343 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
347 StringFromGUID2(guid
, buf
, 39);
348 return register_key_defvalueW(base
, name
, buf
);
351 /***********************************************************************
352 * regsvr_key_defvalueW
354 static LONG
register_key_defvalueW(
362 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
363 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
364 if (res
!= ERROR_SUCCESS
) return res
;
365 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
366 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
371 /***********************************************************************
372 * regsvr_key_defvalueA
374 static LONG
register_key_defvalueA(
382 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
383 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
384 if (res
!= ERROR_SUCCESS
) return res
;
385 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
386 lstrlenA(value
) + 1);
391 /***********************************************************************
394 static LONG
register_progid(
397 char const *curver_progid
,
404 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
405 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
407 if (res
!= ERROR_SUCCESS
) return res
;
410 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
411 (CONST BYTE
*)name
, strlen(name
) + 1);
412 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
416 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
417 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
421 res
= register_key_defvalueA(progid_key
, curver_keyname
,
423 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
429 res
= RegCreateKeyExA(progid_key
, extra
, 0,
430 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
432 if (res
== ERROR_SUCCESS
)
433 RegCloseKey(extra_key
);
436 error_close_progid_key
:
437 RegCloseKey(progid_key
);
441 /***********************************************************************
444 static struct regsvr_coclass
const coclass_list
[] = {
447 "Multiple AutoComplete List Container",
453 &CLSID_ProgressDialog
,
460 &CLSID_CompCatCacheDaemon
,
461 "Component Catagory Cache Daemon",
468 "Shell Folder AutoComplete List",
473 { NULL
} /* list terminator */
476 /***********************************************************************
480 static struct regsvr_interface
const interface_list
[] = {
481 { NULL
} /* list terminator */
484 /***********************************************************************
485 * DllRegisterServer (HHCTRL.@)
487 HRESULT WINAPI
DllRegisterServer(void)
493 hr
= register_coclasses(coclass_list
);
495 hr
= register_interfaces(interface_list
);
499 /***********************************************************************
500 * DllUnregisterServer (HHCTRL.@)
502 HRESULT WINAPI
DllUnregisterServer(void)
508 hr
= unregister_coclasses(coclass_list
);
510 hr
= unregister_interfaces(interface_list
);