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: %08x, 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: %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
;
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: %08x, 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: %08x, expected E_NOINTERFACE\n",
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
;
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
;
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
);
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
));
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
;
254 DWORD
*sizes
[4]; /* Stack for the sizes of RIFF and LIST chunks */
261 ck
= (struct chunk
*)p
;
265 *sizes
[level
] = p
- (char *)sizes
[level
] - sizeof(DWORD
);
270 sizes
[level
] = &ck
->size
;
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
);
285 static void test_parsedescriptor(void)
287 IDirectMusicObject
*dmo
;
289 DMUS_OBJECTDESC desc
= {0};
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
);
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
);
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
);
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
);
338 if (missing_dmscript())
340 skip("dmscript not available\n");
345 test_COM_scripttrack();
348 test_parsedescriptor();