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