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