shell32: Remove redundant loop to count already known value.
[wine/multimedia.git] / dlls / dsound / buffer.c
blobe2f2cc200d811f53e91f793bac36d4f12ee47f09
1 /* DirectSound
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "mmsystem.h"
30 #include "winternl.h"
31 #include "vfwmsgs.h"
32 #include "wine/debug.h"
33 #include "dsound.h"
34 #include "dsound_private.h"
35 #include "dsconf.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
39 /*******************************************************************************
40 * IDirectSoundNotify
43 struct IDirectSoundNotifyImpl
45 /* IUnknown fields */
46 const IDirectSoundNotifyVtbl *lpVtbl;
47 LONG ref;
48 IDirectSoundBufferImpl* dsb;
51 static HRESULT IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl *dsb,
52 IDirectSoundNotifyImpl **pdsn);
53 static HRESULT IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl *pdsn);
55 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
56 LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
57 ) {
58 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
59 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
61 if (This->dsb == NULL) {
62 WARN("invalid parameter\n");
63 return E_INVALIDARG;
66 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
69 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
71 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
72 ULONG ref = InterlockedIncrement(&(This->ref));
73 TRACE("(%p) ref was %d\n", This, ref - 1);
74 return ref;
77 static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
79 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
80 ULONG ref = InterlockedDecrement(&(This->ref));
81 TRACE("(%p) ref was %d\n", This, ref + 1);
83 if (!ref) {
84 This->dsb->notify = NULL;
85 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
86 HeapFree(GetProcessHeap(), 0, This);
87 TRACE("(%p) released\n", This);
89 return ref;
92 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
93 LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
94 ) {
95 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
96 TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
98 if (howmuch > 0 && notify == NULL) {
99 WARN("invalid parameter: notify == NULL\n");
100 return DSERR_INVALIDPARAM;
103 if (TRACE_ON(dsound)) {
104 unsigned int i;
105 for (i=0;i<howmuch;i++)
106 TRACE("notify at %d to %p\n",
107 notify[i].dwOffset,notify[i].hEventNotify);
110 if (howmuch > 0) {
111 /* Make an internal copy of the caller-supplied array.
112 * Replace the existing copy if one is already present. */
113 HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
114 This->dsb->notifies = HeapAlloc(GetProcessHeap(), 0,
115 howmuch * sizeof(DSBPOSITIONNOTIFY));
117 if (This->dsb->notifies == NULL) {
118 WARN("out of memory\n");
119 return DSERR_OUTOFMEMORY;
121 CopyMemory(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
122 This->dsb->nrofnotifies = howmuch;
123 } else {
124 HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
125 This->dsb->notifies = NULL;
126 This->dsb->nrofnotifies = 0;
129 return S_OK;
132 static const IDirectSoundNotifyVtbl dsnvt =
134 IDirectSoundNotifyImpl_QueryInterface,
135 IDirectSoundNotifyImpl_AddRef,
136 IDirectSoundNotifyImpl_Release,
137 IDirectSoundNotifyImpl_SetNotificationPositions,
140 static HRESULT IDirectSoundNotifyImpl_Create(
141 IDirectSoundBufferImpl * dsb,
142 IDirectSoundNotifyImpl **pdsn)
144 IDirectSoundNotifyImpl * dsn;
145 TRACE("(%p,%p)\n",dsb,pdsn);
147 dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dsn));
149 if (dsn == NULL) {
150 WARN("out of memory\n");
151 return DSERR_OUTOFMEMORY;
154 dsn->ref = 0;
155 dsn->lpVtbl = &dsnvt;
156 dsn->dsb = dsb;
157 dsb->notify = dsn;
158 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
160 *pdsn = dsn;
161 return DS_OK;
164 static HRESULT IDirectSoundNotifyImpl_Destroy(
165 IDirectSoundNotifyImpl *pdsn)
167 TRACE("(%p)\n",pdsn);
169 while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
171 return DS_OK;
174 /*******************************************************************************
175 * IDirectSoundBuffer
178 static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 *iface)
180 return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
183 static inline BOOL is_primary_buffer(IDirectSoundBufferImpl *This)
185 return This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER ? TRUE : FALSE;
188 static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 *iface,
189 LPCWAVEFORMATEX wfex)
191 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
193 TRACE("(%p,%p)\n", iface, wfex);
195 if (is_primary_buffer(This))
196 return primarybuffer_SetFormat(This->device, wfex);
197 else {
198 WARN("not available for secondary buffers.\n");
199 return DSERR_INVALIDCALL;
203 static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 *iface, LONG vol)
205 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
206 LONG oldVol;
208 HRESULT hres = DS_OK;
210 TRACE("(%p,%d)\n",This,vol);
212 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
213 WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags);
214 return DSERR_CONTROLUNAVAIL;
217 if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
218 WARN("invalid parameter: vol = %d\n", vol);
219 return DSERR_INVALIDPARAM;
222 /* **** */
223 RtlAcquireResourceExclusive(&This->lock, TRUE);
225 if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
226 oldVol = This->ds3db_lVolume;
227 This->ds3db_lVolume = vol;
228 if (vol != oldVol)
229 /* recalc 3d volume, which in turn recalcs the pans */
230 DSOUND_Calc3DBuffer(This);
231 } else {
232 oldVol = This->volpan.lVolume;
233 This->volpan.lVolume = vol;
234 if (vol != oldVol)
235 DSOUND_RecalcVolPan(&(This->volpan));
238 RtlReleaseResource(&This->lock);
239 /* **** */
241 return hres;
244 static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(IDirectSoundBuffer8 *iface, LONG *vol)
246 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
248 TRACE("(%p,%p)\n",This,vol);
250 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
251 WARN("control unavailable\n");
252 return DSERR_CONTROLUNAVAIL;
255 if (vol == NULL) {
256 WARN("invalid parameter: vol == NULL\n");
257 return DSERR_INVALIDPARAM;
260 *vol = This->volpan.lVolume;
262 return DS_OK;
265 static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *iface, DWORD freq)
267 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
268 DWORD oldFreq;
270 TRACE("(%p,%d)\n",This,freq);
272 if (is_primary_buffer(This)) {
273 WARN("not available for primary buffers.\n");
274 return DSERR_CONTROLUNAVAIL;
277 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
278 WARN("control unavailable\n");
279 return DSERR_CONTROLUNAVAIL;
282 if (freq == DSBFREQUENCY_ORIGINAL)
283 freq = This->pwfx->nSamplesPerSec;
285 if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
286 WARN("invalid parameter: freq = %d\n", freq);
287 return DSERR_INVALIDPARAM;
290 /* **** */
291 RtlAcquireResourceExclusive(&This->lock, TRUE);
293 oldFreq = This->freq;
294 This->freq = freq;
295 if (freq != oldFreq) {
296 This->freqAdjust = ((DWORD64)This->freq << DSOUND_FREQSHIFT) / This->device->pwfx->nSamplesPerSec;
297 This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
298 DSOUND_RecalcFormat(This);
301 RtlReleaseResource(&This->lock);
302 /* **** */
304 return DS_OK;
307 static HRESULT WINAPI IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 *iface, DWORD reserved1,
308 DWORD reserved2, DWORD flags)
310 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
311 HRESULT hres = DS_OK;
313 TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
315 /* **** */
316 RtlAcquireResourceExclusive(&This->lock, TRUE);
318 This->playflags = flags;
319 if (This->state == STATE_STOPPED) {
320 This->leadin = TRUE;
321 This->state = STATE_STARTING;
322 } else if (This->state == STATE_STOPPING)
323 This->state = STATE_PLAYING;
325 RtlReleaseResource(&This->lock);
326 /* **** */
328 return hres;
331 static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface)
333 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
334 HRESULT hres = DS_OK;
336 TRACE("(%p)\n",This);
338 /* **** */
339 RtlAcquireResourceExclusive(&This->lock, TRUE);
341 if (This->state == STATE_PLAYING)
342 This->state = STATE_STOPPING;
343 else if (This->state == STATE_STARTING)
345 This->state = STATE_STOPPED;
346 DSOUND_CheckEvent(This, 0, 0);
349 RtlReleaseResource(&This->lock);
350 /* **** */
352 return hres;
355 static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface)
357 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
358 ULONG ref = InterlockedIncrement(&This->ref);
360 TRACE("(%p) ref was %d\n", This, ref - 1);
362 if(ref == 1)
363 InterlockedIncrement(&This->numIfaces);
365 return ref;
368 static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface)
370 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
371 ULONG ref = InterlockedDecrement(&This->ref);
373 TRACE("(%p) ref was %d\n", This, ref + 1);
375 if (!ref && !InterlockedDecrement(&This->numIfaces)) {
376 if (is_primary_buffer(This))
377 primarybuffer_destroy(This);
378 else
379 secondarybuffer_destroy(This);
381 return ref;
384 static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuffer8 *iface,
385 DWORD *playpos, DWORD *writepos)
387 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
388 DWORD pos;
390 TRACE("(%p,%p,%p)\n",This,playpos,writepos);
392 RtlAcquireResourceShared(&This->lock, TRUE);
394 pos = This->sec_mixpos;
396 /* sanity */
397 if (pos >= This->buflen){
398 FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
399 pos %= This->buflen;
402 if (playpos)
403 *playpos = pos;
404 if (writepos)
405 *writepos = pos;
407 if (writepos && This->state != STATE_STOPPED) {
408 /* apply the documented 10ms lead to writepos */
409 *writepos += This->writelead;
410 *writepos %= This->buflen;
413 RtlReleaseResource(&This->lock);
415 TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
416 playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount());
418 return DS_OK;
421 static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status)
423 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
425 TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId());
427 if (status == NULL) {
428 WARN("invalid parameter: status = NULL\n");
429 return DSERR_INVALIDPARAM;
432 *status = 0;
433 RtlAcquireResourceShared(&This->lock, TRUE);
434 if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
435 *status |= DSBSTATUS_PLAYING;
436 if (This->playflags & DSBPLAY_LOOPING)
437 *status |= DSBSTATUS_LOOPING;
439 RtlReleaseResource(&This->lock);
441 TRACE("status=%x\n", *status);
442 return DS_OK;
446 static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(IDirectSoundBuffer8 *iface,
447 LPWAVEFORMATEX lpwf, DWORD wfsize, DWORD *wfwritten)
449 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
450 DWORD size;
452 TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
454 size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
456 if (lpwf) { /* NULL is valid */
457 if (wfsize >= size) {
458 CopyMemory(lpwf,This->pwfx,size);
459 if (wfwritten)
460 *wfwritten = size;
461 } else {
462 WARN("invalid parameter: wfsize too small\n");
463 CopyMemory(lpwf,This->pwfx,wfsize);
464 if (wfwritten)
465 *wfwritten = wfsize;
466 return DSERR_INVALIDPARAM;
468 } else {
469 if (wfwritten)
470 *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
471 else {
472 WARN("invalid parameter: wfwritten == NULL\n");
473 return DSERR_INVALIDPARAM;
477 return DS_OK;
480 static HRESULT WINAPI IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 *iface, DWORD writecursor,
481 DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
482 DWORD *audiobytes2, DWORD flags)
484 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
485 HRESULT hres = DS_OK;
487 TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", This, writecursor, writebytes, lplpaudioptr1,
488 audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount());
490 if (!audiobytes1)
491 return DSERR_INVALIDPARAM;
493 /* when this flag is set, writecursor is meaningless and must be calculated */
494 if (flags & DSBLOCK_FROMWRITECURSOR) {
495 /* GetCurrentPosition does too much magic to duplicate here */
496 hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor);
497 if (hres != DS_OK) {
498 WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
499 return hres;
503 /* when this flag is set, writebytes is meaningless and must be set */
504 if (flags & DSBLOCK_ENTIREBUFFER)
505 writebytes = This->buflen;
507 if (writecursor >= This->buflen) {
508 WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
509 writecursor, This->buflen);
510 return DSERR_INVALIDPARAM;
513 if (writebytes > This->buflen) {
514 WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
515 writebytes, This->buflen);
516 return DSERR_INVALIDPARAM;
519 /* **** */
520 RtlAcquireResourceShared(&This->lock, TRUE);
522 if (writecursor+writebytes <= This->buflen) {
523 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
524 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
525 WARN("Overwriting mixing position, case 1\n");
526 *audiobytes1 = writebytes;
527 if (lplpaudioptr2)
528 *(LPBYTE*)lplpaudioptr2 = NULL;
529 if (audiobytes2)
530 *audiobytes2 = 0;
531 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
532 *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
533 TRACE("->%d.0\n",writebytes);
534 } else {
535 DWORD remainder = writebytes + writecursor - This->buflen;
536 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
537 *audiobytes1 = This->buflen-writecursor;
538 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
539 WARN("Overwriting mixing position, case 2\n");
540 if (lplpaudioptr2)
541 *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
542 if (audiobytes2)
543 *audiobytes2 = writebytes-(This->buflen-writecursor);
544 if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
545 WARN("Overwriting mixing position, case 3\n");
546 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
549 RtlReleaseResource(&This->lock);
550 /* **** */
552 return DS_OK;
555 static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuffer8 *iface,
556 DWORD newpos)
558 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
559 HRESULT hres = DS_OK;
560 DWORD oldpos;
562 TRACE("(%p,%d)\n",This,newpos);
564 /* **** */
565 RtlAcquireResourceExclusive(&This->lock, TRUE);
567 oldpos = This->sec_mixpos;
569 /* start mixing from this new location instead */
570 newpos %= This->buflen;
571 newpos -= newpos%This->pwfx->nBlockAlign;
572 This->sec_mixpos = newpos;
574 /* at this point, do not attempt to reset buffers, mess with primary mix position,
575 or anything like that to reduce latency. The data already prebuffered cannot be changed */
577 /* position HW buffer if applicable, else just start mixing from new location instead */
578 if (oldpos != newpos)
579 This->buf_mixpos = DSOUND_secpos_to_bufpos(This, newpos, 0, NULL);
581 RtlReleaseResource(&This->lock);
582 /* **** */
584 return hres;
587 static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 *iface, LONG pan)
589 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
590 HRESULT hres = DS_OK;
592 TRACE("(%p,%d)\n",This,pan);
594 if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
595 WARN("invalid parameter: pan = %d\n", pan);
596 return DSERR_INVALIDPARAM;
599 /* You cannot use both pan and 3D controls */
600 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
601 (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
602 WARN("control unavailable\n");
603 return DSERR_CONTROLUNAVAIL;
606 /* **** */
607 RtlAcquireResourceExclusive(&This->lock, TRUE);
609 if (This->volpan.lPan != pan) {
610 This->volpan.lPan = pan;
611 DSOUND_RecalcVolPan(&(This->volpan));
614 RtlReleaseResource(&This->lock);
615 /* **** */
617 return hres;
620 static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(IDirectSoundBuffer8 *iface, LONG *pan)
622 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
624 TRACE("(%p,%p)\n",This,pan);
626 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
627 WARN("control unavailable\n");
628 return DSERR_CONTROLUNAVAIL;
631 if (pan == NULL) {
632 WARN("invalid parameter: pan = NULL\n");
633 return DSERR_INVALIDPARAM;
636 *pan = This->volpan.lPan;
638 return DS_OK;
641 static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface, void *p1, DWORD x1,
642 void *p2, DWORD x2)
644 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface), *iter;
645 HRESULT hres = DS_OK;
647 TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
649 if (!p2)
650 x2 = 0;
652 if((p1 && ((BYTE*)p1 < This->buffer->memory ||
653 (BYTE*)p1 >= This->buffer->memory + This->buflen)) ||
654 (p2 && ((BYTE*)p2 < This->buffer->memory ||
655 (BYTE*)p2 >= This->buffer->memory + This->buflen)))
656 return DSERR_INVALIDPARAM;
658 if (x1 || x2)
660 RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
661 LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
663 RtlAcquireResourceShared(&iter->lock, TRUE);
664 if (x1)
666 if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
667 hres = DSERR_INVALIDPARAM;
669 RtlReleaseResource(&iter->lock);
671 RtlReleaseResource(&This->device->buffer_list_lock);
674 return hres;
677 static HRESULT WINAPI IDirectSoundBufferImpl_Restore(IDirectSoundBuffer8 *iface)
679 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
681 FIXME("(%p):stub\n",This);
682 return DS_OK;
685 static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 *iface, DWORD *freq)
687 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
689 TRACE("(%p,%p)\n",This,freq);
691 if (freq == NULL) {
692 WARN("invalid parameter: freq = NULL\n");
693 return DSERR_INVALIDPARAM;
696 *freq = This->freq;
697 TRACE("-> %d\n", *freq);
699 return DS_OK;
702 static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, DWORD dwEffectsCount,
703 LPDSEFFECTDESC pDSFXDesc, DWORD *pdwResultCodes)
705 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
706 DWORD u;
708 FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
710 if (pdwResultCodes)
711 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
713 WARN("control unavailable\n");
714 return DSERR_CONTROLUNAVAIL;
717 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 *iface,
718 DWORD dwFlags, DWORD dwEffectsCount, DWORD *pdwResultCodes)
720 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
721 DWORD u;
723 FIXME("(%p,%08u,%u,%p): stub, faking success\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
725 if (pdwResultCodes)
726 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
728 WARN("control unavailable\n");
729 return DS_OK;
732 static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(IDirectSoundBuffer8 *iface,
733 REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
735 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
737 FIXME("(%p,%s,%u,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
739 WARN("control unavailable\n");
740 return DSERR_CONTROLUNAVAIL;
743 static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(IDirectSoundBuffer8 *iface,
744 IDirectSound *dsound, LPCDSBUFFERDESC dbsd)
746 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
748 WARN("(%p) already initialized\n", This);
749 return DSERR_ALREADYINITIALIZED;
752 static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 *iface, LPDSBCAPS caps)
754 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
756 TRACE("(%p)->(%p)\n",This,caps);
758 if (caps == NULL) {
759 WARN("invalid parameter: caps == NULL\n");
760 return DSERR_INVALIDPARAM;
763 if (caps->dwSize < sizeof(*caps)) {
764 WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize);
765 return DSERR_INVALIDPARAM;
768 caps->dwFlags = This->dsbd.dwFlags;
769 caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
771 caps->dwBufferBytes = This->buflen;
773 /* According to windows, this is zero*/
774 caps->dwUnlockTransferRate = 0;
775 caps->dwPlayCpuOverhead = 0;
777 return DS_OK;
780 static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8 *iface, REFIID riid,
781 void **ppobj)
783 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
785 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
787 if (ppobj == NULL) {
788 WARN("invalid parameter\n");
789 return E_INVALIDARG;
792 *ppobj = NULL; /* assume failure */
794 if ( IsEqualGUID(riid, &IID_IUnknown) ||
795 IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
796 IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
797 IDirectSoundBuffer8_AddRef(iface);
798 *ppobj = iface;
799 return S_OK;
802 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
803 if (!This->notify)
804 IDirectSoundNotifyImpl_Create(This, &(This->notify));
805 if (This->notify) {
806 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
807 *ppobj = This->notify;
808 return S_OK;
810 WARN("IID_IDirectSoundNotify\n");
811 return E_NOINTERFACE;
814 if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
815 if (!This->ds3db)
816 IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
817 if (This->ds3db) {
818 IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
819 *ppobj = This->ds3db;
820 return S_OK;
822 WARN("IID_IDirectSound3DBuffer\n");
823 return E_NOINTERFACE;
826 if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
827 ERR("app requested IDirectSound3DListener on secondary buffer\n");
828 return E_NOINTERFACE;
831 if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
832 if (!This->iks)
833 IKsBufferPropertySetImpl_Create(This, &(This->iks));
834 if (This->iks) {
835 IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks);
836 *ppobj = This->iks;
837 return S_OK;
839 WARN("IID_IKsPropertySet\n");
840 return E_NOINTERFACE;
843 FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
845 return E_NOINTERFACE;
848 static const IDirectSoundBuffer8Vtbl dsbvt =
850 IDirectSoundBufferImpl_QueryInterface,
851 IDirectSoundBufferImpl_AddRef,
852 IDirectSoundBufferImpl_Release,
853 IDirectSoundBufferImpl_GetCaps,
854 IDirectSoundBufferImpl_GetCurrentPosition,
855 IDirectSoundBufferImpl_GetFormat,
856 IDirectSoundBufferImpl_GetVolume,
857 IDirectSoundBufferImpl_GetPan,
858 IDirectSoundBufferImpl_GetFrequency,
859 IDirectSoundBufferImpl_GetStatus,
860 IDirectSoundBufferImpl_Initialize,
861 IDirectSoundBufferImpl_Lock,
862 IDirectSoundBufferImpl_Play,
863 IDirectSoundBufferImpl_SetCurrentPosition,
864 IDirectSoundBufferImpl_SetFormat,
865 IDirectSoundBufferImpl_SetVolume,
866 IDirectSoundBufferImpl_SetPan,
867 IDirectSoundBufferImpl_SetFrequency,
868 IDirectSoundBufferImpl_Stop,
869 IDirectSoundBufferImpl_Unlock,
870 IDirectSoundBufferImpl_Restore,
871 IDirectSoundBufferImpl_SetFX,
872 IDirectSoundBufferImpl_AcquireResources,
873 IDirectSoundBufferImpl_GetObjectInPath
876 HRESULT IDirectSoundBufferImpl_Create(
877 DirectSoundDevice * device,
878 IDirectSoundBufferImpl **pdsb,
879 LPCDSBUFFERDESC dsbd)
881 IDirectSoundBufferImpl *dsb;
882 LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
883 HRESULT err = DS_OK;
884 DWORD capf = 0;
885 TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
887 if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
888 WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes);
889 *pdsb = NULL;
890 return DSERR_INVALIDPARAM; /* FIXME: which error? */
893 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
895 if (dsb == 0) {
896 WARN("out of memory\n");
897 *pdsb = NULL;
898 return DSERR_OUTOFMEMORY;
901 TRACE("Created buffer at %p\n", dsb);
903 dsb->ref = 1;
904 dsb->numIfaces = 1;
905 dsb->device = device;
906 dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
907 dsb->iks = NULL;
909 /* size depends on version */
910 CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
912 dsb->pwfx = DSOUND_CopyFormat(wfex);
913 if (dsb->pwfx == NULL) {
914 HeapFree(GetProcessHeap(),0,dsb);
915 *pdsb = NULL;
916 return DSERR_OUTOFMEMORY;
919 if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
920 dsb->buflen = dsbd->dwBufferBytes +
921 (dsbd->lpwfxFormat->nBlockAlign -
922 (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
923 else
924 dsb->buflen = dsbd->dwBufferBytes;
926 dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
927 dsb->notify = NULL;
928 dsb->notifies = NULL;
929 dsb->nrofnotifies = 0;
931 /* Check necessary hardware mixing capabilities */
932 if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
933 else capf |= DSCAPS_SECONDARYMONO;
934 if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
935 else capf |= DSCAPS_SECONDARY8BIT;
937 TRACE("capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", capf, device->drvcaps.dwFlags);
939 /* Allocate an empty buffer */
940 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
941 if (dsb->buffer == NULL) {
942 WARN("out of memory\n");
943 HeapFree(GetProcessHeap(),0,dsb->pwfx);
944 HeapFree(GetProcessHeap(),0,dsb);
945 *pdsb = NULL;
946 return DSERR_OUTOFMEMORY;
949 /* Allocate system memory for buffer */
950 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
951 if (dsb->buffer->memory == NULL) {
952 WARN("out of memory\n");
953 HeapFree(GetProcessHeap(),0,dsb->pwfx);
954 HeapFree(GetProcessHeap(),0,dsb->buffer);
955 HeapFree(GetProcessHeap(),0,dsb);
956 *pdsb = NULL;
957 return DSERR_OUTOFMEMORY;
960 dsb->buffer->ref = 1;
961 list_init(&dsb->buffer->buffers);
962 list_add_head(&dsb->buffer->buffers, &dsb->entry);
963 FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
965 /* It's not necessary to initialize values to zero since */
966 /* we allocated this structure with HEAP_ZERO_MEMORY... */
967 dsb->buf_mixpos = dsb->sec_mixpos = 0;
968 dsb->state = STATE_STOPPED;
970 dsb->freqAdjust = ((DWORD64)dsb->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
971 dsb->nAvgBytesPerSec = dsb->freq *
972 dsbd->lpwfxFormat->nBlockAlign;
974 /* calculate fragment size and write lead */
975 DSOUND_RecalcFormat(dsb);
977 if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
978 dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
979 dsb->ds3db_ds3db.vPosition.x = 0.0;
980 dsb->ds3db_ds3db.vPosition.y = 0.0;
981 dsb->ds3db_ds3db.vPosition.z = 0.0;
982 dsb->ds3db_ds3db.vVelocity.x = 0.0;
983 dsb->ds3db_ds3db.vVelocity.y = 0.0;
984 dsb->ds3db_ds3db.vVelocity.z = 0.0;
985 dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
986 dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
987 dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
988 dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
989 dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
990 dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
991 dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
992 dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
993 dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
995 dsb->ds3db_need_recalc = FALSE;
996 DSOUND_Calc3DBuffer(dsb);
997 } else
998 DSOUND_RecalcVolPan(&(dsb->volpan));
1000 RtlInitializeResource(&dsb->lock);
1002 /* register buffer if not primary */
1003 if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
1004 err = DirectSoundDevice_AddBuffer(device, dsb);
1005 if (err != DS_OK) {
1006 HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
1007 HeapFree(GetProcessHeap(),0,dsb->buffer);
1008 RtlDeleteResource(&dsb->lock);
1009 HeapFree(GetProcessHeap(),0,dsb->pwfx);
1010 HeapFree(GetProcessHeap(),0,dsb);
1011 dsb = NULL;
1015 *pdsb = dsb;
1016 return err;
1019 void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
1021 DirectSoundDevice_RemoveBuffer(This->device, This);
1022 RtlDeleteResource(&This->lock);
1024 This->buffer->ref--;
1025 list_remove(&This->entry);
1026 if (This->buffer->ref == 0) {
1027 HeapFree(GetProcessHeap(), 0, This->buffer->memory);
1028 HeapFree(GetProcessHeap(), 0, This->buffer);
1031 HeapFree(GetProcessHeap(), 0, This->notifies);
1032 HeapFree(GetProcessHeap(), 0, This->pwfx);
1033 HeapFree(GetProcessHeap(), 0, This);
1035 TRACE("(%p) released\n", This);
1038 HRESULT IDirectSoundBufferImpl_Destroy(
1039 IDirectSoundBufferImpl *pdsb)
1041 TRACE("(%p)\n",pdsb);
1043 /* This keeps the *_Destroy functions from possibly deleting
1044 * this object until it is ready to be deleted */
1045 InterlockedIncrement(&pdsb->numIfaces);
1047 if (pdsb->iks) {
1048 WARN("iks not NULL\n");
1049 IKsBufferPropertySetImpl_Destroy(pdsb->iks);
1050 pdsb->iks = NULL;
1053 if (pdsb->ds3db) {
1054 WARN("ds3db not NULL\n");
1055 IDirectSound3DBufferImpl_Destroy(pdsb->ds3db);
1056 pdsb->ds3db = NULL;
1059 if (pdsb->notify) {
1060 WARN("notify not NULL\n");
1061 IDirectSoundNotifyImpl_Destroy(pdsb->notify);
1062 pdsb->notify = NULL;
1065 secondarybuffer_destroy(pdsb);
1067 return S_OK;
1070 HRESULT IDirectSoundBufferImpl_Duplicate(
1071 DirectSoundDevice *device,
1072 IDirectSoundBufferImpl **ppdsb,
1073 IDirectSoundBufferImpl *pdsb)
1075 IDirectSoundBufferImpl *dsb;
1076 HRESULT hres = DS_OK;
1077 TRACE("(%p,%p,%p)\n", device, ppdsb, pdsb);
1079 dsb = HeapAlloc(GetProcessHeap(),0,sizeof(*dsb));
1080 if (dsb == NULL) {
1081 WARN("out of memory\n");
1082 *ppdsb = NULL;
1083 return DSERR_OUTOFMEMORY;
1085 CopyMemory(dsb, pdsb, sizeof(*dsb));
1087 dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx);
1088 if (dsb->pwfx == NULL) {
1089 HeapFree(GetProcessHeap(),0,dsb);
1090 *ppdsb = NULL;
1091 return DSERR_OUTOFMEMORY;
1094 dsb->buffer->ref++;
1095 list_add_head(&dsb->buffer->buffers, &dsb->entry);
1096 dsb->ref = 1;
1097 dsb->numIfaces = 1;
1098 dsb->state = STATE_STOPPED;
1099 dsb->buf_mixpos = dsb->sec_mixpos = 0;
1100 dsb->notify = NULL;
1101 dsb->notifies = NULL;
1102 dsb->nrofnotifies = 0;
1103 dsb->device = device;
1104 dsb->ds3db = NULL;
1105 dsb->iks = NULL; /* FIXME? */
1106 DSOUND_RecalcFormat(dsb);
1108 RtlInitializeResource(&dsb->lock);
1110 /* register buffer */
1111 hres = DirectSoundDevice_AddBuffer(device, dsb);
1112 if (hres != DS_OK) {
1113 RtlDeleteResource(&dsb->lock);
1114 list_remove(&dsb->entry);
1115 dsb->buffer->ref--;
1116 HeapFree(GetProcessHeap(),0,dsb->pwfx);
1117 HeapFree(GetProcessHeap(),0,dsb);
1118 dsb = NULL;
1121 *ppdsb = dsb;
1122 return hres;
1125 /*******************************************************************************
1126 * IKsBufferPropertySet
1129 /* IUnknown methods */
1130 static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
1131 LPKSPROPERTYSET iface,
1132 REFIID riid,
1133 LPVOID *ppobj )
1135 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1136 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1138 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
1141 static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
1143 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1144 ULONG ref = InterlockedIncrement(&(This->ref));
1145 TRACE("(%p) ref was %d\n", This, ref - 1);
1146 return ref;
1149 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
1151 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1152 ULONG ref = InterlockedDecrement(&(This->ref));
1153 TRACE("(%p) ref was %d\n", This, ref + 1);
1155 if (!ref) {
1156 This->dsb->iks = 0;
1157 IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
1158 HeapFree(GetProcessHeap(), 0, This);
1159 TRACE("(%p) released\n", This);
1161 return ref;
1164 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
1165 LPKSPROPERTYSET iface,
1166 REFGUID guidPropSet,
1167 ULONG dwPropID,
1168 LPVOID pInstanceData,
1169 ULONG cbInstanceData,
1170 LPVOID pPropData,
1171 ULONG cbPropData,
1172 PULONG pcbReturned )
1174 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1176 TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1177 This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1179 return E_PROP_ID_UNSUPPORTED;
1182 static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
1183 LPKSPROPERTYSET iface,
1184 REFGUID guidPropSet,
1185 ULONG dwPropID,
1186 LPVOID pInstanceData,
1187 ULONG cbInstanceData,
1188 LPVOID pPropData,
1189 ULONG cbPropData )
1191 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1193 TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1195 return E_PROP_ID_UNSUPPORTED;
1198 static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
1199 LPKSPROPERTYSET iface,
1200 REFGUID guidPropSet,
1201 ULONG dwPropID,
1202 PULONG pTypeSupport )
1204 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1206 TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1208 return E_PROP_ID_UNSUPPORTED;
1211 static const IKsPropertySetVtbl iksbvt = {
1212 IKsBufferPropertySetImpl_QueryInterface,
1213 IKsBufferPropertySetImpl_AddRef,
1214 IKsBufferPropertySetImpl_Release,
1215 IKsBufferPropertySetImpl_Get,
1216 IKsBufferPropertySetImpl_Set,
1217 IKsBufferPropertySetImpl_QuerySupport
1220 HRESULT IKsBufferPropertySetImpl_Create(
1221 IDirectSoundBufferImpl *dsb,
1222 IKsBufferPropertySetImpl **piks)
1224 IKsBufferPropertySetImpl *iks;
1225 TRACE("(%p,%p)\n",dsb,piks);
1226 *piks = NULL;
1228 iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
1229 if (iks == 0) {
1230 WARN("out of memory\n");
1231 *piks = NULL;
1232 return DSERR_OUTOFMEMORY;
1235 iks->ref = 0;
1236 iks->dsb = dsb;
1237 dsb->iks = iks;
1238 iks->lpVtbl = &iksbvt;
1240 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
1242 *piks = iks;
1243 return S_OK;
1246 HRESULT IKsBufferPropertySetImpl_Destroy(
1247 IKsBufferPropertySetImpl *piks)
1249 TRACE("(%p)\n",piks);
1251 while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
1253 return S_OK;