* - Also creates the special registry keys created at run-time
*/
-#define NONAMELESSSTRUCT
-#define NONAMELESSUNION
-
#include "devenum_private.h"
-#include <vfw.h>
-#include <wine/debug.h>
-//#include "wine/unicode.h"
-//#include "mmddk.h"
+#include <vfw.h>
+#include <aviriff.h>
+#include <shlwapi.h>
-WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+#include "resource.h"
extern HINSTANCE DEVENUM_hInstance;
-const WCHAR wszInstanceKeyName[] ={'I','n','s','t','a','n','c','e',0};
+const WCHAR wszInstanceKeyName[] ={'\\','I','n','s','t','a','n','c','e',0};
static const WCHAR wszRegSeparator[] = {'\\', 0 };
static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0};
static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0};
static const WCHAR wszTypes[] = {'T','y','p','e','s',0};
+static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
+static const WCHAR wszWaveInID[] = {'W','a','v','e','I','n','I','D',0};
+static const WCHAR wszWaveOutID[] = {'W','a','v','e','O','u','t','I','D',0};
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface);
static HRESULT DEVENUM_CreateSpecialCategories(void);
/**********************************************************************
* DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown)
*/
-static HRESULT WINAPI DEVENUM_ICreateDevEnum_QueryInterface(
- ICreateDevEnum * iface,
- REFIID riid,
- LPVOID *ppvObj)
+static HRESULT WINAPI DEVENUM_ICreateDevEnum_QueryInterface(ICreateDevEnum *iface, REFIID riid,
+ void **ppv)
{
- TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+ TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
- if (ppvObj == NULL) return E_POINTER;
+ if (!ppv)
+ return E_POINTER;
if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_ICreateDevEnum))
{
- *ppvObj = iface;
+ *ppv = iface;
DEVENUM_ICreateDevEnum_AddRef(iface);
return S_OK;
}
FIXME("- no interface IID: %s\n", debugstr_guid(riid));
+ *ppv = NULL;
return E_NOINTERFACE;
}
return 1; /* non-heap based object */
}
+static BOOL IsSpecialCategory(const CLSID *clsid)
+{
+ return IsEqualGUID(clsid, &CLSID_AudioRendererCategory) ||
+ IsEqualGUID(clsid, &CLSID_AudioInputDeviceCategory) ||
+ IsEqualGUID(clsid, &CLSID_VideoInputDeviceCategory) ||
+ IsEqualGUID(clsid, &CLSID_VideoCompressorCategory) ||
+ IsEqualGUID(clsid, &CLSID_MidiRendererCategory);
+}
+
HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR *wszRegKeyName, UINT maxLen)
{
- if (IsEqualGUID(clsidDeviceClass, &CLSID_AudioRendererCategory) ||
- IsEqualGUID(clsidDeviceClass, &CLSID_AudioInputDeviceCategory) ||
- IsEqualGUID(clsidDeviceClass, &CLSID_VideoInputDeviceCategory) ||
- IsEqualGUID(clsidDeviceClass, &CLSID_MidiRendererCategory))
+ if (IsSpecialCategory(clsidDeviceClass))
{
*pBaseKey = HKEY_CURRENT_USER;
strcpyW(wszRegKeyName, wszActiveMovieKey);
if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + CLSID_STR_LEN, maxLen - CLSID_STR_LEN))
return E_OUTOFMEMORY;
- strcatW(wszRegKeyName, wszRegSeparator);
strcatW(wszRegKeyName, wszInstanceKeyName);
}
return S_OK;
}
+static HKEY open_category_key(const CLSID *clsid)
+{
+ WCHAR key_name[sizeof(wszInstanceKeyName)/sizeof(WCHAR) + CHARS_IN_GUID-1 + 6 /* strlen("CLSID\") */], *ptr;
+ HKEY ret;
+
+ strcpyW(key_name, clsid_keyname);
+ ptr = key_name + strlenW(key_name);
+ *ptr++ = '\\';
+
+ if (!StringFromGUID2(clsid, ptr, CHARS_IN_GUID))
+ return NULL;
+
+ ptr += strlenW(ptr);
+ strcpyW(ptr, wszInstanceKeyName);
+
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, key_name, 0, KEY_READ, &ret) != ERROR_SUCCESS) {
+ WARN("Could not open %s\n", debugstr_w(key_name));
+ return NULL;
+ }
+
+ return ret;
+}
+
+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 void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS *rgPin)
{
HKEY hkeyTypes = NULL;
for (i1 = 0; i1 < dwMinorTypes; i1++)
{
WCHAR wszMinorTypeName[64];
- DWORD cName = sizeof(wszMinorTypeName) / sizeof(WCHAR);
CLSID *clsMajorType = NULL, *clsMinorType = NULL;
HRESULT hr;
+ cName = sizeof(wszMinorTypeName) / sizeof(WCHAR);
if (RegEnumKeyExW(hkeyMajorType, i1, wszMinorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
clsMinorType = CoTaskMemAlloc(sizeof(CLSID));
HKEY hkeyCategoryBaseKey;
WCHAR wszRegKey[MAX_PATH];
HKEY hkeyInstance = NULL;
- HRESULT hr;
if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
IEnumMoniker **ppEnumMoniker,
DWORD dwFlags)
{
- WCHAR wszRegKey[MAX_PATH];
- HKEY hkey;
- HKEY hbasekey;
+ HKEY hkey, special_hkey = NULL;
HRESULT hr;
- CreateDevEnumImpl *This = (CreateDevEnumImpl *)iface;
- TRACE("(%p)->(%s, %p, %x)\n\tDeviceClass:\t%s\n", This, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags, debugstr_guid(clsidDeviceClass));
+ TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags);
if (!ppEnumMoniker)
return E_POINTER;
DEVENUM_RegisterLegacyAmFilters();
}
- hr = DEVENUM_GetCategoryKey(clsidDeviceClass, &hbasekey, wszRegKey, MAX_PATH);
- if (FAILED(hr))
- return hr;
-
- if (IsEqualGUID(clsidDeviceClass, &CLSID_AudioRendererCategory) ||
- IsEqualGUID(clsidDeviceClass, &CLSID_AudioInputDeviceCategory) ||
- IsEqualGUID(clsidDeviceClass, &CLSID_VideoInputDeviceCategory) ||
- IsEqualGUID(clsidDeviceClass, &CLSID_MidiRendererCategory))
+ if (IsSpecialCategory(clsidDeviceClass))
{
hr = DEVENUM_CreateSpecialCategories();
if (FAILED(hr))
return hr;
- if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
+
+ special_hkey = open_special_category_key(clsidDeviceClass, FALSE);
+ if (!special_hkey)
{
ERR("Couldn't open registry key for special device: %s\n",
debugstr_guid(clsidDeviceClass));
return S_FALSE;
}
}
- else if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
+
+ hkey = open_category_key(clsidDeviceClass);
+ if (!hkey && !special_hkey)
{
FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
return S_FALSE;
}
- return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker);
+ return DEVENUM_IEnumMoniker_Construct(hkey, special_hkey, ppEnumMoniker);
}
/**********************************************************************
/**********************************************************************
* static CreateDevEnum instance
*/
-CreateDevEnumImpl DEVENUM_CreateDevEnum = { &ICreateDevEnum_Vtbl };
+ICreateDevEnum DEVENUM_CreateDevEnum = { &ICreateDevEnum_Vtbl };
/**********************************************************************
* DEVENUM_CreateAMCategoryKey (INTERNAL)
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 HANDLE DEVENUM_populate_handle;
static const WCHAR DEVENUM_populate_handle_nameW[] =
{'_','_','W','I','N','E','_',
RegDeleteTreeW(basekey, path);
if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey, path, MAX_PATH)))
RegDeleteTreeW(basekey, path);
+ if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoCompressorCategory, &basekey, path, MAX_PATH)))
+ RegDeleteTreeW(basekey, path);
rf2.dwVersion = 2;
rf2.dwMerit = MERIT_PREFERRED;
WAVEINCAPSW wicaps;
MIDIOUTCAPSW mocaps;
REGPINTYPES * pTypes;
+ IPropertyBag * pPropBag = NULL;
numDevs = waveOutGetNumDevs();
wocaps.szPname,
&rf2);
- /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
-
- if (pMoniker)
- IMoniker_Release(pMoniker);
+ 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, wszWaveOutID, &var);
+ else
+ pPropBag = NULL;
+
+ V_VT(&var) = VT_LPWSTR;
+ V_BSTR(&var) = wocaps.szPname;
+ if (SUCCEEDED(res))
+ res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var);
+ if (pPropBag)
+ IPropertyBag_Release(pPropBag);
+ IMoniker_Release(pMoniker);
+ pMoniker = NULL;
+ }
wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname);
res = IFilterMapper2_RegisterFilter(pMapper,
rfp2.lpMediaType = pTypes;
- res = IFilterMapper2_RegisterFilter(pMapper,
+ res = IFilterMapper2_RegisterFilter(pMapper,
&CLSID_AudioRecord,
wicaps.szPname,
&pMoniker,
wicaps.szPname,
&rf2);
- /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
- if (pMoniker)
- IMoniker_Release(pMoniker);
+ 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);
}
szDeviceVersion, sizeof(szDeviceVersion)/sizeof(WCHAR)))
{
IMoniker * pMoniker = NULL;
- IPropertyBag * pPropBag = 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 */
OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 };
VARIANT var;
V_VT(&var) = VT_I4;
- V_UNION(&var, ulVal) = i;
+ V_I4(&var) = i;
res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag);
- if (SUCCEEDED(res))
- res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var);
+ if (SUCCEEDED(res)) {
+ res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var);
+ IPropertyBag_Release(pPropBag);
+ }
IMoniker_Release(pMoniker);
}
if (pMapper)
IFilterMapper2_Release(pMapper);
+
+ register_vfw_codecs();
+
SetEvent(DEVENUM_populate_handle);
return res;
}