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