Module: wine Branch: master Commit: 604809027525a946d589e7271ae93800e5043612 URL: http://source.winehq.org/git/wine.git/?a=commit;h=604809027525a946d589e7271a...
Author: Jactry Zeng jzeng@codeweavers.com Date: Mon Aug 14 21:33:56 2017 +0800
shell32: Implement SHCreateItemFromRelativeName.
Signed-off-by: Jactry Zeng jzeng@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/shell32/shell32.spec | 1 + dlls/shell32/shellitem.c | 49 ++++++++++++++++++++++++ dlls/shell32/tests/shlfolder.c | 84 ++++++++++++++++++++++++++++++++++++++++++ include/shobjidl.idl | 1 + 4 files changed, 135 insertions(+)
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec index 780fa50..e8bbf37 100644 --- a/dlls/shell32/shell32.spec +++ b/dlls/shell32/shell32.spec @@ -344,6 +344,7 @@ @ stdcall SHCreateDirectoryExW(long wstr ptr) @ stdcall SHCreateItemFromIDList(ptr ptr ptr) @ stdcall SHCreateItemFromParsingName(wstr ptr ptr ptr) +@ stdcall SHCreateItemFromRelativeName(ptr wstr ptr ptr ptr) @ stub SHCreateProcessAsUserW @ stdcall SHCreateShellItem(ptr ptr ptr ptr) @ stdcall SHCreateShellItemArray(ptr ptr long ptr ptr) diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c index 1e19f7c..cc607ec 100644 --- a/dlls/shell32/shellitem.c +++ b/dlls/shell32/shellitem.c @@ -637,6 +637,55 @@ HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath, return ret; }
+HRESULT WINAPI SHCreateItemFromRelativeName(IShellItem *parent, PCWSTR name, IBindCtx *pbc, + REFIID riid, void **ppv) +{ + LPITEMIDLIST pidl_folder = NULL, pidl = NULL; + IShellFolder *desktop = NULL, *folder = NULL; + HRESULT hr; + + TRACE("(%p, %s, %p, %s, %p)\n", parent, wine_dbgstr_w(name), pbc, debugstr_guid(riid), ppv); + + if(!ppv) + return E_INVALIDARG; + *ppv = NULL; + if(!name) + return E_INVALIDARG; + + hr = SHGetIDListFromObject((IUnknown*)parent, &pidl_folder); + if(hr != S_OK) + return hr; + + hr = SHGetDesktopFolder(&desktop); + if(hr != S_OK) + goto cleanup; + + if(!_ILIsDesktop(pidl_folder)) + { + hr = IShellFolder_BindToObject(desktop, pidl_folder, NULL, &IID_IShellFolder, + (void**)&folder); + if(hr != S_OK) + goto cleanup; + } + + hr = IShellFolder_ParseDisplayName(folder ? folder : desktop, NULL, pbc, (LPWSTR)name, + NULL, &pidl, NULL); + if(hr != S_OK) + goto cleanup; + hr = SHCreateItemFromIDList(pidl, riid, ppv); + +cleanup: + if(pidl_folder) + ILFree(pidl_folder); + if(pidl) + ILFree(pidl); + if(desktop) + IShellFolder_Release(desktop); + if(folder) + IShellFolder_Release(folder); + return hr; +} + HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv) { IPersistIDList *persist; diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 9e7127d..1b9956e 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -58,6 +58,7 @@ static void (WINAPI *pILFree)(LPITEMIDLIST); static BOOL (WINAPI *pILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST); static HRESULT (WINAPI *pSHCreateItemFromIDList)(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv); static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**); +static HRESULT (WINAPI *pSHCreateItemFromRelativeName)(IShellItem*,PCWSTR,IBindCtx*,REFIID,void**); static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**); static HRESULT (WINAPI *pSHCreateShellItemArray)(LPCITEMIDLIST,IShellFolder*,UINT,LPCITEMIDLIST*,IShellItemArray**); static HRESULT (WINAPI *pSHCreateShellItemArrayFromIDLists)(UINT, PCIDLIST_ABSOLUTE*, IShellItemArray**); @@ -66,6 +67,7 @@ static HRESULT (WINAPI *pSHCreateShellItemArrayFromShellItem)(IShellItem*, REFII static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST); static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*); static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID); +static HRESULT (WINAPI *pSHGetKnownFolderPath)(REFKNOWNFOLDERID,DWORD,HANDLE,PWSTR*); static HRESULT (WINAPI *pSHGetNameFromIDList)(PCIDLIST_ABSOLUTE,SIGDN,PWSTR*); static HRESULT (WINAPI *pSHGetItemFromDataObject)(IDataObject*,DATAOBJ_GET_ITEM_FLAGS,REFIID,void**); static HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*); @@ -115,6 +117,7 @@ static void init_function_pointers(void) MAKEFUNC(SHBindToParent); MAKEFUNC(SHCreateItemFromIDList); MAKEFUNC(SHCreateItemFromParsingName); + MAKEFUNC(SHCreateItemFromRelativeName); MAKEFUNC(SHCreateShellItem); MAKEFUNC(SHCreateShellItemArray); MAKEFUNC(SHCreateShellItemArrayFromIDLists); @@ -127,6 +130,7 @@ static void init_function_pointers(void) MAKEFUNC(SHGetSpecialFolderPathW); MAKEFUNC(SHGetSpecialFolderLocation); MAKEFUNC(SHParseDisplayName); + MAKEFUNC(SHGetKnownFolderPath); MAKEFUNC(SHGetNameFromIDList); MAKEFUNC(SHGetItemFromDataObject); MAKEFUNC(SHGetIDListFromObject); @@ -2519,6 +2523,86 @@ static void test_SHCreateShellItem(void) else win_skip("No SHCreateItemFromIDList\n");
+ /* SHCreateItemFromRelativeName */ + if(pSHCreateItemFromRelativeName && pSHGetKnownFolderPath) + { + IShellItem *shellitem_desktop = NULL; + WCHAR *desktop_path, *displayname; + WCHAR testfile_path[MAX_PATH] = {0}; + HANDLE file; + LPITEMIDLIST pidl_desktop_testfile = NULL; + int order; + + ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem_desktop); + ok(ret == S_OK, "SHCreateShellItem failed: 0x%08x.\n", ret); + + shellitem = (void*)0xdeadbeef; + ret = pSHCreateItemFromRelativeName(shellitem_desktop, NULL, NULL, &IID_IShellItem, + (void**)&shellitem); + ok(ret == E_INVALIDARG, "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n", + E_INVALIDARG, ret); + ok(shellitem == NULL, "shellitem was %p.\n", shellitem); + + /* Test with a non-existent file */ + shellitem = (void*)0xdeadbeef; + ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem, + (void**)&shellitem); + ok(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), + "Expected 0x%08x but SHCreateItemFromRelativeName return: 0x%08x.\n", + HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), ret); + ok(shellitem == NULL, "shellitem was %p.\n", shellitem); + + /* Create a file for testing in desktop folder */ + pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &desktop_path); + lstrcatW(testfile_path, desktop_path); + myPathAddBackslashW(testfile_path); + lstrcatW(testfile_path, testfileW); + file = CreateFileW(testfile_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: 0x%08x.\n", GetLastError()); + CloseHandle(file); + + shellitem = (void*)0xdeadbeef; + ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem, + (void**)&shellitem); + ok(ret == S_OK, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret); + ok(shellitem != NULL, "shellitem was %p.\n", shellitem); + if(SUCCEEDED(ret)) + { + ret = IShellItem_GetDisplayName(shellitem, 0, &displayname); + ok(ret == S_OK, "IShellItem_GetDisplayName failed: 0x%08x.\n", ret); + ok(!lstrcmpW(displayname, testfileW), "got wrong display name: %s.\n", wine_dbgstr_w(displayname)); + CoTaskMemFree(displayname); + + shellitem2 = (void*)0xdeadbeef; + ret = pSHCreateItemFromRelativeName(shellitem_desktop, testfileW, NULL, &IID_IShellItem, + (void**)&shellitem2); + ok(ret == S_OK, "SHCreateItemFromRelativeName failed: 0x%08x.\n", ret); + ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); + ok(ret == S_OK, "IShellItem_Compare failed: 0x%08x.\n", ret); + ok(!order, "order got wrong value: %d.\n", order); + IShellItem_Release(shellitem2); + + shellitem2 = (void*)0xdeadbeef; + ret = IShellFolder_ParseDisplayName(desktopfolder, NULL, NULL, testfileW, NULL, + &pidl_desktop_testfile, NULL); + ok(ret == S_OK, "ParseDisplayName failed 0x%08x.\n", ret); + ret = pSHCreateItemFromIDList(pidl_desktop_testfile, &IID_IShellItem, (void**)&shellitem2); + ret = IShellItem_Compare(shellitem, shellitem2, 0, &order); + ok(ret == S_OK, "IShellItem_Compare fail: 0x%08x.\n", ret); + ok(!order, "order got wrong value: %d.\n", order); + pILFree(pidl_desktop_testfile); + IShellItem_Release(shellitem2); + + IShellItem_Release(shellitem); + } + + DeleteFileW(testfile_path); + CoTaskMemFree(desktop_path); + IShellItem_Release(shellitem_desktop); + } + else + win_skip("No SHCreateItemFromRelativeName or SHGetKnownFolderPath\n"); + DeleteFileA(".\testfile"); pILFree(pidl_abstestfile); pILFree(pidl_testfile); diff --git a/include/shobjidl.idl b/include/shobjidl.idl index 571fbab..83fcbce 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -601,6 +601,7 @@ cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(DATAOBJ_GET_ITEM_FLAGS)") cpp_quote("HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName);") cpp_quote("HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);") cpp_quote("HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv);") +cpp_quote("HRESULT WINAPI SHCreateItemFromRelativeName(IShellItem *parent, PCWSTR name, IBindCtx *pbc, REFIID riid, void **ppv);") cpp_quote("HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj, DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv);") cpp_quote("HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl);") cpp_quote("HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv);")