Signed-off-by: Myah Caron qsniyg@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