Make sure dsound.h exists
[dsound-openal.git] / regsvr.c
blobf45f81b839006bff7083b8a5cfcd3fa090109226
1 /*
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
21 #include <stdarg.h>
23 #ifdef __WINESRC__
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winreg.h"
32 #include "mmsystem.h"
33 #include "dsound.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
41 #else
43 #define WINVER 0x0600
44 #include <windows.h>
45 #include <dsound.h>
47 #include "dsound_private.h"
49 typedef LONG LSTATUS;
51 #endif
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);
77 struct regsvr_coclass
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
98 static WCHAR const base_ifa_keyname[14] = {
99 'B','a','s','e','I','n','t','e','r','f','a','c','e',0
101 static WCHAR const num_methods_keyname[11] = {
102 'N','u','m','M','e','t','h','o','d','s',0
104 static WCHAR const ps_clsid_keyname[15] = {
105 'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0
107 static WCHAR const ps_clsid32_keyname[17] = {
108 'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0
110 static WCHAR const clsid_keyname[6] = {
111 'C','L','S','I','D',0
113 static WCHAR const curver_keyname[7] = {
114 'C','u','r','V','e','r',0
116 static WCHAR const ips_keyname[13] = {
117 'I','n','P','r','o','c','S','e','r','v','e','r',0
119 static WCHAR const ips32_keyname[15] = {
120 'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0
122 static WCHAR const progid_keyname[7] = {
123 'P','r','o','g','I','D',0
125 static WCHAR const viprogid_keyname[25] = {
126 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0
128 static char const tmodel_valuename[] = "ThreadingModel";
130 /***********************************************************************
131 * static helper functions
133 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
134 static LONG register_key_defvalueW(HKEY base, WCHAR const *name, WCHAR const *value);
135 static LONG register_key_defvalueA(HKEY base, WCHAR const *name, char const *value);
136 static LONG register_progid(WCHAR const *clsid, char const *progid, char const *curver_progid,
137 char const *name, char const *extra);
139 /***********************************************************************
140 * register_interfaces
142 static HRESULT register_interfaces(struct regsvr_interface const *list)
144 LONG res = ERROR_SUCCESS;
145 HKEY interface_key;
147 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
148 KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
149 if(res != ERROR_SUCCESS) goto error_return;
151 for(;res == ERROR_SUCCESS && list->iid;++list)
153 WCHAR buf[39];
154 HKEY iid_key;
156 StringFromGUID2(list->iid, buf, 39);
157 res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
158 KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
159 if(res != ERROR_SUCCESS) goto error_close_interface_key;
161 if(list->name)
163 res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
164 (CONST BYTE*)(list->name),
165 strlen(list->name) + 1);
166 if(res != ERROR_SUCCESS) goto error_close_iid_key;
169 if(list->base_iid)
171 res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
172 if(res != ERROR_SUCCESS) goto error_close_iid_key;
175 if(0 <= list->num_methods)
177 static WCHAR const fmt[3] = { '%','d',0 };
178 HKEY key;
180 res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
181 KEY_READ | KEY_WRITE, NULL, &key, NULL);
182 if(res != ERROR_SUCCESS) goto error_close_iid_key;
184 wsprintfW(buf, fmt, list->num_methods);
185 res = RegSetValueExW(key, NULL, 0, REG_SZ,
186 (CONST BYTE*)buf,
187 (lstrlenW(buf) + 1) * sizeof(WCHAR));
188 RegCloseKey(key);
190 if(res != ERROR_SUCCESS) goto error_close_iid_key;
193 if(list->ps_clsid)
195 res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
196 if(res != ERROR_SUCCESS) goto error_close_iid_key;
199 if(list->ps_clsid32)
201 res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
202 if(res != ERROR_SUCCESS) goto error_close_iid_key;
205 error_close_iid_key:
206 RegCloseKey(iid_key);
209 error_close_interface_key:
210 RegCloseKey(interface_key);
211 error_return:
212 return (res != ERROR_SUCCESS) ? HRESULT_FROM_WIN32(res) : S_OK;
215 /***********************************************************************
216 * unregister_interfaces
218 static HRESULT unregister_interfaces(struct regsvr_interface const *list)
220 LONG res = ERROR_SUCCESS;
221 HKEY interface_key;
223 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
224 KEY_READ | KEY_WRITE, &interface_key);
225 if(res == ERROR_FILE_NOT_FOUND) return S_OK;
226 if(res != ERROR_SUCCESS) goto error_return;
228 for(;res == ERROR_SUCCESS && list->iid;++list)
230 WCHAR buf[39];
232 StringFromGUID2(list->iid, buf, 39);
233 res = pRegDeleteTreeW(interface_key, buf);
234 if(res == ERROR_FILE_NOT_FOUND)
235 res = ERROR_SUCCESS;
238 RegCloseKey(interface_key);
239 error_return:
240 return (res != ERROR_SUCCESS) ? HRESULT_FROM_WIN32(res) : S_OK;
243 /***********************************************************************
244 * register_coclasses
246 static HRESULT register_coclasses(struct regsvr_coclass const *list)
248 LONG res = ERROR_SUCCESS;
249 HKEY coclass_key;
251 res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
252 KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
253 if(res != ERROR_SUCCESS) goto error_return;
255 for(;res == ERROR_SUCCESS && list->clsid;++list)
257 WCHAR buf[39];
258 HKEY clsid_key;
260 StringFromGUID2(list->clsid, buf, 39);
261 res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
262 KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
263 if(res != ERROR_SUCCESS) goto error_close_coclass_key;
265 if(list->name)
267 res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
268 (CONST BYTE*)(list->name),
269 strlen(list->name) + 1);
270 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
273 if(list->ips)
275 res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
276 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
279 if(list->ips32)
281 HKEY ips32_key;
283 res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
284 KEY_READ | KEY_WRITE, NULL,
285 &ips32_key, NULL);
286 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
288 res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
289 (CONST BYTE*)list->ips32,
290 lstrlenA(list->ips32) + 1);
291 if(res == ERROR_SUCCESS && list->ips32_tmodel)
292 res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
293 (CONST BYTE*)list->ips32_tmodel,
294 strlen(list->ips32_tmodel) + 1);
295 RegCloseKey(ips32_key);
296 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
299 if(list->progid)
301 res = register_key_defvalueA(clsid_key, progid_keyname,
302 list->progid);
303 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
305 res = register_progid(buf, list->progid, NULL,
306 list->name, list->progid_extra);
307 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
310 if(list->viprogid)
312 res = register_key_defvalueA(clsid_key, viprogid_keyname,
313 list->viprogid);
314 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
316 res = register_progid(buf, list->viprogid, list->progid,
317 list->name, list->progid_extra);
318 if(res != ERROR_SUCCESS) goto error_close_clsid_key;
321 error_close_clsid_key:
322 RegCloseKey(clsid_key);
325 error_close_coclass_key:
326 RegCloseKey(coclass_key);
327 error_return:
328 return (res != ERROR_SUCCESS) ? HRESULT_FROM_WIN32(res) : S_OK;
331 /***********************************************************************
332 * unregister_coclasses
334 static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
336 LONG res = ERROR_SUCCESS;
337 HKEY coclass_key;
339 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
340 KEY_READ | KEY_WRITE, &coclass_key);
341 if(res == ERROR_FILE_NOT_FOUND) return S_OK;
342 if(res != ERROR_SUCCESS) goto error_return;
344 for(;res == ERROR_SUCCESS && list->clsid;++list)
346 WCHAR buf[39];
348 StringFromGUID2(list->clsid, buf, 39);
349 res = pRegDeleteTreeW(coclass_key, buf);
350 if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
351 if (res != ERROR_SUCCESS) goto error_close_coclass_key;
353 if(list->progid)
355 res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
356 if(res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
357 if(res != ERROR_SUCCESS) goto error_close_coclass_key;
360 if(list->viprogid)
362 res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
363 if(res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
364 if(res != ERROR_SUCCESS) goto error_close_coclass_key;
368 error_close_coclass_key:
369 RegCloseKey(coclass_key);
370 error_return:
371 return (res != ERROR_SUCCESS) ? HRESULT_FROM_WIN32(res) : S_OK;
374 /***********************************************************************
375 * regsvr_key_guid
377 static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
379 WCHAR buf[39];
381 StringFromGUID2(guid, buf, 39);
382 return register_key_defvalueW(base, name, buf);
385 /***********************************************************************
386 * regsvr_key_defvalueW
388 static LONG register_key_defvalueW(
389 HKEY base,
390 WCHAR const *name,
391 WCHAR const *value)
393 LONG res;
394 HKEY key;
396 res = RegCreateKeyExW(base, name, 0, NULL, 0,
397 KEY_READ | KEY_WRITE, NULL, &key, NULL);
398 if(res != ERROR_SUCCESS) return res;
399 res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
400 (lstrlenW(value) + 1) * sizeof(WCHAR));
401 RegCloseKey(key);
402 return res;
405 /***********************************************************************
406 * regsvr_key_defvalueA
408 static LONG register_key_defvalueA(
409 HKEY base,
410 WCHAR const *name,
411 char const *value)
413 LONG res;
414 HKEY key;
416 res = RegCreateKeyExW(base, name, 0, NULL, 0,
417 KEY_READ | KEY_WRITE, NULL, &key, NULL);
418 if(res != ERROR_SUCCESS) return res;
419 res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
420 lstrlenA(value) + 1);
421 RegCloseKey(key);
422 return res;
425 /***********************************************************************
426 * regsvr_progid
428 static LONG register_progid(
429 WCHAR const *clsid,
430 char const *progid,
431 char const *curver_progid,
432 char const *name,
433 char const *extra)
435 LONG res;
436 HKEY progid_key;
438 res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
439 NULL, 0, KEY_READ | KEY_WRITE, NULL,
440 &progid_key, NULL);
441 if(res != ERROR_SUCCESS) return res;
443 if(name)
445 res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
446 (CONST BYTE*)name, strlen(name) + 1);
447 if (res != ERROR_SUCCESS) goto error_close_progid_key;
450 if(clsid)
452 res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
453 if(res != ERROR_SUCCESS) goto error_close_progid_key;
456 if(curver_progid)
458 res = register_key_defvalueA(progid_key, curver_keyname,
459 curver_progid);
460 if(res != ERROR_SUCCESS) goto error_close_progid_key;
463 if(extra)
465 HKEY extra_key;
467 res = RegCreateKeyExA(progid_key, extra, 0,
468 NULL, 0, KEY_READ | KEY_WRITE, NULL,
469 &extra_key, NULL);
470 if(res == ERROR_SUCCESS)
471 RegCloseKey(extra_key);
474 error_close_progid_key:
475 RegCloseKey(progid_key);
476 return res;
479 /***********************************************************************
480 * coclass list
482 static GUID const CLSID_DirectSoundBufferConfig = {
483 0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
485 static struct regsvr_coclass const coclass_list[] = {
486 { &CLSID_DirectSound,
487 "DirectSound Object",
488 NULL,
489 "dsound.dll",
490 "Both", NULL, NULL, NULL
492 { &CLSID_DirectSound8,
493 "DirectSound 8.0 Object",
494 NULL,
495 "dsound.dll",
496 "Both", NULL, NULL, NULL
498 { &CLSID_DirectSoundBufferConfig,
499 "DirectSoundBufferConfig Object",
500 NULL,
501 "dsound.dll",
502 "Both", NULL, NULL, NULL
504 { &CLSID_DirectSoundCapture,
505 "DirectSoundCapture Object",
506 NULL,
507 "dsound.dll",
508 "Both", NULL, NULL, NULL
510 { &CLSID_DirectSoundCapture8,
511 "DirectSoundCapture 8.0 Object",
512 NULL,
513 "dsound.dll",
514 "Both", NULL, NULL, NULL
516 { &CLSID_DirectSoundFullDuplex,
517 "DirectSoundFullDuplex Object",
518 NULL,
519 "dsound.dll",
520 "Both", NULL, NULL, NULL
522 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } /* list terminator */
525 /***********************************************************************
526 * interface list
529 static struct regsvr_interface const interface_list[] = {
530 { NULL, NULL, NULL, 0, NULL, NULL } /* list terminator */
533 /***********************************************************************
534 * DllRegisterServer (DSOUND.@)
536 HRESULT WINAPI DllRegisterServer(void)
538 HRESULT hr;
540 TRACE("\n");
542 hr = register_coclasses(coclass_list);
543 if(SUCCEEDED(hr))
544 hr = register_interfaces(interface_list);
545 return hr;
548 /***********************************************************************
549 * DllUnregisterServer (DSOUND.@)
551 HRESULT WINAPI DllUnregisterServer(void)
553 HMODULE advapi32;
554 HRESULT hr;
556 TRACE("\n");
558 advapi32 = GetModuleHandleA("advapi32");
559 if(!advapi32) return E_FAIL;
560 pRegDeleteTreeA = (void *) GetProcAddress(advapi32, "RegDeleteTreeA");
561 pRegDeleteTreeW = (void *) GetProcAddress(advapi32, "RegDeleteTreeW");
562 if(!pRegDeleteTreeA || !pRegDeleteTreeW) return E_FAIL;
564 hr = unregister_coclasses(coclass_list);
565 if(SUCCEEDED(hr))
566 hr = unregister_interfaces(interface_list);
567 return hr;