Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2018
- 90 participants
- 1704 messages
[PATCH 4/4] devenum: Register VFW codecs as codec devices.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/createdevenum.c | 153 ++++++++++++++++++++++++-----------------
dlls/devenum/tests/Makefile.in | 2 +-
dlls/devenum/tests/devenum.c | 66 ++++++++++++++++++
3 files changed, 158 insertions(+), 63 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c
index 677336c..2427469 100644
--- a/dlls/devenum/createdevenum.c
+++ b/dlls/devenum/createdevenum.c
@@ -107,28 +107,6 @@ static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface)
return 1; /* non-heap based object */
}
-static HKEY open_special_category_key(const CLSID *clsid, BOOL create)
-{
- WCHAR key_name[sizeof(wszActiveMovieKey)/sizeof(WCHAR) + CHARS_IN_GUID-1];
- HKEY ret;
- LONG res;
-
- strcpyW(key_name, wszActiveMovieKey);
- if (!StringFromGUID2(clsid, key_name + sizeof(wszActiveMovieKey)/sizeof(WCHAR)-1, CHARS_IN_GUID))
- return NULL;
-
- if(create)
- res = RegCreateKeyW(HKEY_CURRENT_USER, key_name, &ret);
- else
- res = RegOpenKeyExW(HKEY_CURRENT_USER, key_name, 0, KEY_READ, &ret);
- if (res != ERROR_SUCCESS) {
- WARN("Could not open %s\n", debugstr_w(key_name));
- return NULL;
- }
-
- return ret;
-}
-
static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **ret)
{
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0};
@@ -818,6 +796,96 @@ cleanup:
}
}
+static void register_vfw_codecs(void)
+{
+ static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
+ REGFILTERPINS2 rgpins[2] = {0};
+ IPropertyBag *prop_bag = NULL;
+ REGPINTYPES rgtypes[2] = {0};
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ GUID typeguid;
+ ICINFO info;
+ VARIANT var;
+ HRESULT hr;
+ int i = 0;
+ HIC hic;
+
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
+
+ while (ICInfo(ICTYPE_VIDEO, i++, &info))
+ {
+ WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)), HIBYTE(LOWORD(info.fccHandler)),
+ LOBYTE(HIWORD(info.fccHandler)), HIBYTE(HIWORD(info.fccHandler))};
+
+ hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY);
+ ICGetInfo(hic, &info, sizeof(info));
+ ICClose(hic);
+
+ V_VT(&var) = VT_BSTR;
+
+ V_BSTR(&var) = SysAllocString(name);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_VideoCompressorCategory, 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 WaveInId */
+ hr = IPropertyBag_Write(prop_bag, fcchandlerW, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write friendly name */
+ V_VT(&var) = VT_BSTR;
+ if (!(V_BSTR(&var) = SysAllocString(info.szDescription)))
+ goto cleanup;
+
+ hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
+ if (FAILED(hr)) goto cleanup;
+ VariantClear(&var);
+
+ /* write clsid */
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(&CLSID_AVICo, 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;
+ rgf.u.s2.cPins2 = 2;
+ rgf.u.s2.rgPins2 = rgpins;
+ rgpins[0].dwFlags = 0;
+ rgpins[0].nMediaTypes = 1;
+ rgpins[0].lpMediaType = &rgtypes[0];
+ rgtypes[0].clsMajorType = &MEDIATYPE_Video;
+ typeguid = MEDIASUBTYPE_PCM;
+ typeguid.Data1 = info.fccHandler;
+ rgtypes[0].clsMinorType = &typeguid;
+ rgpins[1].dwFlags = REG_PINFLAG_B_OUTPUT;
+ rgpins[1].nMediaTypes = 1;
+ rgpins[1].lpMediaType = &rgtypes[1];
+ rgtypes[1].clsMajorType = &MEDIATYPE_Video;
+ rgtypes[1].clsMinorType = &GUID_NULL;
+
+ write_filter_data(prop_bag, &rgf);
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ }
+}
+
/**********************************************************************
* DEVENUM_ICreateDevEnum_CreateClassEnumerator
*/
@@ -843,6 +911,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
register_waveout_devices();
register_wavein_devices();
register_midiout_devices();
+ register_vfw_codecs();
return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
}
@@ -895,44 +964,6 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
return res;
}
-static void register_vfw_codecs(void)
-{
- WCHAR avico_clsid_str[CHARS_IN_GUID];
- HKEY basekey, key;
- ICINFO icinfo;
- DWORD i, res;
-
- static const WCHAR CLSIDW[] = {'C','L','S','I','D',0};
- static const WCHAR FccHandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
- static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
-
- StringFromGUID2(&CLSID_AVICo, avico_clsid_str, sizeof(avico_clsid_str)/sizeof(WCHAR));
-
- basekey = open_special_category_key(&CLSID_VideoCompressorCategory, TRUE);
- if(!basekey) {
- ERR("Could not create key\n");
- return;
- }
-
- for(i=0; ICInfo(FCC('v','i','d','c'), i, &icinfo); i++) {
- WCHAR fcc_str[5] = {LOBYTE(LOWORD(icinfo.fccHandler)), HIBYTE(LOWORD(icinfo.fccHandler)),
- LOBYTE(HIWORD(icinfo.fccHandler)), HIBYTE(HIWORD(icinfo.fccHandler))};
-
- res = RegCreateKeyW(basekey, fcc_str, &key);
- if(res != ERROR_SUCCESS)
- continue;
-
- RegSetValueExW(key, CLSIDW, 0, REG_SZ, (const BYTE*)avico_clsid_str, sizeof(avico_clsid_str));
- RegSetValueExW(key, FccHandlerW, 0, REG_SZ, (const BYTE*)fcc_str, sizeof(fcc_str));
- RegSetValueExW(key, FriendlyNameW, 0, REG_SZ, (const BYTE*)icinfo.szName, (strlenW(icinfo.szName)+1)*sizeof(WCHAR));
- /* FIXME: Set ClassManagerFlags and FilterData values */
-
- RegCloseKey(key);
- }
-
- RegCloseKey(basekey);
-}
-
static HRESULT register_codecs(void)
{
HRESULT res;
@@ -1038,7 +1069,5 @@ static HRESULT register_codecs(void)
if (pMapper)
IFilterMapper2_Release(pMapper);
- register_vfw_codecs();
-
return res;
}
diff --git a/dlls/devenum/tests/Makefile.in b/dlls/devenum/tests/Makefile.in
index a673f20..b268adf 100644
--- a/dlls/devenum/tests/Makefile.in
+++ b/dlls/devenum/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = devenum.dll
-IMPORTS = advapi32 dsound oleaut32 ole32 winmm
+IMPORTS = advapi32 dsound msvfw32 oleaut32 ole32 winmm
C_SRCS = \
devenum.c
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index d9ea5e9..0b295ce 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -31,6 +31,7 @@
#include "mmsystem.h"
#include "dsound.h"
#include "mmddk.h"
+#include "vfw.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
@@ -879,6 +880,70 @@ static void test_midiout(void)
IParseDisplayName_Release(parser);
}
+static void test_vfw(void)
+{
+ static const WCHAR fcchandlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
+ IParseDisplayName *parser;
+ IPropertyBag *prop_bag;
+ IMoniker *mon;
+ WCHAR buffer[200];
+ ICINFO info;
+ VARIANT var;
+ HRESULT hr;
+ int i = 0;
+ HIC hic;
+
+ hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
+ ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
+
+ while (ICInfo(ICTYPE_VIDEO, i++, &info))
+ {
+ WCHAR name[5] = {LOBYTE(LOWORD(info.fccHandler)), HIBYTE(LOWORD(info.fccHandler)),
+ LOBYTE(HIWORD(info.fccHandler)), HIBYTE(HIWORD(info.fccHandler))};
+
+ hic = ICOpen(ICTYPE_VIDEO, info.fccHandler, ICMODE_QUERY);
+ ICGetInfo(hic, &info, sizeof(info));
+ ICClose(hic);
+
+ lstrcpyW(buffer, deviceW);
+ lstrcatW(buffer, cmW);
+ StringFromGUID2(&CLSID_VideoCompressorCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ lstrcatW(buffer, backslashW);
+ lstrcatW(buffer, name);
+
+ 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);
+ ok(hr == S_OK, "Read failed: %#x\n", hr);
+
+ ok(!lstrcmpW(info.szDescription, V_BSTR(&var)), "expected %s, got %s\n",
+ wine_dbgstr_w(info.szDescription), 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_AVICo, 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, fcchandlerW, &var, NULL);
+ ok(hr == S_OK, "Read failed: %#x\n", hr);
+ ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
+ wine_dbgstr_w(name), wine_dbgstr_w(V_BSTR(&var)));
+
+ IPropertyBag_Release(prop_bag);
+ IMoniker_Release(mon);
+ }
+
+ IParseDisplayName_Release(parser);
+}
+
START_TEST(devenum)
{
IBindCtx *bind_ctx = NULL;
@@ -907,6 +972,7 @@ START_TEST(devenum)
test_waveout();
test_wavein();
test_midiout();
+ test_vfw();
CoUninitialize();
}
--
2.7.4
March 31, 2018
[PATCH 3/4] devenum: Register midiOut devices as codec devices.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/createdevenum.c | 132 +++++++++++++++++++++++++----------------
dlls/devenum/devenum.rc | 9 ---
dlls/devenum/devenum_private.h | 7 ---
dlls/devenum/tests/devenum.c | 68 +++++++++++++++++++++
4 files changed, 148 insertions(+), 68 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c
index 9be34d7..677336c 100644
--- a/dlls/devenum/createdevenum.c
+++ b/dlls/devenum/createdevenum.c
@@ -739,6 +739,85 @@ cleanup:
}
}
+static void register_midiout_devices(void)
+{
+ 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};
+ static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0};
+ IPropertyBag *prop_bag = NULL;
+ REGFILTERPINS2 rgpins = {0};
+ REGPINTYPES rgtypes = {0};
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ MIDIOUTCAPSW caps;
+ int i, count;
+ VARIANT var;
+ HRESULT hr;
+
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
+
+ count = midiOutGetNumDevs();
+
+ for (i = -1; i < count; i++)
+ {
+ midiOutGetDevCapsW(i, &caps, sizeof(caps));
+
+ V_VT(&var) = VT_BSTR;
+
+ if (i == -1) /* MIDI_MAPPER */
+ V_BSTR(&var) = SysAllocString(defaultW);
+ else
+ V_BSTR(&var) = SysAllocString(caps.szPname);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_MidiRendererCategory, 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_AVIMIDIRender, 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 = (i == -1) ? MERIT_PREFERRED : MERIT_DO_NOT_USE;
+ rgf.u.s2.cPins2 = 1;
+ rgf.u.s2.rgPins2 = &rgpins;
+ rgpins.dwFlags = REG_PINFLAG_B_RENDERER;
+ rgpins.nMediaTypes = 1;
+ rgpins.lpMediaType = &rgtypes;
+ rgtypes.clsMajorType = &MEDIATYPE_Midi;
+ rgtypes.clsMinorType = &MEDIASUBTYPE_NULL;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write MidiOutId */
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = i;
+ hr = IPropertyBag_Write(prop_bag, midioutidW, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ }
+}
+
/**********************************************************************
* DEVENUM_ICreateDevEnum_CreateClassEnumerator
*/
@@ -763,6 +842,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
if (FAILED(hr)) return hr;
register_waveout_devices();
register_wavein_devices();
+ register_midiout_devices();
return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
}
@@ -858,7 +938,6 @@ static HRESULT register_codecs(void)
HRESULT res;
WCHAR class[CHARS_IN_GUID];
DWORD iDefaultDevice = -1;
- UINT numDevs;
IFilterMapper2 * pMapper = NULL;
REGFILTER2 rf2;
REGFILTERPINS2 rfp2;
@@ -899,60 +978,9 @@ static HRESULT register_codecs(void)
if (SUCCEEDED(res))
{
UINT i;
- MIDIOUTCAPSW mocaps;
REGPINTYPES * pTypes;
IPropertyBag * pPropBag = NULL;
- numDevs = midiOutGetNumDevs();
-
- res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory);
- if (FAILED(res)) /* can't register any devices in this category */
- numDevs = 0;
-
- rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
- for (i = 0; i < numDevs; i++)
- {
- if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW))
- == 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_Midi;
- pTypes[0].clsMinorType = &MEDIASUBTYPE_None;
-
- rfp2.lpMediaType = pTypes;
-
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_AVIMIDIRender,
- mocaps.szPname,
- &pMoniker,
- &CLSID_MidiRendererCategory,
- mocaps.szPname,
- &rf2);
-
- /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
- /* Native version sets MidiOutId */
-
- if (pMoniker)
- IMoniker_Release(pMoniker);
-
- if (i == iDefaultDevice)
- {
- FIXME("Default device\n");
- }
-
- CoTaskMemFree(pTypes);
- }
- }
res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
if (SUCCEEDED(res))
for (i = 0; i < 10; i++)
diff --git a/dlls/devenum/devenum.rc b/dlls/devenum/devenum.rc
index 95e39d6..24da9b8 100644
--- a/dlls/devenum/devenum.rc
+++ b/dlls/devenum/devenum.rc
@@ -23,15 +23,6 @@
#include "winnls.h"
#include "devenum_private.h"
-#pragma makedep po
-
-LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
-
-STRINGTABLE
-{
- IDS_DEVENUM_MIDEFAULT "Default MidiOut Device"
-}
-
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define WINE_FILEDESCRIPTION_STR "Wine Device Enumerator Library"
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index c891083..d4e1141 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -97,10 +97,3 @@ static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
-
-/**********************************************************************
- * Resource IDs
- */
-#define IDS_DEVENUM_MIDEFAULT 10
-#define IDS_DEVENUM_KSDEFAULT 11
-#define IDS_DEVENUM_KS 12
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index 3f66237..d9ea5e9 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -812,6 +812,73 @@ static void test_wavein(void)
IParseDisplayName_Release(parser);
}
+static void test_midiout(void)
+{
+ 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};
+ static const WCHAR midioutidW[] = {'M','i','d','i','O','u','t','I','d',0};
+ IParseDisplayName *parser;
+ IPropertyBag *prop_bag;
+ IMoniker *mon;
+ MIDIOUTCAPSW caps;
+ WCHAR buffer[200];
+ const WCHAR *name;
+ 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 = midiOutGetNumDevs();
+
+ for (i = -1; i < count; i++)
+ {
+ midiOutGetDevCapsW(i, &caps, sizeof(caps));
+
+ if (i == -1) /* MIDI_MAPPER */
+ name = defaultW;
+ else
+ name = caps.szPname;
+
+ lstrcpyW(buffer, deviceW);
+ lstrcatW(buffer, cmW);
+ StringFromGUID2(&CLSID_MidiRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ lstrcatW(buffer, backslashW);
+ lstrcatW(buffer, name);
+
+ 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);
+ ok(hr == S_OK, "Read failed: %#x\n", hr);
+
+ ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
+ wine_dbgstr_w(name), 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_AVIMIDIRender, 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, midioutidW, &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;
@@ -839,6 +906,7 @@ START_TEST(devenum)
ok(hr == S_OK, "got %#x\n", hr);
test_waveout();
test_wavein();
+ test_midiout();
CoUninitialize();
}
--
2.7.4
March 31, 2018
[PATCH 2/4] devenum: Register waveIn devices as codec devices.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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();
}
--
2.7.4
March 31, 2018
[PATCH 1/4] devenum: Register waveOut devices as codec devices.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/devenum/createdevenum.c | 131 +++++++++++++++++++++++++----------------
dlls/devenum/devenum.rc | 1 -
dlls/devenum/devenum_private.h | 1 -
dlls/devenum/tests/Makefile.in | 2 +-
dlls/devenum/tests/devenum.c | 109 ++++++++++++++++++++++++++++++++++
5 files changed, 190 insertions(+), 54 deletions(-)
diff --git a/dlls/devenum/createdevenum.c b/dlls/devenum/createdevenum.c
index 6884ffc..e3fe049 100644
--- a/dlls/devenum/createdevenum.c
+++ b/dlls/devenum/createdevenum.c
@@ -594,6 +594,85 @@ cleanup:
return TRUE;
}
+static void register_waveout_devices(void)
+{
+ 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};
+ static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0};
+ IPropertyBag *prop_bag = NULL;
+ REGFILTERPINS2 rgpins = {0};
+ REGPINTYPES rgtypes = {0};
+ REGFILTER2 rgf = {0};
+ WCHAR clsid[CHARS_IN_GUID];
+ IMoniker *mon = NULL;
+ WAVEOUTCAPSW caps;
+ int i, count;
+ VARIANT var;
+ HRESULT hr;
+
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(hr)) return;
+
+ count = waveOutGetNumDevs();
+
+ for (i = -1; i < count; i++)
+ {
+ waveOutGetDevCapsW(i, &caps, sizeof(caps));
+
+ V_VT(&var) = VT_BSTR;
+
+ if (i == -1) /* WAVE_MAPPER */
+ V_BSTR(&var) = SysAllocString(defaultW);
+ else
+ V_BSTR(&var) = SysAllocString(caps.szPname);
+ if (!(V_BSTR(&var)))
+ goto cleanup;
+
+ hr = register_codec(&CLSID_AudioRendererCategory, 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_AudioRender, 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;
+ rgf.u.s2.cPins2 = 1;
+ rgf.u.s2.rgPins2 = &rgpins;
+ rgpins.dwFlags = REG_PINFLAG_B_RENDERER;
+ rgpins.nMediaTypes = 1;
+ rgpins.lpMediaType = &rgtypes;
+ rgtypes.clsMajorType = &MEDIATYPE_Audio;
+ rgtypes.clsMinorType = &MEDIASUBTYPE_NULL;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write WaveOutId */
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = i;
+ hr = IPropertyBag_Write(prop_bag, waveoutidW, &var);
+ if (FAILED(hr)) goto cleanup;
+
+cleanup:
+ VariantClear(&var);
+ if (prop_bag) IPropertyBag_Release(prop_bag);
+ if (mon) IMoniker_Release(mon);
+ }
+}
+
/**********************************************************************
* DEVENUM_ICreateDevEnum_CreateClassEnumerator
*/
@@ -616,6 +695,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
register_legacy_filters();
hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL);
if (FAILED(hr)) return hr;
+ register_waveout_devices();
return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
}
@@ -752,62 +832,11 @@ static HRESULT register_codecs(void)
if (SUCCEEDED(res))
{
UINT i;
- WAVEOUTCAPSW wocaps;
WAVEINCAPSW wicaps;
MIDIOUTCAPSW mocaps;
REGPINTYPES * pTypes;
IPropertyBag * pPropBag = NULL;
- numDevs = waveOutGetNumDevs();
-
- res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
- if (FAILED(res)) /* can't register any devices in this category */
- numDevs = 0;
-
- rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
- for (i = 0; i < numDevs; i++)
- {
- if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW))
- == MMSYSERR_NOERROR)
- {
- IMoniker * pMoniker = NULL;
-
- rfp2.nMediaTypes = 1;
- pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
- if (!pTypes)
- {
- IFilterMapper2_Release(pMapper);
- return E_OUTOFMEMORY;
- }
- /* FIXME: Native devenum seems to register a lot more types for
- * DSound than we do. Not sure what purpose they serve */
- pTypes[0].clsMajorType = &MEDIATYPE_Audio;
- pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
-
- rfp2.lpMediaType = pTypes;
-
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_AudioRender,
- wocaps.szPname,
- &pMoniker,
- &CLSID_AudioRendererCategory,
- wocaps.szPname,
- &rf2);
-
- /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
-
- if (pMoniker)
- IMoniker_Release(pMoniker);
-
- if (i == iDefaultDevice)
- {
- FIXME("Default device\n");
- }
-
- CoTaskMemFree(pTypes);
- }
- }
-
numDevs = waveInGetNumDevs();
res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory);
diff --git a/dlls/devenum/devenum.rc b/dlls/devenum/devenum.rc
index d9262e1..95e39d6 100644
--- a/dlls/devenum/devenum.rc
+++ b/dlls/devenum/devenum.rc
@@ -29,7 +29,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
{
- IDS_DEVENUM_WODEFAULT "Default WaveOut Device"
IDS_DEVENUM_MIDEFAULT "Default MidiOut Device"
}
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index 93147ad..c891083 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -101,7 +101,6 @@ extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
/**********************************************************************
* Resource IDs
*/
-#define IDS_DEVENUM_WODEFAULT 9
#define IDS_DEVENUM_MIDEFAULT 10
#define IDS_DEVENUM_KSDEFAULT 11
#define IDS_DEVENUM_KS 12
diff --git a/dlls/devenum/tests/Makefile.in b/dlls/devenum/tests/Makefile.in
index 028ba27..a673f20 100644
--- a/dlls/devenum/tests/Makefile.in
+++ b/dlls/devenum/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = devenum.dll
-IMPORTS = advapi32 dsound oleaut32 ole32
+IMPORTS = advapi32 dsound oleaut32 ole32 winmm
C_SRCS = \
devenum.c
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index c4bf8af..79f5ed8 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -30,6 +30,7 @@
#include "vfwmsgs.h"
#include "mmsystem.h"
#include "dsound.h"
+#include "mmddk.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
@@ -37,11 +38,25 @@ static const WCHAR friendly_name[] = {'F','r','i','e','n','d','l','y','N','a','m
static const WCHAR fcc_handlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
static const WCHAR clsidW[] = {'C','L','S','I','D',0};
+static const WCHAR waveW[] = {'w','a','v','e',':',0};
static const WCHAR mrleW[] = {'m','r','l','e',0};
static const WCHAR swW[] = {'s','w',':',0};
static const WCHAR cmW[] = {'c','m',':',0};
static const WCHAR backslashW[] = {'\\',0};
+static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
+{
+ do { if (*str == ch) return (WCHAR *)str; } while (*str++);
+ return NULL;
+}
+
+static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
+{
+ if (n <= 0) return 0;
+ while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
+ return *str1 - *str2;
+}
+
static void test_devenum(IBindCtx *bind_ctx)
{
IEnumMoniker *enum_cat, *enum_moniker;
@@ -618,6 +633,99 @@ static BOOL CALLBACK test_dsound(GUID *guid, const WCHAR *desc, const WCHAR *mod
return TRUE;
}
+static void test_waveout(void)
+{
+ 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};
+ static const WCHAR waveoutidW[] = {'W','a','v','e','O','u','t','I','d',0};
+ IParseDisplayName *parser;
+ IPropertyBag *prop_bag;
+ IMoniker *mon;
+ WCHAR endpoint[200];
+ WAVEOUTCAPSW caps;
+ WCHAR buffer[200];
+ const WCHAR *name;
+ 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 = waveOutGetNumDevs();
+
+ for (i = -1; i < count; i++)
+ {
+ waveOutGetDevCapsW(i, &caps, sizeof(caps));
+
+ if (i == -1) /* WAVE_MAPPER */
+ name = defaultW;
+ else
+ name = caps.szPname;
+
+ lstrcpyW(buffer, deviceW);
+ lstrcatW(buffer, cmW);
+ StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ lstrcatW(buffer, backslashW);
+ lstrcatW(buffer, name);
+
+ 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 = waveOutMessage((HWAVEOUT)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID,
+ (DWORD_PTR) endpoint, sizeof(endpoint));
+ ok(!mmr, "waveOutMessage failed: %u\n", mmr);
+
+ lstrcpyW(buffer, deviceW);
+ lstrcatW(buffer, cmW);
+ StringFromGUID2(&CLSID_AudioRendererCategory, 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(name, V_BSTR(&var), lstrlenW(name)), "expected %s, got %s\n",
+ wine_dbgstr_w(name), 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_AudioRender, 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, waveoutidW, &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;
@@ -643,6 +751,7 @@ START_TEST(devenum)
test_legacy_filter();
hr = DirectSoundEnumerateW(test_dsound, NULL);
ok(hr == S_OK, "got %#x\n", hr);
+ test_waveout();
CoUninitialize();
}
--
2.7.4
March 31, 2018
Re: [PATCH] oleaut32/typelib.c: fix cursor2 having the wrong type
by André Hentschel
Am 14.03.2018 um 07:00 schrieb Adeniyi Mayokun:
> From 275d93c9ab0f533fa70d698726afc8adaaefb664 Mon Sep 17 00:00:00 2001
> From: Adeniyi Mayokun <adeniyimayokun17(a)gmail.com <mailto:adeniyimayokun17(a)gmail.com>>
> Date: Wed, 14 Mar 2018 06:55:15 +0100
> Subject: [PATCH] oleaut32/typelib.c: fix cursor2 having the wrong type
>
> Signed-off-by: Adeniyi Mayokun <adeniyimayokun17(a)gmail>
> ---
> dlls/oleaut32/typelib.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
> index 1c00d715f4..247d383ff7 100644
> --- a/dlls/oleaut32/typelib.c
> +++ b/dlls/oleaut32/typelib.c
> @@ -4725,10 +4725,9 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
> if (!ref)
> {
> TLBImpLib *pImpLib, *pImpLibNext;
> - TLBRefType *ref_type;
> + TLBRefType *ref_type, *ref_type_next;
> TLBString *tlbstr, *tlbstr_next;
> TLBGuid *tlbguid, *tlbguid_next;
> - void *cursor2;
> int i;
>
> /* remove cache entry */
> @@ -4778,7 +4777,7 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
> heap_free(pImpLib);
> }
>
> - LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
> + LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
> {
> list_remove(&ref_type->entry);
> heap_free(ref_type);
> --
> 2.14.1
>
This is an existing patch, if you picked it from wine-staging or somewhere you should have mentioned the original author...
commit 0dde88202a97578ffd346ae24d904a4f89cfb9b9
Author: Nils Kuhnhenn <kuhnhenn.nils(a)gmail.com>
Date: Fri Jun 16 16:05:07 2017 +0200
oleaut32: Use variable with the correct type in LIST_FOR_EACH_ENTRY_SAFE macro.
March 31, 2018
Re: WineConf and sound recording
by Bas Weelinck
If I might offer a few suggestions,
>From the stories I've heard, Blender provides a good video editing suite
these days, which should include all the support needed for multiple
video and audio inputs and transitioning between them. Blender is also a
project with very active development and the aim of being part of a
production pipeline. The most obvious problem with Blender is overcoming
the learning curve.
And if we're talking live casting, OBS (open broadcaster software) is
used a lot now, in favor of proprietary solutions such as X-split even,
and should also handle multiple audio and video sources without problem
and can also do overlays.
Finally, perhaps the people behind FOSDEM might also offer some advice:
video(a)fosdem.org
Cheers,
Bas
On 2018年03月31日 15:33, Stefan Dösinger wrote:
>
>> Am 31.03.2018 um 09:43 schrieb Francois Gouget <fgouget(a)free.fr>:
>>
>> On Fri, 30 Mar 2018, Stefan Dösinger wrote:
>> [...]
>>> What would be highly welcome is help with editing the videos
>>> afterwards. If someone has the patience to create subtitles for
>>> everything we'd make life easier for non-native speakers.
>> What software do you use for the editing? Avidemux? With a pinch of
>> Audacity? What format do you use for the vidéo during editing?
> I used Cinelerra. It is horribly buggy, but it was the only software I could find that was able to work with multiple video (camera, slides) and audio (camera, phones) input streams and allowed me to mix and match between them. I generally kept the video in its original format, and had Cinelerra output motion jpeg with the lowest possible compression ratio and then compressed it into mp4 with VLC. Cinelerra's MP4 output produced ungodly huge files.
>
> In my search for video editing software Avidemux and Audacity did not come up. Avidemux looks rather simplistic, and I'm not sure if Audacity supports video.
>
> Adobe Premiere is a commercial solution I know of, but it has a rather steep price tag.
>
March 31, 2018
Re: WineConf and sound recording
by Stefan Dösinger
> Am 31.03.2018 um 09:43 schrieb Francois Gouget <fgouget(a)free.fr>:
>
> On Fri, 30 Mar 2018, Stefan Dösinger wrote:
> [...]
>> What would be highly welcome is help with editing the videos
>> afterwards. If someone has the patience to create subtitles for
>> everything we'd make life easier for non-native speakers.
>
> What software do you use for the editing? Avidemux? With a pinch of
> Audacity? What format do you use for the vidéo during editing?
I used Cinelerra. It is horribly buggy, but it was the only software I could find that was able to work with multiple video (camera, slides) and audio (camera, phones) input streams and allowed me to mix and match between them. I generally kept the video in its original format, and had Cinelerra output motion jpeg with the lowest possible compression ratio and then compressed it into mp4 with VLC. Cinelerra's MP4 output produced ungodly huge files.
In my search for video editing software Avidemux and Audacity did not come up. Avidemux looks rather simplistic, and I'm not sure if Audacity supports video.
Adobe Premiere is a commercial solution I know of, but it has a rather steep price tag.
March 31, 2018
[PATCH] msvcrt: Don't increment variables both in the loop header and body (clang)
by André Hentschel
Signed-off-by: André Hentschel <nerv(a)dawncrow.de>
---
dlls/msvcrt/mbcs.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/dlls/msvcrt/mbcs.c b/dlls/msvcrt/mbcs.c
index 7ca1906..430c2a6 100644
--- a/dlls/msvcrt/mbcs.c
+++ b/dlls/msvcrt/mbcs.c
@@ -2011,13 +2011,12 @@ MSVCRT_size_t CDECL _mbsspn(const unsigned char* string, const unsigned char* se
{
if (_ismbblead(*p))
{
- for (q = set; *q; q++)
+ for (q = set; *q; q += 2)
{
if (!q[1])
break;
if ((*p == *q) && (p[1] == q[1]))
break;
- q++;
}
if (!q[0] || !q[1]) break;
}
@@ -2043,13 +2042,12 @@ unsigned char* CDECL _mbsspnp(const unsigned char* string, const unsigned char*
{
if (_ismbblead(*p))
{
- for (q = set; *q; q++)
+ for (q = set; *q; q += 2)
{
if (!q[1])
break;
if ((*p == *q) && (p[1] == q[1]))
break;
- q++;
}
if (!q[0] || !q[1]) break;
}
--
2.7.4
March 31, 2018
[PATCH] ntdll: Throw exception if invalid handle is passed to NtClose and debugger enabled.
by Alistair Leslie-Hughes
From: Sebastian Lackner <sebastian(a)fds-team.de>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/ntdll/om.c | 26 ++++++++++++++++
dlls/ntdll/tests/exception.c | 71 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index febe5bd81d..0b56251348 100644
--- a/dlls/ntdll/om.c
+++ b/dlls/ntdll/om.c
@@ -38,6 +38,7 @@
#include "winternl.h"
#include "ntdll_misc.h"
#include "wine/server.h"
+#include "wine/exception.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -377,6 +378,12 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
return ret;
}
+static LONG WINAPI invalid_handle_exception_handler( EXCEPTION_POINTERS *eptr )
+{
+ EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
+ return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+
/* Everquest 2 / Pirates of the Burning Sea hooks NtClose, so we need a wrapper */
NTSTATUS close_handle( HANDLE handle )
{
@@ -390,6 +397,25 @@ NTSTATUS close_handle( HANDLE handle )
}
SERVER_END_REQ;
if (fd != -1) close( fd );
+
+ if (ret == STATUS_INVALID_HANDLE && handle && NtCurrentTeb()->Peb->BeingDebugged)
+ {
+ __TRY
+ {
+ EXCEPTION_RECORD record;
+ record.ExceptionCode = EXCEPTION_INVALID_HANDLE;
+ record.ExceptionFlags = 0;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = NULL;
+ record.NumberParameters = 0;
+ RtlRaiseException( &record );
+ }
+ __EXCEPT(invalid_handle_exception_handler)
+ {
+ }
+ __ENDTRY
+ }
+
return ret;
}
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index b3592e6e1e..64a23110a5 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -52,6 +52,7 @@ static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
+static NTSTATUS (WINAPI *pNtClose)(HANDLE);
#if defined(__x86_64__)
typedef struct
@@ -1091,6 +1092,16 @@ static void test_debugger(void)
if (stage == 10) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
}
+ else if (stage == 11 || stage == 12 || stage == 13)
+ {
+ ok(de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_INVALID_HANDLE,
+ "unexpected exception code %08x, expected %08x\n", de.u.Exception.ExceptionRecord.ExceptionCode,
+ EXCEPTION_INVALID_HANDLE);
+ ok(de.u.Exception.ExceptionRecord.NumberParameters == 0,
+ "unexpected number of parameters %d, expected 0\n", de.u.Exception.ExceptionRecord.NumberParameters);
+
+ if (stage == 12|| stage == 13) continuestatus = DBG_EXCEPTION_NOT_HANDLED;
+ }
else
ok(FALSE, "unexpected stage %x\n", stage);
@@ -2895,6 +2906,54 @@ static void test_breakpoint(DWORD numexc)
pRtlRemoveVectoredExceptionHandler(vectored_handler);
}
+static DWORD invalid_handle_exceptions;
+
+static LONG CALLBACK invalid_handle_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
+{
+ PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
+ trace("vect. handler %08x addr:%p\n", rec->ExceptionCode, rec->ExceptionAddress);
+
+ ok(rec->ExceptionCode == EXCEPTION_INVALID_HANDLE, "ExceptionCode is %08x instead of %08x\n",
+ rec->ExceptionCode, EXCEPTION_INVALID_HANDLE);
+ ok(rec->NumberParameters == 0, "ExceptionParameters is %d instead of 0\n", rec->NumberParameters);
+
+ invalid_handle_exceptions++;
+ return (rec->ExceptionCode == EXCEPTION_INVALID_HANDLE) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void test_closehandle(DWORD numexc, HANDLE handle)
+{
+ PVOID vectored_handler;
+ NTSTATUS status;
+ DWORD res;
+
+ if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
+ {
+ skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
+ return;
+ }
+
+ vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, &invalid_handle_vectored_handler);
+ ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
+
+ invalid_handle_exceptions = 0;
+ res = CloseHandle(handle);
+
+ ok(!res || (is_wow64 && res), "CloseHandle(%p) unexpectedly succeeded\n", handle);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error code %d instead of %d\n",
+ GetLastError(), ERROR_INVALID_HANDLE);
+ ok(invalid_handle_exceptions == numexc, "CloseHandle generated %d exceptions, expected %d\n",
+ invalid_handle_exceptions, numexc);
+
+ invalid_handle_exceptions = 0;
+ status = pNtClose(handle);
+ ok(status == STATUS_INVALID_HANDLE || (is_wow64 && status == 0), "NtClose(%p) returned status %08x\n", handle, status);
+ ok(invalid_handle_exceptions == numexc, "NtClose generated %d exceptions, expected %d\n",
+ invalid_handle_exceptions, numexc);
+
+ pRtlRemoveVectoredExceptionHandler(vectored_handler);
+}
+
static void test_vectored_continue_handler(void)
{
PVOID handler1, handler2;
@@ -2949,6 +3008,7 @@ START_TEST(exception)
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
+ pNtClose = (void *)GetProcAddress( hntdll, "NtClose" );
pRtlUnwind = (void *)GetProcAddress( hntdll, "RtlUnwind" );
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
pRtlCaptureContext = (void *)GetProcAddress( hntdll, "RtlCaptureContext" );
@@ -2997,6 +3057,7 @@ START_TEST(exception)
if (pRtlRaiseException)
{
test_stage = 1;
+
run_rtlraiseexception_test(0x12345);
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
@@ -3004,6 +3065,7 @@ START_TEST(exception)
run_rtlraiseexception_test(0x12345);
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
+
test_stage = 3;
test_outputdebugstring(0, FALSE);
test_stage = 4;
@@ -3020,6 +3082,12 @@ START_TEST(exception)
test_breakpoint(0);
test_stage = 10;
test_breakpoint(1);
+ test_stage = 11;
+ test_closehandle(0, (HANDLE)0xdeadbeef);
+ test_stage = 12;
+ test_closehandle(1, (HANDLE)0xdeadbeef);
+ test_stage = 13;
+ test_closehandle(0, 0); /* Special case. */
}
else
skip( "RtlRaiseException not found\n" );
@@ -3036,6 +3104,7 @@ START_TEST(exception)
test_ripevent(1);
test_debug_service(1);
test_breakpoint(1);
+ test_closehandle(0, (HANDLE)0xdeadbeef);
test_vectored_continue_handler();
test_debugger();
test_simd_exceptions();
@@ -3043,7 +3112,6 @@ START_TEST(exception)
test_dpe_exceptions();
test_prot_fault();
test_thread_context();
-
#elif defined(__x86_64__)
pRtlAddFunctionTable = (void *)GetProcAddress( hntdll,
"RtlAddFunctionTable" );
@@ -3069,6 +3137,7 @@ START_TEST(exception)
test_ripevent(1);
test_debug_service(1);
test_breakpoint(1);
+ test_closehandle(0, (HANDLE)0xdeadbeef);
test_vectored_continue_handler();
test_virtual_unwind();
test___C_specific_handler();
--
2.16.2
March 31, 2018
[PATCH 2/2] kernel32: improve stub for SetThreadUILanguage a bit
by Louis Lenders
For https://bugs.winehq.org/show_bug.cgi?id=44469
March 31, 2018