mirror of
https://github.com/reactos/reactos.git
synced 2025-04-05 05:01:03 +00:00
[SHLWAPI][SHLWAPI_APITEST][SDK] Implement IShellFolder_GetDisplayNameOf (#6918)
This export function is needed to implement shell32!SHGetRealIDL function correctly. JIRA issue: CORE-19278 - Implement IShellFolder_GetDisplayNameOf function (This function is not inline function in this case) with retry data. - Add SFGDNO_RETRYALWAYS flag to <shlwapi_undoc.h>. - Add IShellFolderHelpers testcase.
This commit is contained in:
parent
f69e256376
commit
53518bbab3
5 changed files with 360 additions and 7 deletions
|
@ -140,16 +140,36 @@ SHLWAPI_IsBogusHRESULT(HRESULT hr)
|
|||
return (hr == E_FAIL || hr == E_INVALIDARG || hr == E_NOTIMPL);
|
||||
}
|
||||
|
||||
// Used for IShellFolder_GetDisplayNameOf
|
||||
struct RETRY_DATA
|
||||
{
|
||||
SHGDNF uRemove;
|
||||
SHGDNF uAdd;
|
||||
DWORD dwRetryFlags;
|
||||
};
|
||||
static const RETRY_DATA g_RetryData[] =
|
||||
{
|
||||
{ SHGDN_FOREDITING, SHGDN_NORMAL, SFGDNO_RETRYALWAYS },
|
||||
{ SHGDN_FORADDRESSBAR, SHGDN_NORMAL, SFGDNO_RETRYALWAYS },
|
||||
{ SHGDN_NORMAL, SHGDN_FORPARSING, SFGDNO_RETRYALWAYS },
|
||||
{ SHGDN_FORPARSING, SHGDN_NORMAL, SFGDNO_RETRYWITHFORPARSING },
|
||||
{ SHGDN_INFOLDER, SHGDN_NORMAL, SFGDNO_RETRYALWAYS },
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* IShellFolder_GetDisplayNameOf [SHLWAPI.316]
|
||||
*
|
||||
* @note Don't confuse with <shobjidl.h> inline function of the same name.
|
||||
* If the original call fails with the given uFlags, this function will
|
||||
* retry with other flags to attempt retrieving any meaningful description.
|
||||
*/
|
||||
EXTERN_C HRESULT WINAPI
|
||||
IShellFolder_GetDisplayNameOf(
|
||||
_In_ IShellFolder *psf,
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_In_ DWORD uFlags,
|
||||
_In_ SHGDNF uFlags,
|
||||
_Out_ LPSTRRET lpName,
|
||||
_In_ DWORD dwRetryFlags)
|
||||
_In_ DWORD dwRetryFlags) // dwRetryFlags is an additional parameter
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -159,19 +179,37 @@ IShellFolder_GetDisplayNameOf(
|
|||
if (!SHLWAPI_IsBogusHRESULT(hr))
|
||||
return hr;
|
||||
|
||||
dwRetryFlags |= 0x80000000;
|
||||
dwRetryFlags |= SFGDNO_RETRYALWAYS;
|
||||
|
||||
if ((uFlags & SHGDN_FORPARSING) == 0)
|
||||
dwRetryFlags |= SFGDNO_RETRYWITHFORPARSING;
|
||||
|
||||
/* It seems the function is actually retrying here */
|
||||
FIXME("dwRetryFlags: 0x%X\n", dwRetryFlags);
|
||||
// Retry with other flags to get successful results
|
||||
for (SIZE_T iEntry = 0; iEntry < _countof(g_RetryData); ++iEntry)
|
||||
{
|
||||
const RETRY_DATA *pData = &g_RetryData[iEntry];
|
||||
if (!(dwRetryFlags & pData->dwRetryFlags))
|
||||
continue;
|
||||
|
||||
SHGDNF uNewFlags = ((uFlags & ~pData->uRemove) | pData->uAdd);
|
||||
if (uNewFlags == uFlags)
|
||||
continue;
|
||||
|
||||
hr = psf->GetDisplayNameOf(pidl, uNewFlags, lpName);
|
||||
if (!SHLWAPI_IsBogusHRESULT(hr))
|
||||
break;
|
||||
|
||||
uFlags = uNewFlags; // Update flags every time
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* IShellFolder_ParseDisplayName [SHLWAPI.317]
|
||||
*
|
||||
* @note Don't confuse with <shobjidl.h> inline function of the same name.
|
||||
* This function is safer than IShellFolder::ParseDisplayName.
|
||||
*/
|
||||
EXTERN_C HRESULT WINAPI
|
||||
IShellFolder_ParseDisplayName(
|
||||
|
@ -209,6 +247,9 @@ IShellFolder_ParseDisplayName(
|
|||
|
||||
/*************************************************************************
|
||||
* IShellFolder_CompareIDs [SHLWAPI.551]
|
||||
*
|
||||
* @note Don't confuse with <shobjidl.h> inline function of the same name.
|
||||
* This function tries IShellFolder2 if possible.
|
||||
*/
|
||||
EXTERN_C HRESULT WINAPI
|
||||
IShellFolder_CompareIDs(
|
||||
|
|
|
@ -6,6 +6,7 @@ include_directories($<TARGET_FILE_DIR:shlwapi_resource_dll>)
|
|||
|
||||
list(APPEND SOURCE
|
||||
AssocQueryString.c
|
||||
IShellFolderHelpers.cpp
|
||||
PathFileExistsDefExtAndAttributesW.c
|
||||
PathFindOnPath.c
|
||||
PathIsUNC.c
|
||||
|
|
308
modules/rostests/apitests/shlwapi/IShellFolderHelpers.cpp
Normal file
308
modules/rostests/apitests/shlwapi/IShellFolderHelpers.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Tests for SHLWAPI IShellFolder helpers
|
||||
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include <apitest.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <versionhelpers.h>
|
||||
|
||||
#define SHLWAPI_ISHELLFOLDER_HELPERS
|
||||
#include <shlwapi_undoc.h>
|
||||
|
||||
static INT s_nStep = 0;
|
||||
|
||||
class CTestShellFolder : public IShellFolder
|
||||
{
|
||||
public:
|
||||
CTestShellFolder() { }
|
||||
virtual ~CTestShellFolder() { }
|
||||
|
||||
static void *operator new(size_t size)
|
||||
{
|
||||
return LocalAlloc(LPTR, size);
|
||||
}
|
||||
static void operator delete(void *ptr)
|
||||
{
|
||||
LocalFree(ptr);
|
||||
}
|
||||
static void operator delete(void *ptr, size_t size)
|
||||
{
|
||||
LocalFree(ptr);
|
||||
}
|
||||
|
||||
// IUnknown methods
|
||||
STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject) override
|
||||
{
|
||||
ok_int(s_nStep, 11);
|
||||
ok_int(IsEqualGUID(riid, IID_IShellFolder2), TRUE);
|
||||
++s_nStep;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
STDMETHOD_(ULONG, AddRef)() override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return 1;
|
||||
}
|
||||
STDMETHOD_(ULONG, Release)() override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IShellFolder methods
|
||||
STDMETHOD(ParseDisplayName)(
|
||||
HWND hwndOwner,
|
||||
LPBC pbc,
|
||||
LPOLESTR lpszDisplayName,
|
||||
ULONG *pchEaten,
|
||||
PIDLIST_RELATIVE *ppidl,
|
||||
ULONG *pdwAttributes) override
|
||||
{
|
||||
ok_ptr(*ppidl, NULL);
|
||||
ok_long(*pdwAttributes, 0);
|
||||
++s_nStep;
|
||||
return 0xDEADFACE;
|
||||
}
|
||||
STDMETHOD(EnumObjects)(
|
||||
HWND hwndOwner,
|
||||
DWORD dwFlags,
|
||||
LPENUMIDLIST *ppEnumIDList) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHOD(BindToObject)(
|
||||
PCUIDLIST_RELATIVE pidl,
|
||||
LPBC pbcReserved,
|
||||
REFIID riid,
|
||||
LPVOID *ppvOut) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHOD(BindToStorage)(
|
||||
PCUIDLIST_RELATIVE pidl,
|
||||
LPBC pbcReserved,
|
||||
REFIID riid,
|
||||
LPVOID *ppvOut) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHOD(CompareIDs)(
|
||||
LPARAM lParam,
|
||||
PCUIDLIST_RELATIVE pidl1,
|
||||
PCUIDLIST_RELATIVE pidl2) override
|
||||
{
|
||||
switch (s_nStep)
|
||||
{
|
||||
case 11:
|
||||
// It shouldn't come here
|
||||
ok_int(TRUE, FALSE);
|
||||
break;
|
||||
case 12:
|
||||
ok_long((LONG)lParam, 0x00001234);
|
||||
break;
|
||||
case 13:
|
||||
ok_long((LONG)lParam, 0x00005678);
|
||||
break;
|
||||
default:
|
||||
skip("\n");
|
||||
break;
|
||||
}
|
||||
++s_nStep;
|
||||
return 0xFEEDF00D;
|
||||
}
|
||||
STDMETHOD(CreateViewObject)(
|
||||
HWND hwndOwner,
|
||||
REFIID riid,
|
||||
LPVOID *ppvOut) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHOD(GetAttributesOf)(
|
||||
UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl,
|
||||
DWORD *rgfInOut) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHOD(GetUIObjectOf)(
|
||||
HWND hwndOwner,
|
||||
UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl,
|
||||
REFIID riid,
|
||||
UINT * prgfInOut,
|
||||
LPVOID * ppvOut) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHOD(GetDisplayNameOf)(
|
||||
PCUITEMID_CHILD pidl,
|
||||
DWORD dwFlags,
|
||||
LPSTRRET strRet) override
|
||||
{
|
||||
switch (s_nStep)
|
||||
{
|
||||
case 0:
|
||||
ok_long(dwFlags, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR | SHGDN_FOREDITING |
|
||||
SHGDN_INFOLDER);
|
||||
break;
|
||||
case 1:
|
||||
ok_long(dwFlags, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR | SHGDN_INFOLDER);
|
||||
break;
|
||||
case 2:
|
||||
ok_long(dwFlags, SHGDN_FORPARSING | SHGDN_INFOLDER);
|
||||
break;
|
||||
case 3:
|
||||
ok_long(dwFlags, SHGDN_FORPARSING);
|
||||
break;
|
||||
case 4:
|
||||
ok_long(dwFlags, SHGDN_FORADDRESSBAR | SHGDN_FOREDITING | SHGDN_INFOLDER);
|
||||
break;
|
||||
case 5:
|
||||
ok_long(dwFlags, SHGDN_FORADDRESSBAR | SHGDN_INFOLDER);
|
||||
break;
|
||||
case 6:
|
||||
ok_long(dwFlags, SHGDN_INFOLDER);
|
||||
break;
|
||||
case 7:
|
||||
ok_long(dwFlags, SHGDN_FORPARSING | SHGDN_INFOLDER);
|
||||
break;
|
||||
case 8:
|
||||
ok_long(dwFlags, SHGDN_INFOLDER);
|
||||
break;
|
||||
case 9:
|
||||
ok_long(dwFlags, SHGDN_NORMAL);
|
||||
break;
|
||||
default:
|
||||
skip("\n");
|
||||
break;
|
||||
}
|
||||
++s_nStep;
|
||||
return E_FAIL;
|
||||
}
|
||||
STDMETHOD(SetNameOf)(
|
||||
HWND hwndOwner,
|
||||
PCUITEMID_CHILD pidl,
|
||||
LPCOLESTR lpName,
|
||||
DWORD dwFlags,
|
||||
PITEMID_CHILD *pPidlOut) override
|
||||
{
|
||||
ok_int(TRUE, FALSE);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
};
|
||||
|
||||
static void Test_GetDisplayNameOf(void)
|
||||
{
|
||||
CTestShellFolder *psf = new CTestShellFolder();
|
||||
HRESULT hr;
|
||||
|
||||
hr = IShellFolder_GetDisplayNameOf(
|
||||
psf,
|
||||
NULL,
|
||||
SHGDN_FOREDITING | SHGDN_FORADDRESSBAR | SHGDN_FORPARSING | SHGDN_INFOLDER,
|
||||
NULL,
|
||||
0);
|
||||
ok_long(hr, E_FAIL);
|
||||
ok_int(s_nStep, 4);
|
||||
|
||||
hr = IShellFolder_GetDisplayNameOf(
|
||||
psf,
|
||||
NULL,
|
||||
SHGDN_FOREDITING | SHGDN_FORADDRESSBAR | SHGDN_INFOLDER,
|
||||
NULL,
|
||||
0);
|
||||
ok_long(hr, E_FAIL);
|
||||
ok_int(s_nStep, 10);
|
||||
|
||||
if (s_nStep != 10)
|
||||
skip("s_nStep value is wrong\n");
|
||||
|
||||
delete psf;
|
||||
}
|
||||
|
||||
static void Test_ParseDisplayName(void)
|
||||
{
|
||||
CTestShellFolder *psf = new CTestShellFolder();
|
||||
HRESULT hr;
|
||||
|
||||
s_nStep = 10;
|
||||
LPITEMIDLIST pidl = (LPITEMIDLIST)UlongToPtr(0xDEADDEAD);
|
||||
hr = IShellFolder_ParseDisplayName(
|
||||
psf,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&pidl,
|
||||
NULL);
|
||||
ok_long(hr, 0xDEADFACE);
|
||||
ok_int(s_nStep, 11);
|
||||
|
||||
delete psf;
|
||||
}
|
||||
|
||||
typedef HRESULT (WINAPI *FN_IShellFolder_CompareIDs)(
|
||||
_In_ IShellFolder *psf,
|
||||
_In_ LPARAM lParam,
|
||||
_In_ PCUIDLIST_RELATIVE pidl1,
|
||||
_In_ PCUIDLIST_RELATIVE pidl2);
|
||||
|
||||
static void Test_CompareIDs(void)
|
||||
{
|
||||
FN_IShellFolder_CompareIDs fnIShellFolder_CompareIDs;
|
||||
fnIShellFolder_CompareIDs =
|
||||
(FN_IShellFolder_CompareIDs)
|
||||
GetProcAddress(GetModuleHandleA("shlwapi"), MAKEINTRESOURCEA(551));
|
||||
|
||||
if (IsWindowsVistaOrGreater())
|
||||
{
|
||||
skip("Vista+\n");
|
||||
ok(fnIShellFolder_CompareIDs == NULL, "Vista+ has no IShellFolder_CompareIDs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CTestShellFolder *psf = new CTestShellFolder();
|
||||
HRESULT hr;
|
||||
|
||||
s_nStep = 11;
|
||||
hr = fnIShellFolder_CompareIDs(
|
||||
psf,
|
||||
0xFFFF1234,
|
||||
NULL,
|
||||
NULL);
|
||||
ok_long(hr, 0xFEEDF00D);
|
||||
ok_int(s_nStep, 13);
|
||||
|
||||
s_nStep = 13;
|
||||
hr = fnIShellFolder_CompareIDs(
|
||||
psf,
|
||||
0x00005678,
|
||||
NULL,
|
||||
NULL);
|
||||
ok_long(hr, 0xFEEDF00D);
|
||||
ok_int(s_nStep, 14);
|
||||
|
||||
delete psf;
|
||||
}
|
||||
|
||||
START_TEST(IShellFolderHelpers)
|
||||
{
|
||||
HRESULT hrCoInit = ::CoInitialize(NULL);
|
||||
|
||||
Test_GetDisplayNameOf();
|
||||
Test_ParseDisplayName();
|
||||
Test_CompareIDs();
|
||||
|
||||
if (SUCCEEDED(hrCoInit))
|
||||
::CoUninitialize();
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
extern void func_AssocQueryString(void);
|
||||
extern void func_PathFileExistsDefExtAndAttributesW(void);
|
||||
extern void func_PathFindOnPath(void);
|
||||
extern void func_IShellFolderHelpers(void);
|
||||
extern void func_isuncpath(void);
|
||||
extern void func_isuncpathserver(void);
|
||||
extern void func_isuncpathservershare(void);
|
||||
|
@ -22,6 +23,7 @@ const struct test winetest_testlist[] =
|
|||
{ "AssocQueryString", func_AssocQueryString },
|
||||
{ "PathFileExistsDefExtAndAttributesW", func_PathFileExistsDefExtAndAttributesW },
|
||||
{ "PathFindOnPath", func_PathFindOnPath },
|
||||
{ "IShellFolderHelpers", func_IShellFolderHelpers },
|
||||
{ "PathIsUNC", func_isuncpath },
|
||||
{ "PathIsUNCServer", func_isuncpathserver },
|
||||
{ "PathIsUNCServerShare", func_isuncpathservershare },
|
||||
|
|
|
@ -341,12 +341,13 @@ HRESULT WINAPI
|
|||
IShellFolder_GetDisplayNameOf(
|
||||
_In_ IShellFolder *psf,
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_In_ DWORD uFlags,
|
||||
_In_ SHGDNF uFlags,
|
||||
_Out_ LPSTRRET lpName,
|
||||
_In_ DWORD dwRetryFlags);
|
||||
|
||||
/* Flags for IShellFolder_GetDisplayNameOf */
|
||||
#define SFGDNO_RETRYWITHFORPARSING 1
|
||||
#define SFGDNO_RETRYWITHFORPARSING 0x00000001
|
||||
#define SFGDNO_RETRYALWAYS 0x80000000
|
||||
|
||||
HRESULT WINAPI
|
||||
IShellFolder_ParseDisplayName(
|
||||
|
|
Loading…
Reference in a new issue