devenum: Allow parsing display name without class ID.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f5c531bdd1
commit
f49fc4c7ef
|
@ -71,6 +71,10 @@ typedef struct
|
|||
IMoniker IMoniker_iface;
|
||||
LONG ref;
|
||||
HKEY hkey;
|
||||
CLSID class;
|
||||
BOOL has_class;
|
||||
enum device_type type;
|
||||
WCHAR *name;
|
||||
} MediaCatMoniker;
|
||||
|
||||
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
|
||||
|
@ -84,6 +88,7 @@ extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
|
|||
* Global string constant declarations
|
||||
*/
|
||||
|
||||
static const WCHAR backslashW[] = {'\\',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','\\',
|
||||
|
|
|
@ -345,6 +345,7 @@ static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(IMoniker *iface)
|
|||
|
||||
if (ref == 0) {
|
||||
RegCloseKey(This->hkey);
|
||||
CoTaskMemFree(This->name);
|
||||
CoTaskMemFree(This);
|
||||
DEVENUM_UnlockModule();
|
||||
}
|
||||
|
@ -695,6 +696,8 @@ MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void)
|
|||
pMoniker->IMoniker_iface.lpVtbl = &IMoniker_Vtbl;
|
||||
pMoniker->ref = 0;
|
||||
pMoniker->hkey = NULL;
|
||||
pMoniker->has_class = FALSE;
|
||||
pMoniker->name = NULL;
|
||||
|
||||
DEVENUM_IMediaCatMoniker_AddRef(&pMoniker->IMoniker_iface);
|
||||
|
||||
|
|
|
@ -76,87 +76,81 @@ static ULONG WINAPI DEVENUM_IParseDisplayName_Release(IParseDisplayName *iface)
|
|||
* not in "@device:sw:{CLSID1}\<filter name or CLSID>" format
|
||||
*/
|
||||
static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
|
||||
IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
|
||||
IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret)
|
||||
{
|
||||
LPOLESTR pszBetween = NULL;
|
||||
LPOLESTR pszClass = NULL;
|
||||
MediaCatMoniker * pMoniker = NULL;
|
||||
CLSID clsidDevice;
|
||||
HRESULT hr = S_OK;
|
||||
WCHAR wszRegKeyName[MAX_PATH];
|
||||
WCHAR buffer[MAX_PATH];
|
||||
enum device_type type;
|
||||
MediaCatMoniker *mon;
|
||||
HKEY hbasekey;
|
||||
int classlen;
|
||||
LONG res;
|
||||
static const WCHAR wszRegSeparator[] = {'\\', 0 };
|
||||
CLSID class;
|
||||
LRESULT res;
|
||||
|
||||
TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
|
||||
TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(name), eaten, ret);
|
||||
|
||||
*ppmkOut = NULL;
|
||||
if (pchEaten)
|
||||
*pchEaten = strlenW(pszDisplayName);
|
||||
*ret = NULL;
|
||||
if (eaten)
|
||||
*eaten = strlenW(name);
|
||||
|
||||
pszDisplayName = strchrW(pszDisplayName, ':') + 1;
|
||||
if (pszDisplayName[0] == 's' && pszDisplayName[1] == 'w' && pszDisplayName[2] == ':')
|
||||
name = strchrW(name, ':') + 1;
|
||||
|
||||
if (name[0] == 's' && name[1] == 'w' && name[2] == ':')
|
||||
{
|
||||
type = DEVICE_FILTER;
|
||||
if ((res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsidW, 0, 0, &hbasekey)))
|
||||
return HRESULT_FROM_WIN32(res);
|
||||
name += 3;
|
||||
}
|
||||
else if (pszDisplayName[0] == 'c' && pszDisplayName[1] == 'm' && pszDisplayName[2] == ':')
|
||||
else if (name[0] == 'c' && name[1] == 'm' && name[2] == ':')
|
||||
{
|
||||
type = DEVICE_CODEC;
|
||||
if ((res = RegOpenKeyExW(HKEY_CURRENT_USER, wszActiveMovieKey, 0, 0, &hbasekey)))
|
||||
return HRESULT_FROM_WIN32(res);
|
||||
name += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("unhandled device type %s\n", debugstr_w(pszDisplayName+1));
|
||||
FIXME("unhandled device type %s\n", debugstr_w(name));
|
||||
return MK_E_SYNTAX;
|
||||
}
|
||||
|
||||
pszDisplayName = strchrW(pszDisplayName, '{');
|
||||
pszBetween = strchrW(pszDisplayName, '}') + 2;
|
||||
|
||||
/* size = pszBetween - pszDisplayName - 1 (for '\\' after CLSID)
|
||||
* + 1 (for NULL character)
|
||||
*/
|
||||
classlen = (int)(pszBetween - pszDisplayName - 1);
|
||||
pszClass = CoTaskMemAlloc((classlen + 1) * sizeof(WCHAR));
|
||||
if (!pszClass)
|
||||
if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
memcpy(pszClass, pszDisplayName, classlen * sizeof(WCHAR));
|
||||
pszClass[classlen] = 0;
|
||||
|
||||
TRACE("Device CLSID: %s\n", debugstr_w(pszClass));
|
||||
|
||||
hr = CLSIDFromString(pszClass, &clsidDevice);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
lstrcpynW(buffer, name, CHARS_IN_GUID);
|
||||
if (CLSIDFromString(buffer, &class) == S_OK)
|
||||
{
|
||||
pMoniker = DEVENUM_IMediaCatMoniker_Construct();
|
||||
if (pMoniker)
|
||||
{
|
||||
strcpyW(wszRegKeyName, pszClass);
|
||||
if (type == DEVICE_FILTER)
|
||||
strcatW(wszRegKeyName, instanceW);
|
||||
strcatW(wszRegKeyName, wszRegSeparator);
|
||||
strcatW(wszRegKeyName, pszBetween);
|
||||
if (RegCreateKeyW(hbasekey, wszRegKeyName, &pMoniker->hkey) == ERROR_SUCCESS)
|
||||
*ppmkOut = &pMoniker->IMoniker_iface;
|
||||
else
|
||||
{
|
||||
IMoniker_Release(&pMoniker->IMoniker_iface);
|
||||
hr = MK_E_NOOBJECT;
|
||||
}
|
||||
}
|
||||
mon->has_class = TRUE;
|
||||
mon->class = class;
|
||||
name += CHARS_IN_GUID;
|
||||
}
|
||||
|
||||
CoTaskMemFree(pszClass);
|
||||
mon->type = type;
|
||||
|
||||
TRACE("-- returning: %x\n", hr);
|
||||
return hr;
|
||||
if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
|
||||
{
|
||||
IMoniker_Release(&mon->IMoniker_iface);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
strcpyW(mon->name, name);
|
||||
|
||||
buffer[0] = 0;
|
||||
if (mon->has_class)
|
||||
{
|
||||
StringFromGUID2(&mon->class, buffer, CHARS_IN_GUID);
|
||||
if (mon->type == DEVICE_FILTER)
|
||||
strcatW(buffer, instanceW);
|
||||
strcatW(buffer, backslashW);
|
||||
}
|
||||
strcatW(buffer, mon->name);
|
||||
|
||||
if (RegCreateKeyW(hbasekey, buffer, &mon->hkey))
|
||||
{
|
||||
IMoniker_Release(&mon->IMoniker_iface);
|
||||
return MK_E_NOOBJECT;
|
||||
}
|
||||
*ret = &mon->IMoniker_iface;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
|
|
@ -363,6 +363,43 @@ static void test_directshow_filter(void)
|
|||
ok(!res, "RegDeleteKey failed: %lu\n", res);
|
||||
}
|
||||
|
||||
VariantClear(&var);
|
||||
IPropertyBag_Release(prop_bag);
|
||||
|
||||
/* name can be anything */
|
||||
|
||||
lstrcpyW(buffer, deviceW);
|
||||
lstrcatW(buffer, testW+1);
|
||||
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);
|
||||
|
||||
VariantClear(&var);
|
||||
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
|
||||
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got %#x\n", hr);
|
||||
|
||||
V_VT(&var) = VT_BSTR;
|
||||
V_BSTR(&var) = SysAllocString(testW);
|
||||
hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
|
||||
if (hr != E_ACCESSDENIED)
|
||||
{
|
||||
ok(hr == S_OK, "Write failed: %#x\n", hr);
|
||||
|
||||
VariantClear(&var);
|
||||
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
|
||||
ok(hr == S_OK, "Read failed: %#x\n", hr);
|
||||
ok(!lstrcmpW(V_BSTR(&var), testW), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
|
||||
|
||||
IMoniker_Release(mon);
|
||||
|
||||
/* vista+ stores it inside the Instance key */
|
||||
RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\test\\Instance");
|
||||
|
||||
res = RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\test");
|
||||
ok(!res, "RegDeleteKey failed: %lu\n", res);
|
||||
}
|
||||
|
||||
VariantClear(&var);
|
||||
IPropertyBag_Release(prop_bag);
|
||||
IParseDisplayName_Release(parser);
|
||||
|
|
Loading…
Reference in New Issue