2 * self-registerable dll functions for dsound.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
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
36 * Near the bottom of this file are the exported DllRegisterServer and
37 * DllUnregisterServer, which make all this worthwhile.
40 /***********************************************************************
41 * interface for self-registering
43 struct regsvr_interface
45 IID
const *iid
; /* NULL for end of list */
46 LPCSTR name
; /* can be NULL to omit */
47 IID
const *base_iid
; /* can be NULL to omit */
48 int num_methods
; /* can be <0 to omit */
49 CLSID
const *ps_clsid
; /* can be NULL to omit */
50 CLSID
const *ps_clsid32
; /* can be NULL to omit */
53 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
54 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
58 CLSID
const *clsid
; /* NULL for end of list */
59 LPCSTR name
; /* can be NULL to omit */
60 LPCSTR ips
; /* can be NULL to omit */
61 LPCSTR ips32
; /* can be NULL to omit */
62 LPCSTR ips32_tmodel
; /* can be NULL to omit */
63 LPCSTR progid
; /* can be NULL to omit */
64 LPCSTR viprogid
; /* can be NULL to omit */
65 LPCSTR progid_extra
; /* can be NULL to omit */
68 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
69 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
71 /***********************************************************************
72 * static string constants
74 static WCHAR
const interface_keyname
[10] = {
75 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
76 static WCHAR
const base_ifa_keyname
[14] = {
77 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
79 static WCHAR
const num_methods_keyname
[11] = {
80 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
81 static WCHAR
const ps_clsid_keyname
[15] = {
82 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
84 static WCHAR
const ps_clsid32_keyname
[17] = {
85 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
86 'i', 'd', '3', '2', 0 };
87 static WCHAR
const clsid_keyname
[6] = {
88 'C', 'L', 'S', 'I', 'D', 0 };
89 static WCHAR
const curver_keyname
[7] = {
90 'C', 'u', 'r', 'V', 'e', 'r', 0 };
91 static WCHAR
const ips_keyname
[13] = {
92 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
94 static WCHAR
const ips32_keyname
[15] = {
95 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
97 static WCHAR
const progid_keyname
[7] = {
98 'P', 'r', 'o', 'g', 'I', 'D', 0 };
99 static WCHAR
const viprogid_keyname
[25] = {
100 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
101 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
103 static char const tmodel_valuename
[] = "ThreadingModel";
105 /***********************************************************************
106 * static helper functions
108 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
109 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
111 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
113 static LONG
register_progid(WCHAR
const *clsid
,
114 char const *progid
, char const *curver_progid
,
115 char const *name
, char const *extra
);
116 static LONG
recursive_delete_key(HKEY key
);
117 static LONG
recursive_delete_keyA(HKEY base
, char const *name
);
118 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
);
120 /***********************************************************************
121 * register_interfaces
123 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
125 LONG res
= ERROR_SUCCESS
;
128 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
129 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
130 if (res
!= ERROR_SUCCESS
) goto error_return
;
132 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
136 StringFromGUID2(list
->iid
, buf
, 39);
137 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
138 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
139 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
142 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
143 (CONST BYTE
*)(list
->name
),
144 strlen(list
->name
) + 1);
145 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
148 if (list
->base_iid
) {
149 register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
150 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
153 if (0 <= list
->num_methods
) {
154 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
157 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
158 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
159 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
161 wsprintfW(buf
, fmt
, list
->num_methods
);
162 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
164 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
167 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
170 if (list
->ps_clsid
) {
171 register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
172 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
175 if (list
->ps_clsid32
) {
176 register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
177 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
181 RegCloseKey(iid_key
);
184 error_close_interface_key
:
185 RegCloseKey(interface_key
);
187 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
190 /***********************************************************************
191 * unregister_interfaces
193 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
195 LONG res
= ERROR_SUCCESS
;
198 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
199 KEY_READ
| KEY_WRITE
, &interface_key
);
200 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
201 if (res
!= ERROR_SUCCESS
) goto error_return
;
203 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
206 StringFromGUID2(list
->iid
, buf
, 39);
207 res
= recursive_delete_keyW(interface_key
, buf
);
210 RegCloseKey(interface_key
);
212 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
215 /***********************************************************************
218 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
220 LONG res
= ERROR_SUCCESS
;
223 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
224 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
225 if (res
!= ERROR_SUCCESS
) goto error_return
;
227 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
231 StringFromGUID2(list
->clsid
, buf
, 39);
232 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
233 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
234 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
237 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
238 (CONST BYTE
*)(list
->name
),
239 strlen(list
->name
) + 1);
240 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
244 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
245 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
251 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
252 KEY_READ
| KEY_WRITE
, NULL
,
254 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
256 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
257 (CONST BYTE
*)list
->ips32
,
258 lstrlenA(list
->ips32
) + 1);
259 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
260 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
261 (CONST BYTE
*)list
->ips32_tmodel
,
262 strlen(list
->ips32_tmodel
) + 1);
263 RegCloseKey(ips32_key
);
264 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
268 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
270 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
272 res
= register_progid(buf
, list
->progid
, NULL
,
273 list
->name
, list
->progid_extra
);
274 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
277 if (list
->viprogid
) {
278 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
280 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
282 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
283 list
->name
, list
->progid_extra
);
284 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
287 error_close_clsid_key
:
288 RegCloseKey(clsid_key
);
291 error_close_coclass_key
:
292 RegCloseKey(coclass_key
);
294 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
297 /***********************************************************************
298 * unregister_coclasses
300 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
302 LONG res
= ERROR_SUCCESS
;
305 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
306 KEY_READ
| KEY_WRITE
, &coclass_key
);
307 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
308 if (res
!= ERROR_SUCCESS
) goto error_return
;
310 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
313 StringFromGUID2(list
->clsid
, buf
, 39);
314 res
= recursive_delete_keyW(coclass_key
, buf
);
315 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
318 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->progid
);
319 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
322 if (list
->viprogid
) {
323 res
= recursive_delete_keyA(HKEY_CLASSES_ROOT
, list
->viprogid
);
324 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
328 error_close_coclass_key
:
329 RegCloseKey(coclass_key
);
331 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
334 /***********************************************************************
337 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
341 StringFromGUID2(guid
, buf
, 39);
342 return register_key_defvalueW(base
, name
, buf
);
345 /***********************************************************************
346 * regsvr_key_defvalueW
348 static LONG
register_key_defvalueW(
356 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
357 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
358 if (res
!= ERROR_SUCCESS
) return res
;
359 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
360 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
365 /***********************************************************************
366 * regsvr_key_defvalueA
368 static LONG
register_key_defvalueA(
376 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
377 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
378 if (res
!= ERROR_SUCCESS
) return res
;
379 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
380 lstrlenA(value
) + 1);
385 /***********************************************************************
388 static LONG
register_progid(
391 char const *curver_progid
,
398 res
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, progid
, 0,
399 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
401 if (res
!= ERROR_SUCCESS
) return res
;
404 res
= RegSetValueExA(progid_key
, NULL
, 0, REG_SZ
,
405 (CONST BYTE
*)name
, strlen(name
) + 1);
406 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
410 res
= register_key_defvalueW(progid_key
, clsid_keyname
, clsid
);
411 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
415 res
= register_key_defvalueA(progid_key
, curver_keyname
,
417 if (res
!= ERROR_SUCCESS
) goto error_close_progid_key
;
423 res
= RegCreateKeyExA(progid_key
, extra
, 0,
424 NULL
, 0, KEY_READ
| KEY_WRITE
, NULL
,
426 if (res
== ERROR_SUCCESS
)
427 RegCloseKey(extra_key
);
430 error_close_progid_key
:
431 RegCloseKey(progid_key
);
435 /***********************************************************************
436 * recursive_delete_key
438 static LONG
recursive_delete_key(HKEY key
)
441 WCHAR subkey_name
[MAX_PATH
];
446 cName
= sizeof(subkey_name
) / sizeof(WCHAR
);
447 res
= RegEnumKeyExW(key
, 0, subkey_name
, &cName
,
448 NULL
, NULL
, NULL
, NULL
);
449 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) {
450 res
= ERROR_SUCCESS
; /* presumably we're done enumerating */
453 res
= RegOpenKeyExW(key
, subkey_name
, 0,
454 KEY_READ
| KEY_WRITE
, &subkey
);
455 if (res
== ERROR_FILE_NOT_FOUND
) continue;
456 if (res
!= ERROR_SUCCESS
) break;
458 res
= recursive_delete_key(subkey
);
460 if (res
!= ERROR_SUCCESS
) break;
463 if (res
== ERROR_SUCCESS
) res
= RegDeleteKeyW(key
, 0);
467 /***********************************************************************
468 * recursive_delete_keyA
470 static LONG
recursive_delete_keyA(HKEY base
, char const *name
)
475 res
= RegOpenKeyExA(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
476 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
477 if (res
!= ERROR_SUCCESS
) return res
;
478 res
= recursive_delete_key(key
);
483 /***********************************************************************
484 * recursive_delete_keyW
486 static LONG
recursive_delete_keyW(HKEY base
, WCHAR
const *name
)
491 res
= RegOpenKeyExW(base
, name
, 0, KEY_READ
| KEY_WRITE
, &key
);
492 if (res
== ERROR_FILE_NOT_FOUND
) return ERROR_SUCCESS
;
493 if (res
!= ERROR_SUCCESS
) return res
;
494 res
= recursive_delete_key(key
);
499 /***********************************************************************
502 static GUID
const CLSID_DirectSoundBufferConfig
= {
503 0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
505 static struct regsvr_coclass
const coclass_list
[] = {
506 { &CLSID_DirectSound
,
507 "DirectSound Object",
512 { &CLSID_DirectSound8
,
513 "DirectSound 8.0 Object",
518 { &CLSID_DirectSoundBufferConfig
,
519 "DirectSoundBufferConfig Object",
524 { &CLSID_DirectSoundCapture
,
525 "DirectSoundCapture Object",
530 { &CLSID_DirectSoundCapture8
,
531 "DirectSoundCapture 8.0 Object",
536 { &CLSID_DirectSoundFullDuplex
,
537 "DirectSoundFullDuplex Object",
542 { NULL
} /* list terminator */
545 /***********************************************************************
549 static struct regsvr_interface
const interface_list
[] = {
550 { NULL
} /* list terminator */
553 /***********************************************************************
554 * DllRegisterServer (DSOUND.@)
556 HRESULT WINAPI
DSOUND_DllRegisterServer(void)
562 hr
= register_coclasses(coclass_list
);
564 hr
= register_interfaces(interface_list
);
568 /***********************************************************************
569 * DllUnregisterServer (DSOUND.@)
571 HRESULT WINAPI
DSOUND_DllUnregisterServer(void)
577 hr
= unregister_coclasses(coclass_list
);
579 hr
= unregister_interfaces(interface_list
);