From cb5eb331590c96c26ab50cfe9ae96692dfcca34f Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Mon, 16 Aug 2010 13:55:14 -0500 Subject: [PATCH] hlink: Implement HLINKGETREF flags handling. --- dlls/hlink/link.c | 101 ++++++++++++------ dlls/hlink/tests/hlink.c | 272 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 334 insertions(+), 39 deletions(-) diff --git a/dlls/hlink/link.c b/dlls/hlink/link.c index ffd3cda854b..3e22c476d47 100644 --- a/dlls/hlink/link.c +++ b/dlls/hlink/link.c @@ -69,20 +69,40 @@ static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface) return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl)); } -static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker) +static HRESULT __GetMoniker(HlinkImpl* This, IMoniker** moniker, + DWORD ref_type) { - *moniker = NULL; - if (This->Moniker) - { - *moniker = This->Moniker; - if (*moniker) - IMoniker_AddRef(*moniker); - } - else if (This->Site) + HRESULT hres; + + if (ref_type == HLINKGETREF_DEFAULT) + ref_type = HLINKGETREF_RELATIVE; + + if (ref_type == HLINKGETREF_ABSOLUTE && This->Site) { - IHlinkSite_GetMoniker(This->Site, This->SiteData, - OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER, moniker); + IMoniker *hls_moniker; + + hres = IHlinkSite_GetMoniker(This->Site, This->SiteData, + OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER, &hls_moniker); + if (FAILED(hres)) + return hres; + + if (This->Moniker) + { + hres = IMoniker_ComposeWith(hls_moniker, This->Moniker, FALSE, + moniker); + IMoniker_Release(hls_moniker); + return hres; + } + + *moniker = hls_moniker; + return S_OK; } + + *moniker = This->Moniker; + if (*moniker) + IMoniker_AddRef(*moniker); + + return S_OK; } HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid, @@ -307,8 +327,16 @@ static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface, TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget, ppwzLocation); - if(ppimkTarget) - __GetMoniker(This, ppimkTarget); + if (ppimkTarget) + { + HRESULT hres = __GetMoniker(This, ppimkTarget, dwWhichRef); + if (FAILED(hres)) + { + if (ppwzLocation) + *ppwzLocation = NULL; + return hres; + } + } if (ppwzLocation) IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation); @@ -323,7 +351,6 @@ static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface, TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation); - /* note: undocumented behavior with dwWhichRef == -1 */ if(dwWhichRef != -1 && dwWhichRef & ~(HLINKGETREF_DEFAULT | HLINKGETREF_ABSOLUTE | HLINKGETREF_RELATIVE)) { if(ppwzTarget) @@ -333,13 +360,16 @@ static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface, return E_INVALIDARG; } - if(dwWhichRef != HLINKGETREF_DEFAULT) - FIXME("unhandled flags: 0x%x\n", dwWhichRef); - if (ppwzTarget) { IMoniker* mon; - __GetMoniker(This, &mon); + HRESULT hres = __GetMoniker(This, &mon, dwWhichRef); + if (FAILED(hres)) + { + if (ppwzLocation) + *ppwzLocation = NULL; + return hres; + } if (mon) { IBindCtx *pbc; @@ -389,7 +419,12 @@ static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface, else { IMoniker *moniker; - __GetMoniker(This, &moniker); + HRESULT hres = __GetMoniker(This, &moniker, HLINKGETREF_DEFAULT); + if (FAILED(hres)) + { + *ppwzFriendlyName = NULL; + return hres; + } if (moniker) { IBindCtx *bcxt; @@ -440,20 +475,17 @@ static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc, { HlinkImpl *This = (HlinkImpl*)iface; IMoniker *mon = NULL; + HRESULT r; FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc); - if (This->Site) - IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0); - - __GetMoniker(This, &mon); + r = __GetMoniker(This, &mon, HLINKGETREF_ABSOLUTE); TRACE("Moniker %p\n", mon); - if (mon) + if (SUCCEEDED(r)) { IBindCtx *bcxt; IHlinkTarget *target = NULL; - HRESULT r = S_OK; CreateBindCtx(0, &bcxt); @@ -488,10 +520,10 @@ static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc, } if (This->Site) - IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL); + IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, r, NULL); TRACE("Finished Navigation\n"); - return S_OK; + return r; } static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface, @@ -782,14 +814,17 @@ end: static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface, IStream* pStm, BOOL fClearDirty) { - HRESULT r = E_FAIL; + HRESULT r; HlinkImpl *This = HlinkImpl_from_IPersistStream(iface); DWORD hdr[2]; IMoniker *moniker; TRACE("(%p) Moniker(%p)\n", This, This->Moniker); - __GetMoniker(This, &moniker); + r = __GetMoniker(This, &moniker, HLINKGETREF_DEFAULT); + if (FAILED(r)) + return r; + r = E_FAIL; hdr[0] = HLINK_SAVE_MAGIC; hdr[1] = 0; @@ -850,7 +885,7 @@ end: static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface, ULARGE_INTEGER* pcbSize) { - HRESULT r = E_FAIL; + HRESULT r; HlinkImpl *This = HlinkImpl_from_IPersistStream(iface); IMoniker *moniker; @@ -864,7 +899,11 @@ static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface, if (This->FriendlyName) pcbSize->QuadPart += size_hlink_string(This->FriendlyName); - __GetMoniker(This, &moniker); + r = __GetMoniker(This, &moniker, HLINKGETREF_DEFAULT); + if (FAILED(r)) + return r; + r = E_FAIL; + if (moniker) { IPersistStream* monstream = NULL; diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c index 3db2e819d54..61b9498fb01 100644 --- a/dlls/hlink/tests/hlink.c +++ b/dlls/hlink/tests/hlink.c @@ -57,6 +57,11 @@ DEFINE_EXPECT(IsSystemMoniker); DEFINE_EXPECT(BindToStorage); DEFINE_EXPECT(GetDisplayName); +DEFINE_EXPECT(ComposeWith); +DEFINE_EXPECT(OnNavigationComplete); +DEFINE_EXPECT(Enum); +DEFINE_EXPECT(Reduce); + static const char *debugstr_guid(REFIID riid) { static char buf[50]; @@ -437,7 +442,7 @@ static void test_persist(void) hr = HlinkCreateFromString(url, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr); if (!lnk) { skip("Can't create lnk, skipping test_persist.\n"); return; @@ -449,7 +454,7 @@ static void test_persist(void) hr = HlinkCreateFromString(url, NULL, friendly_name, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr); test_persist_save_data("url + friendly name", lnk, expected_hlink_data2, sizeof(expected_hlink_data2), expected_hlink_data2_ie7, sizeof(expected_hlink_data2_ie7)); @@ -457,7 +462,7 @@ static void test_persist(void) hr = HlinkCreateFromString(url, location, friendly_name, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr); test_persist_save_data("url + friendly_name + location", lnk, expected_hlink_data3, sizeof(expected_hlink_data3), expected_hlink_data3_ie7, sizeof(expected_hlink_data3_ie7)); @@ -465,7 +470,7 @@ static void test_persist(void) hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr); test_persist_save_data("relative url", lnk, expected_hlink_data4, sizeof(expected_hlink_data4), expected_hlink_data4, sizeof(expected_hlink_data4)); @@ -473,7 +478,7 @@ static void test_persist(void) hr = HlinkCreateFromString(url, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr); hr = IHlink_SetTargetFrameName(lnk, target_frame_name); ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr); test_persist_save_data("url + target frame name", lnk, @@ -483,7 +488,7 @@ static void test_persist(void) hr = HlinkCreateFromString(filename, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr); test_persist_save_data("filename", lnk, expected_hlink_data6, sizeof(expected_hlink_data6), expected_hlink_data6, sizeof(expected_hlink_data6)); @@ -876,7 +881,7 @@ static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMon static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced) { - ok(0, "unexpected call\n"); + CHECK_EXPECT(Reduce); return E_NOTIMPL; } @@ -889,7 +894,7 @@ static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight, static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker) { - ok(0, "unexpected call\n"); + CHECK_EXPECT(Enum); return E_NOTIMPL; } @@ -1442,6 +1447,256 @@ static void test_HashLink(void) } } +static WCHAR site_monikerW[] = {'S','I','T','E','_','M','O','N','I','K','E','R',0}; +static WCHAR ref_monikerW[] = {'R','E','F','_','M','O','N','I','K','E','R',0}; + +static HRESULT WINAPI hls_test_Moniker_BindToStorage(IMoniker *iface, + IBindCtx *pbc, IMoniker *toLeft, REFIID riid, void **obj) +{ + ok(0, "BTS: %p %p %p %p %p\n", iface, pbc, toLeft, riid, obj); + return E_NOTIMPL; +} + +static HRESULT WINAPI hls_site_Moniker_ComposeWith(IMoniker *iface, + IMoniker *right, BOOL onlyIfNotGeneric, IMoniker **composite) +{ + LPOLESTR rightName; + HRESULT hres; + + ok(onlyIfNotGeneric == 0, "Expected onlyIfNotGeneric to be FALSE\n"); + + CHECK_EXPECT(ComposeWith); + + hres = IMoniker_GetDisplayName(right, NULL, NULL, &rightName); + ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres); + ok(!lstrcmpW(rightName, ref_monikerW), + "Expected to get moniker set via SetMonikerReference, instead got: %s\n", + wine_dbgstr_w(rightName)); + CoTaskMemFree(rightName); + + *composite = NULL; + + /* unlikely error code to verify this return result is used */ + return E_OUTOFMEMORY; +} + +static HRESULT WINAPI hls_site_Moniker_GetDisplayName(IMoniker *iface, + IBindCtx *pbc, IMoniker *toLeft, LPOLESTR *displayName) +{ + *displayName = CoTaskMemAlloc(sizeof(site_monikerW)); + memcpy(*displayName, site_monikerW, sizeof(site_monikerW)); + return S_OK; +} + +static HRESULT WINAPI hls_ref_Moniker_GetDisplayName(IMoniker *iface, + IBindCtx *pbc, IMoniker *toLeft, LPOLESTR *displayName) +{ + *displayName = CoTaskMemAlloc(sizeof(ref_monikerW)); + memcpy(*displayName, ref_monikerW, sizeof(ref_monikerW)); + return S_OK; +} + +static HRESULT WINAPI hls_test_Moniker_IsSystemMoniker(IMoniker *iface, + DWORD *mksys) +{ + return S_FALSE; +} + +static IMonikerVtbl hls_site_MonikerVtbl = { + Moniker_QueryInterface, + Moniker_AddRef, + Moniker_Release, + Moniker_GetClassID, + Moniker_IsDirty, + Moniker_Load, + Moniker_Save, + Moniker_GetSizeMax, + Moniker_BindToObject, + hls_test_Moniker_BindToStorage, + Moniker_Reduce, + hls_site_Moniker_ComposeWith, + Moniker_Enum, + Moniker_IsEqual, + Moniker_Hash, + Moniker_IsRunning, + Moniker_GetTimeOfLastChange, + Moniker_Inverse, + Moniker_CommonPrefixWith, + Moniker_RelativePathTo, + hls_site_Moniker_GetDisplayName, + Moniker_ParseDisplayName, + hls_test_Moniker_IsSystemMoniker +}; + +static IMonikerVtbl hls_ref_MonikerVtbl = { + Moniker_QueryInterface, + Moniker_AddRef, + Moniker_Release, + Moniker_GetClassID, + Moniker_IsDirty, + Moniker_Load, + Moniker_Save, + Moniker_GetSizeMax, + Moniker_BindToObject, + hls_test_Moniker_BindToStorage, + Moniker_Reduce, + Moniker_ComposeWith, + Moniker_Enum, + Moniker_IsEqual, + Moniker_Hash, + Moniker_IsRunning, + Moniker_GetTimeOfLastChange, + Moniker_Inverse, + Moniker_CommonPrefixWith, + Moniker_RelativePathTo, + hls_ref_Moniker_GetDisplayName, + Moniker_ParseDisplayName, + hls_test_Moniker_IsSystemMoniker +}; + +static IMoniker hls_site_Moniker = { &hls_site_MonikerVtbl }; +static IMoniker hls_ref_Moniker = { &hls_ref_MonikerVtbl }; + +static HRESULT WINAPI hls_QueryInterface(IHlinkSite *iface, REFGUID iid, + void **obj) +{ + ok(0, "QI: %p %s %p\n", iface, debugstr_guid(iid), obj); + return E_NOTIMPL; +} + +static ULONG WINAPI hls_AddRef(IHlinkSite *iface) +{ + return 2; +} + +static ULONG WINAPI hls_Release(IHlinkSite *iface) +{ + return 1; +} + +static HRESULT WINAPI hls_QueryService(IHlinkSite *iface, DWORD siteData, + REFGUID service, REFIID riid, IUnknown **punk) +{ + ok(0, "QS: %p %x %s %s %p\n", iface, siteData, debugstr_guid(service), + debugstr_guid(riid), punk); + return E_NOTIMPL; +} + +static HRESULT WINAPI hls_GetMoniker(IHlinkSite *iface, DWORD siteData, + DWORD assign, DWORD which, IMoniker **pmk) +{ + ok(siteData == 17, "Expected siteData == 17, got: %d\n", siteData); + *pmk = &hls_site_Moniker; + return S_OK; +} + +static HRESULT WINAPI hls_ReadyToNavigate(IHlinkSite *iface, DWORD siteData, + DWORD reserved) +{ + ok(0, "RTN: %p %x %x\n", iface, siteData, reserved); + return E_NOTIMPL; +} + +static HRESULT WINAPI hls_OnNavigationComplete(IHlinkSite *iface, + DWORD siteData, DWORD reserved, HRESULT error, LPCWSTR errorStr) +{ + CHECK_EXPECT(OnNavigationComplete); + ok(siteData == 17, "Expected siteData == 17, got: %d\n", siteData); + ok(error == E_OUTOFMEMORY, "Expected E_OUTOFMEMORY, got: %08x\n", error); + return E_NOTIMPL; +} + +static IHlinkSiteVtbl HlinkSiteVtbl = { + hls_QueryInterface, + hls_AddRef, + hls_Release, + hls_QueryService, + hls_GetMoniker, + hls_ReadyToNavigate, + hls_OnNavigationComplete +}; + +static IHlinkSite HlinkSite = { &HlinkSiteVtbl }; + +static void test_HlinkSite(void) +{ + IHlink *hl; + IMoniker *mon_ref; + IBindCtx *pbc; + HRESULT hres; + + hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL, + &IID_IHlink, (LPVOID*)&hl); + ok(hres == S_OK, "HlinkCreateFromString failed: %08x\n", hres); + getMonikerRef(hl, NULL, NULL); + + hres = IHlink_SetHlinkSite(hl, &HlinkSite, 17); + ok(hres == S_OK, "SetHlinkSite failed: %08x\n", hres); + getMonikerRef(hl, NULL, NULL); + getStringRef(hl, NULL, NULL); + + hres = IHlink_GetMonikerReference(hl, HLINKGETREF_RELATIVE, &mon_ref, NULL); + ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres); + ok(mon_ref == NULL, "Didn't get expected moniker, instead: %p\n", mon_ref); + + hres = IHlink_GetMonikerReference(hl, HLINKGETREF_ABSOLUTE, &mon_ref, NULL); + ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres); + ok(mon_ref == &hls_site_Moniker, "Didn't get expected moniker, instead: %p\n", mon_ref); + + SET_EXPECT(Reduce); + SET_EXPECT(Enum); + hres = IHlink_SetMonikerReference(hl, HLINKSETF_TARGET, &hls_ref_Moniker, NULL); + ok(hres == S_OK, "SetMonikerReference failed: %08x\n", hres); + todo_wine CHECK_CALLED(Reduce); + todo_wine CHECK_CALLED(Enum); + + getMonikerRef(hl, &hls_ref_Moniker, NULL); + + SET_EXPECT(Enum); + getStringRef(hl, ref_monikerW, NULL); + todo_wine CHECK_CALLED(Enum); + + hres = IHlink_GetMonikerReference(hl, HLINKGETREF_RELATIVE, &mon_ref, NULL); + ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres); + ok(mon_ref == &hls_ref_Moniker, "Didn't get expected moniker, instead: %p\n", mon_ref); + IMoniker_Release(mon_ref); + + SET_EXPECT(ComposeWith); + hres = IHlink_GetMonikerReference(hl, HLINKGETREF_ABSOLUTE, &mon_ref, NULL); + ok(hres == E_OUTOFMEMORY, "Expected E_OUTOFMEMORY, got: %08x\n", hres); + ok(mon_ref == NULL, "Shouldn't have got a Moniker, got: %p\n", mon_ref); + CHECK_CALLED(ComposeWith); + + hres = CreateBindCtx(0, &pbc); + ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres); + + SET_EXPECT(ComposeWith); + SET_EXPECT(OnNavigationComplete); + hres = IHlink_Navigate(hl, 0, pbc, NULL, NULL); + ok(hres == E_OUTOFMEMORY, "Navigate should've failed: %08x\n", hres); + CHECK_CALLED(ComposeWith); + CHECK_CALLED(OnNavigationComplete); + + IBindCtx_Release(pbc); + IHlink_Release(hl); + + SET_EXPECT(Reduce); + SET_EXPECT(Enum); + hres = HlinkCreateFromMoniker(&hls_ref_Moniker, NULL, NULL, &HlinkSite, 17, + NULL, &IID_IHlink, (LPVOID*)&hl); + ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres); + todo_wine CHECK_CALLED(Reduce); + todo_wine CHECK_CALLED(Enum); + getMonikerRef(hl, &hls_ref_Moniker, NULL); + IHlink_Release(hl); + + hres = HlinkCreateFromMoniker(NULL, NULL, NULL, &HlinkSite, 17, + NULL, &IID_IHlink, (LPVOID*)&hl); + ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres); + getMonikerRef(hl, NULL, NULL); + IHlink_Release(hl); +} + START_TEST(hlink) { CoInitialize(NULL); @@ -1457,6 +1712,7 @@ START_TEST(hlink) test_HlinkGetSetStringReference(); test_HlinkMoniker(); test_HashLink(); + test_HlinkSite(); CoUninitialize(); } -- 2.11.4.GIT