shlwapi/tests: Add some tests for memory stream.
[wine.git] / dlls / dmscript / tests / dmscript.c
blob6784901cddee3a28bb7795f3ea18b072c8417b83
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: %08x, 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: %08x, 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: %08x, expected S_OK\n", hr);
109 refcount = IDirectMusicScript_AddRef(dms);
110 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
112 hr = IDirectMusicScript_QueryInterface(dms, &IID_IDirectMusicObject, (void**)&dmo);
113 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
114 refcount = IDirectMusicObject_AddRef(dmo);
115 ok(refcount == 4, "refcount == %u, 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: %08x\n", hr);
120 refcount = IPersistStream_AddRef(ps);
121 ok(refcount == 5, "refcount == %u, 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: %08x\n", hr);
126 refcount = IUnknown_AddRef(unk);
127 ok(refcount == 6, "refcount == %u, 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: %08x, 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: %08x, expected E_NOINTERFACE\n",
153 hr);
155 /* Same refcount for all DirectMusicScriptTrack interfaces */
156 hr = CoCreateInstance(&CLSID_DirectMusicScriptTrack, NULL, CLSCTX_INPROC_SERVER,
157 &IID_IDirectMusicTrack, (void**)&dmt);
158 ok(hr == S_OK, "DirectMusicScriptTrack create failed: %08x, expected S_OK\n", hr);
159 refcount = IDirectMusicTrack_AddRef(dmt);
160 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
162 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
163 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
164 refcount = IPersistStream_AddRef(ps);
165 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
166 IPersistStream_Release(ps);
168 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IUnknown, (void**)&unk);
169 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
170 refcount = IUnknown_AddRef(unk);
171 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
172 refcount = IUnknown_Release(unk);
174 while (IDirectMusicTrack_Release(dmt));
177 static void test_dmscript(void)
179 IDirectMusicScript *dms;
180 IPersistStream *ps;
181 CLSID class;
182 ULARGE_INTEGER size;
183 HRESULT hr;
185 hr = CoCreateInstance(&CLSID_DirectMusicScript, NULL, CLSCTX_INPROC_SERVER,
186 &IID_IDirectMusicScript, (void**)&dms);
187 ok(hr == S_OK, "DirectMusicScript create failed: %08x, expected S_OK\n", hr);
189 /* Unimplemented IPersistStream methods */
190 hr = IDirectMusicScript_QueryInterface(dms, &IID_IPersistStream, (void**)&ps);
191 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
192 hr = IPersistStream_GetClassID(ps, &class);
193 ok(hr == E_NOTIMPL, "IPersistStream_GetClassID failed: %08x\n", hr);
194 hr = IPersistStream_IsDirty(ps);
195 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
196 hr = IPersistStream_GetSizeMax(ps, &size);
197 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
198 hr = IPersistStream_Save(ps, NULL, TRUE);
199 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
201 while (IDirectMusicScript_Release(dms));
204 static void test_scripttrack(void)
206 IDirectMusicTrack *dmt;
207 IPersistStream *ps;
208 CLSID class;
209 ULARGE_INTEGER size;
210 HRESULT hr;
212 hr = CoCreateInstance(&CLSID_DirectMusicScriptTrack, NULL, CLSCTX_INPROC_SERVER,
213 &IID_IDirectMusicTrack, (void**)&dmt);
214 ok(hr == S_OK, "DirectMusicScriptTrack create failed: %08x, expected S_OK\n", hr);
216 /* IPersistStream */
217 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
218 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
220 hr = IPersistStream_GetClassID(ps, NULL);
221 ok(hr == E_POINTER, "got 0x%08x\n", hr);
223 hr = IPersistStream_GetClassID(ps, &class);
224 ok(hr == S_OK, "IPersistStream_GetClassID failed: %08x\n", hr);
225 ok(IsEqualGUID(&class, &CLSID_DirectMusicScriptTrack),
226 "Expected class CLSID_DirectMusicScriptTrack got %s\n", wine_dbgstr_guid(&class));
228 /* Unimplemented IPersistStream methods */
229 hr = IPersistStream_IsDirty(ps);
230 todo_wine ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
231 hr = IPersistStream_GetSizeMax(ps, &size);
232 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
233 hr = IPersistStream_Save(ps, NULL, TRUE);
234 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
236 while (IDirectMusicTrack_Release(dmt));
239 struct chunk {
240 FOURCC id;
241 DWORD size;
242 FOURCC type;
245 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
247 /* Generate a RIFF file format stream from an array of FOURCC ids.
248 RIFF and LIST need to be followed by the form type respectively list type,
249 followed by the chunks of the list and terminated with 0. */
250 static IStream *gen_riff_stream(const FOURCC *ids)
252 static const LARGE_INTEGER zero;
253 int level = -1;
254 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
255 char riff[1024];
256 char *p = riff;
257 struct chunk *ck;
258 IStream *stream;
260 do {
261 ck = (struct chunk *)p;
262 ck->id = *ids++;
263 switch (ck->id) {
264 case 0:
265 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
266 level--;
267 break;
268 case FOURCC_RIFF:
269 level++;
270 sizes[level] = &ck->size;
271 ck->type = *ids++;
272 p += sizeof(*ck);
273 break;
275 } while (level >= 0);
277 ck = (struct chunk *)riff;
278 CreateStreamOnHGlobal(NULL, TRUE, &stream);
279 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
280 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
282 return stream;
285 static void test_parsedescriptor(void)
287 IDirectMusicObject *dmo;
288 IStream *stream;
289 DMUS_OBJECTDESC desc = {0};
290 HRESULT hr;
291 FOURCC empty[] = {FOURCC_RIFF, DMUS_FOURCC_SCRIPT_FORM, 0};
293 hr = CoCreateInstance(&CLSID_DirectMusicScript, NULL, CLSCTX_INPROC_SERVER,
294 &IID_IDirectMusicObject, (void **)&dmo);
295 ok(hr == S_OK, "DirectMusicScript create failed: %08x, expected S_OK\n", hr);
297 /* Nothing loaded */
298 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
299 ok(hr == S_OK, "GetDescriptor failed: %08x, expected S_OK\n", hr);
300 todo_wine ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_VERSION),
301 "Got valid data %#x, expected DMUS_OBJ_OBJECT | DMUS_OBJ_VERSION\n", desc.dwValidData);
302 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicScript),
303 "Got class guid %s, expected CLSID_DirectMusicScript\n",
304 wine_dbgstr_guid(&desc.guidClass));
305 ok(!desc.vVersion.dwVersionMS && !desc.vVersion.dwVersionLS,
306 "Got DMUS_VERSION %u.%u, expected 0.0\n", desc.vVersion.dwVersionMS,
307 desc.vVersion.dwVersionLS);
309 /* Empty RIFF stream */
310 stream = gen_riff_stream(empty);
311 memset(&desc, 0, sizeof(desc));
312 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
313 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
314 ok(!desc.dwValidData, "Got valid data %#x, expected 0\n", desc.dwValidData);
315 IStream_Release(stream);
317 /* NULL pointers */
318 memset(&desc, 0, sizeof(desc));
319 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
320 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
321 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
322 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
324 /* Wrong form */
325 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
326 stream = gen_riff_stream(empty);
327 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
328 ok(hr == DMUS_E_SCRIPT_INVALID_FILE,
329 "ParseDescriptor failed: %08x, expected DMUS_E_SCRIPT_INVALID_FILE\n", hr);
331 IDirectMusicObject_Release(dmo);
334 START_TEST(dmscript)
336 CoInitialize(NULL);
338 if (missing_dmscript())
340 skip("dmscript not available\n");
341 CoUninitialize();
342 return;
344 test_COM();
345 test_COM_scripttrack();
346 test_dmscript();
347 test_scripttrack();
348 test_parsedescriptor();
350 CoUninitialize();