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