Authors: Mike McCormack <mike@codeweavers.com>, Aric Stewart <aric@codeweavers.com...
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/fcntl.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>       /* Insomnia - pow() function */
34
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "winuser.h"
41 #include "winerror.h"
42 #include "mmsystem.h"
43 #include "winreg.h"
44 #include "winternl.h"
45 #include "winnls.h"
46 #include "mmddk.h"
47 #include "wine/windef16.h"
48 #include "wine/debug.h"
49 #include "dsound.h"
50 #include "dsdriver.h"
51 #include "dsound_private.h"
52 #include "initguid.h"
53 #include "dsconf.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
56
57
58 /*******************************************************************************
59  *              IKsBufferPropertySet
60  */
61
62 /* IUnknown methods */
63 static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
64     LPKSPROPERTYSET iface,
65     REFIID riid,
66     LPVOID *ppobj )
67 {
68     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
69     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
70
71     return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
72 }
73
74 static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
75 {
76     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
77     TRACE("(%p) ref was %ld\n", This, This->ref);
78     return InterlockedIncrement(&(This->ref));
79 }
80
81 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
82 {
83     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
84     ULONG ulReturn;
85
86     TRACE("(%p) ref was %ld\n", This, This->ref);
87     ulReturn = InterlockedDecrement(&(This->ref));
88     if (!ulReturn) {
89         This->dsb->iks = 0;
90         IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
91         HeapFree(GetProcessHeap(),0,This);
92         TRACE("(%p) released\n",This);
93     }
94     return ulReturn;
95 }
96
97 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
98     LPKSPROPERTYSET iface,
99     REFGUID guidPropSet,
100     ULONG dwPropID,
101     LPVOID pInstanceData,
102     ULONG cbInstanceData,
103     LPVOID pPropData,
104     ULONG cbPropData,
105     PULONG pcbReturned )
106 {
107     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
108     PIDSDRIVERPROPERTYSET ps;
109     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
110         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
111
112     if (This->dsb->hwbuf) {
113         IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
114
115         if (ps) {
116             DSPROPERTY prop;
117             HRESULT hres;
118
119             prop.s.Set = *guidPropSet;
120             prop.s.Id = dwPropID;
121             prop.s.Flags = 0;   /* unused */
122             prop.s.InstanceId = (ULONG)This->dsb->dsound;
123
124             hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
125
126             IDsDriverPropertySet_Release(ps);
127
128             return hres;
129         }
130     }
131
132     return E_PROP_ID_UNSUPPORTED;
133 }
134
135 static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
136     LPKSPROPERTYSET iface,
137     REFGUID guidPropSet,
138     ULONG dwPropID,
139     LPVOID pInstanceData,
140     ULONG cbInstanceData,
141     LPVOID pPropData,
142     ULONG cbPropData )
143 {
144     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
145     PIDSDRIVERPROPERTYSET ps;
146     TRACE("(%p,%s,%ld,%p,%ld,%p,%ld)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
147
148     if (This->dsb->hwbuf) {
149         IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
150
151         if (ps) {
152             DSPROPERTY prop;
153             HRESULT hres;
154
155             prop.s.Set = *guidPropSet;
156             prop.s.Id = dwPropID;
157             prop.s.Flags = 0;   /* unused */
158             prop.s.InstanceId = (ULONG)This->dsb->dsound;
159             hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
160
161             IDsDriverPropertySet_Release(ps);
162
163             return hres;
164         }
165     }
166
167     return E_PROP_ID_UNSUPPORTED;
168 }
169
170 static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
171     LPKSPROPERTYSET iface,
172     REFGUID guidPropSet,
173     ULONG dwPropID,
174     PULONG pTypeSupport )
175 {
176     IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
177     PIDSDRIVERPROPERTYSET ps;
178     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
179
180     if (This->dsb->hwbuf) {
181         IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
182
183         if (ps) {
184             HRESULT hres;
185
186             hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
187
188             IDsDriverPropertySet_Release(ps);
189
190             return hres;
191         }
192     }
193
194     return E_PROP_ID_UNSUPPORTED;
195 }
196
197 static IKsPropertySetVtbl iksbvt = {
198     IKsBufferPropertySetImpl_QueryInterface,
199     IKsBufferPropertySetImpl_AddRef,
200     IKsBufferPropertySetImpl_Release,
201     IKsBufferPropertySetImpl_Get,
202     IKsBufferPropertySetImpl_Set,
203     IKsBufferPropertySetImpl_QuerySupport
204 };
205
206 HRESULT WINAPI IKsBufferPropertySetImpl_Create(
207     IDirectSoundBufferImpl *dsb,
208     IKsBufferPropertySetImpl **piks)
209 {
210     IKsBufferPropertySetImpl *iks;
211     TRACE("(%p,%p)\n",dsb,piks);
212
213     iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
214     if (iks == 0) {
215         WARN("out of memory\n");
216         *piks = NULL;
217         return DSERR_OUTOFMEMORY;
218     }
219
220     iks->ref = 0;
221     iks->dsb = dsb;
222     dsb->iks = iks;
223     iks->lpVtbl = &iksbvt;
224
225     IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
226
227     *piks = iks;
228     return S_OK;
229 }
230
231 HRESULT WINAPI IKsBufferPropertySetImpl_Destroy(
232     IKsBufferPropertySetImpl *piks)
233 {
234     TRACE("(%p)\n",piks);
235
236     while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
237
238     return S_OK;
239 }
240
241 /*******************************************************************************
242  *              IKsPrivatePropertySet
243  */
244
245 /* IUnknown methods */
246 static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
247     LPKSPROPERTYSET iface,
248     REFIID riid,
249     LPVOID *ppobj )
250 {
251     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
252     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
253
254     *ppobj = NULL;
255     return DSERR_INVALIDPARAM;
256 }
257
258 static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface)
259 {
260     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
261     TRACE("(%p) ref was %ld\n", This, This->ref);
262     return InterlockedIncrement(&(This->ref));
263 }
264
265 static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface)
266 {
267     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
268     ULONG ulReturn;
269
270     TRACE("(%p) ref was %ld\n", This, This->ref);
271     ulReturn = InterlockedDecrement(&(This->ref));
272     if (ulReturn == 0) {
273         HeapFree(GetProcessHeap(),0,This);
274         TRACE("(%p) released\n",This);
275     }
276     return ulReturn;
277 }
278
279 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA(
280     REFGUID guidPropSet,
281     LPVOID pPropData,
282     ULONG cbPropData,
283     PULONG pcbReturned )
284 {
285     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA ppd;
286     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) not implemented!\n",
287         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
288
289     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA) pPropData;
290
291     if (!ppd) {
292         WARN("invalid parameter: pPropData\n");
293         return DSERR_INVALIDPARAM;
294     }
295
296     FIXME("DeviceName=%s\n",ppd->DeviceName);
297     FIXME("DataFlow=%s\n",
298         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? "DIRECTSOUNDDEVICE_DATAFLOW_RENDER" :
299         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE ? "DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE" : "UNKNOWN");
300
301     /* FIXME: match the name to a wave device somehow. */
302     ppd->DeviceId = GUID_NULL;
303
304     if (pcbReturned) {
305         *pcbReturned = cbPropData;
306         FIXME("*pcbReturned=%ld\n", *pcbReturned);
307     }
308
309     return S_OK;
310 }
311
312 static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW(
313     REFGUID guidPropSet,
314     LPVOID pPropData,
315     ULONG cbPropData,
316     PULONG pcbReturned )
317 {
318     PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd;
319     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) not implemented!\n",
320         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
321
322     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA) pPropData;
323
324     if (!ppd) {
325         WARN("invalid parameter: pPropData\n");
326         return DSERR_INVALIDPARAM;
327     }
328
329     FIXME("DeviceName=%s\n",debugstr_w(ppd->DeviceName));
330     FIXME("DataFlow=%s\n",
331         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? "DIRECTSOUNDDEVICE_DATAFLOW_RENDER" :
332         ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE ? "DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE" : "UNKNOWN");
333
334     /* FIXME: match the name to a wave device somehow. */
335     ppd->DeviceId = GUID_NULL;
336
337     if (pcbReturned) {
338         *pcbReturned = cbPropData;
339         FIXME("*pcbReturned=%ld\n", *pcbReturned);
340     }
341
342     return S_OK;
343 }
344
345 static HRESULT WINAPI DSPROPERTY_Description1(
346     REFGUID guidPropSet,
347     LPVOID pPropData,
348     ULONG cbPropData,
349     PULONG pcbReturned )
350 {
351     HRESULT err;
352     GUID guid, dev_guid;
353     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA ppd;
354     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
355         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
356
357     ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA) pPropData;
358
359     if (!ppd) {
360         WARN("invalid parameter: pPropData\n");
361         return DSERR_INVALIDPARAM;
362     }
363
364     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
365     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
366         /* default device of type specified by ppd->DataFlow */
367         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
368             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
369         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
370             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
371         } else {
372             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
373         }
374         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
375             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
376         return E_PROP_ID_UNSUPPORTED;
377     }
378
379     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
380     GetDeviceID(&ppd->DeviceId, &dev_guid);
381
382     if ( IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultPlayback) ||
383          IsEqualGUID( &ppd->DeviceId, &DSDEVID_DefaultVoicePlayback) ) {
384         ULONG wod;
385         unsigned int wodn;
386         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
387         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
388         wodn = waveOutGetNumDevs();
389         for (wod = 0; wod < wodn; wod++) {
390             if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
391                 DSDRIVERDESC desc;
392                 ppd->WaveDeviceId = wod;
393                 ppd->Devnode = wod;
394                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
395                 if (err == DS_OK) {
396                     PIDSDRIVER drv = NULL;
397                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
398                     strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
399                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
400                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
401                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
402                     if (err == DS_OK && drv)
403                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
404                     break;
405                 } else {
406                     WARN("waveOutMessage failed\n");
407                     return E_PROP_ID_UNSUPPORTED;
408                 }
409             }
410         }
411     } else if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
412                 IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
413         ULONG wid;
414         unsigned int widn;
415         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
416         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
417         widn = waveInGetNumDevs();
418         for (wid = 0; wid < widn; wid++) {
419             if (IsEqualGUID( &dev_guid, &guid) ) {
420                 DSDRIVERDESC desc;
421                 ppd->WaveDeviceId = wid;
422                 ppd->Devnode = wid;
423                 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
424                 if (err == DS_OK) {
425                     PIDSCDRIVER drv;
426                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
427                     strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
428                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
429                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
430                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
431                     if (err == DS_OK && drv)
432                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
433                     break;
434                 } else {
435                     WARN("waveInMessage failed\n");
436                     return E_PROP_ID_UNSUPPORTED;
437                 }
438             }
439         }
440     } else {
441         BOOL found = FALSE;
442         ULONG wod;
443         unsigned int wodn;
444         /* given specific device so try the render devices first */
445         wodn = waveOutGetNumDevs();
446         for (wod = 0; wod < wodn; wod++) {
447             if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
448                 DSDRIVERDESC desc;
449                 TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
450                 ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
451                 ppd->WaveDeviceId = wod;
452                 ppd->Devnode = wod;
453                 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
454                 if (err == DS_OK) {
455                     PIDSDRIVER drv = NULL;
456                     strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
457                     strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
458                     MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
459                     MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
460                     err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
461                     if (err == DS_OK && drv)
462                         ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
463                     found = TRUE;
464                     break;
465                 } else {
466                     WARN("waveOutMessage failed\n");
467                     return E_PROP_ID_UNSUPPORTED;
468                 }
469             }
470         }
471
472         if (found == FALSE) {
473             ULONG wid;
474             unsigned int widn;
475             /* given specific device so try the capture devices next */
476             widn = waveInGetNumDevs();
477             for (wid = 0; wid < widn; wid++) {
478                 if (IsEqualGUID( &ppd->DeviceId, &capture_guids[wid] ) ) {
479                     DSDRIVERDESC desc;
480                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
481                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
482                     ppd->WaveDeviceId = wid;
483                     ppd->Devnode = wid;
484                     err = mmErr(waveInMessage((HWAVEIN)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
485                     if (err == DS_OK) {
486                         PIDSDRIVER drv = NULL;
487                         strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
488                         strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
489                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
490                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
491                         err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
492                         if (err == DS_OK && drv)
493                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
494                         found = TRUE;
495                         break;
496                     } else {
497                         WARN("waveInMessage failed\n");
498                         return E_PROP_ID_UNSUPPORTED;
499                     }
500                 }
501             }
502
503             if (found == FALSE) {
504                 WARN("device not found\n");
505                 return E_PROP_ID_UNSUPPORTED;
506             }
507         }
508     }
509
510     if (pcbReturned) {
511         *pcbReturned = cbPropData;
512         TRACE("*pcbReturned=%ld\n", *pcbReturned);
513     }
514
515     return S_OK;
516 }
517
518 static HRESULT WINAPI DSPROPERTY_DescriptionA(
519     REFGUID guidPropSet,
520     LPVOID pPropData,
521     ULONG cbPropData,
522     PULONG pcbReturned )
523 {
524     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA) pPropData;
525     HRESULT err;
526     GUID dev_guid;
527     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
528         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
529
530     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
531     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
532         /* default device of type specified by ppd->DataFlow */
533         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
534             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
535         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
536             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
537         } else {
538             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
539         }
540         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
541             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
542         return E_PROP_ID_UNSUPPORTED;
543     }
544
545     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
546     GetDeviceID(&ppd->DeviceId, &dev_guid);
547
548     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
549          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
550         ULONG wod;
551         unsigned int wodn;
552         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
553         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
554         wodn = waveOutGetNumDevs();
555         for (wod = 0; wod < wodn; wod++) {
556                 if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
557                     DSDRIVERDESC desc;
558                     ppd->WaveDeviceId = wod;
559                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
560                     if (err == DS_OK) {
561                         PIDSDRIVER drv = NULL;
562                         /* FIXME: this is a memory leak */
563                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
564                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
565                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
566
567                         strcpy(szDescription, desc.szDesc);
568                         strcpy(szModule, desc.szDrvName);
569                         strcpy(szInterface, "Interface");
570
571                         ppd->Description = szDescription;
572                         ppd->Module = szModule;
573                         ppd->Interface = szInterface;
574                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
575                         if (err == DS_OK && drv)
576                             ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
577                         break;
578                     } else {
579                         WARN("waveOutMessage failed\n");
580                         return E_PROP_ID_UNSUPPORTED;
581                     }
582                 }
583         }
584     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
585                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
586         ULONG wid;
587         unsigned int widn;
588         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
589         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
590         widn = waveInGetNumDevs();
591         for (wid = 0; wid < widn; wid++) {
592                 if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
593                     DSDRIVERDESC desc;
594                     ppd->WaveDeviceId = wid;
595                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
596                     if (err == DS_OK) {
597                         PIDSCDRIVER drv;
598                         /* FIXME: this is a memory leak */
599                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
600                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
601                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
602
603                         strcpy(szDescription, desc.szDesc);
604                         strcpy(szModule, desc.szDrvName);
605                         strcpy(szInterface, "Interface");
606
607                         ppd->Description = szDescription;
608                         ppd->Module = szModule;
609                         ppd->Interface = szInterface;
610                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
611                         if (err == DS_OK && drv)
612                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
613                         break;
614                     } else {
615                         WARN("waveInMessage failed\n");
616                         return E_PROP_ID_UNSUPPORTED;
617                     }
618                 }
619         }
620     } else {
621         BOOL found = FALSE;
622         ULONG wod;
623         unsigned int wodn;
624         /* given specific device so try the render devices first */
625         wodn = waveOutGetNumDevs();
626         for (wod = 0; wod < wodn; wod++) {
627                 if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
628                     DSDRIVERDESC desc;
629                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
630                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
631                     ppd->WaveDeviceId = wod;
632                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
633                     if (err == DS_OK) {
634                         PIDSDRIVER drv = NULL;
635                         /* FIXME: this is a memory leak */
636                         CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
637                         CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
638                         CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
639
640                         strcpy(szDescription, desc.szDesc);
641                         strcpy(szModule, desc.szDrvName);
642                         strcpy(szInterface, "Interface");
643
644                         ppd->Description = szDescription;
645                         ppd->Module = szModule;
646                         ppd->Interface = szInterface;
647                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
648                         if (err == DS_OK && drv)
649                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
650                         found = TRUE;
651                         break;
652                     } else {
653                         WARN("waveOutMessage failed\n");
654                         return E_PROP_ID_UNSUPPORTED;
655                     }
656                 }
657         }
658
659         if (found == FALSE) {
660             WARN("device not found\n");
661             return E_PROP_ID_UNSUPPORTED;
662         }
663     }
664
665     if (pcbReturned) {
666         *pcbReturned = cbPropData;
667         TRACE("*pcbReturned=%ld\n", *pcbReturned);
668     }
669
670     return S_OK;
671 }
672
673 static HRESULT WINAPI DSPROPERTY_DescriptionW(
674     REFGUID guidPropSet,
675     LPVOID pPropData,
676     ULONG cbPropData,
677     PULONG pcbReturned )
678 {
679     PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData;
680     HRESULT err;
681     GUID dev_guid;
682     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
683         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
684
685     TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId));
686     if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) {
687         /* default device of type specified by ppd->DataFlow */
688         if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
689             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
690         } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
691             TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
692         } else {
693             TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow);
694         }
695         FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n",
696             debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
697         return E_PROP_ID_UNSUPPORTED;
698     }
699
700     ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED;
701     GetDeviceID(&ppd->DeviceId, &dev_guid);
702
703     if ( IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultPlayback) ||
704          IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoicePlayback) ) {
705         ULONG wod;
706         unsigned int wodn;
707         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
708         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
709         wodn = waveOutGetNumDevs();
710         for (wod = 0; wod < wodn; wod++) {
711                 if (IsEqualGUID( &dev_guid, &renderer_guids[wod] ) ) {
712                     DSDRIVERDESC desc;
713                     ppd->WaveDeviceId = wod;
714                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
715                     if (err == DS_OK) {
716                         PIDSDRIVER drv = NULL;
717                         /* FIXME: this is a memory leak */
718                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
719                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
720                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
721
722                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
723                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
724                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
725
726                         ppd->Description = wDescription;
727                         ppd->Module = wModule;
728                         ppd->Interface = wInterface;
729                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
730                         if (err == DS_OK && drv)
731                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
732                             break;
733                     } else {
734                         WARN("waveOutMessage failed\n");
735                         return E_PROP_ID_UNSUPPORTED;
736                     }
737                 }
738         }
739     } else if (IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultCapture) ||
740                IsEqualGUID( &ppd->DeviceId , &DSDEVID_DefaultVoiceCapture) ) {
741         ULONG wid;
742         unsigned int widn;
743         TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
744         ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
745         widn = waveInGetNumDevs();
746         for (wid = 0; wid < widn; wid++) {
747                 if (IsEqualGUID( &dev_guid, &capture_guids[wid] ) ) {
748                     DSDRIVERDESC desc;
749                     ppd->WaveDeviceId = wid;
750                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
751                     if (err == DS_OK) {
752                         PIDSCDRIVER drv;
753                         /* FIXME: this is a memory leak */
754                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
755                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
756                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
757
758                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
759                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
760                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
761
762                         ppd->Description = wDescription;
763                         ppd->Module = wModule;
764                         ppd->Interface = wInterface;
765                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&drv,0));
766                         if (err == DS_OK && drv)
767                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
768                         break;
769                     } else {
770                         WARN("waveInMessage failed\n");
771                         return E_PROP_ID_UNSUPPORTED;
772                     }
773                 }
774         }
775     } else {
776         BOOL found = FALSE;
777         ULONG wod;
778         unsigned int wodn;
779         /* given specific device so try the render devices first */
780         wodn = waveOutGetNumDevs();
781         for (wod = 0; wod < wodn; wod++) {
782                 if (IsEqualGUID( &ppd->DeviceId, &renderer_guids[wod] ) ) {
783                     DSDRIVERDESC desc;
784                     TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
785                     ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
786                     ppd->WaveDeviceId = wod;
787                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
788                     if (err == DS_OK) {
789                         PIDSDRIVER drv = NULL;
790                         /* FIXME: this is a memory leak */
791                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
792                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
793                         WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
794
795                         MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100  );
796                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
797                         MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
798
799                         ppd->Description = wDescription;
800                         ppd->Module = wModule;
801                         ppd->Interface = wInterface;
802                         err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
803                         if (err == DS_OK && drv)
804                                 ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
805                         found = TRUE;
806                         break;
807                     } else {
808                         WARN("waveOutMessage failed\n");
809                         return E_PROP_ID_UNSUPPORTED;
810                     }
811                 }
812         }
813
814         if (found == FALSE) {
815             WARN("device not found\n");
816             return E_PROP_ID_UNSUPPORTED;
817         }
818     }
819
820     if (pcbReturned) {
821         *pcbReturned = cbPropData;
822         TRACE("*pcbReturned=%ld\n", *pcbReturned);
823     }
824
825     return S_OK;
826 }
827
828 static HRESULT WINAPI DSPROPERTY_Enumerate1(
829     REFGUID guidPropSet,
830     LPVOID pPropData,
831     ULONG cbPropData,
832     PULONG pcbReturned )
833 {
834     FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
835         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
836     return E_PROP_ID_UNSUPPORTED;
837 }
838
839 static HRESULT WINAPI DSPROPERTY_EnumerateA(
840     REFGUID guidPropSet,
841     LPVOID pPropData,
842     ULONG cbPropData,
843     PULONG pcbReturned )
844 {
845     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA) pPropData;
846     HRESULT err;
847     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
848         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
849
850     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
851         if (ppd) {
852             if (ppd->Callback) {
853                 unsigned devs, wod, wid;
854                 DSDRIVERDESC desc;
855                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data;
856
857                 devs = waveOutGetNumDevs();
858                 for (wod = 0; wod < devs; ++wod) {
859                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
860                     if (err == DS_OK) {
861                         DWORD size;
862                         memset(&data, 0, sizeof(data));
863                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
864                         data.WaveDeviceId = wod;
865                         data.DeviceId = renderer_guids[wod];
866                         data.Description = desc.szDesc;
867                         data.Module = desc.szDrvName;
868                         err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
869                         if (err == DS_OK) {
870                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
871                             err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
872                             if (err == DS_OK) {
873                                 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
874                                 WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
875                                 data.Interface = szInterface;
876
877                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
878                                 (ppd->Callback)(&data, ppd->Context);
879
880                                 HeapFree(GetProcessHeap(),0,szInterface);
881                             }
882                             HeapFree(GetProcessHeap(),0,nameW);
883                         }
884                     }
885                 }
886
887                 devs = waveInGetNumDevs();
888                 for (wid = 0; wid < devs; ++wid) {
889                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
890                     if (err == DS_OK) {
891                         DWORD size;
892                         memset(&data, 0, sizeof(data));
893                         data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
894                         data.WaveDeviceId = wid;
895                         data.DeviceId = capture_guids[wid];
896                         data.Description = desc.szDesc;
897                         data.Module = desc.szDrvName;
898                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0));
899                         if (err == DS_OK) {
900                             WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size);
901                             err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size));
902                             if (err == DS_OK) {
903                                 CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR));
904                                 WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL );
905                                 data.Interface = szInterface;
906
907                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
908                                 (ppd->Callback)(&data, ppd->Context);
909
910                                 HeapFree(GetProcessHeap(),0,szInterface);
911                             }
912                             HeapFree(GetProcessHeap(),0,nameW);
913                         }
914                     }
915                 }
916
917                 return S_OK;
918             }
919         }
920     } else {
921         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
922     }
923
924     if (pcbReturned) {
925         *pcbReturned = 0;
926         FIXME("*pcbReturned=%ld\n", *pcbReturned);
927     }
928
929     return E_PROP_ID_UNSUPPORTED;
930 }
931
932 static HRESULT WINAPI DSPROPERTY_EnumerateW(
933     REFGUID guidPropSet,
934     LPVOID pPropData,
935     ULONG cbPropData,
936     PULONG pcbReturned )
937 {
938     PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData;
939     HRESULT err;
940     TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
941         debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned);
942
943     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
944         if (ppd) {
945             if (ppd->Callback) {
946                 unsigned devs, wod, wid;
947                 DSDRIVERDESC desc;
948                 DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
949
950                 devs = waveOutGetNumDevs();
951                 for (wod = 0; wod < devs; ++wod) {
952                     err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
953                     if (err == DS_OK) {
954                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
955                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
956                         DWORD size;
957                         err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
958                         if (err == DS_OK) {
959                             WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
960                             err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
961                             if (err == DS_OK) {
962                                 memset(&data, 0, sizeof(data));
963                                 data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
964                                 data.WaveDeviceId = wod;
965                                 data.DeviceId = renderer_guids[wod];
966
967                                 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
968                                 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
969
970                                 data.Description = wDescription;
971                                 data.Module = wModule;
972                                 data.Interface = wInterface;
973
974                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
975                                 (ppd->Callback)(&data, ppd->Context);
976                             }
977                             HeapFree(GetProcessHeap(),0,wInterface);
978                         }
979                         HeapFree(GetProcessHeap(),0,wDescription);
980                         HeapFree(GetProcessHeap(),0,wModule);
981                     }
982                 }
983
984                 devs = waveInGetNumDevs();
985                 for (wid = 0; wid < devs; ++wid) {
986                     err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
987                     if (err == DS_OK) {
988                         WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
989                         WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
990                         DWORD size;
991                         err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0));
992                         if (err == DS_OK) {
993                             WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size);
994                             err = mmErr(waveInMessage((HWAVEIN)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size));
995                             if (err == DS_OK) {
996                                 memset(&data, 0, sizeof(data));
997                                 data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
998                                 data.WaveDeviceId = wid;
999                                 data.DeviceId = capture_guids[wid];
1000
1001                                 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
1002                                 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
1003
1004                                 data.Description = wDescription;
1005                                 data.Module = wModule;
1006                                 data.Interface = wInterface;
1007                                 TRACE("calling Callback(%p,%p)\n", &data, ppd->Context);
1008                                 (ppd->Callback)(&data, ppd->Context);
1009                             }
1010                             HeapFree(GetProcessHeap(),0,wInterface);
1011                         }
1012                         HeapFree(GetProcessHeap(),0,wDescription);
1013                         HeapFree(GetProcessHeap(),0,wModule);
1014                     }
1015                 }
1016
1017                 return S_OK;
1018             }
1019         }
1020     } else {
1021         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1022     }
1023
1024     if (pcbReturned) {
1025         *pcbReturned = 0;
1026         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1027     }
1028
1029     return E_PROP_ID_UNSUPPORTED;
1030 }
1031
1032 static HRESULT WINAPI IKsPrivatePropertySetImpl_Get(
1033     LPKSPROPERTYSET iface,
1034     REFGUID guidPropSet,
1035     ULONG dwPropID,
1036     LPVOID pInstanceData,
1037     ULONG cbInstanceData,
1038     LPVOID pPropData,
1039     ULONG cbPropData,
1040     PULONG pcbReturned
1041 ) {
1042     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1043     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n",
1044         This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1045
1046     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1047         switch (dwPropID) {
1048         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1049             return DSPROPERTY_WaveDeviceMappingA(guidPropSet,pPropData,cbPropData,pcbReturned);
1050         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1051             return DSPROPERTY_Description1(guidPropSet,pPropData,cbPropData,pcbReturned);
1052         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1053             return DSPROPERTY_Enumerate1(guidPropSet,pPropData,cbPropData,pcbReturned);
1054         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1055             return DSPROPERTY_WaveDeviceMappingW(guidPropSet,pPropData,cbPropData,pcbReturned);
1056         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1057             return DSPROPERTY_DescriptionA(guidPropSet,pPropData,cbPropData,pcbReturned);
1058         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1059             return DSPROPERTY_DescriptionW(guidPropSet,pPropData,cbPropData,pcbReturned);
1060         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1061             return DSPROPERTY_EnumerateA(guidPropSet,pPropData,cbPropData,pcbReturned);
1062         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1063             return DSPROPERTY_EnumerateW(guidPropSet,pPropData,cbPropData,pcbReturned);
1064         default:
1065             FIXME("unsupported ID: %ld\n",dwPropID);
1066             break;
1067         }
1068     } else {
1069         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1070     }
1071
1072     if (pcbReturned) {
1073         *pcbReturned = 0;
1074         FIXME("*pcbReturned=%ld\n", *pcbReturned);
1075     }
1076
1077     return E_PROP_ID_UNSUPPORTED;
1078 }
1079
1080 static HRESULT WINAPI IKsPrivatePropertySetImpl_Set(
1081     LPKSPROPERTYSET iface,
1082     REFGUID guidPropSet,
1083     ULONG dwPropID,
1084     LPVOID pInstanceData,
1085     ULONG cbInstanceData,
1086     LPVOID pPropData,
1087     ULONG cbPropData )
1088 {
1089     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1090
1091     FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1092     return E_PROP_ID_UNSUPPORTED;
1093 }
1094
1095 static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport(
1096     LPKSPROPERTYSET iface,
1097     REFGUID guidPropSet,
1098     ULONG dwPropID,
1099     PULONG pTypeSupport )
1100 {
1101     IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface;
1102     TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1103
1104     if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) {
1105         switch (dwPropID) {
1106         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A:
1107             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1108             return S_OK;
1109         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1:
1110             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1111             return S_OK;
1112         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1:
1113             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1114             return S_OK;
1115         case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W:
1116             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1117             return S_OK;
1118         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A:
1119             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1120             return S_OK;
1121         case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W:
1122             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1123             return S_OK;
1124         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A:
1125             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1126             return S_OK;
1127         case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W:
1128             *pTypeSupport = KSPROPERTY_SUPPORT_GET;
1129             return S_OK;
1130         default:
1131             FIXME("unsupported ID: %ld\n",dwPropID);
1132             break;
1133         }
1134     } else {
1135         FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet));
1136     }
1137
1138     return E_PROP_ID_UNSUPPORTED;
1139 }
1140
1141 static IKsPropertySetVtbl ikspvt = {
1142     IKsPrivatePropertySetImpl_QueryInterface,
1143     IKsPrivatePropertySetImpl_AddRef,
1144     IKsPrivatePropertySetImpl_Release,
1145     IKsPrivatePropertySetImpl_Get,
1146     IKsPrivatePropertySetImpl_Set,
1147     IKsPrivatePropertySetImpl_QuerySupport
1148 };
1149
1150 HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
1151     IKsPrivatePropertySetImpl **piks)
1152 {
1153     IKsPrivatePropertySetImpl *iks;
1154
1155     iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
1156     iks->ref = 0;
1157     iks->lpVtbl = &ikspvt;
1158
1159     *piks = iks;
1160     return S_OK;
1161 }