msvcrt: Added more read tests.
[wine] / dlls / dsound / buffer.c
1 /*                      DirectSound
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2002 TransGaming Technologies, Inc.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <stdarg.h>
23
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"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
38
39 /*******************************************************************************
40  *              IDirectSoundNotify
41  */
42
43 static inline struct IDirectSoundBufferImpl *impl_from_IDirectSoundNotify(IDirectSoundNotify *iface)
44 {
45     return CONTAINING_RECORD(iface, struct IDirectSoundBufferImpl, IDirectSoundNotify_iface);
46 }
47
48 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(IDirectSoundNotify *iface, REFIID riid,
49         void **ppobj)
50 {
51     IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
52
53     TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj);
54
55     return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
56 }
57
58 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(IDirectSoundNotify *iface)
59 {
60     IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
61     ULONG ref = InterlockedIncrement(&This->refn);
62
63     TRACE("(%p) ref was %d\n", This, ref - 1);
64
65     if(ref == 1)
66         InterlockedIncrement(&This->numIfaces);
67
68     return ref;
69 }
70
71 static ULONG WINAPI IDirectSoundNotifyImpl_Release(IDirectSoundNotify *iface)
72 {
73     IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
74     ULONG ref = InterlockedDecrement(&This->refn);
75
76     TRACE("(%p) ref was %d\n", This, ref + 1);
77
78     if (!ref && !InterlockedDecrement(&This->numIfaces))
79         secondarybuffer_destroy(This);
80
81     return ref;
82 }
83
84 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSoundNotify *iface,
85         DWORD howmuch, const DSBPOSITIONNOTIFY *notify)
86 {
87         IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
88
89         TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
90
91         if (howmuch > 0 && notify == NULL) {
92             WARN("invalid parameter: notify == NULL\n");
93             return DSERR_INVALIDPARAM;
94         }
95
96         if (TRACE_ON(dsound)) {
97             unsigned int        i;
98             for (i=0;i<howmuch;i++)
99                 TRACE("notify at %d to %p\n",
100                     notify[i].dwOffset,notify[i].hEventNotify);
101         }
102
103         if (howmuch > 0) {
104             /* Make an internal copy of the caller-supplied array.
105              * Replace the existing copy if one is already present. */
106             HeapFree(GetProcessHeap(), 0, This->notifies);
107             This->notifies = HeapAlloc(GetProcessHeap(), 0,
108                         howmuch * sizeof(DSBPOSITIONNOTIFY));
109
110             if (This->notifies == NULL) {
111                     WARN("out of memory\n");
112                     return DSERR_OUTOFMEMORY;
113             }
114             CopyMemory(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
115             This->nrofnotifies = howmuch;
116         } else {
117            HeapFree(GetProcessHeap(), 0, This->notifies);
118            This->notifies = NULL;
119            This->nrofnotifies = 0;
120         }
121
122         return S_OK;
123 }
124
125 static const IDirectSoundNotifyVtbl dsnvt =
126 {
127     IDirectSoundNotifyImpl_QueryInterface,
128     IDirectSoundNotifyImpl_AddRef,
129     IDirectSoundNotifyImpl_Release,
130     IDirectSoundNotifyImpl_SetNotificationPositions,
131 };
132
133 /*******************************************************************************
134  *              IDirectSoundBuffer
135  */
136
137 static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 *iface)
138 {
139     return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
140 }
141
142 static inline BOOL is_primary_buffer(IDirectSoundBufferImpl *This)
143 {
144     return (This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) != 0;
145 }
146
147 static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 *iface,
148         LPCWAVEFORMATEX wfex)
149 {
150     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
151
152     TRACE("(%p,%p)\n", iface, wfex);
153
154     if (is_primary_buffer(This))
155         return primarybuffer_SetFormat(This->device, wfex);
156     else {
157         WARN("not available for secondary buffers.\n");
158         return DSERR_INVALIDCALL;
159     }
160 }
161
162 static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 *iface, LONG vol)
163 {
164         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
165         LONG oldVol;
166
167         HRESULT hres = DS_OK;
168
169         TRACE("(%p,%d)\n",This,vol);
170
171         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
172                 WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags);
173                 return DSERR_CONTROLUNAVAIL;
174         }
175
176         if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
177                 WARN("invalid parameter: vol = %d\n", vol);
178                 return DSERR_INVALIDPARAM;
179         }
180
181         /* **** */
182         RtlAcquireResourceExclusive(&This->lock, TRUE);
183
184         if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
185                 oldVol = This->ds3db_lVolume;
186                 This->ds3db_lVolume = vol;
187                 if (vol != oldVol)
188                         /* recalc 3d volume, which in turn recalcs the pans */
189                         DSOUND_Calc3DBuffer(This);
190         } else {
191                 oldVol = This->volpan.lVolume;
192                 This->volpan.lVolume = vol;
193                 if (vol != oldVol)
194                         DSOUND_RecalcVolPan(&(This->volpan));
195         }
196
197         RtlReleaseResource(&This->lock);
198         /* **** */
199
200         return hres;
201 }
202
203 static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(IDirectSoundBuffer8 *iface, LONG *vol)
204 {
205         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
206
207         TRACE("(%p,%p)\n",This,vol);
208
209         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
210                 WARN("control unavailable\n");
211                 return DSERR_CONTROLUNAVAIL;
212         }
213
214         if (vol == NULL) {
215                 WARN("invalid parameter: vol == NULL\n");
216                 return DSERR_INVALIDPARAM;
217         }
218
219         *vol = This->volpan.lVolume;
220
221         return DS_OK;
222 }
223
224 static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *iface, DWORD freq)
225 {
226         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
227         DWORD oldFreq;
228
229         TRACE("(%p,%d)\n",This,freq);
230
231         if (is_primary_buffer(This)) {
232                 WARN("not available for primary buffers.\n");
233                 return DSERR_CONTROLUNAVAIL;
234         }
235
236         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
237                 WARN("control unavailable\n");
238                 return DSERR_CONTROLUNAVAIL;
239         }
240
241         if (freq == DSBFREQUENCY_ORIGINAL)
242                 freq = This->pwfx->nSamplesPerSec;
243
244         if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
245                 WARN("invalid parameter: freq = %d\n", freq);
246                 return DSERR_INVALIDPARAM;
247         }
248
249         /* **** */
250         RtlAcquireResourceExclusive(&This->lock, TRUE);
251
252         oldFreq = This->freq;
253         This->freq = freq;
254         if (freq != oldFreq) {
255                 This->freqAdjust = This->freq / (float)This->device->pwfx->nSamplesPerSec;
256                 This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
257                 DSOUND_RecalcFormat(This);
258         }
259
260         RtlReleaseResource(&This->lock);
261         /* **** */
262
263         return DS_OK;
264 }
265
266 static HRESULT WINAPI IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 *iface, DWORD reserved1,
267         DWORD reserved2, DWORD flags)
268 {
269         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
270         HRESULT hres = DS_OK;
271
272         TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
273
274         /* **** */
275         RtlAcquireResourceExclusive(&This->lock, TRUE);
276
277         This->playflags = flags;
278         if (This->state == STATE_STOPPED) {
279                 This->leadin = TRUE;
280                 This->state = STATE_STARTING;
281         } else if (This->state == STATE_STOPPING)
282                 This->state = STATE_PLAYING;
283
284         RtlReleaseResource(&This->lock);
285         /* **** */
286
287         return hres;
288 }
289
290 static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface)
291 {
292         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
293         HRESULT hres = DS_OK;
294
295         TRACE("(%p)\n",This);
296
297         /* **** */
298         RtlAcquireResourceExclusive(&This->lock, TRUE);
299
300         if (This->state == STATE_PLAYING)
301                 This->state = STATE_STOPPING;
302         else if (This->state == STATE_STARTING)
303         {
304                 This->state = STATE_STOPPED;
305                 DSOUND_CheckEvent(This, 0, 0);
306         }
307
308         RtlReleaseResource(&This->lock);
309         /* **** */
310
311         return hres;
312 }
313
314 static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface)
315 {
316     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
317     ULONG ref = InterlockedIncrement(&This->ref);
318
319     TRACE("(%p) ref was %d\n", This, ref - 1);
320
321     if(ref == 1)
322         InterlockedIncrement(&This->numIfaces);
323
324     return ref;
325 }
326
327 static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface)
328 {
329     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
330     ULONG ref;
331
332     if (is_primary_buffer(This)){
333         ref = capped_refcount_dec(&This->ref);
334         if(!ref)
335             capped_refcount_dec(&This->numIfaces);
336         TRACE("(%p) ref is now: %d\n", This, ref);
337         return ref;
338     }
339
340     ref = InterlockedDecrement(&This->ref);
341     if (!ref && !InterlockedDecrement(&This->numIfaces))
342             secondarybuffer_destroy(This);
343
344     TRACE("(%p) ref is now %d\n", This, ref);
345
346     return ref;
347 }
348
349 static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuffer8 *iface,
350         DWORD *playpos, DWORD *writepos)
351 {
352         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
353         DWORD pos;
354
355         TRACE("(%p,%p,%p)\n",This,playpos,writepos);
356
357         RtlAcquireResourceShared(&This->lock, TRUE);
358
359         pos = This->sec_mixpos;
360
361         /* sanity */
362         if (pos >= This->buflen){
363                 FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
364                 pos %= This->buflen;
365         }
366
367         if (playpos)
368                 *playpos = pos;
369         if (writepos)
370                 *writepos = pos;
371
372         if (writepos && This->state != STATE_STOPPED) {
373                 /* apply the documented 10ms lead to writepos */
374                 *writepos += This->writelead;
375                 *writepos %= This->buflen;
376         }
377
378         RtlReleaseResource(&This->lock);
379
380         TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
381                 playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount());
382
383         return DS_OK;
384 }
385
386 static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status)
387 {
388         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
389
390         TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId());
391
392         if (status == NULL) {
393                 WARN("invalid parameter: status = NULL\n");
394                 return DSERR_INVALIDPARAM;
395         }
396
397         *status = 0;
398         RtlAcquireResourceShared(&This->lock, TRUE);
399         if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
400                 *status |= DSBSTATUS_PLAYING;
401                 if (This->playflags & DSBPLAY_LOOPING)
402                         *status |= DSBSTATUS_LOOPING;
403         }
404         RtlReleaseResource(&This->lock);
405
406         TRACE("status=%x\n", *status);
407         return DS_OK;
408 }
409
410
411 static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(IDirectSoundBuffer8 *iface,
412         LPWAVEFORMATEX lpwf, DWORD wfsize, DWORD *wfwritten)
413 {
414     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
415     DWORD size;
416
417     TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
418
419     size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
420
421     if (lpwf) { /* NULL is valid */
422         if (wfsize >= size) {
423             CopyMemory(lpwf,This->pwfx,size);
424             if (wfwritten)
425                 *wfwritten = size;
426         } else {
427             WARN("invalid parameter: wfsize too small\n");
428             CopyMemory(lpwf,This->pwfx,wfsize);
429             if (wfwritten)
430                 *wfwritten = wfsize;
431             return DSERR_INVALIDPARAM;
432         }
433     } else {
434         if (wfwritten)
435             *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
436         else {
437             WARN("invalid parameter: wfwritten == NULL\n");
438             return DSERR_INVALIDPARAM;
439         }
440     }
441
442     return DS_OK;
443 }
444
445 static HRESULT WINAPI IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 *iface, DWORD writecursor,
446         DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
447         DWORD *audiobytes2, DWORD flags)
448 {
449         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
450         HRESULT hres = DS_OK;
451
452         TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", This, writecursor, writebytes, lplpaudioptr1,
453                 audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount());
454
455         if (!audiobytes1)
456             return DSERR_INVALIDPARAM;
457
458         /* when this flag is set, writecursor is meaningless and must be calculated */
459         if (flags & DSBLOCK_FROMWRITECURSOR) {
460                 /* GetCurrentPosition does too much magic to duplicate here */
461                 hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor);
462                 if (hres != DS_OK) {
463                         WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
464                         return hres;
465                 }
466         }
467
468         /* when this flag is set, writebytes is meaningless and must be set */
469         if (flags & DSBLOCK_ENTIREBUFFER)
470                 writebytes = This->buflen;
471
472         if (writecursor >= This->buflen) {
473                 WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
474                      writecursor, This->buflen);
475                 return DSERR_INVALIDPARAM;
476         }
477
478         if (writebytes > This->buflen) {
479                 WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
480                      writebytes, This->buflen);
481                 return DSERR_INVALIDPARAM;
482         }
483
484         /* **** */
485         RtlAcquireResourceShared(&This->lock, TRUE);
486
487         if (writecursor+writebytes <= This->buflen) {
488                 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
489                 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
490                         WARN("Overwriting mixing position, case 1\n");
491                 *audiobytes1 = writebytes;
492                 if (lplpaudioptr2)
493                         *(LPBYTE*)lplpaudioptr2 = NULL;
494                 if (audiobytes2)
495                         *audiobytes2 = 0;
496                 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
497                   *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
498                 TRACE("->%d.0\n",writebytes);
499         } else {
500                 DWORD remainder = writebytes + writecursor - This->buflen;
501                 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
502                 *audiobytes1 = This->buflen-writecursor;
503                 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
504                         WARN("Overwriting mixing position, case 2\n");
505                 if (lplpaudioptr2)
506                         *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
507                 if (audiobytes2)
508                         *audiobytes2 = writebytes-(This->buflen-writecursor);
509                 if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
510                         WARN("Overwriting mixing position, case 3\n");
511                 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
512         }
513
514         RtlReleaseResource(&This->lock);
515         /* **** */
516
517         return DS_OK;
518 }
519
520 static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuffer8 *iface,
521         DWORD newpos)
522 {
523         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
524         HRESULT hres = DS_OK;
525
526         TRACE("(%p,%d)\n",This,newpos);
527
528         /* **** */
529         RtlAcquireResourceExclusive(&This->lock, TRUE);
530
531         /* start mixing from this new location instead */
532         newpos %= This->buflen;
533         newpos -= newpos%This->pwfx->nBlockAlign;
534         This->sec_mixpos = newpos;
535
536         /* at this point, do not attempt to reset buffers, mess with primary mix position,
537            or anything like that to reduce latency. The data already prebuffered cannot be changed */
538
539         RtlReleaseResource(&This->lock);
540         /* **** */
541
542         return hres;
543 }
544
545 static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 *iface, LONG pan)
546 {
547         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
548         HRESULT hres = DS_OK;
549
550         TRACE("(%p,%d)\n",This,pan);
551
552         if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
553                 WARN("invalid parameter: pan = %d\n", pan);
554                 return DSERR_INVALIDPARAM;
555         }
556
557         /* You cannot use both pan and 3D controls */
558         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
559             (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
560                 WARN("control unavailable\n");
561                 return DSERR_CONTROLUNAVAIL;
562         }
563
564         /* **** */
565         RtlAcquireResourceExclusive(&This->lock, TRUE);
566
567         if (This->volpan.lPan != pan) {
568                 This->volpan.lPan = pan;
569                 DSOUND_RecalcVolPan(&(This->volpan));
570         }
571
572         RtlReleaseResource(&This->lock);
573         /* **** */
574
575         return hres;
576 }
577
578 static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(IDirectSoundBuffer8 *iface, LONG *pan)
579 {
580         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
581
582         TRACE("(%p,%p)\n",This,pan);
583
584         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
585                 WARN("control unavailable\n");
586                 return DSERR_CONTROLUNAVAIL;
587         }
588
589         if (pan == NULL) {
590                 WARN("invalid parameter: pan = NULL\n");
591                 return DSERR_INVALIDPARAM;
592         }
593
594         *pan = This->volpan.lPan;
595
596         return DS_OK;
597 }
598
599 static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface, void *p1, DWORD x1,
600         void *p2, DWORD x2)
601 {
602         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface), *iter;
603         HRESULT hres = DS_OK;
604
605         TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
606
607         if (!p2)
608                 x2 = 0;
609
610         if((p1 && ((BYTE*)p1 < This->buffer->memory || (BYTE*)p1 >= This->buffer->memory + This->buflen)) ||
611            (p2 && ((BYTE*)p2 < This->buffer->memory || (BYTE*)p2 >= This->buffer->memory + This->buflen)))
612                 return DSERR_INVALIDPARAM;
613
614         if (x1 || x2)
615         {
616                 RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
617                 LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
618                 {
619                         RtlAcquireResourceShared(&iter->lock, TRUE);
620                         if (x1)
621                         {
622                             if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
623                               hres = DSERR_INVALIDPARAM;
624                         }
625                         RtlReleaseResource(&iter->lock);
626                 }
627                 RtlReleaseResource(&This->device->buffer_list_lock);
628         }
629
630         return hres;
631 }
632
633 static HRESULT WINAPI IDirectSoundBufferImpl_Restore(IDirectSoundBuffer8 *iface)
634 {
635         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
636
637         FIXME("(%p):stub\n",This);
638         return DS_OK;
639 }
640
641 static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 *iface, DWORD *freq)
642 {
643         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
644
645         TRACE("(%p,%p)\n",This,freq);
646
647         if (freq == NULL) {
648                 WARN("invalid parameter: freq = NULL\n");
649                 return DSERR_INVALIDPARAM;
650         }
651
652         *freq = This->freq;
653         TRACE("-> %d\n", *freq);
654
655         return DS_OK;
656 }
657
658 static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, DWORD dwEffectsCount,
659         LPDSEFFECTDESC pDSFXDesc, DWORD *pdwResultCodes)
660 {
661         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
662         DWORD u;
663
664         FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
665
666         if (pdwResultCodes)
667                 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
668
669         WARN("control unavailable\n");
670         return DSERR_CONTROLUNAVAIL;
671 }
672
673 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 *iface,
674         DWORD dwFlags, DWORD dwEffectsCount, DWORD *pdwResultCodes)
675 {
676         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
677         DWORD u;
678
679         FIXME("(%p,%08u,%u,%p): stub, faking success\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
680
681         if (pdwResultCodes)
682                 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
683
684         WARN("control unavailable\n");
685         return DS_OK;
686 }
687
688 static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(IDirectSoundBuffer8 *iface,
689         REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
690 {
691         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
692
693         FIXME("(%p,%s,%u,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
694
695         WARN("control unavailable\n");
696         return DSERR_CONTROLUNAVAIL;
697 }
698
699 static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(IDirectSoundBuffer8 *iface,
700         IDirectSound *dsound, LPCDSBUFFERDESC dbsd)
701 {
702         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
703
704         WARN("(%p) already initialized\n", This);
705         return DSERR_ALREADYINITIALIZED;
706 }
707
708 static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 *iface, LPDSBCAPS caps)
709 {
710         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
711
712         TRACE("(%p)->(%p)\n",This,caps);
713
714         if (caps == NULL) {
715                 WARN("invalid parameter: caps == NULL\n");
716                 return DSERR_INVALIDPARAM;
717         }
718
719         if (caps->dwSize < sizeof(*caps)) {
720                 WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize);
721                 return DSERR_INVALIDPARAM;
722         }
723
724         caps->dwFlags = This->dsbd.dwFlags;
725         caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
726
727         caps->dwBufferBytes = This->buflen;
728
729         /* According to windows, this is zero*/
730         caps->dwUnlockTransferRate = 0;
731         caps->dwPlayCpuOverhead = 0;
732
733         return DS_OK;
734 }
735
736 static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8 *iface, REFIID riid,
737         void **ppobj)
738 {
739         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
740
741         TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
742
743         if (ppobj == NULL) {
744                 WARN("invalid parameter\n");
745                 return E_INVALIDARG;
746         }
747
748         *ppobj = NULL;  /* assume failure */
749
750         if ( IsEqualGUID(riid, &IID_IUnknown) ||
751              IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
752              IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
753                 IDirectSoundBuffer8_AddRef(iface);
754                 *ppobj = iface;
755                 return S_OK;
756         }
757
758         if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
759                 IDirectSoundNotify_AddRef(&This->IDirectSoundNotify_iface);
760                 *ppobj = &This->IDirectSoundNotify_iface;
761                 return S_OK;
762         }
763
764         if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
765             if(This->dsbd.dwFlags & DSBCAPS_CTRL3D){
766                 IDirectSound3DBuffer_AddRef(&This->IDirectSound3DBuffer_iface);
767                 *ppobj = &This->IDirectSound3DBuffer_iface;
768                 return S_OK;
769             }
770             TRACE("app requested IDirectSound3DBuffer on non-3D secondary buffer\n");
771             return E_NOINTERFACE;
772         }
773
774         if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
775                 ERR("app requested IDirectSound3DListener on secondary buffer\n");
776                 return E_NOINTERFACE;
777         }
778
779         if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
780                 IKsPropertySet_AddRef(&This->IKsPropertySet_iface);
781                 *ppobj = &This->IKsPropertySet_iface;
782                 return S_OK;
783         }
784
785         FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
786
787         return E_NOINTERFACE;
788 }
789
790 static const IDirectSoundBuffer8Vtbl dsbvt =
791 {
792         IDirectSoundBufferImpl_QueryInterface,
793         IDirectSoundBufferImpl_AddRef,
794         IDirectSoundBufferImpl_Release,
795         IDirectSoundBufferImpl_GetCaps,
796         IDirectSoundBufferImpl_GetCurrentPosition,
797         IDirectSoundBufferImpl_GetFormat,
798         IDirectSoundBufferImpl_GetVolume,
799         IDirectSoundBufferImpl_GetPan,
800         IDirectSoundBufferImpl_GetFrequency,
801         IDirectSoundBufferImpl_GetStatus,
802         IDirectSoundBufferImpl_Initialize,
803         IDirectSoundBufferImpl_Lock,
804         IDirectSoundBufferImpl_Play,
805         IDirectSoundBufferImpl_SetCurrentPosition,
806         IDirectSoundBufferImpl_SetFormat,
807         IDirectSoundBufferImpl_SetVolume,
808         IDirectSoundBufferImpl_SetPan,
809         IDirectSoundBufferImpl_SetFrequency,
810         IDirectSoundBufferImpl_Stop,
811         IDirectSoundBufferImpl_Unlock,
812         IDirectSoundBufferImpl_Restore,
813         IDirectSoundBufferImpl_SetFX,
814         IDirectSoundBufferImpl_AcquireResources,
815         IDirectSoundBufferImpl_GetObjectInPath
816 };
817
818 HRESULT IDirectSoundBufferImpl_Create(
819         DirectSoundDevice * device,
820         IDirectSoundBufferImpl **pdsb,
821         LPCDSBUFFERDESC dsbd)
822 {
823         IDirectSoundBufferImpl *dsb;
824         LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
825         HRESULT err = DS_OK;
826         DWORD capf = 0;
827         TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
828
829         if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
830                 WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes);
831                 *pdsb = NULL;
832                 return DSERR_INVALIDPARAM; /* FIXME: which error? */
833         }
834
835         dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
836
837         if (dsb == 0) {
838                 WARN("out of memory\n");
839                 *pdsb = NULL;
840                 return DSERR_OUTOFMEMORY;
841         }
842
843         TRACE("Created buffer at %p\n", dsb);
844
845         dsb->ref = 0;
846         dsb->refn = 0;
847         dsb->ref3D = 0;
848         dsb->refiks = 0;
849         dsb->numIfaces = 0;
850         dsb->device = device;
851         dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
852         dsb->IDirectSoundNotify_iface.lpVtbl = &dsnvt;
853         dsb->IDirectSound3DBuffer_iface.lpVtbl = &ds3dbvt;
854         dsb->IKsPropertySet_iface.lpVtbl = &iksbvt;
855
856         /* size depends on version */
857         CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
858
859         dsb->pwfx = DSOUND_CopyFormat(wfex);
860         if (dsb->pwfx == NULL) {
861                 HeapFree(GetProcessHeap(),0,dsb);
862                 *pdsb = NULL;
863                 return DSERR_OUTOFMEMORY;
864         }
865
866         if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
867                 dsb->buflen = dsbd->dwBufferBytes + 
868                         (dsbd->lpwfxFormat->nBlockAlign - 
869                         (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
870         else
871                 dsb->buflen = dsbd->dwBufferBytes;
872
873         dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
874         dsb->notifies = NULL;
875         dsb->nrofnotifies = 0;
876
877         /* Check necessary hardware mixing capabilities */
878         if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
879         else capf |= DSCAPS_SECONDARYMONO;
880         if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
881         else capf |= DSCAPS_SECONDARY8BIT;
882
883         TRACE("capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", capf, device->drvcaps.dwFlags);
884
885         /* Allocate an empty buffer */
886         dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
887         if (dsb->buffer == NULL) {
888                 WARN("out of memory\n");
889                 HeapFree(GetProcessHeap(),0,dsb->pwfx);
890                 HeapFree(GetProcessHeap(),0,dsb);
891                 *pdsb = NULL;
892                 return DSERR_OUTOFMEMORY;
893         }
894
895         /* Allocate system memory for buffer */
896         dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
897         if (dsb->buffer->memory == NULL) {
898                 WARN("out of memory\n");
899                 HeapFree(GetProcessHeap(),0,dsb->pwfx);
900                 HeapFree(GetProcessHeap(),0,dsb->buffer);
901                 HeapFree(GetProcessHeap(),0,dsb);
902                 *pdsb = NULL;
903                 return DSERR_OUTOFMEMORY;
904         }
905
906         dsb->buffer->ref = 1;
907         list_init(&dsb->buffer->buffers);
908         list_add_head(&dsb->buffer->buffers, &dsb->entry);
909         FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
910
911         /* It's not necessary to initialize values to zero since */
912         /* we allocated this structure with HEAP_ZERO_MEMORY... */
913         dsb->sec_mixpos = 0;
914         dsb->state = STATE_STOPPED;
915
916         dsb->freqAdjust = dsb->freq / (float)device->pwfx->nSamplesPerSec;
917         dsb->nAvgBytesPerSec = dsb->freq *
918                 dsbd->lpwfxFormat->nBlockAlign;
919
920         /* calculate fragment size and write lead */
921         DSOUND_RecalcFormat(dsb);
922
923         if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
924                 dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
925                 dsb->ds3db_ds3db.vPosition.x = 0.0;
926                 dsb->ds3db_ds3db.vPosition.y = 0.0;
927                 dsb->ds3db_ds3db.vPosition.z = 0.0;
928                 dsb->ds3db_ds3db.vVelocity.x = 0.0;
929                 dsb->ds3db_ds3db.vVelocity.y = 0.0;
930                 dsb->ds3db_ds3db.vVelocity.z = 0.0;
931                 dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
932                 dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
933                 dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
934                 dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
935                 dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
936                 dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
937                 dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
938                 dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
939                 dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
940
941                 dsb->ds3db_need_recalc = FALSE;
942                 DSOUND_Calc3DBuffer(dsb);
943         } else
944                 DSOUND_RecalcVolPan(&(dsb->volpan));
945
946         RtlInitializeResource(&dsb->lock);
947
948         /* register buffer if not primary */
949         if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
950                 err = DirectSoundDevice_AddBuffer(device, dsb);
951                 if (err != DS_OK) {
952                         HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
953                         HeapFree(GetProcessHeap(),0,dsb->buffer);
954                         RtlDeleteResource(&dsb->lock);
955                         HeapFree(GetProcessHeap(),0,dsb->pwfx);
956                         HeapFree(GetProcessHeap(),0,dsb);
957                         dsb = NULL;
958                 }
959         }
960
961         IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
962         *pdsb = dsb;
963         return err;
964 }
965
966 void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
967 {
968     ULONG ref = InterlockedIncrement(&This->numIfaces);
969
970     if (ref > 1)
971         WARN("Destroying buffer with %u in use interfaces\n", ref - 1);
972
973     DirectSoundDevice_RemoveBuffer(This->device, This);
974     RtlDeleteResource(&This->lock);
975
976     This->buffer->ref--;
977     list_remove(&This->entry);
978     if (This->buffer->ref == 0) {
979         HeapFree(GetProcessHeap(), 0, This->buffer->memory);
980         HeapFree(GetProcessHeap(), 0, This->buffer);
981     }
982
983     HeapFree(GetProcessHeap(), 0, This->notifies);
984     HeapFree(GetProcessHeap(), 0, This->pwfx);
985     HeapFree(GetProcessHeap(), 0, This);
986
987     TRACE("(%p) released\n", This);
988 }
989
990 HRESULT IDirectSoundBufferImpl_Duplicate(
991     DirectSoundDevice *device,
992     IDirectSoundBufferImpl **ppdsb,
993     IDirectSoundBufferImpl *pdsb)
994 {
995     IDirectSoundBufferImpl *dsb;
996     HRESULT hres = DS_OK;
997     TRACE("(%p,%p,%p)\n", device, ppdsb, pdsb);
998
999     dsb = HeapAlloc(GetProcessHeap(),0,sizeof(*dsb));
1000     if (dsb == NULL) {
1001         WARN("out of memory\n");
1002         *ppdsb = NULL;
1003         return DSERR_OUTOFMEMORY;
1004     }
1005
1006     RtlAcquireResourceShared(&pdsb->lock, TRUE);
1007
1008     CopyMemory(dsb, pdsb, sizeof(*dsb));
1009
1010     dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx);
1011
1012     RtlReleaseResource(&pdsb->lock);
1013
1014     if (dsb->pwfx == NULL) {
1015         HeapFree(GetProcessHeap(),0,dsb);
1016         *ppdsb = NULL;
1017         return DSERR_OUTOFMEMORY;
1018     }
1019
1020     dsb->buffer->ref++;
1021     list_add_head(&dsb->buffer->buffers, &dsb->entry);
1022     dsb->ref = 0;
1023     dsb->refn = 0;
1024     dsb->ref3D = 0;
1025     dsb->refiks = 0;
1026     dsb->numIfaces = 0;
1027     dsb->state = STATE_STOPPED;
1028     dsb->sec_mixpos = 0;
1029     dsb->notifies = NULL;
1030     dsb->nrofnotifies = 0;
1031     dsb->device = device;
1032     DSOUND_RecalcFormat(dsb);
1033
1034     RtlInitializeResource(&dsb->lock);
1035
1036     /* register buffer */
1037     hres = DirectSoundDevice_AddBuffer(device, dsb);
1038     if (hres != DS_OK) {
1039         RtlDeleteResource(&dsb->lock);
1040         list_remove(&dsb->entry);
1041         dsb->buffer->ref--;
1042         HeapFree(GetProcessHeap(),0,dsb->pwfx);
1043         HeapFree(GetProcessHeap(),0,dsb);
1044         dsb = NULL;
1045     }
1046
1047     IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
1048     *ppdsb = dsb;
1049     return hres;
1050 }
1051
1052 /*******************************************************************************
1053  *              IKsPropertySet
1054  */
1055
1056 static inline IDirectSoundBufferImpl *impl_from_IKsPropertySet(IKsPropertySet *iface)
1057 {
1058     return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IKsPropertySet_iface);
1059 }
1060
1061 /* IUnknown methods */
1062 static HRESULT WINAPI IKsPropertySetImpl_QueryInterface(IKsPropertySet *iface, REFIID riid,
1063         void **ppobj)
1064 {
1065     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1066
1067     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1068
1069     return IDirectSoundBuffer_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
1070 }
1071
1072 static ULONG WINAPI IKsPropertySetImpl_AddRef(IKsPropertySet *iface)
1073 {
1074     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1075     ULONG ref = InterlockedIncrement(&This->refiks);
1076
1077     TRACE("(%p) ref was %d\n", This, ref - 1);
1078
1079     if(ref == 1)
1080         InterlockedIncrement(&This->numIfaces);
1081
1082     return ref;
1083 }
1084
1085 static ULONG WINAPI IKsPropertySetImpl_Release(IKsPropertySet *iface)
1086 {
1087     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1088     ULONG ref;
1089
1090     if (is_primary_buffer(This)){
1091         ref = capped_refcount_dec(&This->refiks);
1092         if(!ref)
1093             capped_refcount_dec(&This->numIfaces);
1094         TRACE("(%p) ref is now: %d\n", This, ref);
1095         return ref;
1096     }
1097
1098     ref = InterlockedDecrement(&This->refiks);
1099     if (!ref && !InterlockedDecrement(&This->numIfaces))
1100         secondarybuffer_destroy(This);
1101
1102     TRACE("(%p) ref is now %d\n", This, ref);
1103
1104     return ref;
1105 }
1106
1107 static HRESULT WINAPI IKsPropertySetImpl_Get(IKsPropertySet *iface, REFGUID guidPropSet,
1108         ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
1109         ULONG cbPropData, ULONG *pcbReturned)
1110 {
1111     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1112
1113     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1114     This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1115
1116     return E_PROP_ID_UNSUPPORTED;
1117 }
1118
1119 static HRESULT WINAPI IKsPropertySetImpl_Set(IKsPropertySet *iface, REFGUID guidPropSet,
1120         ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
1121         ULONG cbPropData)
1122 {
1123     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1124
1125     TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1126
1127     return E_PROP_ID_UNSUPPORTED;
1128 }
1129
1130 static HRESULT WINAPI IKsPropertySetImpl_QuerySupport(IKsPropertySet *iface, REFGUID guidPropSet,
1131         ULONG dwPropID, ULONG *pTypeSupport)
1132 {
1133     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1134
1135     TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1136
1137     return E_PROP_ID_UNSUPPORTED;
1138 }
1139
1140 const IKsPropertySetVtbl iksbvt = {
1141     IKsPropertySetImpl_QueryInterface,
1142     IKsPropertySetImpl_AddRef,
1143     IKsPropertySetImpl_Release,
1144     IKsPropertySetImpl_Get,
1145     IKsPropertySetImpl_Set,
1146     IKsPropertySetImpl_QuerySupport
1147 };