diff --git a/dlls/hlink/hlink_main.c b/dlls/hlink/hlink_main.c index 0e2ce905186..f6c41848c53 100644 --- a/dlls/hlink/hlink_main.c +++ b/dlls/hlink/hlink_main.c @@ -77,14 +77,12 @@ HRESULT WINAPI HlinkCreateFromMoniker( IMoniker *pimkTrgt, LPCWSTR pwzLocation, if (FAILED(r)) return r; - if (pwzLocation) - IHlink_SetStringReference(hl, HLINKSETF_LOCATION, NULL, pwzLocation); + IHlink_SetMonikerReference(hl, HLINKSETF_LOCATION | HLINKSETF_TARGET, pimkTrgt, pwzLocation); + if (pwzFriendlyName) IHlink_SetFriendlyName(hl, pwzFriendlyName); if (pihlsite) IHlink_SetHlinkSite(hl, pihlsite, dwSiteData); - if (pimkTrgt) - IHlink_SetMonikerReference(hl, HLINKSETF_LOCATION | HLINKSETF_TARGET, pimkTrgt, pwzLocation); *ppvObj = hl; @@ -111,43 +109,12 @@ HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation, if (FAILED(r)) return r; - if (pwzLocation) - IHlink_SetStringReference(hl, HLINKSETF_LOCATION, NULL, pwzLocation); - - if (pwzTarget) - { - IMoniker *pTgtMk = NULL; - IBindCtx *pbc = NULL; - ULONG eaten; - - CreateBindCtx(0, &pbc); - r = MkParseDisplayName(pbc, pwzTarget, &eaten, &pTgtMk); - IBindCtx_Release(pbc); - - if (FAILED(r)) - { - LPCWSTR p = strchrW(pwzTarget, ':'); - if (p && (p - pwzTarget > 1)) - r = CreateURLMoniker(NULL, pwzTarget, &pTgtMk); - else - r = CreateFileMoniker(pwzTarget,&pTgtMk); - } - - if (FAILED(r)) - { - ERR("couldn't create moniker for %s, failed with error 0x%08x\n", - debugstr_w(pwzTarget), r); - return r; - } - - IHlink_SetMonikerReference(hl, HLINKSETF_TARGET | HLINKSETF_LOCATION, pTgtMk, pwzLocation); - IMoniker_Release(pTgtMk); - - IHlink_SetStringReference(hl, HLINKSETF_TARGET, pwzTarget, NULL); - } + IHlink_SetStringReference(hl, HLINKSETF_TARGET | HLINKSETF_LOCATION, + pwzTarget, pwzLocation); if (pwzFriendlyName) IHlink_SetFriendlyName(hl, pwzFriendlyName); + if (pihlsite) IHlink_SetHlinkSite(hl, pihlsite, dwSiteData); diff --git a/dlls/hlink/link.c b/dlls/hlink/link.c index 78b6c1eba8c..52197ccf6fd 100644 --- a/dlls/hlink/link.c +++ b/dlls/hlink/link.c @@ -51,7 +51,6 @@ typedef struct LPWSTR FriendlyName; LPWSTR Location; - LPWSTR Target; LPWSTR TargetFrameName; IMoniker *Moniker; IHlinkSite *Site; @@ -155,7 +154,6 @@ static ULONG WINAPI IHlink_fnRelease (IHlink* iface) TRACE("-- destroying IHlink (%p)\n", This); heap_free(This->FriendlyName); - heap_free(This->Target); heap_free(This->TargetFrameName); heap_free(This->Location); if (This->Moniker) @@ -251,9 +249,45 @@ static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface, if (grfHLSETF & HLINKSETF_TARGET) { - heap_free(This->Target); - This->Target = hlink_strdupW( pwzTarget ); + if (This->Moniker) + { + IMoniker_Release(This->Moniker); + This->Moniker = NULL; + } + if (pwzTarget && *pwzTarget) + { + IMoniker *pMon; + IBindCtx *pbc = NULL; + ULONG eaten; + HRESULT r; + + r = CreateBindCtx(0, &pbc); + if (FAILED(r)) + return E_OUTOFMEMORY; + + r = MkParseDisplayName(pbc, pwzTarget, &eaten, &pMon); + IBindCtx_Release(pbc); + + if (FAILED(r)) + { + LPCWSTR p = strchrW(pwzTarget, ':'); + if (p && (p - pwzTarget > 1)) + r = CreateURLMoniker(NULL, pwzTarget, &pMon); + else + r = CreateFileMoniker(pwzTarget, &pMon); + if (FAILED(r)) + { + ERR("couldn't create moniker for %s, failed with error 0x%08x\n", + debugstr_w(pwzTarget), r); + return r; + } + } + + IHlink_SetMonikerReference(iface, HLINKSETF_TARGET, pMon, NULL); + IMoniker_Release(pMon); + } } + if (grfHLSETF & HLINKSETF_LOCATION) { heap_free(This->Location); @@ -302,22 +336,19 @@ static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface, if (ppwzTarget) { - *ppwzTarget = hlink_co_strdupW( This->Target ); - - if (!This->Target) + IMoniker* mon; + __GetMoniker(This, &mon); + if (mon) { - IMoniker* mon; - __GetMoniker(This, &mon); - if (mon) - { - IBindCtx *pbc; + IBindCtx *pbc; - CreateBindCtx( 0, &pbc); - IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget); - IBindCtx_Release(pbc); - IMoniker_Release(mon); - } + CreateBindCtx( 0, &pbc); + IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget); + IBindCtx_Release(pbc); + IMoniker_Release(mon); } + else + *ppwzTarget = NULL; } if (ppwzLocation) *ppwzLocation = hlink_co_strdupW( This->Location ); diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c index 6999187a39a..6a67f597e79 100644 --- a/dlls/hlink/tests/hlink.c +++ b/dlls/hlink/tests/hlink.c @@ -137,9 +137,7 @@ static void test_reference(void) r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL); ok(r == S_OK, "failed\n"); - todo_wine { ok(!lstrcmpW(str, url2), "url wrong\n"); - } CoTaskMemFree(str); r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL); @@ -1215,6 +1213,117 @@ static void test_HlinkGetSetStringReference(void) IHlink_Release(link); } +#define setStringRef(h,f,t,l) r_setStringRef(__LINE__,h,f,t,l) +static void r_setStringRef(unsigned line, IHlink *hlink, DWORD flags, const WCHAR *tgt, const WCHAR *loc) +{ + HRESULT hres; + hres = IHlink_SetStringReference(hlink, flags, tgt, loc); + ok_(__FILE__,line) (hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres); +} + +#define getStringRef(h,t,l) r_getStringRef(__LINE__,h,t,l) +static void r_getStringRef(unsigned line, IHlink *hlink, const WCHAR *exp_tgt, const WCHAR *exp_loc) +{ + HRESULT hres; + WCHAR *fnd_tgt, *fnd_loc; + + hres = IHlink_GetStringReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc); + ok_(__FILE__,line) (hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres); + + if(exp_tgt) + ok_(__FILE__,line) (!lstrcmpW(fnd_tgt, exp_tgt), "Found string target should have been %s, was: %s\n", wine_dbgstr_w(exp_tgt), wine_dbgstr_w(fnd_tgt)); + else + ok_(__FILE__,line) (exp_tgt == NULL, "Found string target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt)); + + if(exp_loc) + ok_(__FILE__,line) (!lstrcmpW(fnd_loc, exp_loc), "Found string location should have been %s, was: %s\n", wine_dbgstr_w(exp_loc), wine_dbgstr_w(fnd_loc)); + else + ok_(__FILE__,line) (exp_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc)); + + CoTaskMemFree(fnd_tgt); + CoTaskMemFree(fnd_loc); +} + +#define setMonikerRef(h,f,t,l) r_setMonikerRef(__LINE__,h,f,t,l) +static void r_setMonikerRef(unsigned line, IHlink *hlink, DWORD flags, IMoniker *tgt, const WCHAR *loc) +{ + HRESULT hres; + hres = IHlink_SetMonikerReference(hlink, flags, tgt, loc); + ok_(__FILE__,line) (hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres); +} + +/* passing 0xFFFFFFFF as exp_tgt will return the retrieved target & not test it */ +#define getMonikerRef(h,t,l) r_getMonikerRef(__LINE__,h,t,l) +static IMoniker *r_getMonikerRef(unsigned line, IHlink *hlink, IMoniker *exp_tgt, const WCHAR *exp_loc) +{ + HRESULT hres; + IMoniker *fnd_tgt; + WCHAR *fnd_loc; + + hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc); + ok_(__FILE__,line) (hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres); + + if(exp_loc) + ok_(__FILE__,line) (!lstrcmpW(fnd_loc, exp_loc), "Found string location should have been %s, was: %s\n", wine_dbgstr_w(exp_loc), wine_dbgstr_w(fnd_loc)); + else + ok_(__FILE__,line) (exp_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc)); + + CoTaskMemFree(fnd_loc); + + if(exp_tgt == (IMoniker*)0xFFFFFFFF) + return fnd_tgt; + + ok_(__FILE__,line) (fnd_tgt == exp_tgt, "Found moniker target should have been %p, was: %p\n", exp_tgt, fnd_tgt); + + if(fnd_tgt) + IMoniker_Release(fnd_tgt); + + return NULL; +} + +static void test_HlinkMoniker(void) +{ + IHlink *hlink; + IMoniker *aMon, *file_mon; + static const WCHAR emptyW[] = {0}; + static const WCHAR wordsW[] = {'w','o','r','d','s',0}; + static const WCHAR aW[] = {'a',0}; + static const WCHAR bW[] = {'b',0}; + HRESULT hres; + + hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hlink); + ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres); + getStringRef(hlink, NULL, NULL); + getMonikerRef(hlink, NULL, NULL); + + /* setting a string target creates a moniker reference */ + setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, aW, wordsW); + getStringRef(hlink, aW, wordsW); + aMon = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, wordsW); + ok(aMon != NULL, "Moniker from %s target should not be NULL\n", wine_dbgstr_w(aW)); + if(aMon) + IMoniker_Release(aMon); + + /* setting target & location to the empty string deletes the moniker + * reference */ + setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, emptyW, emptyW); + getStringRef(hlink, NULL, NULL); + getMonikerRef(hlink, NULL, NULL); + + /* setting a moniker target also sets the target string to that moniker's + * display name */ + hres = CreateFileMoniker(bW, &file_mon); + ok(hres == S_OK, "CreateFileMoniker failed: 0x%08x\n", hres); + + setMonikerRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, file_mon, wordsW); + getStringRef(hlink, bW, wordsW); + getMonikerRef(hlink, file_mon, wordsW); + + IMoniker_Release(file_mon); + + IHlink_Release(hlink); +} + START_TEST(hlink) { CoInitialize(NULL); @@ -1228,6 +1337,7 @@ START_TEST(hlink) test_HlinkResolveMonikerForData(); test_HlinkGetSetMonikerReference(); test_HlinkGetSetStringReference(); + test_HlinkMoniker(); CoUninitialize(); }