winegstreamer: Implement IWMReader::SetOutputProps().
[wine.git] / dlls / wmvcore / tests / wmvcore.c
blobc1972b29eb9d662341e6dee7e23566e859daa358
1 /*
2 * Copyright 2017 Alistair Leslie-Hughes
3 * Copyright 2019 Vijay Kiran Kamuju
4 * Copyright 2021 Zebediah Figura for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdbool.h>
22 #define COBJMACROS
23 #define WIN32_LEAN_AND_MEAN
24 #include "initguid.h"
25 #include "wmsdk.h"
26 #include "wmsecure.h"
27 #include "amvideo.h"
28 #include "uuids.h"
29 #include "wmcodecdsp.h"
31 #include "wine/test.h"
33 HRESULT WINAPI WMCreateWriterPriv(IWMWriter **writer);
35 static BOOL compare_media_types(const WM_MEDIA_TYPE *a, const WM_MEDIA_TYPE *b)
37 /* We can't use memcmp(), because WM_MEDIA_TYPE has a hole, which sometimes
38 * contains junk. */
40 return IsEqualGUID(&a->majortype, &b->majortype)
41 && IsEqualGUID(&a->subtype, &b->subtype)
42 && a->bFixedSizeSamples == b->bFixedSizeSamples
43 && a->bTemporalCompression == b->bTemporalCompression
44 && a->lSampleSize == b->lSampleSize
45 && IsEqualGUID(&a->formattype, &b->formattype)
46 && a->pUnk == b->pUnk
47 && a->cbFormat == b->cbFormat
48 && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat);
51 static WCHAR *load_resource(const WCHAR *name)
53 static WCHAR pathW[MAX_PATH];
54 DWORD written;
55 HANDLE file;
56 HRSRC res;
57 void *ptr;
59 GetTempPathW(ARRAY_SIZE(pathW), pathW);
60 wcscat(pathW, name);
62 file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
63 ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s, error %u.\n",
64 wine_dbgstr_w(pathW), GetLastError());
66 res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA);
67 ok(!!res, "Failed to load resource, error %u.\n", GetLastError());
68 ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
69 WriteFile(file, ptr, SizeofResource( GetModuleHandleA(NULL), res), &written, NULL);
70 ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write resource.\n");
71 CloseHandle(file);
73 return pathW;
76 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
77 static HRESULT check_interface_(unsigned int line, void *iface, REFIID riid, BOOL supported)
79 HRESULT hr, expected_hr;
80 IUnknown *unknown = iface, *out;
82 expected_hr = supported ? S_OK : E_NOINTERFACE;
84 hr = IUnknown_QueryInterface(unknown, riid, (void **)&out);
85 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
86 if (SUCCEEDED(hr))
87 IUnknown_Release(out);
88 return hr;
91 static void test_wmwriter_interfaces(void)
93 HRESULT hr;
94 IWMWriter *writer;
96 hr = WMCreateWriter( NULL, &writer );
97 ok(hr == S_OK, "WMCreateWriter failed 0x%08x\n", hr);
98 if(FAILED(hr))
100 win_skip("Failed to create IWMWriter\n");
101 return;
104 check_interface(writer, &IID_IWMWriterSink, FALSE);
106 check_interface(writer, &IID_IWMWriter, TRUE);
107 check_interface(writer, &IID_IWMWriterAdvanced, TRUE);
108 check_interface(writer, &IID_IWMWriterAdvanced2, TRUE);
109 check_interface(writer, &IID_IWMWriterAdvanced3, TRUE);
110 todo_wine check_interface(writer, &IID_IWMWriterPreprocess, TRUE);
111 todo_wine check_interface(writer, &IID_IWMHeaderInfo, TRUE);
112 todo_wine check_interface(writer, &IID_IWMHeaderInfo2, TRUE);
113 todo_wine check_interface(writer, &IID_IWMHeaderInfo3, TRUE);
115 IWMWriter_Release(writer);
118 static void test_wmreader_interfaces(void)
120 HRESULT hr;
121 IWMReader *reader;
123 hr = WMCreateReader( NULL, 0, &reader );
124 ok(hr == S_OK, "WMCreateReader failed 0x%08x\n", hr);
125 if(FAILED(hr))
127 win_skip("Failed to create IWMReader\n");
128 return;
131 check_interface(reader, &IID_IWMDRMReader, FALSE);
132 check_interface(reader, &IID_IWMDRMReader2, FALSE);
133 check_interface(reader, &IID_IWMDRMReader3, FALSE);
134 check_interface(reader, &IID_IWMSyncReader, FALSE);
135 check_interface(reader, &IID_IWMSyncReader2, FALSE);
137 check_interface(reader, &IID_IReferenceClock, TRUE);
138 check_interface(reader, &IID_IWMHeaderInfo, TRUE);
139 check_interface(reader, &IID_IWMHeaderInfo2, TRUE);
140 check_interface(reader, &IID_IWMHeaderInfo3, TRUE);
141 check_interface(reader, &IID_IWMLanguageList, TRUE);
142 check_interface(reader, &IID_IWMPacketSize, TRUE);
143 check_interface(reader, &IID_IWMPacketSize2, TRUE);
144 check_interface(reader, &IID_IWMProfile, TRUE);
145 check_interface(reader, &IID_IWMProfile2, TRUE);
146 check_interface(reader, &IID_IWMProfile3, TRUE);
147 check_interface(reader, &IID_IWMReader, TRUE);
148 check_interface(reader, &IID_IWMReaderAccelerator, TRUE);
149 check_interface(reader, &IID_IWMReaderAdvanced, TRUE);
150 check_interface(reader, &IID_IWMReaderAdvanced2, TRUE);
151 check_interface(reader, &IID_IWMReaderAdvanced3, TRUE);
152 check_interface(reader, &IID_IWMReaderAdvanced4, TRUE);
153 check_interface(reader, &IID_IWMReaderAdvanced5, TRUE);
154 check_interface(reader, &IID_IWMReaderAdvanced6, TRUE);
155 check_interface(reader, &IID_IWMReaderNetworkConfig, TRUE);
156 check_interface(reader, &IID_IWMReaderNetworkConfig2, TRUE);
157 check_interface(reader, &IID_IWMReaderPlaylistBurn, TRUE);
158 check_interface(reader, &IID_IWMReaderStreamClock, TRUE);
159 check_interface(reader, &IID_IWMReaderTimecode, TRUE);
160 check_interface(reader, &IID_IWMReaderTypeNegotiation, TRUE);
162 IWMReader_Release(reader);
165 static void test_wmsyncreader_interfaces(void)
167 HRESULT hr;
168 IWMSyncReader *reader;
170 hr = WMCreateSyncReader( NULL, 0, &reader );
171 ok(hr == S_OK, "WMCreateSyncReader failed 0x%08x\n", hr);
172 if(FAILED(hr))
174 win_skip("Failed to create IWMSyncReader\n");
175 return;
178 check_interface(reader, &IID_IReferenceClock, FALSE);
179 check_interface(reader, &IID_IWMDRMReader, FALSE);
180 check_interface(reader, &IID_IWMDRMReader2, FALSE);
181 check_interface(reader, &IID_IWMDRMReader3, FALSE);
182 check_interface(reader, &IID_IWMReader, FALSE);
183 check_interface(reader, &IID_IWMReaderAccelerator, FALSE);
184 check_interface(reader, &IID_IWMReaderAdvanced, FALSE);
185 check_interface(reader, &IID_IWMReaderAdvanced2, FALSE);
186 check_interface(reader, &IID_IWMReaderAdvanced3, FALSE);
187 check_interface(reader, &IID_IWMReaderAdvanced4, FALSE);
188 check_interface(reader, &IID_IWMReaderAdvanced5, FALSE);
189 check_interface(reader, &IID_IWMReaderAdvanced6, FALSE);
190 check_interface(reader, &IID_IWMReaderNetworkConfig, FALSE);
191 check_interface(reader, &IID_IWMReaderNetworkConfig2, FALSE);
192 check_interface(reader, &IID_IWMReaderStreamClock, FALSE);
193 check_interface(reader, &IID_IWMReaderTypeNegotiation, FALSE);
195 check_interface(reader, &IID_IWMHeaderInfo, TRUE);
196 check_interface(reader, &IID_IWMHeaderInfo2, TRUE);
197 check_interface(reader, &IID_IWMHeaderInfo3, TRUE);
198 check_interface(reader, &IID_IWMLanguageList, TRUE);
199 check_interface(reader, &IID_IWMPacketSize, TRUE);
200 check_interface(reader, &IID_IWMPacketSize2, TRUE);
201 check_interface(reader, &IID_IWMProfile, TRUE);
202 check_interface(reader, &IID_IWMProfile2, TRUE);
203 check_interface(reader, &IID_IWMProfile3, TRUE);
204 check_interface(reader, &IID_IWMReaderPlaylistBurn, TRUE);
205 check_interface(reader, &IID_IWMReaderTimecode, TRUE);
206 check_interface(reader, &IID_IWMSyncReader, TRUE);
207 check_interface(reader, &IID_IWMSyncReader2, TRUE);
209 IWMSyncReader_Release(reader);
213 static void test_profile_manager_interfaces(void)
215 HRESULT hr;
216 IWMProfileManager *profile;
218 hr = WMCreateProfileManager(&profile);
219 ok(hr == S_OK, "WMCreateProfileManager failed 0x%08x\n", hr);
220 if(FAILED(hr))
222 win_skip("Failed to create IWMProfileManager\n");
223 return;
226 IWMProfileManager_Release(profile);
229 static void test_WMCreateWriterPriv(void)
231 IWMWriter *writer, *writer2;
232 HRESULT hr;
234 hr = WMCreateWriterPriv(&writer);
235 ok(hr == S_OK, "got 0x%08x\n", hr);
237 hr = IWMWriter_QueryInterface(writer, &IID_IWMWriter, (void**)&writer2);
238 ok(hr == S_OK, "got 0x%08x\n", hr);
240 IWMWriter_Release(writer);
241 IWMWriter_Release(writer2);
244 static void test_urlextension(void)
246 HRESULT hr;
248 hr = WMCheckURLExtension(NULL);
249 ok(hr == E_INVALIDARG, "WMCheckURLExtension failed 0x%08x\n", hr);
250 hr = WMCheckURLExtension(L"test.mkv");
251 ok(hr == NS_E_INVALID_NAME, "WMCheckURLExtension failed 0x%08x\n", hr);
252 hr = WMCheckURLExtension(L"test.mp3");
253 todo_wine ok(hr == S_OK, "WMCheckURLExtension failed 0x%08x\n", hr);
254 hr = WMCheckURLExtension(L"abcd://test/test.wmv");
255 todo_wine ok(hr == S_OK, "WMCheckURLExtension failed 0x%08x\n", hr);
256 hr = WMCheckURLExtension(L"http://test/t.asf?alt=t.mkv");
257 todo_wine ok(hr == S_OK, "WMCheckURLExtension failed 0x%08x\n", hr);
260 static void test_iscontentprotected(void)
262 HRESULT hr;
263 BOOL drm;
265 hr = WMIsContentProtected(NULL, NULL);
266 ok(hr == E_INVALIDARG, "WMIsContentProtected failed 0x%08x\n", hr);
267 hr = WMIsContentProtected(NULL, &drm);
268 ok(hr == E_INVALIDARG, "WMIsContentProtected failed 0x%08x\n", hr);
269 hr = WMIsContentProtected(L"test.mp3", NULL);
270 ok(hr == E_INVALIDARG, "WMIsContentProtected failed 0x%08x\n", hr);
271 hr = WMIsContentProtected(L"test.mp3", &drm);
272 ok(hr == S_FALSE, "WMIsContentProtected failed 0x%08x\n", hr);
273 ok(drm == FALSE, "got %0dx\n", drm);
276 struct teststream
278 IStream IStream_iface;
279 LONG refcount;
280 HANDLE file;
283 static struct teststream *impl_from_IStream(IStream *iface)
285 return CONTAINING_RECORD(iface, struct teststream, IStream_iface);
288 static HRESULT WINAPI stream_QueryInterface(IStream *iface, REFIID iid, void **out)
290 if (winetest_debug > 1)
291 trace("%04x: IStream::QueryInterface(%s)\n", GetCurrentThreadId(), debugstr_guid(iid));
293 if (!IsEqualGUID(iid, &IID_IWMGetSecureChannel) && !IsEqualGUID(iid, &IID_IWMIStreamProps))
294 ok(0, "Unexpected IID %s.\n", debugstr_guid(iid));
296 return E_NOINTERFACE;
299 static ULONG WINAPI stream_AddRef(IStream *iface)
301 struct teststream *stream = impl_from_IStream(iface);
303 return InterlockedIncrement(&stream->refcount);
306 static ULONG WINAPI stream_Release(IStream *iface)
308 struct teststream *stream = impl_from_IStream(iface);
310 return InterlockedDecrement(&stream->refcount);
313 static HRESULT WINAPI stream_Read(IStream *iface, void *data, ULONG size, ULONG *ret_size)
315 struct teststream *stream = impl_from_IStream(iface);
317 if (winetest_debug > 2)
318 trace("%04x: IStream::Read(size %u)\n", GetCurrentThreadId(), size);
320 ok(size > 0, "Got zero size.\n");
321 ok(!!ret_size, "Got NULL ret_size pointer.\n");
322 if (!ReadFile(stream->file, data, size, ret_size, NULL))
323 return HRESULT_FROM_WIN32(GetLastError());
324 return S_OK;
327 static HRESULT WINAPI stream_Write(IStream *iface, const void *data, ULONG size, ULONG *ret_size)
329 ok(0, "Unexpected call.\n");
330 return E_NOTIMPL;
333 static HRESULT WINAPI stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD method, ULARGE_INTEGER *ret_offset)
335 struct teststream *stream = impl_from_IStream(iface);
336 LARGE_INTEGER size;
338 if (winetest_debug > 2)
339 trace("%04x: IStream::Seek(offset %I64u, method %#x)\n", GetCurrentThreadId(), offset.QuadPart, method);
341 GetFileSizeEx(stream->file, &size);
342 ok(offset.QuadPart < size.QuadPart, "Expected offset less than size %I64u, got %I64u.\n",
343 size.QuadPart, offset.QuadPart);
345 ok(method == STREAM_SEEK_SET, "Got method %#x.\n", method);
346 ok(!ret_offset, "Got unexpected ret_offset pointer %p\n", ret_offset);
348 if (!SetFilePointerEx(stream->file, offset, &offset, method))
349 return HRESULT_FROM_WIN32(GetLastError());
350 return S_OK;
353 static HRESULT WINAPI stream_SetSize(IStream *iface, ULARGE_INTEGER size)
355 ok(0, "Unexpected call.\n");
356 return E_NOTIMPL;
359 static HRESULT WINAPI stream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER size,
360 ULARGE_INTEGER *read_size, ULARGE_INTEGER *write_size)
362 ok(0, "Unexpected call.\n");
363 return E_NOTIMPL;
366 static HRESULT WINAPI stream_Commit(IStream *iface, DWORD flags)
368 ok(0, "Unexpected call.\n");
369 return E_NOTIMPL;
372 static HRESULT WINAPI stream_Revert(IStream *iface)
374 ok(0, "Unexpected call.\n");
375 return E_NOTIMPL;
378 static HRESULT WINAPI stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
380 ok(0, "Unexpected call.\n");
381 return E_NOTIMPL;
384 static HRESULT WINAPI stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
386 ok(0, "Unexpected call.\n");
387 return E_NOTIMPL;
390 static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *stat, DWORD flags)
392 struct teststream *stream = impl_from_IStream(iface);
393 LARGE_INTEGER size;
395 if (winetest_debug > 1)
396 trace("%04x: IStream::Stat(flags %#x)\n", GetCurrentThreadId(), flags);
398 ok(flags == STATFLAG_NONAME, "Got flags %#x.\n", flags);
400 stat->type = 0xdeadbeef;
401 GetFileSizeEx(stream->file, &size);
402 stat->cbSize.QuadPart = size.QuadPart;
403 stat->grfMode = 0;
404 stat->grfLocksSupported = TRUE;
406 return S_OK;
409 static HRESULT WINAPI stream_Clone(IStream *iface, IStream **out)
411 ok(0, "Unexpected call.\n");
412 return E_NOTIMPL;
415 static const IStreamVtbl stream_vtbl =
417 stream_QueryInterface,
418 stream_AddRef,
419 stream_Release,
420 stream_Read,
421 stream_Write,
422 stream_Seek,
423 stream_SetSize,
424 stream_CopyTo,
425 stream_Commit,
426 stream_Revert,
427 stream_LockRegion,
428 stream_UnlockRegion,
429 stream_Stat,
430 stream_Clone,
433 static void teststream_init(struct teststream *stream, HANDLE file)
435 memset(stream, 0, sizeof(*stream));
436 stream->IStream_iface.lpVtbl = &stream_vtbl;
437 stream->refcount = 1;
438 stream->file = file;
441 static void test_reader_attributes(IWMProfile *profile)
443 WORD size, stream_number, ret_stream_number;
444 IWMHeaderInfo *header_info;
445 IWMStreamConfig *config;
446 WMT_ATTR_DATATYPE type;
447 ULONG count, i;
448 QWORD duration;
449 DWORD dword;
450 HRESULT hr;
452 IWMProfile_QueryInterface(profile, &IID_IWMHeaderInfo, (void **)&header_info);
454 hr = IWMProfile_GetStreamCount(profile, &count);
455 ok(hr == S_OK, "Got hr %#x.\n", hr);
456 ok(count == 2, "Got count %u.\n", count);
458 for (i = 0; i < count; ++i)
460 hr = IWMProfile_GetStream(profile, i, &config);
461 ok(hr == S_OK, "Got hr %#x.\n", hr);
462 hr = IWMStreamConfig_GetStreamNumber(config, &stream_number);
463 ok(hr == S_OK, "Got hr %#x.\n", hr);
464 ret_stream_number = stream_number;
466 size = sizeof(DWORD);
467 type = 0xdeadbeef;
468 dword = 0xdeadbeef;
469 hr = IWMHeaderInfo_GetAttributeByName(header_info, &ret_stream_number,
470 L"WM/VideoFrameRate", &type, (BYTE *)&dword, &size);
471 ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
472 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
473 ok(size == sizeof(DWORD), "Got size %u.\n", size);
474 ok(dword == 0xdeadbeef, "Got frame rate %u.\n", dword);
475 ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
476 stream_number, ret_stream_number);
478 size = sizeof(QWORD);
479 type = 0xdeadbeef;
480 duration = 0xdeadbeef;
481 hr = IWMHeaderInfo_GetAttributeByName(header_info, &ret_stream_number,
482 L"Duration", &type, (BYTE *)&duration, &size);
483 ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
484 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
485 ok(size == sizeof(QWORD), "Got size %u.\n", size);
486 ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
487 stream_number, ret_stream_number);
489 size = sizeof(DWORD);
490 type = 0xdeadbeef;
491 dword = 0xdeadbeef;
492 hr = IWMHeaderInfo_GetAttributeByName(header_info, &ret_stream_number,
493 L"Seekable", &type, (BYTE *)&dword, &size);
494 ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
495 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
496 ok(size == sizeof(DWORD), "Got size %u.\n", size);
497 ok(ret_stream_number == stream_number, "Expected stream number %u, got %u.\n",
498 stream_number, ret_stream_number);
500 IWMStreamConfig_Release(config);
503 /* WM/VideoFrameRate with a NULL stream number. */
505 size = sizeof(DWORD);
506 type = 0xdeadbeef;
507 dword = 0xdeadbeef;
508 hr = IWMHeaderInfo_GetAttributeByName(header_info, NULL,
509 L"WM/VideoFrameRate", &type, (BYTE *)&dword, &size);
510 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
511 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
512 ok(size == sizeof(DWORD), "Got size %u.\n", size);
513 ok(dword == 0xdeadbeef, "Got frame rate %u.\n", dword);
515 /* And with a zero stream number. */
517 stream_number = 0;
518 size = sizeof(DWORD);
519 type = 0xdeadbeef;
520 dword = 0xdeadbeef;
521 hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
522 L"WM/VideoFrameRate", &type, (BYTE *)&dword, &size);
523 ok(hr == ASF_E_NOTFOUND, "Got hr %#x.\n", hr);
524 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
525 ok(size == sizeof(DWORD), "Got size %u.\n", size);
526 ok(dword == 0xdeadbeef, "Got frame rate %u.\n", dword);
527 ok(stream_number == 0, "Got stream number %u.\n", stream_number);
529 /* Duration with a NULL stream number. */
531 size = sizeof(QWORD);
532 type = 0xdeadbeef;
533 duration = 0xdeadbeef;
534 hr = IWMHeaderInfo_GetAttributeByName(header_info, NULL,
535 L"Duration", &type, (BYTE *)&duration, &size);
536 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
537 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
538 ok(size == sizeof(QWORD), "Got size %u.\n", size);
539 ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
541 /* And with a zero stream number. */
543 size = sizeof(QWORD);
544 type = 0xdeadbeef;
545 duration = 0xdeadbeef;
546 hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
547 L"Duration", &type, (BYTE *)&duration, &size);
548 ok(hr == S_OK, "Got hr %#x.\n", hr);
549 ok(type == WMT_TYPE_QWORD, "Got type %#x.\n", type);
550 ok(size == sizeof(QWORD), "Got size %u.\n", size);
551 ok(duration == 20460000, "Got duration %I64u.\n", duration);
552 ok(stream_number == 0, "Got stream number %u.\n", stream_number);
554 /* Pass a too-small size. */
556 size = sizeof(QWORD) - 1;
557 type = 0xdeadbeef;
558 duration = 0xdeadbeef;
559 hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
560 L"Duration", &type, (BYTE *)&duration, &size);
561 ok(hr == ASF_E_BUFFERTOOSMALL, "Got hr %#x.\n", hr);
562 ok(type == 0xdeadbeef, "Got type %#x.\n", type);
563 ok(size == sizeof(QWORD), "Got size %u.\n", size);
564 ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
565 ok(stream_number == 0, "Got stream number %u.\n", stream_number);
567 /* Pass a NULL buffer. */
569 size = 0xdead;
570 type = 0xdeadbeef;
571 hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
572 L"Duration", &type, NULL, &size);
573 ok(hr == S_OK, "Got hr %#x.\n", hr);
574 ok(type == WMT_TYPE_QWORD, "Got type %#x.\n", type);
575 ok(size == sizeof(QWORD), "Got size %u.\n", size);
576 ok(stream_number == 0, "Got stream number %u.\n", stream_number);
578 size = sizeof(DWORD);
579 type = 0xdeadbeef;
580 dword = 0xdeadbeef;
581 hr = IWMHeaderInfo_GetAttributeByName(header_info, &stream_number,
582 L"Seekable", &type, (BYTE *)&dword, &size);
583 ok(hr == S_OK, "Got hr %#x.\n", hr);
584 ok(type == WMT_TYPE_BOOL, "Got type %#x.\n", type);
585 ok(size == sizeof(DWORD), "Got size %u.\n", size);
586 ok(dword == TRUE, "Got duration %I64u.\n", duration);
587 ok(stream_number == 0, "Got stream number %u.\n", stream_number);
589 IWMHeaderInfo_Release(header_info);
592 static void test_sync_reader_streaming(void)
594 DWORD size, flags, output_number, expect_output_number;
595 const WCHAR *filename = load_resource(L"test.wmv");
596 WORD stream_numbers[2], stream_number;
597 IWMStreamConfig *config, *config2;
598 bool eos[2] = {0}, first = true;
599 struct teststream stream;
600 ULONG i, j, count, ref;
601 IWMSyncReader *reader;
602 IWMProfile *profile;
603 QWORD pts, duration;
604 INSSBuffer *sample;
605 HANDLE file;
606 HRESULT hr;
607 BYTE *data;
608 BOOL ret;
610 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
611 ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u.\n", debugstr_w(file), GetLastError());
613 teststream_init(&stream, file);
615 hr = WMCreateSyncReader(NULL, 0, &reader);
616 ok(hr == S_OK, "Got hr %#x.\n", hr);
617 IWMSyncReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
619 hr = IWMSyncReader_OpenStream(reader, &stream.IStream_iface);
620 ok(hr == S_OK, "Got hr %#x.\n", hr);
621 ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
623 hr = IWMProfile_GetStreamCount(profile, NULL);
624 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
626 count = 0xdeadbeef;
627 hr = IWMProfile_GetStreamCount(profile, &count);
628 ok(hr == S_OK, "Got hr %#x.\n", hr);
629 ok(count == 2, "Got count %u.\n", count);
631 count = 0xdeadbeef;
632 hr = IWMSyncReader_GetOutputCount(reader, &count);
633 ok(hr == S_OK, "Got hr %#x.\n", hr);
634 ok(count == 2, "Got count %u.\n", count);
636 for (i = 0; i < 2; ++i)
638 hr = IWMProfile_GetStream(profile, i, &config);
639 ok(hr == S_OK, "Got hr %#x.\n", hr);
641 hr = IWMProfile_GetStream(profile, i, &config2);
642 ok(hr == S_OK, "Got hr %#x.\n", hr);
643 ok(config2 != config, "Expected different objects.\n");
644 ref = IWMStreamConfig_Release(config2);
645 ok(!ref, "Got outstanding refcount %d.\n", ref);
647 stream_numbers[i] = 0xdead;
648 hr = IWMStreamConfig_GetStreamNumber(config, &stream_numbers[i]);
649 ok(hr == S_OK, "Got hr %#x.\n", hr);
650 ok(stream_numbers[i] == i + 1, "Got stream number %u.\n", stream_numbers[i]);
652 ref = IWMStreamConfig_Release(config);
653 ok(!ref, "Got outstanding refcount %d.\n", ref);
655 hr = IWMSyncReader_SetReadStreamSamples(reader, stream_numbers[i], FALSE);
656 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
659 hr = IWMProfile_GetStream(profile, 2, &config);
660 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
662 while (!eos[0] || !eos[1])
664 for (j = 0; j < 2; ++j)
666 stream_number = pts = duration = flags = output_number = 0xdeadbeef;
667 hr = IWMSyncReader_GetNextSample(reader, stream_numbers[j], &sample,
668 &pts, &duration, &flags, &output_number, &stream_number);
669 if (first)
670 ok(hr == S_OK, "Expected at least one valid sample; got hr %#x.\n", hr);
671 else if (eos[j])
672 ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
673 else
674 ok(hr == S_OK || hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
676 if (hr == S_OK)
678 hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
679 ok(hr == S_OK, "Got hr %#x.\n", hr);
680 ref = INSSBuffer_Release(sample);
681 ok(!ref, "Got outstanding refcount %d.\n", ref);
683 hr = IWMSyncReader_GetOutputNumberForStream(reader, stream_number, &expect_output_number);
684 ok(hr == S_OK, "Got hr %#x.\n", hr);
685 ok(output_number == expect_output_number, "Expected output number %u, got %u.\n",
686 expect_output_number, output_number);
688 else
690 ok(pts == 0xdeadbeef, "Got PTS %I64u.\n", pts);
691 ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
692 ok(flags == 0xdeadbeef, "Got flags %#x.\n", flags);
693 ok(output_number == 0xdeadbeef, "Got output number %u.\n", output_number);
694 eos[j] = true;
697 ok(stream_number == stream_numbers[j], "Expected stream number %u, got %u.\n",
698 stream_numbers[j], stream_number);
700 first = false;
703 hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
704 &pts, &duration, &flags, NULL, NULL);
705 ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
707 hr = IWMSyncReader_GetNextSample(reader, stream_numbers[1], &sample,
708 &pts, &duration, &flags, NULL, NULL);
709 ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
711 hr = IWMSyncReader_SetRange(reader, 0, 0);
712 ok(hr == S_OK, "Got hr %#x.\n", hr);
714 hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample, &pts, &duration, &flags, NULL, NULL);
715 ok(hr == S_OK, "Got hr %#x.\n", hr);
716 INSSBuffer_Release(sample);
718 hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, NULL);
719 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
721 hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, &output_number, NULL);
722 ok(hr == S_OK, "Got hr %#x.\n", hr);
723 INSSBuffer_Release(sample);
725 hr = IWMSyncReader_GetNextSample(reader, 0, &sample, &pts, &duration, &flags, NULL, &stream_number);
726 ok(hr == S_OK, "Got hr %#x.\n", hr);
727 INSSBuffer_Release(sample);
729 for (;;)
731 stream_number = pts = duration = flags = output_number = 0xdeadbeef;
732 hr = IWMSyncReader_GetNextSample(reader, 0, &sample,
733 &pts, &duration, &flags, &output_number, &stream_number);
734 ok(hr == S_OK || hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
736 if (hr == S_OK)
738 hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
739 ok(hr == S_OK, "Got hr %#x.\n", hr);
740 ref = INSSBuffer_Release(sample);
741 ok(!ref, "Got outstanding refcount %d.\n", ref);
743 else
745 ok(pts == 0xdeadbeef, "Got PTS %I64u.\n", pts);
746 ok(duration == 0xdeadbeef, "Got duration %I64u.\n", duration);
747 ok(flags == 0xdeadbeef, "Got flags %#x.\n", flags);
748 ok(output_number == 0xdeadbeef, "Got output number %u.\n", output_number);
749 ok(stream_number == 0xbeef, "Got stream number %u.\n", stream_number);
750 break;
754 hr = IWMSyncReader_GetNextSample(reader, 0, &sample,
755 &pts, &duration, &flags, NULL, &stream_number);
756 ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
758 hr = IWMSyncReader_GetNextSample(reader, stream_numbers[0], &sample,
759 &pts, &duration, &flags, NULL, NULL);
760 ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
762 hr = IWMSyncReader_GetNextSample(reader, stream_numbers[1], &sample,
763 &pts, &duration, &flags, NULL, NULL);
764 ok(hr == NS_E_NO_MORE_SAMPLES, "Got hr %#x.\n", hr);
766 test_reader_attributes(profile);
768 hr = IWMSyncReader_Close(reader);
769 ok(hr == S_OK, "Got hr %#x.\n", hr);
771 hr = IWMSyncReader_Close(reader);
772 ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
774 ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
776 SetFilePointer(stream.file, 0, NULL, FILE_BEGIN);
777 hr = IWMSyncReader_OpenStream(reader, &stream.IStream_iface);
778 ok(hr == S_OK, "Got hr %#x.\n", hr);
779 ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
781 IWMProfile_Release(profile);
782 ref = IWMSyncReader_Release(reader);
783 ok(!ref, "Got outstanding refcount %d.\n", ref);
785 ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
786 CloseHandle(stream.file);
787 ret = DeleteFileW(filename);
788 ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
791 static void check_video_type(const WM_MEDIA_TYPE *mt)
793 const VIDEOINFOHEADER *video_info = (const VIDEOINFOHEADER *)mt->pbFormat;
794 static const RECT rect = {.right = 64, .bottom = 48};
796 ok(IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo), "Got format %s.\n", debugstr_guid(&mt->formattype));
797 ok(mt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", mt->bFixedSizeSamples);
798 ok(!mt->bTemporalCompression, "Got temporal compression %d.\n", mt->bTemporalCompression);
799 ok(!mt->pUnk, "Got pUnk %p.\n", mt->pUnk);
801 ok(EqualRect(&video_info->rcSource, &rect), "Got source rect %s.\n", wine_dbgstr_rect(&rect));
802 ok(EqualRect(&video_info->rcTarget, &rect), "Got target rect %s.\n", wine_dbgstr_rect(&rect));
803 ok(!video_info->dwBitRate, "Got bit rate %u.\n", video_info->dwBitRate);
804 ok(!video_info->dwBitErrorRate, "Got bit error rate %u.\n", video_info->dwBitErrorRate);
805 ok(video_info->bmiHeader.biSize == sizeof(video_info->bmiHeader),
806 "Got size %u.\n", video_info->bmiHeader.biSize);
807 ok(video_info->bmiHeader.biWidth == 64, "Got width %d.\n", video_info->bmiHeader.biWidth);
808 ok(video_info->bmiHeader.biHeight == 48, "Got height %d.\n", video_info->bmiHeader.biHeight);
809 ok(video_info->bmiHeader.biPlanes == 1, "Got planes %d.\n", video_info->bmiHeader.biPlanes);
812 static void check_audio_type(const WM_MEDIA_TYPE *mt)
814 const WAVEFORMATEX *wave_format = (const WAVEFORMATEX *)mt->pbFormat;
816 ok(IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_PCM), "Got subtype %s.\n", debugstr_guid(&mt->subtype));
817 ok(IsEqualGUID(&mt->formattype, &FORMAT_WaveFormatEx), "Got format %s.\n", debugstr_guid(&mt->formattype));
818 ok(mt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", mt->bFixedSizeSamples);
819 ok(!mt->bTemporalCompression, "Got temporal compression %d.\n", mt->bTemporalCompression);
820 ok(!mt->pUnk, "Got pUnk %p.\n", mt->pUnk);
822 ok(wave_format->wFormatTag == WAVE_FORMAT_PCM, "Got tag %#x.\n", wave_format->wFormatTag);
825 static void test_sync_reader_types(void)
827 char mt_buffer[2000], mt2_buffer[2000];
828 const WCHAR *filename = load_resource(L"test.wmv");
829 IWMOutputMediaProps *output_props, *output_props2;
830 WM_MEDIA_TYPE *mt2 = (WM_MEDIA_TYPE *)mt2_buffer;
831 WM_MEDIA_TYPE *mt = (WM_MEDIA_TYPE *)mt_buffer;
832 bool got_video = false, got_audio = false;
833 DWORD size, ret_size, output_number;
834 WORD stream_number, stream_number2;
835 struct teststream stream;
836 IWMStreamConfig *config;
837 ULONG count, ref, i, j;
838 IWMSyncReader *reader;
839 IWMProfile *profile;
840 GUID majortype;
841 HANDLE file;
842 HRESULT hr;
843 BOOL ret;
845 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
846 ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u.\n", debugstr_w(file), GetLastError());
848 teststream_init(&stream, file);
850 hr = WMCreateSyncReader(NULL, 0, &reader);
851 ok(hr == S_OK, "Got hr %#x.\n", hr);
852 IWMSyncReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
854 hr = IWMSyncReader_OpenStream(reader, &stream.IStream_iface);
855 ok(hr == S_OK, "Got hr %#x.\n", hr);
856 ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
858 for (i = 0; i < 2; ++i)
860 winetest_push_context("Stream %u", i);
862 hr = IWMProfile_GetStream(profile, i, &config);
863 ok(hr == S_OK, "Got hr %#x.\n", hr);
865 stream_number = 0xdead;
866 hr = IWMStreamConfig_GetStreamNumber(config, &stream_number);
867 ok(hr == S_OK, "Got hr %#x.\n", hr);
868 ok(stream_number == i + 1, "Got stream number %u.\n", stream_number);
870 hr = IWMStreamConfig_GetStreamType(config, &majortype);
871 ok(hr == S_OK, "Got hr %#x.\n", hr);
872 if (!i)
873 ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype));
874 else
875 ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
877 ref = IWMStreamConfig_Release(config);
878 ok(!ref, "Got outstanding refcount %d.\n", ref);
880 output_number = 0xdeadbeef;
881 hr = IWMSyncReader_GetOutputNumberForStream(reader, stream_number, &output_number);
882 ok(hr == S_OK, "Got hr %#x.\n", hr);
883 todo_wine ok(output_number == 1 - i, "Got output number %u.\n", output_number);
885 stream_number2 = 0xdead;
886 hr = IWMSyncReader_GetStreamNumberForOutput(reader, output_number, &stream_number2);
887 ok(hr == S_OK, "Got hr %#x.\n", hr);
888 ok(stream_number2 == stream_number, "Expected stream number %u, got %u.\n", stream_number, stream_number2);
890 hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props);
891 ok(hr == S_OK, "Got hr %#x.\n", hr);
893 ret_size = sizeof(mt_buffer);
894 hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size);
895 ok(hr == S_OK, "Got hr %#x.\n", hr);
897 ref = IWMOutputMediaProps_Release(output_props);
898 ok(!ref, "Got outstanding refcount %d.\n", ref);
900 if (IsEqualGUID(&majortype, &MEDIATYPE_Audio))
902 got_audio = true;
903 check_audio_type(mt);
905 else
907 ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype));
908 got_video = true;
909 check_video_type(mt);
912 count = 0;
913 hr = IWMSyncReader_GetOutputFormatCount(reader, output_number, &count);
914 ok(hr == S_OK, "Got hr %#x.\n", hr);
915 ok(count > 0, "Got count %u.\n", count);
917 for (j = 0; j < count; ++j)
919 winetest_push_context("Format %u", j);
921 hr = IWMSyncReader_GetOutputFormat(reader, output_number, j, &output_props);
922 ok(hr == S_OK, "Got hr %#x.\n", hr);
924 hr = IWMSyncReader_GetOutputFormat(reader, output_number, j, &output_props2);
925 ok(hr == S_OK, "Got hr %#x.\n", hr);
926 ok(output_props2 != output_props, "Expected different objects.\n");
927 ref = IWMOutputMediaProps_Release(output_props2);
928 ok(!ref, "Got outstanding refcount %d.\n", ref);
930 size = 0xdeadbeef;
931 hr = IWMOutputMediaProps_GetMediaType(output_props, NULL, &size);
932 ok(hr == S_OK, "Got hr %#x.\n", hr);
933 ok(size != 0xdeadbeef && size >= sizeof(WM_MEDIA_TYPE), "Got size %u.\n", size);
935 ret_size = size - 1;
936 hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size);
937 ok(hr == ASF_E_BUFFERTOOSMALL, "Got hr %#x.\n", hr);
938 ok(ret_size == size, "Expected size %u, got %u.\n", size, ret_size);
940 ret_size = sizeof(mt_buffer);
941 memset(mt_buffer, 0xcc, sizeof(mt_buffer));
942 hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size);
943 ok(hr == S_OK, "Got hr %#x.\n", hr);
944 ok(ret_size == size, "Expected size %u, got %u.\n", size, ret_size);
945 ok(size == sizeof(WM_MEDIA_TYPE) + mt->cbFormat, "Expected size %u, got %u.\n",
946 sizeof(WM_MEDIA_TYPE) + mt->cbFormat, size);
948 ok(IsEqualGUID(&mt->majortype, &majortype), "Got major type %s.\n", debugstr_guid(&mt->majortype));
950 if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Audio))
951 check_audio_type(mt);
952 else
953 check_video_type(mt);
955 hr = IWMSyncReader_SetOutputProps(reader, output_number, output_props);
956 ok(hr == S_OK, "Got hr %#x.\n", hr);
957 hr = IWMSyncReader_SetOutputProps(reader, 1 - output_number, output_props);
958 if (!i)
959 todo_wine ok(hr == ASF_E_BADMEDIATYPE, "Got hr %#x.\n", hr);
960 else
961 ok(hr == NS_E_INCOMPATIBLE_FORMAT
962 || hr == NS_E_INVALID_OUTPUT_FORMAT /* win10 */, "Got hr %#x.\n", hr);
963 hr = IWMSyncReader_SetOutputProps(reader, 2, output_props);
964 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
966 hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props2);
967 ok(hr == S_OK, "Got hr %#x.\n", hr);
968 ok(output_props2 != output_props, "Expected different objects.\n");
970 ret_size = sizeof(mt2_buffer);
971 hr = IWMOutputMediaProps_GetMediaType(output_props2, mt2, &ret_size);
972 ok(hr == S_OK, "Got hr %#x.\n", hr);
973 ok(compare_media_types(mt, mt2), "Media types didn't match.\n");
975 ref = IWMOutputMediaProps_Release(output_props2);
976 ok(!ref, "Got outstanding refcount %d.\n", ref);
977 ref = IWMOutputMediaProps_Release(output_props);
978 ok(!ref, "Got outstanding refcount %d.\n", ref);
980 winetest_pop_context();
983 hr = IWMSyncReader_GetOutputFormat(reader, output_number, count, &output_props);
984 ok(hr == NS_E_INVALID_OUTPUT_FORMAT, "Got hr %#x.\n", hr);
986 hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props);
987 ok(hr == S_OK, "Got hr %#x.\n", hr);
989 hr = IWMSyncReader_GetOutputProps(reader, output_number, &output_props2);
990 ok(hr == S_OK, "Got hr %#x.\n", hr);
991 ok(output_props2 != output_props, "Expected different objects.\n");
993 ref = IWMOutputMediaProps_Release(output_props2);
994 ok(!ref, "Got outstanding refcount %d.\n", ref);
995 ref = IWMOutputMediaProps_Release(output_props);
996 ok(!ref, "Got outstanding refcount %d.\n", ref);
998 winetest_pop_context();
1001 ok(got_audio, "No audio stream was enumerated.\n");
1002 ok(got_video, "No video stream was enumerated.\n");
1004 count = 0xdeadbeef;
1005 hr = IWMSyncReader_GetOutputFormatCount(reader, 2, &count);
1006 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1007 ok(count == 0xdeadbeef, "Got count %#x.\n", count);
1009 output_props = (void *)0xdeadbeef;
1010 hr = IWMSyncReader_GetOutputProps(reader, 2, &output_props);
1011 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1012 ok(output_props == (void *)0xdeadbeef, "Got output props %p.\n", output_props);
1014 output_props = (void *)0xdeadbeef;
1015 hr = IWMSyncReader_GetOutputFormat(reader, 2, 0, &output_props);
1016 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1017 ok(output_props == (void *)0xdeadbeef, "Got output props %p.\n", output_props);
1019 IWMProfile_Release(profile);
1020 ref = IWMSyncReader_Release(reader);
1021 ok(!ref, "Got outstanding refcount %d.\n", ref);
1023 ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
1024 CloseHandle(stream.file);
1025 ret = DeleteFileW(filename);
1026 ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
1029 static void test_sync_reader_file(void)
1031 const WCHAR *filename = load_resource(L"test.wmv");
1032 IWMSyncReader *reader;
1033 IWMProfile *profile;
1034 DWORD count;
1035 HRESULT hr;
1036 ULONG ref;
1037 BOOL ret;
1039 hr = WMCreateSyncReader(NULL, 0, &reader);
1040 ok(hr == S_OK, "Got hr %#x.\n", hr);
1041 IWMSyncReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
1043 hr = IWMSyncReader_Open(reader, filename);
1044 ok(hr == S_OK, "Got hr %#x.\n", hr);
1046 count = 0xdeadbeef;
1047 hr = IWMSyncReader_GetOutputCount(reader, &count);
1048 ok(hr == S_OK, "Got hr %#x.\n", hr);
1049 ok(count == 2, "Got count %u.\n", count);
1051 hr = IWMSyncReader_Close(reader);
1052 ok(hr == S_OK, "Got hr %#x.\n", hr);
1054 hr = IWMSyncReader_Close(reader);
1055 ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
1057 hr = IWMSyncReader_Open(reader, filename);
1058 ok(hr == S_OK, "Got hr %#x.\n", hr);
1060 IWMProfile_Release(profile);
1061 ref = IWMSyncReader_Release(reader);
1062 ok(!ref, "Got outstanding refcount %d.\n", ref);
1064 ret = DeleteFileW(filename);
1065 ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
1068 struct callback
1070 IWMReaderCallback IWMReaderCallback_iface;
1071 LONG refcount;
1072 HANDLE got_opened, got_stopped, eof_event;
1073 unsigned int got_closed, got_started, got_sample, got_end_of_streaming, got_eof;
1076 static struct callback *impl_from_IWMReaderCallback(IWMReaderCallback *iface)
1078 return CONTAINING_RECORD(iface, struct callback, IWMReaderCallback_iface);
1081 static HRESULT WINAPI callback_QueryInterface(IWMReaderCallback *iface, REFIID iid, void **out)
1083 if (winetest_debug > 1)
1084 trace("%04x: IWMReaderCallback::QueryInterface(%s)\n", GetCurrentThreadId(), debugstr_guid(iid));
1086 if (!IsEqualGUID(iid, &IID_IWMReaderCallbackAdvanced) && !IsEqualGUID(iid, &IID_IWMCredentialCallback))
1087 ok(0, "Unexpected IID %s.\n", debugstr_guid(iid));
1089 return E_NOINTERFACE;
1092 static ULONG WINAPI callback_AddRef(IWMReaderCallback *iface)
1094 struct callback *callback = impl_from_IWMReaderCallback(iface);
1096 return InterlockedIncrement(&callback->refcount);
1099 static ULONG WINAPI callback_Release(IWMReaderCallback *iface)
1101 struct callback *callback = impl_from_IWMReaderCallback(iface);
1103 return InterlockedDecrement(&callback->refcount);
1106 static HRESULT WINAPI callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS status,
1107 HRESULT hr, WMT_ATTR_DATATYPE type, BYTE *value, void *context)
1109 struct callback *callback = impl_from_IWMReaderCallback(iface);
1111 if (winetest_debug > 1)
1112 trace("%u: %04x: IWMReaderCallback::OnStatus(status %u, hr %#x, type %#x, value %p)\n",
1113 GetTickCount(), GetCurrentThreadId(), status, hr, type, value);
1115 switch (status)
1117 case WMT_OPENED:
1118 ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type);
1119 ok(!*(DWORD *)value, "Got value %#x.\n", *(DWORD *)value);
1120 ok(context == (void *)0xdeadbeef, "Got unexpected context %p.\n", context);
1121 SetEvent(callback->got_opened);
1122 break;
1124 case WMT_STARTED:
1125 ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type);
1126 ok(!*(DWORD *)value, "Got value %#x.\n", *(DWORD *)value);
1127 ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1128 ++callback->got_started;
1129 break;
1131 case WMT_STOPPED:
1132 ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type);
1133 ok(!*(DWORD *)value, "Got value %#x.\n", *(DWORD *)value);
1134 ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1135 SetEvent(callback->got_stopped);
1136 break;
1138 case WMT_CLOSED:
1139 ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type);
1140 ok(!*(DWORD *)value, "Got value %#x.\n", *(DWORD *)value);
1141 todo_wine ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1142 ++callback->got_closed;
1143 break;
1145 case WMT_END_OF_STREAMING:
1146 ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type);
1147 ok(!*(DWORD *)value, "Got value %#x.\n", *(DWORD *)value);
1148 ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1149 ok(!callback->got_eof, "Got %u WMT_EOF callbacks.\n", callback->got_eof);
1150 ++callback->got_end_of_streaming;
1151 break;
1153 case WMT_EOF:
1154 ok(type == WMT_TYPE_DWORD, "Got type %#x.\n", type);
1155 ok(!*(DWORD *)value, "Got value %#x.\n", *(DWORD *)value);
1156 ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1157 ok(callback->got_sample > 0, "Got no samples.\n");
1158 ok(callback->got_end_of_streaming == 1, "Got %u WMT_END_OF_STREAMING callbacks.\n",
1159 callback->got_end_of_streaming);
1160 ++callback->got_eof;
1161 SetEvent(callback->eof_event);
1162 break;
1164 /* Not sent when not using IWMReaderAdvanced::DeliverTime(). */
1165 case WMT_END_OF_SEGMENT:
1166 ok(type == WMT_TYPE_QWORD, "Got type %#x.\n", type);
1167 ok(*(QWORD *)value == 3000, "Got value %#x.\n", *(DWORD *)value);
1168 ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1169 ok(callback->got_sample > 0, "Got no samples.\n");
1170 ok(callback->got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback->got_eof);
1171 break;
1173 default:
1174 ok(0, "Unexpected status %#x.\n", status);
1177 ok(hr == S_OK, "Got hr %#x.\n", hr);
1178 return S_OK;
1181 static HRESULT WINAPI callback_OnSample(IWMReaderCallback *iface, DWORD output,
1182 QWORD time, QWORD duration, DWORD flags, INSSBuffer *sample, void *context)
1184 struct callback *callback = impl_from_IWMReaderCallback(iface);
1185 HRESULT hr;
1186 DWORD size;
1187 BYTE *data;
1189 if (winetest_debug > 1)
1190 trace("%u: %04x: IWMReaderCallback::OnSample(output %u, time %I64u, duration %I64u, flags %#x)\n",
1191 GetTickCount(), GetCurrentThreadId(), output, time, duration, flags);
1193 ok(context == (void *)0xfacade, "Got unexpected context %p.\n", context);
1195 hr = INSSBuffer_GetBufferAndLength(sample, &data, &size);
1196 ok(hr == S_OK, "Got hr %#x.\n", hr);
1198 ok(callback->got_started > 0, "Got %u WMT_STARTED callbacks.\n", callback->got_started);
1199 ok(!callback->got_eof, "Got %u WMT_EOF callbacks.\n", callback->got_eof);
1200 ++callback->got_sample;
1202 return S_OK;
1205 static const IWMReaderCallbackVtbl callback_vtbl =
1207 callback_QueryInterface,
1208 callback_AddRef,
1209 callback_Release,
1210 callback_OnStatus,
1211 callback_OnSample,
1214 static void callback_init(struct callback *callback)
1216 memset(callback, 0, sizeof(*callback));
1217 callback->IWMReaderCallback_iface.lpVtbl = &callback_vtbl;
1218 callback->refcount = 1;
1219 callback->got_opened = CreateEventW(NULL, FALSE, FALSE, NULL);
1220 callback->got_stopped = CreateEventW(NULL, FALSE, FALSE, NULL);
1221 callback->eof_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1224 static void callback_cleanup(struct callback *callback)
1226 CloseHandle(callback->got_opened);
1227 CloseHandle(callback->got_stopped);
1228 CloseHandle(callback->eof_event);
1231 static void test_async_reader_streaming(void)
1233 const WCHAR *filename = load_resource(L"test.wmv");
1234 IWMReaderAdvanced2 *advanced;
1235 struct teststream stream;
1236 struct callback callback;
1237 IWMStreamConfig *config;
1238 WORD stream_numbers[2];
1239 IWMProfile *profile;
1240 ULONG i, count, ref;
1241 IWMReader *reader;
1242 HANDLE file;
1243 HRESULT hr;
1244 BOOL ret;
1246 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
1247 ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u.\n", debugstr_w(file), GetLastError());
1249 teststream_init(&stream, file);
1250 callback_init(&callback);
1252 hr = WMCreateReader(NULL, 0, &reader);
1253 ok(hr == S_OK, "Got hr %#x.\n", hr);
1254 IWMReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
1255 IWMReader_QueryInterface(reader, &IID_IWMReaderAdvanced2, (void **)&advanced);
1257 hr = IWMReaderAdvanced2_OpenStream(advanced, &stream.IStream_iface, &callback.IWMReaderCallback_iface, (void **)0xdeadbeef);
1258 ok(hr == S_OK, "Got hr %#x.\n", hr);
1259 ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
1260 ok(callback.refcount > 1, "Got refcount %d.\n", callback.refcount);
1261 ret = WaitForSingleObject(callback.got_opened, 1000);
1262 ok(!ret, "Wait timed out.\n");
1264 count = 0xdeadbeef;
1265 hr = IWMReader_GetOutputCount(reader, &count);
1266 ok(hr == S_OK, "Got hr %#x.\n", hr);
1267 ok(count == 2, "Got count %u.\n", count);
1269 for (i = 0; i < 2; ++i)
1271 hr = IWMProfile_GetStream(profile, i, &config);
1272 ok(hr == S_OK, "Got hr %#x.\n", hr);
1274 stream_numbers[i] = 0xdead;
1275 hr = IWMStreamConfig_GetStreamNumber(config, &stream_numbers[i]);
1276 ok(hr == S_OK, "Got hr %#x.\n", hr);
1277 ok(stream_numbers[i] == i + 1, "Got stream number %u.\n", stream_numbers[i]);
1279 ref = IWMStreamConfig_Release(config);
1280 ok(!ref, "Got outstanding refcount %d.\n", ref);
1283 hr = IWMReader_Start(reader, 0, 0, 1.0f, (void *)0xfacade);
1284 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1286 if (hr == S_OK)
1288 /* By default the reader will time itself, and attempt to deliver samples
1289 * according to their presentation time. Call DeliverTime with the file
1290 * duration in order to request all samples as fast as possible. */
1291 hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
1292 ok(hr == E_UNEXPECTED, "Got hr %#x.\n", hr);
1293 hr = IWMReaderAdvanced2_SetUserProvidedClock(advanced, TRUE);
1294 ok(hr == S_OK, "Got hr %#x.\n", hr);
1295 hr = IWMReaderAdvanced2_DeliverTime(advanced, 3000 * 10000);
1296 ok(hr == S_OK, "Got hr %#x.\n", hr);
1298 ret = WaitForSingleObject(callback.eof_event, 1000);
1299 ok(!ret, "Wait timed out.\n");
1300 ok(callback.got_eof == 1, "Got %u WMT_EOF callbacks.\n", callback.got_eof);
1302 hr = IWMReader_Stop(reader);
1303 ok(hr == S_OK, "Got hr %#x.\n", hr);
1304 ret = WaitForSingleObject(callback.got_stopped, 1000);
1305 ok(!ret, "Wait timed out.\n");
1307 hr = IWMReader_Stop(reader);
1308 ok(hr == S_OK, "Got hr %#x.\n", hr);
1309 ret = WaitForSingleObject(callback.got_stopped, 1000);
1310 ok(!ret, "Wait timed out.\n");
1313 test_reader_attributes(profile);
1315 hr = IWMReader_Close(reader);
1316 ok(hr == S_OK, "Got hr %#x.\n", hr);
1317 ok(callback.got_closed == 1, "Got %u WMT_CLOSED callbacks.\n", callback.got_closed);
1318 ok(callback.refcount == 1, "Got outstanding refcount %d.\n", callback.refcount);
1319 callback_cleanup(&callback);
1321 ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
1322 CloseHandle(stream.file);
1323 ret = DeleteFileW(filename);
1324 ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
1326 hr = IWMReader_Close(reader);
1327 ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
1329 IWMReaderAdvanced2_Release(advanced);
1330 IWMProfile_Release(profile);
1331 ref = IWMReader_Release(reader);
1332 ok(!ref, "Got outstanding refcount %d.\n", ref);
1335 static void test_async_reader_types(void)
1337 char mt_buffer[2000], mt2_buffer[2000];
1338 const WCHAR *filename = load_resource(L"test.wmv");
1339 IWMOutputMediaProps *output_props, *output_props2;
1340 WM_MEDIA_TYPE *mt2 = (WM_MEDIA_TYPE *)mt2_buffer;
1341 WM_MEDIA_TYPE *mt = (WM_MEDIA_TYPE *)mt_buffer;
1342 bool got_video = false, got_audio = false;
1343 DWORD size, ret_size, output_number;
1344 IWMReaderAdvanced2 *advanced;
1345 struct teststream stream;
1346 struct callback callback;
1347 IWMStreamConfig *config;
1348 ULONG count, ref, i, j;
1349 IWMProfile *profile;
1350 IWMReader *reader;
1351 GUID majortype;
1352 HANDLE file;
1353 HRESULT hr;
1354 BOOL ret;
1356 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
1357 ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u.\n", debugstr_w(file), GetLastError());
1359 teststream_init(&stream, file);
1360 callback_init(&callback);
1362 hr = WMCreateReader(NULL, 0, &reader);
1363 ok(hr == S_OK, "Got hr %#x.\n", hr);
1364 IWMReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
1365 IWMReader_QueryInterface(reader, &IID_IWMReaderAdvanced2, (void **)&advanced);
1367 hr = IWMReaderAdvanced2_OpenStream(advanced, &stream.IStream_iface, &callback.IWMReaderCallback_iface, (void **)0xdeadbeef);
1368 ok(hr == S_OK, "Got hr %#x.\n", hr);
1369 ok(stream.refcount > 1, "Got refcount %d.\n", stream.refcount);
1370 ok(callback.refcount > 1, "Got refcount %d.\n", callback.refcount);
1371 ret = WaitForSingleObject(callback.got_opened, 1000);
1372 ok(!ret, "Wait timed out.\n");
1374 for (i = 0; i < 2; ++i)
1376 winetest_push_context("Stream %u", i);
1378 hr = IWMProfile_GetStream(profile, i, &config);
1379 ok(hr == S_OK, "Got hr %#x.\n", hr);
1381 hr = IWMStreamConfig_GetStreamType(config, &majortype);
1382 ok(hr == S_OK, "Got hr %#x.\n", hr);
1383 if (!i)
1384 ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype));
1385 else
1386 ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
1388 ref = IWMStreamConfig_Release(config);
1389 ok(!ref, "Got outstanding refcount %d.\n", ref);
1391 winetest_pop_context();
1394 for (i = 0; i < 2; ++i)
1396 winetest_push_context("Output %u", i);
1397 output_number = i;
1399 hr = IWMReader_GetOutputProps(reader, output_number, &output_props);
1400 ok(hr == S_OK, "Got hr %#x.\n", hr);
1402 ret_size = sizeof(mt_buffer);
1403 hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size);
1404 ok(hr == S_OK, "Got hr %#x.\n", hr);
1406 ref = IWMOutputMediaProps_Release(output_props);
1407 ok(!ref, "Got outstanding refcount %d.\n", ref);
1409 majortype = mt->majortype;
1410 if (IsEqualGUID(&majortype, &MEDIATYPE_Audio))
1412 got_audio = true;
1413 check_audio_type(mt);
1415 /* R.U.S.E. enumerates all audio formats, picks the first one it
1416 * likes, and then sets the wrong stream to that format.
1417 * Accordingly we need the first audio format to be the default
1418 * format, and we need it to be a format that the game is happy
1419 * with. In particular it has to be PCM. */
1421 hr = IWMReader_GetOutputFormat(reader, output_number, 0, &output_props);
1422 ok(hr == S_OK, "Got hr %#x.\n", hr);
1424 ret_size = sizeof(mt2_buffer);
1425 hr = IWMOutputMediaProps_GetMediaType(output_props, mt2, &ret_size);
1426 ok(hr == S_OK, "Got hr %#x.\n", hr);
1428 ref = IWMOutputMediaProps_Release(output_props);
1429 ok(!ref, "Got outstanding refcount %d.\n", ref);
1431 /* The sample size might differ. */
1432 mt2->lSampleSize = mt->lSampleSize;
1433 ok(compare_media_types(mt, mt2), "Media types didn't match.\n");
1435 else
1437 ok(IsEqualGUID(&majortype, &MEDIATYPE_Video), "Got major type %s.\n", debugstr_guid(&majortype));
1438 got_video = true;
1439 check_video_type(mt);
1442 count = 0;
1443 hr = IWMReader_GetOutputFormatCount(reader, output_number, &count);
1444 ok(hr == S_OK, "Got hr %#x.\n", hr);
1445 ok(count > 0, "Got count %u.\n", count);
1447 for (j = 0; j < count; ++j)
1449 winetest_push_context("Format %u", j);
1451 hr = IWMReader_GetOutputFormat(reader, output_number, j, &output_props);
1452 ok(hr == S_OK, "Got hr %#x.\n", hr);
1454 hr = IWMReader_GetOutputFormat(reader, output_number, j, &output_props2);
1455 ok(hr == S_OK, "Got hr %#x.\n", hr);
1456 ok(output_props2 != output_props, "Expected different objects.\n");
1457 ref = IWMOutputMediaProps_Release(output_props2);
1458 ok(!ref, "Got outstanding refcount %d.\n", ref);
1460 size = 0xdeadbeef;
1461 hr = IWMOutputMediaProps_GetMediaType(output_props, NULL, &size);
1462 ok(hr == S_OK, "Got hr %#x.\n", hr);
1463 ok(size != 0xdeadbeef && size >= sizeof(WM_MEDIA_TYPE), "Got size %u.\n", size);
1465 ret_size = size - 1;
1466 hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size);
1467 ok(hr == ASF_E_BUFFERTOOSMALL, "Got hr %#x.\n", hr);
1468 ok(ret_size == size, "Expected size %u, got %u.\n", size, ret_size);
1470 ret_size = sizeof(mt_buffer);
1471 memset(mt_buffer, 0xcc, sizeof(mt_buffer));
1472 hr = IWMOutputMediaProps_GetMediaType(output_props, mt, &ret_size);
1473 ok(hr == S_OK, "Got hr %#x.\n", hr);
1474 ok(ret_size == size, "Expected size %u, got %u.\n", size, ret_size);
1475 ok(size == sizeof(WM_MEDIA_TYPE) + mt->cbFormat, "Expected size %u, got %u.\n",
1476 sizeof(WM_MEDIA_TYPE) + mt->cbFormat, size);
1478 ok(IsEqualGUID(&mt->majortype, &majortype), "Got major type %s.\n", debugstr_guid(&mt->majortype));
1480 if (IsEqualGUID(&mt->majortype, &MEDIATYPE_Audio))
1481 check_audio_type(mt);
1482 else
1483 check_video_type(mt);
1485 hr = IWMReader_SetOutputProps(reader, output_number, output_props);
1486 ok(hr == S_OK, "Got hr %#x.\n", hr);
1487 hr = IWMReader_SetOutputProps(reader, 1 - output_number, output_props);
1488 if (!i)
1489 ok(hr == NS_E_INCOMPATIBLE_FORMAT /* win < 8, win10 1507-1809 */
1490 || hr == ASF_E_BADMEDIATYPE /* win8, win10 1909+ */, "Got hr %#x.\n", hr);
1491 else
1492 todo_wine ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
1493 hr = IWMReader_SetOutputProps(reader, 2, output_props);
1494 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1496 hr = IWMReader_GetOutputProps(reader, output_number, &output_props2);
1497 ok(hr == S_OK, "Got hr %#x.\n", hr);
1498 ok(output_props2 != output_props, "Expected different objects.\n");
1500 ret_size = sizeof(mt2_buffer);
1501 hr = IWMOutputMediaProps_GetMediaType(output_props2, mt2, &ret_size);
1502 ok(hr == S_OK, "Got hr %#x.\n", hr);
1503 ok(compare_media_types(mt, mt2), "Media types didn't match.\n");
1505 ref = IWMOutputMediaProps_Release(output_props2);
1506 ok(!ref, "Got outstanding refcount %d.\n", ref);
1507 ref = IWMOutputMediaProps_Release(output_props);
1508 ok(!ref, "Got outstanding refcount %d.\n", ref);
1510 winetest_pop_context();
1513 hr = IWMReader_GetOutputFormat(reader, output_number, count, &output_props);
1514 ok(hr == NS_E_INVALID_OUTPUT_FORMAT, "Got hr %#x.\n", hr);
1516 hr = IWMReader_GetOutputProps(reader, output_number, &output_props);
1517 ok(hr == S_OK, "Got hr %#x.\n", hr);
1519 hr = IWMReader_GetOutputProps(reader, output_number, &output_props2);
1520 ok(hr == S_OK, "Got hr %#x.\n", hr);
1521 ok(output_props2 != output_props, "Expected different objects.\n");
1523 ref = IWMOutputMediaProps_Release(output_props2);
1524 ok(!ref, "Got outstanding refcount %d.\n", ref);
1525 ref = IWMOutputMediaProps_Release(output_props);
1526 ok(!ref, "Got outstanding refcount %d.\n", ref);
1528 winetest_pop_context();
1531 ok(got_audio, "No audio stream was enumerated.\n");
1532 ok(got_video, "No video stream was enumerated.\n");
1534 count = 0xdeadbeef;
1535 hr = IWMReader_GetOutputFormatCount(reader, 2, &count);
1536 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1537 ok(count == 0xdeadbeef, "Got count %#x.\n", count);
1539 output_props = (void *)0xdeadbeef;
1540 hr = IWMReader_GetOutputProps(reader, 2, &output_props);
1541 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1542 ok(output_props == (void *)0xdeadbeef, "Got output props %p.\n", output_props);
1544 output_props = (void *)0xdeadbeef;
1545 hr = IWMReader_GetOutputFormat(reader, 2, 0, &output_props);
1546 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1547 ok(output_props == (void *)0xdeadbeef, "Got output props %p.\n", output_props);
1549 IWMReaderAdvanced2_Release(advanced);
1550 IWMProfile_Release(profile);
1551 ref = IWMReader_Release(reader);
1552 ok(!ref, "Got outstanding refcount %d.\n", ref);
1554 ok(stream.refcount == 1, "Got outstanding refcount %d.\n", stream.refcount);
1555 CloseHandle(stream.file);
1556 ret = DeleteFileW(filename);
1557 ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
1560 START_TEST(wmvcore)
1562 HRESULT hr;
1564 hr = CoInitialize(0);
1565 ok(hr == S_OK, "failed to init com\n");
1566 if(hr != S_OK)
1567 return;
1569 test_wmreader_interfaces();
1570 test_wmsyncreader_interfaces();
1571 test_wmwriter_interfaces();
1572 test_profile_manager_interfaces();
1573 test_WMCreateWriterPriv();
1574 test_urlextension();
1575 test_iscontentprotected();
1576 test_sync_reader_streaming();
1577 test_sync_reader_types();
1578 test_sync_reader_file();
1579 test_async_reader_streaming();
1580 test_async_reader_types();
1582 CoUninitialize();