Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/devenum/createdevenum.c | 130 ++++++++++++++++++++++--------------------- dlls/devenum/tests/devenum.c | 87 +++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 63 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c index e3fe049..9be34d7 100644 --- a/dlls/devenum/createdevenum.c +++ b/dlls/devenum/createdevenum.c @@ -673,6 +673,72 @@ cleanup: } }
+static void register_wavein_devices(void) +{ + static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0}; + IPropertyBag *prop_bag = NULL; + REGFILTER2 rgf = {0}; + WCHAR clsid[CHARS_IN_GUID]; + IMoniker *mon = NULL; + WAVEINCAPSW caps; + int i, count; + VARIANT var; + HRESULT hr; + + hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); + if (FAILED(hr)) return; + + count = waveInGetNumDevs(); + + for (i = 0; i < count; i++) + { + waveInGetDevCapsW(i, &caps, sizeof(caps)); + + V_VT(&var) = VT_BSTR; + + V_BSTR(&var) = SysAllocString(caps.szPname); + if (!(V_BSTR(&var))) + goto cleanup; + + hr = register_codec(&CLSID_AudioInputDeviceCategory, V_BSTR(&var), &mon); + if (FAILED(hr)) goto cleanup; + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + if (FAILED(hr)) goto cleanup; + + /* write friendly name */ + hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write clsid */ + V_VT(&var) = VT_BSTR; + StringFromGUID2(&CLSID_AudioRecord, clsid, CHARS_IN_GUID); + if (!(V_BSTR(&var) = SysAllocString(clsid))) + goto cleanup; + hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var); + if (FAILED(hr)) goto cleanup; + VariantClear(&var); + + /* write filter data */ + rgf.dwVersion = 2; + rgf.dwMerit = MERIT_DO_NOT_USE; + + write_filter_data(prop_bag, &rgf); + + /* write WaveInId */ + V_VT(&var) = VT_I4; + V_I4(&var) = i; + hr = IPropertyBag_Write(prop_bag, waveinidW, &var); + if (FAILED(hr)) goto cleanup; + +cleanup: + VariantClear(&var); + if (prop_bag) IPropertyBag_Release(prop_bag); + if (mon) IMoniker_Release(mon); + } +} + /********************************************************************** * DEVENUM_ICreateDevEnum_CreateClassEnumerator */ @@ -696,6 +762,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL); if (FAILED(hr)) return hr; register_waveout_devices(); + register_wavein_devices();
return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker); } @@ -832,73 +899,10 @@ static HRESULT register_codecs(void) if (SUCCEEDED(res)) { UINT i; - WAVEINCAPSW wicaps; MIDIOUTCAPSW mocaps; REGPINTYPES * pTypes; IPropertyBag * pPropBag = NULL;
- numDevs = waveInGetNumDevs(); - - res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory); - if (FAILED(res)) /* can't register any devices in this category */ - numDevs = 0; - - rfp2.dwFlags = REG_PINFLAG_B_OUTPUT; - for (i = 0; i < numDevs; i++) - { - if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW)) - == MMSYSERR_NOERROR) - { - IMoniker * pMoniker = NULL; - - rfp2.nMediaTypes = 1; - pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); - if (!pTypes) - { - IFilterMapper2_Release(pMapper); - return E_OUTOFMEMORY; - } - - /* FIXME: Not sure if these are correct */ - pTypes[0].clsMajorType = &MEDIATYPE_Audio; - pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; - - rfp2.lpMediaType = pTypes; - - res = IFilterMapper2_RegisterFilter(pMapper, - &CLSID_AudioRecord, - wicaps.szPname, - &pMoniker, - &CLSID_AudioInputDeviceCategory, - wicaps.szPname, - &rf2); - - - if (pMoniker) { - VARIANT var; - - V_VT(&var) = VT_I4; - V_I4(&var) = i; - res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); - if (SUCCEEDED(res)) - res = IPropertyBag_Write(pPropBag, wszWaveInID, &var); - else - pPropBag = NULL; - - V_VT(&var) = VT_LPWSTR; - V_BSTR(&var) = wicaps.szPname; - if (SUCCEEDED(res)) - res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var); - - if (pPropBag) - IPropertyBag_Release(pPropBag); - IMoniker_Release(pMoniker); - } - - CoTaskMemFree(pTypes); - } - } - numDevs = midiOutGetNumDevs();
res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory); diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c index 79f5ed8..3f66237 100644 --- a/dlls/devenum/tests/devenum.c +++ b/dlls/devenum/tests/devenum.c @@ -726,6 +726,92 @@ static void test_waveout(void) IParseDisplayName_Release(parser); }
+static void test_wavein(void) +{ + static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0}; + IParseDisplayName *parser; + IPropertyBag *prop_bag; + IMoniker *mon; + WCHAR endpoint[200]; + WCHAR buffer[200]; + WAVEINCAPSW caps; + MMRESULT mmr; + int count, i; + VARIANT var; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser); + ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr); + + count = waveInGetNumDevs(); + + for (i = 0; i < count; i++) + { + waveInGetDevCapsW(i, &caps, sizeof(caps)); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, caps.szPname); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + VariantInit(&var); + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + + /* Win8+ uses the endpoint GUID instead of the device name */ + mmr = waveInMessage((HWAVEIN)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID, + (DWORD_PTR) endpoint, sizeof(endpoint)); + ok(!mmr, "waveInMessage failed: %u\n", mmr); + + lstrcpyW(buffer, deviceW); + lstrcatW(buffer, cmW); + StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID); + lstrcatW(buffer, backslashW); + lstrcatW(buffer, waveW); + lstrcatW(buffer, strchrW(endpoint, '}') + 2); + + mon = check_display_name(parser, buffer); + + hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag); + ok(hr == S_OK, "BindToStorage failed: %#x\n", hr); + + hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL); + } + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(!strncmpW(caps.szPname, V_BSTR(&var), lstrlenW(caps.szPname)), "expected %s, got %s\n", + wine_dbgstr_w(caps.szPname), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + StringFromGUID2(&CLSID_AudioRecord, buffer, CHARS_IN_GUID); + ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n", + wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var))); + + VariantClear(&var); + hr = IPropertyBag_Read(prop_bag, waveinidW, &var, NULL); + ok(hr == S_OK, "Read failed: %#x\n", hr); + + ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var)); + + IPropertyBag_Release(prop_bag); + IMoniker_Release(mon); + } + + IParseDisplayName_Release(parser); +} + START_TEST(devenum) { IBindCtx *bind_ctx = NULL; @@ -752,6 +838,7 @@ START_TEST(devenum) hr = DirectSoundEnumerateW(test_dsound, NULL); ok(hr == S_OK, "got %#x\n", hr); test_waveout(); + test_wavein();
CoUninitialize(); }