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