diff --git a/dlls/devenum/devenum_private.h b/dlls/devenum/devenum_private.h index bcc5085492e..9a0b5ad7bf6 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 583ca7dbba8..0f38a0e24d5 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 b5a3951eece..2875a8c6507 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}\" 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; } /********************************************************************** diff --git a/dlls/devenum/tests/devenum.c b/dlls/devenum/tests/devenum.c index c53f909c17b..fe8cb2e1ffd 100644 --- a/dlls/devenum/tests/devenum.c +++ b/dlls/devenum/tests/devenum.c @@ -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);