1 /* DirectSound
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 * Copyright 2004 Robert Reif
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "winternl.h"
33 #include "mmddk.h"
34 #include "wingdi.h"
35 #include "mmreg.h"
36 #include "ks.h"
37 #include "ksmedia.h"
38 #include "wine/debug.h"
39 #include "dsound.h"
40 #include "dsdriver.h"
41 #include "dsound_private.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
44
45 /*****************************************************************************
46 * IDirectSound COM components
47 */
48 struct IDirectSound_IUnknown {
49 const IUnknownVtbl *lpVtbl;
50 LONG ref;
51 LPDIRECTSOUND8 pds;
52 };
53
54 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
55
56 struct IDirectSound_IDirectSound {
57 const IDirectSoundVtbl *lpVtbl;
58 LONG ref;
59 LPDIRECTSOUND8 pds;
60 };
61
62 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
63
64 /*****************************************************************************
65 * IDirectSound8 COM components
66 */
67 struct IDirectSound8_IUnknown {
68 const IUnknownVtbl *lpVtbl;
69 LONG ref;
70 LPDIRECTSOUND8 pds;
71 };
72
73 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
74 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
75
76 struct IDirectSound8_IDirectSound {
77 const IDirectSoundVtbl *lpVtbl;
78 LONG ref;
79 LPDIRECTSOUND8 pds;
80 };
81
82 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
83 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
84
85 struct IDirectSound8_IDirectSound8 {
86 const IDirectSound8Vtbl *lpVtbl;
87 LONG ref;
88 LPDIRECTSOUND8 pds;
89 };
90
91 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
92 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
93
94 /*****************************************************************************
95 * IDirectSound implementation structure
96 */
97 struct IDirectSoundImpl
98 {
99 LONG ref;
100
101 DirectSoundDevice *device;
102 LPUNKNOWN pUnknown;
103 LPDIRECTSOUND pDS;
104 LPDIRECTSOUND8 pDS8;
105 };
106
107 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
108
109 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
110 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
111
112 static HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device, LPDWORD pdwCertified);
113
114 const char * dumpCooperativeLevel(DWORD level)
115 {
116 static char unknown[32];
117 #define LE(x) case x: return #x
118 switch (level) {
119 LE(DSSCL_NORMAL);
120 LE(DSSCL_PRIORITY);
121 LE(DSSCL_EXCLUSIVE);
122 LE(DSSCL_WRITEPRIMARY);
123 }
124 #undef LE
125 sprintf(unknown, "Unknown(%08x)", level);
126 return unknown;
127 }
128
129 static void _dump_DSCAPS(DWORD xmask) {
130 struct {
131 DWORD mask;
132 const char *name;
133 } flags[] = {
134 #define FE(x) { x, #x },
135 FE(DSCAPS_PRIMARYMONO)
136 FE(DSCAPS_PRIMARYSTEREO)
137 FE(DSCAPS_PRIMARY8BIT)
138 FE(DSCAPS_PRIMARY16BIT)
139 FE(DSCAPS_CONTINUOUSRATE)
140 FE(DSCAPS_EMULDRIVER)
141 FE(DSCAPS_CERTIFIED)
142 FE(DSCAPS_SECONDARYMONO)
143 FE(DSCAPS_SECONDARYSTEREO)
144 FE(DSCAPS_SECONDARY8BIT)
145 FE(DSCAPS_SECONDARY16BIT)
146 #undef FE
147 };
148 unsigned int i;
149
150 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
151 if ((flags[i].mask & xmask) == flags[i].mask)
152 TRACE("%s ",flags[i].name);
153 }
154
155 static void _dump_DSBCAPS(DWORD xmask) {
156 struct {
157 DWORD mask;
158 const char *name;
159 } flags[] = {
160 #define FE(x) { x, #x },
161 FE(DSBCAPS_PRIMARYBUFFER)
162 FE(DSBCAPS_STATIC)
163 FE(DSBCAPS_LOCHARDWARE)
164 FE(DSBCAPS_LOCSOFTWARE)
165 FE(DSBCAPS_CTRL3D)
166 FE(DSBCAPS_CTRLFREQUENCY)
167 FE(DSBCAPS_CTRLPAN)
168 FE(DSBCAPS_CTRLVOLUME)
169 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
170 FE(DSBCAPS_STICKYFOCUS)
171 FE(DSBCAPS_GLOBALFOCUS)
172 FE(DSBCAPS_GETCURRENTPOSITION2)
173 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
174 #undef FE
175 };
176 unsigned int i;
177
178 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
179 if ((flags[i].mask & xmask) == flags[i].mask)
180 TRACE("%s ",flags[i].name);
181 }
182
183 /*******************************************************************************
184 * IDirectSoundImpl_DirectSound
185 */
186 static HRESULT DSOUND_QueryInterface(
187 LPDIRECTSOUND8 iface,
188 REFIID riid,
189 LPVOID * ppobj)
190 {
191 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
192 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
193
194 if (ppobj == NULL) {
195 WARN("invalid parameter\n");
196 return E_INVALIDARG;
197 }
198
199 if (IsEqualIID(riid, &IID_IUnknown)) {
200 if (!This->pUnknown) {
201 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
202 if (!This->pUnknown) {
203 WARN("IDirectSound_IUnknown_Create() failed\n");
204 *ppobj = NULL;
205 return E_NOINTERFACE;
206 }
207 }
208 IDirectSound_IUnknown_AddRef(This->pUnknown);
209 *ppobj = This->pUnknown;
210 return S_OK;
211 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
212 if (!This->pDS) {
213 IDirectSound_IDirectSound_Create(iface, &This->pDS);
214 if (!This->pDS) {
215 WARN("IDirectSound_IDirectSound_Create() failed\n");
216 *ppobj = NULL;
217 return E_NOINTERFACE;
218 }
219 }
220 IDirectSound_IDirectSound_AddRef(This->pDS);
221 *ppobj = This->pDS;
222 return S_OK;
223 }
224
225 *ppobj = NULL;
226 WARN("Unknown IID %s\n",debugstr_guid(riid));
227 return E_NOINTERFACE;
228 }
229
230 static HRESULT DSOUND_QueryInterface8(
231 LPDIRECTSOUND8 iface,
232 REFIID riid,
233 LPVOID * ppobj)
234 {
235 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
236 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
237
238 if (ppobj == NULL) {
239 WARN("invalid parameter\n");
240 return E_INVALIDARG;
241 }
242
243 if (IsEqualIID(riid, &IID_IUnknown)) {
244 if (!This->pUnknown) {
245 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
246 if (!This->pUnknown) {
247 WARN("IDirectSound8_IUnknown_Create() failed\n");
248 *ppobj = NULL;
249 return E_NOINTERFACE;
250 }
251 }
252 IDirectSound8_IUnknown_AddRef(This->pUnknown);
253 *ppobj = This->pUnknown;
254 return S_OK;
255 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
256 if (!This->pDS) {
257 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
258 if (!This->pDS) {
259 WARN("IDirectSound8_IDirectSound_Create() failed\n");
260 *ppobj = NULL;
261 return E_NOINTERFACE;
262 }
263 }
264 IDirectSound8_IDirectSound_AddRef(This->pDS);
265 *ppobj = This->pDS;
266 return S_OK;
267 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
268 if (!This->pDS8) {
269 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
270 if (!This->pDS8) {
271 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
272 *ppobj = NULL;
273 return E_NOINTERFACE;
274 }
275 }
276 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
277 *ppobj = This->pDS8;
278 return S_OK;
279 }
280
281 *ppobj = NULL;
282 WARN("Unknown IID %s\n",debugstr_guid(riid));
283 return E_NOINTERFACE;
284 }
285
286 static ULONG IDirectSoundImpl_AddRef(
287 LPDIRECTSOUND8 iface)
288 {
289 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
290 ULONG ref = InterlockedIncrement(&(This->ref));
291 TRACE("(%p) ref was %d\n", This, ref - 1);
292 return ref;
293 }
294
295 static ULONG IDirectSoundImpl_Release(
296 LPDIRECTSOUND8 iface)
297 {
298 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
299 ULONG ref = InterlockedDecrement(&(This->ref));
300 TRACE("(%p) ref was %d\n", This, ref + 1);
301
302 if (!ref) {
303 if (This->device)
304 DirectSoundDevice_Release(This->device);
305 HeapFree(GetProcessHeap(),0,This);
306 TRACE("(%p) released\n", This);
307 }
308 return ref;
309 }
310
311 static HRESULT IDirectSoundImpl_Create(
312 LPDIRECTSOUND8 * ppDS)
313 {
314 IDirectSoundImpl* pDS;
315 TRACE("(%p)\n",ppDS);
316
317 /* Allocate memory */
318 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
319 if (pDS == NULL) {
320 WARN("out of memory\n");
321 *ppDS = NULL;
322 return DSERR_OUTOFMEMORY;
323 }
324
325 pDS->ref = 0;
326 pDS->device = NULL;
327
328 *ppDS = (LPDIRECTSOUND8)pDS;
329
330 return DS_OK;
331 }
332
333 /*******************************************************************************
334 * IDirectSound_IUnknown
335 */
336 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
337 LPUNKNOWN iface,
338 REFIID riid,
339 LPVOID * ppobj)
340 {
341 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
342 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
343 return DSOUND_QueryInterface(This->pds, riid, ppobj);
344 }
345
346 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
347 LPUNKNOWN iface)
348 {
349 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
350 ULONG ref = InterlockedIncrement(&(This->ref));
351 TRACE("(%p) ref was %d\n", This, ref - 1);
352 return ref;
353 }
354
355 static ULONG WINAPI IDirectSound_IUnknown_Release(
356 LPUNKNOWN iface)
357 {
358 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
359 ULONG ref = InterlockedDecrement(&(This->ref));
360 TRACE("(%p) ref was %d\n", This, ref + 1);
361 if (!ref) {
362 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
363 IDirectSoundImpl_Release(This->pds);
364 HeapFree(GetProcessHeap(), 0, This);
365 TRACE("(%p) released\n", This);
366 }
367 return ref;
368 }
369
370 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
371 {
372 IDirectSound_IUnknown_QueryInterface,
373 IDirectSound_IUnknown_AddRef,
374 IDirectSound_IUnknown_Release
375 };
376
377 static HRESULT IDirectSound_IUnknown_Create(
378 LPDIRECTSOUND8 pds,
379 LPUNKNOWN * ppunk)
380 {
381 IDirectSound_IUnknown * pdsunk;
382 TRACE("(%p,%p)\n",pds,ppunk);
383
384 if (ppunk == NULL) {
385 ERR("invalid parameter: ppunk == NULL\n");
386 return DSERR_INVALIDPARAM;
387 }
388
389 if (pds == NULL) {
390 ERR("invalid parameter: pds == NULL\n");
391 *ppunk = NULL;
392 return DSERR_INVALIDPARAM;
393 }
394
395 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
396 if (pdsunk == NULL) {
397 WARN("out of memory\n");
398 *ppunk = NULL;
399 return DSERR_OUTOFMEMORY;
400 }
401
402 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
403 pdsunk->ref = 0;
404 pdsunk->pds = pds;
405
406 IDirectSoundImpl_AddRef(pds);
407 *ppunk = (LPUNKNOWN)pdsunk;
408
409 return DS_OK;
410 }
411
412 /*******************************************************************************
413 * IDirectSound_IDirectSound
414 */
415 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
416 LPDIRECTSOUND iface,
417 REFIID riid,
418 LPVOID * ppobj)
419 {
420 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
421 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
422 return DSOUND_QueryInterface(This->pds, riid, ppobj);
423 }
424
425 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
426 LPDIRECTSOUND iface)
427 {
428 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
429 ULONG ref = InterlockedIncrement(&(This->ref));
430 TRACE("(%p) ref was %d\n", This, ref - 1);
431 return ref;
432 }
433
434 static ULONG WINAPI IDirectSound_IDirectSound_Release(
435 LPDIRECTSOUND iface)
436 {
437 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
438 ULONG ref = InterlockedDecrement(&(This->ref));
439 TRACE("(%p) ref was %d\n", This, ref + 1);
440 if (!ref) {
441 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
442 IDirectSoundImpl_Release(This->pds);
443 HeapFree(GetProcessHeap(), 0, This);
444 TRACE("(%p) released\n", This);
445 }
446 return ref;
447 }
448
449 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
450 LPDIRECTSOUND iface,
451 LPCDSBUFFERDESC dsbd,
452 LPLPDIRECTSOUNDBUFFER ppdsb,
453 LPUNKNOWN lpunk)
454 {
455 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
456 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
457 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
458 }
459
460 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
461 LPDIRECTSOUND iface,
462 LPDSCAPS lpDSCaps)
463 {
464 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
465 TRACE("(%p,%p)\n",This,lpDSCaps);
466 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
467 }
468
469 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
470 LPDIRECTSOUND iface,
471 LPDIRECTSOUNDBUFFER psb,
472 LPLPDIRECTSOUNDBUFFER ppdsb)
473 {
474 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
475 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
476 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
477 }
478
479 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
480 LPDIRECTSOUND iface,
481 HWND hwnd,
482 DWORD level)
483 {
484 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
485 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
486 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
487 }
488
489 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
490 LPDIRECTSOUND iface)
491 {
492 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
493 TRACE("(%p)\n", This);
494 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
495 }
496
497 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
498 LPDIRECTSOUND iface,
499 LPDWORD lpdwSpeakerConfig)
500 {
501 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
502 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
503 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
504 }
505
506 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
507 LPDIRECTSOUND iface,
508 DWORD config)
509 {
510 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
511 TRACE("(%p,0x%08x)\n",This,config);
512 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
513 }
514
515 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
516 LPDIRECTSOUND iface,
517 LPCGUID lpcGuid)
518 {
519 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
520 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
521 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
522 }
523
524 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
525 {
526 IDirectSound_IDirectSound_QueryInterface,
527 IDirectSound_IDirectSound_AddRef,
528 IDirectSound_IDirectSound_Release,
529 IDirectSound_IDirectSound_CreateSoundBuffer,
530 IDirectSound_IDirectSound_GetCaps,
531 IDirectSound_IDirectSound_DuplicateSoundBuffer,
532 IDirectSound_IDirectSound_SetCooperativeLevel,
533 IDirectSound_IDirectSound_Compact,
534 IDirectSound_IDirectSound_GetSpeakerConfig,
535 IDirectSound_IDirectSound_SetSpeakerConfig,
536 IDirectSound_IDirectSound_Initialize
537 };
538
539 static HRESULT IDirectSound_IDirectSound_Create(
540 LPDIRECTSOUND8 pds,
541 LPDIRECTSOUND * ppds)
542 {
543 IDirectSound_IDirectSound * pdsds;
544 TRACE("(%p,%p)\n",pds,ppds);
545
546 if (ppds == NULL) {
547 ERR("invalid parameter: ppds == NULL\n");
548 return DSERR_INVALIDPARAM;
549 }
550
551 if (pds == NULL) {
552 ERR("invalid parameter: pds == NULL\n");
553 *ppds = NULL;
554 return DSERR_INVALIDPARAM;
555 }
556
557 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
558 if (pdsds == NULL) {
559 WARN("out of memory\n");
560 *ppds = NULL;
561 return DSERR_OUTOFMEMORY;
562 }
563
564 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
565 pdsds->ref = 0;
566 pdsds->pds = pds;
567
568 IDirectSoundImpl_AddRef(pds);
569 *ppds = (LPDIRECTSOUND)pdsds;
570
571 return DS_OK;
572 }
573
574 /*******************************************************************************
575 * IDirectSound8_IUnknown
576 */
577 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
578 LPUNKNOWN iface,
579 REFIID riid,
580 LPVOID * ppobj)
581 {
582 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
583 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
584 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
585 }
586
587 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
588 LPUNKNOWN iface)
589 {
590 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
591 ULONG ref = InterlockedIncrement(&(This->ref));
592 TRACE("(%p) ref was %d\n", This, ref - 1);
593 return ref;
594 }
595
596 static ULONG WINAPI IDirectSound8_IUnknown_Release(
597 LPUNKNOWN iface)
598 {
599 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
600 ULONG ref = InterlockedDecrement(&(This->ref));
601 TRACE("(%p) ref was %d\n", This, ref + 1);
602 if (!ref) {
603 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
604 IDirectSoundImpl_Release(This->pds);
605 HeapFree(GetProcessHeap(), 0, This);
606 TRACE("(%p) released\n", This);
607 }
608 return ref;
609 }
610
611 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
612 {
613 IDirectSound8_IUnknown_QueryInterface,
614 IDirectSound8_IUnknown_AddRef,
615 IDirectSound8_IUnknown_Release
616 };
617
618 static HRESULT IDirectSound8_IUnknown_Create(
619 LPDIRECTSOUND8 pds,
620 LPUNKNOWN * ppunk)
621 {
622 IDirectSound8_IUnknown * pdsunk;
623 TRACE("(%p,%p)\n",pds,ppunk);
624
625 if (ppunk == NULL) {
626 ERR("invalid parameter: ppunk == NULL\n");
627 return DSERR_INVALIDPARAM;
628 }
629
630 if (pds == NULL) {
631 ERR("invalid parameter: pds == NULL\n");
632 *ppunk = NULL;
633 return DSERR_INVALIDPARAM;
634 }
635
636 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
637 if (pdsunk == NULL) {
638 WARN("out of memory\n");
639 *ppunk = NULL;
640 return DSERR_OUTOFMEMORY;
641 }
642
643 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
644 pdsunk->ref = 0;
645 pdsunk->pds = pds;
646
647 IDirectSoundImpl_AddRef(pds);
648 *ppunk = (LPUNKNOWN)pdsunk;
649
650 return DS_OK;
651 }
652
653 /*******************************************************************************
654 * IDirectSound8_IDirectSound
655 */
656 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
657 LPDIRECTSOUND iface,
658 REFIID riid,
659 LPVOID * ppobj)
660 {
661 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
662 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
663 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
664 }
665
666 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
667 LPDIRECTSOUND iface)
668 {
669 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
670 ULONG ref = InterlockedIncrement(&(This->ref));
671 TRACE("(%p) ref was %d\n", This, ref - 1);
672 return ref;
673 }
674
675 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
676 LPDIRECTSOUND iface)
677 {
678 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
679 ULONG ref = InterlockedDecrement(&(This->ref));
680 TRACE("(%p) ref was %d\n", This, ref + 1);
681 if (!ref) {
682 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
683 IDirectSoundImpl_Release(This->pds);
684 HeapFree(GetProcessHeap(), 0, This);
685 TRACE("(%p) released\n", This);
686 }
687 return ref;
688 }
689
690 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
691 LPDIRECTSOUND iface,
692 LPCDSBUFFERDESC dsbd,
693 LPLPDIRECTSOUNDBUFFER ppdsb,
694 LPUNKNOWN lpunk)
695 {
696 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
697 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
698 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
699 }
700
701 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
702 LPDIRECTSOUND iface,
703 LPDSCAPS lpDSCaps)
704 {
705 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
706 TRACE("(%p,%p)\n",This,lpDSCaps);
707 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
708 }
709
710 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
711 LPDIRECTSOUND iface,
712 LPDIRECTSOUNDBUFFER psb,
713 LPLPDIRECTSOUNDBUFFER ppdsb)
714 {
715 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
716 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
717 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
718 }
719
720 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
721 LPDIRECTSOUND iface,
722 HWND hwnd,
723 DWORD level)
724 {
725 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
726 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
727 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
728 }
729
730 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
731 LPDIRECTSOUND iface)
732 {
733 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
734 TRACE("(%p)\n", This);
735 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
736 }
737
738 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
739 LPDIRECTSOUND iface,
740 LPDWORD lpdwSpeakerConfig)
741 {
742 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
743 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
744 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
745 }
746
747 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
748 LPDIRECTSOUND iface,
749 DWORD config)
750 {
751 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
752 TRACE("(%p,0x%08x)\n",This,config);
753 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
754 }
755
756 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
757 LPDIRECTSOUND iface,
758 LPCGUID lpcGuid)
759 {
760 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
761 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
762 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
763 }
764
765 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
766 {
767 IDirectSound8_IDirectSound_QueryInterface,
768 IDirectSound8_IDirectSound_AddRef,
769 IDirectSound8_IDirectSound_Release,
770 IDirectSound8_IDirectSound_CreateSoundBuffer,
771 IDirectSound8_IDirectSound_GetCaps,
772 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
773 IDirectSound8_IDirectSound_SetCooperativeLevel,
774 IDirectSound8_IDirectSound_Compact,
775 IDirectSound8_IDirectSound_GetSpeakerConfig,
776 IDirectSound8_IDirectSound_SetSpeakerConfig,
777 IDirectSound8_IDirectSound_Initialize
778 };
779
780 static HRESULT IDirectSound8_IDirectSound_Create(
781 LPDIRECTSOUND8 pds,
782 LPDIRECTSOUND * ppds)
783 {
784 IDirectSound8_IDirectSound * pdsds;
785 TRACE("(%p,%p)\n",pds,ppds);
786
787 if (ppds == NULL) {
788 ERR("invalid parameter: ppds == NULL\n");
789 return DSERR_INVALIDPARAM;
790 }
791
792 if (pds == NULL) {
793 ERR("invalid parameter: pds == NULL\n");
794 *ppds = NULL;
795 return DSERR_INVALIDPARAM;
796 }
797
798 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
799 if (pdsds == NULL) {
800 WARN("out of memory\n");
801 *ppds = NULL;
802 return DSERR_OUTOFMEMORY;
803 }
804
805 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
806 pdsds->ref = 0;
807 pdsds->pds = pds;
808
809 IDirectSoundImpl_AddRef(pds);
810 *ppds = (LPDIRECTSOUND)pdsds;
811
812 return DS_OK;
813 }
814
815 /*******************************************************************************
816 * IDirectSound8_IDirectSound8
817 */
818 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
819 LPDIRECTSOUND8 iface,
820 REFIID riid,
821 LPVOID * ppobj)
822 {
823 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
824 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
825 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
826 }
827
828 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
829 LPDIRECTSOUND8 iface)
830 {
831 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
832 ULONG ref = InterlockedIncrement(&(This->ref));
833 TRACE("(%p) ref was %d\n", This, ref - 1);
834 return ref;
835 }
836
837 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
838 LPDIRECTSOUND8 iface)
839 {
840 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
841 ULONG ref = InterlockedDecrement(&(This->ref));
842 TRACE("(%p) ref was %d\n", This, ref + 1);
843 if (!ref) {
844 ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
845 IDirectSoundImpl_Release(This->pds);
846 HeapFree(GetProcessHeap(), 0, This);
847 TRACE("(%p) released\n", This);
848 }
849 return ref;
850 }
851
852 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
853 LPDIRECTSOUND8 iface,
854 LPCDSBUFFERDESC dsbd,
855 LPLPDIRECTSOUNDBUFFER ppdsb,
856 LPUNKNOWN lpunk)
857 {
858 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
859 TRACE("(%p,%p,%p,%p)\n