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
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
38 static LSTATUS (WINAPI *pRegDeleteTreeW)(HKEY,LPCWSTR);
39 static LSTATUS (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR);
42 * Near the bottom of this file are the exported DllRegisterServer and
43 * DllUnregisterServer, which make all this worthwhile.
46 /***********************************************************************
47 * interface for self-registering
49 struct regsvr_interface
51 IID const *iid; /* NULL for end of list */
52 LPCSTR name; /* can be NULL to omit */
53 IID const *base_iid; /* can be NULL to omit */
54 int num_methods; /* can be <0 to omit */
55 CLSID const *ps_clsid; /* can be NULL to omit */
56 CLSID const *ps_clsid32; /* can be NULL to omit */
59 static HRESULT register_interfaces(struct regsvr_interface const *list);
60 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
64 CLSID const *clsid; /* NULL for end of list */
65 LPCSTR name; /* can be NULL to omit */
66 LPCSTR ips; /* can be NULL to omit */
67 LPCSTR ips32; /* can be NULL to omit */
68 LPCSTR ips32_tmodel; /* can be NULL to omit */
69 LPCSTR progid; /* can be NULL to omit */
70 LPCSTR viprogid; /* can be NULL to omit */
71 LPCSTR progid_extra; /* can be NULL to omit */
74 static HRESULT register_coclasses(struct regsvr_coclass const *list);
75 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
77 /***********************************************************************
78 * static string constants
80 static WCHAR const interface_keyname[10] = {
81 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
82 static WCHAR const base_ifa_keyname[14] = {
83 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
85 static WCHAR const num_methods_keyname[11] = {
86 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
87 static WCHAR const ps_clsid_keyname[15] = {
88 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
90 static WCHAR const ps_clsid32_keyname[17] = {
91 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
92 'i', 'd', '3', '2', 0 };
93 static WCHAR const clsid_keyname[6] = {
94 'C', 'L', 'S', 'I', 'D', 0 };
95 static WCHAR const curver_keyname[7] = {
96 'C', 'u', 'r', 'V', 'e', 'r', 0 };
97 static WCHAR const ips_keyname[13] = {
98 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
100 static WCHAR const ips32_keyname[15] = {
101 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
103 static WCHAR const progid_keyname[7] = {
104 'P', 'r', 'o', 'g', 'I', 'D', 0 };
105 static WCHAR const viprogid_keyname[25] = {
106 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
107 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
109 static char const tmodel_valuename[] = "ThreadingModel";
111 /***********************************************************************
112 * static helper functions
114 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
115 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
117 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
119 static LONG register_progid(WCHAR const *clsid,
120 char const *progid, char const *curver_progid,
121 char const *name, char const *extra);
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 res = 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 sprintfW(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 res = 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 res = 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 = pRegDeleteTreeW(interface_key, buf);
211 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
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 = pRegDeleteTreeW(coclass_key, buf);
319 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
320 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
323 res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
324 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
325 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
328 if (list->viprogid) {
329 res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
330 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
331 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
335 error_close_coclass_key:
336 RegCloseKey(coclass_key);
338 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
341 /***********************************************************************
344 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
348 StringFromGUID2(guid, buf, 39);
349 return register_key_defvalueW(base, name, buf);
352 /***********************************************************************
353 * regsvr_key_defvalueW
355 static LONG register_key_defvalueW(
363 res = RegCreateKeyExW(base, name, 0, NULL, 0,
364 KEY_READ | KEY_WRITE, NULL, &key, NULL);
365 if (res != ERROR_SUCCESS) return res;
366 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
367 (lstrlenW(value) + 1) * sizeof(WCHAR));
372 /***********************************************************************
373 * regsvr_key_defvalueA
375 static LONG register_key_defvalueA(
383 res = RegCreateKeyExW(base, name, 0, NULL, 0,
384 KEY_READ | KEY_WRITE, NULL, &key, NULL);
385 if (res != ERROR_SUCCESS) return res;
386 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
387 lstrlenA(value) + 1);
392 /***********************************************************************
395 static LONG register_progid(
398 char const *curver_progid,
405 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
406 NULL, 0, KEY_READ | KEY_WRITE, NULL,
408 if (res != ERROR_SUCCESS) return res;
411 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
412 (CONST BYTE*)name, strlen(name) + 1);
413 if (res != ERROR_SUCCESS) goto error_close_progid_key;
417 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
418 if (res != ERROR_SUCCESS) goto error_close_progid_key;
422 res = register_key_defvalueA(progid_key, curver_keyname,
424 if (res != ERROR_SUCCESS) goto error_close_progid_key;
430 res = RegCreateKeyExA(progid_key, extra, 0,
431 NULL, 0, KEY_READ | KEY_WRITE, NULL,
433 if (res == ERROR_SUCCESS)
434 RegCloseKey(extra_key);
437 error_close_progid_key:
438 RegCloseKey(progid_key);
442 /***********************************************************************
445 static GUID const CLSID_DirectSoundBufferConfig = {
446 0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
448 static struct regsvr_coclass const coclass_list[] = {
449 { &CLSID_DirectSound,
450 "DirectSound Object",
455 { &CLSID_DirectSound8,
456 "DirectSound 8.0 Object",
461 { &CLSID_DirectSoundBufferConfig,
462 "DirectSoundBufferConfig Object",
467 { &CLSID_DirectSoundCapture,
468 "DirectSoundCapture Object",
473 { &CLSID_DirectSoundCapture8,
474 "DirectSoundCapture 8.0 Object",
479 { &CLSID_DirectSoundFullDuplex,
480 "DirectSoundFullDuplex Object",
485 { NULL } /* list terminator */
488 /***********************************************************************
492 static struct regsvr_interface const interface_list[] = {
493 { NULL } /* list terminator */
496 /***********************************************************************
497 * DllRegisterServer (DSOUND.@)
499 HRESULT WINAPI DllRegisterServer(void)
505 hr = register_coclasses(coclass_list);
507 hr = register_interfaces(interface_list);
511 /***********************************************************************
512 * DllUnregisterServer (DSOUND.@)
514 HRESULT WINAPI DllUnregisterServer(void)
518 HMODULE advapi32 = GetModuleHandleA("advapi32");
519 if (!advapi32) return E_FAIL;
520 pRegDeleteTreeA = (void *) GetProcAddress(advapi32, "RegDeleteTreeA");
521 pRegDeleteTreeW = (void *) GetProcAddress(advapi32, "RegDeleteTreeW");
522 if (!pRegDeleteTreeA || !pRegDeleteTreeW) return E_FAIL;
526 hr = unregister_coclasses(coclass_list);
528 hr = unregister_interfaces(interface_list);