2 * File writer filter unit tests
4 * Copyright (C) 2020 Zebediah Figura
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
23 #include "wine/test.h"
25 static IBaseFilter
*create_file_writer(void)
27 IBaseFilter
*filter
= NULL
;
28 HRESULT hr
= CoCreateInstance(&CLSID_FileWriter
, NULL
,
29 CLSCTX_INPROC_SERVER
, &IID_IBaseFilter
, (void **)&filter
);
30 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
34 static ULONG
get_refcount(void *iface
)
36 IUnknown
*unknown
= iface
;
37 IUnknown_AddRef(unknown
);
38 return IUnknown_Release(unknown
);
41 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
42 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
44 IUnknown
*iface
= iface_ptr
;
45 HRESULT hr
, expected_hr
;
48 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
50 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
51 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
53 IUnknown_Release(unk
);
56 static void test_interfaces(void)
58 IBaseFilter
*filter
= create_file_writer();
62 todo_wine
check_interface(filter
, &IID_IAMFilterMiscFlags
, TRUE
);
63 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
64 todo_wine
check_interface(filter
, &IID_IFileSinkFilter
, TRUE
);
65 todo_wine
check_interface(filter
, &IID_IFileSinkFilter2
, TRUE
);
66 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
67 check_interface(filter
, &IID_IPersist
, TRUE
);
68 todo_wine
check_interface(filter
, &IID_IPersistStream
, TRUE
);
69 check_interface(filter
, &IID_IUnknown
, TRUE
);
71 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
72 check_interface(filter
, &IID_IBasicVideo
, FALSE
);
73 check_interface(filter
, &IID_IKsPropertySet
, FALSE
);
74 check_interface(filter
, &IID_IMediaPosition
, FALSE
);
75 check_interface(filter
, &IID_IMediaSeeking
, FALSE
);
76 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
77 check_interface(filter
, &IID_IPin
, FALSE
);
78 check_interface(filter
, &IID_IQualityControl
, FALSE
);
79 check_interface(filter
, &IID_IQualProp
, FALSE
);
80 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
81 check_interface(filter
, &IID_IVideoWindow
, FALSE
);
83 IBaseFilter_FindPin(filter
, L
"in", &pin
);
85 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
86 check_interface(pin
, &IID_IPin
, TRUE
);
87 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
88 check_interface(pin
, &IID_IUnknown
, TRUE
);
90 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
91 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
92 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
95 ref
= IBaseFilter_Release(filter
);
96 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
99 static const GUID test_iid
= {0x33333333};
100 static LONG outer_ref
= 1;
102 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
104 if (IsEqualGUID(iid
, &IID_IUnknown
)
105 || IsEqualGUID(iid
, &IID_IBaseFilter
)
106 || IsEqualGUID(iid
, &test_iid
))
108 *out
= (IUnknown
*)0xdeadbeef;
111 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
112 return E_NOINTERFACE
;
115 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
117 return InterlockedIncrement(&outer_ref
);
120 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
122 return InterlockedDecrement(&outer_ref
);
125 static const IUnknownVtbl outer_vtbl
=
127 outer_QueryInterface
,
132 static IUnknown test_outer
= {&outer_vtbl
};
134 static void test_aggregation(void)
136 IBaseFilter
*filter
, *filter2
;
137 IUnknown
*unk
, *unk2
;
141 filter
= (IBaseFilter
*)0xdeadbeef;
142 hr
= CoCreateInstance(&CLSID_FileWriter
, &test_outer
, CLSCTX_INPROC_SERVER
,
143 &IID_IBaseFilter
, (void **)&filter
);
144 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
145 ok(!filter
, "Got interface %p.\n", filter
);
147 hr
= CoCreateInstance(&CLSID_FileWriter
, &test_outer
, CLSCTX_INPROC_SERVER
,
148 &IID_IUnknown
, (void **)&unk
);
149 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
150 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
151 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
152 ref
= get_refcount(unk
);
153 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
155 ref
= IUnknown_AddRef(unk
);
156 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
157 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
159 ref
= IUnknown_Release(unk
);
160 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
161 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
163 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
164 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
165 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
166 IUnknown_Release(unk2
);
168 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
169 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
171 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
172 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
173 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
175 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
176 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
177 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
179 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
180 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
181 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
183 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
184 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
185 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
187 IBaseFilter_Release(filter
);
188 ref
= IUnknown_Release(unk
);
189 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
190 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
193 static void test_enum_pins(void)
195 IBaseFilter
*filter
= create_file_writer();
196 IEnumPins
*enum1
, *enum2
;
201 ref
= get_refcount(filter
);
202 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
204 hr
= IBaseFilter_EnumPins(filter
, NULL
);
205 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
207 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
208 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
209 ref
= get_refcount(filter
);
210 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
211 ref
= get_refcount(enum1
);
212 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
214 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
215 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
217 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
218 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
219 ref
= get_refcount(filter
);
220 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
221 ref
= get_refcount(pins
[0]);
222 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
223 ref
= get_refcount(enum1
);
224 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
225 IPin_Release(pins
[0]);
226 ref
= get_refcount(filter
);
227 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
229 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
230 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
232 hr
= IEnumPins_Reset(enum1
);
233 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
235 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
236 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
237 ok(count
== 1, "Got count %u.\n", count
);
238 IPin_Release(pins
[0]);
240 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
241 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
242 ok(!count
, "Got count %u.\n", count
);
244 hr
= IEnumPins_Reset(enum1
);
245 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
247 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
248 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
250 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
251 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
252 ok(count
== 1, "Got count %u.\n", count
);
253 IPin_Release(pins
[0]);
255 hr
= IEnumPins_Reset(enum1
);
256 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
258 hr
= IEnumPins_Clone(enum1
, &enum2
);
259 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
261 hr
= IEnumPins_Skip(enum1
, 2);
262 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
264 hr
= IEnumPins_Skip(enum1
, 1);
265 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
267 hr
= IEnumPins_Skip(enum1
, 1);
268 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
270 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
271 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
273 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
274 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
275 IPin_Release(pins
[0]);
277 IEnumPins_Release(enum2
);
278 IEnumPins_Release(enum1
);
279 ref
= IBaseFilter_Release(filter
);
280 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
283 static void test_find_pin(void)
285 IBaseFilter
*filter
= create_file_writer();
286 IEnumPins
*enum_pins
;
291 hr
= IBaseFilter_EnumPins(filter
, &enum_pins
);
292 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
294 hr
= IBaseFilter_FindPin(filter
, L
"in", &pin
);
295 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
296 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
297 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
298 ok(pin2
== pin
, "Expected pin %p, got %p.\n", pin
, pin2
);
302 IEnumPins_Release(enum_pins
);
303 ref
= IBaseFilter_Release(filter
);
304 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
307 static void test_pin_info(void)
309 IBaseFilter
*filter
= create_file_writer();
317 hr
= IBaseFilter_FindPin(filter
, L
"in", &pin
);
318 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
319 ref
= get_refcount(filter
);
320 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
321 ref
= get_refcount(pin
);
322 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
324 hr
= IPin_QueryPinInfo(pin
, &info
);
325 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
326 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
327 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
328 ok(!wcscmp(info
.achName
, L
"in"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
329 ref
= get_refcount(filter
);
330 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
331 ref
= get_refcount(pin
);
332 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
333 IBaseFilter_Release(info
.pFilter
);
335 hr
= IPin_QueryDirection(pin
, &dir
);
336 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
337 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
339 hr
= IPin_QueryId(pin
, &id
);
340 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
341 ok(!wcscmp(id
, L
"in"), "Got id %s.\n", wine_dbgstr_w(id
));
344 hr
= IPin_QueryInternalConnections(pin
, NULL
, NULL
);
345 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
348 ref
= IBaseFilter_Release(filter
);
349 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
352 START_TEST(filewriter
)
354 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);