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