diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c index 1718df72dd7..88a188f96a0 100644 --- a/dlls/shell32/shelllink.c +++ b/dlls/shell32/shelllink.c @@ -161,6 +161,8 @@ typedef struct BOOL bDirty; INT iIdOpen; /* id of the "Open" entry in the context menu */ IUnknown *site; + + LPOLESTR filepath; /* file path returned by IPersistFile::GetCurFile */ } IShellLinkImpl; static inline IShellLinkImpl *impl_from_IShellLinkW( IShellLinkW *iface ) @@ -307,6 +309,7 @@ static ULONG ShellLink_Release( IShellLinkImpl *This ) HeapFree(GetProcessHeap(), 0, This->sPathRel); HeapFree(GetProcessHeap(), 0, This->sProduct); HeapFree(GetProcessHeap(), 0, This->sComponent); + HeapFree(GetProcessHeap(), 0, This->filepath); if (This->site) IUnknown_Release( This->site ); @@ -392,6 +395,11 @@ static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFile r = IPersistStream_Load(StreamThis, stm); ShellLink_UpdatePath(This->sPathRel, pszFileName, This->sWorkDir, &This->sPath); IStream_Release( stm ); + + /* update file path */ + HeapFree(GetProcessHeap(), 0, This->filepath); + This->filepath = strdupW(pszFileName); + This->bDirty = FALSE; } TRACE("-- returning hr %08x\n", r); @@ -477,6 +485,10 @@ static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFile { StartLinkProcessor( pszFileName ); + /* update file path */ + HeapFree(GetProcessHeap(), 0, This->filepath); + This->filepath = strdupW(pszFileName); + This->bDirty = FALSE; } else @@ -496,11 +508,26 @@ static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLEST return NOERROR; } -static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName) +static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *filename) { - IShellLinkImpl *This = impl_from_IPersistFile(iface); - FIXME("(%p)->(%p): stub\n", This, ppszFileName); - return NOERROR; + IShellLinkImpl *This = impl_from_IPersistFile(iface); + IMalloc *pMalloc; + + TRACE("(%p)->(%p)\n", This, filename); + + if (!This->filepath) + { + *filename = NULL; + return S_FALSE; + } + + SHGetMalloc(&pMalloc); + *filename = IMalloc_Alloc(pMalloc, (strlenW(This->filepath)+1)*sizeof(WCHAR)); + if (!*filename) return E_OUTOFMEMORY; + + strcpyW(*filename, This->filepath); + + return S_OK; } static const IPersistFileVtbl pfvt = @@ -1239,6 +1266,7 @@ HRESULT WINAPI IShellLink_Constructor( IUnknown *pUnkOuter, sl->bDirty = FALSE; sl->iIdOpen = -1; sl->site = NULL; + sl->filepath = NULL; TRACE("(%p)->()\n",sl); diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index bb2d5b366db..52a21f12eed 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -421,6 +421,22 @@ void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails) lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08x)\n", r); if (SUCCEEDED(r)) { + CHAR buff[MAX_PATH], buff2[MAX_PATH]; + IMalloc *pmalloc; + LPOLESTR str; + + if (0) + { + /* crashes on XP */ + r = IPersistFile_GetCurFile(pf, NULL); + } + + /* test GetCurFile before ::Save */ + str = (LPWSTR)0xdeadbeef; + r = IPersistFile_GetCurFile(pf, &str); + lok(r == S_FALSE, "got 0x%08x\n", r); + ok(str == NULL, "got %p\n", str); + r = IPersistFile_Save(pf, path, TRUE); if (save_fails) { @@ -432,6 +448,18 @@ void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails) { lok(SUCCEEDED(r), "save failed (0x%08x)\n", r); } + + /* test GetCurFile after ::Save */ + r = IPersistFile_GetCurFile(pf, &str); + lok(r == S_OK, "got 0x%08x\n", r); + + WideCharToMultiByte( CP_ACP, 0, str, -1, buff, sizeof(buff), NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, path, -1, buff2, sizeof(buff2), NULL, NULL ); + + lok(!strcmp(buff, buff2), "Expected %s, got %s\n", buff2, buff); + + SHGetMalloc(&pmalloc); + IMalloc_Free(pmalloc, str); IPersistFile_Release(pf); } @@ -444,6 +472,9 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo) IShellLinkA *sl; IPersistFile *pf; char buffer[INFOTIPSIZE]; + CHAR buff[MAX_PATH], buff2[MAX_PATH]; + IMalloc *pmalloc; + LPOLESTR str; r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkA, (LPVOID*)&sl); @@ -459,8 +490,28 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo) return; } + SHGetMalloc(&pmalloc); + + /* test GetCurFile before ::Load */ + str = (LPWSTR)0xdeadbeef; + r = IPersistFile_GetCurFile(pf, &str); + lok(r == S_FALSE, "got 0x%08x\n", r); + lok(str == NULL, "got %p\n", str); + r = IPersistFile_Load(pf, path, STGM_READ); lok(SUCCEEDED(r), "load failed (0x%08x)\n", r); + + /* test GetCurFile after ::Save */ + r = IPersistFile_GetCurFile(pf, &str); + lok(r == S_OK, "got 0x%08x\n", r); + + WideCharToMultiByte( CP_ACP, 0, str, -1, buff, sizeof(buff), NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, path, -1, buff2, sizeof(buff2), NULL, NULL ); + + lok(!strcmp(buff, buff2), "Expected %s, got %s\n", buff2, buff); + + IMalloc_Free(pmalloc, str); + IPersistFile_Release(pf); if (FAILED(r)) { @@ -744,10 +795,11 @@ static void test_datalink(void) r = IShellLinkW_SetPath(sl, lnk); ok(r == S_OK, "set path failed\n"); - /* - * The following crashes: - * r = IShellLinkDataList_GetFlags( dl, NULL ); - */ +if (0) +{ + /* the following crashes */ + r = IShellLinkDataList_GetFlags( dl, NULL ); +} flags = 0; r = IShellLinkDataList_GetFlags( dl, &flags );