~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dsound/dsound.c

Version: ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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