ntdll: Load .so builtin modules without using libwine.
[wine/zf.git] / dlls / dmusic / tests / dmusic.c
blob776f9d0ec99b678264435a5ec3992df753121ea7
1 /*
2 * Unit tests for dmusic functions
4 * Copyright (C) 2012 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdio.h>
25 #include "wine/test.h"
26 #include "uuids.h"
27 #include "ole2.h"
28 #include "initguid.h"
29 #include "dmusici.h"
30 #include "dmusicf.h"
31 #include "dmksctrl.h"
33 static void test_dmusic(void)
35 IDirectMusic *dmusic = NULL;
36 HRESULT hr;
37 ULONG index = 0;
38 DMUS_PORTCAPS port_caps;
39 DMUS_PORTPARAMS port_params;
40 IDirectMusicPort *port = NULL;
42 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (LPVOID*)&dmusic);
43 ok(hr == S_OK, "Cannot create DirectMusic object (%x)\n", hr);
45 port_params.dwSize = sizeof(port_params);
46 port_params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
47 port_params.dwChannelGroups = 1;
48 port_params.dwAudioChannels = 2;
50 /* No port can be created before SetDirectSound is called */
51 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
52 ok(hr == DMUS_E_DSOUND_NOT_SET, "IDirectMusic_CreatePort returned: %x\n", hr);
54 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
55 ok(hr == S_OK, "IDirectMusic_SetDirectSound returned: %x\n", hr);
57 /* Check wrong params */
58 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, (IUnknown*)dmusic);
59 ok(hr == CLASS_E_NOAGGREGATION, "IDirectMusic_CreatePort returned: %x\n", hr);
60 hr = IDirectMusic_CreatePort(dmusic, NULL, &port_params, &port, NULL);
61 ok(hr == E_POINTER, "IDirectMusic_CreatePort returned: %x\n", hr);
62 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, NULL, &port, NULL);
63 ok(hr == E_INVALIDARG, "IDirectMusic_CreatePort returned: %x\n", hr);
64 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, NULL, NULL);
65 ok(hr == E_POINTER, "IDirectMusic_CreatePort returned: %x\n", hr);
67 /* Test creation of default port with GUID_NULL */
68 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
69 ok(hr == S_OK, "IDirectMusic_CreatePort returned: %x\n", hr);
71 port_caps.dwSize = sizeof(port_caps);
72 while (IDirectMusic_EnumPort(dmusic, index, &port_caps) == S_OK)
74 ok(port_caps.dwSize == sizeof(port_caps), "DMUS_PORTCAPS dwSize member is wrong (%u)\n", port_caps.dwSize);
75 trace("Port %u:\n", index);
76 trace(" dwFlags = %x\n", port_caps.dwFlags);
77 trace(" guidPort = %s\n", wine_dbgstr_guid(&port_caps.guidPort));
78 trace(" dwClass = %u\n", port_caps.dwClass);
79 trace(" dwType = %u\n", port_caps.dwType);
80 trace(" dwMemorySize = %u\n", port_caps.dwMemorySize);
81 trace(" dwMaxChannelGroups = %u\n", port_caps.dwMaxChannelGroups);
82 trace(" dwMaxVoices = %u\n", port_caps.dwMaxVoices);
83 trace(" dwMaxAudioChannels = %u\n", port_caps.dwMaxAudioChannels);
84 trace(" dwEffectFlags = %x\n", port_caps.dwEffectFlags);
85 trace(" wszDescription = %s\n", wine_dbgstr_w(port_caps.wszDescription));
86 index++;
89 if (port)
90 IDirectMusicPort_Release(port);
91 IDirectMusic_Release(dmusic);
94 static ULONG get_refcount(IDirectSound *iface)
96 IDirectSound_AddRef(iface);
97 return IDirectSound_Release(iface);
100 static void test_setdsound(void)
102 IDirectMusic *dmusic;
103 IDirectSound *dsound, *dsound2;
104 DMUS_PORTPARAMS params;
105 IDirectMusicPort *port = NULL;
106 HRESULT hr;
107 ULONG ref;
109 params.dwSize = sizeof(params);
110 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
111 params.dwChannelGroups = 1;
112 params.dwAudioChannels = 2;
114 /* Old dsound without SetCooperativeLevel() */
115 hr = DirectSoundCreate(NULL, &dsound, NULL);
116 if (hr == DSERR_NODRIVER ) {
117 skip("No driver\n");
118 return;
120 ok(hr == S_OK, "DirectSoundCreate failed: %08x\n", hr);
121 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
122 (void **)&dmusic);
123 ok(hr == S_OK, "DirectMusic create failed: %08x\n", hr);
124 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
125 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
126 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &params, &port, NULL);
127 ok(hr == S_OK, "CreatePort returned: %x\n", hr);
128 IDirectMusicPort_Release(port);
129 IDirectMusic_Release(dmusic);
130 IDirectSound_Release(dsound);
132 /* dsound ref counting */
133 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
134 (void **)&dmusic);
135 ok(hr == S_OK, "DirectMusic create failed: %08x\n", hr);
136 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&dsound, NULL);
137 ok(hr == S_OK, "DirectSoundCreate failed: %08x\n", hr);
138 hr = IDirectSound_SetCooperativeLevel(dsound, GetForegroundWindow(), DSSCL_PRIORITY);
139 ok(hr == S_OK, "SetCooperativeLevel failed: %08x\n", hr);
140 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
141 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
142 ref = get_refcount(dsound);
143 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
144 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &params, &port, NULL);
145 ok(hr == S_OK, "CreatePort returned: %x\n", hr);
146 ref = get_refcount(dsound);
147 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
148 IDirectMusicPort_AddRef(port);
149 ref = IDirectMusicPort_Release(port);
150 ok(ref == 1, "port ref count got %d expected 1\n", ref);
151 hr = IDirectMusicPort_Activate(port, TRUE);
152 ok(hr == S_OK, "Port Activate returned: %x\n", hr);
153 ref = get_refcount(dsound);
154 ok(ref == 4, "dsound ref count got %d expected 4\n", ref);
155 IDirectMusicPort_AddRef(port);
156 ref = IDirectMusicPort_Release(port);
157 ok(ref == 1, "port ref count got %d expected 1\n", ref);
159 /* Releasing dsound from dmusic */
160 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
161 ok(hr == DMUS_E_DSOUND_ALREADY_SET, "SetDirectSound failed: %08x\n", hr);
162 hr = IDirectMusicPort_Activate(port, FALSE);
163 ok(hr == S_OK, "Port Activate returned: %x\n", hr);
164 ref = get_refcount(dsound);
165 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
166 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
167 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
168 ref = get_refcount(dsound);
169 ok(ref == 1, "dsound ref count got %d expected 1\n", ref);
171 /* Setting the same dsound twice */
172 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
173 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
174 ref = get_refcount(dsound);
175 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
176 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
177 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
178 ref = get_refcount(dsound);
179 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
181 /* Replacing one dsound with another */
182 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&dsound2, NULL);
183 ok(hr == S_OK, "DirectSoundCreate failed: %08x\n", hr);
184 hr = IDirectMusic_SetDirectSound(dmusic, dsound2, NULL);
185 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
186 ref = get_refcount(dsound);
187 ok(ref == 1, "dsound ref count got %d expected 1\n", ref);
188 ref = get_refcount(dsound2);
189 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
191 /* Replacing the dsound in the port */
192 hr = IDirectMusicPort_SetDirectSound(port, dsound, NULL);
193 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
194 ref = get_refcount(dsound);
195 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
196 ref = get_refcount(dsound2);
197 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
198 /* Setting the dsound again on the port will mess with the parent dmusic */
199 hr = IDirectMusicPort_SetDirectSound(port, dsound, NULL);
200 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
201 ref = get_refcount(dsound);
202 ok(ref == 3, "dsound ref count got %d expected 3\n", ref);
203 ref = get_refcount(dsound2);
204 ok(ref == 1, "dsound2 ref count got %d expected 1\n", ref);
205 IDirectSound_AddRef(dsound2); /* Crash prevention */
206 hr = IDirectMusicPort_Activate(port, TRUE);
207 ok(hr == S_OK, "Activate returned: %x\n", hr);
208 ref = get_refcount(dsound);
209 ok(ref == 4, "dsound ref count got %d expected 4\n", ref);
210 ref = get_refcount(dsound2);
211 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
212 hr = IDirectMusicPort_Activate(port, TRUE);
213 ok(hr == S_FALSE, "Activate returned: %x\n", hr);
214 ref = get_refcount(dsound);
215 ok(ref == 4, "dsound ref count got %d expected 4\n", ref);
216 ref = get_refcount(dsound2);
217 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
219 /* Deactivating the port messes with the dsound refcount in the parent dmusic */
220 hr = IDirectMusicPort_Activate(port, FALSE);
221 ok(hr == S_OK, "Port Activate returned: %x\n", hr);
222 ref = get_refcount(dsound);
223 ok(ref == 3, "dsound ref count got %d expected 3\n", ref);
224 ref = get_refcount(dsound2);
225 ok(ref == 1, "dsound2 ref count got %d expected 1\n", ref);
226 hr = IDirectMusicPort_Activate(port, FALSE);
227 ok(hr == S_FALSE, "Port Activate returned: %x\n", hr);
228 ref = get_refcount(dsound);
229 ok(ref == 3, "dsound ref count got %d expected 3\n", ref);
230 ref = get_refcount(dsound2);
231 ok(ref == 1, "dsound2 ref count got %d expected 1\n", ref);
233 IDirectMusicPort_Release(port);
234 IDirectMusic_Release(dmusic);
235 while (IDirectSound_Release(dsound));
238 static void test_dmbuffer(void)
240 IDirectMusic *dmusic;
241 IDirectMusicBuffer *dmbuffer = NULL;
242 HRESULT hr;
243 DMUS_BUFFERDESC desc;
244 GUID format;
245 DWORD size;
246 DWORD bytes;
247 REFERENCE_TIME time;
248 LPBYTE data;
250 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (LPVOID*)&dmusic);
251 ok(hr == S_OK, "Cannot create DirectMusic object (%x)\n", hr);
253 desc.dwSize = sizeof(DMUS_BUFFERDESC);
254 desc.dwFlags = 0;
255 desc.cbBuffer = 1023;
256 memcpy(&desc.guidBufferFormat, &GUID_NULL, sizeof(GUID));
258 hr = IDirectMusic_CreateMusicBuffer(dmusic, &desc, &dmbuffer, NULL);
259 ok(hr == S_OK, "IDirectMusic_CreateMusicBuffer return %x\n", hr);
261 hr = IDirectMusicBuffer_GetBufferFormat(dmbuffer, &format);
262 ok(hr == S_OK, "IDirectMusicBuffer_GetBufferFormat returned %x\n", hr);
263 ok(IsEqualGUID(&format, &KSDATAFORMAT_SUBTYPE_MIDI), "Wrong format returned %s\n", wine_dbgstr_guid(&format));
264 hr = IDirectMusicBuffer_GetMaxBytes(dmbuffer, &size);
265 ok(hr == S_OK, "IDirectMusicBuffer_GetMaxBytes returned %x\n", hr);
266 ok(size == 1024, "Buffer size is %u instead of 1024\n", size);
268 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
269 ok(hr == DMUS_E_BUFFER_EMPTY, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
270 hr = IDirectMusicBuffer_SetStartTime(dmbuffer, 10);
271 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
272 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
273 ok(hr == DMUS_E_BUFFER_EMPTY, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
275 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 20, 0, 0);
276 ok(hr == DMUS_E_INVALID_EVENT, "IDirectMusicBuffer_PackStructured returned %x\n", hr);
277 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 20, 0, 0x000090); /* note on : chan 0, note 0 & vel 0 */
278 ok(hr == S_OK, "IDirectMusicBuffer_PackStructured returned %x\n", hr);
279 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 30, 0, 0x000080); /* note off : chan 0, note 0 & vel 0 */
280 ok(hr == S_OK, "IDirectMusicBuffer_PackStructured returned %x\n", hr);
281 hr = IDirectMusicBuffer_GetUsedBytes(dmbuffer, &bytes);
282 ok(hr == S_OK, "IDirectMusicBuffer_GetUsedBytes returned %x\n", hr);
283 ok(bytes == 48, "Buffer size is %u instead of 48\n", bytes);
285 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
286 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
287 ok(time == 20, "Buffer start time is wrong\n");
288 hr = IDirectMusicBuffer_SetStartTime(dmbuffer, 40);
289 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
290 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
291 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
292 ok(time == 40, "Buffer start time is wrong\n");
294 hr = IDirectMusicBuffer_GetRawBufferPtr(dmbuffer, &data);
295 ok(hr == S_OK, "IDirectMusicBuffer_GetRawBufferPtr returned %x\n", hr);
296 if (hr == S_OK)
298 DMUS_EVENTHEADER* header;
299 DWORD message;
301 /* Check message 1 */
302 header = (DMUS_EVENTHEADER*)data;
303 data += sizeof(DMUS_EVENTHEADER);
304 ok(header->cbEvent == 3, "cbEvent is %u instead of 3\n", header->cbEvent);
305 ok(header->dwChannelGroup == 0, "dwChannelGroup is %u instead of 0\n", header->dwChannelGroup);
306 ok(header->rtDelta == 0, "rtDelta is %s instead of 0\n", wine_dbgstr_longlong(header->rtDelta));
307 ok(header->dwFlags == DMUS_EVENT_STRUCTURED, "dwFlags is %x instead of %x\n", header->dwFlags, DMUS_EVENT_STRUCTURED);
308 message = *(DWORD*)data & 0xffffff; /* Only 3 bytes are relevant */
309 data += sizeof(DWORD);
310 ok(message == 0x000090, "Message is %0x instead of 0x000090\n", message);
312 /* Check message 2 */
313 header = (DMUS_EVENTHEADER*)data;
314 data += sizeof(DMUS_EVENTHEADER);
315 ok(header->cbEvent == 3, "cbEvent is %u instead of 3\n", header->cbEvent);
316 ok(header->dwChannelGroup == 0, "dwChannelGroup is %u instead of 0\n", header->dwChannelGroup);
317 ok(header->rtDelta == 10, "rtDelta is %s instead of 0\n", wine_dbgstr_longlong(header->rtDelta));
318 ok(header->dwFlags == DMUS_EVENT_STRUCTURED, "dwFlags is %x instead of %x\n", header->dwFlags, DMUS_EVENT_STRUCTURED);
319 message = *(DWORD*)data & 0xffffff; /* Only 3 bytes are relevant */
320 ok(message == 0x000080, "Message 2 is %0x instead of 0x000080\n", message);
323 if (dmbuffer)
324 IDirectMusicBuffer_Release(dmbuffer);
325 IDirectMusic_Release(dmusic);
328 static void test_COM(void)
330 IDirectMusic8 *dm8 = (IDirectMusic8*)0xdeadbeef;
331 IDirectMusic *dm;
332 IUnknown *unk;
333 ULONG refcount;
334 HRESULT hr;
336 /* COM aggregation */
337 hr = CoCreateInstance(&CLSID_DirectMusic, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
338 (void**)&dm8);
339 ok(hr == CLASS_E_NOAGGREGATION,
340 "DirectMusic8 create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
341 ok(!dm8, "dm8 = %p\n", dm8);
343 /* Invalid RIID */
344 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
345 (void**)&dm8);
346 ok(hr == E_NOINTERFACE, "DirectMusic8 create failed: %08x, expected E_NOINTERFACE\n", hr);
348 /* Same refcount for DirectMusic and DirectMusic8 */
349 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
350 (void**)&dm8);
351 if (hr == E_NOINTERFACE)
353 win_skip("DirectMusic too old (no IDirectMusic8)\n");
354 return;
356 ok(hr == S_OK, "DirectMusic8 create failed: %08x, expected S_OK\n", hr);
357 refcount = IDirectMusic8_AddRef(dm8);
358 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
360 hr = IDirectMusic8_QueryInterface(dm8, &IID_IDirectMusic, (void**)&dm);
361 ok(hr == S_OK, "QueryInterface for IID_IDirectMusic failed: %08x\n", hr);
362 refcount = IDirectMusic_AddRef(dm);
363 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
364 IDirectMusic_Release(dm);
366 hr = IDirectMusic8_QueryInterface(dm8, &IID_IUnknown, (void**)&unk);
367 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
368 refcount = IUnknown_AddRef(unk);
369 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
370 refcount = IUnknown_Release(unk);
372 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
373 while (IDirectMusic8_Release(dm8));
376 static void test_COM_dmcoll(void)
378 IDirectMusicCollection *dmc = (IDirectMusicCollection*)0xdeadbeef;
379 IDirectMusicObject *dmo;
380 IPersistStream *ps;
381 IUnknown *unk;
382 ULONG refcount;
383 HRESULT hr;
385 /* COM aggregation */
386 hr = CoCreateInstance(&CLSID_DirectMusicCollection, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
387 &IID_IUnknown, (void**)&dmc);
388 ok(hr == CLASS_E_NOAGGREGATION,
389 "DirectMusicCollection create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
390 ok(!dmc, "dmc = %p\n", dmc);
392 /* Invalid RIID */
393 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
394 &IID_IClassFactory, (void**)&dmc);
395 ok(hr == E_NOINTERFACE, "DirectMusicCollection create failed: %08x, expected E_NOINTERFACE\n", hr);
397 /* Same refcount for all DirectMusicCollection interfaces */
398 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
399 &IID_IDirectMusicCollection, (void**)&dmc);
400 ok(hr == S_OK, "DirectMusicCollection create failed: %08x, expected S_OK\n", hr);
401 refcount = IDirectMusicCollection_AddRef(dmc);
402 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
404 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IDirectMusicObject, (void**)&dmo);
405 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
406 refcount = IDirectMusicObject_AddRef(dmo);
407 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
408 refcount = IDirectMusicObject_Release(dmo);
410 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IPersistStream, (void**)&ps);
411 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
412 refcount = IPersistStream_AddRef(ps);
413 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
414 refcount = IPersistStream_Release(ps);
416 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IUnknown, (void**)&unk);
417 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
418 refcount = IUnknown_AddRef(unk);
419 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
420 refcount = IUnknown_Release(unk);
422 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
423 while (IDirectMusicCollection_Release(dmc));
426 static void test_dmcoll(void)
428 IDirectMusicCollection *dmc;
429 IDirectMusicObject *dmo;
430 IPersistStream *ps;
431 DMUS_OBJECTDESC desc;
432 CLSID class;
433 ULARGE_INTEGER size;
434 HRESULT hr;
436 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
437 &IID_IDirectMusicCollection, (void**)&dmc);
438 ok(hr == S_OK, "DirectMusicCollection create failed: %08x, expected S_OK\n", hr);
440 /* IDirectMusicObject */
441 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IDirectMusicObject, (void**)&dmo);
442 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
443 hr = IDirectMusicObject_GetDescriptor(dmo, NULL);
444 ok(hr == E_POINTER, "IDirectMusicObject_GetDescriptor: expected E_POINTER, got %08x\n", hr);
445 hr = IDirectMusicObject_SetDescriptor(dmo, NULL);
446 ok(hr == E_POINTER, "IDirectMusicObject_SetDescriptor: expected E_POINTER, got %08x\n", hr);
447 ZeroMemory(&desc, sizeof(desc));
448 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
449 ok(hr == S_OK, "IDirectMusicObject_GetDescriptor failed: %08x\n", hr);
450 ok(desc.dwValidData == DMUS_OBJ_CLASS,
451 "Fresh object has more valid data (%08x) than DMUS_OBJ_CLASS\n", desc.dwValidData);
452 /* DMUS_OBJ_CLASS is immutable */
453 desc.dwValidData = DMUS_OBJ_CLASS;
454 hr = IDirectMusicObject_SetDescriptor(dmo, &desc);
455 ok(hr == S_FALSE , "IDirectMusicObject_SetDescriptor failed: %08x\n", hr);
456 ok(!desc.dwValidData, "dwValidData wasn't cleared: %08x\n", desc.dwValidData);
457 desc.dwValidData = DMUS_OBJ_CLASS;
458 desc.guidClass = CLSID_DirectMusicSegment;
459 hr = IDirectMusicObject_SetDescriptor(dmo, &desc);
460 ok(hr == S_FALSE && !desc.dwValidData, "IDirectMusicObject_SetDescriptor failed: %08x\n", hr);
461 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
462 ok(hr == S_OK, "IDirectMusicObject_GetDescriptor failed: %08x\n", hr);
463 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
464 "guidClass changed, should be CLSID_DirectMusicCollection\n");
466 /* Unimplemented IPersistStream methods*/
467 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IPersistStream, (void**)&ps);
468 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
469 hr = IPersistStream_GetClassID(ps, &class);
470 ok(hr == E_NOTIMPL, "IPersistStream_GetClassID failed: %08x\n", hr);
471 hr = IPersistStream_IsDirty(ps);
472 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
473 hr = IPersistStream_GetSizeMax(ps, &size);
474 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
475 hr = IPersistStream_Save(ps, NULL, TRUE);
476 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
478 while (IDirectMusicCollection_Release(dmc));
481 static BOOL missing_dmusic(void)
483 IDirectMusic8 *dm;
484 HRESULT hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic,
485 (void**)&dm);
487 if (hr == S_OK && dm)
489 IDirectMusic_Release(dm);
490 return FALSE;
492 return TRUE;
495 static void test_COM_synthport(void)
497 IDirectMusic *dmusic = NULL;
498 IDirectMusicPort *port = NULL;
499 IDirectMusicPortDownload *dmpd;
500 IDirectMusicThru *dmt;
501 IKsControl *iksc;
502 IReferenceClock *clock;
503 IUnknown *unk;
504 DMUS_PORTPARAMS port_params;
505 ULONG refcount;
506 HRESULT hr;
508 /* Create a IDirectMusicPort */
509 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic,
510 (void**)&dmusic);
511 ok(hr == S_OK, "Cannot create DirectMusic object (%x)\n", hr);
512 port_params.dwSize = sizeof(port_params);
513 port_params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
514 port_params.dwChannelGroups = 1;
515 port_params.dwAudioChannels = 2;
516 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
517 ok(hr == S_OK, "IDirectMusic_SetDirectSound returned: %x\n", hr);
518 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
519 ok(hr == S_OK, "IDirectMusic_CreatePort returned: %x\n", hr);
521 /* Same refcount for all DirectMusicPort interfaces */
522 refcount = IDirectMusicPort_AddRef(port);
523 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
525 hr = IDirectMusicPort_QueryInterface(port, &IID_IDirectMusicPortDownload, (void**)&dmpd);
526 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicPortDownload failed: %08x\n", hr);
527 refcount = IDirectMusicPortDownload_AddRef(dmpd);
528 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
529 IDirectMusicPortDownload_Release(dmpd);
531 hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void**)&iksc);
532 ok(hr == S_OK, "QueryInterface for IID_IKsControl failed: %08x\n", hr);
533 refcount = IKsControl_AddRef(iksc);
534 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
535 IKsControl_Release(iksc);
537 hr = IDirectMusicPort_QueryInterface(port, &IID_IUnknown, (void**)&unk);
538 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
539 refcount = IUnknown_AddRef(unk);
540 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
541 IUnknown_Release(unk);
543 /* Unsupported interface */
544 hr = IDirectMusicPort_QueryInterface(port, &IID_IDirectMusicThru, (void**)&dmt);
545 todo_wine ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicThru failed: %08x\n", hr);
546 hr = IDirectMusicPort_QueryInterface(port, &IID_IReferenceClock, (void**)&clock);
547 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IReferenceClock failed: %08x\n", hr);
549 while (IDirectMusicPort_Release(port));
552 struct chunk {
553 FOURCC id;
554 DWORD size;
555 FOURCC type;
558 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
560 /* Generate a RIFF file format stream from an array of FOURCC ids.
561 RIFF and LIST need to be followed by the form type respectively list type,
562 followed by the chunks of the list and terminated with 0. */
563 static IStream *gen_riff_stream(const FOURCC *ids)
565 static const LARGE_INTEGER zero;
566 int level = -1;
567 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
568 char riff[1024];
569 char *p = riff;
570 struct chunk *ck;
571 IStream *stream;
573 do {
574 ck = (struct chunk *)p;
575 ck->id = *ids++;
576 switch (ck->id) {
577 case 0:
578 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
579 level--;
580 break;
581 case FOURCC_LIST:
582 case FOURCC_RIFF:
583 level++;
584 sizes[level] = &ck->size;
585 ck->type = *ids++;
586 p += sizeof(*ck);
587 break;
588 case DMUS_FOURCC_GUID_CHUNK:
589 ck->size = sizeof(GUID_NULL);
590 p += CHUNK_HDR_SIZE;
591 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
592 p += ck->size;
593 break;
594 case DMUS_FOURCC_VERSION_CHUNK:
596 DMUS_VERSION ver = {5, 8};
598 ck->size = sizeof(ver);
599 p += CHUNK_HDR_SIZE;
600 memcpy(p, &ver, sizeof(ver));
601 p += ck->size;
602 break;
604 case mmioFOURCC('I','N','A','M'):
605 ck->size = 5;
606 p += CHUNK_HDR_SIZE;
607 strcpy(p, "INAM");
608 p += ck->size + 1; /* WORD aligned */
609 break;
610 default:
612 /* Just convert the FOURCC id to a WCHAR string */
613 WCHAR *s;
615 ck->size = 5 * sizeof(WCHAR);
616 p += CHUNK_HDR_SIZE;
617 s = (WCHAR *)p;
618 s[0] = (char)(ck->id);
619 s[1] = (char)(ck->id >> 8);
620 s[2] = (char)(ck->id >> 16);
621 s[3] = (char)(ck->id >> 24);
622 s[4] = 0;
623 p += ck->size;
626 } while (level >= 0);
628 ck = (struct chunk *)riff;
629 CreateStreamOnHGlobal(NULL, TRUE, &stream);
630 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
631 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
633 return stream;
636 static void test_parsedescriptor(void)
638 IDirectMusicObject *dmo;
639 IStream *stream;
640 DMUS_OBJECTDESC desc = {0};
641 HRESULT hr;
642 const FOURCC alldesc[] =
644 FOURCC_RIFF, FOURCC_DLS, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST,
645 DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK,
646 DMUS_FOURCC_UCMT_CHUNK, DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK,
647 DMUS_FOURCC_GUID_CHUNK, 0
649 const FOURCC dupes[] =
651 FOURCC_RIFF, FOURCC_DLS, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
652 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
653 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_INFO_LIST, mmioFOURCC('I','N','A','M'), 0,
654 FOURCC_LIST, DMUS_FOURCC_INFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
656 FOURCC empty[] = {FOURCC_RIFF, FOURCC_DLS, 0};
657 FOURCC inam[] =
659 FOURCC_RIFF, FOURCC_DLS, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
660 mmioFOURCC('I','N','A','M'), 0, 0
663 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
664 &IID_IDirectMusicObject, (void **)&dmo);
665 ok(hr == S_OK, "DirectMusicCollection create failed: %08x, expected S_OK\n", hr);
667 /* Nothing loaded */
668 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
669 ok(hr == S_OK, "GetDescriptor failed: %08x, expected S_OK\n", hr);
670 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_OBJECT\n",
671 desc.dwValidData);
672 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
673 "Got class guid %s, expected CLSID_DirectMusicCollection\n",
674 wine_dbgstr_guid(&desc.guidClass));
676 /* Empty RIFF stream */
677 stream = gen_riff_stream(empty);
678 memset(&desc, 0, sizeof(desc));
679 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
680 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
681 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n",
682 desc.dwValidData);
683 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
684 "Got class guid %s, expected CLSID_DirectMusicCollection\n",
685 wine_dbgstr_guid(&desc.guidClass));
686 IStream_Release(stream);
688 /* NULL pointers */
689 memset(&desc, 0, sizeof(desc));
690 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
691 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
692 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
693 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
695 /* Wrong form */
696 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
697 stream = gen_riff_stream(empty);
698 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
699 ok(hr == DMUS_E_NOTADLSCOL, "ParseDescriptor failed: %08x, expected DMUS_E_NOTADLSCOL\n", hr);
700 IStream_Release(stream);
702 /* All desc chunks */
703 stream = gen_riff_stream(alldesc);
704 memset(&desc, 0, sizeof(desc));
705 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
706 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
707 ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_VERSION),
708 "Got valid data %#x, expected DMUS_OBJ_CLASS | DMUS_OBJ_VERSION\n", desc.dwValidData);
709 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
710 "Got class guid %s, expected CLSID_DirectMusicCollection\n",
711 wine_dbgstr_guid(&desc.guidClass));
712 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
713 wine_dbgstr_guid(&desc.guidClass));
714 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
715 "Got version %u.%u, expected 5.8\n", desc.vVersion.dwVersionMS,
716 desc.vVersion.dwVersionLS);
717 IStream_Release(stream);
719 /* UNFO list with INAM */
720 inam[3] = DMUS_FOURCC_UNFO_LIST;
721 stream = gen_riff_stream(inam);
722 memset(&desc, 0, sizeof(desc));
723 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
724 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
725 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n",
726 desc.dwValidData);
727 IStream_Release(stream);
729 /* INFO list with INAM */
730 inam[3] = DMUS_FOURCC_INFO_LIST;
731 stream = gen_riff_stream(inam);
732 memset(&desc, 0, sizeof(desc));
733 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
734 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
735 ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_NAME),
736 "Got valid data %#x, expected DMUS_OBJ_CLASS | DMUS_OBJ_NAME\n", desc.dwValidData);
737 ok(!lstrcmpW(desc.wszName, L"INAM"), "Got name '%s', expected 'INAM'\n",
738 wine_dbgstr_w(desc.wszName));
739 IStream_Release(stream);
741 /* Duplicated chunks */
742 stream = gen_riff_stream(dupes);
743 memset(&desc, 0, sizeof(desc));
744 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
745 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
746 ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_NAME | DMUS_OBJ_VERSION),
747 "Got valid data %#x, expected DMUS_OBJ_CLASS | DMUS_OBJ_NAME | DMUS_OBJ_VERSION\n",
748 desc.dwValidData);
749 ok(!lstrcmpW(desc.wszName, L"INAM"), "Got name '%s', expected 'INAM'\n",
750 wine_dbgstr_w(desc.wszName));
751 IStream_Release(stream);
753 IDirectMusicObject_Release(dmo);
756 static void test_master_clock(void)
758 static const GUID guid_system_clock = {0x58d58419, 0x71b4, 0x11d1, {0xa7, 0x4c, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12}};
759 static const GUID guid_dsound_clock = {0x58d58420, 0x71b4, 0x11d1, {0xa7, 0x4c, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12}};
760 IReferenceClock *clock, *clock2;
761 REFERENCE_TIME time1, time2;
762 LARGE_INTEGER counter, freq;
763 DMUS_CLOCKINFO clock_info;
764 IDirectMusic *dmusic;
765 DWORD cookie;
766 HRESULT hr;
767 ULONG ref;
768 GUID guid;
770 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (void **)&dmusic);
771 ok(hr == S_OK, "Got hr %#x.\n", hr);
773 hr = IDirectMusic_GetMasterClock(dmusic, NULL, NULL);
774 ok(hr == S_OK, "Got hr %#x.\n", hr);
776 memset(&guid, 0xcc, sizeof(guid));
777 hr = IDirectMusic_GetMasterClock(dmusic, &guid, NULL);
778 ok(hr == S_OK, "Got hr %#x.\n", hr);
779 todo_wine ok(IsEqualGUID(&guid, &guid_system_clock), "Got guid %s.\n", wine_dbgstr_guid(&guid));
781 clock = (IReferenceClock *)0xdeadbeef;
782 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock);
783 ok(hr == S_OK, "Got hr %#x.\n", hr);
784 ok(clock && clock != (IReferenceClock *)0xdeadbeef, "Got clock %p.\n", clock);
786 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock2);
787 ok(hr == S_OK, "Got hr %#x.\n", hr);
788 ok(clock2 == clock, "Clocks didn't match.\n");
789 IReferenceClock_Release(clock2);
791 memset(&guid, 0xcc, sizeof(guid));
792 hr = IDirectMusic_GetMasterClock(dmusic, &guid, &clock2);
793 ok(hr == S_OK, "Got hr %#x.\n", hr);
794 todo_wine ok(IsEqualGUID(&guid, &guid_system_clock), "Got guid %s.\n", wine_dbgstr_guid(&guid));
795 ok(clock2 == clock, "Clocks didn't match.\n");
796 IReferenceClock_Release(clock2);
798 QueryPerformanceFrequency(&freq);
799 QueryPerformanceCounter(&counter);
800 hr = IReferenceClock_GetTime(clock, &time1);
801 ok(hr == S_OK, "Got hr %#x.\n", hr);
802 time2 = counter.QuadPart * 10000000.0 / freq.QuadPart;
803 ok(abs(time1 - time2) < 20 * 10000, "Expected about %s, got %s.\n",
804 wine_dbgstr_longlong(time2), wine_dbgstr_longlong(time1));
806 hr = IReferenceClock_GetTime(clock, &time2);
807 ok(hr == (time2 == time1 ? S_FALSE : S_OK), "Got hr %#x.\n", hr);
809 Sleep(100);
810 hr = IReferenceClock_GetTime(clock, &time2);
811 ok(hr == S_OK, "Got hr %#x.\n", hr);
812 ok(time2 - time1 > 80 * 10000, "Expected about %s, but got %s.\n",
813 wine_dbgstr_longlong(time1 + 100 * 10000), wine_dbgstr_longlong(time2));
815 hr = IReferenceClock_AdviseTime(clock, 0, 0, NULL, &cookie);
816 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
818 hr = IReferenceClock_AdvisePeriodic(clock, 0, 0, NULL, &cookie);
819 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
821 hr = IReferenceClock_Unadvise(clock, 0);
822 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
824 IReferenceClock_Release(clock);
826 hr = IDirectMusic_EnumMasterClock(dmusic, 0, NULL);
827 todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
829 memset(&clock_info, 0xcc, sizeof(DMUS_CLOCKINFO));
830 clock_info.dwSize = sizeof(DMUS_CLOCKINFO7);
831 hr = IDirectMusic_EnumMasterClock(dmusic, 0, &clock_info);
832 ok(hr == S_OK, "Got hr %#x.\n", hr);
833 ok(clock_info.ctType == DMUS_CLOCK_SYSTEM, "Got type %#x.\n", clock_info.ctType);
834 ok(IsEqualGUID(&clock_info.guidClock, &guid_system_clock), "Got guid %s.\n",
835 wine_dbgstr_guid(&clock_info.guidClock));
836 ok(clock_info.dwFlags == 0xcccccccc, "Got flags %#x.\n", clock_info.dwFlags);
838 memset(&clock_info, 0xcc, sizeof(DMUS_CLOCKINFO));
839 clock_info.dwSize = sizeof(DMUS_CLOCKINFO7);
840 hr = IDirectMusic_EnumMasterClock(dmusic, 1, &clock_info);
841 ok(hr == S_OK, "Got hr %#x.\n", hr);
842 ok(clock_info.ctType == DMUS_CLOCK_SYSTEM, "Got type %#x.\n", clock_info.ctType);
843 ok(IsEqualGUID(&clock_info.guidClock, &guid_dsound_clock), "Got guid %s.\n",
844 wine_dbgstr_guid(&clock_info.guidClock));
845 ok(clock_info.dwFlags == 0xcccccccc, "Got flags %#x.\n", clock_info.dwFlags);
847 memset(&clock_info, 0xcc, sizeof(DMUS_CLOCKINFO));
848 clock_info.dwSize = sizeof(DMUS_CLOCKINFO7);
849 hr = IDirectMusic_EnumMasterClock(dmusic, 2, &clock_info);
850 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
852 ref = IDirectMusic_Release(dmusic);
853 ok(!ref, "Got outstanding refcount %d.\n", ref);
856 START_TEST(dmusic)
858 CoInitializeEx(NULL, COINIT_MULTITHREADED);
860 if (missing_dmusic())
862 skip("DirectMusic not available\n");
863 CoUninitialize();
864 return;
866 test_COM();
867 test_COM_dmcoll();
868 test_COM_synthport();
869 test_dmusic();
870 test_setdsound();
871 test_dmbuffer();
872 test_dmcoll();
873 test_parsedescriptor();
874 test_master_clock();
876 CoUninitialize();