#include "dsound.h"
#include "wine/debug.h"
-#include "wine/unicode.h"
#include "wine/heap.h"
#include "mmddk.h"
#include "initguid.h"
-#include "fil_data.h"
+#include "wine/fil_data.h"
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
-extern HINSTANCE DEVENUM_hInstance;
-
static const WCHAR wszFilterKeyName[] = {'F','i','l','t','e','r',0};
static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};
static const WCHAR wszPins[] = {'P','i','n','s',0};
static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0};
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface);
-static HRESULT register_codecs(void);
static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory);
/**********************************************************************
return 1; /* non-heap based object */
}
-static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **ret)
+static HRESULT register_codec(const GUID *class, const WCHAR *name,
+ const GUID *clsid, const WCHAR *friendly_name, IPropertyBag **ret)
{
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':','c','m',':',0};
+ WCHAR guidstr[CHARS_IN_GUID];
IParseDisplayName *parser;
+ IPropertyBag *propbag;
+ IMoniker *mon;
WCHAR *buffer;
+ VARIANT var;
ULONG eaten;
HRESULT hr;
if (FAILED(hr))
return hr;
- buffer = heap_alloc((strlenW(deviceW) + CHARS_IN_GUID + strlenW(name) + 1) * sizeof(WCHAR));
+ buffer = heap_alloc((lstrlenW(deviceW) + CHARS_IN_GUID + lstrlenW(name) + 1) * sizeof(WCHAR));
if (!buffer)
{
IParseDisplayName_Release(parser);
return E_OUTOFMEMORY;
}
- strcpyW(buffer, deviceW);
- StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
- strcatW(buffer, backslashW);
- strcatW(buffer, name);
+ lstrcpyW(buffer, deviceW);
+ StringFromGUID2(class, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ lstrcatW(buffer, backslashW);
+ lstrcatW(buffer, name);
- hr = IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, ret);
+ IParseDisplayName_ParseDisplayName(parser, NULL, buffer, &eaten, &mon);
IParseDisplayName_Release(parser);
heap_free(buffer);
- return hr;
+
+ IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&propbag);
+ IMoniker_Release(mon);
+
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(friendly_name);
+ hr = IPropertyBag_Write(propbag, wszFriendlyName, &var);
+ VariantClear(&var);
+ if (FAILED(hr))
+ {
+ IPropertyBag_Release(propbag);
+ return hr;
+ }
+
+ V_VT(&var) = VT_BSTR;
+ StringFromGUID2(clsid, guidstr, ARRAY_SIZE(guidstr));
+ V_BSTR(&var) = SysAllocString(guidstr);
+ hr = IPropertyBag_Write(propbag, clsidW, &var);
+ VariantClear(&var);
+ if (FAILED(hr))
+ {
+ IPropertyBag_Release(propbag);
+ return hr;
+ }
+
+ *ret = propbag;
+ return S_OK;
}
static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin)
{
HKEY hkeyMajorType = NULL;
WCHAR wszMajorTypeName[64];
- DWORD cName = sizeof(wszMajorTypeName) / sizeof(WCHAR);
+ DWORD cName = ARRAY_SIZE(wszMajorTypeName);
DWORD dwMinorTypes, i1;
if (RegEnumKeyExW(hkeyTypes, i, wszMajorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
CLSID *clsMajorType = NULL, *clsMinorType = NULL;
HRESULT hr;
- cName = sizeof(wszMinorTypeName) / sizeof(WCHAR);
+ cName = ARRAY_SIZE(wszMinorTypeName);
if (RegEnumKeyExW(hkeyMajorType, i1, wszMinorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
clsMinorType = CoTaskMemAlloc(sizeof(CLSID));
{
HKEY hkeyPinKey = NULL;
WCHAR wszPinName[MAX_PATH];
- DWORD cName = sizeof(wszPinName) / sizeof(WCHAR);
+ DWORD cName = ARRAY_SIZE(wszPinName);
REGFILTERPINS2 *rgPin = &rgPins[rgf2->u.s2.cPins2];
DWORD value, size, Type;
LONG lRet;
static void write_filter_data(IPropertyBag *prop_bag, REGFILTER2 *rgf)
{
+ BYTE *data = NULL, *array;
IAMFilterData *fildata;
SAFEARRAYBOUND sabound;
- BYTE *data, *array;
VARIANT var;
ULONG size;
HRESULT hr;
for (i = 0; i < dwFilterSubkeys; i++)
{
WCHAR wszFilterSubkeyName[64];
- DWORD cName = sizeof(wszFilterSubkeyName) / sizeof(WCHAR);
+ DWORD cName = ARRAY_SIZE(wszFilterSubkeyName);
IPropertyBag *prop_bag = NULL;
WCHAR wszRegKey[MAX_PATH];
HKEY classkey = NULL;
- IMoniker *mon = NULL;
- VARIANT var;
REGFILTER2 rgf2;
DWORD Type, len;
+ GUID clsid;
if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
- strcpyW(wszRegKey, clsidW);
- strcatW(wszRegKey, wszFilterSubkeyName);
-
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS)
+ hr = CLSIDFromString(wszFilterSubkeyName, &clsid);
+ if (FAILED(hr))
continue;
- hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName, &mon);
- if (FAILED(hr)) goto cleanup;
+ lstrcpyW(wszRegKey, clsidW);
+ lstrcatW(wszRegKey, backslashW);
+ lstrcatW(wszRegKey, wszFilterSubkeyName);
- hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
- if (FAILED(hr)) goto cleanup;
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS)
+ continue;
- /* write friendly name */
len = 0;
- V_VT(&var) = VT_BSTR;
if (!RegQueryValueExW(classkey, NULL, NULL, &Type, NULL, &len))
{
WCHAR *friendlyname = heap_alloc(len);
if (!friendlyname)
- goto cleanup;
+ {
+ RegCloseKey(classkey);
+ continue;
+ }
RegQueryValueExW(classkey, NULL, NULL, &Type, (BYTE *)friendlyname, &len);
- V_BSTR(&var) = SysAllocStringLen(friendlyname, len/sizeof(WCHAR));
+
+ hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName,
+ &clsid, friendlyname, &prop_bag);
+
heap_free(friendlyname);
}
else
- V_BSTR(&var) = SysAllocString(wszFilterSubkeyName);
-
- if (!V_BSTR(&var))
- goto cleanup;
- hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
- if (FAILED(hr)) goto cleanup;
- VariantClear(&var);
-
- /* write clsid */
- V_VT(&var) = VT_BSTR;
- if (!(V_BSTR(&var) = SysAllocString(wszFilterSubkeyName)))
- goto cleanup;
- hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
- if (FAILED(hr)) goto cleanup;
- VariantClear(&var);
+ hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName,
+ &clsid, wszFilterSubkeyName, &prop_bag);
+ if (FAILED(hr))
+ {
+ RegCloseKey(classkey);
+ continue;
+ }
/* write filter data */
rgf2.dwMerit = MERIT_NORMAL;
write_filter_data(prop_bag, &rgf2);
-cleanup:
- if (prop_bag) IPropertyBag_Release(prop_bag);
- if (mon) IMoniker_Release(mon);
+ IPropertyBag_Release(prop_bag);
RegCloseKey(classkey);
- VariantClear(&var);
free_regfilter2(&rgf2);
}
}
REGPINTYPES rgtypes = {0};
REGFILTER2 rgf = {0};
WCHAR clsid[CHARS_IN_GUID];
- IMoniker *mon = NULL;
VARIANT var;
HRESULT hr;
hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
- if (FAILED(hr)) goto cleanup;
+ if (FAILED(hr))
+ return FALSE;
- V_VT(&var) = VT_BSTR;
if (guid)
{
- WCHAR *name = heap_alloc(sizeof(defaultW) + strlenW(desc) * sizeof(WCHAR));
+ WCHAR *name = heap_alloc(sizeof(defaultW) + lstrlenW(desc) * sizeof(WCHAR));
if (!name)
- goto cleanup;
- strcpyW(name, directsoundW);
- strcatW(name, desc);
+ return FALSE;
+ lstrcpyW(name, directsoundW);
+ lstrcatW(name, desc);
- V_BSTR(&var) = SysAllocString(name);
+ hr = register_codec(&CLSID_AudioRendererCategory, name,
+ &CLSID_DSoundRender, name, &prop_bag);
heap_free(name);
}
else
- V_BSTR(&var) = SysAllocString(defaultW);
-
- 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_DSoundRender, 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);
+ hr = register_codec(&CLSID_AudioRendererCategory, defaultW,
+ &CLSID_DSoundRender, defaultW, &prop_bag);
+ if (FAILED(hr))
+ return FALSE;
/* write filter data */
rgf.dwVersion = 2;
/* write DSound guid */
V_VT(&var) = VT_BSTR;
StringFromGUID2(guid ? guid : &GUID_NULL, clsid, CHARS_IN_GUID);
- if (!(V_BSTR(&var) = SysAllocString(clsid)))
- goto cleanup;
- hr = IPropertyBag_Write(prop_bag, dsguidW, &var);
- if (FAILED(hr)) goto cleanup;
+ if ((V_BSTR(&var) = SysAllocString(clsid)))
+ hr = IPropertyBag_Write(prop_bag, dsguidW, &var);
-cleanup:
VariantClear(&var);
- if (prop_bag) IPropertyBag_Release(prop_bag);
- if (mon) IMoniker_Release(mon);
-
+ IPropertyBag_Release(prop_bag);
return TRUE;
}
REGFILTERPINS2 rgpins = {0};
REGPINTYPES rgtypes = {0};
REGFILTER2 rgf = {0};
- WCHAR clsid[CHARS_IN_GUID];
- IMoniker *mon = NULL;
WAVEOUTCAPSW caps;
+ const WCHAR *name;
int i, count;
VARIANT var;
HRESULT hr;
{
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;
+ name = (i == -1) ? defaultW : caps.szPname;
- 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);
+ hr = register_codec(&CLSID_AudioRendererCategory, name,
+ &CLSID_AudioRender, name, &prop_bag);
+ if (FAILED(hr))
+ continue;
/* write filter data */
rgf.dwVersion = 2;
/* write WaveOutId */
V_VT(&var) = VT_I4;
V_I4(&var) = i;
- hr = IPropertyBag_Write(prop_bag, waveoutidW, &var);
- if (FAILED(hr)) goto cleanup;
+ IPropertyBag_Write(prop_bag, waveoutidW, &var);
-cleanup:
VariantClear(&var);
if (prop_bag) IPropertyBag_Release(prop_bag);
- if (mon) IMoniker_Release(mon);
}
}
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;
{
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);
+ hr = register_codec(&CLSID_AudioInputDeviceCategory, caps.szPname,
+ &CLSID_AudioRecord, caps.szPname, &prop_bag);
+ if (FAILED(hr))
+ continue;
/* write filter data */
rgf.dwVersion = 2;
/* write WaveInId */
V_VT(&var) = VT_I4;
V_I4(&var) = i;
- hr = IPropertyBag_Write(prop_bag, waveinidW, &var);
- if (FAILED(hr)) goto cleanup;
+ IPropertyBag_Write(prop_bag, waveinidW, &var);
-cleanup:
VariantClear(&var);
- if (prop_bag) IPropertyBag_Release(prop_bag);
- if (mon) IMoniker_Release(mon);
+ IPropertyBag_Release(prop_bag);
}
}
REGFILTERPINS2 rgpins = {0};
REGPINTYPES rgtypes = {0};
REGFILTER2 rgf = {0};
- WCHAR clsid[CHARS_IN_GUID];
- IMoniker *mon = NULL;
MIDIOUTCAPSW caps;
+ const WCHAR *name;
int i, count;
VARIANT var;
HRESULT hr;
{
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;
+ name = (i == -1) ? defaultW : caps.szPname;
- 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);
+ hr = register_codec(&CLSID_MidiRendererCategory, name,
+ &CLSID_AVIMIDIRender, name, &prop_bag);
+ if (FAILED(hr))
+ continue;
/* write filter data */
rgf.dwVersion = 2;
/* write MidiOutId */
V_VT(&var) = VT_I4;
V_I4(&var) = i;
- hr = IPropertyBag_Write(prop_bag, midioutidW, &var);
- if (FAILED(hr)) goto cleanup;
+ IPropertyBag_Write(prop_bag, midioutidW, &var);
-cleanup:
VariantClear(&var);
- if (prop_bag) IPropertyBag_Release(prop_bag);
- if (mon) IMoniker_Release(mon);
+ IPropertyBag_Release(prop_bag);
}
}
IPropertyBag *prop_bag = NULL;
REGPINTYPES rgtypes[2];
REGFILTER2 rgf;
- WCHAR clsid[CHARS_IN_GUID];
- IMoniker *mon = NULL;
GUID typeguid;
ICINFO info;
VARIANT var;
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);
+ hr = register_codec(&CLSID_VideoCompressorCategory, name,
+ &CLSID_AVICo, info.szDescription, &prop_bag);
+ if (FAILED(hr))
+ continue;
/* write filter data */
rgf.dwVersion = 2;
write_filter_data(prop_bag, &rgf);
-cleanup:
+ /* write WaveInId */
+ V_VT(&var) = VT_BSTR;
+ V_BSTR(&var) = SysAllocString(name);
+ IPropertyBag_Write(prop_bag, fcchandlerW, &var);
+
VariantClear(&var);
- if (prop_bag) IPropertyBag_Release(prop_bag);
- if (mon) IMoniker_Release(mon);
+ IPropertyBag_Release(prop_bag);
+ }
+}
+
+static void register_avicap_devices(void)
+{
+ static const WCHAR vfwindexW[] = {'V','F','W','I','n','d','e','x',0};
+ WCHAR name[] = {'v','i','d','e','o','0',0};
+ WCHAR friendlyname[32], version[32];
+ IPropertyBag *prop_bag = NULL;
+ REGFILTERPINS2 rgpins = {0};
+ REGPINTYPES rgtypes;
+ REGFILTER2 rgf;
+ VARIANT var;
+ HRESULT hr;
+ int i = 0;
+
+ hr = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
+ if (FAILED(hr))
+ return;
+
+ for (i = 0; i < 10; ++i)
+ {
+ if (!capGetDriverDescriptionW(i, friendlyname, ARRAY_SIZE(friendlyname),
+ version, ARRAY_SIZE(version)))
+ continue;
+
+ name[5] = '0' + i;
+
+ hr = register_codec(&CLSID_VideoInputDeviceCategory, name,
+ &CLSID_VfwCapture, friendlyname, &prop_bag);
+ if (FAILED(hr))
+ continue;
+
+ rgf.dwVersion = 2;
+ rgf.dwMerit = MERIT_DO_NOT_USE;
+ rgf.u.s2.cPins2 = 1;
+ rgf.u.s2.rgPins2 = &rgpins;
+ rgpins.dwFlags = 0;
+ rgpins.nMediaTypes = 1;
+ rgpins.lpMediaType = &rgtypes;
+ rgtypes.clsMajorType = &MEDIATYPE_Video;
+ rgtypes.clsMinorType = &MEDIASUBTYPE_None;
+
+ write_filter_data(prop_bag, &rgf);
+
+ /* write VFWIndex */
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = i;
+ IPropertyBag_Write(prop_bag, vfwindexW, &var);
+
+ VariantClear(&var);
+ IPropertyBag_Release(prop_bag);
}
}
* DEVENUM_ICreateDevEnum_CreateClassEnumerator
*/
static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
- ICreateDevEnum * iface,
- REFCLSID clsidDeviceClass,
- IEnumMoniker **ppEnumMoniker,
- DWORD dwFlags)
+ ICreateDevEnum *iface, REFCLSID class, IEnumMoniker **out, DWORD flags)
{
+ WCHAR guidstr[CHARS_IN_GUID];
HRESULT hr;
+ HKEY key;
- TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags);
+ TRACE("iface %p, class %s, out %p, flags %#x.\n", iface, debugstr_guid(class), out, flags);
- if (!ppEnumMoniker)
+ if (!out)
return E_POINTER;
- *ppEnumMoniker = NULL;
+ *out = NULL;
- register_codecs();
- register_legacy_filters();
- hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL);
- if (FAILED(hr)) return hr;
- register_waveout_devices();
- register_wavein_devices();
- register_midiout_devices();
- register_vfw_codecs();
+ if (!RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &key))
+ {
+ StringFromGUID2(class, guidstr, ARRAY_SIZE(guidstr));
+ RegDeleteTreeW(key, guidstr);
+ }
- return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
+ if (IsEqualGUID(class, &CLSID_LegacyAmFilterCategory))
+ register_legacy_filters();
+ else if (IsEqualGUID(class, &CLSID_AudioRendererCategory))
+ {
+ hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL);
+ if (FAILED(hr)) return hr;
+ register_waveout_devices();
+ register_midiout_devices();
+ }
+ else if (IsEqualGUID(class, &CLSID_AudioInputDeviceCategory))
+ register_wavein_devices();
+ else if (IsEqualGUID(class, &CLSID_VideoCompressorCategory))
+ register_vfw_codecs();
+ else if (IsEqualGUID(class, &CLSID_VideoInputDeviceCategory))
+ register_avicap_devices();
+
+ if (SUCCEEDED(hr = create_EnumMoniker(class, out)))
+ {
+ IMoniker *mon;
+ hr = IEnumMoniker_Next(*out, 1, &mon, NULL);
+ if (hr == S_OK)
+ {
+ IMoniker_Release(mon);
+ IEnumMoniker_Reset(*out);
+ }
+ else
+ {
+ IEnumMoniker_Release(*out);
+ *out = NULL;
+ }
+ }
+
+ return hr;
}
/**********************************************************************
HRESULT res = S_OK;
HKEY hkeyDummy = NULL;
- strcpyW(wszRegKey, wszActiveMovieKey);
+ lstrcpyW(wszRegKey, wszActiveMovieKey);
- if (!StringFromGUID2(clsidCategory, wszRegKey + strlenW(wszRegKey), sizeof(wszRegKey)/sizeof(wszRegKey[0]) - strlenW(wszRegKey)))
+ if (!StringFromGUID2(clsidCategory, wszRegKey + lstrlenW(wszRegKey), ARRAY_SIZE(wszRegKey) - lstrlenW(wszRegKey)))
res = E_INVALIDARG;
if (SUCCEEDED(res))
return res;
}
-
-static HRESULT register_codecs(void)
-{
- HRESULT res;
- WCHAR class[CHARS_IN_GUID];
- DWORD iDefaultDevice = -1;
- IFilterMapper2 * pMapper = NULL;
- REGFILTER2 rf2;
- REGFILTERPINS2 rfp2;
- HKEY basekey;
-
- /* Since devices can change between session, for example because you just plugged in a webcam
- * or switched from pulseaudio to alsa, delete all old devices first
- */
- RegOpenKeyW(HKEY_CURRENT_USER, wszActiveMovieKey, &basekey);
- StringFromGUID2(&CLSID_LegacyAmFilterCategory, class, CHARS_IN_GUID);
- RegDeleteTreeW(basekey, class);
- StringFromGUID2(&CLSID_AudioRendererCategory, class, CHARS_IN_GUID);
- RegDeleteTreeW(basekey, class);
- StringFromGUID2(&CLSID_AudioInputDeviceCategory, class, CHARS_IN_GUID);
- RegDeleteTreeW(basekey, class);
- StringFromGUID2(&CLSID_VideoInputDeviceCategory, class, CHARS_IN_GUID);
- RegDeleteTreeW(basekey, class);
- StringFromGUID2(&CLSID_MidiRendererCategory, class, CHARS_IN_GUID);
- RegDeleteTreeW(basekey, class);
- StringFromGUID2(&CLSID_VideoCompressorCategory, class, CHARS_IN_GUID);
- RegDeleteTreeW(basekey, class);
- RegCloseKey(basekey);
-
- rf2.dwVersion = 2;
- rf2.dwMerit = MERIT_PREFERRED;
- rf2.u.s2.cPins2 = 1;
- rf2.u.s2.rgPins2 = &rfp2;
- rfp2.cInstances = 1;
- rfp2.nMediums = 0;
- rfp2.lpMedium = NULL;
- rfp2.clsPinCategory = &IID_NULL;
-
- res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
- &IID_IFilterMapper2, (void **) &pMapper);
- /*
- * Fill in info for devices
- */
- if (SUCCEEDED(res))
- {
- UINT i;
- REGPINTYPES * pTypes;
- IPropertyBag * pPropBag = NULL;
-
- res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
- if (SUCCEEDED(res))
- for (i = 0; i < 10; i++)
- {
- WCHAR szDeviceName[32], szDeviceVersion[32], szDevicePath[10];
-
- if (capGetDriverDescriptionW ((WORD) i,
- szDeviceName, sizeof(szDeviceName)/sizeof(WCHAR),
- szDeviceVersion, sizeof(szDeviceVersion)/sizeof(WCHAR)))
- {
- IMoniker * pMoniker = NULL;
- WCHAR dprintf[] = { 'v','i','d','e','o','%','d',0 };
- snprintfW(szDevicePath, sizeof(szDevicePath)/sizeof(WCHAR), dprintf, i);
- /* The above code prevents 1 device with a different ID overwriting another */
-
- rfp2.nMediaTypes = 1;
- pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
- if (!pTypes) {
- IFilterMapper2_Release(pMapper);
- return E_OUTOFMEMORY;
- }
-
- pTypes[0].clsMajorType = &MEDIATYPE_Video;
- pTypes[0].clsMinorType = &MEDIASUBTYPE_None;
-
- rfp2.lpMediaType = pTypes;
-
- res = IFilterMapper2_RegisterFilter(pMapper,
- &CLSID_VfwCapture,
- szDeviceName,
- &pMoniker,
- &CLSID_VideoInputDeviceCategory,
- szDevicePath,
- &rf2);
-
- if (pMoniker) {
- OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 };
- 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, wszVfwIndex, &var);
- IPropertyBag_Release(pPropBag);
- }
- IMoniker_Release(pMoniker);
- }
-
- if (i == iDefaultDevice) FIXME("Default device\n");
- CoTaskMemFree(pTypes);
- }
- }
- }
-
- if (pMapper)
- IFilterMapper2_Release(pMapper);
-
- return res;
-}
#include "devenum_private.h"
#include "oleauto.h"
#include "ocidl.h"
+#include "dmoreg.h"
#include "wine/debug.h"
IEnumMoniker IEnumMoniker_iface;
CLSID class;
LONG ref;
+ IEnumDMO *dmo_enum;
HKEY sw_key;
DWORD sw_index;
HKEY cm_key;
IPropertyBag IPropertyBag_iface;
LONG ref;
enum device_type type;
- WCHAR path[MAX_PATH];
+ union
+ {
+ WCHAR path[MAX_PATH]; /* for filters and codecs */
+ CLSID clsid; /* for DMOs */
+ };
} RegPropBagImpl;
VARIANT* pVar,
IErrorLog* pErrorLog)
{
+ static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
LPVOID pData = NULL;
DWORD received;
DWORD type = 0;
RegPropBagImpl *This = impl_from_IPropertyBag(iface);
HRESULT res = S_OK;
LONG reswin32 = ERROR_SUCCESS;
+ WCHAR name[80];
HKEY hkey;
TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
if (!pszPropName || !pVar)
return E_POINTER;
+ if (This->type == DEVICE_DMO)
+ {
+ if (!lstrcmpW(pszPropName, FriendlyNameW))
+ {
+ res = DMOGetName(&This->clsid, name);
+ if (SUCCEEDED(res))
+ {
+ V_VT(pVar) = VT_BSTR;
+ V_BSTR(pVar) = SysAllocString(name);
+ }
+ return res;
+ }
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+
if (This->type == DEVICE_FILTER)
reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
else if (This->type == DEVICE_CODEC)
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
+ if (This->type == DEVICE_DMO)
+ return E_ACCESSDENIED;
+
switch (V_VT(pVar))
{
case VT_BSTR:
rpb->ref = 1;
rpb->type = mon->type;
- if (rpb->type == DEVICE_FILTER)
- strcpyW(rpb->path, clsidW);
+ if (rpb->type == DEVICE_DMO)
+ rpb->clsid = mon->clsid;
+ else if (rpb->type == DEVICE_FILTER)
+ {
+ lstrcpyW(rpb->path, clsidW);
+ lstrcatW(rpb->path, backslashW);
+ if (mon->has_class)
+ {
+ StringFromGUID2(&mon->class, rpb->path + lstrlenW(rpb->path), CHARS_IN_GUID);
+ lstrcatW(rpb->path, instanceW);
+ lstrcatW(rpb->path, backslashW);
+ }
+ lstrcatW(rpb->path, mon->name);
+ }
else if (rpb->type == DEVICE_CODEC)
- strcpyW(rpb->path, wszActiveMovieKey);
- if (mon->has_class)
{
- StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
- if (rpb->type == DEVICE_FILTER)
- strcatW(rpb->path, instanceW);
- strcatW(rpb->path, backslashW);
+ lstrcpyW(rpb->path, wszActiveMovieKey);
+ if (mon->has_class)
+ {
+ StringFromGUID2(&mon->class, rpb->path + lstrlenW(rpb->path), CHARS_IN_GUID);
+ lstrcatW(rpb->path, backslashW);
+ }
+ lstrcatW(rpb->path, mon->name);
}
- strcatW(rpb->path, mon->name);
*ppBag = &rpb->IPropertyBag_iface;
DEVENUM_LockModule();
if (SUCCEEDED(res))
{
V_VT(&var) = VT_LPWSTR;
- res = IPropertyBag_Read(pProp, clsid_keyname, &var, NULL);
+ res = IPropertyBag_Read(pProp, clsidW, &var, NULL);
}
if (SUCCEEDED(res))
{
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
{
- static const WCHAR swW[] = {'s','w',':',0};
- static const WCHAR cmW[] = {'c','m',':',0};
MediaCatMoniker *This = impl_from_IMoniker(iface);
WCHAR *buffer;
*ppszDisplayName = NULL;
- buffer = CoTaskMemAlloc((strlenW(deviceW) + 4 + (This->has_class ? CHARS_IN_GUID : 0)
- + strlenW(This->name) + 1) * sizeof(WCHAR));
- if (!buffer)
- return E_OUTOFMEMORY;
+ if (This->type == DEVICE_DMO)
+ {
+ buffer = CoTaskMemAlloc((lstrlenW(deviceW) + lstrlenW(dmoW)
+ + 2 * CHARS_IN_GUID + 1) * sizeof(WCHAR));
+ if (!buffer) return E_OUTOFMEMORY;
+
+ lstrcpyW(buffer, deviceW);
+ lstrcatW(buffer, dmoW);
+ StringFromGUID2(&This->clsid, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ StringFromGUID2(&This->class, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ }
+ else
+ {
+ buffer = CoTaskMemAlloc((lstrlenW(deviceW) + 3 + (This->has_class ? CHARS_IN_GUID : 0)
+ + lstrlenW(This->name) + 1) * sizeof(WCHAR));
+ if (!buffer) return E_OUTOFMEMORY;
- strcpyW(buffer, deviceW);
- if (This->type == DEVICE_FILTER)
- strcatW(buffer, swW);
- else if (This->type == DEVICE_CODEC)
- strcatW(buffer, cmW);
+ lstrcpyW(buffer, deviceW);
+ if (This->type == DEVICE_FILTER)
+ lstrcatW(buffer, swW);
+ else if (This->type == DEVICE_CODEC)
+ lstrcatW(buffer, cmW);
- if (This->has_class)
- {
- StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
- strcatW(buffer, backslashW);
+ if (This->has_class)
+ {
+ StringFromGUID2(&This->class, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ lstrcatW(buffer, backslashW);
+ }
+ lstrcatW(buffer, This->name);
}
- strcatW(buffer, This->name);
*ppszDisplayName = buffer;
return S_OK;
if (!ref)
{
+ IEnumDMO_Release(This->dmo_enum);
RegCloseKey(This->sw_key);
RegCloseKey(This->cm_key);
CoTaskMemFree(This);
LONG res;
ULONG fetched = 0;
MediaCatMoniker * pMoniker;
+ CLSID clsid;
+ HRESULT hr;
HKEY hkey;
TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
while (fetched < celt)
{
- /* FIXME: try PNP devices and DMOs first */
+ /* FIXME: try PNP devices first */
+
+ /* try DMOs */
+ if ((hr = IEnumDMO_Next(This->dmo_enum, 1, &clsid, NULL, NULL)) == S_OK)
+ {
+ if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct()))
+ return E_OUTOFMEMORY;
+
+ pMoniker->type = DEVICE_DMO;
+ pMoniker->clsid = clsid;
+ StringFromGUID2(&clsid, buffer, CHARS_IN_GUID);
+ StringFromGUID2(&This->class, buffer + CHARS_IN_GUID - 1, CHARS_IN_GUID);
+ }
/* try DirectShow filters */
- if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
+ else if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, ARRAY_SIZE(buffer))))
{
This->sw_index++;
if ((res = RegOpenKeyExW(This->sw_key, buffer, 0, KEY_QUERY_VALUE, &hkey)))
return E_OUTOFMEMORY;
pMoniker->type = DEVICE_FILTER;
+
+ if (!(pMoniker->name = CoTaskMemAlloc((lstrlenW(buffer) + 1) * sizeof(WCHAR))))
+ {
+ IMoniker_Release(&pMoniker->IMoniker_iface);
+ return E_OUTOFMEMORY;
+ }
+ lstrcpyW(pMoniker->name, buffer);
}
/* then try codecs */
- else if (!(res = RegEnumKeyW(This->cm_key, This->cm_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
+ else if (!(res = RegEnumKeyW(This->cm_key, This->cm_index, buffer, ARRAY_SIZE(buffer))))
{
This->cm_index++;
return E_OUTOFMEMORY;
pMoniker->type = DEVICE_CODEC;
+
+ if (!(pMoniker->name = CoTaskMemAlloc((lstrlenW(buffer) + 1) * sizeof(WCHAR))))
+ {
+ IMoniker_Release(&pMoniker->IMoniker_iface);
+ return E_OUTOFMEMORY;
+ }
+ lstrcpyW(pMoniker->name, buffer);
}
else
break;
- if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) * sizeof(WCHAR))))
- {
- IMoniker_Release(&pMoniker->IMoniker_iface);
- return E_OUTOFMEMORY;
- }
- strcpyW(pMoniker->name, buffer);
pMoniker->has_class = TRUE;
pMoniker->class = This->class;
while (celt--)
{
- /* FIXME: try PNP devices and DMOs first */
+ /* FIXME: try PNP devices first */
+ /* try DMOs */
+ if (IEnumDMO_Skip(This->dmo_enum, 1) == S_OK)
+ ;
/* try DirectShow filters */
- if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS)
+ else if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS)
{
This->sw_index++;
}
TRACE("(%p)->()\n", iface);
+ IEnumDMO_Reset(This->dmo_enum);
This->sw_index = 0;
This->cm_index = 0;
{
EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
WCHAR buffer[78];
+ HRESULT hr;
if (!pEnumMoniker)
return E_OUTOFMEMORY;
pEnumMoniker->cm_index = 0;
pEnumMoniker->class = *class;
- strcpyW(buffer, clsidW);
- StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
- strcatW(buffer, instanceW);
+ lstrcpyW(buffer, clsidW);
+ lstrcatW(buffer, backslashW);
+ StringFromGUID2(class, buffer + lstrlenW(buffer), CHARS_IN_GUID);
+ lstrcatW(buffer, instanceW);
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->sw_key))
pEnumMoniker->sw_key = NULL;
- strcpyW(buffer, wszActiveMovieKey);
- StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
+ lstrcpyW(buffer, wszActiveMovieKey);
+ StringFromGUID2(class, buffer + lstrlenW(buffer), CHARS_IN_GUID);
if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->cm_key))
pEnumMoniker->cm_key = NULL;
+ hr = DMOEnum(class, 0, 0, NULL, 0, NULL, &pEnumMoniker->dmo_enum);
+ if (FAILED(hr))
+ {
+ IEnumMoniker_Release(&pEnumMoniker->IEnumMoniker_iface);
+ return hr;
+ }
+
*ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface;
DEVENUM_LockModule();