2 * Copyright 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
24 #include <wine/test.h>
29 static BOOL
missing_dmscript(void)
31 IDirectMusicScript
*dms
;
32 HRESULT hr
= CoCreateInstance(&CLSID_DirectMusicScript
, NULL
, CLSCTX_INPROC_SERVER
,
33 &IID_IDirectMusicScript
, (void**)&dms
);
35 if (hr
== S_OK
&& dms
)
37 IDirectMusicScript_Release(dms
);
43 /* Outer IUnknown for COM aggregation tests */
45 IUnknown IUnknown_iface
;
50 static inline struct unk_impl
*impl_from_IUnknown(IUnknown
*iface
)
52 return CONTAINING_RECORD(iface
, struct unk_impl
, IUnknown_iface
);
55 static HRESULT WINAPI
unk_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
57 struct unk_impl
*This
= impl_from_IUnknown(iface
);
59 return IUnknown_QueryInterface(This
->inner_unk
, riid
, ppv
);
62 static ULONG WINAPI
unk_AddRef(IUnknown
*iface
)
64 struct unk_impl
*This
= impl_from_IUnknown(iface
);
66 return InterlockedIncrement(&This
->ref
);
69 static ULONG WINAPI
unk_Release(IUnknown
*iface
)
71 struct unk_impl
*This
= impl_from_IUnknown(iface
);
73 return InterlockedDecrement(&This
->ref
);
76 static const IUnknownVtbl unk_vtbl
=
83 static void test_COM(void)
85 IDirectMusicScript
*dms
= NULL
;
86 IDirectMusicObject
*dmo
;
89 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
93 /* COM aggregation. An invalid non-NULL outer IUnknown crashes newer Windows versions */
94 hr
= CoCreateInstance(&CLSID_DirectMusicScript
, &unk_obj
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
95 &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
96 ok(hr
== CLASS_E_NOAGGREGATION
,
97 "DirectMusicScript create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
98 ok(!unk_obj
.inner_unk
, "unk_obj.inner_unk = %p\n", unk_obj
.inner_unk
);
101 hr
= CoCreateInstance(&CLSID_DirectMusicScript
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IClassFactory
,
103 ok(hr
== E_NOINTERFACE
, "DirectMusicScript create failed: %#lx, expected E_NOINTERFACE\n", hr
);
105 /* Same refcount for all DirectMusicScript interfaces */
106 hr
= CoCreateInstance(&CLSID_DirectMusicScript
, NULL
, CLSCTX_INPROC_SERVER
,
107 &IID_IDirectMusicScript
, (void**)&dms
);
108 ok(hr
== S_OK
, "DirectMusicScript create failed: %#lx, expected S_OK\n", hr
);
109 refcount
= IDirectMusicScript_AddRef(dms
);
110 ok(refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
112 hr
= IDirectMusicScript_QueryInterface(dms
, &IID_IDirectMusicObject
, (void**)&dmo
);
113 ok(hr
== S_OK
, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr
);
114 refcount
= IDirectMusicObject_AddRef(dmo
);
115 ok(refcount
== 4, "refcount == %lu, expected 4\n", refcount
);
116 refcount
= IDirectMusicObject_Release(dmo
);
118 hr
= IDirectMusicScript_QueryInterface(dms
, &IID_IPersistStream
, (void**)&ps
);
119 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
120 refcount
= IPersistStream_AddRef(ps
);
121 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
122 refcount
= IPersistStream_Release(ps
);
124 hr
= IDirectMusicScript_QueryInterface(dms
, &IID_IUnknown
, (void**)&unk
);
125 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
126 refcount
= IUnknown_AddRef(unk
);
127 ok(refcount
== 6, "refcount == %lu, expected 6\n", refcount
);
128 refcount
= IUnknown_Release(unk
);
130 while (IDirectMusicScript_Release(dms
));
133 static void test_COM_scripttrack(void)
135 IDirectMusicTrack
*dmt
;
138 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
142 /* COM aggregation. An invalid non-NULL outer IUnknown crashes newer Windows versions */
143 hr
= CoCreateInstance(&CLSID_DirectMusicScriptTrack
, &unk_obj
.IUnknown_iface
,
144 CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
145 ok(hr
== CLASS_E_NOAGGREGATION
,
146 "DirectMusicScriptTrack create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
147 ok(!unk_obj
.inner_unk
, "unk_obj.inner_unk = %p\n", unk_obj
.inner_unk
);
150 hr
= CoCreateInstance(&CLSID_DirectMusicScriptTrack
, NULL
, CLSCTX_INPROC_SERVER
,
151 &IID_IDirectMusicObject
, (void**)&dmt
);
152 ok(hr
== E_NOINTERFACE
, "DirectMusicScriptTrack create failed: %#lx, expected E_NOINTERFACE\n", hr
);
154 /* Same refcount for all DirectMusicScriptTrack interfaces */
155 hr
= CoCreateInstance(&CLSID_DirectMusicScriptTrack
, NULL
, CLSCTX_INPROC_SERVER
,
156 &IID_IDirectMusicTrack
, (void**)&dmt
);
157 ok(hr
== S_OK
, "DirectMusicScriptTrack create failed: %#lx, expected S_OK\n", hr
);
158 refcount
= IDirectMusicTrack_AddRef(dmt
);
159 ok(refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
161 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IPersistStream
, (void**)&ps
);
162 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
163 refcount
= IPersistStream_AddRef(ps
);
164 ok(refcount
== 4, "refcount == %lu, expected 4\n", refcount
);
165 IPersistStream_Release(ps
);
167 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IUnknown
, (void**)&unk
);
168 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
169 refcount
= IUnknown_AddRef(unk
);
170 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
171 refcount
= IUnknown_Release(unk
);
173 while (IDirectMusicTrack_Release(dmt
));
176 static void test_dmscript(void)
178 IDirectMusicScript
*dms
;
184 hr
= CoCreateInstance(&CLSID_DirectMusicScript
, NULL
, CLSCTX_INPROC_SERVER
,
185 &IID_IDirectMusicScript
, (void**)&dms
);
186 ok(hr
== S_OK
, "DirectMusicScript create failed: %#lx, expected S_OK\n", hr
);
188 /* Unimplemented IPersistStream methods */
189 hr
= IDirectMusicScript_QueryInterface(dms
, &IID_IPersistStream
, (void**)&ps
);
190 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
191 hr
= IPersistStream_GetClassID(ps
, &class);
192 ok(hr
== E_NOTIMPL
, "IPersistStream_GetClassID failed: %#lx\n", hr
);
193 hr
= IPersistStream_IsDirty(ps
);
194 ok(hr
== S_FALSE
, "IPersistStream_IsDirty failed: %#lx\n", hr
);
195 hr
= IPersistStream_GetSizeMax(ps
, &size
);
196 ok(hr
== E_NOTIMPL
, "IPersistStream_GetSizeMax failed: %#lx\n", hr
);
197 hr
= IPersistStream_Save(ps
, NULL
, TRUE
);
198 ok(hr
== E_NOTIMPL
, "IPersistStream_Save failed: %#lx\n", hr
);
200 while (IDirectMusicScript_Release(dms
));
203 static void test_scripttrack(void)
205 IDirectMusicTrack8
*dmt
;
209 char buf
[64] = { 0 };
211 #define X(guid) &guid, #guid
216 { X(GUID_BandParam
) },
217 { X(GUID_ChordParam
) },
218 { X(GUID_Clear_All_Bands
) },
219 { X(GUID_CommandParam
) },
220 { X(GUID_CommandParam2
) },
221 { X(GUID_CommandParamNext
) },
222 { X(GUID_ConnectToDLSCollection
) },
223 { X(GUID_Disable_Auto_Download
) },
224 { X(GUID_DisableTempo
) },
225 { X(GUID_DisableTimeSig
) },
226 { X(GUID_Download
) },
227 { X(GUID_DownloadToAudioPath
) },
228 { X(GUID_Enable_Auto_Download
) },
229 { X(GUID_EnableTempo
) },
230 { X(GUID_EnableTimeSig
) },
231 { X(GUID_IDirectMusicBand
) },
232 { X(GUID_IDirectMusicChordMap
) },
233 { X(GUID_IDirectMusicStyle
) },
234 { X(GUID_MuteParam
) },
235 { X(GUID_Play_Marker
) },
236 { X(GUID_RhythmParam
) },
237 { X(GUID_SeedVariations
) },
238 { X(GUID_StandardMIDIFile
) },
239 { X(GUID_TempoParam
) },
240 { X(GUID_TimeSignature
) },
242 { X(GUID_UnloadFromAudioPath
) },
243 { X(GUID_Valid_Start_Time
) },
244 { X(GUID_Variations
) },
249 hr
= CoCreateInstance(&CLSID_DirectMusicScriptTrack
, NULL
, CLSCTX_INPROC_SERVER
,
250 &IID_IDirectMusicTrack8
, (void**)&dmt
);
251 ok(hr
== S_OK
, "DirectMusicScriptTrack create failed: %#lx, expected S_OK\n", hr
);
253 /* IDirectMusicTrack8 */
255 hr
= IDirectMusicTrack8_Init(dmt
, NULL
);
256 ok(hr
== E_POINTER
, "IDirectMusicTrack8_Init failed: %#lx\n", hr
);
257 hr
= IDirectMusicTrack8_InitPlay(dmt
, NULL
, NULL
, NULL
, 0, 0);
258 ok(hr
== E_POINTER
, "IDirectMusicTrack8_InitPlay failed: %#lx\n", hr
);
259 hr
= IDirectMusicTrack8_EndPlay(dmt
, NULL
);
260 ok(hr
== E_POINTER
, "IDirectMusicTrack8_EndPlay failed: %#lx\n", hr
);
261 hr
= IDirectMusicTrack8_Play(dmt
, NULL
, 0, 0, 0, 0, NULL
, NULL
, 0);
262 ok(hr
== E_POINTER
, "IDirectMusicTrack8_Play failed: %#lx\n", hr
);
264 hr
= IDirectMusicTrack8_GetParam(dmt
, NULL
, 0, NULL
, NULL
);
265 ok(hr
== DMUS_E_GET_UNSUPPORTED
, "IDirectMusicTrack8_GetParam failed: %#lx\n", hr
);
266 for (i
= 0; i
< ARRAY_SIZE(unsupported
); i
++) {
267 hr
= IDirectMusicTrack8_IsParamSupported(dmt
, unsupported
[i
].type
);
268 ok(hr
== DMUS_E_TYPE_UNSUPPORTED
,
269 "IsParamSupported(%s) failed: %#lx, expected DMUS_E_TYPE_UNSUPPORTED\n",
270 unsupported
[i
].name
, hr
);
271 hr
= IDirectMusicTrack8_GetParam(dmt
, unsupported
[i
].type
, 0, NULL
, buf
);
272 ok(hr
== DMUS_E_GET_UNSUPPORTED
,
273 "GetParam(%s) failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n",
274 unsupported
[i
].name
, hr
);
275 hr
= IDirectMusicTrack8_SetParam(dmt
, unsupported
[i
].type
, 0, buf
);
276 ok(hr
== DMUS_E_SET_UNSUPPORTED
,
277 "SetParam(%s) failed: %#lx, expected DMUS_E_SET_UNSUPPORTED\n",
278 unsupported
[i
].name
, hr
);
280 hr
= IDirectMusicTrack8_AddNotificationType(dmt
, NULL
);
281 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_AddNotificationType failed: %#lx\n", hr
);
282 hr
= IDirectMusicTrack8_RemoveNotificationType(dmt
, NULL
);
283 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_RemoveNotificationType failed: %#lx\n", hr
);
284 hr
= IDirectMusicTrack8_Clone(dmt
, 0, 0, NULL
);
285 todo_wine
ok(hr
== E_POINTER
, "IDirectMusicTrack8_Clone failed: %#lx\n", hr
);
286 hr
= IDirectMusicTrack8_PlayEx(dmt
, NULL
, 0, 0, 0, 0, NULL
, NULL
, 0);
287 todo_wine
ok(hr
== E_POINTER
, "IDirectMusicTrack8_PlayEx failed: %#lx\n", hr
);
288 hr
= IDirectMusicTrack8_Compose(dmt
, NULL
, 0, NULL
);
289 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_Compose failed: %#lx\n", hr
);
290 hr
= IDirectMusicTrack8_Join(dmt
, NULL
, 0, NULL
, 0, NULL
);
291 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_Join failed: %#lx\n", hr
);
294 hr
= IDirectMusicTrack8_QueryInterface(dmt
, &IID_IPersistStream
, (void**)&ps
);
295 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
297 hr
= IPersistStream_GetClassID(ps
, NULL
);
298 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
300 hr
= IPersistStream_GetClassID(ps
, &class);
301 ok(hr
== S_OK
, "IPersistStream_GetClassID failed: %#lx\n", hr
);
302 ok(IsEqualGUID(&class, &CLSID_DirectMusicScriptTrack
),
303 "Expected class CLSID_DirectMusicScriptTrack got %s\n", wine_dbgstr_guid(&class));
305 /* Unimplemented IPersistStream methods */
306 hr
= IPersistStream_IsDirty(ps
);
307 ok(hr
== S_FALSE
, "IPersistStream_IsDirty failed: %#lx\n", hr
);
308 hr
= IPersistStream_GetSizeMax(ps
, &size
);
309 ok(hr
== E_NOTIMPL
, "IPersistStream_GetSizeMax failed: %#lx\n", hr
);
310 hr
= IPersistStream_Save(ps
, NULL
, TRUE
);
311 ok(hr
== E_NOTIMPL
, "IPersistStream_Save failed: %#lx\n", hr
);
313 while (IDirectMusicTrack8_Release(dmt
));
322 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
324 /* Generate a RIFF file format stream from an array of FOURCC ids.
325 RIFF and LIST need to be followed by the form type respectively list type,
326 followed by the chunks of the list and terminated with 0. */
327 static IStream
*gen_riff_stream(const FOURCC
*ids
)
329 static const LARGE_INTEGER zero
;
331 DWORD
*sizes
[4]; /* Stack for the sizes of RIFF and LIST chunks */
338 ck
= (struct chunk
*)p
;
342 *sizes
[level
] = p
- (char *)sizes
[level
] - sizeof(DWORD
);
347 sizes
[level
] = &ck
->size
;
352 } while (level
>= 0);
354 ck
= (struct chunk
*)riff
;
355 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
356 IStream_Write(stream
, riff
, ck
->size
+ CHUNK_HDR_SIZE
, NULL
);
357 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
362 static void test_parsedescriptor(void)
364 IDirectMusicObject
*dmo
;
366 DMUS_OBJECTDESC desc
= {0};
368 FOURCC empty
[] = {FOURCC_RIFF
, DMUS_FOURCC_SCRIPT_FORM
, 0};
370 hr
= CoCreateInstance(&CLSID_DirectMusicScript
, NULL
, CLSCTX_INPROC_SERVER
,
371 &IID_IDirectMusicObject
, (void **)&dmo
);
372 ok(hr
== S_OK
, "DirectMusicScript create failed: %#lx, expected S_OK\n", hr
);
375 hr
= IDirectMusicObject_GetDescriptor(dmo
, &desc
);
376 ok(hr
== S_OK
, "GetDescriptor failed: %#lx, expected S_OK\n", hr
);
377 todo_wine
ok(desc
.dwValidData
== (DMUS_OBJ_CLASS
| DMUS_OBJ_VERSION
),
378 "Got valid data %#lx, expected DMUS_OBJ_OBJECT | DMUS_OBJ_VERSION\n", desc
.dwValidData
);
379 ok(IsEqualGUID(&desc
.guidClass
, &CLSID_DirectMusicScript
),
380 "Got class guid %s, expected CLSID_DirectMusicScript\n",
381 wine_dbgstr_guid(&desc
.guidClass
));
382 ok(!desc
.vVersion
.dwVersionMS
&& !desc
.vVersion
.dwVersionLS
,
383 "Got DMUS_VERSION %lu.%lu, expected 0.0\n", desc
.vVersion
.dwVersionMS
,
384 desc
.vVersion
.dwVersionLS
);
386 /* Empty RIFF stream */
387 stream
= gen_riff_stream(empty
);
388 memset(&desc
, 0, sizeof(desc
));
389 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
390 ok(hr
== S_OK
, "ParseDescriptor failed: %#lx, expected S_OK\n", hr
);
391 ok(!desc
.dwValidData
, "Got valid data %#lx, expected 0\n", desc
.dwValidData
);
392 IStream_Release(stream
);
395 memset(&desc
, 0, sizeof(desc
));
396 hr
= IDirectMusicObject_ParseDescriptor(dmo
, NULL
, &desc
);
397 ok(hr
== E_POINTER
, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr
);
398 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, NULL
);
399 ok(hr
== E_POINTER
, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr
);
402 empty
[1] = DMUS_FOURCC_CONTAINER_FORM
;
403 stream
= gen_riff_stream(empty
);
404 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
405 ok(hr
== DMUS_E_SCRIPT_INVALID_FILE
,
406 "ParseDescriptor failed: %#lx, expected DMUS_E_SCRIPT_INVALID_FILE\n", hr
);
407 IStream_Release(stream
);
409 IDirectMusicObject_Release(dmo
);
416 if (missing_dmscript())
418 skip("dmscript not available\n");
423 test_COM_scripttrack();
426 test_parsedescriptor();