include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / dmscript / tests / dmscript.c
blobf3ae2c940d2bd75dd76be968ea73e967e3eba63f
1 /*
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
19 #define COBJMACROS
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <initguid.h>
24 #include <wine/test.h>
25 #include <ole2.h>
26 #include <dmusici.h>
27 #include <dmusicf.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);
38 return FALSE;
40 return TRUE;
43 /* Outer IUnknown for COM aggregation tests */
44 struct unk_impl {
45 IUnknown IUnknown_iface;
46 LONG ref;
47 IUnknown *inner_unk;
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 =
78 unk_QueryInterface,
79 unk_AddRef,
80 unk_Release
83 static void test_COM(void)
85 IDirectMusicScript *dms = NULL;
86 IDirectMusicObject *dmo;
87 IPersistStream *ps;
88 IUnknown *unk;
89 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL};
90 ULONG refcount;
91 HRESULT hr;
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);
100 /* Invalid RIID */
101 hr = CoCreateInstance(&CLSID_DirectMusicScript, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory,
102 (void**)&dms);
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;
136 IPersistStream *ps;
137 IUnknown *unk;
138 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL};
139 ULONG refcount;
140 HRESULT hr;
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);
149 /* Invalid RIID */
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;
179 IPersistStream *ps;
180 CLSID class;
181 ULARGE_INTEGER size;
182 HRESULT hr;
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;
206 IPersistStream *ps;
207 CLSID class;
208 ULARGE_INTEGER size;
209 char buf[64] = { 0 };
210 HRESULT hr;
211 #define X(guid) &guid, #guid
212 const struct {
213 REFGUID type;
214 const char *name;
215 } unsupported[] = {
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) },
241 { X(GUID_Unload) },
242 { X(GUID_UnloadFromAudioPath) },
243 { X(GUID_Valid_Start_Time) },
244 { X(GUID_Variations) },
246 #undef X
247 unsigned int i;
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 */
254 todo_wine {
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);
293 /* IPersistStream */
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));
316 struct chunk {
317 FOURCC id;
318 DWORD size;
319 FOURCC type;
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;
330 int level = -1;
331 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
332 char riff[1024];
333 char *p = riff;
334 struct chunk *ck;
335 IStream *stream;
337 do {
338 ck = (struct chunk *)p;
339 ck->id = *ids++;
340 switch (ck->id) {
341 case 0:
342 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
343 level--;
344 break;
345 case FOURCC_RIFF:
346 level++;
347 sizes[level] = &ck->size;
348 ck->type = *ids++;
349 p += sizeof(*ck);
350 break;
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);
359 return stream;
362 static void test_parsedescriptor(void)
364 IDirectMusicObject *dmo;
365 IStream *stream;
366 DMUS_OBJECTDESC desc = {0};
367 HRESULT hr;
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);
374 /* Nothing loaded */
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);
394 /* NULL pointers */
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);
401 /* Wrong form */
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);
412 START_TEST(dmscript)
414 CoInitialize(NULL);
416 if (missing_dmscript())
418 skip("dmscript not available\n");
419 CoUninitialize();
420 return;
422 test_COM();
423 test_COM_scripttrack();
424 test_dmscript();
425 test_scripttrack();
426 test_parsedescriptor();
428 CoUninitialize();