[DEVENUM] Sync with Wine Staging 4.18. CORE-16441

This commit is contained in:
Amine Khaldi 2019-10-20 18:56:05 +01:00
parent a186e66945
commit c1585bb868
10 changed files with 486 additions and 616 deletions

View file

@ -4,13 +4,11 @@ add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600)
add_definitions(-D__WINESRC__)
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
add_idl_headers(devenum_fil_data_header fil_data.idl)
spec2def(devenum.dll devenum.spec)
list(APPEND SOURCE
createdevenum.c
devenum_main.c
factory.c
mediacatenum.c
parsedisplayname.c
precomp.h)
@ -24,7 +22,7 @@ set_source_files_properties(devenum.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT
set_module_type(devenum win32dll UNICODE)
target_link_libraries(devenum strmiids uuid wine)
add_delay_importlibs(devenum msvfw32)
add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32 msacm32 dsound msvcrt kernel32 ntdll)
add_dependencies(devenum devenum_fil_data_header)
add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32 msacm32 dsound msdmo msvcrt kernel32 ntdll)
add_dependencies(devenum wineheaders)
add_pch(devenum precomp.h SOURCE)
add_cd_file(TARGET devenum DESTINATION reactos/system32 FOR all)

View file

@ -32,17 +32,14 @@
#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};
@ -55,7 +52,6 @@ static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a',
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);
/**********************************************************************
@ -106,11 +102,16 @@ static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface)
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;
@ -118,22 +119,48 @@ static HRESULT register_codec(const CLSID *class, const WCHAR *name, IMoniker **
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)
@ -157,7 +184,7 @@ 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;
@ -177,7 +204,7 @@ static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS2 *rgPin)
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));
@ -263,7 +290,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
{
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;
@ -352,9 +379,9 @@ static void free_regfilter2(REGFILTER2 *rgf)
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;
@ -410,59 +437,53 @@ static void register_legacy_filters(void)
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);
hr = CLSIDFromString(wszFilterSubkeyName, &clsid);
if (FAILED(hr))
continue;
lstrcpyW(wszRegKey, clsidW);
lstrcatW(wszRegKey, backslashW);
lstrcatW(wszRegKey, wszFilterSubkeyName);
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &classkey) != ERROR_SUCCESS)
continue;
hr = register_codec(&CLSID_LegacyAmFilterCategory, wszFilterSubkeyName, &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 */
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;
@ -474,11 +495,8 @@ static void register_legacy_filters(void)
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);
}
}
@ -496,50 +514,30 @@ static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, cons
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;
@ -558,16 +556,11 @@ static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, cons
/* 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;
}
@ -579,9 +572,8 @@ static void register_waveout_devices(void)
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;
@ -595,34 +587,12 @@ static void register_waveout_devices(void)
{
waveOutGetDevCapsW(i, &caps, sizeof(caps));
V_VT(&var) = VT_BSTR;
name = (i == -1) ? defaultW : caps.szPname;
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);
hr = register_codec(&CLSID_AudioRendererCategory, name,
&CLSID_AudioRender, name, &prop_bag);
if (FAILED(hr))
continue;
/* write filter data */
rgf.dwVersion = 2;
@ -640,13 +610,10 @@ static void register_waveout_devices(void)
/* 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);
}
}
@ -655,8 +622,6 @@ 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;
@ -671,31 +636,10 @@ static void register_wavein_devices(void)
{
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;
@ -706,13 +650,10 @@ static void register_wavein_devices(void)
/* 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);
}
}
@ -724,9 +665,8 @@ static void register_midiout_devices(void)
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;
@ -740,34 +680,12 @@ static void register_midiout_devices(void)
{
midiOutGetDevCapsW(i, &caps, sizeof(caps));
V_VT(&var) = VT_BSTR;
name = (i == -1) ? defaultW : caps.szPname;
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);
hr = register_codec(&CLSID_MidiRendererCategory, name,
&CLSID_AVIMIDIRender, name, &prop_bag);
if (FAILED(hr))
continue;
/* write filter data */
rgf.dwVersion = 2;
@ -785,13 +703,10 @@ static void register_midiout_devices(void)
/* 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);
}
}
@ -802,8 +717,6 @@ static void register_vfw_codecs(void)
IPropertyBag *prop_bag = NULL;
REGPINTYPES rgtypes[2];
REGFILTER2 rgf;
WCHAR clsid[CHARS_IN_GUID];
IMoniker *mon = NULL;
GUID typeguid;
ICINFO info;
VARIANT var;
@ -823,40 +736,10 @@ static void register_vfw_codecs(void)
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;
@ -878,10 +761,65 @@ static void register_vfw_codecs(void)
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);
}
}
@ -889,30 +827,58 @@ cleanup:
* 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(&register_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(&register_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;
}
/**********************************************************************
@ -943,9 +909,9 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
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))
@ -962,111 +928,3 @@ static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
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;
}

View file

@ -1,5 +1,5 @@
/*
* exported dll functions for devenum.dll
* Device Enumeration
*
* Copyright (C) 2002 John K. Hohm
* Copyright (C) 2002 Robert Shearman
@ -26,24 +26,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
DECLSPEC_HIDDEN LONG dll_refs;
DECLSPEC_HIDDEN HINSTANCE DEVENUM_hInstance;
typedef struct
{
REFCLSID clsid;
LPCWSTR friendly_name;
BOOL instance;
} register_info;
static HINSTANCE devenum_instance;
#ifdef __REACTOS__
static void DEVENUM_RegisterQuartz(void);
#endif
/***********************************************************************
* Global string constant definitions
*/
const WCHAR clsid_keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 };
/***********************************************************************
* DllEntryPoint
*/
@ -53,29 +41,101 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DEVENUM_hInstance = hinstDLL;
devenum_instance = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
break;
}
return TRUE;
}
struct class_factory
{
IClassFactory IClassFactory_iface;
IUnknown *obj;
};
static inline struct class_factory *impl_from_IClassFactory( IClassFactory *iface )
{
return CONTAINING_RECORD( iface, struct class_factory, IClassFactory_iface );
}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
{
TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), obj);
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
{
IClassFactory_AddRef(iface);
*obj = iface;
return S_OK;
}
*obj = NULL;
WARN("no interface for %s\n", debugstr_guid(iid));
return E_NOINTERFACE;
}
static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
{
DEVENUM_LockModule();
return 2;
}
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
{
DEVENUM_UnlockModule();
return 1;
}
static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface,
IUnknown *outer, REFIID iid, void **obj)
{
struct class_factory *This = impl_from_IClassFactory( iface );
TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
if (!obj) return E_POINTER;
if (outer) return CLASS_E_NOAGGREGATION;
return IUnknown_QueryInterface(This->obj, iid, obj);
}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
{
if (lock)
DEVENUM_LockModule();
else
DEVENUM_UnlockModule();
return S_OK;
}
static const IClassFactoryVtbl ClassFactory_vtbl = {
ClassFactory_QueryInterface,
ClassFactory_AddRef,
ClassFactory_Release,
ClassFactory_CreateInstance,
ClassFactory_LockServer
};
static struct class_factory create_devenum_cf = { { &ClassFactory_vtbl }, (IUnknown *)&DEVENUM_CreateDevEnum };
static struct class_factory device_moniker_cf = { { &ClassFactory_vtbl }, (IUnknown *)&DEVENUM_ParseDisplayName };
/***********************************************************************
* DllGetClassObject (DEVENUM.@)
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **obj)
{
TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
TRACE("(%s, %s, %p)\n", debugstr_guid(clsid), debugstr_guid(iid), obj);
*ppv = NULL;
*obj = NULL;
/* FIXME: we should really have two class factories.
* Oh well - works just fine as it is */
if (IsEqualGUID(rclsid, &CLSID_SystemDeviceEnum) ||
IsEqualGUID(rclsid, &CLSID_CDeviceMoniker))
return IClassFactory_QueryInterface(&DEVENUM_ClassFactory.IClassFactory_iface, iid, ppv);
if (IsEqualGUID(clsid, &CLSID_SystemDeviceEnum))
return IClassFactory_QueryInterface(&create_devenum_cf.IClassFactory_iface, iid, obj);
else if (IsEqualGUID(clsid, &CLSID_CDeviceMoniker))
return IClassFactory_QueryInterface(&device_moniker_cf.IClassFactory_iface, iid, obj);
FIXME("CLSID: %s, IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid));
FIXME("class %s not available\n", debugstr_guid(clsid));
return CLASS_E_CLASSNOTAVAILABLE;
}
@ -98,7 +158,7 @@ HRESULT WINAPI DllRegisterServer(void)
TRACE("\n");
res = __wine_register_resources( DEVENUM_hInstance );
res = __wine_register_resources( devenum_instance );
if (FAILED(res))
return res;
@ -151,7 +211,7 @@ HRESULT WINAPI DllRegisterServer(void)
HRESULT WINAPI DllUnregisterServer(void)
{
FIXME("stub!\n");
return __wine_unregister_resources( DEVENUM_hInstance );
return __wine_unregister_resources( devenum_instance );
}
#ifdef __REACTOS__

View file

@ -42,10 +42,6 @@
#include "olectl.h"
#include "uuids.h"
#ifndef RC_INVOKED
#include "wine/unicode.h"
#endif
/**********************************************************************
* Dll lifetime tracking declaration for devenum.dll
*/
@ -53,19 +49,11 @@ extern LONG dll_refs DECLSPEC_HIDDEN;
static inline void DEVENUM_LockModule(void) { InterlockedIncrement(&dll_refs); }
static inline void DEVENUM_UnlockModule(void) { InterlockedDecrement(&dll_refs); }
/**********************************************************************
* ClassFactory declaration for devenum.dll
*/
typedef struct
{
IClassFactory IClassFactory_iface;
} ClassFactoryImpl;
enum device_type
{
DEVICE_FILTER,
DEVICE_CODEC,
DEVICE_DMO,
};
typedef struct
@ -75,13 +63,16 @@ typedef struct
CLSID class;
BOOL has_class;
enum device_type type;
WCHAR *name;
union
{
WCHAR *name; /* for filters and codecs */
CLSID clsid; /* for DMOs */
};
} MediaCatMoniker;
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **enum_mon) DECLSPEC_HIDDEN;
extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN;
extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN;
extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
@ -90,12 +81,13 @@ extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
*/
static const WCHAR backslashW[] = {'\\',0};
static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
static const WCHAR clsidW[] = {'C','L','S','I','D',0};
static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0};
static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'A','c','t','i','v','e','M','o','v','i','e','\\',
'd','e','v','e','n','u','m','\\',0};
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
static const WCHAR dmoW[] = {'d','m','o',':',0};
static const WCHAR swW[] = {'s','w',':',0};
static const WCHAR cmW[] = {'c','m',':',0};

View file

@ -1,134 +0,0 @@
/*
* ClassFactory implementation for DEVENUM.dll
*
* Copyright (C) 2002 John K. Hohm
* Copyright (C) 2002 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "devenum_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
/**********************************************************************
* DEVENUM_IClassFactory_QueryInterface (also IUnknown)
*/
static HRESULT WINAPI DEVENUM_IClassFactory_QueryInterface(IClassFactory *iface, REFIID riid,
void **ppvObj)
{
TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObj);
if (ppvObj == NULL) return E_POINTER;
if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IClassFactory))
{
*ppvObj = iface;
IClassFactory_AddRef(iface);
return S_OK;
}
else if (IsEqualGUID(riid, &IID_IParseDisplayName))
{
return IClassFactory_CreateInstance(iface, NULL, riid, ppvObj);
}
FIXME("- no interface IID: %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
/**********************************************************************
* DEVENUM_IClassFactory_AddRef (also IUnknown)
*/
static ULONG WINAPI DEVENUM_IClassFactory_AddRef(IClassFactory *iface)
{
TRACE("\n");
DEVENUM_LockModule();
return 2; /* non-heap based object */
}
/**********************************************************************
* DEVENUM_IClassFactory_Release (also IUnknown)
*/
static ULONG WINAPI DEVENUM_IClassFactory_Release(IClassFactory *iface)
{
TRACE("\n");
DEVENUM_UnlockModule();
return 1; /* non-heap based object */
}
/**********************************************************************
* DEVENUM_IClassFactory_CreateInstance
*/
static HRESULT WINAPI DEVENUM_IClassFactory_CreateInstance(IClassFactory *iface,
IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
{
TRACE("(%p)->(%p, %s, %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppvObj);
if (ppvObj == NULL) return E_POINTER;
/* Don't support aggregation (Windows doesn't) */
if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
if (IsEqualGUID(&IID_ICreateDevEnum, riid))
{
*ppvObj = &DEVENUM_CreateDevEnum;
return S_OK;
}
if (IsEqualGUID(&IID_IParseDisplayName, riid))
{
*ppvObj = &DEVENUM_ParseDisplayName;
return S_OK;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
/**********************************************************************
* DEVENUM_IClassFactory_LockServer
*/
static HRESULT WINAPI DEVENUM_IClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
{
TRACE("\n");
if (fLock)
DEVENUM_LockModule();
else
DEVENUM_UnlockModule();
return S_OK;
}
/**********************************************************************
* IClassFactory_Vtbl
*/
static const IClassFactoryVtbl IClassFactory_Vtbl =
{
DEVENUM_IClassFactory_QueryInterface,
DEVENUM_IClassFactory_AddRef,
DEVENUM_IClassFactory_Release,
DEVENUM_IClassFactory_CreateInstance,
DEVENUM_IClassFactory_LockServer
};
/**********************************************************************
* static ClassFactory instance
*/
ClassFactoryImpl DEVENUM_ClassFactory = { { &IClassFactory_Vtbl } };

View file

@ -25,6 +25,7 @@
#include "devenum_private.h"
#include "oleauto.h"
#include "ocidl.h"
#include "dmoreg.h"
#include "wine/debug.h"
@ -35,6 +36,7 @@ typedef struct
IEnumMoniker IEnumMoniker_iface;
CLSID class;
LONG ref;
IEnumDMO *dmo_enum;
HKEY sw_key;
DWORD sw_index;
HKEY cm_key;
@ -46,7 +48,11 @@ typedef struct
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;
@ -114,12 +120,14 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
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);
@ -127,6 +135,21 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
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)
@ -246,6 +269,9 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
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:
@ -316,18 +342,30 @@ static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag)
rpb->ref = 1;
rpb->type = mon->type;
if (rpb->type == DEVICE_FILTER)
strcpyW(rpb->path, clsidW);
else if (rpb->type == DEVICE_CODEC)
strcpyW(rpb->path, wszActiveMovieKey);
if (mon->has_class)
if (rpb->type == DEVICE_DMO)
rpb->clsid = mon->clsid;
else if (rpb->type == DEVICE_FILTER)
{
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, 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)
{
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();
@ -459,7 +497,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(IMoniker *iface, IBi
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))
{
@ -658,8 +696,6 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(IMoniker *iface, I
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;
@ -667,23 +703,36 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, I
*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;
strcpyW(buffer, deviceW);
if (This->type == DEVICE_FILTER)
strcatW(buffer, swW);
else if (This->type == DEVICE_CODEC)
strcatW(buffer, cmW);
if (This->has_class)
if (This->type == DEVICE_DMO)
{
StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
strcatW(buffer, backslashW);
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;
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 + lstrlenW(buffer), CHARS_IN_GUID);
lstrcatW(buffer, backslashW);
}
lstrcatW(buffer, This->name);
}
strcatW(buffer, This->name);
*ppszDisplayName = buffer;
return S_OK;
@ -798,6 +847,7 @@ static ULONG WINAPI DEVENUM_IEnumMoniker_Release(IEnumMoniker *iface)
if (!ref)
{
IEnumDMO_Release(This->dmo_enum);
RegCloseKey(This->sw_key);
RegCloseKey(This->cm_key);
CoTaskMemFree(This);
@ -815,16 +865,30 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
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)))
@ -834,9 +898,16 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
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++;
@ -847,16 +918,17 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
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;
@ -883,10 +955,13 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt)
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++;
}
@ -908,6 +983,7 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(IEnumMoniker *iface)
TRACE("(%p)->()\n", iface);
IEnumDMO_Reset(This->dmo_enum);
This->sw_index = 0;
This->cm_index = 0;
@ -939,6 +1015,7 @@ HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
{
EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
WCHAR buffer[78];
HRESULT hr;
if (!pEnumMoniker)
return E_OUTOFMEMORY;
@ -949,17 +1026,25 @@ HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
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();

View file

@ -87,20 +87,25 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
*ret = NULL;
if (eaten)
*eaten = strlenW(name);
*eaten = lstrlenW(name);
name = strchrW(name, ':') + 1;
name = wcschr(name, ':') + 1;
if (name[0] == 's' && name[1] == 'w' && name[2] == ':')
if (!wcsncmp(name, swW, 3))
{
type = DEVICE_FILTER;
name += 3;
}
else if (name[0] == 'c' && name[1] == 'm' && name[2] == ':')
else if (!wcsncmp(name, cmW, 3))
{
type = DEVICE_CODEC;
name += 3;
}
else if (!wcsncmp(name, dmoW, 4))
{
type = DEVICE_DMO;
name += 4;
}
else
{
FIXME("unhandled device type %s\n", debugstr_w(name));
@ -110,23 +115,42 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
return E_OUTOFMEMORY;
lstrcpynW(buffer, name, CHARS_IN_GUID);
if (CLSIDFromString(buffer, &class) == S_OK)
if (type == DEVICE_DMO)
{
mon->has_class = TRUE;
mon->class = class;
name += CHARS_IN_GUID;
lstrcpynW(buffer, name, CHARS_IN_GUID);
if (FAILED(CLSIDFromString(buffer, &mon->clsid)))
{
IMoniker_Release(&mon->IMoniker_iface);
return MK_E_SYNTAX;
}
lstrcpynW(buffer, name + CHARS_IN_GUID - 1, CHARS_IN_GUID);
if (FAILED(CLSIDFromString(buffer, &mon->class)))
{
IMoniker_Release(&mon->IMoniker_iface);
return MK_E_SYNTAX;
}
}
else
{
lstrcpynW(buffer, name, CHARS_IN_GUID);
if (CLSIDFromString(buffer, &class) == S_OK)
{
mon->has_class = TRUE;
mon->class = class;
name += CHARS_IN_GUID;
}
if (!(mon->name = CoTaskMemAlloc((lstrlenW(name) + 1) * sizeof(WCHAR))))
{
IMoniker_Release(&mon->IMoniker_iface);
return E_OUTOFMEMORY;
}
lstrcpyW(mon->name, name);
}
mon->type = type;
if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
{
IMoniker_Release(&mon->IMoniker_iface);
return E_OUTOFMEMORY;
}
strcpyW(mon->name, name);
*ret = &mon->IMoniker_iface;
return S_OK;

View file

@ -29,7 +29,7 @@ dll/directx/wine/d3drm # Synced to WineStaging-4.0
dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-4.0
dll/directx/wine/d3dxof # Synced to WineStaging-3.17
dll/directx/wine/ddraw # Synced to WineStaging-3.3
dll/directx/wine/devenum # Synced to WineStaging-3.9
dll/directx/wine/devenum # Synced to WineStaging-4.18
dll/directx/wine/dinput # Synced to WineStaging-4.0
dll/directx/wine/dinput8 # Synced to WineStaging-3.3
dll/directx/wine/dmusic # Synced to WineStaging-4.0

View file

@ -1,2 +1,2 @@
add_idl_headers(wineheaders itss.idl)
add_idl_headers(wineheaders fil_data.idl itss.idl)

View file

@ -18,14 +18,9 @@
#pragma makedep header
import "objidl.idl";
import "strmif.idl";
import "unknwn.idl";
import "strmif.idl";
/*****************************************************************************
* IAMFilterData interface
*/
[
object,
uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
@ -33,15 +28,7 @@ import "unknwn.idl";
]
interface IAMFilterData : IUnknown
{
typedef [unique] IAMFilterData *LPIAMFILTERDATA;
HRESULT ParseFilterData( [in] BYTE *data, [in] ULONG size, [out] BYTE **regfilter );
HRESULT ParseFilterData(
[in] BYTE * rgbFilterData,
[in] ULONG cb,
[out] BYTE ** prgbRegFilter2);
HRESULT CreateFilterData(
[in] REGFILTER2 * prf2,
[out] BYTE ** prgbFilterData,
[out] ULONG * pcb);
HRESULT CreateFilterData( [in] REGFILTER2 *regfilter, [out] BYTE **data, [out] ULONG *size );
}