2 * Some unit tests for devenum
4 * Copyright (C) 2012 Christian Costa
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
25 #include "wine/test.h"
35 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
37 static const WCHAR friendly_name
[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
38 static const WCHAR fcc_handlerW
[] = {'F','c','c','H','a','n','d','l','e','r',0};
39 static const WCHAR deviceW
[] = {'@','d','e','v','i','c','e',':',0};
40 static const WCHAR clsidW
[] = {'C','L','S','I','D',0};
41 static const WCHAR waveW
[] = {'w','a','v','e',':',0};
42 static const WCHAR mrleW
[] = {'m','r','l','e',0};
43 static const WCHAR swW
[] = {'s','w',':',0};
44 static const WCHAR cmW
[] = {'c','m',':',0};
45 static const WCHAR backslashW
[] = {'\\',0};
47 static inline WCHAR
*strchrW( const WCHAR
*str
, WCHAR ch
)
49 do { if (*str
== ch
) return (WCHAR
*)str
; } while (*str
++);
53 static inline int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
56 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
60 static void test_devenum(IBindCtx
*bind_ctx
)
62 IEnumMoniker
*enum_cat
, *enum_moniker
;
63 ICreateDevEnum
* create_devenum
;
64 IPropertyBag
*prop_bag
;
66 BOOL have_mrle
= FALSE
;
71 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
,
72 &IID_ICreateDevEnum
, (LPVOID
*)&create_devenum
);
73 ok(hr
== S_OK
, "Failed to create devenum: %#x\n", hr
);
75 hr
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &CLSID_ActiveMovieCategories
, &enum_cat
, 0);
76 ok(hr
== S_OK
, "Failed to enum categories: %#x\n", hr
);
78 while (IEnumMoniker_Next(enum_cat
, 1, &moniker
, NULL
) == S_OK
)
80 hr
= IMoniker_BindToStorage(moniker
, bind_ctx
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
81 ok(hr
== S_OK
, "IMoniker_BindToStorage failed: %#x\n", hr
);
84 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
85 ok(hr
== S_OK
, "Failed to read FriendlyName: %#x\n", hr
);
87 if (winetest_debug
> 1)
88 trace("%s:\n", wine_dbgstr_w(V_BSTR(&var
)));
91 hr
= IPropertyBag_Read(prop_bag
, clsidW
, &var
, NULL
);
92 ok(hr
== S_OK
, "Failed to read CLSID: %#x\n", hr
);
94 hr
= CLSIDFromString(V_BSTR(&var
), &cat_guid
);
95 ok(hr
== S_OK
, "got %#x\n", hr
);
97 IPropertyBag_Release(prop_bag
);
98 IMoniker_Release(moniker
);
100 hr
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &cat_guid
, &enum_moniker
, 0);
101 ok(SUCCEEDED(hr
), "Failed to enum devices: %#x\n", hr
);
105 while (IEnumMoniker_Next(enum_moniker
, 1, &moniker
, NULL
) == S_OK
)
107 hr
= IMoniker_GetClassID(moniker
, NULL
);
108 ok(hr
== E_INVALIDARG
, "IMoniker_GetClassID should failed %x\n", hr
);
110 hr
= IMoniker_GetClassID(moniker
, &clsid
);
111 ok(hr
== S_OK
, "IMoniker_GetClassID failed with error %x\n", hr
);
112 ok(IsEqualGUID(&clsid
, &CLSID_CDeviceMoniker
),
113 "Expected CLSID_CDeviceMoniker got %s\n", wine_dbgstr_guid(&clsid
));
116 hr
= IMoniker_BindToStorage(moniker
, bind_ctx
, NULL
, &IID_IPropertyBag
, (LPVOID
*)&prop_bag
);
117 ok(hr
== S_OK
, "IMoniker_BindToStorage failed with error %x\n", hr
);
119 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
120 ok(hr
== S_OK
, "IPropertyBag_Read failed: %#x\n", hr
);
122 if (winetest_debug
> 1)
123 trace(" %s\n", wine_dbgstr_w(V_BSTR(&var
)));
125 if (IsEqualGUID(&CLSID_VideoCompressorCategory
, &cat_guid
)) {
126 /* Test well known compressor to ensure that we really enumerate codecs */
127 hr
= IPropertyBag_Read(prop_bag
, fcc_handlerW
, &var
, NULL
);
129 ok(V_VT(&var
) == VT_BSTR
, "V_VT(var) = %d\n", V_VT(&var
));
130 if(!lstrcmpW(V_BSTR(&var
), mrleW
))
136 IPropertyBag_Release(prop_bag
);
137 IMoniker_Release(moniker
);
139 IEnumMoniker_Release(enum_moniker
);
143 ICreateDevEnum_Release(create_devenum
);
145 /* 64-bit windows are missing mrle codec */
146 if(sizeof(void*) == 4)
147 ok(have_mrle
, "mrle codec not found\n");
149 static void test_moniker_isequal(void)
152 ICreateDevEnum
*create_devenum
= NULL
;
153 IEnumMoniker
*enum_moniker0
= NULL
, *enum_moniker1
= NULL
;
154 IMoniker
*moniker0
= NULL
, *moniker1
= NULL
;
156 res
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
,
157 &IID_ICreateDevEnum
, (LPVOID
*)&create_devenum
);
160 skip("Cannot create SystemDeviceEnum object (%x)\n", res
);
164 res
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &CLSID_LegacyAmFilterCategory
, &enum_moniker0
, 0);
165 ok(SUCCEEDED(res
), "Cannot create enum moniker (res = %x)\n", res
);
168 if (IEnumMoniker_Next(enum_moniker0
, 1, &moniker0
, NULL
) == S_OK
&&
169 IEnumMoniker_Next(enum_moniker0
, 1, &moniker1
, NULL
) == S_OK
)
171 res
= IMoniker_IsEqual(moniker0
, moniker1
);
172 ok(res
== S_FALSE
, "IMoniker_IsEqual should fail (res = %x)\n", res
);
174 res
= IMoniker_IsEqual(moniker1
, moniker0
);
175 ok(res
== S_FALSE
, "IMoniker_IsEqual should fail (res = %x)\n", res
);
177 IMoniker_Release(moniker0
);
178 IMoniker_Release(moniker1
);
181 skip("Cannot get moniker for testing.\n");
183 IEnumMoniker_Release(enum_moniker0
);
185 res
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &CLSID_LegacyAmFilterCategory
, &enum_moniker0
, 0);
186 ok(SUCCEEDED(res
), "Cannot create enum moniker (res = %x)\n", res
);
187 res
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &CLSID_AudioRendererCategory
, &enum_moniker1
, 0);
188 ok(SUCCEEDED(res
), "Cannot create enum moniker (res = %x)\n", res
);
191 if (IEnumMoniker_Next(enum_moniker0
, 1, &moniker0
, NULL
) == S_OK
&&
192 IEnumMoniker_Next(enum_moniker1
, 1, &moniker1
, NULL
) == S_OK
)
194 res
= IMoniker_IsEqual(moniker0
, moniker1
);
195 ok(res
== S_FALSE
, "IMoniker_IsEqual should failed (res = %x)\n", res
);
197 res
= IMoniker_IsEqual(moniker1
, moniker0
);
198 ok(res
== S_FALSE
, "IMoniker_IsEqual should failed (res = %x)\n", res
);
200 IMoniker_Release(moniker0
);
201 IMoniker_Release(moniker1
);
204 skip("Cannot get moniker for testing.\n");
206 IEnumMoniker_Release(enum_moniker0
);
207 IEnumMoniker_Release(enum_moniker1
);
209 res
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &CLSID_LegacyAmFilterCategory
, &enum_moniker0
, 0);
210 ok(SUCCEEDED(res
), "Cannot create enum moniker (res = %x)\n", res
);
211 res
= ICreateDevEnum_CreateClassEnumerator(create_devenum
, &CLSID_LegacyAmFilterCategory
, &enum_moniker1
, 0);
212 ok(SUCCEEDED(res
), "Cannot create enum moniker (res = %x)\n", res
);
215 if (IEnumMoniker_Next(enum_moniker0
, 1, &moniker0
, NULL
) == S_OK
&&
216 IEnumMoniker_Next(enum_moniker1
, 1, &moniker1
, NULL
) == S_OK
)
218 res
= IMoniker_IsEqual(moniker0
, moniker1
);
219 ok(res
== S_OK
, "IMoniker_IsEqual failed (res = %x)\n", res
);
221 res
= IMoniker_IsEqual(moniker1
, moniker0
);
222 ok(res
== S_OK
, "IMoniker_IsEqual failed (res = %x)\n", res
);
224 IMoniker_Release(moniker0
);
225 IMoniker_Release(moniker1
);
228 skip("Cannot get moniker for testing.\n");
230 IEnumMoniker_Release(enum_moniker0
);
231 IEnumMoniker_Release(enum_moniker1
);
233 ICreateDevEnum_Release(create_devenum
);
238 static BOOL
find_moniker(const GUID
*class, IMoniker
*needle
)
240 ICreateDevEnum
*devenum
;
241 IEnumMoniker
*enum_mon
;
245 CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC
, &IID_ICreateDevEnum
, (void **)&devenum
);
246 ICreateDevEnum_CreateClassEnumerator(devenum
, class, &enum_mon
, 0);
247 while (!found
&& IEnumMoniker_Next(enum_mon
, 1, &mon
, NULL
) == S_OK
)
249 if (IMoniker_IsEqual(mon
, needle
) == S_OK
)
252 IMoniker_Release(mon
);
255 IEnumMoniker_Release(enum_mon
);
256 ICreateDevEnum_Release(devenum
);
260 DEFINE_GUID(CLSID_TestFilter
, 0xdeadbeef,0xcf51,0x43e6,0xb6,0xc5,0x29,0x9e,0xa8,0xb6,0xb5,0x91);
262 static void test_register_filter(void)
264 static const WCHAR name
[] = {'d','e','v','e','n','u','m',' ','t','e','s','t',0};
265 IFilterMapper2
*mapper2
;
266 IMoniker
*mon
= NULL
;
267 REGFILTER2 rgf2
= {0};
270 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC
, &IID_IFilterMapper2
, (void **)&mapper2
);
271 ok(hr
== S_OK
, "Failed to create FilterMapper2: %#x\n", hr
);
274 rgf2
.dwMerit
= MERIT_UNLIKELY
;
275 S2(U(rgf2
)).cPins2
= 0;
277 hr
= IFilterMapper2_RegisterFilter(mapper2
, &CLSID_TestFilter
, name
, &mon
, NULL
, NULL
, &rgf2
);
278 if (hr
== E_ACCESSDENIED
)
280 skip("Not enough permissions to register filters\n");
281 IFilterMapper2_Release(mapper2
);
284 ok(hr
== S_OK
, "RegisterFilter failed: %#x\n", hr
);
286 ok(find_moniker(&CLSID_LegacyAmFilterCategory
, mon
), "filter should be registered\n");
288 hr
= IFilterMapper2_UnregisterFilter(mapper2
, NULL
, NULL
, &CLSID_TestFilter
);
289 ok(hr
== S_OK
, "UnregisterFilter failed: %#x\n", hr
);
291 ok(!find_moniker(&CLSID_LegacyAmFilterCategory
, mon
), "filter should not be registered\n");
292 IMoniker_Release(mon
);
295 hr
= IFilterMapper2_RegisterFilter(mapper2
, &CLSID_TestFilter
, name
, &mon
, &CLSID_AudioRendererCategory
, NULL
, &rgf2
);
296 ok(hr
== S_OK
, "RegisterFilter failed: %#x\n", hr
);
298 ok(find_moniker(&CLSID_AudioRendererCategory
, mon
), "filter should be registered\n");
300 hr
= IFilterMapper2_UnregisterFilter(mapper2
, &CLSID_AudioRendererCategory
, NULL
, &CLSID_TestFilter
);
301 ok(hr
== S_OK
, "UnregisterFilter failed: %#x\n", hr
);
303 ok(!find_moniker(&CLSID_AudioRendererCategory
, mon
), "filter should not be registered\n");
304 IMoniker_Release(mon
);
306 IFilterMapper2_Release(mapper2
);
309 static IMoniker
*check_display_name_(int line
, IParseDisplayName
*parser
, WCHAR
*buffer
)
316 hr
= IParseDisplayName_ParseDisplayName(parser
, NULL
, buffer
, &eaten
, &mon
);
317 ok_(__FILE__
, line
)(hr
== S_OK
, "ParseDisplayName failed: %#x\n", hr
);
319 hr
= IMoniker_GetDisplayName(mon
, NULL
, NULL
, &str
);
320 ok_(__FILE__
, line
)(hr
== S_OK
, "GetDisplayName failed: %#x\n", hr
);
321 ok_(__FILE__
, line
)(!lstrcmpW(str
, buffer
), "got %s\n", wine_dbgstr_w(str
));
327 #define check_display_name(parser, buffer) check_display_name_(__LINE__, parser, buffer)
329 static void test_directshow_filter(void)
331 static const WCHAR instanceW
[] = {'\\','I','n','s','t','a','n','c','e',0};
332 static const WCHAR clsidW
[] = {'C','L','S','I','D','\\',0};
333 static WCHAR testW
[] = {'\\','t','e','s','t',0};
334 IParseDisplayName
*parser
;
335 IPropertyBag
*prop_bag
;
342 /* Test ParseDisplayName and GetDisplayName */
343 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
344 ok(hr
== S_OK
, "Failed to create ParseDisplayName: %#x\n", hr
);
346 lstrcpyW(buffer
, deviceW
);
347 lstrcatW(buffer
, swW
);
348 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
349 lstrcatW(buffer
, testW
);
350 mon
= check_display_name(parser
, buffer
);
352 /* Test writing and reading from the property bag */
353 ok(!find_moniker(&CLSID_AudioRendererCategory
, mon
), "filter should not be registered\n");
355 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
356 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
359 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
360 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got %#x\n", hr
);
362 /* writing causes the key to be created */
363 V_VT(&var
) = VT_BSTR
;
364 V_BSTR(&var
) = SysAllocString(testW
);
365 hr
= IPropertyBag_Write(prop_bag
, friendly_name
, &var
);
366 if (hr
!= E_ACCESSDENIED
)
368 ok(hr
== S_OK
, "Write failed: %#x\n", hr
);
370 ok(find_moniker(&CLSID_AudioRendererCategory
, mon
), "filter should be registered\n");
373 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
374 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
375 ok(!lstrcmpW(V_BSTR(&var
), testW
), "got %s\n", wine_dbgstr_w(V_BSTR(&var
)));
377 IMoniker_Release(mon
);
379 /* devenum doesn't give us a way to unregister—we have to do that manually */
380 lstrcpyW(buffer
, clsidW
);
381 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
382 lstrcatW(buffer
, instanceW
);
383 lstrcatW(buffer
, testW
);
384 res
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, buffer
);
385 ok(!res
, "RegDeleteKey failed: %lu\n", res
);
389 IPropertyBag_Release(prop_bag
);
391 /* name can be anything */
393 lstrcpyW(buffer
, deviceW
);
394 lstrcatW(buffer
, swW
);
395 lstrcatW(buffer
, testW
+1);
396 mon
= check_display_name(parser
, buffer
);
398 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
399 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
402 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
403 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got %#x\n", hr
);
405 V_VT(&var
) = VT_BSTR
;
406 V_BSTR(&var
) = SysAllocString(testW
);
407 hr
= IPropertyBag_Write(prop_bag
, friendly_name
, &var
);
408 if (hr
!= E_ACCESSDENIED
)
410 ok(hr
== S_OK
, "Write failed: %#x\n", hr
);
413 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
414 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
415 ok(!lstrcmpW(V_BSTR(&var
), testW
), "got %s\n", wine_dbgstr_w(V_BSTR(&var
)));
417 IMoniker_Release(mon
);
419 /* vista+ stores it inside the Instance key */
420 RegDeleteKeyA(HKEY_CLASSES_ROOT
, "CLSID\\test\\Instance");
422 res
= RegDeleteKeyA(HKEY_CLASSES_ROOT
, "CLSID\\test");
423 ok(!res
, "RegDeleteKey failed: %lu\n", res
);
427 IPropertyBag_Release(prop_bag
);
428 IParseDisplayName_Release(parser
);
431 static void test_codec(void)
433 static WCHAR testW
[] = {'\\','t','e','s','t',0};
434 IParseDisplayName
*parser
;
435 IPropertyBag
*prop_bag
;
441 /* Test ParseDisplayName and GetDisplayName */
442 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
443 ok(hr
== S_OK
, "Failed to create ParseDisplayName: %#x\n", hr
);
445 lstrcpyW(buffer
, deviceW
);
446 lstrcatW(buffer
, cmW
);
447 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
448 lstrcatW(buffer
, testW
);
449 mon
= check_display_name(parser
, buffer
);
451 /* Test writing and reading from the property bag */
452 ok(!find_moniker(&CLSID_AudioRendererCategory
, mon
), "codec should not be registered\n");
454 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
455 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
458 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
459 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got %#x\n", hr
);
461 V_VT(&var
) = VT_BSTR
;
462 V_BSTR(&var
) = SysAllocString(testW
);
463 hr
= IPropertyBag_Write(prop_bag
, friendly_name
, &var
);
464 ok(hr
== S_OK
, "Write failed: %#x\n", hr
);
467 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
468 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
469 ok(!lstrcmpW(V_BSTR(&var
), testW
), "got %s\n", wine_dbgstr_w(V_BSTR(&var
)));
471 /* unlike DirectShow filters, these are automatically generated, so
472 * enumerating them will destroy the key */
473 ok(!find_moniker(&CLSID_AudioRendererCategory
, mon
), "codec should not be registered\n");
475 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
476 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "got %#x\n", hr
);
478 IPropertyBag_Release(prop_bag
);
479 IMoniker_Release(mon
);
481 IParseDisplayName_Release(parser
);
484 static void test_legacy_filter(void)
486 static const WCHAR nameW
[] = {'t','e','s','t',0};
487 IParseDisplayName
*parser
;
488 IPropertyBag
*prop_bag
;
489 IFilterMapper
*mapper
;
495 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
496 ok(hr
== S_OK
, "Failed to create ParseDisplayName: %#x\n", hr
);
498 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC
, &IID_IFilterMapper
, (void **)&mapper
);
499 ok(hr
== S_OK
, "Failed to create FilterMapper: %#x\n", hr
);
501 hr
= IFilterMapper_RegisterFilter(mapper
, CLSID_TestFilter
, nameW
, 0xdeadbeef);
502 if (hr
== VFW_E_BAD_KEY
)
504 win_skip("not enough permissions to register filters\n");
507 ok(hr
== S_OK
, "RegisterFilter failed: %#x\n", hr
);
509 lstrcpyW(buffer
, deviceW
);
510 lstrcatW(buffer
, cmW
);
511 StringFromGUID2(&CLSID_LegacyAmFilterCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
512 lstrcatW(buffer
, backslashW
);
513 StringFromGUID2(&CLSID_TestFilter
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
515 mon
= check_display_name(parser
, buffer
);
516 ok(find_moniker(&CLSID_LegacyAmFilterCategory
, mon
), "filter should be registered\n");
518 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
519 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
522 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
523 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
525 StringFromGUID2(&CLSID_TestFilter
, buffer
, CHARS_IN_GUID
);
526 ok(!lstrcmpW(buffer
, V_BSTR(&var
)), "expected %s, got %s\n",
527 wine_dbgstr_w(buffer
), wine_dbgstr_w(V_BSTR(&var
)));
530 hr
= IPropertyBag_Read(prop_bag
, clsidW
, &var
, NULL
);
531 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
532 ok(!lstrcmpW(buffer
, V_BSTR(&var
)), "expected %s, got %s\n",
533 wine_dbgstr_w(buffer
), wine_dbgstr_w(V_BSTR(&var
)));
535 IPropertyBag_Release(prop_bag
);
537 hr
= IFilterMapper_UnregisterFilter(mapper
, CLSID_TestFilter
);
538 ok(hr
== S_OK
, "UnregisterFilter failed: %#x\n", hr
);
540 ok(!find_moniker(&CLSID_LegacyAmFilterCategory
, mon
), "filter should not be registered\n");
541 IMoniker_Release(mon
);
544 IFilterMapper_Release(mapper
);
545 IParseDisplayName_Release(parser
);
548 static BOOL CALLBACK
test_dsound(GUID
*guid
, const WCHAR
*desc
, const WCHAR
*module
, void *context
)
550 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};
551 static const WCHAR directsoundW
[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0};
552 static const WCHAR dsguidW
[] = {'D','S','G','u','i','d',0};
553 IParseDisplayName
*parser
;
554 IPropertyBag
*prop_bag
;
563 lstrcpyW(name
, directsoundW
);
564 lstrcatW(name
, desc
);
568 lstrcpyW(name
, defaultW
);
569 guid
= (GUID
*)&GUID_NULL
;
572 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
573 ok(hr
== S_OK
, "Failed to create ParseDisplayName: %#x\n", hr
);
575 lstrcpyW(buffer
, deviceW
);
576 lstrcatW(buffer
, cmW
);
577 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
578 lstrcatW(buffer
, backslashW
);
579 lstrcatW(buffer
, name
);
581 mon
= check_display_name(parser
, buffer
);
583 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
584 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
587 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
588 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
590 /* Win8+ uses the GUID instead of the device name */
591 IPropertyBag_Release(prop_bag
);
592 IMoniker_Release(mon
);
594 lstrcpyW(buffer
, deviceW
);
595 lstrcatW(buffer
, cmW
);
596 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
597 lstrcatW(buffer
, backslashW
);
598 lstrcatW(buffer
, directsoundW
);
599 StringFromGUID2(guid
, buffer
+ lstrlenW(buffer
) - 1, CHARS_IN_GUID
);
601 mon
= check_display_name(parser
, buffer
);
603 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
604 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
607 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
609 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
611 ok(!lstrcmpW(name
, V_BSTR(&var
)), "expected %s, got %s\n",
612 wine_dbgstr_w(name
), wine_dbgstr_w(V_BSTR(&var
)));
615 hr
= IPropertyBag_Read(prop_bag
, clsidW
, &var
, NULL
);
616 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
618 StringFromGUID2(&CLSID_DSoundRender
, buffer
, CHARS_IN_GUID
);
619 ok(!lstrcmpW(buffer
, V_BSTR(&var
)), "expected %s, got %s\n",
620 wine_dbgstr_w(buffer
), wine_dbgstr_w(V_BSTR(&var
)));
623 hr
= IPropertyBag_Read(prop_bag
, dsguidW
, &var
, NULL
);
624 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
626 StringFromGUID2(guid
, buffer
, CHARS_IN_GUID
);
627 ok(!lstrcmpW(buffer
, V_BSTR(&var
)), "expected %s, got %s\n",
628 wine_dbgstr_w(buffer
), wine_dbgstr_w(V_BSTR(&var
)));
630 IPropertyBag_Release(prop_bag
);
631 IMoniker_Release(mon
);
632 IParseDisplayName_Release(parser
);
636 static void test_waveout(void)
638 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};
639 static const WCHAR waveoutidW
[] = {'W','a','v','e','O','u','t','I','d',0};
640 IParseDisplayName
*parser
;
641 IPropertyBag
*prop_bag
;
652 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
653 ok(hr
== S_OK
, "Failed to create ParseDisplayName: %#x\n", hr
);
655 count
= waveOutGetNumDevs();
657 for (i
= -1; i
< count
; i
++)
659 waveOutGetDevCapsW(i
, &caps
, sizeof(caps
));
661 if (i
== -1) /* WAVE_MAPPER */
666 lstrcpyW(buffer
, deviceW
);
667 lstrcatW(buffer
, cmW
);
668 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
669 lstrcatW(buffer
, backslashW
);
670 lstrcatW(buffer
, name
);
672 mon
= check_display_name(parser
, buffer
);
674 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
675 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
678 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
679 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
681 IPropertyBag_Release(prop_bag
);
682 IMoniker_Release(mon
);
684 /* Win8+ uses the endpoint GUID instead of the device name */
685 mmr
= waveOutMessage((HWAVEOUT
)(DWORD_PTR
) i
, DRV_QUERYFUNCTIONINSTANCEID
,
686 (DWORD_PTR
) endpoint
, sizeof(endpoint
));
687 ok(!mmr
, "waveOutMessage failed: %u\n", mmr
);
689 lstrcpyW(buffer
, deviceW
);
690 lstrcatW(buffer
, cmW
);
691 StringFromGUID2(&CLSID_AudioRendererCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
692 lstrcatW(buffer
, backslashW
);
693 lstrcatW(buffer
, waveW
);
694 lstrcatW(buffer
, strchrW(endpoint
, '}') + 2);
696 mon
= check_display_name(parser
, buffer
);
698 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
699 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
701 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
703 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
705 ok(!strncmpW(name
, V_BSTR(&var
), lstrlenW(name
)), "expected %s, got %s\n",
706 wine_dbgstr_w(name
), wine_dbgstr_w(V_BSTR(&var
)));
709 hr
= IPropertyBag_Read(prop_bag
, clsidW
, &var
, NULL
);
710 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
712 StringFromGUID2(&CLSID_AudioRender
, buffer
, CHARS_IN_GUID
);
713 ok(!lstrcmpW(buffer
, V_BSTR(&var
)), "expected %s, got %s\n",
714 wine_dbgstr_w(buffer
), wine_dbgstr_w(V_BSTR(&var
)));
717 hr
= IPropertyBag_Read(prop_bag
, waveoutidW
, &var
, NULL
);
718 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
720 ok(V_I4(&var
) == i
, "expected %d, got %d\n", i
, V_I4(&var
));
722 IPropertyBag_Release(prop_bag
);
723 IMoniker_Release(mon
);
726 IParseDisplayName_Release(parser
);
729 static void test_wavein(void)
731 static const WCHAR waveinidW
[] = {'W','a','v','e','I','n','I','d',0};
732 IParseDisplayName
*parser
;
733 IPropertyBag
*prop_bag
;
743 hr
= CoCreateInstance(&CLSID_CDeviceMoniker
, NULL
, CLSCTX_INPROC
, &IID_IParseDisplayName
, (void **)&parser
);
744 ok(hr
== S_OK
, "Failed to create ParseDisplayName: %#x\n", hr
);
746 count
= waveInGetNumDevs();
748 for (i
= 0; i
< count
; i
++)
750 waveInGetDevCapsW(i
, &caps
, sizeof(caps
));
752 lstrcpyW(buffer
, deviceW
);
753 lstrcatW(buffer
, cmW
);
754 StringFromGUID2(&CLSID_AudioInputDeviceCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
755 lstrcatW(buffer
, backslashW
);
756 lstrcatW(buffer
, caps
.szPname
);
758 mon
= check_display_name(parser
, buffer
);
760 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
761 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
764 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
765 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
767 IPropertyBag_Release(prop_bag
);
768 IMoniker_Release(mon
);
770 /* Win8+ uses the endpoint GUID instead of the device name */
771 mmr
= waveInMessage((HWAVEIN
)(DWORD_PTR
) i
, DRV_QUERYFUNCTIONINSTANCEID
,
772 (DWORD_PTR
) endpoint
, sizeof(endpoint
));
773 ok(!mmr
, "waveInMessage failed: %u\n", mmr
);
775 lstrcpyW(buffer
, deviceW
);
776 lstrcatW(buffer
, cmW
);
777 StringFromGUID2(&CLSID_AudioInputDeviceCategory
, buffer
+ lstrlenW(buffer
), CHARS_IN_GUID
);
778 lstrcatW(buffer
, backslashW
);
779 lstrcatW(buffer
, waveW
);
780 lstrcatW(buffer
, strchrW(endpoint
, '}') + 2);
782 mon
= check_display_name(parser
, buffer
);
784 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&prop_bag
);
785 ok(hr
== S_OK
, "BindToStorage failed: %#x\n", hr
);
787 hr
= IPropertyBag_Read(prop_bag
, friendly_name
, &var
, NULL
);
789 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
791 ok(!strncmpW(caps
.szPname
, V_BSTR(&var
), lstrlenW(caps
.szPname
)), "expected %s, got %s\n",
792 wine_dbgstr_w(caps
.szPname
), wine_dbgstr_w(V_BSTR(&var
)));
795 hr
= IPropertyBag_Read(prop_bag
, clsidW
, &var
, NULL
);
796 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
798 StringFromGUID2(&CLSID_AudioRecord
, buffer
, CHARS_IN_GUID
);
799 ok(!lstrcmpW(buffer
, V_BSTR(&var
)), "expected %s, got %s\n",
800 wine_dbgstr_w(buffer
), wine_dbgstr_w(V_BSTR(&var
)));
803 hr
= IPropertyBag_Read(prop_bag
, waveinidW
, &var
, NULL
);
804 ok(hr
== S_OK
, "Read failed: %#x\n", hr
);
806 ok(V_I4(&var
) == i
, "expected %d, got %d\n", i
, V_I4(&var
));
808 IPropertyBag_Release(prop_bag
);
809 IMoniker_Release(mon
);
812 IParseDisplayName_Release(parser
);
817 IBindCtx
*bind_ctx
= NULL
;
824 /* IBindCtx is allowed in IMoniker_BindToStorage (IMediaCatMoniker_BindToStorage) */
825 hr
= CreateBindCtx(0, &bind_ctx
);
826 ok(hr
== S_OK
, "Cannot create BindCtx: (res = 0x%x)\n", hr
);
828 test_devenum(bind_ctx
);
829 IBindCtx_Release(bind_ctx
);
832 test_moniker_isequal();
833 test_register_filter();
834 test_directshow_filter();
837 test_legacy_filter();
838 hr
= DirectSoundEnumerateW(test_dsound
, NULL
);
839 ok(hr
== S_OK
, "got %#x\n", hr
);