3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 * Copyright 2004 Robert Reif
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.
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.
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
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
34 #include "wine/debug.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
41 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
42 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
43 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
44 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
45 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
47 static const char * dumpCooperativeLevel(DWORD level
)
49 static char unknown
[32];
50 #define LE(x) case x: return #x
55 LE(DSSCL_WRITEPRIMARY
);
58 sprintf(unknown
, "Unknown(%08lx)", level
);
62 static void _dump_DSCAPS(DWORD xmask
) {
67 #define FE(x) { x, #x },
68 FE(DSCAPS_PRIMARYMONO
)
69 FE(DSCAPS_PRIMARYSTEREO
)
70 FE(DSCAPS_PRIMARY8BIT
)
71 FE(DSCAPS_PRIMARY16BIT
)
72 FE(DSCAPS_CONTINUOUSRATE
)
75 FE(DSCAPS_SECONDARYMONO
)
76 FE(DSCAPS_SECONDARYSTEREO
)
77 FE(DSCAPS_SECONDARY8BIT
)
78 FE(DSCAPS_SECONDARY16BIT
)
83 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
84 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
85 DPRINTF("%s ",flags
[i
].name
);
88 static void _dump_DSBCAPS(DWORD xmask
) {
93 #define FE(x) { x, #x },
94 FE(DSBCAPS_PRIMARYBUFFER
)
96 FE(DSBCAPS_LOCHARDWARE
)
97 FE(DSBCAPS_LOCSOFTWARE
)
99 FE(DSBCAPS_CTRLFREQUENCY
)
101 FE(DSBCAPS_CTRLVOLUME
)
102 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
103 FE(DSBCAPS_STICKYFOCUS
)
104 FE(DSBCAPS_GLOBALFOCUS
)
105 FE(DSBCAPS_GETCURRENTPOSITION2
)
106 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
111 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
112 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
113 DPRINTF("%s ",flags
[i
].name
);
116 /*******************************************************************************
117 * IDirectSoundImpl_DirectSound
119 static HRESULT WINAPI
IDirectSoundImpl_QueryInterface(
120 LPDIRECTSOUND8 iface
,
124 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppobj
);
125 FIXME("shouldn't be called directly\n");
126 return E_NOINTERFACE
;
129 static HRESULT WINAPI
DSOUND_QueryInterface(
130 LPDIRECTSOUND8 iface
,
134 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
135 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
138 WARN("invalid parameter\n");
142 if (IsEqualIID(riid
, &IID_IUnknown
)) {
143 if (!This
->pUnknown
) {
144 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
145 if (!This
->pUnknown
) {
146 WARN("IDirectSound_IUnknown_Create() failed\n");
148 return E_NOINTERFACE
;
151 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
152 *ppobj
= This
->pUnknown
;
154 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
156 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
158 WARN("IDirectSound_IDirectSound_Create() failed\n");
160 return E_NOINTERFACE
;
163 IDirectSound_IDirectSound_AddRef(This
->pDS
);
169 WARN("Unknown IID %s\n",debugstr_guid(riid
));
170 return E_NOINTERFACE
;
173 static HRESULT WINAPI
DSOUND_QueryInterface8(
174 LPDIRECTSOUND8 iface
,
178 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
179 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
182 WARN("invalid parameter\n");
186 if (IsEqualIID(riid
, &IID_IUnknown
)) {
187 if (!This
->pUnknown
) {
188 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
189 if (!This
->pUnknown
) {
190 WARN("IDirectSound8_IUnknown_Create() failed\n");
192 return E_NOINTERFACE
;
195 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
196 *ppobj
= This
->pUnknown
;
198 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
200 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
202 WARN("IDirectSound8_IDirectSound_Create() failed\n");
204 return E_NOINTERFACE
;
207 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
210 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
212 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
214 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
216 return E_NOINTERFACE
;
219 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
225 WARN("Unknown IID %s\n",debugstr_guid(riid
));
226 return E_NOINTERFACE
;
229 static ULONG WINAPI
IDirectSoundImpl_AddRef(
230 LPDIRECTSOUND8 iface
)
232 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
233 ULONG ref
= InterlockedIncrement(&(This
->ref
));
234 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
238 static ULONG WINAPI
IDirectSoundImpl_Release(
239 LPDIRECTSOUND8 iface
)
241 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
242 ULONG ref
= InterlockedDecrement(&(This
->ref
));
243 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
249 timeKillEvent(This
->timerID
);
250 timeEndPeriod(DS_TIME_RES
);
251 /* wait for timer to expire */
252 Sleep(DS_TIME_RES
+1);
254 /* The sleep above should have allowed the timer process to expire
255 * but try to grab the lock just in case. Can't hold lock because
256 * IDirectSoundBufferImpl_Destroy also grabs the lock */
257 RtlAcquireResourceShared(&(This
->buffer_list_lock
), TRUE
);
258 RtlReleaseResource(&(This
->buffer_list_lock
));
260 /* It is allowed to release this object even when buffers are playing */
262 WARN("%d secondary buffers not released\n", This
->nrofbuffers
);
263 for( i
=0;i
<This
->nrofbuffers
;i
++)
264 IDirectSoundBufferImpl_Destroy(This
->buffers
[i
]);
268 WARN("primary buffer not released\n");
269 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)This
->primary
);
272 hres
= DSOUND_PrimaryDestroy(This
);
274 WARN("DSOUND_PrimaryDestroy failed\n");
277 IDsDriver_Close(This
->driver
);
279 if (This
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
280 waveOutClose(This
->hwo
);
283 IDsDriver_Release(This
->driver
);
285 HeapFree(GetProcessHeap(),0,This
->tmp_buffer
);
286 HeapFree(GetProcessHeap(),0,This
->buffer
);
287 RtlDeleteResource(&This
->buffer_list_lock
);
288 This
->mixlock
.DebugInfo
->Spare
[1] = 0;
289 DeleteCriticalSection(&This
->mixlock
);
290 HeapFree(GetProcessHeap(),0,This
);
292 TRACE("(%p) released\n", This
);
297 static HRESULT WINAPI
IDirectSoundImpl_CreateSoundBuffer(
298 LPDIRECTSOUND8 iface
,
299 LPCDSBUFFERDESC dsbd
,
300 LPLPDIRECTSOUNDBUFFER ppdsb
,
303 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
304 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
305 FIXME("shouldn't be called directly\n");
306 return DSERR_GENERIC
;
309 static HRESULT WINAPI
DSOUND_CreateSoundBuffer(
310 LPDIRECTSOUND8 iface
,
311 LPCDSBUFFERDESC dsbd
,
312 LPLPDIRECTSOUNDBUFFER ppdsb
,
316 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
317 HRESULT hres
= DS_OK
;
318 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
321 WARN("invalid parameter: This == NULL\n");
322 return DSERR_INVALIDPARAM
;
325 if (This
->initialized
== FALSE
) {
326 WARN("not initialized\n");
327 return DSERR_UNINITIALIZED
;
331 WARN("invalid parameter: dsbd == NULL\n");
332 return DSERR_INVALIDPARAM
;
335 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
336 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
337 WARN("invalid parameter: dsbd\n");
338 return DSERR_INVALIDPARAM
;
342 WARN("invalid parameter: ppdsb == NULL\n");
343 return DSERR_INVALIDPARAM
;
346 if (TRACE_ON(dsound
)) {
347 TRACE("(structsize=%ld)\n",dsbd
->dwSize
);
348 TRACE("(flags=0x%08lx:\n",dsbd
->dwFlags
);
349 _dump_DSBCAPS(dsbd
->dwFlags
);
351 TRACE("(bufferbytes=%ld)\n",dsbd
->dwBufferBytes
);
352 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
355 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
356 if (dsbd
->lpwfxFormat
!= NULL
) {
357 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
359 return DSERR_INVALIDPARAM
;
363 WARN("Primary Buffer already created\n");
364 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->primary
));
365 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->primary
);
368 hres
= PrimaryBufferImpl_Create(This
, (PrimaryBufferImpl
**)&(This
->primary
), &(This
->dsbd
));
370 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->primary
));
371 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->primary
);
373 WARN("PrimaryBufferImpl_Create failed\n");
376 IDirectSoundBufferImpl
* dsb
;
378 if (dsbd
->lpwfxFormat
== NULL
) {
379 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
380 "secondary buffer\n");
381 return DSERR_INVALIDPARAM
;
384 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
385 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
386 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
387 dsbd
->lpwfxFormat
->nSamplesPerSec
,
388 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
389 dsbd
->lpwfxFormat
->nBlockAlign
,
390 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
392 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
393 WARN("invalid parameter: 3D buffer format must be mono\n");
394 return DSERR_INVALIDPARAM
;
397 hres
= IDirectSoundBufferImpl_Create(This
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
399 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
401 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
402 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
404 WARN("SecondaryBufferImpl_Create failed\n");
406 WARN("IDirectSoundBufferImpl_Create failed\n");
412 static HRESULT WINAPI
IDirectSoundImpl_GetCaps(
413 LPDIRECTSOUND8 iface
,
416 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
417 TRACE("(%p,%p)\n",This
,lpDSCaps
);
420 WARN("invalid parameter: This == NULL\n");
421 return DSERR_INVALIDPARAM
;
424 if (This
->initialized
== FALSE
) {
425 WARN("not initialized\n");
426 return DSERR_UNINITIALIZED
;
429 if (lpDSCaps
== NULL
) {
430 WARN("invalid parameter: lpDSCaps = NULL\n");
431 return DSERR_INVALIDPARAM
;
434 /* check if there is enough room */
435 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
436 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
437 lpDSCaps
->dwSize
, sizeof(*lpDSCaps
));
438 return DSERR_INVALIDPARAM
;
441 lpDSCaps
->dwFlags
= This
->drvcaps
.dwFlags
;
442 if (TRACE_ON(dsound
)) {
443 TRACE("(flags=0x%08lx:\n",lpDSCaps
->dwFlags
);
444 _dump_DSCAPS(lpDSCaps
->dwFlags
);
447 lpDSCaps
->dwMinSecondarySampleRate
= This
->drvcaps
.dwMinSecondarySampleRate
;
448 lpDSCaps
->dwMaxSecondarySampleRate
= This
->drvcaps
.dwMaxSecondarySampleRate
;
449 lpDSCaps
->dwPrimaryBuffers
= This
->drvcaps
.dwPrimaryBuffers
;
450 lpDSCaps
->dwMaxHwMixingAllBuffers
= This
->drvcaps
.dwMaxHwMixingAllBuffers
;
451 lpDSCaps
->dwMaxHwMixingStaticBuffers
= This
->drvcaps
.dwMaxHwMixingStaticBuffers
;
452 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= This
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
453 lpDSCaps
->dwFreeHwMixingAllBuffers
= This
->drvcaps
.dwFreeHwMixingAllBuffers
;
454 lpDSCaps
->dwFreeHwMixingStaticBuffers
= This
->drvcaps
.dwFreeHwMixingStaticBuffers
;
455 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= This
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
456 lpDSCaps
->dwMaxHw3DAllBuffers
= This
->drvcaps
.dwMaxHw3DAllBuffers
;
457 lpDSCaps
->dwMaxHw3DStaticBuffers
= This
->drvcaps
.dwMaxHw3DStaticBuffers
;
458 lpDSCaps
->dwMaxHw3DStreamingBuffers
= This
->drvcaps
.dwMaxHw3DStreamingBuffers
;
459 lpDSCaps
->dwFreeHw3DAllBuffers
= This
->drvcaps
.dwFreeHw3DAllBuffers
;
460 lpDSCaps
->dwFreeHw3DStaticBuffers
= This
->drvcaps
.dwFreeHw3DStaticBuffers
;
461 lpDSCaps
->dwFreeHw3DStreamingBuffers
= This
->drvcaps
.dwFreeHw3DStreamingBuffers
;
462 lpDSCaps
->dwTotalHwMemBytes
= This
->drvcaps
.dwTotalHwMemBytes
;
463 lpDSCaps
->dwFreeHwMemBytes
= This
->drvcaps
.dwFreeHwMemBytes
;
464 lpDSCaps
->dwMaxContigFreeHwMemBytes
= This
->drvcaps
.dwMaxContigFreeHwMemBytes
;
466 /* driver doesn't have these */
467 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
468 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
473 static HRESULT WINAPI
IDirectSoundImpl_DuplicateSoundBuffer(
474 LPDIRECTSOUND8 iface
,
475 LPDIRECTSOUNDBUFFER psb
,
476 LPLPDIRECTSOUNDBUFFER ppdsb
)
478 IDirectSoundBufferImpl
* pdsb
;
479 IDirectSoundBufferImpl
* dsb
;
480 HRESULT hres
= DS_OK
;
482 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
484 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
487 WARN("invalid parameter: This == NULL\n");
488 return DSERR_INVALIDPARAM
;
491 if (This
->initialized
== FALSE
) {
492 WARN("not initialized\n");
493 return DSERR_UNINITIALIZED
;
497 WARN("invalid parameter: psb == NULL\n");
498 return DSERR_INVALIDPARAM
;
502 WARN("invalid parameter: ppdsb == NULL\n");
503 return DSERR_INVALIDPARAM
;
506 /* FIXME: hack to make sure we have a secondary buffer */
507 if ((DWORD
)((SecondaryBufferImpl
*)psb
)->dsb
== (DWORD
)This
) {
508 WARN("trying to duplicate primary buffer\n");
510 return DSERR_INVALIDCALL
;
513 pdsb
= ((SecondaryBufferImpl
*)psb
)->dsb
;
515 dsb
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(*dsb
));
518 WARN("out of memory\n");
520 return DSERR_OUTOFMEMORY
;
523 CopyMemory(dsb
, pdsb
, sizeof(IDirectSoundBufferImpl
));
526 TRACE("duplicating hardware buffer\n");
528 hres
= IDsDriver_DuplicateSoundBuffer(This
->driver
, pdsb
->hwbuf
, (LPVOID
*)&dsb
->hwbuf
);
530 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
532 /* allocate buffer */
533 if (This
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
534 dsb
->buffer
= HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb
->buffer
)));
535 if (dsb
->buffer
== NULL
) {
536 WARN("out of memory\n");
537 HeapFree(GetProcessHeap(),0,dsb
);
539 return DSERR_OUTOFMEMORY
;
542 dsb
->buffer
->memory
= HeapAlloc(GetProcessHeap(),0,dsb
->buflen
);
543 if (dsb
->buffer
->memory
== NULL
) {
544 WARN("out of memory\n");
545 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
546 HeapFree(GetProcessHeap(),0,dsb
);
548 return DSERR_OUTOFMEMORY
;
550 dsb
->buffer
->ref
= 1;
552 /* FIXME: copy buffer ? */
561 dsb
->state
= STATE_STOPPED
;
566 dsb
->iks
= NULL
; /* FIXME? */
569 /* variable sized struct so calculate size based on format */
570 size
= sizeof(WAVEFORMATEX
) + pdsb
->pwfx
->cbSize
;
572 dsb
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
573 if (dsb
->pwfx
== NULL
) {
574 WARN("out of memory\n");
575 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
576 HeapFree(GetProcessHeap(),0,dsb
);
578 return DSERR_OUTOFMEMORY
;
581 CopyMemory(dsb
->pwfx
, pdsb
->pwfx
, size
);
583 InitializeCriticalSection(&(dsb
->lock
));
584 dsb
->lock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUNDBUFFER_lock";
586 /* register buffer */
587 hres
= DSOUND_AddBuffer(This
, dsb
);
589 IDirectSoundBuffer8_Release(psb
);
590 dsb
->lock
.DebugInfo
->Spare
[1] = 0;
591 DeleteCriticalSection(&(dsb
->lock
));
592 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
593 HeapFree(GetProcessHeap(),0,dsb
->pwfx
);
594 HeapFree(GetProcessHeap(),0,dsb
);
597 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
599 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
600 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
602 WARN("SecondaryBufferImpl_Create failed\n");
608 static HRESULT WINAPI
IDirectSoundImpl_SetCooperativeLevel(
609 LPDIRECTSOUND8 iface
,
613 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
614 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
616 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
617 FIXME("level=%s not fully supported\n",
618 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
620 This
->priolevel
= level
;
624 static HRESULT WINAPI
IDirectSoundImpl_Compact(
625 LPDIRECTSOUND8 iface
)
627 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
628 TRACE("(%p)\n",This
);
630 if (This
->initialized
== FALSE
) {
631 WARN("not initialized\n");
632 return DSERR_UNINITIALIZED
;
635 if (This
->priolevel
!= DSSCL_PRIORITY
) {
636 WARN("incorrect priority level\n");
637 return DSERR_PRIOLEVELNEEDED
;
643 static HRESULT WINAPI
IDirectSoundImpl_GetSpeakerConfig(
644 LPDIRECTSOUND8 iface
,
645 LPDWORD lpdwSpeakerConfig
)
647 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
648 TRACE("(%p, %p)\n",This
,lpdwSpeakerConfig
);
650 if (This
->initialized
== FALSE
) {
651 WARN("not initialized\n");
652 return DSERR_UNINITIALIZED
;
655 if (lpdwSpeakerConfig
== NULL
) {
656 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
657 return DSERR_INVALIDPARAM
;
660 WARN("not fully functional\n");
661 *lpdwSpeakerConfig
= This
->speaker_config
;
665 static HRESULT WINAPI
IDirectSoundImpl_SetSpeakerConfig(
666 LPDIRECTSOUND8 iface
,
669 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
670 TRACE("(%p,0x%08lx)\n",This
,config
);
672 if (This
->initialized
== FALSE
) {
673 WARN("not initialized\n");
674 return DSERR_UNINITIALIZED
;
677 This
->speaker_config
= config
;
678 WARN("not fully functional\n");
682 static HRESULT WINAPI
IDirectSoundImpl_Initialize(
683 LPDIRECTSOUND8 iface
,
686 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
687 TRACE("(%p,%s)\n",This
,debugstr_guid(lpcGuid
));
689 This
->initialized
= TRUE
;
694 static HRESULT WINAPI
IDirectSoundImpl_VerifyCertification(
695 LPDIRECTSOUND8 iface
,
696 LPDWORD pdwCertified
)
698 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
699 TRACE("(%p, %p)\n",This
,pdwCertified
);
701 if (This
->initialized
== FALSE
) {
702 WARN("not initialized\n");
703 return DSERR_UNINITIALIZED
;
706 if (This
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
707 *pdwCertified
= DS_CERTIFIED
;
709 *pdwCertified
= DS_UNCERTIFIED
;
713 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl
=
715 IDirectSoundImpl_QueryInterface
,
716 IDirectSoundImpl_AddRef
,
717 IDirectSoundImpl_Release
,
718 IDirectSoundImpl_CreateSoundBuffer
,
719 IDirectSoundImpl_GetCaps
,
720 IDirectSoundImpl_DuplicateSoundBuffer
,
721 IDirectSoundImpl_SetCooperativeLevel
,
722 IDirectSoundImpl_Compact
,
723 IDirectSoundImpl_GetSpeakerConfig
,
724 IDirectSoundImpl_SetSpeakerConfig
,
725 IDirectSoundImpl_Initialize
,
726 IDirectSoundImpl_VerifyCertification
729 HRESULT WINAPI
IDirectSoundImpl_Create(
731 LPDIRECTSOUND8
* ppDS
)
734 PIDSDRIVER drv
= NULL
;
735 IDirectSoundImpl
* pDS
;
737 BOOLEAN found
= FALSE
;
738 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID
),ppDS
);
740 /* Enumerate WINMM audio devices and find the one we want */
741 wodn
= waveOutGetNumDevs();
745 return DSERR_NODRIVER
;
748 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID
));
750 for (wod
=0; wod
<wodn
; wod
++) {
751 if (IsEqualGUID( lpcGUID
, &renderer_guids
[wod
])) {
757 if (found
== FALSE
) {
758 WARN("No device found matching given ID!\n");
760 return DSERR_NODRIVER
;
763 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
764 waveOutMessage((HWAVEOUT
)wod
, DRV_QUERYDSOUNDIFACE
, (DWORD
)&drv
, 0);
766 /* Disable the direct sound driver to force emulation if requested. */
767 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
770 /* Allocate memory */
771 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
773 WARN("out of memory\n");
775 return DSERR_OUTOFMEMORY
;
778 pDS
->lpVtbl
= &IDirectSoundImpl_Vtbl
;
782 pDS
->priolevel
= DSSCL_NORMAL
;
788 pDS
->state
= STATE_STOPPED
;
789 pDS
->nrofbuffers
= 0;
792 pDS
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
793 pDS
->initialized
= FALSE
;
794 pDS
->tmp_buffer
= NULL
;
795 pDS
->tmp_buffer_len
= 0;
797 /* 3D listener initial parameters */
798 pDS
->listener
= NULL
;
799 pDS
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
800 pDS
->ds3dl
.vPosition
.x
= 0.0;
801 pDS
->ds3dl
.vPosition
.y
= 0.0;
802 pDS
->ds3dl
.vPosition
.z
= 0.0;
803 pDS
->ds3dl
.vVelocity
.x
= 0.0;
804 pDS
->ds3dl
.vVelocity
.y
= 0.0;
805 pDS
->ds3dl
.vVelocity
.z
= 0.0;
806 pDS
->ds3dl
.vOrientFront
.x
= 0.0;
807 pDS
->ds3dl
.vOrientFront
.y
= 0.0;
808 pDS
->ds3dl
.vOrientFront
.z
= 1.0;
809 pDS
->ds3dl
.vOrientTop
.x
= 0.0;
810 pDS
->ds3dl
.vOrientTop
.y
= 1.0;
811 pDS
->ds3dl
.vOrientTop
.z
= 0.0;
812 pDS
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
813 pDS
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
814 pDS
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
816 pDS
->prebuf
= ds_snd_queue_max
;
817 pDS
->guid
= *lpcGUID
;
819 /* Get driver description */
821 err
= IDsDriver_GetDriverDesc(drv
,&(pDS
->drvdesc
));
823 WARN("IDsDriver_GetDriverDesc failed\n");
824 HeapFree(GetProcessHeap(),0,pDS
);
829 /* if no DirectSound interface available, use WINMM API instead */
830 pDS
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
| DSDDESC_DOMMSYSTEMSETFORMAT
;
833 pDS
->drvdesc
.dnDevNode
= wod
;
835 /* Set default wave format (may need it for waveOutOpen) */
836 pDS
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
837 if (pDS
->pwfx
== NULL
) {
838 WARN("out of memory\n");
839 HeapFree(GetProcessHeap(),0,pDS
);
841 return DSERR_OUTOFMEMORY
;
844 pDS
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
845 /* We rely on the sound driver to return the actual sound format of
846 * the device if it does not support 22050x8x2 and is given the
847 * WAVE_DIRECTSOUND flag.
849 pDS
->pwfx
->nSamplesPerSec
= 22050;
850 pDS
->pwfx
->wBitsPerSample
= 8;
851 pDS
->pwfx
->nChannels
= 2;
852 pDS
->pwfx
->nBlockAlign
= pDS
->pwfx
->wBitsPerSample
* pDS
->pwfx
->nChannels
/ 8;
853 pDS
->pwfx
->nAvgBytesPerSec
= pDS
->pwfx
->nSamplesPerSec
* pDS
->pwfx
->nBlockAlign
;
854 pDS
->pwfx
->cbSize
= 0;
856 /* If the driver requests being opened through MMSYSTEM
857 * (which is recommended by the DDK), it is supposed to happen
858 * before the DirectSound interface is opened */
859 if (pDS
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
861 DWORD flags
= CALLBACK_FUNCTION
;
863 /* disable direct sound if requested */
864 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
865 flags
|= WAVE_DIRECTSOUND
;
867 err
= mmErr(waveOutOpen(&(pDS
->hwo
),
868 pDS
->drvdesc
.dnDevNode
, pDS
->pwfx
,
869 (DWORD
)DSOUND_callback
, (DWORD
)pDS
,
872 WARN("waveOutOpen failed\n");
873 HeapFree(GetProcessHeap(),0,pDS
);
880 err
= IDsDriver_Open(drv
);
882 WARN("IDsDriver_Open failed\n");
883 HeapFree(GetProcessHeap(),0,pDS
);
888 /* the driver is now open, so it's now allowed to call GetCaps */
889 err
= IDsDriver_GetCaps(drv
,&(pDS
->drvcaps
));
891 WARN("IDsDriver_GetCaps failed\n");
892 HeapFree(GetProcessHeap(),0,pDS
);
898 err
= mmErr(waveOutGetDevCapsA(pDS
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
900 WARN("waveOutGetDevCaps failed\n");
901 HeapFree(GetProcessHeap(),0,pDS
);
905 ZeroMemory(&pDS
->drvcaps
, sizeof(pDS
->drvcaps
));
906 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
907 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
908 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
909 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
910 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
911 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
912 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
914 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
915 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
916 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
917 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
918 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
919 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
920 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
922 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
923 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
924 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
925 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
926 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
927 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
928 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
930 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
931 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
932 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
933 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
934 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
935 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
936 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
939 pDS
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
940 pDS
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
941 pDS
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
942 pDS
->drvcaps
.dwPrimaryBuffers
= 1;
945 InitializeCriticalSection(&(pDS
->mixlock
));
946 pDS
->mixlock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUND_mixlock";
948 RtlInitializeResource(&(pDS
->buffer_list_lock
));
950 *ppDS
= (LPDIRECTSOUND8
)pDS
;
954 /*******************************************************************************
955 * IDirectSound_IUnknown
957 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
962 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
963 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
964 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
967 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
970 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
971 ULONG ref
= InterlockedIncrement(&(This
->ref
));
972 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
976 static ULONG WINAPI
IDirectSound_IUnknown_Release(
979 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
980 ULONG ref
= InterlockedDecrement(&(This
->ref
));
981 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
983 IDirectSoundImpl_Release(This
->pds
);
984 HeapFree(GetProcessHeap(), 0, This
);
985 TRACE("(%p) released\n", This
);
990 static IUnknownVtbl DirectSound_Unknown_Vtbl
=
992 IDirectSound_IUnknown_QueryInterface
,
993 IDirectSound_IUnknown_AddRef
,
994 IDirectSound_IUnknown_Release
997 HRESULT WINAPI
IDirectSound_IUnknown_Create(
1001 IDirectSound_IUnknown
* pdsunk
;
1002 TRACE("(%p,%p)\n",pds
,ppunk
);
1004 if (ppunk
== NULL
) {
1005 ERR("invalid parameter: ppunk == NULL\n");
1006 return DSERR_INVALIDPARAM
;
1010 ERR("invalid parameter: pds == NULL\n");
1012 return DSERR_INVALIDPARAM
;
1015 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1016 if (pdsunk
== NULL
) {
1017 WARN("out of memory\n");
1019 return DSERR_OUTOFMEMORY
;
1022 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
1026 IDirectSoundImpl_AddRef(pds
);
1027 *ppunk
= (LPUNKNOWN
)pdsunk
;
1032 /*******************************************************************************
1033 * IDirectSound_IDirectSound
1035 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
1036 LPDIRECTSOUND iface
,
1040 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1041 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1042 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
1045 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
1046 LPDIRECTSOUND iface
)
1048 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1049 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1050 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1054 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
1055 LPDIRECTSOUND iface
)
1057 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1058 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1059 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1061 IDirectSoundImpl_Release(This
->pds
);
1062 HeapFree(GetProcessHeap(), 0, This
);
1063 TRACE("(%p) released\n", This
);
1068 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
1069 LPDIRECTSOUND iface
,
1070 LPCDSBUFFERDESC dsbd
,
1071 LPLPDIRECTSOUNDBUFFER ppdsb
,
1074 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1075 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1076 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,FALSE
);
1079 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
1080 LPDIRECTSOUND iface
,
1083 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1084 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1085 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1088 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
1089 LPDIRECTSOUND iface
,
1090 LPDIRECTSOUNDBUFFER psb
,
1091 LPLPDIRECTSOUNDBUFFER ppdsb
)
1093 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1094 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1095 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1098 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
1099 LPDIRECTSOUND iface
,
1103 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1104 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1105 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1108 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
1109 LPDIRECTSOUND iface
)
1111 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1112 TRACE("(%p)\n", This
);
1113 return IDirectSoundImpl_Compact(This
->pds
);
1116 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
1117 LPDIRECTSOUND iface
,
1118 LPDWORD lpdwSpeakerConfig
)
1120 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1121 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1122 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1125 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
1126 LPDIRECTSOUND iface
,
1129 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1130 TRACE("(%p,0x%08lx)\n",This
,config
);
1131 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1134 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
1135 LPDIRECTSOUND iface
,
1138 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1139 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1140 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1143 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
1145 IDirectSound_IDirectSound_QueryInterface
,
1146 IDirectSound_IDirectSound_AddRef
,
1147 IDirectSound_IDirectSound_Release
,
1148 IDirectSound_IDirectSound_CreateSoundBuffer
,
1149 IDirectSound_IDirectSound_GetCaps
,
1150 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
1151 IDirectSound_IDirectSound_SetCooperativeLevel
,
1152 IDirectSound_IDirectSound_Compact
,
1153 IDirectSound_IDirectSound_GetSpeakerConfig
,
1154 IDirectSound_IDirectSound_SetSpeakerConfig
,
1155 IDirectSound_IDirectSound_Initialize
1158 HRESULT WINAPI
IDirectSound_IDirectSound_Create(
1160 LPDIRECTSOUND
* ppds
)
1162 IDirectSound_IDirectSound
* pdsds
;
1163 TRACE("(%p,%p)\n",pds
,ppds
);
1166 ERR("invalid parameter: ppds == NULL\n");
1167 return DSERR_INVALIDPARAM
;
1171 ERR("invalid parameter: pds == NULL\n");
1173 return DSERR_INVALIDPARAM
;
1176 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1177 if (pdsds
== NULL
) {
1178 WARN("out of memory\n");
1180 return DSERR_OUTOFMEMORY
;
1183 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
1187 IDirectSoundImpl_AddRef(pds
);
1188 *ppds
= (LPDIRECTSOUND
)pdsds
;
1193 /*******************************************************************************
1194 * IDirectSound8_IUnknown
1196 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
1201 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1202 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1203 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1206 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
1209 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1210 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1211 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1215 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
1218 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1219 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1220 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1222 IDirectSoundImpl_Release(This
->pds
);
1223 HeapFree(GetProcessHeap(), 0, This
);
1224 TRACE("(%p) released\n", This
);
1229 static IUnknownVtbl DirectSound8_Unknown_Vtbl
=
1231 IDirectSound8_IUnknown_QueryInterface
,
1232 IDirectSound8_IUnknown_AddRef
,
1233 IDirectSound8_IUnknown_Release
1236 HRESULT WINAPI
IDirectSound8_IUnknown_Create(
1240 IDirectSound8_IUnknown
* pdsunk
;
1241 TRACE("(%p,%p)\n",pds
,ppunk
);
1243 if (ppunk
== NULL
) {
1244 ERR("invalid parameter: ppunk == NULL\n");
1245 return DSERR_INVALIDPARAM
;
1249 ERR("invalid parameter: pds == NULL\n");
1251 return DSERR_INVALIDPARAM
;
1254 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1255 if (pdsunk
== NULL
) {
1256 WARN("out of memory\n");
1258 return DSERR_OUTOFMEMORY
;
1261 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
1265 IDirectSoundImpl_AddRef(pds
);
1266 *ppunk
= (LPUNKNOWN
)pdsunk
;
1271 /*******************************************************************************
1272 * IDirectSound8_IDirectSound
1274 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
1275 LPDIRECTSOUND iface
,
1279 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1280 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1281 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1284 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
1285 LPDIRECTSOUND iface
)
1287 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1288 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1289 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1293 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
1294 LPDIRECTSOUND iface
)
1296 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1297 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1298 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1300 IDirectSoundImpl_Release(This
->pds
);
1301 HeapFree(GetProcessHeap(), 0, This
);
1302 TRACE("(%p) released\n", This
);
1307 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
1308 LPDIRECTSOUND iface
,
1309 LPCDSBUFFERDESC dsbd
,
1310 LPLPDIRECTSOUNDBUFFER ppdsb
,
1313 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1314 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1315 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,TRUE
);
1318 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
1319 LPDIRECTSOUND iface
,
1322 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1323 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1324 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1327 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1328 LPDIRECTSOUND iface
,
1329 LPDIRECTSOUNDBUFFER psb
,
1330 LPLPDIRECTSOUNDBUFFER ppdsb
)
1332 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1333 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1334 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1337 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
1338 LPDIRECTSOUND iface
,
1342 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1343 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1344 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1347 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
1348 LPDIRECTSOUND iface
)
1350 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1351 TRACE("(%p)\n", This
);
1352 return IDirectSoundImpl_Compact(This
->pds
);
1355 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
1356 LPDIRECTSOUND iface
,
1357 LPDWORD lpdwSpeakerConfig
)
1359 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1360 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1361 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1364 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
1365 LPDIRECTSOUND iface
,
1368 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1369 TRACE("(%p,0x%08lx)\n",This
,config
);
1370 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1373 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
1374 LPDIRECTSOUND iface
,
1377 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1378 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1379 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1382 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
1384 IDirectSound8_IDirectSound_QueryInterface
,
1385 IDirectSound8_IDirectSound_AddRef
,
1386 IDirectSound8_IDirectSound_Release
,
1387 IDirectSound8_IDirectSound_CreateSoundBuffer
,
1388 IDirectSound8_IDirectSound_GetCaps
,
1389 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
1390 IDirectSound8_IDirectSound_SetCooperativeLevel
,
1391 IDirectSound8_IDirectSound_Compact
,
1392 IDirectSound8_IDirectSound_GetSpeakerConfig
,
1393 IDirectSound8_IDirectSound_SetSpeakerConfig
,
1394 IDirectSound8_IDirectSound_Initialize
1397 HRESULT WINAPI
IDirectSound8_IDirectSound_Create(
1399 LPDIRECTSOUND
* ppds
)
1401 IDirectSound8_IDirectSound
* pdsds
;
1402 TRACE("(%p,%p)\n",pds
,ppds
);
1405 ERR("invalid parameter: ppds == NULL\n");
1406 return DSERR_INVALIDPARAM
;
1410 ERR("invalid parameter: pds == NULL\n");
1412 return DSERR_INVALIDPARAM
;
1415 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1416 if (pdsds
== NULL
) {
1417 WARN("out of memory\n");
1419 return DSERR_OUTOFMEMORY
;
1422 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
1426 IDirectSoundImpl_AddRef(pds
);
1427 *ppds
= (LPDIRECTSOUND
)pdsds
;
1432 /*******************************************************************************
1433 * IDirectSound8_IDirectSound8
1435 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
1436 LPDIRECTSOUND8 iface
,
1440 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1441 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1442 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1445 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
1446 LPDIRECTSOUND8 iface
)
1448 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1449 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1450 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1454 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
1455 LPDIRECTSOUND8 iface
)
1457 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1458 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1459 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1461 IDirectSoundImpl_Release(This
->pds
);
1462 HeapFree(GetProcessHeap(), 0, This
);
1463 TRACE("(%p) released\n", This
);
1468 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
1469 LPDIRECTSOUND8 iface
,
1470 LPCDSBUFFERDESC dsbd
,
1471 LPLPDIRECTSOUNDBUFFER ppdsb
,
1474 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1475 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1476 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,TRUE
);
1479 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
1480 LPDIRECTSOUND8 iface
,
1483 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1484 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1485 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1488 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1489 LPDIRECTSOUND8 iface
,
1490 LPDIRECTSOUNDBUFFER psb
,
1491 LPLPDIRECTSOUNDBUFFER ppdsb
)
1493 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1494 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1495 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1498 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
1499 LPDIRECTSOUND8 iface
,
1503 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1504 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1505 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1508 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
1509 LPDIRECTSOUND8 iface
)
1511 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1512 TRACE("(%p)\n", This
);
1513 return IDirectSoundImpl_Compact(This
->pds
);
1516 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
1517 LPDIRECTSOUND8 iface
,
1518 LPDWORD lpdwSpeakerConfig
)
1520 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1521 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1522 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1525 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
1526 LPDIRECTSOUND8 iface
,
1529 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1530 TRACE("(%p,0x%08lx)\n",This
,config
);
1531 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1534 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
1535 LPDIRECTSOUND8 iface
,
1538 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1539 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1540 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1543 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
1544 LPDIRECTSOUND8 iface
,
1545 LPDWORD pdwCertified
)
1547 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1548 TRACE("(%p, %p)\n", This
, pdwCertified
);
1549 return IDirectSoundImpl_VerifyCertification(This
->pds
,pdwCertified
);
1552 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
1554 IDirectSound8_IDirectSound8_QueryInterface
,
1555 IDirectSound8_IDirectSound8_AddRef
,
1556 IDirectSound8_IDirectSound8_Release
,
1557 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
1558 IDirectSound8_IDirectSound8_GetCaps
,
1559 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
1560 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
1561 IDirectSound8_IDirectSound8_Compact
,
1562 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
1563 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
1564 IDirectSound8_IDirectSound8_Initialize
,
1565 IDirectSound8_IDirectSound8_VerifyCertification
1568 HRESULT WINAPI
IDirectSound8_IDirectSound8_Create(
1570 LPDIRECTSOUND8
* ppds
)
1572 IDirectSound8_IDirectSound8
* pdsds
;
1573 TRACE("(%p,%p)\n",pds
,ppds
);
1576 ERR("invalid parameter: ppds == NULL\n");
1577 return DSERR_INVALIDPARAM
;
1581 ERR("invalid parameter: pds == NULL\n");
1583 return DSERR_INVALIDPARAM
;
1586 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1587 if (pdsds
== NULL
) {
1588 WARN("out of memory\n");
1590 return DSERR_OUTOFMEMORY
;
1593 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
1597 IDirectSoundImpl_AddRef(pds
);
1598 *ppds
= (LPDIRECTSOUND8
)pdsds
;
1603 HRESULT WINAPI
DSOUND_Create(
1605 LPDIRECTSOUND
*ppDS
,
1606 IUnknown
*pUnkOuter
)
1611 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1613 if (pUnkOuter
!= NULL
) {
1614 WARN("invalid parameter: pUnkOuter != NULL\n");
1615 return DSERR_INVALIDPARAM
;
1619 WARN("invalid parameter: ppDS == NULL\n");
1620 return DSERR_INVALIDPARAM
;
1623 /* Get dsound configuration */
1624 setup_dsound_options();
1626 /* Default device? */
1627 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1628 lpcGUID
= &DSDEVID_DefaultPlayback
;
1630 if (GetDeviceID(lpcGUID
, &devGuid
) != DS_OK
) {
1631 WARN("invalid parameter: lpcGUID\n");
1633 return DSERR_INVALIDPARAM
;
1637 if (IsEqualGUID(&devGuid
, &dsound
->guid
)) {
1638 hr
= IDirectSound_IDirectSound_Create((LPDIRECTSOUND8
)dsound
, ppDS
);
1640 IDirectSound_IDirectSound_AddRef(*ppDS
);
1642 WARN("IDirectSound_IDirectSound_Create failed\n");
1644 ERR("different dsound already opened (only support one sound card at a time now)\n");
1646 hr
= DSERR_ALLOCATED
;
1650 hr
= IDirectSoundImpl_Create(&devGuid
, &pDS
);
1652 hr
= DSOUND_PrimaryCreate((IDirectSoundImpl
*)pDS
);
1654 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1656 IDirectSound_IDirectSound_AddRef(*ppDS
);
1658 dsound
= (IDirectSoundImpl
*)pDS
;
1659 timeBeginPeriod(DS_TIME_RES
);
1660 dsound
->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1661 (DWORD
)dsound
, TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1663 WARN("IDirectSound_IDirectSound_Create failed\n");
1664 IDirectSound8_Release(pDS
);
1667 WARN("DSOUND_PrimaryCreate failed\n");
1668 IDirectSound8_Release(pDS
);
1671 WARN("IDirectSoundImpl_Create failed\n");
1677 /*******************************************************************************
1678 * DirectSoundCreate (DSOUND.1)
1680 * Creates and initializes a DirectSound interface.
1683 * lpcGUID [I] Address of the GUID that identifies the sound device.
1684 * ppDS [O] Address of a variable to receive the interface pointer.
1685 * pUnkOuter [I] Must be NULL.
1689 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1690 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1692 HRESULT WINAPI
DirectSoundCreate(
1694 LPDIRECTSOUND
*ppDS
,
1695 IUnknown
*pUnkOuter
)
1699 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1701 hr
= DSOUND_Create(lpcGUID
, ppDS
, pUnkOuter
);
1703 IDirectSoundImpl_Initialize((LPDIRECTSOUND8
)dsound
, lpcGUID
);
1708 HRESULT WINAPI
DSOUND_Create8(
1710 LPDIRECTSOUND8
*ppDS
,
1711 IUnknown
*pUnkOuter
)
1716 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1718 if (pUnkOuter
!= NULL
) {
1719 WARN("invalid parameter: pUnkOuter != NULL\n");
1720 return DSERR_INVALIDPARAM
;
1724 WARN("invalid parameter: ppDS == NULL\n");
1725 return DSERR_INVALIDPARAM
;
1728 /* Get dsound configuration */
1729 setup_dsound_options();
1731 /* Default device? */
1732 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1733 lpcGUID
= &DSDEVID_DefaultPlayback
;
1735 if (GetDeviceID(lpcGUID
, &devGuid
) != DS_OK
) {
1736 WARN("invalid parameter: lpcGUID\n");
1738 return DSERR_INVALIDPARAM
;
1742 if (IsEqualGUID(&devGuid
, &dsound
->guid
)) {
1743 hr
= IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8
)dsound
, ppDS
);
1745 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1747 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1749 ERR("different dsound already opened (only support one sound card at a time now)\n");
1751 hr
= DSERR_ALLOCATED
;
1755 hr
= IDirectSoundImpl_Create(&devGuid
, &pDS
);
1757 hr
= DSOUND_PrimaryCreate((IDirectSoundImpl
*)pDS
);
1759 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1761 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1763 dsound
= (IDirectSoundImpl
*)pDS
;
1764 timeBeginPeriod(DS_TIME_RES
);
1765 dsound
->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1766 (DWORD
)dsound
, TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1768 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1769 IDirectSound8_Release(pDS
);
1772 WARN("DSOUND_PrimaryCreate failed\n");
1773 IDirectSound8_Release(pDS
);
1776 WARN("IDirectSoundImpl_Create failed\n");
1782 /*******************************************************************************
1783 * DirectSoundCreate8 (DSOUND.11)
1785 * Creates and initializes a DirectSound8 interface.
1788 * lpcGUID [I] Address of the GUID that identifies the sound device.
1789 * ppDS [O] Address of a variable to receive the interface pointer.
1790 * pUnkOuter [I] Must be NULL.
1794 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1795 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1797 HRESULT WINAPI
DirectSoundCreate8(
1799 LPDIRECTSOUND8
*ppDS
,
1800 IUnknown
*pUnkOuter
)
1804 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1806 hr
= DSOUND_Create8(lpcGUID
, ppDS
, pUnkOuter
);
1808 IDirectSoundImpl_Initialize((LPDIRECTSOUND8
)dsound
, lpcGUID
);
1814 * Add secondary buffer to buffer list.
1815 * Gets exclusive access to buffer for writing.
1817 HRESULT
DSOUND_AddBuffer(
1818 IDirectSoundImpl
* pDS
,
1819 IDirectSoundBufferImpl
* pDSB
)
1821 IDirectSoundBufferImpl
**newbuffers
;
1824 TRACE("(%p, %p)\n", pDS
, pDSB
);
1826 RtlAcquireResourceExclusive(&(pDS
->buffer_list_lock
), TRUE
);
1829 newbuffers
= HeapReAlloc(GetProcessHeap(),0,pDS
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(pDS
->nrofbuffers
+1));
1831 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(pDS
->nrofbuffers
+1));
1834 pDS
->buffers
= newbuffers
;
1835 pDS
->buffers
[pDS
->nrofbuffers
] = pDSB
;
1837 TRACE("buffer count is now %d\n", pDS
->nrofbuffers
);
1839 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS
->nrofbuffers
);
1840 hr
= DSERR_OUTOFMEMORY
;
1843 RtlReleaseResource(&(pDS
->buffer_list_lock
));
1849 * Remove secondary buffer from buffer list.
1850 * Gets exclusive access to buffer for writing.
1852 HRESULT
DSOUND_RemoveBuffer(
1853 IDirectSoundImpl
* pDS
,
1854 IDirectSoundBufferImpl
* pDSB
)
1859 TRACE("(%p, %p)\n", pDS
, pDSB
);
1861 RtlAcquireResourceExclusive(&(pDS
->buffer_list_lock
), TRUE
);
1863 for (i
= 0; i
< pDS
->nrofbuffers
; i
++)
1864 if (pDS
->buffers
[i
] == pDSB
)
1867 if (i
< pDS
->nrofbuffers
) {
1868 /* Put the last buffer of the list in the (now empty) position */
1869 pDS
->buffers
[i
] = pDS
->buffers
[pDS
->nrofbuffers
- 1];
1871 pDS
->buffers
= HeapReAlloc(GetProcessHeap(),0,pDS
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*pDS
->nrofbuffers
);
1872 TRACE("buffer count is now %d\n", pDS
->nrofbuffers
);
1875 if (pDS
->nrofbuffers
== 0) {
1876 HeapFree(GetProcessHeap(),0,pDS
->buffers
);
1877 pDS
->buffers
= NULL
;
1880 RtlReleaseResource(&(pDS
->buffer_list_lock
));