Andrew Eikum : hlink: Implement HlinkClone.

Alexandre Julliard julliard at winehq.org
Tue Nov 2 11:10:53 CDT 2010


Module: wine
Branch: master
Commit: 5c5e53ae215abc9a2c0fd63a5ae58c8d4e41926a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5c5e53ae215abc9a2c0fd63a5ae58c8d4e41926a

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Mon Nov  1 12:06:05 2010 -0500

hlink: Implement HlinkClone.

---

 dlls/hlink/hlink.spec    |    2 +-
 dlls/hlink/hlink_main.c  |   65 +++++++++++++++++++++++
 dlls/hlink/tests/hlink.c |  131 ++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 193 insertions(+), 5 deletions(-)

diff --git a/dlls/hlink/hlink.spec b/dlls/hlink/hlink.spec
index 0cc761f..ca8144e 100644
--- a/dlls/hlink/hlink.spec
+++ b/dlls/hlink/hlink.spec
@@ -2,7 +2,7 @@
 4 stdcall HlinkCreateFromString(wstr wstr wstr ptr long ptr ptr ptr)
 5 stdcall HlinkCreateFromData(ptr ptr long ptr ptr ptr)
 6 stdcall HlinkCreateBrowseContext(ptr ptr ptr)
-7 stub HlinkClone
+7 stdcall HlinkClone(ptr ptr ptr long ptr)
 8 stdcall HlinkNavigateToStringReference(wstr wstr ptr long ptr long ptr ptr ptr)
 9 stdcall HlinkOnNavigate(ptr ptr long ptr wstr wstr ptr)
 10 stdcall HlinkNavigate(ptr ptr long ptr ptr ptr)
diff --git a/dlls/hlink/hlink_main.c b/dlls/hlink/hlink_main.c
index e96f206..cda9683 100644
--- a/dlls/hlink/hlink_main.c
+++ b/dlls/hlink/hlink_main.c
@@ -428,6 +428,71 @@ HRESULT WINAPI HlinkResolveMonikerForData(LPMONIKER pimkReference, DWORD reserve
     return IMoniker_BindToStorage(pimkReference, pibc, NULL, &IID_IUnknown, &obj);
 }
 
+/***********************************************************************
+ *             HlinkClone (HLINK.@)
+ */
+HRESULT WINAPI HlinkClone(IHlink *hlink, REFIID riid, IHlinkSite *hls,
+        DWORD site_data, void **obj)
+{
+    IMoniker *mk, *clone_mk = NULL;
+    WCHAR *loc, *name = NULL;
+    HRESULT hres;
+
+    if(!hlink || !riid || !obj)
+        return E_INVALIDARG;
+
+    *obj = NULL;
+
+    hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &mk, &loc);
+    if(FAILED(hres))
+        return hres;
+
+    if(mk) {
+        IStream *strm;
+        LARGE_INTEGER lgint;
+
+        hres = CreateStreamOnHGlobal(NULL, TRUE, &strm);
+        if(FAILED(hres)) {
+            IMoniker_Release(mk);
+            goto cleanup;
+        }
+
+        hres = OleSaveToStream((IPersistStream*)mk, strm);
+        if(FAILED(hres)) {
+            IStream_Release(strm);
+            IMoniker_Release(mk);
+            goto cleanup;
+        }
+        IMoniker_Release(mk);
+
+        lgint.QuadPart = 0;
+        hres = IStream_Seek(strm, lgint, STREAM_SEEK_SET, NULL);
+        if(FAILED(hres)) {
+            IStream_Release(strm);
+            goto cleanup;
+        }
+
+        hres = OleLoadFromStream(strm, &IID_IMoniker, (void**)&clone_mk);
+        IStream_Release(strm);
+        if(FAILED(hres))
+            goto cleanup;
+    }
+
+    hres = IHlink_GetFriendlyName(hlink, HLFNAMEF_DEFAULT, &name);
+    if(FAILED(hres))
+        goto cleanup;
+
+    hres = HlinkCreateFromMoniker(clone_mk, loc, name, hls, site_data, NULL,
+            &IID_IHlink, obj);
+
+cleanup:
+    if(clone_mk)
+        IMoniker_Release(clone_mk);
+    CoTaskMemFree(loc);
+    CoTaskMemFree(name);
+    return hres;
+}
+
 static HRESULT WINAPI HLinkCF_fnQueryInterface ( LPCLASSFACTORY iface,
         REFIID riid, LPVOID *ppvObj)
 {
diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c
index 61b9498..21422bc 100644
--- a/dlls/hlink/tests/hlink.c
+++ b/dlls/hlink/tests/hlink.c
@@ -62,6 +62,9 @@ DEFINE_EXPECT(OnNavigationComplete);
 DEFINE_EXPECT(Enum);
 DEFINE_EXPECT(Reduce);
 
+DEFINE_EXPECT(GetClassID);
+DEFINE_EXPECT(Save);
+
 static const char *debugstr_guid(REFIID riid)
 {
     static char buf[50];
@@ -818,8 +821,9 @@ static ULONG WINAPI Moniker_Release(IMoniker *iface)
 
 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
 {
-    ok(0, "unexpected call\n");
-    return E_NOTIMPL;
+    CHECK_EXPECT(GetClassID);
+    *pClassID = IID_IUnknown; /* not a valid CLSID */
+    return S_OK;
 }
 
 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
@@ -836,8 +840,8 @@ static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
 
 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
 {
-    ok(0, "unexpected call\n");
-    return E_NOTIMPL;
+    CHECK_EXPECT(Save);
+    return S_OK;
 }
 
 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
@@ -1697,6 +1701,124 @@ static void test_HlinkSite(void)
     IHlink_Release(hl);
 }
 
+static void test_HlinkClone(void)
+{
+    HRESULT hres;
+    IHlink *hl, *cloned = NULL;
+    IMoniker *dummy, *fnd_mk;
+    IHlinkSite *fnd_site;
+    WCHAR *fnd_name;
+    DWORD fnd_data;
+    const WCHAR one[] = {'1',0};
+    const WCHAR two[] = {'2',0};
+    const WCHAR name[] = {'a',0};
+
+    hres = HlinkClone(NULL, NULL, NULL, 0, NULL);
+    ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
+
+    hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL,
+            &IID_IHlink, (void**)&hl);
+    ok(hres == S_OK, "HlinkCreateFromString failed: %08x\n", hres);
+
+    hres = HlinkClone(hl, &IID_IHlink, NULL, 0, NULL);
+    ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
+
+    if(0){ /* crash on Windows XP */
+        hres = HlinkClone(hl, NULL, NULL, 0, NULL);
+        ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
+
+        hres = HlinkClone(hl, NULL, NULL, 0, (void**)&cloned);
+        ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
+    }
+
+    hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
+    ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
+    ok(cloned != NULL, "Didn't get a clone\n");
+    getMonikerRef(cloned, NULL, NULL);
+    IHlink_Release(cloned);
+
+    IHlink_Release(hl);
+
+    SET_EXPECT(Reduce);
+    SET_EXPECT(Enum);
+    hres = HlinkCreateFromMoniker(&hls_ref_Moniker, two, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hl);
+    todo_wine CHECK_CALLED(Reduce);
+    todo_wine CHECK_CALLED(Enum);
+    ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
+    getMonikerRef(hl, &hls_ref_Moniker, two);
+
+    SET_EXPECT(Save);
+    SET_EXPECT(GetClassID);
+    cloned = (IHlink*)0xdeadbeef;
+    hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
+    /* fails because of invalid CLSID given by Moniker_GetClassID */
+    ok(hres == REGDB_E_CLASSNOTREG, "Wrong error code: %08x\n", hres);
+    ok(cloned == NULL, "Shouldn't have gotten a clone\n");
+    CHECK_CALLED(Save);
+    CHECK_CALLED(GetClassID);
+
+    IHlink_Release(hl);
+
+    hres = CreateItemMoniker(one, one, &dummy);
+    ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
+
+    hres = HlinkCreateFromMoniker(dummy, two, name, &HlinkSite, 17, NULL, &IID_IHlink, (void**)&hl);
+    ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
+    getMonikerRef(hl, dummy, two);
+
+    cloned = NULL;
+    hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
+    ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
+    ok(cloned != NULL, "Should have gotten a clone\n");
+
+    fnd_mk = getMonikerRef(cloned, (IMoniker*)0xFFFFFFFF, two);
+    ok(fnd_mk != NULL, "Expected non-null Moniker\n");
+    ok(fnd_mk != dummy, "Expected a new Moniker to be created\n");
+
+    fnd_name = NULL;
+    hres = IHlink_GetFriendlyName(cloned, HLFNAMEF_DEFAULT, &fnd_name);
+    ok(hres == S_OK, "GetFriendlyName failed: %08x\n", hres);
+    ok(fnd_name != NULL, "Expected friendly name to be non-NULL\n");
+    ok(lstrcmpW(fnd_name, name) == 0, "Expected friendly name to be %s, was %s\n",
+            wine_dbgstr_w(name), wine_dbgstr_w(fnd_name));
+    CoTaskMemFree(fnd_name);
+
+    fnd_site = (IHlinkSite*)0xdeadbeef;
+    fnd_data = 4;
+    hres = IHlink_GetHlinkSite(cloned, &fnd_site, &fnd_data);
+    ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres);
+    ok(fnd_site == NULL, "Expected NULL site\n");
+    todo_wine ok(fnd_data == 4, "Expected site data to be 4, was: %d\n", fnd_data);
+
+    IHlink_Release(cloned);
+    IHlink_Release(hl);
+
+    hres = HlinkCreateFromMoniker(dummy, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hl);
+    ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
+    getMonikerRef(hl, dummy, NULL);
+
+    cloned = NULL;
+    hres = HlinkClone(hl, &IID_IHlink, &HlinkSite, 17, (void**)&cloned);
+    ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
+    ok(cloned != NULL, "Should have gotten a clone\n");
+
+    fnd_mk = getMonikerRef(cloned, (IMoniker*)0xFFFFFFFF, NULL);
+    ok(fnd_mk != NULL, "Expected non-null Moniker\n");
+    ok(fnd_mk != dummy, "Expected a new Moniker to be created\n");
+
+    fnd_site = (IHlinkSite*)0xdeadbeef;
+    fnd_data = 4;
+    hres = IHlink_GetHlinkSite(cloned, &fnd_site, &fnd_data);
+    ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres);
+    ok(fnd_site == &HlinkSite, "Expected found site to be HlinkSite, was: %p\n", fnd_site);
+    ok(fnd_data == 17, "Expected site data to be 17, was: %d\n", fnd_data);
+
+    IHlink_Release(cloned);
+    IHlink_Release(hl);
+
+    IMoniker_Release(dummy);
+}
+
 START_TEST(hlink)
 {
     CoInitialize(NULL);
@@ -1713,6 +1835,7 @@ START_TEST(hlink)
     test_HlinkMoniker();
     test_HashLink();
     test_HlinkSite();
+    test_HlinkClone();
 
     CoUninitialize();
 }




More information about the wine-cvs mailing list