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