[PATCH 1/6] shell32: Implement SHGetNameFromIDList and IShellItem::GetDisplayName.
David Hedberg
david.hedberg at gmail.com
Wed Jul 21 14:45:59 CDT 2010
---
dlls/shell32/pidl.c | 62 +++++++++++++++
dlls/shell32/shell32.spec | 1 +
dlls/shell32/shellitem.c | 7 +-
dlls/shell32/tests/shlfolder.c | 162 ++++++++++++++++++++++++++++++++++++++--
include/shobjidl.idl | 2 +
5 files changed, 223 insertions(+), 11 deletions(-)
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c
index dffa2bd..9ec0dd4 100644
--- a/dlls/shell32/pidl.c
+++ b/dlls/shell32/pidl.c
@@ -1347,6 +1347,68 @@ HRESULT WINAPI SHParseDisplayName(LPCWSTR name, IBindCtx *bindctx, LPITEMIDLIST
return hr;
}
+/*************************************************************************
+ * SHGetNameFromIDList [SHELL32.@]
+ */
+HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName)
+{
+ IShellFolder *psfparent;
+ LPCITEMIDLIST child_pidl;
+ STRRET disp_name;
+ HRESULT ret;
+
+ TRACE("%p %d %p\n", pidl, sigdnName, ppszName);
+
+ *ppszName = NULL;
+ ret = SHBindToParent(pidl, &IID_IShellFolder, (void**)&psfparent, &child_pidl);
+ if(SUCCEEDED(ret))
+ {
+ switch(sigdnName)
+ {
+ /* sigdnName & 0xffff */
+ case SIGDN_NORMALDISPLAY: /* SHGDN_NORMAL */
+ case SIGDN_PARENTRELATIVEPARSING: /* SHGDN_INFOLDER | SHGDN_FORPARSING */
+ case SIGDN_PARENTRELATIVEEDITING: /* SHGDN_INFOLDER | SHGDN_FOREDITING */
+ case SIGDN_DESKTOPABSOLUTEPARSING: /* SHGDN_FORPARSING */
+ case SIGDN_DESKTOPABSOLUTEEDITING: /* SHGDN_FOREDITING | SHGDN_FORADDRESSBAR*/
+ case SIGDN_PARENTRELATIVEFORADDRESSBAR: /* SIGDN_INFOLDER | SHGDN_FORADDRESSBAR */
+ case SIGDN_PARENTRELATIVE: /* SIGDN_INFOLDER */
+
+ disp_name.uType = STRRET_WSTR;
+ ret = IShellFolder_GetDisplayNameOf(psfparent, child_pidl,
+ sigdnName & 0xffff,
+ &disp_name);
+ if(SUCCEEDED(ret))
+ ret = StrRetToStrW(&disp_name, pidl, ppszName);
+
+ break;
+
+ case SIGDN_FILESYSPATH:
+ *ppszName = CoTaskMemAlloc(sizeof(WCHAR)*MAX_PATH);
+ if(SHGetPathFromIDListW(pidl, *ppszName))
+ {
+ TRACE("Got string %s\n", debugstr_w(*ppszName));
+ ret = S_OK;
+ }
+ else
+ {
+ CoTaskMemFree(*ppszName);
+ ret = E_INVALIDARG;
+ }
+ break;
+
+ case SIGDN_URL:
+ default:
+ FIXME("Unsupported SIGDN %x\n", sigdnName);
+ ret = E_FAIL;
+ }
+
+ IShellFolder_Release(psfparent);
+ }
+
+ return ret;
+}
+
/**************************************************************************
*
* internal functions
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index 09743e8..07f97af 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -360,6 +360,7 @@
@ stdcall SHGetInstanceExplorer(long)
@ stdcall SHGetLocalizedName(wstr ptr long ptr)
@ stdcall SHGetMalloc(ptr)
+@ stdcall SHGetNameFromIDList(ptr long ptr)
@ stdcall SHGetNewLinkInfo(str str ptr long long) SHGetNewLinkInfoA
@ stdcall SHGetPathFromIDList(ptr ptr) SHGetPathFromIDListA
@ stdcall SHGetPathFromIDListA(ptr ptr)
diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c
index 29f072f..ae6de18 100644
--- a/dlls/shell32/shellitem.c
+++ b/dlls/shell32/shellitem.c
@@ -178,11 +178,10 @@ static HRESULT WINAPI ShellItem_GetParent(IShellItem *iface, IShellItem **ppsi)
static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem *iface, SIGDN sigdnName,
LPWSTR *ppszName)
{
- FIXME("(%p,%x,%p)\n", iface, sigdnName, ppszName);
-
- *ppszName = NULL;
+ ShellItem *This = (ShellItem*)iface;
+ TRACE("(%p,%x,%p)\n", iface, sigdnName, ppszName);
- return E_NOTIMPL;
+ return SHGetNameFromIDList(This->pidl, sigdnName, ppszName);
}
static HRESULT WINAPI ShellItem_GetAttributes(IShellItem *iface, SFGAOF sfgaoMask,
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 210631d..edb58dd 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -46,6 +46,7 @@ static HRESULT (WINAPI *pSHBindToParent)(LPCITEMIDLIST, REFIID, LPVOID*, LPCITEM
static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
static HRESULT (WINAPI *pSHGetFolderPathAndSubDirA)(HWND, int, HANDLE, DWORD, LPCSTR, LPSTR);
static BOOL (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST,LPWSTR);
+static HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *);
static BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
static BOOL (WINAPI *pSHGetSpecialFolderPathW)(HWND, LPWSTR, int, BOOL);
static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT);
@@ -55,6 +56,7 @@ static BOOL (WINAPI *pILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
+static HRESULT (WINAPI *pSHGetNameFromIDList)(PCIDLIST_ABSOLUTE,SIGDN,PWSTR*);
static void init_function_pointers(void)
{
@@ -72,7 +74,9 @@ static void init_function_pointers(void)
MAKEFUNC(SHGetPathFromIDListW);
MAKEFUNC(SHGetSpecialFolderPathA);
MAKEFUNC(SHGetSpecialFolderPathW);
+ MAKEFUNC(SHGetSpecialFolderLocation);
MAKEFUNC(SHParseDisplayName);
+ MAKEFUNC(SHGetNameFromIDList);
#undef MAKEFUNC
#define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
@@ -985,9 +989,7 @@ static void test_SHGetPathFromIDList(void)
STRRET strret;
static WCHAR wszTestFile[] = {
'w','i','n','e','t','e','s','t','.','f','o','o',0 };
- HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *);
- HMODULE hShell32;
- LPITEMIDLIST pidlPrograms;
+ LPITEMIDLIST pidlPrograms;
if(!pSHGetPathFromIDListW || !pSHGetSpecialFolderPathW)
{
@@ -1099,10 +1101,7 @@ static void test_SHGetPathFromIDList(void)
ok(0 == lstrcmpW(wszFileName, wszPath), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
- /* Test if we can get the path from the start menu "program files" PIDL. */
- hShell32 = GetModuleHandleA("shell32");
- pSHGetSpecialFolderLocation = (void *)GetProcAddress(hShell32, "SHGetSpecialFolderLocation");
-
+ /* Test if we can get the path from the start menu "program files" PIDL. */
hr = pSHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES, &pidlPrograms);
ok(hr == S_OK, "SHGetFolderLocation failed: 0x%08x\n", hr);
@@ -2042,6 +2041,154 @@ static void test_SHCreateShellItem(void)
IShellFolder_Release(desktopfolder);
}
+static void test_SHGetNameFromIDList(void)
+{
+ IShellItem *shellitem;
+ LPITEMIDLIST pidl;
+ LPWSTR name_string;
+ HRESULT hres;
+ UINT i;
+ static const DWORD flags[] = {
+ SIGDN_NORMALDISPLAY, SIGDN_PARENTRELATIVEPARSING,
+ SIGDN_DESKTOPABSOLUTEPARSING,SIGDN_PARENTRELATIVEEDITING,
+ SIGDN_DESKTOPABSOLUTEEDITING, /*SIGDN_FILESYSPATH, SIGDN_URL, */
+ SIGDN_PARENTRELATIVEFORADDRESSBAR,SIGDN_PARENTRELATIVE, -1234};
+
+ if(!pSHGetNameFromIDList)
+ {
+ win_skip("SHGetNameFromIDList missing.\n");
+ return;
+ }
+
+ /* These should be available on any platform that passed the above test. */
+ ok(pSHCreateShellItem != NULL, "SHCreateShellItem missing.\n");
+ ok(pSHBindToParent != NULL, "SHBindToParent missing.\n");
+ ok(pSHGetSpecialFolderLocation != NULL, "SHGetSpecialFolderLocation missing.\n");
+ ok(pStrRetToBufW != NULL, "StrRetToBufW missing.\n");
+
+ if(0)
+ {
+ /* Crashes under win7 */
+ hres = pSHGetNameFromIDList(NULL, 0, NULL);
+ }
+
+ hres = pSHGetNameFromIDList(NULL, 0, &name_string);
+ ok(hres == E_INVALIDARG, "Got 0x%08x\n", hres);
+
+ /* Test the desktop */
+ hres = pSHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
+ ok(hres == S_OK, "Got 0x%08x\n", hres);
+ hres = pSHCreateShellItem(NULL, NULL, pidl, &shellitem);
+ ok(hres == S_OK, "Got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ WCHAR *nameSI, *nameSH;
+ WCHAR buf[MAX_PATH];
+ HRESULT hrSI, hrSH, hrSF;
+ STRRET strret;
+ IShellFolder *psf;
+ BOOL res;
+
+ SHGetDesktopFolder(&psf);
+ for(i = 0; flags[i] != -1234; i++)
+ {
+ hrSI = IShellItem_GetDisplayName(shellitem, flags[i], &nameSI);
+ ok(hrSI == S_OK, "Got 0x%08x\n", hrSI);
+ hrSH = pSHGetNameFromIDList(pidl, flags[i], &nameSH);
+ ok(hrSH == S_OK, "Got 0x%08x\n", hrSH);
+ hrSF = IShellFolder_GetDisplayNameOf(psf, pidl, flags[i] & 0xffff, &strret);
+ ok(hrSF == S_OK, "Got 0x%08x\n", hrSF);
+
+ if(SUCCEEDED(hrSI) && SUCCEEDED(hrSH))
+ ok(!lstrcmpW(nameSI, nameSH), "Strings differ.\n");
+
+ if(SUCCEEDED(hrSF))
+ {
+ pStrRetToBufW(&strret, NULL, buf, MAX_PATH);
+ if(SUCCEEDED(hrSI))
+ ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
+ if(SUCCEEDED(hrSF))
+ ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
+ }
+ if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
+ if(SUCCEEDED(hrSH)) CoTaskMemFree(nameSH);
+ }
+ IShellFolder_Release(psf);
+
+ hrSI = pSHGetNameFromIDList(pidl, SIGDN_FILESYSPATH, &nameSI);
+ ok(hrSI == S_OK, "Got 0x%08x\n", hrSI);
+ res = SHGetPathFromIDListW(pidl, buf);
+ ok(res == TRUE, "Got %d\n", res);
+ if(SUCCEEDED(hrSI) && res)
+ ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
+ if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
+
+ hres = pSHGetNameFromIDList(pidl, SIGDN_URL, &name_string);
+ todo_wine ok(hres == S_OK, "Got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) CoTaskMemFree(name_string);
+
+ IShellItem_Release(shellitem);
+ }
+ pILFree(pidl);
+
+ /* Test the control panel */
+ hres = pSHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidl);
+ ok(hres == S_OK, "Got 0x%08x\n", hres);
+ hres = pSHCreateShellItem(NULL, NULL, pidl, &shellitem);
+ ok(hres == S_OK, "Got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ WCHAR *nameSI, *nameSH;
+ WCHAR buf[MAX_PATH];
+ HRESULT hrSI, hrSH, hrSF;
+ STRRET strret;
+ IShellFolder *psf;
+ BOOL res;
+
+ SHGetDesktopFolder(&psf);
+ for(i = 0; flags[i] != -1234; i++)
+ {
+ hrSI = IShellItem_GetDisplayName(shellitem, flags[i], &nameSI);
+ ok(hrSI == S_OK, "Got 0x%08x\n", hrSI);
+ hrSH = pSHGetNameFromIDList(pidl, flags[i], &nameSH);
+ ok(hrSH == S_OK, "Got 0x%08x\n", hrSH);
+ hrSF = IShellFolder_GetDisplayNameOf(psf, pidl, flags[i] & 0xffff, &strret);
+ ok(hrSF == S_OK, "Got 0x%08x\n", hrSF);
+
+ if(SUCCEEDED(hrSI) && SUCCEEDED(hrSH))
+ ok(!lstrcmpW(nameSI, nameSH), "Strings differ.\n");
+
+ if(SUCCEEDED(hrSF))
+ {
+ pStrRetToBufW(&strret, NULL, buf, MAX_PATH);
+ if(SUCCEEDED(hrSI))
+ ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
+ if(SUCCEEDED(hrSF))
+ ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
+ }
+ if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
+ if(SUCCEEDED(hrSH)) CoTaskMemFree(nameSH);
+ }
+ IShellFolder_Release(psf);
+
+ hrSI = pSHGetNameFromIDList(pidl, SIGDN_FILESYSPATH, &nameSI);
+ ok(hrSI == E_INVALIDARG, "Got 0x%08x\n", hrSI);
+ res = SHGetPathFromIDListW(pidl, buf);
+ ok(res == FALSE, "Got %d\n", res);
+ if(SUCCEEDED(hrSI) && res)
+ ok(!lstrcmpW(nameSI, buf), "Strings differ.\n");
+ if(SUCCEEDED(hrSI)) CoTaskMemFree(nameSI);
+
+ hres = pSHGetNameFromIDList(pidl, SIGDN_URL, &name_string);
+ todo_wine ok(hres == E_NOTIMPL /* Win7 */ || hres == S_OK /* Vista */,
+ "Got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) CoTaskMemFree(name_string);
+
+ IShellItem_Release(shellitem);
+ }
+ pILFree(pidl);
+}
+
static void test_SHParseDisplayName(void)
{
LPITEMIDLIST pidl1, pidl2;
@@ -2286,6 +2433,7 @@ START_TEST(shlfolder)
test_SHCreateShellItem();
test_desktop_IPersist();
test_GetUIObject();
+ test_SHGetNameFromIDList();
OleUninitialize();
}
diff --git a/include/shobjidl.idl b/include/shobjidl.idl
index d634d53..be85fbb 100644
--- a/include/shobjidl.idl
+++ b/include/shobjidl.idl
@@ -494,6 +494,8 @@ interface IShellItemArray : IUnknown
}
+cpp_quote("HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName);")
+
/*****************************************************************************
* IShellItemFilter interface
*/
--
1.7.1.1
More information about the wine-patches
mailing list