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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
47 #include "dsound_private.h"
53 static LSTATUS (WINAPI
*pRegDeleteTreeW
)(HKEY
,LPCWSTR
);
54 static LSTATUS (WINAPI
*pRegDeleteTreeA
)(HKEY
,LPCSTR
);
57 * Near the bottom of this file are the exported DllRegisterServer and
58 * DllUnregisterServer, which make all this worthwhile.
61 /***********************************************************************
62 * interface for self-registering
64 struct regsvr_interface
66 IID
const *iid
; /* NULL for end of list */
67 LPCSTR name
; /* can be NULL to omit */
68 IID
const *base_iid
; /* can be NULL to omit */
69 int num_methods
; /* can be <0 to omit */
70 CLSID
const *ps_clsid
; /* can be NULL to omit */
71 CLSID
const *ps_clsid32
; /* can be NULL to omit */
74 static HRESULT
register_interfaces(struct regsvr_interface
const *list
);
75 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
);
79 CLSID
const *clsid
; /* NULL for end of list */
80 LPCSTR name
; /* can be NULL to omit */
81 LPCSTR ips
; /* can be NULL to omit */
82 LPCSTR ips32
; /* can be NULL to omit */
83 LPCSTR ips32_tmodel
; /* can be NULL to omit */
84 LPCSTR progid
; /* can be NULL to omit */
85 LPCSTR viprogid
; /* can be NULL to omit */
86 LPCSTR progid_extra
; /* can be NULL to omit */
89 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
);
90 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
);
92 /***********************************************************************
93 * static string constants
95 static WCHAR
const interface_keyname
[10] = {
96 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
97 static WCHAR
const base_ifa_keyname
[14] = {
98 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
100 static WCHAR
const num_methods_keyname
[11] = {
101 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
102 static WCHAR
const ps_clsid_keyname
[15] = {
103 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
105 static WCHAR
const ps_clsid32_keyname
[17] = {
106 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
107 'i', 'd', '3', '2', 0 };
108 static WCHAR
const clsid_keyname
[6] = {
109 'C', 'L', 'S', 'I', 'D', 0 };
110 static WCHAR
const curver_keyname
[7] = {
111 'C', 'u', 'r', 'V', 'e', 'r', 0 };
112 static WCHAR
const ips_keyname
[13] = {
113 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
115 static WCHAR
const ips32_keyname
[15] = {
116 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
118 static WCHAR
const progid_keyname
[7] = {
119 'P', 'r', 'o', 'g', 'I', 'D', 0 };
120 static WCHAR
const viprogid_keyname
[25] = {
121 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
122 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
124 static char const tmodel_valuename
[] = "ThreadingModel";
126 /***********************************************************************
127 * static helper functions
129 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
);
130 static LONG
register_key_defvalueW(HKEY base
, WCHAR
const *name
,
132 static LONG
register_key_defvalueA(HKEY base
, WCHAR
const *name
,
134 static LONG
register_progid(WCHAR
const *clsid
,
135 char const *progid
, char const *curver_progid
,
136 char const *name
, char const *extra
);
138 /***********************************************************************
139 * register_interfaces
141 static HRESULT
register_interfaces(struct regsvr_interface
const *list
)
143 LONG res
= ERROR_SUCCESS
;
146 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0, NULL
, 0,
147 KEY_READ
| KEY_WRITE
, NULL
, &interface_key
, NULL
);
148 if (res
!= ERROR_SUCCESS
) goto error_return
;
150 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
154 StringFromGUID2(list
->iid
, buf
, 39);
155 res
= RegCreateKeyExW(interface_key
, buf
, 0, NULL
, 0,
156 KEY_READ
| KEY_WRITE
, NULL
, &iid_key
, NULL
);
157 if (res
!= ERROR_SUCCESS
) goto error_close_interface_key
;
160 res
= RegSetValueExA(iid_key
, NULL
, 0, REG_SZ
,
161 (CONST BYTE
*)(list
->name
),
162 strlen(list
->name
) + 1);
163 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
166 if (list
->base_iid
) {
167 res
= register_key_guid(iid_key
, base_ifa_keyname
, list
->base_iid
);
168 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
171 if (0 <= list
->num_methods
) {
172 static WCHAR
const fmt
[3] = { '%', 'd', 0 };
175 res
= RegCreateKeyExW(iid_key
, num_methods_keyname
, 0, NULL
, 0,
176 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
177 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
179 wsprintfW(buf
, fmt
, list
->num_methods
);
180 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
,
182 (lstrlenW(buf
) + 1) * sizeof(WCHAR
));
185 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
188 if (list
->ps_clsid
) {
189 res
= register_key_guid(iid_key
, ps_clsid_keyname
, list
->ps_clsid
);
190 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
193 if (list
->ps_clsid32
) {
194 res
= register_key_guid(iid_key
, ps_clsid32_keyname
, list
->ps_clsid32
);
195 if (res
!= ERROR_SUCCESS
) goto error_close_iid_key
;
199 RegCloseKey(iid_key
);
202 error_close_interface_key
:
203 RegCloseKey(interface_key
);
205 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
208 /***********************************************************************
209 * unregister_interfaces
211 static HRESULT
unregister_interfaces(struct regsvr_interface
const *list
)
213 LONG res
= ERROR_SUCCESS
;
216 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, interface_keyname
, 0,
217 KEY_READ
| KEY_WRITE
, &interface_key
);
218 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
219 if (res
!= ERROR_SUCCESS
) goto error_return
;
221 for (; res
== ERROR_SUCCESS
&& list
->iid
; ++list
) {
224 StringFromGUID2(list
->iid
, buf
, 39);
225 res
= pRegDeleteTreeW(interface_key
, buf
);
226 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
229 RegCloseKey(interface_key
);
231 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
234 /***********************************************************************
237 static HRESULT
register_coclasses(struct regsvr_coclass
const *list
)
239 LONG res
= ERROR_SUCCESS
;
242 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0, NULL
, 0,
243 KEY_READ
| KEY_WRITE
, NULL
, &coclass_key
, NULL
);
244 if (res
!= ERROR_SUCCESS
) goto error_return
;
246 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
250 StringFromGUID2(list
->clsid
, buf
, 39);
251 res
= RegCreateKeyExW(coclass_key
, buf
, 0, NULL
, 0,
252 KEY_READ
| KEY_WRITE
, NULL
, &clsid_key
, NULL
);
253 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
256 res
= RegSetValueExA(clsid_key
, NULL
, 0, REG_SZ
,
257 (CONST BYTE
*)(list
->name
),
258 strlen(list
->name
) + 1);
259 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
263 res
= register_key_defvalueA(clsid_key
, ips_keyname
, list
->ips
);
264 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
270 res
= RegCreateKeyExW(clsid_key
, ips32_keyname
, 0, NULL
, 0,
271 KEY_READ
| KEY_WRITE
, NULL
,
273 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
275 res
= RegSetValueExA(ips32_key
, NULL
, 0, REG_SZ
,
276 (CONST BYTE
*)list
->ips32
,
277 lstrlenA(list
->ips32
) + 1);
278 if (res
== ERROR_SUCCESS
&& list
->ips32_tmodel
)
279 res
= RegSetValueExA(ips32_key
, tmodel_valuename
, 0, REG_SZ
,
280 (CONST BYTE
*)list
->ips32_tmodel
,
281 strlen(list
->ips32_tmodel
) + 1);
282 RegCloseKey(ips32_key
);
283 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
287 res
= register_key_defvalueA(clsid_key
, progid_keyname
,
289 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
291 res
= register_progid(buf
, list
->progid
, NULL
,
292 list
->name
, list
->progid_extra
);
293 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
296 if (list
->viprogid
) {
297 res
= register_key_defvalueA(clsid_key
, viprogid_keyname
,
299 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
301 res
= register_progid(buf
, list
->viprogid
, list
->progid
,
302 list
->name
, list
->progid_extra
);
303 if (res
!= ERROR_SUCCESS
) goto error_close_clsid_key
;
306 error_close_clsid_key
:
307 RegCloseKey(clsid_key
);
310 error_close_coclass_key
:
311 RegCloseKey(coclass_key
);
313 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
316 /***********************************************************************
317 * unregister_coclasses
319 static HRESULT
unregister_coclasses(struct regsvr_coclass
const *list
)
321 LONG res
= ERROR_SUCCESS
;
324 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, clsid_keyname
, 0,
325 KEY_READ
| KEY_WRITE
, &coclass_key
);
326 if (res
== ERROR_FILE_NOT_FOUND
) return S_OK
;
327 if (res
!= ERROR_SUCCESS
) goto error_return
;
329 for (; res
== ERROR_SUCCESS
&& list
->clsid
; ++list
) {
332 StringFromGUID2(list
->clsid
, buf
, 39);
333 res
= pRegDeleteTreeW(coclass_key
, buf
);
334 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
335 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
338 res
= pRegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->progid
);
339 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
340 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
343 if (list
->viprogid
) {
344 res
= pRegDeleteTreeA(HKEY_CLASSES_ROOT
, list
->viprogid
);
345 if (res
== ERROR_FILE_NOT_FOUND
) res
= ERROR_SUCCESS
;
346 if (res
!= ERROR_SUCCESS
) goto error_close_coclass_key
;
350 error_close_coclass_key
:
351 RegCloseKey(coclass_key
);
353 return res
!= ERROR_SUCCESS
? HRESULT_FROM_WIN32(res
) : S_OK
;
356 /***********************************************************************
359 static LONG
register_key_guid(HKEY base
, WCHAR
const *name
, GUID
const *guid
)
363 StringFromGUID2(guid
, buf
, 39);
364 return register_key_defvalueW(base
, name
, buf
);
367 /***********************************************************************
368 * regsvr_key_defvalueW
370 static LONG
register_key_defvalueW(
378 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
379 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
380 if (res
!= ERROR_SUCCESS
) return res
;
381 res
= RegSetValueExW(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
382 (lstrlenW(value
) + 1) * sizeof(WCHAR
));
387 /***********************************************************************
388 * regsvr_key_defvalueA
390 static LONG
register_key_defvalueA(
398 res
= RegCreateKeyExW(base
, name
, 0, NULL
, 0,
399 KEY_READ
| KEY_WRITE
, NULL
, &key
, NULL
);
400 if (res
!= ERROR_SUCCESS
) return res
;
401 res
= RegSetValueExA(key
, NULL
, 0, REG_SZ
, (CONST BYTE
*)value
,
402 lstrlenA(value
) + 1);
407 /***********************************************************************
410 static LONG
register_progid(
413 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 GUID
const CLSID_DirectSoundBufferConfig
= {
461 0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
463 static struct regsvr_coclass
const coclass_list
[] = {
464 { &CLSID_DirectSound
,
465 "DirectSound Object",
470 { &CLSID_DirectSound8
,
471 "DirectSound 8.0 Object",
476 { &CLSID_DirectSoundBufferConfig
,
477 "DirectSoundBufferConfig Object",
482 { &CLSID_DirectSoundCapture
,
483 "DirectSoundCapture Object",
488 { &CLSID_DirectSoundCapture8
,
489 "DirectSoundCapture 8.0 Object",
494 { &CLSID_DirectSoundFullDuplex
,
495 "DirectSoundFullDuplex Object",
500 { NULL
} /* list terminator */
503 /***********************************************************************
507 static struct regsvr_interface
const interface_list
[] = {
508 { NULL
} /* list terminator */
511 /***********************************************************************
512 * DllRegisterServer (DSOUND.@)
514 HRESULT WINAPI
DllRegisterServer(void)
520 hr
= register_coclasses(coclass_list
);
522 hr
= register_interfaces(interface_list
);
526 /***********************************************************************
527 * DllUnregisterServer (DSOUND.@)
529 HRESULT WINAPI
DllUnregisterServer(void)
533 HMODULE advapi32
= GetModuleHandleA("advapi32");
534 if (!advapi32
) return E_FAIL
;
535 pRegDeleteTreeA
= (void *) GetProcAddress(advapi32
, "RegDeleteTreeA");
536 pRegDeleteTreeW
= (void *) GetProcAddress(advapi32
, "RegDeleteTreeW");
537 if (!pRegDeleteTreeA
|| !pRegDeleteTreeW
) return E_FAIL
;
541 hr
= unregister_coclasses(coclass_list
);
543 hr
= unregister_interfaces(interface_list
);