Zebediah Figura : devenum: Allow parsing display name without class ID.
Alexandre Julliard
julliard at winehq.org
Tue Jun 26 04:44:29 CDT 2018
Module: wine
Branch: stable
Commit: 3bde76ccabcb5d980f9bebcea39be65d8a476405
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3bde76ccabcb5d980f9bebcea39be65d8a476405
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Tue Mar 6 20:57:09 2018 -0600
devenum: Allow parsing display name without class ID.
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit f49fc4c7ef940409a2c41ab7230a97e423980015)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>
---
dlls/devenum/devenum_private.h | 5 +++
dlls/devenum/mediacatenum.c | 3 ++
dlls/devenum/parsedisplayname.c | 96 +++++++++++++++++++----------------------
dlls/devenum/tests/devenum.c | 37 ++++++++++++++++
4 files changed, 90 insertions(+), 51 deletions(-)
diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h
index bcc5085..9a0b5ad 100644
--- a/dlls/devenum/devenum_private.h
+++ b/dlls/devenum/devenum_private.h
@@ -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','\\',
diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c
index 583ca7d..0f38a0e 100644
--- a/dlls/devenum/mediacatenum.c
+++ b/dlls/devenum/mediacatenum.c
@@ -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);
diff --git a/dlls/devenum/parsedisplayname.c b/dlls/devenum/parsedisplayname.c
index b5a3951..2875a8c 100644
--- a/dlls/devenum/parsedisplayname.c
+++ b/dlls/devenum/parsedisplayname.c
@@ -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;
+ lstrcpynW(buffer, name, CHARS_IN_GUID);
+ if (CLSIDFromString(buffer, &class) == S_OK)
+ {
+ mon->has_class = TRUE;
+ mon->class = class;
+ name += CHARS_IN_GUID;
+ }
- TRACE("Device CLSID: %s\n", debugstr_w(pszClass));
+ mon->type = type;
- hr = CLSIDFromString(pszClass, &clsidDevice);
+ if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
+ {
+ IMoniker_Release(&mon->IMoniker_iface);
+ return E_OUTOFMEMORY;
+ }
+ strcpyW(mon->name, name);
- if (SUCCEEDED(hr))
+ buffer[0] = 0;
+ if (mon->has_class)
{
- 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;
- }
- }
+ StringFromGUID2(&mon->class, buffer, CHARS_IN_GUID);
+ if (mon->type == DEVICE_FILTER)
+ strcatW(buffer, instanceW);
+ strcatW(buffer, backslashW);
}
+ strcatW(buffer, mon->name);
- CoTaskMemFree(pszClass);
+ if (RegCreateKeyW(hbasekey, buffer, &mon->hkey))
+ {
+ IMoniker_Release(&mon->IMoniker_iface);
+ return MK_E_NOOBJECT;
+ }
+ *ret = &mon->IMoniker_iface;
- TRACE("-- returning: %x\n", hr);
- return hr;
+ return S_OK;
}
/**********************************************************************
diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c
index fd170bd..d665df3 100644
--- a/dlls/devenum/tests/devenum.c
+++ b/dlls/devenum/tests/devenum.c
@@ -378,6 +378,43 @@ static void test_directshow_filter(void)
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);
}
More information about the wine-cvs
mailing list