hlink: Implement HLINKGETREF flags handling.
authorAndrew Eikum <aeikum@codeweavers.com>
Mon, 16 Aug 2010 18:55:14 +0000 (13:55 -0500)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 17 Aug 2010 09:56:13 +0000 (11:56 +0200)
dlls/hlink/link.c
dlls/hlink/tests/hlink.c

index ffd3cda854b781046f7b757d046b034cb4098482..3e22c476d4765a21ab1ee725bd63f561d7ca9942 100644 (file)
@@ -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;
index 3db2e819d5475119eda39cb95822f8723a0a3d69..61b9498fb01b311210911b8fbc5caa87d4eca398 100644 (file)
@@ -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();
 }