win32u: Move NtUserTranslateMessage implementation from user32.
[wine.git] / dlls / dmime / tests / dmime.c
blob8f2bf6f28128d6fbb0b5614cacf4f0b689326773
1 /*
2 * Copyright 2012, 2014 Michael Stefaniuc
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <wine/test.h>
24 #include <ole2.h>
25 #include <dmusici.h>
26 #include <dmusicf.h>
27 #include <audioclient.h>
28 #include <guiddef.h>
30 static BOOL missing_dmime(void)
32 IDirectMusicSegment8 *dms;
33 HRESULT hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
34 &IID_IDirectMusicSegment, (void**)&dms);
36 if (hr == S_OK && dms)
38 IDirectMusicSegment_Release(dms);
39 return FALSE;
41 return TRUE;
44 static void test_COM_audiopath(void)
46 IDirectMusicAudioPath *dmap;
47 IUnknown *unk;
48 IDirectMusicPerformance8 *performance;
49 IDirectSoundBuffer *dsound;
50 IDirectSoundBuffer8 *dsound8;
51 IDirectSoundNotify *notify;
52 IDirectSound3DBuffer *dsound3d;
53 IKsPropertySet *propset;
54 ULONG refcount;
55 HRESULT hr;
56 DWORD buffer = 0;
58 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
59 &IID_IDirectMusicPerformance8, (void**)&performance);
60 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "DirectMusicPerformance create failed: %#lx\n", hr);
61 if (!performance) {
62 win_skip("IDirectMusicPerformance8 not available\n");
63 return;
65 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL,
66 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
67 ok(hr == S_OK || hr == DSERR_NODRIVER ||
68 broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED), /* Win 10 testbot */
69 "DirectMusicPerformance_InitAudio failed: %#lx\n", hr);
70 if (FAILED(hr)) {
71 skip("Audio failed to initialize\n");
72 return;
74 hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &dmap);
75 ok(hr == S_OK, "DirectMusicPerformance_GetDefaultAudioPath failed: %#lx\n", hr);
77 /* IDirectMusicObject and IPersistStream are not supported */
78 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IDirectMusicObject, (void**)&unk);
79 todo_wine ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n",
80 hr, unk);
81 if (unk) IUnknown_Release(unk);
82 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IPersistStream, (void**)&unk);
83 todo_wine ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n",
84 hr, unk);
85 if (unk) IUnknown_Release(unk);
87 /* Same refcount for all DirectMusicAudioPath interfaces */
88 refcount = IDirectMusicAudioPath_AddRef(dmap);
89 ok(refcount == 3, "refcount == %lu, expected 3\n", refcount);
91 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IUnknown, (void**)&unk);
92 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
93 ok(unk == (IUnknown*)dmap, "got %p, %p\n", unk, dmap);
94 refcount = IUnknown_AddRef(unk);
95 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
96 refcount = IUnknown_Release(unk);
98 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
99 0, &IID_IDirectSoundBuffer, (void**)&dsound);
100 ok(hr == S_OK, "Failed: %#lx\n", hr);
101 IDirectSoundBuffer_Release(dsound);
103 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
104 0, &IID_IDirectSoundBuffer8, (void**)&dsound8);
105 ok(hr == S_OK, "Failed: %#lx\n", hr);
106 IDirectSoundBuffer8_Release(dsound8);
108 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
109 0, &IID_IDirectSoundNotify, (void**)&notify);
110 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
112 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
113 0, &IID_IDirectSound3DBuffer, (void**)&dsound3d);
114 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
116 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
117 0, &IID_IKsPropertySet, (void**)&propset);
118 todo_wine ok(hr == S_OK, "Failed: %#lx\n", hr);
119 if (propset)
120 IKsPropertySet_Release(propset);
122 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
123 0, &IID_IUnknown, (void**)&unk);
124 ok(hr == S_OK, "Failed: %#lx\n", hr);
125 IUnknown_Release(unk);
127 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
128 0, &GUID_NULL, (void**)&unk);
129 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
131 while (IDirectMusicAudioPath_Release(dmap) > 1); /* performance has a reference too */
132 IDirectMusicPerformance8_CloseDown(performance);
133 IDirectMusicPerformance8_Release(performance);
136 static void test_COM_audiopathconfig(void)
138 IDirectMusicAudioPath *dmap = (IDirectMusicAudioPath*)0xdeadbeef;
139 IDirectMusicObject *dmo;
140 IPersistStream *ps;
141 IUnknown *unk;
142 ULONG refcount;
143 HRESULT hr;
145 /* COM aggregation */
146 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
147 &IID_IUnknown, (void**)&dmap);
148 if (hr == REGDB_E_CLASSNOTREG) {
149 win_skip("DirectMusicAudioPathConfig not registered\n");
150 return;
152 ok(hr == CLASS_E_NOAGGREGATION,
153 "DirectMusicAudioPathConfig create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
154 ok(!dmap, "dmap = %p\n", dmap);
156 /* IDirectMusicAudioPath not supported */
157 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
158 &IID_IDirectMusicAudioPath, (void**)&dmap);
159 todo_wine ok(FAILED(hr) && !dmap,
160 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
162 /* IDirectMusicObject and IPersistStream supported */
163 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
164 &IID_IPersistStream, (void**)&ps);
165 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
166 IPersistStream_Release(ps);
167 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
168 &IID_IDirectMusicObject, (void**)&dmo);
169 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
171 /* Same refcount for all DirectMusicObject interfaces */
172 refcount = IDirectMusicObject_AddRef(dmo);
173 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
175 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
176 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
177 refcount = IPersistStream_AddRef(ps);
178 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
179 IPersistStream_Release(ps);
181 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IUnknown, (void**)&unk);
182 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
183 refcount = IUnknown_AddRef(unk);
184 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
185 refcount = IUnknown_Release(unk);
187 /* IDirectMusicAudioPath still not supported */
188 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IDirectMusicAudioPath, (void**)&dmap);
189 todo_wine ok(FAILED(hr) && !dmap,
190 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
192 while (IDirectMusicObject_Release(dmo));
196 static void test_COM_graph(void)
198 IDirectMusicGraph *dmg = (IDirectMusicGraph*)0xdeadbeef;
199 IDirectMusicObject *dmo;
200 IPersistStream *ps;
201 IUnknown *unk;
202 ULONG refcount;
203 HRESULT hr;
205 /* COM aggregation */
206 hr = CoCreateInstance(&CLSID_DirectMusicGraph, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
207 &IID_IUnknown, (void**)&dmg);
208 ok(hr == CLASS_E_NOAGGREGATION,
209 "DirectMusicGraph create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
210 ok(!dmg, "dmg = %p\n", dmg);
212 /* Invalid RIID */
213 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory,
214 (void**)&dmg);
215 ok(hr == E_NOINTERFACE, "DirectMusicGraph create failed: %#lx, expected E_NOINTERFACE\n", hr);
217 /* Same refcount for all DirectMusicGraph interfaces */
218 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
219 &IID_IDirectMusicGraph, (void**)&dmg);
220 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
221 refcount = IDirectMusicGraph_AddRef(dmg);
222 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
224 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IDirectMusicObject, (void**)&dmo);
225 if (hr == E_NOINTERFACE) {
226 win_skip("DirectMusicGraph without IDirectMusicObject\n");
227 return;
229 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
230 refcount = IDirectMusicObject_AddRef(dmo);
231 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
232 refcount = IDirectMusicObject_Release(dmo);
234 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
235 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
236 refcount = IPersistStream_AddRef(ps);
237 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
238 refcount = IPersistStream_Release(ps);
240 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IUnknown, (void**)&unk);
241 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
242 refcount = IUnknown_AddRef(unk);
243 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
244 refcount = IUnknown_Release(unk);
246 while (IDirectMusicGraph_Release(dmg));
249 static void test_COM_segment(void)
251 IDirectMusicSegment8 *dms = (IDirectMusicSegment8*)0xdeadbeef;
252 IDirectMusicObject *dmo;
253 IPersistStream *stream;
254 IUnknown *unk;
255 ULONG refcount;
256 HRESULT hr;
258 /* COM aggregation */
259 hr = CoCreateInstance(&CLSID_DirectMusicSegment, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
260 &IID_IUnknown, (void**)&dms);
261 ok(hr == CLASS_E_NOAGGREGATION,
262 "DirectMusicSegment create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
263 ok(!dms, "dms = %p\n", dms);
265 /* Invalid RIID */
266 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
267 &IID_IDirectSound, (void**)&dms);
268 ok(hr == E_NOINTERFACE, "DirectMusicSegment create failed: %#lx, expected E_NOINTERFACE\n", hr);
270 /* Same refcount */
271 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
272 &IID_IDirectMusicSegment8, (void**)&dms);
273 if (hr == E_NOINTERFACE) {
274 win_skip("DirectMusicSegment without IDirectMusicSegment8\n");
275 return;
277 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
278 refcount = IDirectMusicSegment8_AddRef(dms);
279 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
280 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IDirectMusicObject, (void**)&dmo);
281 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
282 IDirectMusicSegment8_AddRef(dms);
283 refcount = IDirectMusicSegment8_Release(dms);
284 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
285 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IPersistStream, (void**)&stream);
286 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
287 refcount = IDirectMusicSegment8_Release(dms);
288 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
289 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IUnknown, (void**)&unk);
290 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
291 refcount = IUnknown_Release(unk);
292 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
293 refcount = IDirectMusicObject_Release(dmo);
294 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
295 refcount = IPersistStream_Release(stream);
296 ok (refcount == 1, "refcount == %lu, expected 1\n", refcount);
297 refcount = IDirectMusicSegment8_Release(dms);
298 ok (refcount == 0, "refcount == %lu, expected 0\n", refcount);
301 static void test_COM_segmentstate(void)
303 IDirectMusicSegmentState8 *dmss8 = (IDirectMusicSegmentState8*)0xdeadbeef;
304 IUnknown *unk;
305 ULONG refcount;
306 HRESULT hr;
308 /* COM aggregation */
309 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
310 &IID_IUnknown, (void**)&dmss8);
311 ok(hr == CLASS_E_NOAGGREGATION,
312 "DirectMusicSegmentState8 create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
313 ok(!dmss8, "dmss8 = %p\n", dmss8);
315 /* Invalid RIID */
316 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
317 &IID_IDirectMusicObject, (void**)&dmss8);
318 ok(hr == E_NOINTERFACE, "DirectMusicSegmentState8 create failed: %#lx, expected E_NOINTERFACE\n", hr);
320 /* Same refcount for all DirectMusicSegmentState interfaces */
321 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
322 &IID_IDirectMusicSegmentState8, (void**)&dmss8);
323 if (hr == E_NOINTERFACE) {
324 win_skip("DirectMusicSegmentState without IDirectMusicSegmentState8\n");
325 return;
327 ok(hr == S_OK, "DirectMusicSegmentState8 create failed: %#lx, expected S_OK\n", hr);
328 refcount = IDirectMusicSegmentState8_AddRef(dmss8);
329 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
331 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, (void**)&unk);
332 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
333 refcount = IUnknown_AddRef(unk);
334 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
335 refcount = IUnknown_Release(unk);
337 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, NULL);
338 ok(hr == E_POINTER, "got %#lx\n", hr);
340 while (IDirectMusicSegmentState8_Release(dmss8));
343 static void test_COM_track(void)
345 IDirectMusicTrack *dmt;
346 IDirectMusicTrack8 *dmt8;
347 IPersistStream *ps;
348 IUnknown *unk;
349 ULONG refcount;
350 HRESULT hr;
351 #define X(class) &CLSID_ ## class, #class
352 const struct {
353 REFCLSID clsid;
354 const char *name;
355 BOOL has_dmt8;
356 } class[] = {
357 { X(DirectMusicLyricsTrack), TRUE },
358 { X(DirectMusicMarkerTrack), FALSE },
359 { X(DirectMusicParamControlTrack), TRUE },
360 { X(DirectMusicSegmentTriggerTrack), TRUE },
361 { X(DirectMusicSeqTrack), TRUE },
362 { X(DirectMusicSysExTrack), TRUE },
363 { X(DirectMusicTempoTrack), TRUE },
364 { X(DirectMusicTimeSigTrack), FALSE },
365 { X(DirectMusicWaveTrack), TRUE }
367 #undef X
368 unsigned int i;
370 for (i = 0; i < ARRAY_SIZE(class); i++) {
371 trace("Testing %s\n", class[i].name);
372 /* COM aggregation */
373 dmt8 = (IDirectMusicTrack8*)0xdeadbeef;
374 hr = CoCreateInstance(class[i].clsid, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
375 (void**)&dmt8);
376 if (hr == REGDB_E_CLASSNOTREG) {
377 win_skip("%s not registered\n", class[i].name);
378 continue;
380 ok(hr == CLASS_E_NOAGGREGATION,
381 "%s create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", class[i].name, hr);
382 ok(!dmt8, "dmt8 = %p\n", dmt8);
384 /* Invalid RIID */
385 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
386 (void**)&dmt8);
387 ok(hr == E_NOINTERFACE, "%s create failed: %#lx, expected E_NOINTERFACE\n", class[i].name, hr);
389 /* Same refcount for all DirectMusicTrack interfaces */
390 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
391 (void**)&dmt);
392 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
393 refcount = IDirectMusicTrack_AddRef(dmt);
394 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
396 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
397 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
398 refcount = IPersistStream_AddRef(ps);
399 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
400 IPersistStream_Release(ps);
402 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IUnknown, (void**)&unk);
403 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
404 refcount = IUnknown_AddRef(unk);
405 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
406 refcount = IUnknown_Release(unk);
408 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
409 if (class[i].has_dmt8) {
410 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
411 refcount = IDirectMusicTrack8_AddRef(dmt8);
412 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
413 refcount = IDirectMusicTrack8_Release(dmt8);
414 } else {
415 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
416 refcount = IDirectMusicTrack_AddRef(dmt);
417 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
420 while (IDirectMusicTrack_Release(dmt));
424 static void test_audiopathconfig(void)
426 IDirectMusicObject *dmo;
427 IPersistStream *ps;
428 CLSID class = { 0 };
429 ULARGE_INTEGER size;
430 HRESULT hr;
432 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
433 &IID_IDirectMusicObject, (void**)&dmo);
434 if (hr == REGDB_E_CLASSNOTREG) {
435 win_skip("DirectMusicAudioPathConfig not registered\n");
436 return;
438 ok(hr == S_OK, "DirectMusicAudioPathConfig create failed: %#lx, expected S_OK\n", hr);
440 /* IPersistStream */
441 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
442 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
443 hr = IPersistStream_GetClassID(ps, &class);
444 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
445 ok(IsEqualGUID(&class, &CLSID_DirectMusicAudioPathConfig),
446 "Expected class CLSID_DirectMusicAudioPathConfig got %s\n", wine_dbgstr_guid(&class));
448 /* Unimplemented IPersistStream methods */
449 hr = IPersistStream_IsDirty(ps);
450 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
451 hr = IPersistStream_GetSizeMax(ps, &size);
452 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
453 hr = IPersistStream_Save(ps, NULL, TRUE);
454 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
456 while (IDirectMusicObject_Release(dmo));
459 static void test_graph(void)
461 IDirectMusicGraph *dmg;
462 IPersistStream *ps;
463 CLSID class = { 0 };
464 ULARGE_INTEGER size;
465 HRESULT hr;
467 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
468 &IID_IDirectMusicGraph, (void**)&dmg);
469 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
471 /* IPersistStream */
472 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
473 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
474 hr = IPersistStream_GetClassID(ps, &class);
475 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
476 if (hr == S_OK)
477 ok(IsEqualGUID(&class, &CLSID_DirectMusicGraph),
478 "Expected class CLSID_DirectMusicGraph got %s\n", wine_dbgstr_guid(&class));
480 /* Unimplemented IPersistStream methods */
481 hr = IPersistStream_IsDirty(ps);
482 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
483 hr = IPersistStream_GetSizeMax(ps, &size);
484 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
485 hr = IPersistStream_Save(ps, NULL, TRUE);
486 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
488 while (IDirectMusicGraph_Release(dmg));
491 static void test_segment(void)
493 IDirectMusicSegment *dms;
494 IPersistStream *ps;
495 CLSID class = { 0 };
496 ULARGE_INTEGER size;
497 HRESULT hr;
499 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
500 &IID_IDirectMusicSegment, (void**)&dms);
501 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
503 /* IPersistStream */
504 hr = IDirectMusicSegment_QueryInterface(dms, &IID_IPersistStream, (void**)&ps);
505 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
506 hr = IPersistStream_GetClassID(ps, &class);
507 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
508 if (hr == S_OK)
509 ok(IsEqualGUID(&class, &CLSID_DirectMusicSegment),
510 "Expected class CLSID_DirectMusicSegment got %s\n", wine_dbgstr_guid(&class));
512 /* Unimplemented IPersistStream methods */
513 hr = IPersistStream_IsDirty(ps);
514 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
515 hr = IPersistStream_GetSizeMax(ps, &size);
516 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
517 hr = IPersistStream_Save(ps, NULL, TRUE);
518 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
520 while (IDirectMusicSegment_Release(dms));
523 static void _add_track(IDirectMusicSegment8 *seg, REFCLSID class, const char *name, DWORD group)
525 IDirectMusicTrack *track;
526 HRESULT hr;
528 hr = CoCreateInstance(class, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
529 (void**)&track);
530 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", name, hr);
531 hr = IDirectMusicSegment8_InsertTrack(seg, track, group);
532 if (group)
533 ok(hr == S_OK, "Inserting %s failed: %#lx, expected S_OK\n", name, hr);
534 else
535 ok(hr == E_INVALIDARG, "Inserting %s failed: %#lx, expected E_INVALIDARG\n", name, hr);
536 IDirectMusicTrack_Release(track);
539 #define add_track(seg, class, group) _add_track(seg, &CLSID_DirectMusic ## class, #class, group)
541 static void _expect_track(IDirectMusicSegment8 *seg, REFCLSID expect, const char *name, DWORD group,
542 DWORD index, BOOL ignore_guid)
544 IDirectMusicTrack *track;
545 IPersistStream *ps;
546 CLSID class;
547 HRESULT hr;
549 if (ignore_guid)
550 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, group, index, &track);
551 else
552 hr = IDirectMusicSegment8_GetTrack(seg, expect, group, index, &track);
553 if (!expect) {
554 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
555 return;
558 ok(hr == S_OK, "GetTrack failed: %#lx, expected S_OK\n", hr);
559 hr = IDirectMusicTrack_QueryInterface(track, &IID_IPersistStream, (void**)&ps);
560 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
561 hr = IPersistStream_GetClassID(ps, &class);
562 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
563 ok(IsEqualGUID(&class, expect), "For group %#lx index %lu: Expected class %s got %s\n",
564 group, index, name, wine_dbgstr_guid(&class));
566 IPersistStream_Release(ps);
567 IDirectMusicTrack_Release(track);
570 #define expect_track(seg, class, group, index) \
571 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, TRUE)
572 #define expect_guid_track(seg, class, group, index) \
573 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, FALSE)
575 static void test_gettrack(void)
577 IDirectMusicSegment8 *seg;
578 IDirectMusicTrack *track;
579 HRESULT hr;
581 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
582 &IID_IDirectMusicSegment8, (void**)&seg);
583 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
585 add_track(seg, LyricsTrack, 0x0); /* failure */
586 add_track(seg, LyricsTrack, 0x1); /* idx 0 group 1 */
587 add_track(seg, ParamControlTrack, 0x3); /* idx 1 group 1, idx 0 group 2 */
588 add_track(seg, SegmentTriggerTrack, 0x2); /* idx 1 group 2 */
589 add_track(seg, SeqTrack, 0x1); /* idx 2 group 1 */
590 add_track(seg, TempoTrack, 0x7); /* idx 3 group 1, idx 2 group 2, idx 0 group 3 */
591 add_track(seg, WaveTrack, 0xffffffff); /* idx 4 group 1, idx 3 group 2, idx 1 group 3 */
593 /* Ignore GUID in GetTrack */
594 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, 0, 0, &track);
595 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
597 expect_track(seg, LyricsTrack, 0x1, 0);
598 expect_track(seg, ParamControlTrack, 0x1, 1);
599 expect_track(seg, SeqTrack, 0x1, 2);
600 expect_track(seg, TempoTrack, 0x1, 3);
601 expect_track(seg, WaveTrack, 0x1, 4);
602 _expect_track(seg, NULL, "", 0x1, 5, TRUE);
603 _expect_track(seg, NULL, "", 0x1, DMUS_SEG_ANYTRACK, TRUE);
604 expect_track(seg, ParamControlTrack, 0x2, 0);
605 expect_track(seg, WaveTrack, 0x80000000, 0);
606 expect_track(seg, SegmentTriggerTrack, 0x3, 2); /* groups 1+2 combined index */
607 expect_track(seg, SeqTrack, 0x3, 3); /* groups 1+2 combined index */
608 expect_track(seg, TempoTrack, 0x7, 4); /* groups 1+2+3 combined index */
609 expect_track(seg, TempoTrack, 0xffffffff, 4); /* all groups combined index */
610 _expect_track(seg, NULL, "", 0xffffffff, DMUS_SEG_ANYTRACK, TRUE);
612 /* Use the GUID in GetTrack */
613 hr = IDirectMusicSegment8_GetTrack(seg, &CLSID_DirectMusicLyricsTrack, 0, 0, &track);
614 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
616 expect_guid_track(seg, LyricsTrack, 0x1, 0);
617 expect_guid_track(seg, ParamControlTrack, 0x1, 0);
618 expect_guid_track(seg, SeqTrack, 0x1, 0);
619 expect_guid_track(seg, TempoTrack, 0x1, 0);
620 expect_guid_track(seg, ParamControlTrack, 0x2, 0);
621 expect_guid_track(seg, SegmentTriggerTrack, 0x3, 0);
622 expect_guid_track(seg, SeqTrack, 0x3, 0);
623 expect_guid_track(seg, TempoTrack, 0x7, 0);
624 expect_guid_track(seg, TempoTrack, 0xffffffff, 0);
626 IDirectMusicSegment8_Release(seg);
629 static void test_segment_param(void)
631 IDirectMusicSegment8 *seg;
632 char buf[64];
633 HRESULT hr;
635 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
636 &IID_IDirectMusicSegment8, (void **)&seg);
637 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
639 add_track(seg, LyricsTrack, 0x1); /* no params */
640 add_track(seg, SegmentTriggerTrack, 0x1); /* all params "supported" */
642 hr = IDirectMusicSegment8_GetParam(seg, NULL, 0x1, 0, 0, NULL, buf);
643 ok(hr == E_POINTER, "GetParam failed: %#lx, expected E_POINTER\n", hr);
644 hr = IDirectMusicSegment8_SetParam(seg, NULL, 0x1, 0, 0, buf);
645 todo_wine ok(hr == E_POINTER, "SetParam failed: %#lx, expected E_POINTER\n", hr);
647 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, NULL, buf);
648 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
649 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, NULL, buf);
650 ok(hr == DMUS_E_TRACK_NOT_FOUND, "GetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
651 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ANYTRACK, 0,
652 NULL, buf);
653 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
655 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, buf);
656 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
657 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, buf);
658 todo_wine ok(hr == DMUS_E_TRACK_NOT_FOUND,
659 "SetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
660 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ALLTRACKS,
661 0, buf);
662 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
664 IDirectMusicSegment8_Release(seg);
667 static void expect_getparam(IDirectMusicTrack *track, REFGUID type, const char *name,
668 HRESULT expect)
670 HRESULT hr;
671 char buf[64] = { 0 };
673 hr = IDirectMusicTrack8_GetParam(track, type, 0, NULL, buf);
674 ok(hr == expect, "GetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
677 static void expect_setparam(IDirectMusicTrack *track, REFGUID type, const char *name,
678 HRESULT expect)
680 HRESULT hr;
681 char buf[64] = { 0 };
683 hr = IDirectMusicTrack8_SetParam(track, type, 0, buf);
684 ok(hr == expect, "SetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
687 static void test_track(void)
689 IDirectMusicTrack *dmt;
690 IDirectMusicTrack8 *dmt8;
691 IPersistStream *ps;
692 CLSID classid;
693 ULARGE_INTEGER size;
694 HRESULT hr;
695 #define X(guid) &guid, #guid
696 const struct {
697 REFGUID type;
698 const char *name;
699 } param_types[] = {
700 { X(GUID_BandParam) },
701 { X(GUID_ChordParam) },
702 { X(GUID_Clear_All_Bands) },
703 { X(GUID_CommandParam) },
704 { X(GUID_CommandParam2) },
705 { X(GUID_CommandParamNext) },
706 { X(GUID_ConnectToDLSCollection) },
707 { X(GUID_Disable_Auto_Download) },
708 { X(GUID_DisableTempo) },
709 { X(GUID_DisableTimeSig) },
710 { X(GUID_Download) },
711 { X(GUID_DownloadToAudioPath) },
712 { X(GUID_Enable_Auto_Download) },
713 { X(GUID_EnableTempo) },
714 { X(GUID_EnableTimeSig) },
715 { X(GUID_IDirectMusicBand) },
716 { X(GUID_IDirectMusicChordMap) },
717 { X(GUID_IDirectMusicStyle) },
718 { X(GUID_MuteParam) },
719 { X(GUID_Play_Marker) },
720 { X(GUID_RhythmParam) },
721 { X(GUID_SeedVariations) },
722 { X(GUID_StandardMIDIFile) },
723 { X(GUID_TempoParam) },
724 { X(GUID_TimeSignature) },
725 { X(GUID_Unload) },
726 { X(GUID_UnloadFromAudioPath) },
727 { X(GUID_Valid_Start_Time) },
728 { X(GUID_Variations) },
729 { X(GUID_NULL) }
731 #undef X
732 #define X(class) &CLSID_ ## class, #class
733 const struct {
734 REFCLSID clsid;
735 const char *name;
736 /* bitfield with supported param types */
737 unsigned int has_params;
738 } class[] = {
739 { X(DirectMusicLyricsTrack), 0 },
740 { X(DirectMusicMarkerTrack), 0x8080000 },
741 { X(DirectMusicParamControlTrack), 0 },
742 { X(DirectMusicSegmentTriggerTrack), 0x3fffffff },
743 { X(DirectMusicSeqTrack), ~0 }, /* param methods not implemented */
744 { X(DirectMusicSysExTrack), ~0 }, /* param methods not implemented */
745 { X(DirectMusicTempoTrack), 0x802100 },
746 { X(DirectMusicTimeSigTrack), 0x1004200 },
747 { X(DirectMusicWaveTrack), 0x6001c80 }
749 #undef X
750 unsigned int i, j;
752 for (i = 0; i < ARRAY_SIZE(class); i++) {
753 trace("Testing %s\n", class[i].name);
754 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
755 (void**)&dmt);
756 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
758 /* IDirectMusicTrack */
759 if (class[i].has_params != ~0) {
760 for (j = 0; j < ARRAY_SIZE(param_types); j++) {
761 hr = IDirectMusicTrack8_IsParamSupported(dmt, param_types[j].type);
762 if (class[i].has_params & (1 << j)) {
763 ok(hr == S_OK, "IsParamSupported(%s) failed: %#lx, expected S_OK\n",
764 param_types[j].name, hr);
765 if (class[i].clsid == &CLSID_DirectMusicSegmentTriggerTrack) {
766 expect_getparam(dmt, param_types[j].type, param_types[j].name,
767 DMUS_E_GET_UNSUPPORTED);
768 expect_setparam(dmt, param_types[j].type, param_types[j].name, S_OK);
769 } else if (class[i].clsid == &CLSID_DirectMusicMarkerTrack)
770 expect_setparam(dmt, param_types[j].type, param_types[j].name,
771 DMUS_E_SET_UNSUPPORTED);
772 else if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
773 expect_getparam(dmt, param_types[j].type, param_types[j].name,
774 DMUS_E_GET_UNSUPPORTED);
775 } else {
776 ok(hr == DMUS_E_TYPE_UNSUPPORTED,
777 "IsParamSupported(%s) failed: %#lx, expected DMUS_E_TYPE_UNSUPPORTED\n",
778 param_types[j].name, hr);
779 expect_getparam(dmt, param_types[j].type, param_types[j].name,
780 DMUS_E_GET_UNSUPPORTED);
781 if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
782 expect_setparam(dmt, param_types[j].type, param_types[j].name,
783 DMUS_E_TYPE_UNSUPPORTED);
784 else
785 expect_setparam(dmt, param_types[j].type, param_types[j].name,
786 DMUS_E_SET_UNSUPPORTED);
789 /* GetParam / SetParam for IsParamSupported supported types */
790 if (class[i].clsid == &CLSID_DirectMusicTimeSigTrack) {
791 expect_getparam(dmt, &GUID_DisableTimeSig, "GUID_DisableTimeSig",
792 DMUS_E_GET_UNSUPPORTED);
793 expect_getparam(dmt, &GUID_EnableTimeSig, "GUID_EnableTimeSig",
794 DMUS_E_GET_UNSUPPORTED);
795 expect_setparam(dmt, &GUID_TimeSignature, "GUID_TimeSignature",
796 DMUS_E_SET_UNSUPPORTED);
797 } else if (class[i].clsid == &CLSID_DirectMusicTempoTrack) {
798 expect_getparam(dmt, &GUID_DisableTempo, "GUID_DisableTempo",
799 DMUS_E_GET_UNSUPPORTED);
800 expect_getparam(dmt, &GUID_EnableTempo, "GUID_EnableTempo",
801 DMUS_E_GET_UNSUPPORTED);
804 } else {
805 hr = IDirectMusicTrack_GetParam(dmt, NULL, 0, NULL, NULL);
806 ok(hr == E_NOTIMPL, "IDirectMusicTrack_GetParam failed: %#lx\n", hr);
807 hr = IDirectMusicTrack_SetParam(dmt, NULL, 0, NULL);
808 ok(hr == E_NOTIMPL, "IDirectMusicTrack_SetParam failed: %#lx\n", hr);
809 hr = IDirectMusicTrack_IsParamSupported(dmt, NULL);
810 ok(hr == E_NOTIMPL, "IDirectMusicTrack_IsParamSupported failed: %#lx\n", hr);
812 hr = IDirectMusicTrack_IsParamSupported(dmt, &GUID_IDirectMusicStyle);
813 ok(hr == E_NOTIMPL, "got: %#lx\n", hr);
815 if (class[i].clsid != &CLSID_DirectMusicMarkerTrack &&
816 class[i].clsid != &CLSID_DirectMusicTimeSigTrack) {
817 hr = IDirectMusicTrack_AddNotificationType(dmt, NULL);
818 ok(hr == E_NOTIMPL, "IDirectMusicTrack_AddNotificationType failed: %#lx\n", hr);
819 hr = IDirectMusicTrack_RemoveNotificationType(dmt, NULL);
820 ok(hr == E_NOTIMPL, "IDirectMusicTrack_RemoveNotificationType failed: %#lx\n", hr);
822 hr = IDirectMusicTrack_Clone(dmt, 0, 0, NULL);
823 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack_Clone failed: %#lx\n", hr);
825 /* IDirectMusicTrack8 */
826 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
827 if (hr == S_OK) {
828 hr = IDirectMusicTrack8_PlayEx(dmt8, NULL, 0, 0, 0, 0, NULL, NULL, 0);
829 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_PlayEx failed: %#lx\n", hr);
830 if (class[i].has_params == ~0) {
831 hr = IDirectMusicTrack8_GetParamEx(dmt8, NULL, 0, NULL, NULL, NULL, 0);
832 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_GetParamEx failed: %#lx\n", hr);
833 hr = IDirectMusicTrack8_SetParamEx(dmt8, NULL, 0, NULL, NULL, 0);
834 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_SetParamEx failed: %#lx\n", hr);
836 hr = IDirectMusicTrack8_Compose(dmt8, NULL, 0, NULL);
837 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Compose failed: %#lx\n", hr);
838 hr = IDirectMusicTrack8_Join(dmt8, NULL, 0, NULL, 0, NULL);
839 if (class[i].clsid == &CLSID_DirectMusicTempoTrack)
840 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
841 else
842 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
843 IDirectMusicTrack8_Release(dmt8);
846 /* IPersistStream */
847 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
848 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
849 hr = IPersistStream_GetClassID(ps, &classid);
850 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
851 ok(IsEqualGUID(&classid, class[i].clsid),
852 "Expected class %s got %s\n", class[i].name, wine_dbgstr_guid(&classid));
853 hr = IPersistStream_IsDirty(ps);
854 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
856 /* Unimplemented IPersistStream methods */
857 hr = IPersistStream_GetSizeMax(ps, &size);
858 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
859 hr = IPersistStream_Save(ps, NULL, TRUE);
860 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
862 while (IDirectMusicTrack_Release(dmt));
866 struct chunk {
867 FOURCC id;
868 DWORD size;
869 FOURCC type;
872 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
874 /* Generate a RIFF file format stream from an array of FOURCC ids.
875 RIFF and LIST need to be followed by the form type respectively list type,
876 followed by the chunks of the list and terminated with 0. */
877 static IStream *gen_riff_stream(const FOURCC *ids)
879 static const LARGE_INTEGER zero;
880 int level = -1;
881 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
882 char riff[1024];
883 char *p = riff;
884 struct chunk *ck;
885 IStream *stream;
887 do {
888 ck = (struct chunk *)p;
889 ck->id = *ids++;
890 switch (ck->id) {
891 case 0:
892 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
893 level--;
894 break;
895 case FOURCC_LIST:
896 case FOURCC_RIFF:
897 level++;
898 sizes[level] = &ck->size;
899 ck->type = *ids++;
900 p += sizeof(*ck);
901 break;
902 case DMUS_FOURCC_GUID_CHUNK:
903 ck->size = sizeof(GUID_NULL);
904 p += CHUNK_HDR_SIZE;
905 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
906 p += ck->size;
907 break;
908 case DMUS_FOURCC_VERSION_CHUNK:
910 DMUS_VERSION ver = {5, 8};
912 ck->size = sizeof(ver);
913 p += CHUNK_HDR_SIZE;
914 memcpy(p, &ver, sizeof(ver));
915 p += ck->size;
916 break;
918 default:
920 /* Just convert the FOURCC id to a WCHAR string */
921 WCHAR *s;
923 ck->size = 5 * sizeof(WCHAR);
924 p += CHUNK_HDR_SIZE;
925 s = (WCHAR *)p;
926 s[0] = (char)(ck->id);
927 s[1] = (char)(ck->id >> 8);
928 s[2] = (char)(ck->id >> 16);
929 s[3] = (char)(ck->id >> 24);
930 s[4] = 0;
931 p += ck->size;
934 } while (level >= 0);
936 ck = (struct chunk *)riff;
937 CreateStreamOnHGlobal(NULL, TRUE, &stream);
938 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
939 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
941 return stream;
944 static void test_parsedescriptor(void)
946 IDirectMusicObject *dmo;
947 IStream *stream;
948 DMUS_OBJECTDESC desc;
949 HRESULT hr;
950 DWORD valid;
951 unsigned int i;
952 /* fourcc ~0 will be replaced later on */
953 FOURCC alldesc[] =
955 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
956 DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK, DMUS_FOURCC_UCMT_CHUNK,
957 DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, 0
959 FOURCC dupes[] =
961 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
962 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
963 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, 0,
964 FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
966 FOURCC empty[] = {FOURCC_RIFF, ~0, 0};
967 FOURCC inam[] = {FOURCC_RIFF, ~0, FOURCC_LIST, ~0, mmioFOURCC('I','N','A','M'), 0, 0};
968 FOURCC noriff[] = {mmioFOURCC('J','U','N','K'), 0};
969 #define X(class) &CLSID_ ## class, #class
970 #define Y(form) form, #form
971 const struct {
972 REFCLSID clsid;
973 const char *class;
974 FOURCC form;
975 const char *name;
976 BOOL needs_size;
977 } forms[] = {
978 { X(DirectMusicSegment), Y(DMUS_FOURCC_SEGMENT_FORM), FALSE },
979 { X(DirectMusicSegment), Y(mmioFOURCC('W','A','V','E')), FALSE },
980 { X(DirectMusicAudioPathConfig), Y(DMUS_FOURCC_AUDIOPATH_FORM), TRUE },
981 { X(DirectMusicGraph), Y(DMUS_FOURCC_TOOLGRAPH_FORM), TRUE },
983 #undef X
984 #undef Y
986 for (i = 0; i < ARRAY_SIZE(forms); i++) {
987 trace("Testing %s / %s\n", forms[i].class, forms[i].name);
988 hr = CoCreateInstance(forms[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
989 (void **)&dmo);
990 if (hr != S_OK) {
991 win_skip("Could not create %s object: %#lx\n", forms[i].class, hr);
992 return;
995 /* Nothing loaded */
996 memset(&desc, 0, sizeof(desc));
997 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
998 if (forms[i].needs_size) {
999 todo_wine ok(hr == E_INVALIDARG, "GetDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1000 desc.dwSize = sizeof(desc);
1001 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1003 ok(hr == S_OK, "GetDescriptor failed: %#lx, expected S_OK\n", hr);
1004 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1005 desc.dwValidData);
1006 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1007 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1009 /* Empty RIFF stream */
1010 empty[1] = forms[i].form;
1011 stream = gen_riff_stream(empty);
1012 memset(&desc, 0, sizeof(desc));
1013 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1014 if (forms[i].needs_size) {
1015 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1016 desc.dwSize = sizeof(desc);
1017 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1019 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1020 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1021 desc.dwValidData);
1022 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1023 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1025 /* NULL pointers */
1026 memset(&desc, 0, sizeof(desc));
1027 desc.dwSize = sizeof(desc);
1028 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
1029 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1030 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
1031 if (forms[i].needs_size)
1032 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1033 else
1034 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1035 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, NULL);
1036 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1037 IStream_Release(stream);
1039 /* Wrong form */
1040 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
1041 stream = gen_riff_stream(empty);
1042 memset(&desc, 0, sizeof(desc));
1043 desc.dwSize = sizeof(desc);
1044 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1045 if (forms[i].needs_size)
1046 ok(hr == DMUS_E_CHUNKNOTFOUND,
1047 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1048 else
1049 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
1050 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
1051 IStream_Release(stream);
1053 /* Not a RIFF stream */
1054 stream = gen_riff_stream(noriff);
1055 memset(&desc, 0, sizeof(desc));
1056 desc.dwSize = sizeof(desc);
1057 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1058 if (forms[i].needs_size)
1059 ok(hr == DMUS_E_CHUNKNOTFOUND,
1060 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1061 else
1062 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
1063 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
1064 IStream_Release(stream);
1066 /* All desc chunks */
1067 alldesc[1] = forms[i].form;
1068 stream = gen_riff_stream(alldesc);
1069 memset(&desc, 0, sizeof(desc));
1070 desc.dwSize = sizeof(desc);
1071 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1072 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1073 valid = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_VERSION;
1074 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1075 valid |= DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY;
1076 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1077 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1078 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1079 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
1080 wine_dbgstr_guid(&desc.guidClass));
1081 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
1082 "Got version %lu.%lu, expected 5.8\n", desc.vVersion.dwVersionMS,
1083 desc.vVersion.dwVersionLS);
1084 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1085 ok(!lstrcmpW(desc.wszName, L"UNAM"), "Got name '%s', expected 'UNAM'\n",
1086 wine_dbgstr_w(desc.wszName));
1087 IStream_Release(stream);
1089 /* Duplicated chunks */
1090 dupes[1] = forms[i].form;
1091 stream = gen_riff_stream(dupes);
1092 memset(&desc, 0, sizeof(desc));
1093 desc.dwSize = sizeof(desc);
1094 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1095 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1096 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1097 IStream_Release(stream);
1099 /* UNFO list with INAM */
1100 inam[1] = forms[i].form;
1101 inam[3] = DMUS_FOURCC_UNFO_LIST;
1102 stream = gen_riff_stream(inam);
1103 memset(&desc, 0, sizeof(desc));
1104 desc.dwSize = sizeof(desc);
1105 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1106 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1107 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1108 desc.dwValidData);
1109 IStream_Release(stream);
1111 /* INFO list with INAM */
1112 inam[3] = DMUS_FOURCC_INFO_LIST;
1113 stream = gen_riff_stream(inam);
1114 memset(&desc, 0, sizeof(desc));
1115 desc.dwSize = sizeof(desc);
1116 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1117 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1118 valid = DMUS_OBJ_CLASS;
1119 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1120 valid |= DMUS_OBJ_NAME;
1121 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1122 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1123 ok(!lstrcmpW(desc.wszName, L"I"), "Got name '%s', expected 'I'\n",
1124 wine_dbgstr_w(desc.wszName));
1125 IStream_Release(stream);
1127 IDirectMusicObject_Release(dmo);
1131 START_TEST(dmime)
1133 CoInitialize(NULL);
1135 if (missing_dmime())
1137 skip("dmime not available\n");
1138 CoUninitialize();
1139 return;
1141 test_COM_audiopath();
1142 test_COM_audiopathconfig();
1143 test_COM_graph();
1144 test_COM_segment();
1145 test_COM_segmentstate();
1146 test_COM_track();
1147 test_audiopathconfig();
1148 test_graph();
1149 test_segment();
1150 test_gettrack();
1151 test_segment_param();
1152 test_track();
1153 test_parsedescriptor();
1155 CoUninitialize();