1 /*
2 * Some unit tests for devenum
3 *
4 * Copyright (C) 2012 Christian Costa
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 <stdio.h>
24
25 #include "wine/test.h"
26 #include "initguid.h"
27 #include "ole2.h"
28 #include "strmif.h"
29 #include "uuids.h"
30 #include "vfwmsgs.h"
31 #include "mmsystem.h"
32 #include "dsound.h"
33 #include "mmddk.h"
34 #include "vfw.h"
35 #include "dmoreg.h"
36 #include "setupapi.h"
37
38 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
39
40 static const WCHAR friendly_name[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
41 static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
42 static const WCHAR clsidW[] = {'C','L','S','I','D',0};
43 static const WCHAR waveW[] = {'w','a','v','e',':',0};
44 static const WCHAR dmoW[] = {'d','m','o',':',0};
45 static const WCHAR swW[] = {'s','w',':',0};
46 static const WCHAR cmW[] = {'c','m',':',0};
47 static const WCHAR backslashW[] = {'\\',0};
48
strchrW(const WCHAR * str,WCHAR ch)49 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
50 {
51 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
52 return NULL;
53 }
54
strncmpW(const WCHAR * str1,const WCHAR * str2,int n)55 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
56 {
57 if (n <= 0) return 0;
58 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
59 return *str1 - *str2;
60 }
61
test_devenum(IBindCtx * bind_ctx)62 static void test_devenum(IBindCtx *bind_ctx)
63 {
64 IEnumMoniker *enum_cat, *enum_moniker;
65 ICreateDevEnum* create_devenum;
66 IPropertyBag *prop_bag;
67 IMoniker *moniker;
68 GUID cat_guid, clsid;
69 WCHAR *displayname;
70 VARIANT var;
71 HRESULT hr;
72 int count;
73
74 hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
75 &IID_ICreateDevEnum, (LPVOID*)&create_devenum);
76 ok(hr == S_OK, "Failed to create devenum: %#x\n", hr);
77
78 hr = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_ActiveMovieCategories, &enum_cat, 0);
79 ok(hr == S_OK, "Failed to enum categories: %#x\n", hr);
80
81 while (IEnumMoniker_Next(enum_cat, 1, &moniker, NULL) == S_OK)
82 {
83 hr = IMoniker_BindToStorage(moniker, bind_ctx, NULL, &IID_IPropertyBag, (void **)&prop_bag);
84 ok(hr == S_OK, "IMoniker_BindToStorage failed: %#x\n", hr);
85
86 VariantInit(&var);
87 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
88 ok(hr == S_OK, "Failed to read CLSID: %#x\n", hr);
89
90 hr = CLSIDFromString(V_BSTR(&var), &cat_guid);
91 ok(hr == S_OK, "got %#x\n", hr);
92
93 VariantClear(&var);
94 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
95 ok(hr == S_OK, "Failed to read FriendlyName: %#x\n", hr);
96
97 if (winetest_debug > 1)
98 trace("%s %s:\n", wine_dbgstr_guid(&cat_guid), wine_dbgstr_w(V_BSTR(&var)));
99
100 VariantClear(&var);
101 IPropertyBag_Release(prop_bag);
102 IMoniker_Release(moniker);
103
104 hr = ICreateDevEnum_CreateClassEnumerator(create_devenum, &cat_guid, &enum_moniker, 0);
105 ok(SUCCEEDED(hr), "Failed to enum devices: %#x\n", hr);
106
107 if (hr == S_OK)
108 {
109 count = 0;
110
111 while (IEnumMoniker_Next(enum_moniker, 1, &moniker, NULL) == S_OK)
112 {
113 hr = IMoniker_GetDisplayName(moniker, NULL, NULL, &displayname);
114 ok(hr == S_OK, "got %#x\n", hr);
115
116 hr = IMoniker_GetClassID(moniker, NULL);
117 ok(hr == E_INVALIDARG, "IMoniker_GetClassID should failed %x\n", hr);
118
119 hr = IMoniker_GetClassID(moniker, &clsid);
120 ok(hr == S_OK, "IMoniker_GetClassID failed with error %x\n", hr);
121 ok(IsEqualGUID(&clsid, &CLSID_CDeviceMoniker),
122 "Expected CLSID_CDeviceMoniker got %s\n", wine_dbgstr_guid(&clsid));
123
124 VariantInit(&var);
125 hr = IMoniker_BindToStorage(moniker, bind_ctx, NULL, &IID_IPropertyBag, (LPVOID*)&prop_bag);
126 ok(hr == S_OK, "IMoniker_BindToStorage failed with error %x\n", hr);
127
128 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
129 ok((hr == S_OK) | (hr == ERROR_KEY_DOES_NOT_EXIST),
130 "IPropertyBag_Read failed: %#x\n", hr);
131
132 if (winetest_debug > 1)
133 trace(" %s %s\n", wine_dbgstr_w(displayname), wine_dbgstr_w(V_BSTR(&var)));
134
135 hr = IMoniker_BindToObject(moniker, bind_ctx, NULL, &IID_IUnknown, NULL);
136 ok(hr == E_POINTER, "got %#x\n", hr);
137
138 VariantClear(&var);
139 CoTaskMemFree(displayname);
140 IPropertyBag_Release(prop_bag);
141 IMoniker_Release(moniker);
142 count++;
143 }
144 IEnumMoniker_Release(enum_moniker);
145
146 ok(count > 0, "CreateClassEnumerator() returned S_OK but no devices were enumerated.\n");
147 }
148 }
149
150 IEnumMoniker_Release(enum_cat);
151 ICreateDevEnum_Release(create_devenum);
152 }
153
test_moniker_isequal(void)154 static void test_moniker_isequal(void)
155 {
156 HRESULT res;
157 ICreateDevEnum *create_devenum = NULL;
158 IEnumMoniker *enum_moniker0 = NULL, *enum_moniker1 = NULL;
159 IMoniker *moniker0 = NULL, *moniker1 = NULL;
160
161 res = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
162 &IID_ICreateDevEnum, (LPVOID*)&create_devenum);
163 if (FAILED(res))
164 {
165 skip("Cannot create SystemDeviceEnum object (%x)\n", res);
166 return;
167 }
168
169 res = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_LegacyAmFilterCategory, &enum_moniker0, 0);
170 ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res);
171 if (SUCCEEDED(res))
172 {
173 if (IEnumMoniker_Next(enum_moniker0, 1, &moniker0, NULL) == S_OK &&
174 IEnumMoniker_Next(enum_moniker0, 1, &moniker1, NULL) == S_OK)
175 {
176 res = IMoniker_IsEqual(moniker0, moniker1);
177 ok(res == S_FALSE, "IMoniker_IsEqual should fail (res = %x)\n", res);
178
179 res = IMoniker_IsEqual(moniker1, moniker0);
180 ok(res == S_FALSE, "IMoniker_IsEqual should fail (res = %x)\n", res);
181
182 IMoniker_Release(moniker0);
183 IMoniker_Release(moniker1);
184 }
185 else
186 skip("Cannot get moniker for testing.\n");
187 }
188 IEnumMoniker_Release(enum_moniker0);
189
190 res = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_LegacyAmFilterCategory, &enum_moniker0, 0);
191 ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res);
192 res = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_AudioRendererCategory, &enum_moniker1, 0);
193 ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res);
194 if (SUCCEEDED(res))
195 {
196 if (IEnumMoniker_Next(enum_moniker0, 1, &moniker0, NULL) == S_OK &&
197 IEnumMoniker_Next(enum_moniker1, 1, &moniker1, NULL) == S_OK)
198 {
199 res = IMoniker_IsEqual(moniker0, moniker1);
200 ok(res == S_FALSE, "IMoniker_IsEqual should failed (res = %x)\n", res);
201
202 res = IMoniker_IsEqual(moniker1, moniker0);
203 ok(res == S_FALSE, "IMoniker_IsEqual should failed (res = %x)\n", res);
204
205 IMoniker_Release(moniker0);
206 IMoniker_Release(moniker1);
207 }
208 else
209 skip("Cannot get moniker for testing.\n");
210 }
211 IEnumMoniker_Release(enum_moniker0);
212 IEnumMoniker_Release(enum_moniker1);
213
214 res = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_LegacyAmFilterCategory, &enum_moniker0, 0);
215 ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res);
216 res = ICreateDevEnum_CreateClassEnumerator(create_devenum, &CLSID_LegacyAmFilterCategory, &enum_moniker1, 0);
217 ok(SUCCEEDED(res), "Cannot create enum moniker (res = %x)\n", res);
218 if (SUCCEEDED(res))
219 {
220 if (IEnumMoniker_Next(enum_moniker0, 1, &moniker0, NULL) == S_OK &&
221 IEnumMoniker_Next(enum_moniker1, 1, &moniker1, NULL) == S_OK)
222 {
223 res = IMoniker_IsEqual(moniker0, moniker1);
224 ok(res == S_OK, "IMoniker_IsEqual failed (res = %x)\n", res);
225
226 res = IMoniker_IsEqual(moniker1, moniker0);
227 ok(res == S_OK, "IMoniker_IsEqual failed (res = %x)\n", res);
228
229 IMoniker_Release(moniker0);
230 IMoniker_Release(moniker1);
231 }
232 else
233 skip("Cannot get moniker for testing.\n");
234 }
235 IEnumMoniker_Release(enum_moniker0);
236 IEnumMoniker_Release(enum_moniker1);
237
238 ICreateDevEnum_Release(create_devenum);
239
240 return;
241 }
242
find_moniker(const GUID * class,IMoniker * needle)243 static BOOL find_moniker(const GUID *class, IMoniker *needle)
244 {
245 ICreateDevEnum *devenum;
246 IEnumMoniker *enum_mon;
247 IMoniker *mon;
248 BOOL found = FALSE;
249
250 CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (void **)&devenum);
251 ICreateDevEnum_CreateClassEnumerator(devenum, class, &enum_mon, 0);
252 while (!found && IEnumMoniker_Next(enum_mon, 1, &mon, NULL) == S_OK)
253 {
254 if (IMoniker_IsEqual(mon, needle) == S_OK)
255 found = TRUE;
256
257 IMoniker_Release(mon);
258 }
259
260 IEnumMoniker_Release(enum_mon);
261 ICreateDevEnum_Release(devenum);
262 return found;
263 }
264
265 DEFINE_GUID(CLSID_TestFilter, 0xdeadbeef,0xcf51,0x43e6,0xb6,0xc5,0x29,0x9e,0xa8,0xb6,0xb5,0x91);
266
test_register_filter(void)267 static void test_register_filter(void)
268 {
269 static const WCHAR name[] = {'d','e','v','e','n','u','m',' ','t','e','s','t',0};
270 IFilterMapper2 *mapper2;
271 IMoniker *mon = NULL;
272 REGFILTER2 rgf2 = {0};
273 HRESULT hr;
274
275 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper2, (void **)&mapper2);
276 ok(hr == S_OK, "Failed to create FilterMapper2: %#x\n", hr);
277
278 rgf2.dwVersion = 2;
279 rgf2.dwMerit = MERIT_UNLIKELY;
280 S2(U(rgf2)).cPins2 = 0;
281
282 hr = IFilterMapper2_RegisterFilter(mapper2, &CLSID_TestFilter, name, &mon, NULL, NULL, &rgf2);
283 if (hr == E_ACCESSDENIED)
284 {
285 skip("Not enough permissions to register filters\n");
286 IFilterMapper2_Release(mapper2);
287 return;
288 }
289 ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr);
290
291 ok(find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should be registered\n");
292
293 hr = IFilterMapper2_UnregisterFilter(mapper2, NULL, NULL, &CLSID_TestFilter);
294 ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr);
295
296 ok(!find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should not be registered\n");
297 IMoniker_Release(mon);
298
299 mon = NULL;
300 hr = IFilterMapper2_RegisterFilter(mapper2, &CLSID_TestFilter, name, &mon, &CLSID_AudioRendererCategory, NULL, &rgf2);
301 ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr);
302
303 ok(find_moniker(&CLSID_AudioRendererCategory, mon), "filter should be registered\n");
304
305 hr = IFilterMapper2_UnregisterFilter(mapper2, &CLSID_AudioRendererCategory, NULL, &CLSID_TestFilter);
306 ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr);
307
308 ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "filter should not be registered\n");
309 IMoniker_Release(mon);
310
311 IFilterMapper2_Release(mapper2);
312 }
313
check_display_name_(int line,IParseDisplayName * parser,WCHAR * buffer)314 static IMoniker *check_display_name_(int line, IParseDisplayName *parser, WCHAR *buffer)
315 {
316 IMoniker *mon;
317 ULONG eaten;
318 HRESULT hr;
319 WCHAR *str;
320
321 hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, &mon);
322 ok_(__FILE__, line)(hr == S_OK, "ParseDisplayName failed: %#x\n", hr);
323
324 hr = IMoniker_GetDisplayName(mon, NULL, NULL, &str);
325 ok_(__FILE__, line)(hr == S_OK, "GetDisplayName failed: %#x\n", hr);
326 ok_(__FILE__, line)(!lstrcmpW(str, buffer), "got %s\n", wine_dbgstr_w(str));
327
328 CoTaskMemFree(str);
329
330 return mon;
331 }
332 #define check_display_name(parser, buffer) check_display_name_(__LINE__, parser, buffer)
333
test_directshow_filter(void)334 static void test_directshow_filter(void)
335 {
336 static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0};
337 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
338 static WCHAR testW[] = {'\\','t','e','s','t',0};
339 IParseDisplayName *parser;
340 IPropertyBag *prop_bag;
341 IMoniker *mon;
342 WCHAR buffer[200];
343 LRESULT res;
344 VARIANT var;
345 HRESULT hr;
346
347 /* Test ParseDisplayName and GetDisplayName */
348 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
349 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
350
351 lstrcpyW(buffer, deviceW);
352 lstrcatW(buffer, swW);
353 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
354 lstrcatW(buffer, testW);
355 mon = check_display_name(parser, buffer);
356
357 /* Test writing and reading from the property bag */
358 ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "filter should not be registered\n");
359
360 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
361 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
362
363 VariantInit(&var);
364 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
365 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr);
366
367 /* writing causes the key to be created */
368 V_VT(&var) = VT_BSTR;
369 V_BSTR(&var) = SysAllocString(testW);
370 hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
371 if (hr != E_ACCESSDENIED)
372 {
373 ok(hr == S_OK, "Write failed: %#x\n", hr);
374
375 ok(find_moniker(&CLSID_AudioRendererCategory, mon), "filter should be registered\n");
376
377 VariantClear(&var);
378 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
379 ok(hr == S_OK, "Read failed: %#x\n", hr);
380 ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
381
382 IMoniker_Release(mon);
383
384 /* devenum doesn't give us a way to unregister�we have to do that manually */
385 lstrcpyW(buffer, clsidW);
386 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
387 lstrcatW(buffer, instanceW);
388 lstrcatW(buffer, testW);
389 res = RegDeleteKeyW(HKEY_CLASSES_ROOT, buffer);
390 ok(!res, "RegDeleteKey failed: %lu\n", res);
391 }
392
393 VariantClear(&var);
394 IPropertyBag_Release(prop_bag);
395
396 /* name can be anything */
397
398 lstrcpyW(buffer, deviceW);
399 lstrcatW(buffer, swW);
400 lstrcatW(buffer, testW+1);
401 mon = check_display_name(parser, buffer);
402
403 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
404 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
405
406 VariantClear(&var);
407 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
408 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr);
409
410 V_VT(&var) = VT_BSTR;
411 V_BSTR(&var) = SysAllocString(testW);
412 hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
413 if (hr != E_ACCESSDENIED)
414 {
415 ok(hr == S_OK, "Write failed: %#x\n", hr);
416
417 VariantClear(&var);
418 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
419 ok(hr == S_OK, "Read failed: %#x\n", hr);
420 ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
421
422 IMoniker_Release(mon);
423
424 /* vista+ stores it inside the Instance key */
425 RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\test\\Instance");
426
427 res = RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\test");
428 ok(!res, "RegDeleteKey failed: %lu\n", res);
429 }
430
431 VariantClear(&var);
432 IPropertyBag_Release(prop_bag);
433 IParseDisplayName_Release(parser);
434 }
435
test_codec(void)436 static void test_codec(void)
437 {
438 static WCHAR testW[] = {'\\','t','e','s','t',0};
439 IParseDisplayName *parser;
440 IPropertyBag *prop_bag;
441 IMoniker *mon;
442 WCHAR buffer[200];
443 VARIANT var;
444 HRESULT hr;
445
446 /* Test ParseDisplayName and GetDisplayName */
447 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
448 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
449
450 lstrcpyW(buffer, deviceW);
451 lstrcatW(buffer, cmW);
452 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
453 lstrcatW(buffer, testW);
454 mon = check_display_name(parser, buffer);
455
456 /* Test writing and reading from the property bag */
457 ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "codec should not be registered\n");
458
459 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
460 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
461
462 VariantInit(&var);
463 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
464 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr);
465
466 V_VT(&var) = VT_BSTR;
467 V_BSTR(&var) = SysAllocString(testW);
468 hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
469 ok(hr == S_OK, "Write failed: %#x\n", hr);
470
471 VariantClear(&var);
472 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
473 ok(hr == S_OK, "Read failed: %#x\n", hr);
474 ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
475
476 /* unlike DirectShow filters, these are automatically generated, so
477 * enumerating them will destroy the key */
478 ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "codec should not be registered\n");
479
480 VariantClear(&var);
481 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
482 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr);
483
484 IPropertyBag_Release(prop_bag);
485 IMoniker_Release(mon);
486
487 IParseDisplayName_Release(parser);
488 }
489
test_dmo(void)490 static void test_dmo(void)
491 {
492 static const WCHAR name[] = {'d','e','v','e','n','u','m',' ','t','e','s','t',0};
493 IParseDisplayName *parser;
494 IPropertyBag *prop_bag;
495 WCHAR buffer[200];
496 IMoniker *mon;
497 VARIANT var;
498 HRESULT hr;
499
500 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
501 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
502
503 lstrcpyW(buffer, deviceW);
504 lstrcatW(buffer, dmoW);
505 StringFromGUID2(&CLSID_TestFilter, buffer + lstrlenW(buffer), CHARS_IN_GUID);
506 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
507 mon = check_display_name(parser, buffer);
508
509 ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should not be registered\n");
510
511 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
512 ok(hr == S_OK, "got %#x\n", hr);
513
514 VariantInit(&var);
515 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
516 ok(hr == E_FAIL, "got %#x\n", hr);
517
518 V_VT(&var) = VT_BSTR;
519 V_BSTR(&var) = SysAllocString(name);
520 hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
521 ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr);
522
523 hr = DMORegister(name, &CLSID_TestFilter, &CLSID_AudioRendererCategory, 0, 0, NULL, 0, NULL);
524 if (hr != E_FAIL)
525 {
526 ok(hr == S_OK, "got %#x\n", hr);
527
528 ok(find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should be registered\n");
529
530 VariantClear(&var);
531 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
532 ok(hr == S_OK, "got %#x\n", hr);
533 ok(!lstrcmpW(V_BSTR(&var), name), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
534
535 VariantClear(&var);
536 V_VT(&var) = VT_BSTR;
537 V_BSTR(&var) = SysAllocString(name);
538 hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
539 ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr);
540
541 VariantClear(&var);
542 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
543 ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "got %#x\n", hr);
544
545 hr = DMOUnregister(&CLSID_TestFilter, &CLSID_AudioRendererCategory);
546 ok(hr == S_OK, "got %#x\n", hr);
547 }
548 IPropertyBag_Release(prop_bag);
549 IMoniker_Release(mon);
550 IParseDisplayName_Release(parser);
551 }
552
test_legacy_filter(void)553 static void test_legacy_filter(void)
554 {
555 static const WCHAR nameW[] = {'t','e','s','t',0};
556 IParseDisplayName *parser;
557 IPropertyBag *prop_bag;
558 IFilterMapper *mapper;
559 IMoniker *mon;
560 WCHAR buffer[200];
561 VARIANT var;
562 HRESULT hr;
563
564 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
565 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
566
567 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper, (void **)&mapper);
568 ok(hr == S_OK, "Failed to create FilterMapper: %#x\n", hr);
569
570 hr = IFilterMapper_RegisterFilter(mapper, CLSID_TestFilter, nameW, 0xdeadbeef);
571 if (hr == VFW_E_BAD_KEY)
572 {
573 win_skip("not enough permissions to register filters\n");
574 goto end;
575 }
576 ok(hr == S_OK, "RegisterFilter failed: %#x\n", hr);
577
578 lstrcpyW(buffer, deviceW);
579 lstrcatW(buffer, cmW);
580 StringFromGUID2(&CLSID_LegacyAmFilterCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
581 lstrcatW(buffer, backslashW);
582 StringFromGUID2(&CLSID_TestFilter, buffer + lstrlenW(buffer), CHARS_IN_GUID);
583
584 mon = check_display_name(parser, buffer);
585 ok(find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should be registered\n");
586
587 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
588 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
589
590 VariantInit(&var);
591 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
592 ok(hr == S_OK, "Read failed: %#x\n", hr);
593
594 StringFromGUID2(&CLSID_TestFilter, buffer, CHARS_IN_GUID);
595 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
596 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
597
598 VariantClear(&var);
599 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
600 ok(hr == S_OK, "Read failed: %#x\n", hr);
601 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
602 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
603
604 VariantClear(&var);
605 IPropertyBag_Release(prop_bag);
606
607 hr = IFilterMapper_UnregisterFilter(mapper, CLSID_TestFilter);
608 ok(hr == S_OK, "UnregisterFilter failed: %#x\n", hr);
609
610 ok(!find_moniker(&CLSID_LegacyAmFilterCategory, mon), "filter should not be registered\n");
611 IMoniker_Release(mon);
612
613 end:
614 IFilterMapper_Release(mapper);
615 IParseDisplayName_Release(parser);
616 }
617
test_dsound(GUID * guid,const WCHAR * desc,const WCHAR * module,void * context)618 static BOOL CALLBACK test_dsound(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context)
619 {
620 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0};
621 static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0};
622 static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0};
623 IParseDisplayName *parser;
624 IPropertyBag *prop_bag;
625 IMoniker *mon;
626 WCHAR buffer[200];
627 WCHAR name[200];
628 VARIANT var;
629 HRESULT hr;
630
631 if (guid)
632 {
633 lstrcpyW(name, directsoundW);
634 lstrcatW(name, desc);
635 }
636 else
637 {
638 lstrcpyW(name, defaultW);
639 guid = (GUID *)&GUID_NULL;
640 }
641
642 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
643 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
644
645 lstrcpyW(buffer, deviceW);
646 lstrcatW(buffer, cmW);
647 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
648 lstrcatW(buffer, backslashW);
649 lstrcatW(buffer, name);
650
651 mon = check_display_name(parser, buffer);
652
653 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
654 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
655
656 VariantInit(&var);
657 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
658 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
659 {
660 /* Win8+ uses the GUID instead of the device name */
661 IPropertyBag_Release(prop_bag);
662 IMoniker_Release(mon);
663
664 lstrcpyW(buffer, deviceW);
665 lstrcatW(buffer, cmW);
666 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
667 lstrcatW(buffer, backslashW);
668 lstrcatW(buffer, directsoundW);
669 StringFromGUID2(guid, buffer + lstrlenW(buffer) - 1, CHARS_IN_GUID);
670
671 mon = check_display_name(parser, buffer);
672
673 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
674 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
675
676 VariantInit(&var);
677 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
678 }
679 ok(hr == S_OK, "Read failed: %#x\n", hr);
680
681 ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
682 wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var)));
683
684 VariantClear(&var);
685 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
686 ok(hr == S_OK, "Read failed: %#x\n", hr);
687
688 StringFromGUID2(&CLSID_DSoundRender, buffer, CHARS_IN_GUID);
689 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
690 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
691
692 VariantClear(&var);
693 hr = IPropertyBag_Read(prop_bag, dsguidW, &var, NULL);
694 ok(hr == S_OK, "Read failed: %#x\n", hr);
695
696 StringFromGUID2(guid, buffer, CHARS_IN_GUID);
697 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
698 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
699
700 VariantClear(&var);
701 IPropertyBag_Release(prop_bag);
702 IMoniker_Release(mon);
703 IParseDisplayName_Release(parser);
704 return TRUE;
705 }
706
test_waveout(void)707 static void test_waveout(void)
708 {
709 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','W','a','v','e','O','u','t',' ','D','e','v','i','c','e',0};
710 static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0};
711 IParseDisplayName *parser;
712 IPropertyBag *prop_bag;
713 IMoniker *mon;
714 WCHAR endpoint[200];
715 WAVEOUTCAPSW caps;
716 WCHAR buffer[200];
717 const WCHAR *name;
718 MMRESULT mmr;
719 int count, i;
720 VARIANT var;
721 HRESULT hr;
722
723 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
724 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
725
726 count = waveOutGetNumDevs();
727
728 for (i = -1; i < count; i++)
729 {
730 waveOutGetDevCapsW(i, &caps, sizeof(caps));
731
732 if (i == -1) /* WAVE_MAPPER */
733 name = defaultW;
734 else
735 name = caps.szPname;
736
737 lstrcpyW(buffer, deviceW);
738 lstrcatW(buffer, cmW);
739 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
740 lstrcatW(buffer, backslashW);
741 lstrcatW(buffer, name);
742
743 mon = check_display_name(parser, buffer);
744
745 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
746 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
747
748 VariantInit(&var);
749 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
750 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
751 {
752 IPropertyBag_Release(prop_bag);
753 IMoniker_Release(mon);
754
755 /* Win8+ uses the endpoint GUID instead of the device name */
756 mmr = waveOutMessage((HWAVEOUT)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID,
757 (DWORD_PTR) endpoint, sizeof(endpoint));
758 ok(!mmr, "waveOutMessage failed: %u\n", mmr);
759
760 lstrcpyW(buffer, deviceW);
761 lstrcatW(buffer, cmW);
762 StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
763 lstrcatW(buffer, backslashW);
764 lstrcatW(buffer, waveW);
765 lstrcatW(buffer, strchrW(endpoint, '}') + 2);
766
767 mon = check_display_name(parser, buffer);
768
769 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
770 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
771
772 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
773 }
774 ok(hr == S_OK, "Read failed: %#x\n", hr);
775
776 ok(!strncmpW(name, V_BSTR(&var), lstrlenW(name)), "expected %s, got %s\n",
777 wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var)));
778
779 VariantClear(&var);
780 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
781 ok(hr == S_OK, "Read failed: %#x\n", hr);
782
783 StringFromGUID2(&CLSID_AudioRender, buffer, CHARS_IN_GUID);
784 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
785 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
786
787 VariantClear(&var);
788 hr = IPropertyBag_Read(prop_bag, waveoutidW, &var, NULL);
789 ok(hr == S_OK, "Read failed: %#x\n", hr);
790
791 ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var));
792
793 IPropertyBag_Release(prop_bag);
794 IMoniker_Release(mon);
795 }
796
797 IParseDisplayName_Release(parser);
798 }
799
test_wavein(void)800 static void test_wavein(void)
801 {
802 static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0};
803 IParseDisplayName *parser;
804 IPropertyBag *prop_bag;
805 IMoniker *mon;
806 WCHAR endpoint[200];
807 WCHAR buffer[200];
808 WAVEINCAPSW caps;
809 MMRESULT mmr;
810 int count, i;
811 VARIANT var;
812 HRESULT hr;
813
814 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
815 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
816
817 count = waveInGetNumDevs();
818
819 for (i = 0; i < count; i++)
820 {
821 waveInGetDevCapsW(i, &caps, sizeof(caps));
822
823 lstrcpyW(buffer, deviceW);
824 lstrcatW(buffer, cmW);
825 StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
826 lstrcatW(buffer, backslashW);
827 lstrcatW(buffer, caps.szPname);
828
829 mon = check_display_name(parser, buffer);
830
831 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
832 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
833
834 VariantInit(&var);
835 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
836 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
837 {
838 IPropertyBag_Release(prop_bag);
839 IMoniker_Release(mon);
840
841 /* Win8+ uses the endpoint GUID instead of the device name */
842 mmr = waveInMessage((HWAVEIN)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID,
843 (DWORD_PTR) endpoint, sizeof(endpoint));
844 ok(!mmr, "waveInMessage failed: %u\n", mmr);
845
846 lstrcpyW(buffer, deviceW);
847 lstrcatW(buffer, cmW);
848 StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
849 lstrcatW(buffer, backslashW);
850 lstrcatW(buffer, waveW);
851 lstrcatW(buffer, strchrW(endpoint, '}') + 2);
852
853 mon = check_display_name(parser, buffer);
854
855 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
856 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
857
858 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
859 }
860 ok(hr == S_OK, "Read failed: %#x\n", hr);
861
862 ok(!strncmpW(caps.szPname, V_BSTR(&var), lstrlenW(caps.szPname)), "expected %s, got %s\n",
863 wine_dbgstr_w(caps.szPname), wine_dbgstr_w(V_BSTR(&var)));
864
865 VariantClear(&var);
866 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
867 ok(hr == S_OK, "Read failed: %#x\n", hr);
868
869 StringFromGUID2(&CLSID_AudioRecord, buffer, CHARS_IN_GUID);
870 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
871 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
872
873 VariantClear(&var);
874 hr = IPropertyBag_Read(prop_bag, waveinidW, &var, NULL);
875 ok(hr == S_OK, "Read failed: %#x\n", hr);
876
877 ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var));
878
879 IPropertyBag_Release(prop_bag);
880 IMoniker_Release(mon);
881 }
882
883 IParseDisplayName_Release(parser);
884 }
885
test_midiout(void)886 static void test_midiout(void)
887 {
888 static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','M','i','d','i','O','u','t',' ','D','e','v','i','c','e',0};
889 static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0};
890 IParseDisplayName *parser;
891 IPropertyBag *prop_bag;
892 IMoniker *mon;
893 MIDIOUTCAPSW caps;
894 WCHAR buffer[200];
895 const WCHAR *name;
896 int count, i;
897 VARIANT var;
898 HRESULT hr;
899
900 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
901 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
902
903 count = midiOutGetNumDevs();
904
905 for (i = -1; i < count; i++)
906 {
907 midiOutGetDevCapsW(i, &caps, sizeof(caps));
908
909 if (i == -1) /* MIDI_MAPPER */
910 name = defaultW;
911 else
912 name = caps.szPname;
913
914 lstrcpyW(buffer, deviceW);
915 lstrcatW(buffer, cmW);
916 StringFromGUID2(&CLSID_MidiRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
917 lstrcatW(buffer, backslashW);
918 lstrcatW(buffer, name);
919
920 mon = check_display_name(parser, buffer);
921
922 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
923 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
924
925 VariantInit(&var);
926 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
927 ok(hr == S_OK, "Read failed: %#x\n", hr);
928
929 ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
930 wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var)));
931
932 VariantClear(&var);
933 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
934 ok(hr == S_OK, "Read failed: %#x\n", hr);
935
936 StringFromGUID2(&CLSID_AVIMIDIRender, buffer, CHARS_IN_GUID);
937 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
938 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
939
940 VariantClear(&var);
941 hr = IPropertyBag_Read(prop_bag, midioutidW, &var, NULL);
942 ok(hr == S_OK, "Read failed: %#x\n", hr);
943
944 ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var));
945
946 IPropertyBag_Release(prop_bag);
947 IMoniker_Release(mon);
948 }
949
950 IParseDisplayName_Release(parser);
951 }
952
test_vfw(void)953 static void test_vfw(void)
954 {
955 static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
956 IParseDisplayName *parser;
957 IPropertyBag *prop_bag;
958 IMoniker *mon;
959 WCHAR buffer[200];
960 ICINFO info;
961 VARIANT var;
962 HRESULT hr;
963 int i = 0;
964 HIC hic;
965
966 if (broken(sizeof(void *) == 8))
967 {
968 win_skip("VFW codecs are not enumerated on 64-bit Windows\n");
969 return;
970 }
971
972 hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
973 ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
974
975 while (ICInfo(ICTYPE_VIDEO, i++, &info))
976 {
977 WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)), HIBYTE(LOWORD(info.fccHandler)),
978 LOBYTE(HIWORD(info.fccHandler)), HIBYTE(HIWORD(info.fccHandler))};
979
980 hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY);
981 ICGetInfo(hic, &info, sizeof(info));
982 ICClose(hic);
983
984 lstrcpyW(buffer, deviceW);
985 lstrcatW(buffer, cmW);
986 StringFromGUID2(&CLSID_VideoCompressorCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
987 lstrcatW(buffer, backslashW);
988 lstrcatW(buffer, name);
989
990 mon = check_display_name(parser, buffer);
991
992 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
993 ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
994
995 VariantInit(&var);
996 hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
997 ok(hr == S_OK, "Read failed: %#x\n", hr);
998
999 ok(!lstrcmpW(info.szDescription, V_BSTR(&var)), "expected %s, got %s\n",
1000 wine_dbgstr_w(info.szDescription), wine_dbgstr_w(V_BSTR(&var)));
1001
1002 VariantClear(&var);
1003 hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
1004 ok(hr == S_OK, "Read failed: %#x\n", hr);
1005
1006 StringFromGUID2(&CLSID_AVICo, buffer, CHARS_IN_GUID);
1007 ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
1008 wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
1009
1010 VariantClear(&var);
1011 hr = IPropertyBag_Read(prop_bag, fcchandlerW, &var, NULL);
1012 ok(hr == S_OK, "Read failed: %#x\n", hr);
1013 ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
1014 wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var)));
1015
1016 VariantClear(&var);
1017 IPropertyBag_Release(prop_bag);
1018 IMoniker_Release(mon);
1019 }
1020
1021 IParseDisplayName_Release(parser);
1022 }
1023
START_TEST(devenum)1024 START_TEST(devenum)
1025 {
1026 IBindCtx *bind_ctx = NULL;
1027 HRESULT hr;
1028
1029 CoInitialize(NULL);
1030
1031 test_devenum(NULL);
1032
1033 /* IBindCtx is allowed in IMoniker_BindToStorage (IMediaCatMoniker_BindToStorage) */
1034 hr = CreateBindCtx(0, &bind_ctx);
1035 ok(hr == S_OK, "Cannot create BindCtx: (res = 0x%x)\n", hr);
1036 if (bind_ctx) {
1037 test_devenum(bind_ctx);
1038 IBindCtx_Release(bind_ctx);
1039 }
1040
1041 test_moniker_isequal();
1042 test_register_filter();
1043 test_directshow_filter();
1044 test_codec();
1045 test_dmo();
1046
1047 test_legacy_filter();
1048 hr = DirectSoundEnumerateW(test_dsound, NULL);
1049 ok(hr == S_OK, "got %#x\n", hr);
1050 test_waveout();
1051 test_wavein();
1052 test_midiout();
1053 test_vfw();
1054
1055 CoUninitialize();
1056 }
1057