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
);
124 /***********************************************************************
125 * register_interfaces
127 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
129 LONG res
= ERROR_SUCCESS
;
132 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
133 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
134 if (res
!= ERROR_SUCCESS
) goto error_return
;
136 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
140 StringFromGUID2(list
->iid
, buf
, 39);
141 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
142 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
143 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
146 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
147 (CONST BYTE
*)(list
->name
),
148 strlen(list
->name
) + 1);
149 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
152 if (list
->base_iid
) {
153 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
154 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
157 if (0 <= list
->num_methods
) {
158 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
161 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
162 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
163 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
165 wsprintfW(buf
, fmt
, list
->num_methods
);
166 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
168 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
171 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
174 if (list
->ps_clsid
) {
175 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
176 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
179 if (list
->ps_clsid32
) {
180 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
181 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
185 RegCloseKey(iid_key
);
188 error_close_interface_key
:
189 RegCloseKey(interface_key
);
191 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
194 /***********************************************************************
195 * unregister_interfaces
197 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
199 LONG res
= ERROR_SUCCESS
;
202 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
203 KEY_READ
| KEY_WRITE
, &interface_key
);
204 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
205 if (res
!= ERROR_SUCCESS
) goto error_return
;
207 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
210 StringFromGUID2(list
->iid
, buf
, 39);
211 res
= RegDeleteTreeW(interface_key
, buf
);
212 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
215 RegCloseKey(interface_key
);
217 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
220 /***********************************************************************
223 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
225 LONG res
= ERROR_SUCCESS
;
228 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
229 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
230 if (res
!= ERROR_SUCCESS
) goto error_return
;
232 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
236 StringFromGUID2(list
->clsid
, buf
, 39);
237 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
238 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
239 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
242 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
243 (CONST BYTE
*)(list
->name
),
244 strlen(list
->name
) + 1);
245 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
249 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
250 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
256 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
257 KEY_READ
| KEY_WRITE
, NULL
,
259 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
261 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
262 (CONST BYTE
*)list
->ips32
,
263 lstrlenA(list
->ips32
) + 1);
264 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
265 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
266 (CONST BYTE
*)list
->ips32_tmodel
,
267 strlen(list
->ips32_tmodel
) + 1);
268 RegCloseKey(ips32_key
);
269 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
273 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
275 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
277 res
= register_progid(buf
, list
->progid
, NULL
,
278 list
->name
, list
->progid_extra
);
279 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
282 if (list
->viprogid
) {
283 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
285 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
287 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
288 list
->name
, list
->progid_extra
);
289 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
292 error_close_clsid_key
:
293 RegCloseKey(clsid_key
);
296 error_close_coclass_key
:
297 RegCloseKey(coclass_key
);
299 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
302 /***********************************************************************
303 * unregister_coclasses
305 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
307 LONG res
= ERROR_SUCCESS
;
310 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
311 KEY_READ
| KEY_WRITE
, &coclass_key
);
312 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
313 if (res
!= ERROR_SUCCESS
) goto error_return
;
315 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
318 StringFromGUID2(list
->clsid
, buf
, 39);
319 res
= RegDeleteTreeW(coclass_key
, buf
);
320 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
321 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
324 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
325 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
326 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
329 if (list
->viprogid
) {
330 res
= RegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
331 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
332 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
336 error_close_coclass_key
:
337 RegCloseKey(coclass_key
);
339 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
342 /***********************************************************************
345 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
349 StringFromGUID2(guid
, buf
, 39);
350 return register_key_defvalueW(base
, name
, buf
);
353 /***********************************************************************
354 * regsvr_key_defvalueW
356 static LONG
register_key_defvalueW(
364 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
365 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
366 if (res
!= ERROR_SUCCESS
) return res
;
367 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
368 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
373 /***********************************************************************
374 * regsvr_key_defvalueA
376 static LONG
register_key_defvalueA(
384 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
385 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
386 if (res
!= ERROR_SUCCESS
) return res
;
387 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
388 lstrlenA(value
) + 1);
393 /***********************************************************************
396 static LONG
register_progid(
399 char const *curver_progid
,
406 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
407 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
409 if (res
!= ERROR_SUCCESS
) return res
;
412 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
413 (CONST BYTE
*)name
, strlen(name
) + 1);
414 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
418 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
419 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
423 res
= register_key_defvalueA(progid_key
, curver_keyname
,
425 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
431 res
= RegCreateKeyExA(progid_key
, extra
, 0,
432 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
434 if (res
== ERROR_SUCCESS
)
435 RegCloseKey(extra_key
);
438 error_close_progid_key
:
439 RegCloseKey(progid_key
);
443 /***********************************************************************
446 static struct regsvr_coclass
const coclass_list
[] = {
448 &CLSID_ActiveSetupEng
,
449 "Microsoft Active Setup Engine",
456 "Download Site Manager",
461 { NULL
} /* list terminator */
464 /***********************************************************************
468 static struct regsvr_interface
const interface_list
[] = {
469 { NULL
} /* list terminator */
472 /***********************************************************************
473 * DllRegisterServer (INSENG.@)
475 HRESULT WINAPI
DllRegisterServer(void)
481 hr
= register_coclasses(coclass_list
);
483 hr
= register_interfaces(interface_list
);
487 /***********************************************************************
488 * DllUnregisterServer (INSENG.@)
490 HRESULT WINAPI
DllUnregisterServer(void)
496 hr
= unregister_coclasses(coclass_list
);
498 hr
= unregister_interfaces(interface_list
);