Initialize and uninitialize COM properly.
[wine] / dlls / dsound / tests / propset.c
1 /*
2  * Unit tests for CLSID_DirectSoundPrivate property set functions
3  * (used by dxdiag)
4  *
5  * Copyright (c) 2003 Robert Reif
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 #define NONAMELESSSTRUCT
23 #define NONAMELESSUNION
24 #include <windows.h>
25
26 #include <math.h>
27 #include <stdlib.h>
28
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "dsound.h"
33 #include "initguid.h"
34 #include "dsconf.h"
35 #include "dxerr8.h"
36
37 #include "dsound_test.h"
38
39 #ifndef DSBCAPS_CTRLDEFAULT
40 #define DSBCAPS_CTRLDEFAULT \
41         DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME
42 #endif
43
44 DEFINE_GUID(DSPROPSETID_VoiceManager, \
45             0x62A69BAE,0xDF9D,0x11D1,0x99,0xA6,0x00,0xC0,0x4F,0xC9,0x9D,0x46);
46 DEFINE_GUID(DSPROPSETID_EAX20_ListenerProperties, \
47             0x306a6a8,0xb224,0x11d2,0x99,0xe5,0x0,0x0,0xe8,0xd8,0xc7,0x22);
48 DEFINE_GUID(DSPROPSETID_EAX20_BufferProperties, \
49             0x306a6a7,0xb224,0x11d2,0x99,0xe5,0x0,0x0,0xe8,0xd8,0xc7,0x22);
50 DEFINE_GUID(DSPROPSETID_I3DL2_ListenerProperties, \
51             0xDA0F0520,0x300A,0x11D3,0x8A,0x2B,0x00,0x60,0x97,0x0D,0xB0,0x11);
52 DEFINE_GUID(DSPROPSETID_I3DL2_BufferProperties, \
53             0xDA0F0521,0x300A,0x11D3,0x8A,0x2B,0x00,0x60,0x97,0x0D,0xB0,0x11);
54 DEFINE_GUID(DSPROPSETID_ZOOMFX_BufferProperties, \
55             0xCD5368E0,0x3450,0x11D3,0x8B,0x6E,0x00,0x10,0x5A,0x9B,0x7B,0xBC);
56
57 typedef HRESULT  (CALLBACK * MYPROC)(REFCLSID, REFIID, LPVOID *);
58
59 BOOL CALLBACK callback(PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA data,
60                        LPVOID context)
61 {
62     trace("found device:\n");
63     trace("\tType: %s\n",
64           data->Type == DIRECTSOUNDDEVICE_TYPE_EMULATED ? "Emulated" :
65           data->Type == DIRECTSOUNDDEVICE_TYPE_VXD ? "VxD" :
66           data->Type == DIRECTSOUNDDEVICE_TYPE_WDM ? "WDM" : "Unknown");
67     trace("\tDataFlow: %s\n",
68           data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? "Render" :
69           data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE ?
70           "Capture" : "Unknown");
71     trace("\tDeviceId: {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
72           data->DeviceId.Data1,data->DeviceId.Data2,data->DeviceId.Data3,
73           data->DeviceId.Data4[0],data->DeviceId.Data4[1],
74           data->DeviceId.Data4[2],data->DeviceId.Data4[3],
75           data->DeviceId.Data4[4],data->DeviceId.Data4[5],
76           data->DeviceId.Data4[6],data->DeviceId.Data4[7]);
77     trace("\tDescription: %s\n", data->Description);
78     trace("\tModule: %s\n", data->Module);
79     trace("\tInterface: %s\n", data->Interface);
80     trace("\tWaveDeviceId: %ld\n", data->WaveDeviceId);
81
82     return TRUE;
83 }
84
85 static void propset_private_tests()
86 {
87     HMODULE hDsound;
88     HRESULT rc;
89     IClassFactory * pcf;
90     IKsPropertySet * pps;
91     MYPROC fProc;
92     ULONG support;
93
94     hDsound = LoadLibrary("dsound.dll");
95     ok(hDsound!=0,"LoadLibrary(dsound.dll) failed\n");
96     if (hDsound==0)
97         return;
98
99     fProc = (MYPROC)GetProcAddress(hDsound, "DllGetClassObject");
100
101     /* try direct sound first */
102     rc = (fProc)(&CLSID_DirectSound, &IID_IClassFactory, (void **)0);
103     ok(rc==DSERR_INVALIDPARAM,"DllGetClassObject(CLSID_DirectSound, "
104        "IID_IClassFactory) should have returned DSERR_INVALIDPARAM, "
105        "returned: %s\n",DXGetErrorString8(rc));
106
107     rc = (fProc)(&CLSID_DirectSound, &IID_IClassFactory, (void **)(&pcf));
108     ok(pcf!=0, "DllGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
109        "failed: %s\n",DXGetErrorString8(rc));
110     if (pcf==0)
111         goto error;
112
113     /* direct sound doesn't have an IKsPropertySet */
114     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
115                                      (void **)0);
116     ok(rc==DSERR_INVALIDPARAM, "CreateInstance(IID_IKsPropertySet) should have "
117        "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
118
119     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
120                                      (void **)(&pps));
121     ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
122        "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
123
124     /* and the direct sound 8 version */
125     rc = (fProc)(&CLSID_DirectSound8, &IID_IClassFactory, (void **)(&pcf));
126     ok(pcf!=0, "DllGetClassObject(CLSID_DirectSound8, IID_IClassFactory) "
127        "failed: %s\n",DXGetErrorString8(rc));
128     if (pcf==0)
129         goto error;
130
131     /* direct sound 8 doesn't have an IKsPropertySet */
132     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
133                                      (void **)(&pps));
134     ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
135        "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
136
137     /* try direct sound capture next */
138     rc = (fProc)(&CLSID_DirectSoundCapture, &IID_IClassFactory,
139                  (void **)(&pcf));
140     ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture, IID_IClassFactory) "
141        "failed: %s\n",DXGetErrorString8(rc));
142     if (pcf==0)
143         goto error;
144
145     /* direct sound capture doesn't have an IKsPropertySet */
146     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
147                                      (void **)(&pps));
148     ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
149        "returned E_NOINTERFACE,returned: %s\n",DXGetErrorString8(rc));
150
151     /* and the direct sound capture 8 version */
152     rc = (fProc)(&CLSID_DirectSoundCapture8, &IID_IClassFactory,
153                  (void **)(&pcf));
154     ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture8, "
155        "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc));
156     if (pcf==0)
157         goto error;
158
159     /* direct sound capture 8 doesn't have an IKsPropertySet */
160     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
161                                      (void **)(&pps));
162     ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
163        "returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
164
165     /* try direct sound full duplex next */
166     rc = (fProc)(&CLSID_DirectSoundFullDuplex, &IID_IClassFactory,
167                  (void **)(&pcf));
168     ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundFullDuplex, "
169        "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc));
170     if (pcf==0)
171         goto error;
172
173     /* direct sound full duplex doesn't have an IKsPropertySet */
174     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
175                                      (void **)(&pps));
176     ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
177        "returned NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
178
179     /* try direct sound private last */
180     rc = (fProc)(&CLSID_DirectSoundPrivate, &IID_IClassFactory,
181                  (void **)(&pcf));
182     ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundPrivate, "
183        "IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc));
184     if (pcf==0)
185         goto error;
186
187     /* direct sound private does have an IKsPropertySet */
188     rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
189                                      (void **)(&pps));
190     ok(rc==DS_OK, "CreateInstance(IID_IKsPropertySet) failed: %s\n",
191        DXGetErrorString8(rc));
192     if (rc!=DS_OK)
193         goto error;
194
195     rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice,
196                                    DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
197                                    &support);
198     ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, "
199        "DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION) failed: %s\n",
200        DXGetErrorString8(rc));
201     if (rc!=DS_OK)
202         goto error;
203
204     ok(support & KSPROPERTY_SUPPORT_GET,
205        "Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION: "
206        "support = 0x%lx\n",support);
207     ok(!(support & KSPROPERTY_SUPPORT_SET),
208        "Shouldn't be able to set DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION: "
209        "support = 0x%lx\n",support);
210
211     rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice,
212         DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING, &support);
213     ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, "
214        "DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING) failed: %s\n",
215        DXGetErrorString8(rc));
216     if (rc!=DS_OK)
217         goto error;
218
219     ok(support & KSPROPERTY_SUPPORT_GET,
220        "Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING: "
221        "support = 0x%lx\n",support);
222     ok(!(support & KSPROPERTY_SUPPORT_SET), "Shouldn't be able to set "
223        "DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING: support = "
224        "0x%lx\n",support);
225
226     rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice,
227                                    DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
228                                    &support);
229     ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, "
230        "DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE) failed: %s\n",
231        DXGetErrorString8(rc));
232     if (rc!=DS_OK)
233         goto error;
234
235     ok(support & KSPROPERTY_SUPPORT_GET,
236        "Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE: "
237        "support = 0x%lx\n",support);
238     ok(!(support & KSPROPERTY_SUPPORT_SET),"Shouldn't be able to set "
239        "DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE: support = 0x%lx\n",support);
240
241     if (support & KSPROPERTY_SUPPORT_GET) {
242         DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA data;
243         ULONG bytes;
244
245         data.Callback = callback;
246         data.Context = 0;
247
248         rc = pps->lpVtbl->Get(pps, &DSPROPSETID_DirectSoundDevice,
249                               DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
250                               NULL, 0, &data, sizeof(data), &bytes);
251         ok(rc==DS_OK, "Couldn't enumerate: 0x%lx\n",rc);
252     }
253
254 error:
255     FreeLibrary(hDsound);
256 }
257
258 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
259                                    LPCSTR lpcstrModule, LPVOID lpContext)
260 {
261     HRESULT rc;
262     LPDIRECTSOUND dso=NULL;
263     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
264     DSBUFFERDESC bufdesc;
265     WAVEFORMATEX wfx;
266     int ref;
267
268     trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
269
270     rc=DirectSoundCreate(lpGuid,&dso,NULL);
271     ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
272        "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
273     if (rc!=DS_OK) {
274         if (rc==DSERR_NODRIVER)
275             trace("  No Driver\n");
276         else if (rc == DSERR_ALLOCATED)
277             trace("  Already In Use\n");
278         goto EXIT;
279     }
280
281     /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
282     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
283     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
284     ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
285        DXGetErrorString8(rc));
286     if (rc!=DS_OK)
287         goto EXIT;
288
289     /* Testing 3D buffers */
290     primary=NULL;
291     ZeroMemory(&bufdesc, sizeof(bufdesc));
292     bufdesc.dwSize=sizeof(bufdesc);
293     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_LOCHARDWARE|DSBCAPS_CTRL3D;
294     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
295     ok(rc==DS_OK&&primary!=NULL,"IDirectSound_CreateSoundBuffer() failed to "
296        "create a hardware 3D primary buffer: %s\n",DXGetErrorString8(rc));
297     if (rc==DS_OK&&primary!=NULL) {
298         ZeroMemory(&wfx, sizeof(wfx));
299         wfx.wFormatTag=WAVE_FORMAT_PCM;
300         wfx.nChannels=1;
301         wfx.wBitsPerSample=16;
302         wfx.nSamplesPerSec=44100;
303         wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
304         wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
305         ZeroMemory(&bufdesc, sizeof(bufdesc));
306         bufdesc.dwSize=sizeof(bufdesc);
307         bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2;
308         bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
309         bufdesc.lpwfxFormat=&wfx;
310         trace("  Testing a secondary buffer at %ldx%dx%d\n",
311             wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
312         rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
313         ok(rc==DS_OK&&secondary!=NULL,"IDirectSound_CreateSoundBuffer() "
314            "failed to create a secondary buffer: %s\n",DXGetErrorString8(rc));
315         if (rc==DS_OK&&secondary!=NULL) {
316             IKsPropertySet * pPropertySet=NULL;
317             rc=IDirectSoundBuffer_QueryInterface(secondary,
318                                                  &IID_IKsPropertySet,
319                                                  (void **)&pPropertySet);
320             /* it's not an error for this to fail */
321             if(rc==DS_OK) {
322                 ULONG ulTypeSupport;
323                 trace("  Supports property sets\n");
324                 /* it's not an error for these to fail */
325                 rc=IKsPropertySet_QuerySupport(pPropertySet,
326                                                &DSPROPSETID_VoiceManager,
327                                                0,&ulTypeSupport);
328                 if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
329                                                 KSPROPERTY_SUPPORT_SET)))
330                     trace("    DSPROPSETID_VoiceManager supported\n");
331                 else
332                     trace("    DSPROPSETID_VoiceManager not supported\n");
333                 rc=IKsPropertySet_QuerySupport(pPropertySet,
334                     &DSPROPSETID_EAX20_ListenerProperties,0,&ulTypeSupport);
335                 if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
336                     KSPROPERTY_SUPPORT_SET)))
337                     trace("    DSPROPSETID_EAX20_ListenerProperties "
338                           "supported\n");
339                 else
340                     trace("    DSPROPSETID_EAX20_ListenerProperties not "
341                           "supported\n");
342                 rc=IKsPropertySet_QuerySupport(pPropertySet,
343                     &DSPROPSETID_EAX20_BufferProperties,0,&ulTypeSupport);
344                 if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
345                     KSPROPERTY_SUPPORT_SET)))
346                     trace("    DSPROPSETID_EAX20_BufferProperties supported\n");
347                 else
348                     trace("    DSPROPSETID_EAX20_BufferProperties not "
349                           "supported\n");
350                 rc=IKsPropertySet_QuerySupport(pPropertySet,
351                     &DSPROPSETID_I3DL2_ListenerProperties,0,&ulTypeSupport);
352                 if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
353                     KSPROPERTY_SUPPORT_SET)))
354                     trace("    DSPROPSETID_I3DL2_ListenerProperties "
355                           "supported\n");
356                 else
357                     trace("    DSPROPSETID_I3DL2_ListenerProperties not "
358                           "supported\n");
359                 rc=IKsPropertySet_QuerySupport(pPropertySet,
360                     &DSPROPSETID_I3DL2_BufferProperties,0,&ulTypeSupport);
361                 if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
362                     KSPROPERTY_SUPPORT_SET)))
363                     trace("    DSPROPSETID_I3DL2_BufferProperties supported\n");
364                 else
365                     trace("    DSPROPSETID_I3DL2_BufferProperties not "
366                           "supported\n");
367                 rc=IKsPropertySet_QuerySupport(pPropertySet,
368                     &DSPROPSETID_ZOOMFX_BufferProperties,0,&ulTypeSupport);
369                 if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
370                     KSPROPERTY_SUPPORT_SET)))
371                     trace("    DSPROPSETID_ZOOMFX_BufferProperties "
372                           "supported\n");
373                 else
374                     trace("    DSPROPSETID_ZOOMFX_BufferProperties not "
375                           "supported\n");
376                 ref=IKsPropertySet_Release(pPropertySet);
377                 /* try a few common ones */
378                 ok(ref==0,"IKsPropertySet_Release() secondary has %d "
379                    "references, should have 0\n",ref);
380             } else
381                 trace("  Doesn't support property sets\n");
382
383             ref=IDirectSoundBuffer_Release(secondary);
384             ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
385                "references, should have 0\n",ref);
386         }
387
388         ref=IDirectSoundBuffer_Release(primary);
389         ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
390            "should have 0\n",ref);
391     }
392
393 EXIT:
394     if (dso!=NULL) {
395         ref=IDirectSound_Release(dso);
396         ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
397            ref);
398     }
399     return 1;
400 }
401
402 static void propset_buffer_tests()
403 {
404     HRESULT rc;
405     rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
406     ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
407 }
408
409 START_TEST(propset)
410 {
411     CoInitialize(NULL);
412
413     propset_private_tests();
414     propset_buffer_tests();
415
416     CoUninitialize();
417 }