[QUARTZ_WINETEST] Sync with Wine Staging 3.9. CORE-14656
[reactos.git] / modules / rostests / winetests / quartz / filtermapper.c
1 /*
2 * Filtermapper unit tests for Quartz
3 *
4 * Copyright (C) 2008 Alexander Dorofeyev
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define COBJMACROS
22
23 #include "wine/test.h"
24 #include "winbase.h"
25 #include "initguid.h"
26 #include "dshow.h"
27 #include "wine/winternl.h"
28
29 #include "fil_data.h"
30
31 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
32
33 /* Helper function, checks if filter with given name was enumerated. */
34 static BOOL enum_find_filter(const WCHAR *wszFilterName, IEnumMoniker *pEnum)
35 {
36 IMoniker *pMoniker = NULL;
37 BOOL found = FALSE;
38 ULONG nb;
39 HRESULT hr;
40 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
41
42 while(!found && IEnumMoniker_Next(pEnum, 1, &pMoniker, &nb) == S_OK)
43 {
44 IPropertyBag * pPropBagCat = NULL;
45 VARIANT var;
46
47 VariantInit(&var);
48
49 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
50 ok(SUCCEEDED(hr), "IMoniker_BindToStorage failed with %x\n", hr);
51
52 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, &var, NULL);
53 ok(SUCCEEDED(hr), "IPropertyBag_Read failed with %x\n", hr);
54
55 if (!lstrcmpW(V_BSTR(&var), wszFilterName))
56 found = TRUE;
57
58 IPropertyBag_Release(pPropBagCat);
59 IMoniker_Release(pMoniker);
60 VariantClear(&var);
61 }
62
63 return found;
64 }
65
66 static void test_fm2_enummatchingfilters(void)
67 {
68 IEnumRegFilters *enum_reg;
69 IFilterMapper2 *pMapper = NULL;
70 IFilterMapper *mapper;
71 HRESULT hr;
72 REGFILTER2 rgf2;
73 REGFILTERPINS2 rgPins2[2];
74 REGPINTYPES rgPinType;
75 static const WCHAR wszFilterName1[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', '1', 0 };
76 static const WCHAR wszFilterName2[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', '2', 0 };
77 CLSID clsidFilter1;
78 CLSID clsidFilter2;
79 IEnumMoniker *pEnum = NULL;
80 BOOL found, registered = TRUE;
81 REGFILTER *regfilter;
82 ULONG count;
83
84 ZeroMemory(&rgf2, sizeof(rgf2));
85
86 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
87 &IID_IFilterMapper2, (LPVOID*)&pMapper);
88 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
89 if (FAILED(hr)) goto out;
90
91 hr = CoCreateGuid(&clsidFilter1);
92 ok(hr == S_OK, "CoCreateGuid failed with %x\n", hr);
93 hr = CoCreateGuid(&clsidFilter2);
94 ok(hr == S_OK, "CoCreateGuid failed with %x\n", hr);
95
96 /* Test that a test renderer filter is returned when enumerating filters with bRender=FALSE */
97 rgf2.dwVersion = 2;
98 rgf2.dwMerit = MERIT_UNLIKELY;
99 S2(U(rgf2)).cPins2 = 1;
100 S2(U(rgf2)).rgPins2 = rgPins2;
101
102 rgPins2[0].dwFlags = REG_PINFLAG_B_RENDERER;
103 rgPins2[0].cInstances = 1;
104 rgPins2[0].nMediaTypes = 1;
105 rgPins2[0].lpMediaType = &rgPinType;
106 rgPins2[0].nMediums = 0;
107 rgPins2[0].lpMedium = NULL;
108 rgPins2[0].clsPinCategory = NULL;
109
110 rgPinType.clsMajorType = &GUID_NULL;
111 rgPinType.clsMinorType = &GUID_NULL;
112
113 hr = IFilterMapper2_RegisterFilter(pMapper, &clsidFilter1, wszFilterName1, NULL,
114 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
115 if (hr == E_ACCESSDENIED)
116 {
117 registered = FALSE;
118 skip("Not authorized to register filters\n");
119 }
120 else
121 {
122 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
123
124 rgPins2[0].dwFlags = 0;
125
126 rgPins2[1].dwFlags = REG_PINFLAG_B_OUTPUT;
127 rgPins2[1].cInstances = 1;
128 rgPins2[1].nMediaTypes = 1;
129 rgPins2[1].lpMediaType = &rgPinType;
130 rgPins2[1].nMediums = 0;
131 rgPins2[1].lpMedium = NULL;
132 rgPins2[1].clsPinCategory = NULL;
133
134 S2(U(rgf2)).cPins2 = 2;
135
136 hr = IFilterMapper2_RegisterFilter(pMapper, &clsidFilter2, wszFilterName2, NULL,
137 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
138 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
139
140 hr = IFilterMapper2_EnumMatchingFilters(pMapper, &pEnum, 0, TRUE, MERIT_UNLIKELY, TRUE,
141 0, NULL, NULL, &GUID_NULL, FALSE, FALSE, 0, NULL, NULL, &GUID_NULL);
142 ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed with %x\n", hr);
143 if (SUCCEEDED(hr) && pEnum)
144 {
145 found = enum_find_filter(wszFilterName1, pEnum);
146 ok(found, "EnumMatchingFilters failed to return the test filter 1\n");
147 }
148
149 if (pEnum) IEnumMoniker_Release(pEnum);
150 pEnum = NULL;
151
152 hr = IFilterMapper2_EnumMatchingFilters(pMapper, &pEnum, 0, TRUE, MERIT_UNLIKELY, TRUE,
153 0, NULL, NULL, &GUID_NULL, FALSE, FALSE, 0, NULL, NULL, &GUID_NULL);
154 ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed with %x\n", hr);
155 if (SUCCEEDED(hr) && pEnum)
156 {
157 found = enum_find_filter(wszFilterName2, pEnum);
158 ok(found, "EnumMatchingFilters failed to return the test filter 2\n");
159 }
160
161 if (pEnum) IEnumMoniker_Release(pEnum);
162 pEnum = NULL;
163
164 /* Non renderer must not be returned with bRender=TRUE */
165
166 hr = IFilterMapper2_EnumMatchingFilters(pMapper, &pEnum, 0, TRUE, MERIT_UNLIKELY, TRUE,
167 0, NULL, NULL, &GUID_NULL, TRUE, FALSE, 0, NULL, NULL, &GUID_NULL);
168 ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed with %x\n", hr);
169
170 if (SUCCEEDED(hr) && pEnum)
171 {
172 found = enum_find_filter(wszFilterName1, pEnum);
173 ok(found, "EnumMatchingFilters failed to return the test filter 1\n");
174 }
175
176 hr = IFilterMapper2_QueryInterface(pMapper, &IID_IFilterMapper, (void **)&mapper);
177 ok(hr == S_OK, "QueryInterface(IFilterMapper) failed: %#x\n", hr);
178
179 found = FALSE;
180 hr = IFilterMapper_EnumMatchingFilters(mapper, &enum_reg, MERIT_UNLIKELY,
181 FALSE, GUID_NULL, GUID_NULL, FALSE, FALSE, GUID_NULL, GUID_NULL);
182 ok(hr == S_OK, "IFilterMapper_EnumMatchingFilters failed: %#x\n", hr);
183 while (!found && IEnumRegFilters_Next(enum_reg, 1, &regfilter, &count) == S_OK)
184 {
185 if (!lstrcmpW(regfilter->Name, wszFilterName1) && IsEqualGUID(&clsidFilter1, &regfilter->Clsid))
186 found = TRUE;
187 }
188 IEnumRegFilters_Release(enum_reg);
189 ok(found, "IFilterMapper didn't find filter\n");
190 }
191
192 if (pEnum) IEnumMoniker_Release(pEnum);
193 pEnum = NULL;
194
195 hr = IFilterMapper2_EnumMatchingFilters(pMapper, &pEnum, 0, TRUE, MERIT_UNLIKELY, TRUE,
196 0, NULL, NULL, &GUID_NULL, TRUE, FALSE, 0, NULL, NULL, &GUID_NULL);
197 ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed with %x\n", hr);
198
199 if (SUCCEEDED(hr) && pEnum)
200 {
201 found = enum_find_filter(wszFilterName2, pEnum);
202 ok(!found, "EnumMatchingFilters should not return the test filter 2\n");
203 }
204
205 if (registered)
206 {
207 hr = IFilterMapper2_UnregisterFilter(pMapper, &CLSID_LegacyAmFilterCategory, NULL,
208 &clsidFilter1);
209 ok(SUCCEEDED(hr), "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
210
211 hr = IFilterMapper2_UnregisterFilter(pMapper, &CLSID_LegacyAmFilterCategory, NULL,
212 &clsidFilter2);
213 ok(SUCCEEDED(hr), "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
214 }
215
216 out:
217
218 if (pEnum) IEnumMoniker_Release(pEnum);
219 if (pMapper) IFilterMapper2_Release(pMapper);
220 }
221
222 static void test_legacy_filter_registration(void)
223 {
224 static const WCHAR testfilterW[] = {'T','e','s','t','f','i','l','t','e','r',0};
225 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
226 static const WCHAR pinW[] = {'P','i','n','1',0};
227 IEnumRegFilters *enum_reg;
228 IEnumMoniker *enum_mon;
229 IFilterMapper2 *mapper2;
230 IFilterMapper *mapper;
231 REGFILTER *regfilter;
232 WCHAR clsidstring[40];
233 WCHAR key_name[50];
234 ULONG count;
235 CLSID clsid;
236 LRESULT ret;
237 HRESULT hr;
238 BOOL found;
239 HKEY hkey;
240
241 /* Register* functions need a filter class key to write pin and pin media
242 * type data to. Create a bogus class key for it. */
243 CoCreateGuid(&clsid);
244 StringFromGUID2(&clsid, clsidstring, sizeof(clsidstring));
245 lstrcpyW(key_name, clsidW);
246 lstrcatW(key_name, clsidstring);
247 ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, key_name, 0, NULL, 0, KEY_WRITE, NULL, &hkey, NULL);
248 if (ret == ERROR_ACCESS_DENIED)
249 {
250 skip("Not authorized to register filters\n");
251 return;
252 }
253
254 /* Test if legacy filter registration scheme works (filter is added to HKCR\Filter). IFilterMapper_RegisterFilter
255 * registers in this way. Filters so registered must then be accessible through both IFilterMapper_EnumMatchingFilters
256 * and IFilterMapper2_EnumMatchingFilters. */
257 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (void **)&mapper2);
258 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
259
260 hr = IFilterMapper2_QueryInterface(mapper2, &IID_IFilterMapper, (void **)&mapper);
261 ok(hr == S_OK, "IFilterMapper2_QueryInterface failed with %x\n", hr);
262
263 /* Set default value - this is interpreted as "friendly name" later. */
264 RegSetValueExW(hkey, NULL, 0, REG_SZ, (BYTE *)testfilterW, sizeof(testfilterW));
265 RegCloseKey(hkey);
266
267 hr = IFilterMapper_RegisterFilter(mapper, clsid, testfilterW, MERIT_UNLIKELY);
268 ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr);
269
270 hr = IFilterMapper_RegisterPin(mapper, clsid, pinW, TRUE, FALSE, FALSE, FALSE, GUID_NULL, NULL);
271 ok(hr == S_OK, "RegisterPin failed: %#x\n", hr);
272
273 hr = IFilterMapper_RegisterPinType(mapper, clsid, pinW, GUID_NULL, GUID_NULL);
274 ok(hr == S_OK, "RegisterPinType failed: %#x\n", hr);
275
276 hr = IFilterMapper2_EnumMatchingFilters(mapper2, &enum_mon, 0, TRUE, MERIT_UNLIKELY, TRUE,
277 0, NULL, NULL, &GUID_NULL, FALSE, FALSE, 0, NULL, NULL, &GUID_NULL);
278 ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed: %x\n", hr);
279 ok(enum_find_filter(testfilterW, enum_mon), "IFilterMapper2 didn't find filter\n");
280 IEnumMoniker_Release(enum_mon);
281
282 found = FALSE;
283 hr = IFilterMapper_EnumMatchingFilters(mapper, &enum_reg, MERIT_UNLIKELY, TRUE, GUID_NULL, GUID_NULL,
284 FALSE, FALSE, GUID_NULL, GUID_NULL);
285 ok(hr == S_OK, "IFilterMapper_EnumMatchingFilters failed with %x\n", hr);
286 while(!found && IEnumRegFilters_Next(enum_reg, 1, &regfilter, &count) == S_OK)
287 {
288 if (!lstrcmpW(regfilter->Name, testfilterW) && IsEqualGUID(&clsid, &regfilter->Clsid))
289 found = TRUE;
290 }
291 IEnumRegFilters_Release(enum_reg);
292 ok(found, "IFilterMapper didn't find filter\n");
293
294 hr = IFilterMapper_UnregisterFilter(mapper, clsid);
295 ok(hr == S_OK, "FilterMapper_UnregisterFilter failed with %x\n", hr);
296
297 hr = IFilterMapper2_EnumMatchingFilters(mapper2, &enum_mon, 0, TRUE, MERIT_UNLIKELY, TRUE,
298 0, NULL, NULL, &GUID_NULL, FALSE, FALSE, 0, NULL, NULL, &GUID_NULL);
299 ok(hr == S_OK, "IFilterMapper2_EnumMatchingFilters failed: %x\n", hr);
300 ok(!enum_find_filter(testfilterW, enum_mon), "IFilterMapper2 shouldn't find filter\n");
301 IEnumMoniker_Release(enum_mon);
302
303 found = FALSE;
304 hr = IFilterMapper_EnumMatchingFilters(mapper, &enum_reg, MERIT_UNLIKELY, TRUE, GUID_NULL, GUID_NULL,
305 FALSE, FALSE, GUID_NULL, GUID_NULL);
306 ok(hr == S_OK, "IFilterMapper_EnumMatchingFilters failed with %x\n", hr);
307 while(!found && IEnumRegFilters_Next(enum_reg, 1, &regfilter, &count) == S_OK)
308 {
309 if (!lstrcmpW(regfilter->Name, testfilterW) && IsEqualGUID(&clsid, &regfilter->Clsid))
310 found = TRUE;
311 }
312 IEnumRegFilters_Release(enum_reg);
313 ok(!found, "IFilterMapper shouldn't find filter\n");
314
315 ret = RegDeleteKeyW(HKEY_CLASSES_ROOT, key_name);
316 ok(!ret, "RegDeleteKeyA failed: %lu\n", ret);
317
318 hr = IFilterMapper_RegisterFilter(mapper, clsid, testfilterW, MERIT_UNLIKELY);
319 ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr);
320
321 hr = IFilterMapper_UnregisterFilter(mapper, clsid);
322 ok(hr == S_OK, "FilterMapper_UnregisterFilter failed with %x\n", hr);
323
324 IFilterMapper_Release(mapper);
325 IFilterMapper2_Release(mapper2);
326 }
327
328 static ULONG getRefcount(IUnknown *iface)
329 {
330 IUnknown_AddRef(iface);
331 return IUnknown_Release(iface);
332 }
333
334 static void test_ifiltermapper_from_filtergraph(void)
335 {
336 IFilterGraph2* pgraph2 = NULL;
337 IFilterMapper2 *pMapper2 = NULL;
338 IFilterGraph *filtergraph = NULL;
339 HRESULT hr;
340 ULONG refcount;
341
342 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2);
343 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
344 if (!pgraph2) goto out;
345
346 hr = IFilterGraph2_QueryInterface(pgraph2, &IID_IFilterMapper2, (LPVOID*)&pMapper2);
347 ok(hr == S_OK, "IFilterGraph2_QueryInterface failed with %08x\n", hr);
348 if (!pMapper2) goto out;
349
350 refcount = getRefcount((IUnknown*)pgraph2);
351 ok(refcount == 2, "unexpected reference count: %u\n", refcount);
352 refcount = getRefcount((IUnknown*)pMapper2);
353 ok(refcount == 2, "unexpected reference count: %u\n", refcount);
354
355 IFilterMapper2_AddRef(pMapper2);
356 refcount = getRefcount((IUnknown*)pgraph2);
357 ok(refcount == 3, "unexpected reference count: %u\n", refcount);
358 refcount = getRefcount((IUnknown*)pMapper2);
359 ok(refcount == 3, "unexpected reference count: %u\n", refcount);
360 IFilterMapper2_Release(pMapper2);
361
362 hr = IFilterMapper2_QueryInterface(pMapper2, &IID_IFilterGraph, (LPVOID*)&filtergraph);
363 ok(hr == S_OK, "IFilterMapper2_QueryInterface failed with %08x\n", hr);
364 if (!filtergraph) goto out;
365
366 IFilterMapper2_Release(pMapper2);
367 pMapper2 = NULL;
368 IFilterGraph_Release(filtergraph);
369 filtergraph = NULL;
370
371 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pMapper2);
372 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
373 if (!pMapper2) goto out;
374
375 hr = IFilterMapper2_QueryInterface(pMapper2, &IID_IFilterGraph, (LPVOID*)&filtergraph);
376 ok(hr == E_NOINTERFACE, "IFilterMapper2_QueryInterface unexpected result: %08x\n", hr);
377
378 out:
379
380 if (pMapper2) IFilterMapper2_Release(pMapper2);
381 if (filtergraph) IFilterGraph_Release(filtergraph);
382 if (pgraph2) IFilterGraph2_Release(pgraph2);
383 }
384
385 static void test_register_filter_with_null_clsMinorType(void)
386 {
387 IFilterMapper2 *pMapper = NULL;
388 HRESULT hr;
389 REGFILTER2 rgf2;
390 REGFILTERPINS rgPins;
391 REGFILTERPINS2 rgPins2;
392 REGPINTYPES rgPinType;
393 static WCHAR wszPinName[] = {'P', 'i', 'n', 0 };
394 static const WCHAR wszFilterName1[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', '1', 0 };
395 static const WCHAR wszFilterName2[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', '2', 0 };
396 CLSID clsidFilter1;
397 CLSID clsidFilter2;
398
399 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
400 &IID_IFilterMapper2, (LPVOID*)&pMapper);
401 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
402 if (FAILED(hr)) goto out;
403
404 hr = CoCreateGuid(&clsidFilter1);
405 ok(hr == S_OK, "CoCreateGuid failed with %x\n", hr);
406 hr = CoCreateGuid(&clsidFilter2);
407 ok(hr == S_OK, "CoCreateGuid failed with %x\n", hr);
408
409 rgPinType.clsMajorType = &GUID_NULL;
410 /* Make sure quartz accepts it without crashing */
411 rgPinType.clsMinorType = NULL;
412
413 /* Test with pin descript version 1 */
414 ZeroMemory(&rgf2, sizeof(rgf2));
415 rgf2.dwVersion = 1;
416 rgf2.dwMerit = MERIT_UNLIKELY;
417 S1(U(rgf2)).cPins = 1;
418 S1(U(rgf2)).rgPins = &rgPins;
419
420 rgPins.strName = wszPinName;
421 rgPins.bRendered = 1;
422 rgPins.bOutput = 0;
423 rgPins.bZero = 0;
424 rgPins.bMany = 0;
425 rgPins.clsConnectsToFilter = NULL;
426 rgPins.strConnectsToPin = NULL;
427 rgPins.nMediaTypes = 1;
428 rgPins.lpMediaType = &rgPinType;
429
430 hr = IFilterMapper2_RegisterFilter(pMapper, &clsidFilter1, wszFilterName1, NULL,
431 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
432 if (hr == E_ACCESSDENIED)
433 {
434 skip("Not authorized to register filters\n");
435 goto out;
436 }
437 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
438
439 hr = IFilterMapper2_UnregisterFilter(pMapper, &CLSID_LegacyAmFilterCategory, NULL, &clsidFilter1);
440 ok(hr == S_OK, "FilterMapper_UnregisterFilter failed with %x\n", hr);
441
442 /* Test with pin descript version 2 */
443 ZeroMemory(&rgf2, sizeof(rgf2));
444 rgf2.dwVersion = 2;
445 rgf2.dwMerit = MERIT_UNLIKELY;
446 S2(U(rgf2)).cPins2 = 1;
447 S2(U(rgf2)).rgPins2 = &rgPins2;
448
449 rgPins2.dwFlags = REG_PINFLAG_B_RENDERER;
450 rgPins2.cInstances = 1;
451 rgPins2.nMediaTypes = 1;
452 rgPins2.lpMediaType = &rgPinType;
453 rgPins2.nMediums = 0;
454 rgPins2.lpMedium = NULL;
455 rgPins2.clsPinCategory = NULL;
456
457 hr = IFilterMapper2_RegisterFilter(pMapper, &clsidFilter2, wszFilterName2, NULL,
458 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
459 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
460
461 hr = IFilterMapper2_UnregisterFilter(pMapper, &CLSID_LegacyAmFilterCategory, NULL, &clsidFilter2);
462 ok(hr == S_OK, "FilterMapper_UnregisterFilter failed with %x\n", hr);
463
464 out:
465
466 if (pMapper) IFilterMapper2_Release(pMapper);
467 }
468
469 static void test_parse_filter_data(void)
470 {
471 static const BYTE data_block[] = {
472 0x02,0x00,0x00,0x00,0xff,0xff,0x5f,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x70,0x69,0x33,
473 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
474 0x30,0x74,0x79,0x33,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x31,0x70,0x69,0x33,
475 0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
476 0x30,0x74,0x79,0x33,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x76,0x69,0x64,0x73,
477 0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
478 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
479
480 BYTE *prgbRegFilter2 = NULL;
481 REGFILTER2 *pRegFilter = NULL;
482 IFilterMapper2 *pMapper = NULL;
483 SAFEARRAYBOUND saBound;
484 SAFEARRAY *psa = NULL;
485 LPBYTE pbSAData = NULL;
486 HRESULT hr;
487
488 IAMFilterData *pData = NULL;
489
490 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
491 &IID_IFilterMapper2, (LPVOID*)&pMapper);
492 ok((hr == S_OK || broken(hr != S_OK)), "CoCreateInstance failed with %x\n", hr);
493 if (FAILED(hr)) goto out;
494
495 hr = IFilterMapper2_QueryInterface(pMapper, &IID_IAMFilterData, (LPVOID*)&pData);
496 ok((hr == S_OK || broken(hr != S_OK)), "Unable to find IID_IAMFilterData interface\n");
497 if (FAILED(hr)) goto out;
498
499 saBound.lLbound = 0;
500 saBound.cElements = sizeof(data_block);
501 psa = SafeArrayCreate(VT_UI1, 1, &saBound);
502 ok(psa != NULL, "Unable to create safe array\n");
503 if (!psa) goto out;
504 hr = SafeArrayAccessData(psa, (LPVOID *)&pbSAData);
505 ok(hr == S_OK, "Unable to access array data\n");
506 if (FAILED(hr)) goto out;
507 memcpy(pbSAData, data_block, sizeof(data_block));
508
509 hr = IAMFilterData_ParseFilterData(pData, pbSAData, sizeof(data_block), &prgbRegFilter2);
510 /* We cannot do anything here. prgbRegFilter2 is very unstable */
511 /* Pre Vista, this is a stack pointer so anything that changes the stack invalidats it */
512 /* Post Vista, it is a static pointer in the data section of the module */
513 pRegFilter =((REGFILTER2**)prgbRegFilter2)[0];
514 ok (hr==S_OK,"Failed to Parse filter Data\n");
515
516 ok(IsBadReadPtr(prgbRegFilter2,sizeof(REGFILTER2*))==0,"Bad read pointer returned\n");
517 ok(IsBadReadPtr(pRegFilter,sizeof(REGFILTER2))==0,"Bad read pointer for FilterData\n");
518 ok(pRegFilter->dwMerit == 0x5fffff,"Incorrect merit returned\n");
519
520 out:
521 CoTaskMemFree(pRegFilter);
522 if (psa)
523 {
524 SafeArrayUnaccessData(psa);
525 SafeArrayDestroy(psa);
526 }
527 if (pData)
528 IAMFilterData_Release(pData);
529 if (pMapper)
530 IFilterMapper2_Release(pMapper);
531 }
532
533 typedef struct IUnknownImpl
534 {
535 IUnknown IUnknown_iface;
536 int AddRef_called;
537 int Release_called;
538 } IUnknownImpl;
539
540 static IUnknownImpl *IUnknownImpl_from_iface(IUnknown * iface)
541 {
542 return CONTAINING_RECORD(iface, IUnknownImpl, IUnknown_iface);
543 }
544
545 static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
546 {
547 ok(0, "QueryInterface should not be called for %s\n", wine_dbgstr_guid(riid));
548 return E_NOINTERFACE;
549 }
550
551 static ULONG WINAPI IUnknownImpl_AddRef(IUnknown * iface)
552 {
553 IUnknownImpl *This = IUnknownImpl_from_iface(iface);
554 This->AddRef_called++;
555 return 2;
556 }
557
558 static ULONG WINAPI IUnknownImpl_Release(IUnknown * iface)
559 {
560 IUnknownImpl *This = IUnknownImpl_from_iface(iface);
561 This->Release_called++;
562 return 1;
563 }
564
565 static CONST_VTBL IUnknownVtbl IUnknownImpl_Vtbl =
566 {
567 IUnknownImpl_QueryInterface,
568 IUnknownImpl_AddRef,
569 IUnknownImpl_Release
570 };
571
572 static void test_aggregate_filter_mapper(void)
573 {
574 HRESULT hr;
575 IUnknown *pmapper;
576 IUnknown *punk;
577 IUnknownImpl unk_outer = { { &IUnknownImpl_Vtbl }, 0, 0 };
578
579 hr = CoCreateInstance(&CLSID_FilterMapper2, &unk_outer.IUnknown_iface, CLSCTX_INPROC_SERVER,
580 &IID_IUnknown, (void **)&pmapper);
581 ok(hr == S_OK, "CoCreateInstance returned %x\n", hr);
582 ok(pmapper != &unk_outer.IUnknown_iface, "pmapper = %p, expected not %p\n", pmapper, &unk_outer.IUnknown_iface);
583
584 hr = IUnknown_QueryInterface(pmapper, &IID_IUnknown, (void **)&punk);
585 ok(hr == S_OK, "IUnknown_QueryInterface returned %x\n", hr);
586 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
587 IUnknown_Release(punk);
588
589 ok(unk_outer.AddRef_called == 0, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
590 ok(unk_outer.Release_called == 0, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
591 unk_outer.AddRef_called = 0;
592 unk_outer.Release_called = 0;
593
594 hr = IUnknown_QueryInterface(pmapper, &IID_IFilterMapper, (void **)&punk);
595 ok(hr == S_OK, "IUnknown_QueryInterface returned %x\n", hr);
596 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
597 IUnknown_Release(punk);
598
599 ok(unk_outer.AddRef_called == 1, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
600 ok(unk_outer.Release_called == 1, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
601 unk_outer.AddRef_called = 0;
602 unk_outer.Release_called = 0;
603
604 hr = IUnknown_QueryInterface(pmapper, &IID_IFilterMapper2, (void **)&punk);
605 ok(hr == S_OK, "IUnknown_QueryInterface returned %x\n", hr);
606 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
607 IUnknown_Release(punk);
608
609 ok(unk_outer.AddRef_called == 1, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
610 ok(unk_outer.Release_called == 1, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
611 unk_outer.AddRef_called = 0;
612 unk_outer.Release_called = 0;
613
614 hr = IUnknown_QueryInterface(pmapper, &IID_IFilterMapper3, (void **)&punk);
615 ok(hr == S_OK, "IUnknown_QueryInterface returned %x\n", hr);
616 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
617 IUnknown_Release(punk);
618
619 ok(unk_outer.AddRef_called == 1, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
620 ok(unk_outer.Release_called == 1, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
621
622 IUnknown_Release(pmapper);
623 }
624
625 START_TEST(filtermapper)
626 {
627 CoInitialize(NULL);
628
629 test_fm2_enummatchingfilters();
630 test_legacy_filter_registration();
631 test_ifiltermapper_from_filtergraph();
632 test_register_filter_with_null_clsMinorType();
633 test_parse_filter_data();
634 test_aggregate_filter_mapper();
635
636 CoUninitialize();
637 }