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"
35 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
37 static LSTATUS (WINAPI *pRegDeleteTreeW)(HKEY,LPCWSTR);
38 static LSTATUS (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR);
41 * Near the bottom of this file are the exported DllRegisterServer and
42 * DllUnregisterServer, which make all this worthwhile.
45 /***********************************************************************
46 * interface for self-registering
48 struct regsvr_interface
50 IID const *iid; /* NULL for end of list */
51 LPCSTR name; /* can be NULL to omit */
52 IID const *base_iid; /* can be NULL to omit */
53 int num_methods; /* can be <0 to omit */
54 CLSID const *ps_clsid; /* can be NULL to omit */
55 CLSID const *ps_clsid32; /* can be NULL to omit */
58 static HRESULT register_interfaces(struct regsvr_interface const *list);
59 static HRESULT unregister_interfaces(struct regsvr_interface const *list);
63 CLSID const *clsid; /* NULL for end of list */
64 LPCSTR name; /* can be NULL to omit */
65 LPCSTR ips; /* can be NULL to omit */
66 LPCSTR ips32; /* can be NULL to omit */
67 LPCSTR ips32_tmodel; /* can be NULL to omit */
68 LPCSTR progid; /* can be NULL to omit */
69 LPCSTR viprogid; /* can be NULL to omit */
70 LPCSTR progid_extra; /* can be NULL to omit */
73 static HRESULT register_coclasses(struct regsvr_coclass const *list);
74 static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
76 /***********************************************************************
77 * static string constants
79 static WCHAR const interface_keyname[10] = {
80 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
81 static WCHAR const base_ifa_keyname[14] = {
82 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
84 static WCHAR const num_methods_keyname[11] = {
85 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
86 static WCHAR const ps_clsid_keyname[15] = {
87 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
89 static WCHAR const ps_clsid32_keyname[17] = {
90 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
91 'i', 'd', '3', '2', 0 };
92 static WCHAR const clsid_keyname[6] = {
93 'C', 'L', 'S', 'I', 'D', 0 };
94 static WCHAR const curver_keyname[7] = {
95 'C', 'u', 'r', 'V', 'e', 'r', 0 };
96 static WCHAR const ips_keyname[13] = {
97 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
99 static WCHAR const ips32_keyname[15] = {
100 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
102 static WCHAR const progid_keyname[7] = {
103 'P', 'r', 'o', 'g', 'I', 'D', 0 };
104 static WCHAR const viprogid_keyname[25] = {
105 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
106 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
108 static char const tmodel_valuename[] = "ThreadingModel";
110 /***********************************************************************
111 * static helper functions
113 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
114 static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
116 static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
118 static LONG register_progid(WCHAR const *clsid,
119 char const *progid, char const *curver_progid,
120 char const *name, char const *extra);
122 /***********************************************************************
123 * register_interfaces
125 static HRESULT register_interfaces(struct regsvr_interface const *list)
127 LONG res = ERROR_SUCCESS;
130 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
131 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
132 if (res != ERROR_SUCCESS) goto error_return;
134 for (; res == ERROR_SUCCESS && list->iid; ++list) {
138 StringFromGUID2(list->iid, buf, 39);
139 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
140 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
141 if (res != ERROR_SUCCESS) goto error_close_interface_key;
144 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
145 (CONST BYTE*)(list->name),
146 strlen(list->name) + 1);
147 if (res != ERROR_SUCCESS) goto error_close_iid_key;
150 if (list->base_iid) {
151 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
152 if (res != ERROR_SUCCESS) goto error_close_iid_key;
155 if (0 <= list->num_methods) {
156 static WCHAR const fmt[3] = { '%', 'd', 0 };
159 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
160 KEY_READ | KEY_WRITE, NULL, &key, NULL);
161 if (res != ERROR_SUCCESS) goto error_close_iid_key;
163 wsprintfW(buf, fmt, list->num_methods);
164 res = RegSetValueExW(key, NULL, 0, REG_SZ,
166 (lstrlenW(buf) + 1) * sizeof(WCHAR));
169 if (res != ERROR_SUCCESS) goto error_close_iid_key;
172 if (list->ps_clsid) {
173 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
174 if (res != ERROR_SUCCESS) goto error_close_iid_key;
177 if (list->ps_clsid32) {
178 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
179 if (res != ERROR_SUCCESS) goto error_close_iid_key;
183 RegCloseKey(iid_key);
186 error_close_interface_key:
187 RegCloseKey(interface_key);
189 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
192 /***********************************************************************
193 * unregister_interfaces
195 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
197 LONG res = ERROR_SUCCESS;
200 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
201 KEY_READ | KEY_WRITE, &interface_key);
202 if (res == ERROR_FILE_NOT_FOUND) return S_OK;
203 if (res != ERROR_SUCCESS) goto error_return;
205 for (; res == ERROR_SUCCESS && list->iid; ++list) {
208 StringFromGUID2(list->iid, buf, 39);
209 res = pRegDeleteTreeW(interface_key, buf);
210 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
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 = pRegDeleteTreeW(coclass_key, buf);
318 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
319 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
322 res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
323 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
324 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
327 if (list->viprogid) {
328 res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
329 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
330 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
334 error_close_coclass_key:
335 RegCloseKey(coclass_key);
337 return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
340 /***********************************************************************
343 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
347 StringFromGUID2(guid, buf, 39);
348 return register_key_defvalueW(base, name, buf);
351 /***********************************************************************
352 * regsvr_key_defvalueW
354 static LONG register_key_defvalueW(
362 res = RegCreateKeyExW(base, name, 0, NULL, 0,
363 KEY_READ | KEY_WRITE, NULL, &key, NULL);
364 if (res != ERROR_SUCCESS) return res;
365 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
366 (lstrlenW(value) + 1) * sizeof(WCHAR));
371 /***********************************************************************
372 * regsvr_key_defvalueA
374 static LONG register_key_defvalueA(
382 res = RegCreateKeyExW(base, name, 0, NULL, 0,
383 KEY_READ | KEY_WRITE, NULL, &key, NULL);
384 if (res != ERROR_SUCCESS) return res;
385 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
386 lstrlenA(value) + 1);
391 /***********************************************************************
394 static LONG register_progid(
397 char const *curver_progid,
404 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
405 NULL, 0, KEY_READ | KEY_WRITE, NULL,
407 if (res != ERROR_SUCCESS) return res;
410 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
411 (CONST BYTE*)name, strlen(name) + 1);
412 if (res != ERROR_SUCCESS) goto error_close_progid_key;
416 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
417 if (res != ERROR_SUCCESS) goto error_close_progid_key;
421 res = register_key_defvalueA(progid_key, curver_keyname,
423 if (res != ERROR_SUCCESS) goto error_close_progid_key;
429 res = RegCreateKeyExA(progid_key, extra, 0,
430 NULL, 0, KEY_READ | KEY_WRITE, NULL,
432 if (res == ERROR_SUCCESS)
433 RegCloseKey(extra_key);
436 error_close_progid_key:
437 RegCloseKey(progid_key);
441 /***********************************************************************
444 static GUID const CLSID_DirectSoundBufferConfig = {
445 0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
447 static struct regsvr_coclass const coclass_list[] = {
448 { &CLSID_DirectSound,
449 "DirectSound Object",
454 { &CLSID_DirectSound8,
455 "DirectSound 8.0 Object",
460 { &CLSID_DirectSoundBufferConfig,
461 "DirectSoundBufferConfig Object",
466 { &CLSID_DirectSoundCapture,
467 "DirectSoundCapture Object",
472 { &CLSID_DirectSoundCapture8,
473 "DirectSoundCapture 8.0 Object",
478 { &CLSID_DirectSoundFullDuplex,
479 "DirectSoundFullDuplex Object",
484 { NULL } /* list terminator */
487 /***********************************************************************
491 static struct regsvr_interface const interface_list[] = {
492 { NULL } /* list terminator */
495 /***********************************************************************
496 * DllRegisterServer (DSOUND.@)
498 HRESULT WINAPI DllRegisterServer(void)
504 hr = register_coclasses(coclass_list);
506 hr = register_interfaces(interface_list);
510 /***********************************************************************
511 * DllUnregisterServer (DSOUND.@)
513 HRESULT WINAPI DllUnregisterServer(void)
517 HMODULE advapi32 = GetModuleHandleA("advapi32");
518 if (!advapi32) return E_FAIL;
519 pRegDeleteTreeA = (void *) GetProcAddress(advapi32, "RegDeleteTreeA");
520 pRegDeleteTreeW = (void *) GetProcAddress(advapi32, "RegDeleteTreeW");
521 if (!pRegDeleteTreeA || !pRegDeleteTreeW) return E_FAIL;
525 hr = unregister_coclasses(coclass_list);
527 hr = unregister_interfaces(interface_list);