2 * self-registerable dll functions for dmusic.dll
4 * Copyright (C) 2003 John K. Hohm
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
40 * Near the bottom of this file are the exported DllRegisterServer and
41 * DllUnregisterServer, which make all this worthwhile.
44 /***********************************************************************
45 * interface for self-registering
47 struct regsvr_interface
49 IID
const *iid
; /* NULL for end of list */
50 LPCSTR name
; /* can be NULL to omit */
51 IID
const *base_iid
; /* can be NULL to omit */
52 int num_methods
; /* can be <0 to omit */
53 CLSID
const *ps_clsid
; /* can be NULL to omit */
54 CLSID
const *ps_clsid32
; /* can be NULL to omit */
57 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
58 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
62 CLSID
const *clsid
; /* NULL for end of list */
63 LPCSTR name
; /* can be NULL to omit */
64 LPCSTR ips
; /* can be NULL to omit */
65 LPCSTR ips32
; /* can be NULL to omit */
66 LPCSTR ips32_tmodel
; /* can be NULL to omit */
67 LPCSTR progid
; /* can be NULL to omit */
68 LPCSTR viprogid
; /* can be NULL to omit */
69 LPCSTR progid_extra
; /* can be NULL to omit */
72 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
73 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
75 /***********************************************************************
76 * static string constants
78 static WCHAR
const interface_keyname
[10] = {
79 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
80 static WCHAR
const base_ifa_keyname
[14] = {
81 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
83 static WCHAR
const num_methods_keyname
[11] = {
84 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
85 static WCHAR
const ps_clsid_keyname
[15] = {
86 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
88 static WCHAR
const ps_clsid32_keyname
[17] = {
89 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
90 'i', 'd', '3', '2', 0 };
91 static WCHAR
const clsid_keyname
[6] = {
92 'C', 'L', 'S', 'I', 'D', 0 };
93 static WCHAR
const curver_keyname
[7] = {
94 'C', 'u', 'r', 'V', 'e', 'r', 0 };
95 static WCHAR
const ips_keyname
[13] = {
96 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
98 static WCHAR
const ips32_keyname
[15] = {
99 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
101 static WCHAR
const progid_keyname
[7] = {
102 'P', 'r', 'o', 'g', 'I', 'D', 0 };
103 static WCHAR
const viprogid_keyname
[25] = {
104 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
105 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
107 static char const tmodel_valuename
[] = "ThreadingModel";
109 /***********************************************************************
110 * static helper functions
112 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
113 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
115 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
117 static LONG
register_progid(WCHAR
const *clsid
,
118 char const *progid
, char const *curver_progid
,
119 char const *name
, char const *extra
);
120 static LONG
recursive_delete_key(HKEY key
);
121 static LONG
recursive_delete_keyA(HKEY base
, char const *name
);
122 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
);
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 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 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 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
= recursive_delete_keyW(interface_key
, buf
);
214 RegCloseKey(interface_key
);
216 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
219 /***********************************************************************
222 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
224 LONG res
= ERROR_SUCCESS
;
227 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
228 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
229 if (res
!= ERROR_SUCCESS
) goto error_return
;
231 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
235 StringFromGUID2(list
->clsid
, buf
, 39);
236 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
237 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
238 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
241 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
242 (CONST BYTE
*)(list
->name
),
243 strlen(list
->name
) + 1);
244 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
248 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
249 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
255 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
256 KEY_READ
| KEY_WRITE
, NULL
,
258 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
260 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
261 (CONST BYTE
*)list
->ips32
,
262 lstrlenA(list
->ips32
) + 1);
263 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
264 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
265 (CONST BYTE
*)list
->ips32_tmodel
,
266 strlen(list
->ips32_tmodel
) + 1);
267 RegCloseKey(ips32_key
);
268 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
272 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
274 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
276 res
= register_progid(buf
, list
->progid
, NULL
,
277 list
->name
, list
->progid_extra
);
278 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
281 if (list
->viprogid
) {
282 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
284 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
286 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
287 list
->name
, list
->progid_extra
);
288 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
291 error_close_clsid_key
:
292 RegCloseKey(clsid_key
);
295 error_close_coclass_key
:
296 RegCloseKey(coclass_key
);
298 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
301 /***********************************************************************
302 * unregister_coclasses
304 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
306 LONG res
= ERROR_SUCCESS
;
309 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
310 KEY_READ
| KEY_WRITE
, &coclass_key
);
311 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
312 if (res
!= ERROR_SUCCESS
) goto error_return
;
314 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
317 StringFromGUID2(list
->clsid
, buf
, 39);
318 res
= recursive_delete_keyW(coclass_key
, buf
);
319 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
322 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->progid
);
323 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
326 if (list
->viprogid
) {
327 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->viprogid
);
328 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
332 error_close_coclass_key
:
333 RegCloseKey(coclass_key
);
335 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
338 /***********************************************************************
341 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
345 StringFromGUID2(guid
, buf
, 39);
346 return register_key_defvalueW(base
, name
, buf
);
349 /***********************************************************************
350 * regsvr_key_defvalueW
352 static LONG
register_key_defvalueW(
360 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
361 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
362 if (res
!= ERROR_SUCCESS
) return res
;
363 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
364 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
369 /***********************************************************************
370 * regsvr_key_defvalueA
372 static LONG
register_key_defvalueA(
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
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
384 lstrlenA(value
) + 1);
389 /***********************************************************************
392 static LONG
register_progid(
395 char const *curver_progid
,
402 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
403 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
405 if (res
!= ERROR_SUCCESS
) return res
;
408 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
409 (CONST BYTE
*)name
, strlen(name
) + 1);
410 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
414 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
415 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
419 res
= register_key_defvalueA(progid_key
, curver_keyname
,
421 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
427 res
= RegCreateKeyExA(progid_key
, extra
, 0,
428 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
430 if (res
== ERROR_SUCCESS
)
431 RegCloseKey(extra_key
);
434 error_close_progid_key
:
435 RegCloseKey(progid_key
);
439 /***********************************************************************
440 * recursive_delete_key
442 static LONG
recursive_delete_key(HKEY key
)
445 WCHAR subkey_name
[MAX_PATH
];
450 cName
= sizeof(subkey_name
) / sizeof(WCHAR
);
451 res
= RegEnumKeyExW(key
, 0, subkey_name
, &cName
,
452 NULL
, NULL
, NULL
, NULL
);
453 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) {
454 res
= ERROR_SUCCESS
; /* presumably we're done enumerating */
457 res
= RegOpenKeyExW(key
, subkey_name
, 0,
458 KEY_READ
| KEY_WRITE
, &subkey
);
459 if (res
== ERROR_FILE_NOT_FOUND
) continue;
460 if (res
!= ERROR_SUCCESS
) break;
462 res
= recursive_delete_key(subkey
);
464 if (res
!= ERROR_SUCCESS
) break;
467 if (res
== ERROR_SUCCESS
) res
= RegDeleteKeyW(key
, 0);
471 /***********************************************************************
472 * recursive_delete_keyA
474 static LONG
recursive_delete_keyA(HKEY base
, char const *name
)
479 res
= RegOpenKeyExA(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
480 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
481 if (res
!= ERROR_SUCCESS
) return res
;
482 res
= recursive_delete_key(key
);
487 /***********************************************************************
488 * recursive_delete_keyW
490 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
)
495 res
= RegOpenKeyExW(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
496 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
497 if (res
!= ERROR_SUCCESS
) return res
;
498 res
= recursive_delete_key(key
);
503 /***********************************************************************
506 static struct regsvr_coclass
const coclass_list
[] = {
507 { &CLSID_DirectMusic
,
512 "Microsoft.DirectMusic.1",
513 "Microsoft.DirectMusic"
515 { &CLSID_DirectMusicCollection
,
516 "DirectMusicCollection",
520 "Microsoft.DirectMusicCollection.1",
521 "Microsoft.DirectMusicCollection"
523 { NULL
} /* list terminator */
526 /***********************************************************************
530 static struct regsvr_interface
const interface_list
[] = {
531 { NULL
} /* list terminator */
534 /***********************************************************************
535 * DllRegisterServer (DMUSIC.3)
537 HRESULT WINAPI
DMUSIC_DllRegisterServer(void)
543 hr
= register_coclasses(coclass_list
);
545 hr
= register_interfaces(interface_list
);
549 /***********************************************************************
550 * DllUnregisterServer (DMUSIC.4)
552 HRESULT WINAPI
DMUSIC_DllUnregisterServer(void)
558 hr
= unregister_coclasses(coclass_list
);
560 hr
= unregister_interfaces(interface_list
);