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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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