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