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
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
39 * Near the bottom of this file are the exported DllRegisterServer and
40 * DllUnregisterServer, which make all this worthwhile.
43 /***********************************************************************
44 * interface for self-registering
46 struct regsvr_interface
48 IID const *iid; /* NULL for end of list */
49 LPCSTR name; /* can be NULL to omit */
50 IID const *base_iid; /* can be NULL to omit */
51 int num_methods; /* can be <0 to omit */
52 CLSID const *ps_clsid; /* can be NULL to omit */
53 CLSID const *ps_clsid32; /* can be NULL to omit */
56 static HRESULT register_interfaces(struct regsvr_interface const *list);
57 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
61 CLSID const *clsid; /* NULL for end of list */
62 LPCSTR name; /* can be NULL to omit */
63 LPCSTR ips; /* can be NULL to omit */
64 LPCSTR ips32; /* can be NULL to omit */
65 LPCSTR ips32_tmodel; /* can be NULL to omit */
66 LPCSTR progid; /* can be NULL to omit */
67 LPCSTR viprogid; /* can be NULL to omit */
68 LPCSTR progid_extra; /* can be NULL to omit */
71 static HRESULT register_coclasses(struct regsvr_coclass const *list);
72 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
74 /***********************************************************************
75 * static string constants
77 static WCHAR const interface_keyname[10] = {
78 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
79 static WCHAR const base_ifa_keyname[14] = {
80 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
82 static WCHAR const num_methods_keyname[11] = {
83 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
84 static WCHAR const ps_clsid_keyname[15] = {
85 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
87 static WCHAR const ps_clsid32_keyname[17] = {
88 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
89 'i', 'd', '3', '2', 0 };
90 static WCHAR const clsid_keyname[6] = {
91 'C', 'L', 'S', 'I', 'D', 0 };
92 static WCHAR const curver_keyname[7] = {
93 'C', 'u', 'r', 'V', 'e', 'r', 0 };
94 static WCHAR const ips_keyname[13] = {
95 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
97 static WCHAR const ips32_keyname[15] = {
98 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
100 static WCHAR const progid_keyname[7] = {
101 'P', 'r', 'o', 'g', 'I', 'D', 0 };
102 static WCHAR const viprogid_keyname[25] = {
103 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
104 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
106 static char const tmodel_valuename[] = "ThreadingModel";
108 /***********************************************************************
109 * static helper functions
111 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
112 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
114 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
116 static LONG register_progid(WCHAR const *clsid,
117 char const *progid, char const *curver_progid,
118 char const *name, char const *extra);
119 static LONG recursive_delete_key(HKEY key);
120 static LONG recursive_delete_keyA(HKEY base, char const *name);
121 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
123 /***********************************************************************
124 * register_interfaces
126 static HRESULT register_interfaces(struct regsvr_interface const *list)
128 LONG res = ERROR_SUCCESS;
131 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
132 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
133 if (res != ERROR_SUCCESS) goto error_return;
135 for (; res == ERROR_SUCCESS && list->iid; ++list) {
139 StringFromGUID2(list->iid, buf, 39);
140 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
141 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
142 if (res != ERROR_SUCCESS) goto error_close_interface_key;
145 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
146 (CONST BYTE*)(list->name),
147 strlen(list->name) + 1);
148 if (res != ERROR_SUCCESS) goto error_close_iid_key;
151 if (list->base_iid) {
152 register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
153 if (res != ERROR_SUCCESS) goto error_close_iid_key;
156 if (0 <= list->num_methods) {
157 static WCHAR const fmt[3] = { '%', 'd', 0 };
160 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
161 KEY_READ | KEY_WRITE, NULL, &key, NULL);
162 if (res != ERROR_SUCCESS) goto error_close_iid_key;
164 wsprintfW(buf, fmt, list->num_methods);
165 res = RegSetValueExW(key, NULL, 0, REG_SZ,
167 (lstrlenW(buf) + 1) * sizeof(WCHAR));
170 if (res != ERROR_SUCCESS) goto error_close_iid_key;
173 if (list->ps_clsid) {
174 register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
175 if (res != ERROR_SUCCESS) goto error_close_iid_key;
178 if (list->ps_clsid32) {
179 register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
180 if (res != ERROR_SUCCESS) goto error_close_iid_key;
184 RegCloseKey(iid_key);
187 error_close_interface_key:
188 RegCloseKey(interface_key);
190 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
193 /***********************************************************************
194 * unregister_interfaces
196 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
198 LONG res = ERROR_SUCCESS;
201 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
202 KEY_READ | KEY_WRITE, &interface_key);
203 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
204 if (res != ERROR_SUCCESS) goto error_return;
206 for (; res == ERROR_SUCCESS && list->iid; ++list) {
209 StringFromGUID2(list->iid, buf, 39);
210 res = recursive_delete_keyW(interface_key, buf);
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 = recursive_delete_keyW(coclass_key, buf);
318 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
321 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
322 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
325 if (list->viprogid) {
326 res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
327 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
331 error_close_coclass_key:
332 RegCloseKey(coclass_key);
334 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
337 /***********************************************************************
340 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
344 StringFromGUID2(guid, buf, 39);
345 return register_key_defvalueW(base, name, buf);
348 /***********************************************************************
349 * regsvr_key_defvalueW
351 static LONG register_key_defvalueW(
359 res = RegCreateKeyExW(base, name, 0, NULL, 0,
360 KEY_READ | KEY_WRITE, NULL, &key, NULL);
361 if (res != ERROR_SUCCESS) return res;
362 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
363 (lstrlenW(value) + 1) * sizeof(WCHAR));
368 /***********************************************************************
369 * regsvr_key_defvalueA
371 static LONG register_key_defvalueA(
379 res = RegCreateKeyExW(base, name, 0, NULL, 0,
380 KEY_READ | KEY_WRITE, NULL, &key, NULL);
381 if (res != ERROR_SUCCESS) return res;
382 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
383 lstrlenA(value) + 1);
388 /***********************************************************************
391 static LONG register_progid(
394 char const *curver_progid,
401 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
402 NULL, 0, KEY_READ | KEY_WRITE, NULL,
404 if (res != ERROR_SUCCESS) return res;
407 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
408 (CONST BYTE*)name, strlen(name) + 1);
409 if (res != ERROR_SUCCESS) goto error_close_progid_key;
413 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
414 if (res != ERROR_SUCCESS) goto error_close_progid_key;
418 res = register_key_defvalueA(progid_key, curver_keyname,
420 if (res != ERROR_SUCCESS) goto error_close_progid_key;
426 res = RegCreateKeyExA(progid_key, extra, 0,
427 NULL, 0, KEY_READ | KEY_WRITE, NULL,
429 if (res == ERROR_SUCCESS)
430 RegCloseKey(extra_key);
433 error_close_progid_key:
434 RegCloseKey(progid_key);
438 /***********************************************************************
439 * recursive_delete_key
441 static LONG recursive_delete_key(HKEY key)
444 WCHAR subkey_name[MAX_PATH];
449 cName = sizeof(subkey_name) / sizeof(WCHAR);
450 res = RegEnumKeyExW(key, 0, subkey_name, &cName,
451 NULL, NULL, NULL, NULL);
452 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
453 res = ERROR_SUCCESS; /* presumably we're done enumerating */
456 res = RegOpenKeyExW(key, subkey_name, 0,
457 KEY_READ | KEY_WRITE, &subkey);
458 if (res == ERROR_FILE_NOT_FOUND) continue;
459 if (res != ERROR_SUCCESS) break;
461 res = recursive_delete_key(subkey);
463 if (res != ERROR_SUCCESS) break;
466 if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
470 /***********************************************************************
471 * recursive_delete_keyA
473 static LONG recursive_delete_keyA(HKEY base, char const *name)
478 res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
479 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
480 if (res != ERROR_SUCCESS) return res;
481 res = recursive_delete_key(key);
486 /***********************************************************************
487 * recursive_delete_keyW
489 static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
494 res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
495 if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
496 if (res != ERROR_SUCCESS) return res;
497 res = recursive_delete_key(key);
502 /***********************************************************************
505 static GUID const CLSID_DirectSoundBufferConfig = {
506 0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
508 static struct regsvr_coclass const coclass_list[] = {
509 { &CLSID_DirectSound,
510 "DirectSound Object",
515 { &CLSID_DirectSound8,
516 "DirectSound 8.0 Object",
521 { &CLSID_DirectSoundBufferConfig,
522 "DirectSoundBufferConfig Object",
527 { &CLSID_DirectSoundCapture,
528 "DirectSoundCapture Object",
533 { &CLSID_DirectSoundCapture8,
534 "DirectSoundCapture 8.0 Object",
539 { &CLSID_DirectSoundFullDuplex,
540 "DirectSoundFullDuplex Object",
545 { NULL } /* list terminator */
548 /***********************************************************************
552 static struct regsvr_interface const interface_list[] = {
553 { NULL } /* list terminator */
556 /***********************************************************************
557 * DllRegisterServer (DSOUND.@)
559 HRESULT WINAPI DSOUND_DllRegisterServer(void)
565 hr = register_coclasses(coclass_list);
567 hr = register_interfaces(interface_list);
571 /***********************************************************************
572 * DllUnregisterServer (DSOUND.@)
574 HRESULT WINAPI DSOUND_DllUnregisterServer(void)
580 hr = unregister_coclasses(coclass_list);
582 hr = unregister_interfaces(interface_list);