ole32: Fix memory leaks in the storage test.
[wine] / dlls / dsound / propset.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 #define COBJMACROS
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "mmsystem.h"
29 #include "winternl.h"
30 #include "winnls.h"
31 #include "vfwmsgs.h"
32 #include "mmddk.h"
33 #include "wine/debug.h"
34 #include "dsound.h"
35 #include "dsdriver.h"
36 #include "dsound_private.h"
37 #include "dsconf.h"
38
39 #ifdef NONAMELESSSTRUCT
40 # define S(x) (x).s
41 #else
42 # define S(x) (x)
43 #endif
44
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
46
47 /*******************************************************************************
48  *              IKsPrivatePropertySet
49  */
50
51 /* IUnknown methods */
52 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
53     LPKSPROPERTYSET iface,
54     REFIID riid,
55     LPVOID *ppobj )
56 {
57     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
58     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
59
60     if (IsEqualIID(riid, &IID_IUnknown) ||
61         IsEqualIID(riid, &IID_IKsPropertySet)) {
62         *ppobj = iface;
63         IUnknown_AddRef(iface);
64         return S_OK;
65     }
66     *ppobj = NULL;
67     return E_NOINTERFACE;
68 }
69
70 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
71 {
72     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
73     ULONG ref = InterlockedIncrement(&(This->ref));
74     TRACE("(%p) ref was %d\n", This, ref - 1);
75     return ref;
76 }
77
78 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
79 {
80     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
81     ULONG ref = InterlockedDecrement(&(This->ref));
82     TRACE("(%p) ref was %d\n", This, ref + 1);
83
84     if (!ref) {
85         HeapFree(GetProcessHeap(), 0, This);
86         TRACE("(%p) released\n", This);
87     }
88     return ref;
89 }
90
91 static HRESULT DSPROPERTY_WaveDeviceMappingW(
92     LPVOID pPropData,
93     ULONG cbPropData,
94     PULONG pcbReturned )
95 {
96     HRESULT hr = DSERR_INVALIDPARAM;
97     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd;
98     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
99           pPropData,cbPropData,pcbReturned);
100
101     ppd = pPropData;
102
103     if (!ppd) {
104         WARN("invalid parameter: pPropData\n");
105         return DSERR_INVALIDPARAM;
106     }
107
108     if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
109         ULONG wod;
110         unsigned int wodn;
111         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
112         wodn = waveOutGetNumDevs();
113         for (wod = 0; wod < wodn; wod++) {
114             WAVEOUTCAPSW capsW;
115             MMRESULT res;
116             res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW));
117             if (res == MMSYSERR_NOERROR) {
118                 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
119                     ppd->DeviceId = DSOUND_renderer_guid;
120                     ppd->DeviceId.Data4[7] = wod;
121                     hr = DS_OK;
122                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
123                           debugstr_w(ppd->DeviceName));
124                     break;
125                 }
126             }
127         }
128     } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
129         ULONG wid;
130         unsigned int widn;
131         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
132         widn = waveInGetNumDevs();
133         for (wid = 0; wid < widn; wid++) {
134             WAVEINCAPSW capsW;
135             MMRESULT res;
136             res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
137             if (res == MMSYSERR_NOERROR) {
138                 if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
139                     ppd->DeviceId = DSOUND_capture_guid;
140                     ppd->DeviceId.Data4[7] = wid;
141                     hr = DS_OK;
142                     TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
143                           debugstr_w(ppd->DeviceName));
144                     break;
145                 }
146             }
147         }
148     }
149
150     if (pcbReturned)
151         *pcbReturned = cbPropData;
152
153     return hr;
154 }
155
156 static HRESULT DSPROPERTY_WaveDeviceMappingA(
157     LPVOID pPropData,
158     ULONG cbPropData,
159     PULONG pcbReturned )
160 {
161     DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA *ppd = pPropData;
162     DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA data;
163     DWORD len;
164     HRESULT hr;
165
166     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
167       pPropData,cbPropData,pcbReturned);
168
169     if (!ppd || !ppd->DeviceName) {
170         WARN("invalid parameter: ppd=%p\n", ppd);
171         return DSERR_INVALIDPARAM;
172     }
173
174     data.DataFlow = ppd->DataFlow;
175     len = MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, NULL, 0);
176     data.DeviceName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
177     if (!data.DeviceName)
178         return E_OUTOFMEMORY;
179     MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, data.DeviceName, len);
180
181     hr = DSPROPERTY_WaveDeviceMappingW(&data, cbPropData, pcbReturned);
182     HeapFree(GetProcessHeap(), 0, data.DeviceName);
183     ppd->DeviceId = data.DeviceId;
184
185     if (pcbReturned)
186         *pcbReturned = cbPropData;
187
188     return hr;
189 }
190
191 static HRESULT DSPROPERTY_DescriptionW(
192     LPVOID pPropData,
193     ULONG cbPropData,
194     PULONG pcbReturned )
195 {
196     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData;
197     HRESULT err;
198     GUID dev_guid;
199     ULONG wod, wid, wodn, widn;
200     DSDRIVERDESC desc;
201
202     TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
203           pPropData,cbPropData,pcbReturned);
204
205     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
206     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
207         /* default device of type specified by ppd->DataFlow */
208         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
209             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
210             ppd->DeviceId = DSDEVID_DefaultCapture;
211         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
212             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
213             ppd->DeviceId = DSDEVID_DefaultPlayback;
214         } else {
215             WARN("DataFlow=Unknown(%d)\n", ppd->DataFlow);
216             return E_PROP_ID_UNSUPPORTED;
217         }
218     }
219
220     GetDeviceID(&ppd->DeviceId, &dev_guid);
221
222     wodn = waveOutGetNumDevs();
223     widn = waveInGetNumDevs();
224     wid = wod = dev_guid.Data4[7];
225     if (!memcmp(&dev_guid, &DSOUND_renderer_guid, sizeof(GUID)-1)
226         && wod < wodn)
227     {
228         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
229         ppd->WaveDeviceId = wod;
230     }
231     else if (!memcmp(&dev_guid, &DSOUND_capture_guid, sizeof(GUID)-1)
232              && wid < widn)
233     {
234         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
235         ppd->WaveDeviceId = wid;
236     }
237     else
238     {
239         WARN("Device not found\n");
240         return E_PROP_ID_UNSUPPORTED;
241     }
242
243     if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
244         err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
245     else
246         err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0);
247
248     if (err != MMSYSERR_NOERROR)
249     {
250         WARN("waveMessage(DRV_QUERYDSOUNDDESC) failed!\n");
251         return E_PROP_ID_UNSUPPORTED;
252     }
253     else
254     {
255         /* FIXME: Still a memory leak.. */
256         int desclen, modlen;
257         static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
258
259         modlen = MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, NULL, 0 );
260         desclen = MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, NULL, 0 );
261         ppd->Module = HeapAlloc(GetProcessHeap(),0,modlen*sizeof(WCHAR));
262         ppd->Description = HeapAlloc(GetProcessHeap(),0,desclen*sizeof(WCHAR));
263         ppd->Interface = wInterface;
264         if (!ppd->Description || !ppd->Module)
265         {
266             WARN("Out of memory\n");
267             HeapFree(GetProcessHeap(), 0, ppd->Description);
268             HeapFree(GetProcessHeap(), 0, ppd->Module);
269             ppd->Description = ppd->Module = NULL;
270             return E_OUTOFMEMORY;
271         }
272
273         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->Module, modlen );
274         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->Description, desclen );
275     }
276
277     ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
278
279     if (pcbReturned) {
280         *pcbReturned = sizeof(*ppd);
281         TRACE("*pcbReturned=%d\n", *pcbReturned);
282     }
283
284     return S_OK;
285 }
286
287 static HRESULT DSPROPERTY_EnumerateW(
288     LPVOID pPropData,
289     ULONG cbPropData,
290     PULONG pcbReturned )
291 {
292     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
293     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
294     BOOL ret;
295     int widn, wodn, i;
296     TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
297           pPropData,cbPropData,pcbReturned);
298
299     if (pcbReturned)
300         *pcbReturned = 0;
301
302     if (!ppd || !ppd->Callback)
303     {
304         WARN("Invalid ppd %p\n", ppd);
305         return E_PROP_ID_UNSUPPORTED;
306     }
307
308     wodn = waveOutGetNumDevs();
309     widn = waveInGetNumDevs();
310
311     data.DeviceId = DSOUND_renderer_guid;
312     for (i = 0; i < wodn; ++i)
313     {
314         HRESULT hr;
315         data.DeviceId.Data4[7] = i;
316         hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
317         if (FAILED(hr))
318         {
319             ERR("DescriptionW failed!\n");
320             return S_OK;
321         }
322         ret = ppd->Callback(&data, ppd->Context);
323         HeapFree(GetProcessHeap(), 0, data.Module);
324         HeapFree(GetProcessHeap(), 0, data.Description);
325         if (!ret)
326             return S_OK;
327     }
328
329     data.DeviceId = DSOUND_capture_guid;
330     for (i = 0; i < widn; ++i)
331     {
332         HRESULT hr;
333         data.DeviceId.Data4[7] = i;
334         hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
335         if (FAILED(hr))
336         {
337             ERR("DescriptionW failed!\n");
338             return S_OK;
339         }
340         ret = ppd->Callback(&data, ppd->Context);
341         HeapFree(GetProcessHeap(), 0, data.Module);
342         HeapFree(GetProcessHeap(), 0, data.Description);
343         if (!ret)
344             return S_OK;
345     }
346     return S_OK;
347 }
348
349 static BOOL DSPROPERTY_descWtoA(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
350                                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *dataA)
351 {
352     DWORD modlen, desclen;
353     static char Interface[] = "Interface";
354
355     modlen = WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, NULL, 0, NULL, NULL);
356     desclen = WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, NULL, 0, NULL, NULL);
357     dataA->Type = dataW->Type;
358     dataA->DataFlow = dataW->DataFlow;
359     dataA->DeviceId = dataW->DeviceId;
360     dataA->WaveDeviceId = dataW->WaveDeviceId;
361     dataA->Interface = Interface;
362     dataA->Module = HeapAlloc(GetProcessHeap(), 0, modlen);
363     dataA->Description = HeapAlloc(GetProcessHeap(), 0, desclen);
364     if (!dataA->Module || !dataA->Description)
365     {
366         HeapFree(GetProcessHeap(), 0, dataA->Module);
367         HeapFree(GetProcessHeap(), 0, dataA->Description);
368         dataA->Module = dataA->Description = NULL;
369         return FALSE;
370     }
371
372     WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, dataA->Module, modlen, NULL, NULL);
373     WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, dataA->Description, desclen, NULL, NULL);
374     return TRUE;
375 }
376
377 static void DSPROPERTY_descWto1(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
378                                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *data1)
379 {
380     data1->DeviceId = dataW->DeviceId;
381     lstrcpynW(data1->ModuleW, dataW->Module, sizeof(data1->ModuleW)/sizeof(*data1->ModuleW));
382     lstrcpynW(data1->DescriptionW, dataW->Description, sizeof(data1->DescriptionW)/sizeof(*data1->DescriptionW));
383     WideCharToMultiByte(CP_ACP, 0, data1->DescriptionW, -1, data1->DescriptionA, sizeof(data1->DescriptionA)-1, NULL, NULL);
384     WideCharToMultiByte(CP_ACP, 0, data1->ModuleW, -1, data1->ModuleA, sizeof(data1->ModuleA)-1, NULL, NULL);
385     data1->DescriptionA[sizeof(data1->DescriptionA)-1] = 0;
386     data1->ModuleA[sizeof(data1->ModuleA)-1] = 0;
387     data1->Type = dataW->Type;
388     data1->DataFlow = dataW->DataFlow;
389     data1->WaveDeviceId = data1->Devnode = dataW->WaveDeviceId;
390 }
391
392 static BOOL CALLBACK DSPROPERTY_enumWtoA(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data)
393 {
394     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA descA;
395     DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = data;
396     BOOL ret;
397
398     ret = DSPROPERTY_descWtoA(descW, &descA);
399     if (!ret)
400         return FALSE;
401     ret = ppd->Callback(&descA, ppd->Context);
402     HeapFree(GetProcessHeap(), 0, descA.Module);
403     HeapFree(GetProcessHeap(), 0, descA.Description);
404     return ret;
405 }
406
407 static HRESULT DSPROPERTY_EnumerateA(
408     LPVOID pPropData,
409     ULONG cbPropData,
410     PULONG pcbReturned)
411 {
412     DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = pPropData;
413     DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data;
414
415     if (!ppd || !ppd->Callback)
416     {
417         WARN("Invalid ppd %p\n", ppd);
418         return E_PROP_ID_UNSUPPORTED;
419     }
420
421     data.Callback = DSPROPERTY_enumWtoA;
422     data.Context = ppd;
423
424     return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned);
425 }
426
427 static BOOL CALLBACK DSPROPERTY_enumWto1(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data)
428 {
429     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA desc1;
430     DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = data;
431     BOOL ret;
432
433     DSPROPERTY_descWto1(descW, &desc1);
434     ret = ppd->Callback(&desc1, ppd->Context);
435     return ret;
436 }
437
438 static HRESULT DSPROPERTY_Enumerate1(
439     LPVOID pPropData,
440     ULONG cbPropData,
441     PULONG pcbReturned)
442 {
443     DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = pPropData;
444     DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data;
445
446     if (!ppd || !ppd->Callback)
447     {
448         WARN("Invalid ppd %p\n", ppd);
449         return E_PROP_ID_UNSUPPORTED;
450     }
451
452     data.Callback = DSPROPERTY_enumWto1;
453     data.Context = ppd;
454
455     return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned);
456 }
457
458 static HRESULT DSPROPERTY_DescriptionA(
459     LPVOID pPropData,
460     ULONG cbPropData,
461     PULONG pcbReturned)
462 {
463     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
464     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *ppd = pPropData;
465     HRESULT hr;
466
467     if (pcbReturned)
468         *pcbReturned = sizeof(*ppd);
469     if (!pPropData)
470         return S_OK;
471
472     data.DeviceId = ppd->DeviceId;
473     data.DataFlow = ppd->DataFlow;
474     hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
475     if (FAILED(hr))
476         return hr;
477     if (!DSPROPERTY_descWtoA(&data, ppd))
478         hr = E_OUTOFMEMORY;
479     HeapFree(GetProcessHeap(), 0, data.Module);
480     HeapFree(GetProcessHeap(), 0, data.Interface);
481     return hr;
482 }
483
484 static HRESULT DSPROPERTY_Description1(
485     LPVOID pPropData,
486     ULONG cbPropData,
487     PULONG pcbReturned)
488 {
489     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
490     DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *ppd = pPropData;
491     HRESULT hr;
492
493     if (pcbReturned)
494         *pcbReturned = sizeof(*ppd);
495     if (!pPropData)
496         return S_OK;
497
498     data.DeviceId = ppd->DeviceId;
499     data.DataFlow = ppd->DataFlow;
500     hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
501     if (FAILED(hr))
502         return hr;
503     DSPROPERTY_descWto1(&data, ppd);
504     HeapFree(GetProcessHeap(), 0, data.Module);
505     HeapFree(GetProcessHeap(), 0, data.Interface);
506     return hr;
507 }
508
509 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
510     LPKSPROPERTYSET iface,
511     REFGUID guidPropSet,
512     ULONG dwPropID,
513     LPVOID pInstanceData,
514     ULONG cbInstanceData,
515     LPVOID pPropData,
516     ULONG cbPropData,
517     PULONG pcbReturned )
518 {
519     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
520     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
521           This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
522
523     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
524         switch (dwPropID) {
525         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
526             return DSPROPERTY_WaveDeviceMappingA(pPropData,cbPropData,pcbReturned);
527         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
528             return DSPROPERTY_Description1(pPropData,cbPropData,pcbReturned);
529         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
530             return DSPROPERTY_Enumerate1(pPropData,cbPropData,pcbReturned);
531         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
532             return DSPROPERTY_WaveDeviceMappingW(pPropData,cbPropData,pcbReturned);
533         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
534             return DSPROPERTY_DescriptionA(pPropData,cbPropData,pcbReturned);
535         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
536             return DSPROPERTY_DescriptionW(pPropData,cbPropData,pcbReturned);
537         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
538             return DSPROPERTY_EnumerateA(pPropData,cbPropData,pcbReturned);
539         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
540             return DSPROPERTY_EnumerateW(pPropData,cbPropData,pcbReturned);
541         default:
542             FIXME("unsupported ID: %d\n",dwPropID);
543             break;
544         }
545     } else {
546         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
547     }
548
549     if (pcbReturned) {
550         *pcbReturned = 0;
551         FIXME("*pcbReturned=%d\n", *pcbReturned);
552     }
553
554     return E_PROP_ID_UNSUPPORTED;
555 }
556
557 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
558     LPKSPROPERTYSET iface,
559     REFGUID guidPropSet,
560     ULONG dwPropID,
561     LPVOID pInstanceData,
562     ULONG cbInstanceData,
563     LPVOID pPropData,
564     ULONG cbPropData )
565 {
566     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
567
568     FIXME("(%p,%s,%d,%p,%d,%p,%d), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
569     return E_PROP_ID_UNSUPPORTED;
570 }
571
572 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
573     LPKSPROPERTYSET iface,
574     REFGUID guidPropSet,
575     ULONG dwPropID,
576     PULONG pTypeSupport )
577 {
578     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
579     TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
580
581     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
582         switch (dwPropID) {
583         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
584             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
585             return S_OK;
586         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
587             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
588             return S_OK;
589         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
590             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
591             return S_OK;
592         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
593             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
594             return S_OK;
595         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
596             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
597             return S_OK;
598         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
599             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
600             return S_OK;
601         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
602             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
603             return S_OK;
604         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
605             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
606             return S_OK;
607         default:
608             FIXME("unsupported ID: %d\n",dwPropID);
609             break;
610         }
611     } else {
612         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
613     }
614
615     return E_PROP_ID_UNSUPPORTED;
616 }
617
618 static const IKsPropertySetVtbl ikspvt = {
619     IKsPrivatePropertySetImpl_QueryInterface,
620     IKsPrivatePropertySetImpl_AddRef,
621     IKsPrivatePropertySetImpl_Release,
622     IKsPrivatePropertySetImpl_Get,
623     IKsPrivatePropertySetImpl_Set,
624     IKsPrivatePropertySetImpl_QuerySupport
625 };
626
627 HRESULT IKsPrivatePropertySetImpl_Create(
628     REFIID riid,
629     IKsPrivatePropertySetImpl **piks)
630 {
631     IKsPrivatePropertySetImpl *iks;
632     TRACE("(%s, %p)\n", debugstr_guid(riid), piks);
633
634     if (!IsEqualIID(riid, &IID_IUnknown) &&
635         !IsEqualIID(riid, &IID_IKsPropertySet)) {
636         *piks = 0;
637         return E_NOINTERFACE;
638     }
639
640     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
641     iks->ref = 1;
642     iks->lpVtbl = &ikspvt;
643
644     *piks = iks;
645     return S_OK;
646 }