Removed W->A from DEFWND_ImmIsUIMessageW.
[wine] / dlls / dsound / dsound.c
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/fcntl.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <stdlib.h>
34 #include <string.h>
35
36 #define NONAMELESSSTRUCT
37 #define NONAMELESSUNION
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winreg.h"
41 #include "winuser.h"
42 #include "wingdi.h"
43 #include "winuser.h"
44 #include "winerror.h"
45 #include "mmsystem.h"
46 #include "winternl.h"
47 #include "mmddk.h"
48 #include "wine/windef16.h"
49 #include "wine/winbase16.h"
50 #include "wine/debug.h"
51 #include "dsound.h"
52 #include "dsdriver.h"
53 #include "dsound_private.h"
54 #include "dsconf.h"
55
56 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
57
58 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
59 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
60 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
61 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
62 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
63
64 static const char * dumpCooperativeLevel(DWORD level)
65 {
66     static char unknown[32];
67 #define LE(x) case x: return #x
68     switch (level) {
69         LE(DSSCL_NORMAL);
70         LE(DSSCL_PRIORITY);
71         LE(DSSCL_EXCLUSIVE);
72         LE(DSSCL_WRITEPRIMARY);
73     }
74 #undef LE
75     sprintf(unknown, "Unknown(%08lx)", level);
76     return unknown;
77 }
78
79 static void _dump_DSCAPS(DWORD xmask) {
80     struct {
81         DWORD   mask;
82         char    *name;
83     } flags[] = {
84 #define FE(x) { x, #x },
85         FE(DSCAPS_PRIMARYMONO)
86         FE(DSCAPS_PRIMARYSTEREO)
87         FE(DSCAPS_PRIMARY8BIT)
88         FE(DSCAPS_PRIMARY16BIT)
89         FE(DSCAPS_CONTINUOUSRATE)
90         FE(DSCAPS_EMULDRIVER)
91         FE(DSCAPS_CERTIFIED)
92         FE(DSCAPS_SECONDARYMONO)
93         FE(DSCAPS_SECONDARYSTEREO)
94         FE(DSCAPS_SECONDARY8BIT)
95         FE(DSCAPS_SECONDARY16BIT)
96 #undef FE
97     };
98     unsigned int     i;
99
100     for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
101         if ((flags[i].mask & xmask) == flags[i].mask)
102             DPRINTF("%s ",flags[i].name);
103 }
104
105 static void _dump_DSBCAPS(DWORD xmask) {
106     struct {
107         DWORD   mask;
108         char    *name;
109     } flags[] = {
110 #define FE(x) { x, #x },
111         FE(DSBCAPS_PRIMARYBUFFER)
112         FE(DSBCAPS_STATIC)
113         FE(DSBCAPS_LOCHARDWARE)
114         FE(DSBCAPS_LOCSOFTWARE)
115         FE(DSBCAPS_CTRL3D)
116         FE(DSBCAPS_CTRLFREQUENCY)
117         FE(DSBCAPS_CTRLPAN)
118         FE(DSBCAPS_CTRLVOLUME)
119         FE(DSBCAPS_CTRLPOSITIONNOTIFY)
120         FE(DSBCAPS_STICKYFOCUS)
121         FE(DSBCAPS_GLOBALFOCUS)
122         FE(DSBCAPS_GETCURRENTPOSITION2)
123         FE(DSBCAPS_MUTE3DATMAXDISTANCE)
124 #undef FE
125     };
126     unsigned int     i;
127
128     for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
129         if ((flags[i].mask & xmask) == flags[i].mask)
130             DPRINTF("%s ",flags[i].name);
131 }
132
133 /*******************************************************************************
134  *              IDirectSoundImpl_DirectSound
135  */
136 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
137     LPDIRECTSOUND8 iface,
138     REFIID riid,
139     LPVOID * ppobj)
140 {
141     TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
142     FIXME("shouldn't be called directly\n");
143     return E_NOINTERFACE;
144 }
145
146 static HRESULT WINAPI DSOUND_QueryInterface(
147     LPDIRECTSOUND8 iface,
148     REFIID riid,
149     LPVOID * ppobj)
150 {
151     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
152     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
153
154     if (ppobj == NULL) {
155         WARN("invalid parameter\n");
156         return E_INVALIDARG;
157     }
158
159     if (IsEqualIID(riid, &IID_IUnknown)) {
160         if (!This->pUnknown) {
161             IDirectSound_IUnknown_Create(iface, &This->pUnknown);
162             if (!This->pUnknown) {
163                 WARN("IDirectSound_IUnknown_Create() failed\n");
164                 *ppobj = NULL;
165                 return E_NOINTERFACE;
166             }
167         }
168         IDirectSound_IUnknown_AddRef(This->pUnknown);
169         *ppobj = This->pUnknown;
170         return S_OK;
171     } else if (IsEqualIID(riid, &IID_IDirectSound)) {
172         if (!This->pDS) {
173             IDirectSound_IDirectSound_Create(iface, &This->pDS);
174             if (!This->pDS) {
175                 WARN("IDirectSound_IDirectSound_Create() failed\n");
176                 *ppobj = NULL;
177                 return E_NOINTERFACE;
178             }
179         }
180         IDirectSound_IDirectSound_AddRef(This->pDS);
181         *ppobj = This->pDS;
182         return S_OK;
183     }
184
185     *ppobj = NULL;
186     WARN("Unknown IID %s\n",debugstr_guid(riid));
187     return E_NOINTERFACE;
188 }
189
190 static HRESULT WINAPI DSOUND_QueryInterface8(
191     LPDIRECTSOUND8 iface,
192     REFIID riid,
193     LPVOID * ppobj)
194 {
195     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
196     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
197
198     if (ppobj == NULL) {
199         WARN("invalid parameter\n");
200         return E_INVALIDARG;
201     }
202
203     if (IsEqualIID(riid, &IID_IUnknown)) {
204         if (!This->pUnknown) {
205             IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
206             if (!This->pUnknown) {
207                 WARN("IDirectSound8_IUnknown_Create() failed\n");
208                 *ppobj = NULL;
209                 return E_NOINTERFACE;
210             }
211         }
212         IDirectSound8_IUnknown_AddRef(This->pUnknown);
213         *ppobj = This->pUnknown;
214         return S_OK;
215     } else if (IsEqualIID(riid, &IID_IDirectSound)) {
216         if (!This->pDS) {
217             IDirectSound8_IDirectSound_Create(iface, &This->pDS);
218             if (!This->pDS) {
219                 WARN("IDirectSound8_IDirectSound_Create() failed\n");
220                 *ppobj = NULL;
221                 return E_NOINTERFACE;
222             }
223         }
224         IDirectSound8_IDirectSound_AddRef(This->pDS);
225         *ppobj = This->pDS;
226         return S_OK;
227     } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
228         if (!This->pDS8) {
229             IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
230             if (!This->pDS8) {
231                 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
232                 *ppobj = NULL;
233                 return E_NOINTERFACE;
234             }
235         }
236         IDirectSound8_IDirectSound8_AddRef(This->pDS8);
237         *ppobj = This->pDS8;
238         return S_OK;
239     }
240
241     *ppobj = NULL;
242     WARN("Unknown IID %s\n",debugstr_guid(riid));
243     return E_NOINTERFACE;
244 }
245
246 static ULONG WINAPI IDirectSoundImpl_AddRef(
247     LPDIRECTSOUND8 iface)
248 {
249     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
250     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
251
252     return InterlockedIncrement(&(This->ref));
253 }
254
255 static ULONG WINAPI IDirectSoundImpl_Release(
256     LPDIRECTSOUND8 iface)
257 {
258     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
259     ULONG ref;
260     TRACE("(%p) ref was %ld, thread is %04lx\n",
261           This, This->ref, GetCurrentThreadId());
262
263     ref = InterlockedDecrement(&(This->ref));
264     if (ref == 0) {
265         HRESULT hres;
266         INT i;
267
268         timeKillEvent(This->timerID);
269         timeEndPeriod(DS_TIME_RES);
270         /* wait for timer to expire */
271         Sleep(DS_TIME_RES+1);
272
273         /* The sleep above should have allowed the timer process to expire
274          * but try to grab the lock just in case. Can't hold lock because
275          * IDirectSoundBufferImpl_Destroy also grabs the lock */
276         RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
277         RtlReleaseResource(&(This->buffer_list_lock));
278
279         /* It is allowed to release this object even when buffers are playing */
280         if (This->buffers) {
281             WARN("%d secondary buffers not released\n", This->nrofbuffers);
282             for( i=0;i<This->nrofbuffers;i++)
283                 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
284         }
285
286         if (This->primary) {
287             WARN("primary buffer not released\n");
288             IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
289         }
290
291         hres = DSOUND_PrimaryDestroy(This);
292         if (hres != DS_OK)
293             WARN("DSOUND_PrimaryDestroy failed\n");
294
295         if (This->driver)
296             IDsDriver_Close(This->driver);
297
298         if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
299             waveOutClose(This->hwo);
300
301         if (This->driver)
302             IDsDriver_Release(This->driver);
303
304         RtlDeleteResource(&This->buffer_list_lock);
305         This->mixlock.DebugInfo->Spare[1] = 0;
306         DeleteCriticalSection(&This->mixlock);
307         HeapFree(GetProcessHeap(),0,This);
308         dsound = NULL;
309         TRACE("(%p) released\n",This);
310     }
311
312     return ref;
313 }
314
315 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
316     LPDIRECTSOUND8 iface,
317     LPCDSBUFFERDESC dsbd,
318     LPLPDIRECTSOUNDBUFFER ppdsb,
319     LPUNKNOWN lpunk)
320 {
321     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
322     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
323     FIXME("shouldn't be called directly\n");
324     return DSERR_GENERIC;
325 }
326
327 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
328     LPDIRECTSOUND8 iface,
329     LPCDSBUFFERDESC dsbd,
330     LPLPDIRECTSOUNDBUFFER ppdsb,
331     LPUNKNOWN lpunk,
332     BOOL from8)
333 {
334     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
335     HRESULT hres = DS_OK;
336     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
337
338     if (This == NULL) {
339         WARN("invalid parameter: This == NULL\n");
340         return DSERR_INVALIDPARAM;
341     }
342
343     if (This->initialized == FALSE) {
344         WARN("not initialized\n");
345         return DSERR_UNINITIALIZED;
346     }
347
348     if (dsbd == NULL) {
349         WARN("invalid parameter: dsbd == NULL\n");
350         return DSERR_INVALIDPARAM;
351     }
352
353     if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
354         dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
355         WARN("invalid parameter: dsbd\n");
356         return DSERR_INVALIDPARAM;
357     }
358
359     if (ppdsb == NULL) {
360         WARN("invalid parameter: ppdsb == NULL\n");
361         return DSERR_INVALIDPARAM;
362     }
363
364     if (TRACE_ON(dsound)) {
365         TRACE("(structsize=%ld)\n",dsbd->dwSize);
366         TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
367         _dump_DSBCAPS(dsbd->dwFlags);
368         DPRINTF(")\n");
369         TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
370         TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
371     }
372
373     if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
374         if (dsbd->lpwfxFormat != NULL) {
375             WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
376                  "primary buffer\n");
377             return DSERR_INVALIDPARAM;
378         }
379
380         if (This->primary) {
381             WARN("Primary Buffer already created\n");
382             IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
383             *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
384         } else {
385            This->dsbd = *dsbd;
386            hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
387            if (This->primary) {
388                IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
389                *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
390            } else
391                WARN("PrimaryBufferImpl_Create failed\n");
392         }
393     } else {
394         IDirectSoundBufferImpl * dsb;
395
396         if (dsbd->lpwfxFormat == NULL) {
397             WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
398                  "secondary buffer\n");
399             return DSERR_INVALIDPARAM;
400         }
401
402         TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
403               "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
404               dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
405               dsbd->lpwfxFormat->nSamplesPerSec,
406               dsbd->lpwfxFormat->nAvgBytesPerSec,
407               dsbd->lpwfxFormat->nBlockAlign,
408               dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
409
410         if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
411             WARN("invalid parameter: 3D buffer format must be mono\n");
412             return DSERR_INVALIDPARAM;
413         }
414
415         hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
416         if (dsb) {
417             hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
418             if (*ppdsb) {
419                 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
420                 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
421             } else
422                 WARN("SecondaryBufferImpl_Create failed\n");
423         } else
424            WARN("IDirectSoundBufferImpl_Create failed\n");
425    }
426
427    return hres;
428 }
429
430 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
431     LPDIRECTSOUND8 iface,
432     LPDSCAPS lpDSCaps)
433 {
434     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
435     TRACE("(%p,%p)\n",This,lpDSCaps);
436
437     if (This == NULL) {
438         WARN("invalid parameter: This == NULL\n");
439         return DSERR_INVALIDPARAM;
440     }
441
442     if (This->initialized == FALSE) {
443         WARN("not initialized\n");
444         return DSERR_UNINITIALIZED;
445     }
446
447     if (lpDSCaps == NULL) {
448         WARN("invalid parameter: lpDSCaps = NULL\n");
449         return DSERR_INVALIDPARAM;
450     }
451
452     /* check if there is enough room */
453     if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
454         WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
455              lpDSCaps->dwSize, sizeof(*lpDSCaps));
456         return DSERR_INVALIDPARAM;
457     }
458
459     lpDSCaps->dwFlags                           = This->drvcaps.dwFlags;
460     if (TRACE_ON(dsound)) {
461         TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
462         _dump_DSCAPS(lpDSCaps->dwFlags);
463         DPRINTF(")\n");
464     }
465     lpDSCaps->dwMinSecondarySampleRate          = This->drvcaps.dwMinSecondarySampleRate;
466     lpDSCaps->dwMaxSecondarySampleRate          = This->drvcaps.dwMaxSecondarySampleRate;
467     lpDSCaps->dwPrimaryBuffers                  = This->drvcaps.dwPrimaryBuffers;
468     lpDSCaps->dwMaxHwMixingAllBuffers           = This->drvcaps.dwMaxHwMixingAllBuffers;
469     lpDSCaps->dwMaxHwMixingStaticBuffers        = This->drvcaps.dwMaxHwMixingStaticBuffers;
470     lpDSCaps->dwMaxHwMixingStreamingBuffers     = This->drvcaps.dwMaxHwMixingStreamingBuffers;
471     lpDSCaps->dwFreeHwMixingAllBuffers          = This->drvcaps.dwFreeHwMixingAllBuffers;
472     lpDSCaps->dwFreeHwMixingStaticBuffers       = This->drvcaps.dwFreeHwMixingStaticBuffers;
473     lpDSCaps->dwFreeHwMixingStreamingBuffers    = This->drvcaps.dwFreeHwMixingStreamingBuffers;
474     lpDSCaps->dwMaxHw3DAllBuffers               = This->drvcaps.dwMaxHw3DAllBuffers;
475     lpDSCaps->dwMaxHw3DStaticBuffers            = This->drvcaps.dwMaxHw3DStaticBuffers;
476     lpDSCaps->dwMaxHw3DStreamingBuffers         = This->drvcaps.dwMaxHw3DStreamingBuffers;
477     lpDSCaps->dwFreeHw3DAllBuffers              = This->drvcaps.dwFreeHw3DAllBuffers;
478     lpDSCaps->dwFreeHw3DStaticBuffers           = This->drvcaps.dwFreeHw3DStaticBuffers;
479     lpDSCaps->dwFreeHw3DStreamingBuffers        = This->drvcaps.dwFreeHw3DStreamingBuffers;
480     lpDSCaps->dwTotalHwMemBytes                 = This->drvcaps.dwTotalHwMemBytes;
481     lpDSCaps->dwFreeHwMemBytes                  = This->drvcaps.dwFreeHwMemBytes;
482     lpDSCaps->dwMaxContigFreeHwMemBytes         = This->drvcaps.dwMaxContigFreeHwMemBytes;
483
484     /* driver doesn't have these */
485     lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
486     lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
487
488     return DS_OK;
489 }
490
491 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
492     LPDIRECTSOUND8 iface,
493     LPDIRECTSOUNDBUFFER psb,
494     LPLPDIRECTSOUNDBUFFER ppdsb)
495 {
496     IDirectSoundBufferImpl* pdsb;
497     IDirectSoundBufferImpl* dsb;
498     HRESULT hres = DS_OK;
499     int size;
500     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
501
502     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
503
504     if (This == NULL) {
505         WARN("invalid parameter: This == NULL\n");
506         return DSERR_INVALIDPARAM;
507     }
508
509     if (This->initialized == FALSE) {
510         WARN("not initialized\n");
511         return DSERR_UNINITIALIZED;
512     }
513
514     if (psb == NULL) {
515         WARN("invalid parameter: psb == NULL\n");
516         return DSERR_INVALIDPARAM;
517     }
518
519     if (ppdsb == NULL) {
520         WARN("invalid parameter: ppdsb == NULL\n");
521         return DSERR_INVALIDPARAM;
522     }
523
524     /* FIXME: hack to make sure we have a secondary buffer */
525     if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
526         WARN("trying to duplicate primary buffer\n");
527         *ppdsb = NULL;
528         return DSERR_INVALIDCALL;
529     }
530
531     pdsb = ((SecondaryBufferImpl *)psb)->dsb;
532
533     dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
534
535     if (dsb == NULL) {
536         WARN("out of memory\n");
537         *ppdsb = NULL;
538         return DSERR_OUTOFMEMORY;
539     }
540
541     memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
542
543     if (pdsb->hwbuf) {
544         TRACE("duplicating hardware buffer\n");
545
546         hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
547         if (hres != DS_OK) {
548             TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
549             dsb->hwbuf = NULL;
550             /* allocate buffer */
551             if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
552                 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
553                 if (dsb->buffer == NULL) {
554                     WARN("out of memory\n");
555                     HeapFree(GetProcessHeap(),0,dsb);
556                     *ppdsb = NULL;
557                     return DSERR_OUTOFMEMORY;
558                 }
559
560                 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
561                 if (dsb->buffer->memory == NULL) {
562                     WARN("out of memory\n");
563                     HeapFree(GetProcessHeap(),0,dsb->buffer);
564                     HeapFree(GetProcessHeap(),0,dsb);
565                     *ppdsb = NULL;
566                     return DSERR_OUTOFMEMORY;
567                 }
568                 dsb->buffer->ref = 1;
569
570                 /* FIXME: copy buffer ? */
571             }
572         }
573     } else {
574         dsb->hwbuf = NULL;
575         dsb->buffer->ref++;
576     }
577
578     dsb->ref = 0;
579     dsb->state = STATE_STOPPED;
580     dsb->playpos = 0;
581     dsb->buf_mixpos = 0;
582     dsb->dsound = This;
583     dsb->ds3db = NULL;
584     dsb->iks = NULL; /* FIXME? */
585     dsb->dsb = NULL;
586
587     /* variable sized struct so calculate size based on format */
588     size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
589
590     dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
591     if (dsb->pwfx == NULL) {
592             WARN("out of memory\n");
593             HeapFree(GetProcessHeap(),0,dsb->buffer);
594             HeapFree(GetProcessHeap(),0,dsb);
595             *ppdsb = NULL;
596             return DSERR_OUTOFMEMORY;
597     }
598
599     memcpy(dsb->pwfx, pdsb->pwfx, size);
600
601     InitializeCriticalSection(&(dsb->lock));
602     dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
603
604     /* register buffer */
605     hres = DSOUND_AddBuffer(This, dsb);
606     if (hres != DS_OK) {
607         IDirectSoundBuffer8_Release(psb);
608         dsb->lock.DebugInfo->Spare[1] = 0;
609         DeleteCriticalSection(&(dsb->lock));
610         HeapFree(GetProcessHeap(),0,dsb->buffer);
611         HeapFree(GetProcessHeap(),0,dsb->pwfx);
612         HeapFree(GetProcessHeap(),0,dsb);
613         *ppdsb = 0;
614     } else {
615         hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
616         if (*ppdsb) {
617             dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
618             IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
619         } else
620             WARN("SecondaryBufferImpl_Create failed\n");
621     }
622
623     return hres;
624 }
625
626 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
627     LPDIRECTSOUND8 iface,
628     HWND hwnd,
629     DWORD level)
630 {
631     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
632     TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
633
634     if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
635         FIXME("level=%s not fully supported\n",
636               level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
637     }
638     This->priolevel = level;
639     return DS_OK;
640 }
641
642 static HRESULT WINAPI IDirectSoundImpl_Compact(
643     LPDIRECTSOUND8 iface)
644 {
645     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
646     TRACE("(%p)\n",This);
647
648     if (This->initialized == FALSE) {
649         WARN("not initialized\n");
650         return DSERR_UNINITIALIZED;
651     }
652
653     if (This->priolevel != DSSCL_PRIORITY) {
654         WARN("incorrect priority level\n");
655         return DSERR_PRIOLEVELNEEDED;
656     }
657
658     return DS_OK;
659 }
660
661 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
662     LPDIRECTSOUND8 iface,
663     LPDWORD lpdwSpeakerConfig)
664 {
665     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
666     TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
667
668     if (This->initialized == FALSE) {
669         WARN("not initialized\n");
670         return DSERR_UNINITIALIZED;
671     }
672
673     if (lpdwSpeakerConfig == NULL) {
674         WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
675         return DSERR_INVALIDPARAM;
676     }
677
678     WARN("not fully functional\n");
679     *lpdwSpeakerConfig = This->speaker_config;
680     return DS_OK;
681 }
682
683 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
684     LPDIRECTSOUND8 iface,
685     DWORD config)
686 {
687     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
688     TRACE("(%p,0x%08lx)\n",This,config);
689
690     if (This->initialized == FALSE) {
691         WARN("not initialized\n");
692         return DSERR_UNINITIALIZED;
693     }
694
695     This->speaker_config = config;
696     WARN("not fully functional\n");
697     return DS_OK;
698 }
699
700 static HRESULT WINAPI IDirectSoundImpl_Initialize(
701     LPDIRECTSOUND8 iface,
702     LPCGUID lpcGuid)
703 {
704     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
705     TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
706
707     This->initialized = TRUE;
708
709     return DS_OK;
710 }
711
712 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
713     LPDIRECTSOUND8 iface,
714     LPDWORD pdwCertified)
715 {
716     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
717     TRACE("(%p, %p)\n",This,pdwCertified);
718
719     if (This->initialized == FALSE) {
720         WARN("not initialized\n");
721         return DSERR_UNINITIALIZED;
722     }
723
724     if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
725         *pdwCertified = DS_CERTIFIED;
726     else
727         *pdwCertified = DS_UNCERTIFIED;
728     return DS_OK;
729 }
730
731 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
732 {
733     IDirectSoundImpl_QueryInterface,
734     IDirectSoundImpl_AddRef,
735     IDirectSoundImpl_Release,
736     IDirectSoundImpl_CreateSoundBuffer,
737     IDirectSoundImpl_GetCaps,
738     IDirectSoundImpl_DuplicateSoundBuffer,
739     IDirectSoundImpl_SetCooperativeLevel,
740     IDirectSoundImpl_Compact,
741     IDirectSoundImpl_GetSpeakerConfig,
742     IDirectSoundImpl_SetSpeakerConfig,
743     IDirectSoundImpl_Initialize,
744     IDirectSoundImpl_VerifyCertification
745 };
746
747 HRESULT WINAPI IDirectSoundImpl_Create(
748     LPCGUID lpcGUID,
749     LPDIRECTSOUND8 * ppDS)
750 {
751     HRESULT err;
752     PIDSDRIVER drv = NULL;
753     IDirectSoundImpl* pDS;
754     unsigned wod, wodn;
755     BOOLEAN found = FALSE;
756     TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
757
758     /* Enumerate WINMM audio devices and find the one we want */
759     wodn = waveOutGetNumDevs();
760     if (!wodn) {
761         WARN("no driver\n");
762         *ppDS = NULL;
763         return DSERR_NODRIVER;
764     }
765
766     TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
767
768     for (wod=0; wod<wodn; wod++) {
769         if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
770             found = TRUE;
771             break;
772         }
773     }
774
775     if (found == FALSE) {
776         WARN("No device found matching given ID!\n");
777         *ppDS = NULL;
778         return DSERR_NODRIVER;
779     }
780
781     /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
782     waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
783
784     /* Disable the direct sound driver to force emulation if requested. */
785     if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
786         drv = NULL;
787
788     /* Allocate memory */
789     pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
790     if (ppDS == NULL) {
791         WARN("out of memory\n");
792         *ppDS = NULL;
793         return DSERR_OUTOFMEMORY;
794     }
795
796     pDS->lpVtbl         = &IDirectSoundImpl_Vtbl;
797     pDS->ref            = 0;
798
799     pDS->driver         = drv;
800     pDS->priolevel      = DSSCL_NORMAL;
801     pDS->fraglen        = 0;
802     pDS->hwbuf          = NULL;
803     pDS->buffer         = NULL;
804     pDS->buflen         = 0;
805     pDS->writelead      = 0;
806     pDS->state          = STATE_STOPPED;
807     pDS->nrofbuffers    = 0;
808     pDS->buffers        = NULL;
809     pDS->primary        = NULL;
810     pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
811     pDS->initialized    = FALSE;
812
813     /* 3D listener initial parameters */
814     pDS->listener       = NULL;
815     pDS->ds3dl.dwSize   = sizeof(DS3DLISTENER);
816     pDS->ds3dl.vPosition.x = 0.0;
817     pDS->ds3dl.vPosition.y = 0.0;
818     pDS->ds3dl.vPosition.z = 0.0;
819     pDS->ds3dl.vVelocity.x = 0.0;
820     pDS->ds3dl.vVelocity.y = 0.0;
821     pDS->ds3dl.vVelocity.z = 0.0;
822     pDS->ds3dl.vOrientFront.x = 0.0;
823     pDS->ds3dl.vOrientFront.y = 0.0;
824     pDS->ds3dl.vOrientFront.z = 1.0;
825     pDS->ds3dl.vOrientTop.x = 0.0;
826     pDS->ds3dl.vOrientTop.y = 1.0;
827     pDS->ds3dl.vOrientTop.z = 0.0;
828     pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
829     pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
830     pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
831
832     pDS->prebuf         = ds_snd_queue_max;
833     pDS->guid           = *lpcGUID;
834
835     /* Get driver description */
836     if (drv) {
837         err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
838         if (err != DS_OK) {
839             WARN("IDsDriver_GetDriverDesc failed\n");
840             HeapFree(GetProcessHeap(),0,pDS);
841             *ppDS = NULL;
842             return err;
843         }
844     } else {
845         /* if no DirectSound interface available, use WINMM API instead */
846         pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
847     }
848
849     pDS->drvdesc.dnDevNode = wod;
850
851     /* Set default wave format (may need it for waveOutOpen) */
852     pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
853     if (pDS->pwfx == NULL) {
854         WARN("out of memory\n");
855         HeapFree(GetProcessHeap(),0,pDS);
856         *ppDS = NULL;
857         return DSERR_OUTOFMEMORY;
858     }
859
860     pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
861     /* We rely on the sound driver to return the actual sound format of
862      * the device if it does not support 22050x8x2 and is given the
863      * WAVE_DIRECTSOUND flag.
864      */
865     pDS->pwfx->nSamplesPerSec = 22050;
866     pDS->pwfx->wBitsPerSample = 8;
867     pDS->pwfx->nChannels = 2;
868     pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
869     pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
870     pDS->pwfx->cbSize = 0;
871
872     /* If the driver requests being opened through MMSYSTEM
873      * (which is recommended by the DDK), it is supposed to happen
874      * before the DirectSound interface is opened */
875     if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
876     {
877         DWORD flags = CALLBACK_FUNCTION;
878
879         /* disable direct sound if requested */
880         if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
881             flags |= WAVE_DIRECTSOUND;
882
883         err = mmErr(waveOutOpen(&(pDS->hwo),
884                                 pDS->drvdesc.dnDevNode, pDS->pwfx,
885                                 (DWORD)DSOUND_callback, (DWORD)pDS,
886                                 flags));
887         if (err != DS_OK) {
888             WARN("waveOutOpen failed\n");
889             HeapFree(GetProcessHeap(),0,pDS);
890             *ppDS = NULL;
891             return err;
892         }
893     }
894
895     if (drv) {
896         err = IDsDriver_Open(drv);
897         if (err != DS_OK) {
898             WARN("IDsDriver_Open failed\n");
899             HeapFree(GetProcessHeap(),0,pDS);
900             *ppDS = NULL;
901             return err;
902         }
903
904         /* the driver is now open, so it's now allowed to call GetCaps */
905         err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
906         if (err != DS_OK) {
907             WARN("IDsDriver_GetCaps failed\n");
908             HeapFree(GetProcessHeap(),0,pDS);
909             *ppDS = NULL;
910             return err;
911         }
912     } else {
913         WAVEOUTCAPSA woc;
914         err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
915         if (err != DS_OK) {
916             WARN("waveOutGetDevCaps failed\n");
917             HeapFree(GetProcessHeap(),0,pDS);
918             *ppDS = NULL;
919             return err;
920         }
921         ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
922         if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
923             (woc.dwFormats & WAVE_FORMAT_2M08) ||
924             (woc.dwFormats & WAVE_FORMAT_4M08) ||
925             (woc.dwFormats & WAVE_FORMAT_48M08) ||
926             (woc.dwFormats & WAVE_FORMAT_96M08)) {
927             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
928             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
929         }
930         if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
931             (woc.dwFormats & WAVE_FORMAT_2M16) ||
932             (woc.dwFormats & WAVE_FORMAT_4M16) ||
933             (woc.dwFormats & WAVE_FORMAT_48M16) ||
934             (woc.dwFormats & WAVE_FORMAT_96M16)) {
935             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
936             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
937         }
938         if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
939             (woc.dwFormats & WAVE_FORMAT_2S08) ||
940             (woc.dwFormats & WAVE_FORMAT_4S08) ||
941             (woc.dwFormats & WAVE_FORMAT_48S08) ||
942             (woc.dwFormats & WAVE_FORMAT_96S08)) {
943             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
944             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
945         }
946         if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
947             (woc.dwFormats & WAVE_FORMAT_2S16) ||
948             (woc.dwFormats & WAVE_FORMAT_4S16) ||
949             (woc.dwFormats & WAVE_FORMAT_48S16) ||
950             (woc.dwFormats & WAVE_FORMAT_96S16)) {
951             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
952             pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
953         }
954         if (ds_emuldriver)
955             pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
956         pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
957         pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
958         pDS->drvcaps.dwPrimaryBuffers = 1;
959     }
960
961     InitializeCriticalSection(&(pDS->mixlock));
962     pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
963
964     RtlInitializeResource(&(pDS->buffer_list_lock));
965
966     *ppDS = (LPDIRECTSOUND8)pDS;
967
968     return DS_OK;
969 }
970 /*******************************************************************************
971  *              IDirectSound_IUnknown
972  */
973 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
974     LPUNKNOWN iface,
975     REFIID riid,
976     LPVOID * ppobj)
977 {
978     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
979     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
980     return DSOUND_QueryInterface(This->pds, riid, ppobj);
981 }
982
983 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
984     LPUNKNOWN iface)
985 {
986     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
987     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
988     return InterlockedIncrement(&(This->ref));
989 }
990
991 static ULONG WINAPI IDirectSound_IUnknown_Release(
992     LPUNKNOWN iface)
993 {
994     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
995     ULONG ulReturn;
996     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
997     ulReturn = InterlockedDecrement(&(This->ref));
998     if (ulReturn == 0) {
999         IDirectSoundImpl_Release(This->pds);
1000         HeapFree(GetProcessHeap(),0,This);
1001         TRACE("(%p) released\n",This);
1002     }
1003     return ulReturn;
1004 }
1005
1006 static IUnknownVtbl DirectSound_Unknown_Vtbl =
1007 {
1008     IDirectSound_IUnknown_QueryInterface,
1009     IDirectSound_IUnknown_AddRef,
1010     IDirectSound_IUnknown_Release
1011 };
1012
1013 HRESULT WINAPI IDirectSound_IUnknown_Create(
1014     LPDIRECTSOUND8 pds,
1015     LPUNKNOWN * ppunk)
1016 {
1017     IDirectSound_IUnknown * pdsunk;
1018     TRACE("(%p,%p)\n",pds,ppunk);
1019
1020     if (ppunk == NULL) {
1021         ERR("invalid parameter: ppunk == NULL\n");
1022         return DSERR_INVALIDPARAM;
1023     }
1024
1025     if (pds == NULL) {
1026         ERR("invalid parameter: pds == NULL\n");
1027         *ppunk = NULL;
1028         return DSERR_INVALIDPARAM;
1029     }
1030
1031     pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1032     if (pdsunk == NULL) {
1033         WARN("out of memory\n");
1034         *ppunk = NULL;
1035         return DSERR_OUTOFMEMORY;
1036     }
1037
1038     pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1039     pdsunk->ref = 0;
1040     pdsunk->pds = pds;
1041
1042     IDirectSoundImpl_AddRef(pds);
1043     *ppunk = (LPUNKNOWN)pdsunk;
1044
1045     return DS_OK;
1046 }
1047
1048 /*******************************************************************************
1049  *              IDirectSound_IDirectSound
1050  */
1051 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1052     LPDIRECTSOUND iface,
1053     REFIID riid,
1054     LPVOID * ppobj)
1055 {
1056     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1057     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1058     return DSOUND_QueryInterface(This->pds, riid, ppobj);
1059 }
1060
1061 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1062     LPDIRECTSOUND iface)
1063 {
1064     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1065     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1066     return InterlockedIncrement(&(This->ref));
1067 }
1068
1069 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1070     LPDIRECTSOUND iface)
1071 {
1072     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1073     ULONG ulReturn;
1074     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1075     ulReturn = InterlockedDecrement(&This->ref);
1076     if (ulReturn == 0) {
1077         IDirectSoundImpl_Release(This->pds);
1078         HeapFree(GetProcessHeap(),0,This);
1079         TRACE("(%p) released\n",This);
1080     }
1081     return ulReturn;
1082 }
1083
1084 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1085     LPDIRECTSOUND iface,
1086     LPCDSBUFFERDESC dsbd,
1087     LPLPDIRECTSOUNDBUFFER ppdsb,
1088     LPUNKNOWN lpunk)
1089 {
1090     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1091     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1092     return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1093 }
1094
1095 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1096     LPDIRECTSOUND iface,
1097     LPDSCAPS lpDSCaps)
1098 {
1099     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1100     TRACE("(%p,%p)\n",This,lpDSCaps);
1101     return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1102 }
1103
1104 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1105     LPDIRECTSOUND iface,
1106     LPDIRECTSOUNDBUFFER psb,
1107     LPLPDIRECTSOUNDBUFFER ppdsb)
1108 {
1109     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1110     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1111     return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1112 }
1113
1114 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1115     LPDIRECTSOUND iface,
1116     HWND hwnd,
1117     DWORD level)
1118 {
1119     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1120     TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1121     return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1122 }
1123
1124 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1125     LPDIRECTSOUND iface)
1126 {
1127     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1128     TRACE("(%p)\n", This);
1129     return IDirectSoundImpl_Compact(This->pds);
1130 }
1131
1132 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1133     LPDIRECTSOUND iface,
1134     LPDWORD lpdwSpeakerConfig)
1135 {
1136     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1137     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1138     return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1139 }
1140
1141 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1142     LPDIRECTSOUND iface,
1143     DWORD config)
1144 {
1145     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1146     TRACE("(%p,0x%08lx)\n",This,config);
1147     return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1148 }
1149
1150 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1151     LPDIRECTSOUND iface,
1152     LPCGUID lpcGuid)
1153 {
1154     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1155     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1156     return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1157 }
1158
1159 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1160 {
1161     IDirectSound_IDirectSound_QueryInterface,
1162     IDirectSound_IDirectSound_AddRef,
1163     IDirectSound_IDirectSound_Release,
1164     IDirectSound_IDirectSound_CreateSoundBuffer,
1165     IDirectSound_IDirectSound_GetCaps,
1166     IDirectSound_IDirectSound_DuplicateSoundBuffer,
1167     IDirectSound_IDirectSound_SetCooperativeLevel,
1168     IDirectSound_IDirectSound_Compact,
1169     IDirectSound_IDirectSound_GetSpeakerConfig,
1170     IDirectSound_IDirectSound_SetSpeakerConfig,
1171     IDirectSound_IDirectSound_Initialize
1172 };
1173
1174 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1175     LPDIRECTSOUND8  pds,
1176     LPDIRECTSOUND * ppds)
1177 {
1178     IDirectSound_IDirectSound * pdsds;
1179     TRACE("(%p,%p)\n",pds,ppds);
1180
1181     if (ppds == NULL) {
1182         ERR("invalid parameter: ppds == NULL\n");
1183         return DSERR_INVALIDPARAM;
1184     }
1185
1186     if (pds == NULL) {
1187         ERR("invalid parameter: pds == NULL\n");
1188         *ppds = NULL;
1189         return DSERR_INVALIDPARAM;
1190     }
1191
1192     pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1193     if (pdsds == NULL) {
1194         WARN("out of memory\n");
1195         *ppds = NULL;
1196         return DSERR_OUTOFMEMORY;
1197     }
1198
1199     pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1200     pdsds->ref = 0;
1201     pdsds->pds = pds;
1202
1203     IDirectSoundImpl_AddRef(pds);
1204     *ppds = (LPDIRECTSOUND)pdsds;
1205
1206     return DS_OK;
1207 }
1208
1209 /*******************************************************************************
1210  *              IDirectSound8_IUnknown
1211  */
1212 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1213     LPUNKNOWN iface,
1214     REFIID riid,
1215     LPVOID * ppobj)
1216 {
1217     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1218     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1219     return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1220 }
1221
1222 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1223     LPUNKNOWN iface)
1224 {
1225     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1226     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1227     return InterlockedIncrement(&(This->ref));
1228 }
1229
1230 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1231     LPUNKNOWN iface)
1232 {
1233     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1234     ULONG ulReturn;
1235     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1236     ulReturn = InterlockedDecrement(&(This->ref));
1237     if (ulReturn == 0) {
1238         IDirectSoundImpl_Release(This->pds);
1239         HeapFree(GetProcessHeap(),0,This);
1240         TRACE("(%p) released\n",This);
1241     }
1242     return ulReturn;
1243 }
1244
1245 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1246 {
1247     IDirectSound8_IUnknown_QueryInterface,
1248     IDirectSound8_IUnknown_AddRef,
1249     IDirectSound8_IUnknown_Release
1250 };
1251
1252 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1253     LPDIRECTSOUND8 pds,
1254     LPUNKNOWN * ppunk)
1255 {
1256     IDirectSound8_IUnknown * pdsunk;
1257     TRACE("(%p,%p)\n",pds,ppunk);
1258
1259     if (ppunk == NULL) {
1260         ERR("invalid parameter: ppunk == NULL\n");
1261         return DSERR_INVALIDPARAM;
1262     }
1263
1264     if (pds == NULL) {
1265         ERR("invalid parameter: pds == NULL\n");
1266         *ppunk = NULL;
1267         return DSERR_INVALIDPARAM;
1268     }
1269
1270     pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1271     if (pdsunk == NULL) {
1272         WARN("out of memory\n");
1273         *ppunk = NULL;
1274         return DSERR_OUTOFMEMORY;
1275     }
1276
1277     pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1278     pdsunk->ref = 0;
1279     pdsunk->pds = pds;
1280
1281     IDirectSoundImpl_AddRef(pds);
1282     *ppunk = (LPUNKNOWN)pdsunk;
1283
1284     return DS_OK;
1285 }
1286
1287 /*******************************************************************************
1288  *              IDirectSound8_IDirectSound
1289  */
1290 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1291     LPDIRECTSOUND iface,
1292     REFIID riid,
1293     LPVOID * ppobj)
1294 {
1295     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1296     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1297     return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1298 }
1299
1300 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1301     LPDIRECTSOUND iface)
1302 {
1303     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1304     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1305     return InterlockedIncrement(&(This->ref));
1306 }
1307
1308 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1309     LPDIRECTSOUND iface)
1310 {
1311     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1312     ULONG ulReturn;
1313     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1314     ulReturn = InterlockedDecrement(&(This->ref));
1315     if (ulReturn == 0) {
1316         IDirectSoundImpl_Release(This->pds);
1317         HeapFree(GetProcessHeap(),0,This);
1318         TRACE("(%p) released\n",This);
1319     }
1320     return ulReturn;
1321 }
1322
1323 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1324     LPDIRECTSOUND iface,
1325     LPCDSBUFFERDESC dsbd,
1326     LPLPDIRECTSOUNDBUFFER ppdsb,
1327     LPUNKNOWN lpunk)
1328 {
1329     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1330     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1331     return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1332 }
1333
1334 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1335     LPDIRECTSOUND iface,
1336     LPDSCAPS lpDSCaps)
1337 {
1338     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1339     TRACE("(%p,%p)\n",This,lpDSCaps);
1340     return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1341 }
1342
1343 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1344     LPDIRECTSOUND iface,
1345     LPDIRECTSOUNDBUFFER psb,
1346     LPLPDIRECTSOUNDBUFFER ppdsb)
1347 {
1348     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1349     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1350     return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1351 }
1352
1353 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1354     LPDIRECTSOUND iface,
1355     HWND hwnd,
1356     DWORD level)
1357 {
1358     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1359     TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1360     return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1361 }
1362
1363 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1364     LPDIRECTSOUND iface)
1365 {
1366     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1367     TRACE("(%p)\n", This);
1368     return IDirectSoundImpl_Compact(This->pds);
1369 }
1370
1371 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1372     LPDIRECTSOUND iface,
1373     LPDWORD lpdwSpeakerConfig)
1374 {
1375     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1376     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1377     return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1378 }
1379
1380 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1381     LPDIRECTSOUND iface,
1382     DWORD config)
1383 {
1384     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1385     TRACE("(%p,0x%08lx)\n",This,config);
1386     return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1387 }
1388
1389 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1390     LPDIRECTSOUND iface,
1391     LPCGUID lpcGuid)
1392 {
1393     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1394     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1395     return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1396 }
1397
1398 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1399 {
1400     IDirectSound8_IDirectSound_QueryInterface,
1401     IDirectSound8_IDirectSound_AddRef,
1402     IDirectSound8_IDirectSound_Release,
1403     IDirectSound8_IDirectSound_CreateSoundBuffer,
1404     IDirectSound8_IDirectSound_GetCaps,
1405     IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1406     IDirectSound8_IDirectSound_SetCooperativeLevel,
1407     IDirectSound8_IDirectSound_Compact,
1408     IDirectSound8_IDirectSound_GetSpeakerConfig,
1409     IDirectSound8_IDirectSound_SetSpeakerConfig,
1410     IDirectSound8_IDirectSound_Initialize
1411 };
1412
1413 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1414     LPDIRECTSOUND8 pds,
1415     LPDIRECTSOUND * ppds)
1416 {
1417     IDirectSound8_IDirectSound * pdsds;
1418     TRACE("(%p,%p)\n",pds,ppds);
1419
1420     if (ppds == NULL) {
1421         ERR("invalid parameter: ppds == NULL\n");
1422         return DSERR_INVALIDPARAM;
1423     }
1424
1425     if (pds == NULL) {
1426         ERR("invalid parameter: pds == NULL\n");
1427         *ppds = NULL;
1428         return DSERR_INVALIDPARAM;
1429     }
1430
1431     pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1432     if (pdsds == NULL) {
1433         WARN("out of memory\n");
1434         *ppds = NULL;
1435         return DSERR_OUTOFMEMORY;
1436     }
1437
1438     pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1439     pdsds->ref = 0;
1440     pdsds->pds = pds;
1441
1442     IDirectSoundImpl_AddRef(pds);
1443     *ppds = (LPDIRECTSOUND)pdsds;
1444
1445     return DS_OK;
1446 }
1447
1448 /*******************************************************************************
1449  *              IDirectSound8_IDirectSound8
1450  */
1451 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1452     LPDIRECTSOUND8 iface,
1453     REFIID riid,
1454     LPVOID * ppobj)
1455 {
1456     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1457     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1458     return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1459 }
1460
1461 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1462     LPDIRECTSOUND8 iface)
1463 {
1464     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1465     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1466     return InterlockedIncrement(&(This->ref));
1467 }
1468
1469 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1470     LPDIRECTSOUND8 iface)
1471 {
1472     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1473     ULONG ulReturn;
1474     TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1475     ulReturn = InterlockedDecrement(&(This->ref));
1476     if (ulReturn == 0) {
1477         IDirectSoundImpl_Release(This->pds);
1478         HeapFree(GetProcessHeap(),0,This);
1479         TRACE("(%p) released\n",This);
1480     }
1481     return ulReturn;
1482 }
1483
1484 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1485     LPDIRECTSOUND8 iface,
1486     LPCDSBUFFERDESC dsbd,
1487     LPLPDIRECTSOUNDBUFFER ppdsb,
1488     LPUNKNOWN lpunk)
1489 {
1490     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1491     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1492     return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1493 }
1494
1495 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1496     LPDIRECTSOUND8 iface,
1497     LPDSCAPS lpDSCaps)
1498 {
1499     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1500     TRACE("(%p,%p)\n",This,lpDSCaps);
1501     return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1502 }
1503
1504 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1505     LPDIRECTSOUND8 iface,
1506     LPDIRECTSOUNDBUFFER psb,
1507     LPLPDIRECTSOUNDBUFFER ppdsb)
1508 {
1509     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1510     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1511     return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1512 }
1513
1514 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1515     LPDIRECTSOUND8 iface,
1516     HWND hwnd,
1517     DWORD level)
1518 {
1519     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1520     TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1521     return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1522 }
1523
1524 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1525     LPDIRECTSOUND8 iface)
1526 {
1527     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1528     TRACE("(%p)\n", This);
1529     return IDirectSoundImpl_Compact(This->pds);
1530 }
1531
1532 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1533     LPDIRECTSOUND8 iface,
1534     LPDWORD lpdwSpeakerConfig)
1535 {
1536     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1537     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1538     return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1539 }
1540
1541 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1542     LPDIRECTSOUND8 iface,
1543     DWORD config)
1544 {
1545     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1546     TRACE("(%p,0x%08lx)\n",This,config);
1547     return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1548 }
1549
1550 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1551     LPDIRECTSOUND8 iface,
1552     LPCGUID lpcGuid)
1553 {
1554     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1555     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1556     return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1557 }
1558
1559 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1560     LPDIRECTSOUND8 iface,
1561     LPDWORD pdwCertified)
1562 {
1563     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1564     TRACE("(%p, %p)\n", This, pdwCertified);
1565     return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1566 }
1567
1568 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1569 {
1570     IDirectSound8_IDirectSound8_QueryInterface,
1571     IDirectSound8_IDirectSound8_AddRef,
1572     IDirectSound8_IDirectSound8_Release,
1573     IDirectSound8_IDirectSound8_CreateSoundBuffer,
1574     IDirectSound8_IDirectSound8_GetCaps,
1575     IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1576     IDirectSound8_IDirectSound8_SetCooperativeLevel,
1577     IDirectSound8_IDirectSound8_Compact,
1578     IDirectSound8_IDirectSound8_GetSpeakerConfig,
1579     IDirectSound8_IDirectSound8_SetSpeakerConfig,
1580     IDirectSound8_IDirectSound8_Initialize,
1581     IDirectSound8_IDirectSound8_VerifyCertification
1582 };
1583
1584 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1585     LPDIRECTSOUND8 pds,
1586     LPDIRECTSOUND8 * ppds)
1587 {
1588     IDirectSound8_IDirectSound8 * pdsds;
1589     TRACE("(%p,%p)\n",pds,ppds);
1590
1591     if (ppds == NULL) {
1592         ERR("invalid parameter: ppds == NULL\n");
1593         return DSERR_INVALIDPARAM;
1594     }
1595
1596     if (pds == NULL) {
1597         ERR("invalid parameter: pds == NULL\n");
1598         *ppds = NULL;
1599         return DSERR_INVALIDPARAM;
1600     }
1601
1602     pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1603     if (pdsds == NULL) {
1604         WARN("out of memory\n");
1605         *ppds = NULL;
1606         return DSERR_OUTOFMEMORY;
1607     }
1608
1609     pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1610     pdsds->ref = 0;
1611     pdsds->pds = pds;
1612
1613     IDirectSoundImpl_AddRef(pds);
1614     *ppds = (LPDIRECTSOUND8)pdsds;
1615
1616     return DS_OK;
1617 }
1618
1619 HRESULT WINAPI DSOUND_Create(
1620     LPCGUID lpcGUID,
1621     LPDIRECTSOUND *ppDS,
1622     IUnknown *pUnkOuter)
1623 {
1624     HRESULT hr;
1625     GUID devGuid;
1626
1627     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1628
1629     if (pUnkOuter != NULL) {
1630         WARN("invalid parameter: pUnkOuter != NULL\n");
1631         return DSERR_INVALIDPARAM;
1632     }
1633
1634     if (ppDS == NULL) {
1635         WARN("invalid parameter: ppDS == NULL\n");
1636         return DSERR_INVALIDPARAM;
1637     }
1638
1639     /* Get dsound configuration */
1640     setup_dsound_options();
1641
1642     /* Default device? */
1643     if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1644         lpcGUID = &DSDEVID_DefaultPlayback;
1645
1646     if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1647         WARN("invalid parameter: lpcGUID\n");
1648         *ppDS = NULL;
1649         return DSERR_INVALIDPARAM;
1650     }
1651
1652     if (dsound) {
1653         if (IsEqualGUID(&devGuid, &dsound->guid)) {
1654             hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1655             if (*ppDS)
1656                 IDirectSound_IDirectSound_AddRef(*ppDS);
1657             else
1658                 WARN("IDirectSound_IDirectSound_Create failed\n");
1659         } else {
1660             ERR("different dsound already opened (only support one sound card at a time now)\n");
1661             *ppDS = NULL;
1662             hr = DSERR_ALLOCATED;
1663         }
1664     } else {
1665         LPDIRECTSOUND8 pDS;
1666         hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1667         if (hr == DS_OK) {
1668             hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1669             if (hr == DS_OK) {
1670                 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1671                 if (*ppDS) {
1672                     IDirectSound_IDirectSound_AddRef(*ppDS);
1673
1674                     dsound = (IDirectSoundImpl*)pDS;
1675                     timeBeginPeriod(DS_TIME_RES);
1676                     dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1677                                        (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1678                 } else {
1679                     WARN("IDirectSound_IDirectSound_Create failed\n");
1680                     IDirectSound8_Release(pDS);
1681                 }
1682             } else {
1683                 WARN("DSOUND_PrimaryCreate failed\n");
1684                 IDirectSound8_Release(pDS);
1685             }
1686         } else
1687             WARN("IDirectSoundImpl_Create failed\n");
1688     }
1689
1690     return hr;
1691 }
1692
1693 /*******************************************************************************
1694  *              DirectSoundCreate (DSOUND.1)
1695  *
1696  *  Creates and initializes a DirectSound interface.
1697  *
1698  *  PARAMS
1699  *     lpcGUID   [I] Address of the GUID that identifies the sound device.
1700  *     ppDS      [O] Address of a variable to receive the interface pointer.
1701  *     pUnkOuter [I] Must be NULL.
1702  *
1703  *  RETURNS
1704  *     Success: DS_OK
1705  *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1706  *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
1707  */
1708 HRESULT WINAPI DirectSoundCreate(
1709     LPCGUID lpcGUID,
1710     LPDIRECTSOUND *ppDS,
1711     IUnknown *pUnkOuter)
1712 {
1713     HRESULT hr;
1714
1715     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1716
1717     hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1718     if (hr == DS_OK)
1719         IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1720
1721     return hr;
1722 }
1723
1724 HRESULT WINAPI DSOUND_Create8(
1725     LPCGUID lpcGUID,
1726     LPDIRECTSOUND8 *ppDS,
1727     IUnknown *pUnkOuter)
1728 {
1729     HRESULT hr;
1730     GUID devGuid;
1731
1732     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1733
1734     if (pUnkOuter != NULL) {
1735         WARN("invalid parameter: pUnkOuter != NULL\n");
1736         return DSERR_INVALIDPARAM;
1737     }
1738
1739     if (ppDS == NULL) {
1740         WARN("invalid parameter: ppDS == NULL\n");
1741         return DSERR_INVALIDPARAM;
1742     }
1743
1744     /* Get dsound configuration */
1745     setup_dsound_options();
1746
1747     /* Default device? */
1748     if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1749         lpcGUID = &DSDEVID_DefaultPlayback;
1750
1751     if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1752         WARN("invalid parameter: lpcGUID\n");
1753         *ppDS = NULL;
1754         return DSERR_INVALIDPARAM;
1755     }
1756
1757     if (dsound) {
1758         if (IsEqualGUID(&devGuid, &dsound->guid)) {
1759             hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1760             if (*ppDS)
1761                 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1762             else
1763                 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1764         } else {
1765             ERR("different dsound already opened (only support one sound card at a time now)\n");
1766             *ppDS = NULL;
1767             hr = DSERR_ALLOCATED;
1768         }
1769     } else {
1770         LPDIRECTSOUND8 pDS;
1771         hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1772         if (hr == DS_OK) {
1773             hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1774             if (hr == DS_OK) {
1775                 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1776                 if (*ppDS) {
1777                     IDirectSound8_IDirectSound8_AddRef(*ppDS);
1778
1779                     dsound = (IDirectSoundImpl*)pDS;
1780                     timeBeginPeriod(DS_TIME_RES);
1781                     dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1782                                        (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1783                 } else {
1784                     WARN("IDirectSound8_IDirectSound8_Create failed\n");
1785                     IDirectSound8_Release(pDS);
1786                 }
1787             } else {
1788                 WARN("DSOUND_PrimaryCreate failed\n");
1789                 IDirectSound8_Release(pDS);
1790             }
1791         } else
1792             WARN("IDirectSoundImpl_Create failed\n");
1793     }
1794
1795     return hr;
1796 }
1797
1798 /*******************************************************************************
1799  *        DirectSoundCreate8 (DSOUND.11)
1800  *
1801  *  Creates and initializes a DirectSound8 interface.
1802  *
1803  *  PARAMS
1804  *     lpcGUID   [I] Address of the GUID that identifies the sound device.
1805  *     ppDS      [O] Address of a variable to receive the interface pointer.
1806  *     pUnkOuter [I] Must be NULL.
1807  *
1808  *  RETURNS
1809  *     Success: DS_OK
1810  *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1811  *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
1812  */
1813 HRESULT WINAPI DirectSoundCreate8(
1814     LPCGUID lpcGUID,
1815     LPDIRECTSOUND8 *ppDS,
1816     IUnknown *pUnkOuter)
1817 {
1818     HRESULT hr;
1819
1820     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1821
1822     hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1823     if (hr == DS_OK)
1824         IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1825
1826     return hr;
1827 }
1828
1829 /*
1830  * Add secondary buffer to buffer list.
1831  * Gets exclusive access to buffer for writing.
1832  */
1833 HRESULT DSOUND_AddBuffer(
1834     IDirectSoundImpl * pDS,
1835     IDirectSoundBufferImpl * pDSB)
1836 {
1837     IDirectSoundBufferImpl **newbuffers;
1838     HRESULT hr = DS_OK;
1839
1840     TRACE("(%p, %p)\n", pDS, pDSB);
1841
1842     RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1843
1844     if (pDS->buffers)
1845         newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1846     else
1847         newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1848
1849     if (newbuffers) {
1850         pDS->buffers = newbuffers;
1851         pDS->buffers[pDS->nrofbuffers] = pDSB;
1852         pDS->nrofbuffers++;
1853         TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1854     } else {
1855         ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
1856         hr = DSERR_OUTOFMEMORY;
1857     }
1858
1859     RtlReleaseResource(&(pDS->buffer_list_lock));
1860
1861     return hr;
1862 }
1863
1864 /*
1865  * Remove secondary buffer from buffer list.
1866  * Gets exclusive access to buffer for writing.
1867  */
1868 HRESULT DSOUND_RemoveBuffer(
1869     IDirectSoundImpl * pDS,
1870     IDirectSoundBufferImpl * pDSB)
1871 {
1872     int i;
1873     HRESULT hr = DS_OK;
1874
1875     TRACE("(%p, %p)\n", pDS, pDSB);
1876
1877     RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1878
1879     for (i = 0; i < pDS->nrofbuffers; i++)
1880         if (pDS->buffers[i] == pDSB)
1881             break;
1882
1883     if (i < pDS->nrofbuffers) {
1884         /* Put the last buffer of the list in the (now empty) position */
1885         pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
1886         pDS->nrofbuffers--;
1887         pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
1888         TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1889     }
1890
1891     if (pDS->nrofbuffers == 0) {
1892         HeapFree(GetProcessHeap(),0,pDS->buffers);
1893         pDS->buffers = NULL;
1894     }
1895
1896     RtlReleaseResource(&(pDS->buffer_list_lock));
1897
1898     return hr;
1899 }