[PATCH v4 2/3] shell32: Implement FolderItem::get_GetLink.

Myah Caron qsniyg at protonmail.com
Mon Sep 14 10:06:09 CDT 2020


Signed-off-by: Myah Caron <qsniyg at protonmail.com>
---
v4:
 - Remove persist_file from Impl (following Nikolay's comment).
 - Release shell_link on error.

 dlls/shell32/shelldispatch.c       | 66 +++++++++++++++++++++++++++++-
 dlls/shell32/tests/shelldispatch.c |  4 +-
 2 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/dlls/shell32/shelldispatch.c b/dlls/shell32/shelldispatch.c
index afe1348bdec..9bc40fcc9c5 100644
--- a/dlls/shell32/shelldispatch.c
+++ b/dlls/shell32/shelldispatch.c
@@ -106,6 +106,8 @@ typedef struct {
 typedef struct {
     IShellLinkDual2 IShellLinkDual2_iface;
     LONG ref;
+
+    IShellLinkW *shell_link;
 } ShellLinkObjectImpl;

 static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface)
@@ -671,6 +673,7 @@ static ULONG WINAPI ShellLinkObject_Release(IShellLinkDual2 *iface)

     if (!ref)
     {
+        if (This->shell_link) IShellLinkW_Release(This->shell_link);
         heap_free(This);
     }
     return ref;
@@ -878,6 +881,52 @@ static const IShellLinkDual2Vtbl ShellLinkObjectVtbl = {
     ShellLinkObject_get_Target,
 };

+static HRESULT ShellLinkObject_Constructor(FolderItemImpl *item, IShellLinkDual2 **link)
+{
+    HRESULT hr;
+    IPersistFile *persist_file = NULL;
+    ShellLinkObjectImpl *This;
+
+    TRACE("%p\n", item);
+
+    *link = NULL;
+
+    This = heap_alloc(sizeof(*This));
+    if (!This) return E_OUTOFMEMORY;
+    This->IShellLinkDual2_iface.lpVtbl = &ShellLinkObjectVtbl;
+    This->ref = 1;
+
+    This->shell_link = NULL;
+    hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IShellLinkW, (LPVOID*)&This->shell_link);
+    if (FAILED(hr))
+    {
+        heap_free(This);
+        return hr;
+    }
+
+    hr = IShellLinkW_QueryInterface(This->shell_link, &IID_IPersistFile,
+                                    (LPVOID*)&persist_file);
+    if (FAILED(hr))
+    {
+        IShellLinkW_Release(This->shell_link);
+        heap_free(This);
+        return hr;
+    }
+
+    hr = IPersistFile_Load(persist_file, item->path, STGM_READ);
+    IPersistFile_Release(persist_file);
+    if (FAILED(hr))
+    {
+        IShellLinkW_Release(This->shell_link);
+        heap_free(This);
+        return hr;
+    }
+
+    *link = (IShellLinkDual2 *)&This->IShellLinkDual2_iface;
+    return S_OK;
+}
+
 static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem2 *iface,
         REFIID riid, LPVOID *ppv)
 {
@@ -1064,10 +1113,23 @@ static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem2 *iface, BSTR *path)
 static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem2 *iface,
         IDispatch **ppid)
 {
-    FIXME("(%p,%p)\n", iface, ppid);
+    IShellLinkDual2 *link;
+    HRESULT hr;
+    FolderItemImpl *This = impl_from_FolderItem(iface);
+
+    TRACE("(%p,%p)\n", iface, ppid);

     *ppid = NULL;
-    return E_NOTIMPL;
+
+    if (!(This->attributes & SFGAO_LINK))
+        return E_NOTIMPL;
+
+    hr = ShellLinkObject_Constructor(This, &link);
+    if (hr != S_OK)
+        return hr;
+
+    *ppid = (IDispatch*)link;
+    return S_OK;
 }

 static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem2 *iface,
diff --git a/dlls/shell32/tests/shelldispatch.c b/dlls/shell32/tests/shelldispatch.c
index 28b0b186b8e..ae1cf086270 100644
--- a/dlls/shell32/tests/shelldispatch.c
+++ b/dlls/shell32/tests/shelldispatch.c
@@ -1492,8 +1492,8 @@ static void test_ShellLinkObject(void)

     dispatch = NULL;
     hr = FolderItem_get_GetLink(item, &dispatch);
-    todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
-    todo_wine ok(dispatch != NULL, "got %p\n", dispatch);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(dispatch != NULL, "got %p\n", dispatch);

     if (dispatch) {
         sld = (IShellLinkDual2*)dispatch;
--
2.28.0





More information about the wine-devel mailing list