mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[SHELL32][SHELL32_APITEST][SDK] Implement PathIsEqualOrSubFolder (#5714)
Implement PathIsEqualOrSubFolder function. - Add it to <undocshell.h>. - Add PathIsEqualOrSubFolder testcase. - Add SHGetPathCchFromIDListW as an extension of SHGetPathFromIDListW. CORE-19278
This commit is contained in:
parent
ea8a49d81f
commit
2aeda3dc15
7 changed files with 183 additions and 18 deletions
|
@ -17,14 +17,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
/*
|
/*
|
||||||
* Unimplemented
|
* Unimplemented
|
||||||
*/
|
*/
|
||||||
EXTERN_C BOOL
|
|
||||||
WINAPI
|
|
||||||
PathIsEqualOrSubFolder(LPWSTR lpFolder, LPWSTR lpSubFolder)
|
|
||||||
{
|
|
||||||
FIXME("PathIsEqualOrSubFolder() stub\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERN_C HRESULT
|
EXTERN_C HRESULT
|
||||||
WINAPI
|
WINAPI
|
||||||
SHGetUnreadMailCountW(HKEY hKeyUser,
|
SHGetUnreadMailCountW(HKEY hKeyUser,
|
||||||
|
|
|
@ -747,3 +747,119 @@ SHStartNetConnectionDialogA(
|
||||||
|
|
||||||
return SHStartNetConnectionDialogW(hwnd, pszRemoteNameW, dwType);
|
return SHStartNetConnectionDialogW(hwnd, pszRemoteNameW, dwType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* Helper functions for PathIsEqualOrSubFolder
|
||||||
|
*/
|
||||||
|
|
||||||
|
static INT
|
||||||
|
DynamicPathCommonPrefixW(
|
||||||
|
_In_ LPCWSTR lpszPath1,
|
||||||
|
_In_ LPCWSTR lpszPath2,
|
||||||
|
_Out_ CStringW& strPath)
|
||||||
|
{
|
||||||
|
SIZE_T cchPath1 = wcslen(lpszPath1);
|
||||||
|
SIZE_T cchPath2 = wcslen(lpszPath2);
|
||||||
|
LPWSTR lpszPath = strPath.GetBuffer((INT)max(cchPath1, cchPath2) + 16);
|
||||||
|
INT ret = PathCommonPrefixW(lpszPath1, lpszPath2, lpszPath);
|
||||||
|
strPath.ReleaseBuffer();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C HRESULT WINAPI
|
||||||
|
SHGetPathCchFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, SIZE_T cchPathMax);
|
||||||
|
|
||||||
|
static HRESULT
|
||||||
|
DynamicSHGetPathFromIDListW(
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_Out_ CStringW& strPath)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
for (UINT cchPath = MAX_PATH;; cchPath *= 2)
|
||||||
|
{
|
||||||
|
LPWSTR lpszPath = strPath.GetBuffer(cchPath);
|
||||||
|
if (!lpszPath)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
hr = SHGetPathCchFromIDListW(pidl, lpszPath, cchPath);
|
||||||
|
strPath.ReleaseBuffer();
|
||||||
|
|
||||||
|
if (hr != E_NOT_SUFFICIENT_BUFFER)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (cchPath >= MAXUINT / 2)
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
strPath.Empty();
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT
|
||||||
|
DynamicSHGetSpecialFolderPathW(
|
||||||
|
_In_ HWND hwndOwner,
|
||||||
|
_Out_ CStringW& strPath,
|
||||||
|
_In_ INT nCSIDL,
|
||||||
|
_In_ BOOL bCreate)
|
||||||
|
{
|
||||||
|
LPITEMIDLIST pidl;
|
||||||
|
HRESULT hr = SHGetSpecialFolderLocation(hwndOwner, nCSIDL, &pidl);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = DynamicSHGetPathFromIDListW(pidl, strPath);
|
||||||
|
CoTaskMemFree(pidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
strPath.Empty();
|
||||||
|
else if (bCreate)
|
||||||
|
CreateDirectoryW(strPath, NULL);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
DynamicPathRemoveBackslashW(
|
||||||
|
_Out_ CStringW& strPath)
|
||||||
|
{
|
||||||
|
INT nLength = strPath.GetLength();
|
||||||
|
if (nLength > 0 && strPath[nLength - 1] == L'\\')
|
||||||
|
strPath = strPath.Left(nLength - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* PathIsEqualOrSubFolder (SHELL32.755)
|
||||||
|
*/
|
||||||
|
EXTERN_C
|
||||||
|
BOOL WINAPI
|
||||||
|
PathIsEqualOrSubFolder(
|
||||||
|
_In_ LPCWSTR pszPath1OrCSIDL,
|
||||||
|
_In_ LPCWSTR pszPath2)
|
||||||
|
{
|
||||||
|
CStringW strCommon, strPath1;
|
||||||
|
|
||||||
|
TRACE("(%s %s)\n", debugstr_w(pszPath1OrCSIDL), debugstr_w(pszPath2));
|
||||||
|
|
||||||
|
if (IS_INTRESOURCE(pszPath1OrCSIDL))
|
||||||
|
{
|
||||||
|
DynamicSHGetSpecialFolderPathW(
|
||||||
|
NULL, strPath1, LOWORD(pszPath1OrCSIDL) | CSIDL_FLAG_DONT_VERIFY, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strPath1 = pszPath1OrCSIDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicPathRemoveBackslashW(strPath1);
|
||||||
|
|
||||||
|
if (!DynamicPathCommonPrefixW(strPath1, pszPath2, strCommon))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return strPath1.CompareNoCase(strCommon) == 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1295,7 +1295,11 @@ BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
|
||||||
*
|
*
|
||||||
* See SHGetPathFromIDListA.
|
* See SHGetPathFromIDListA.
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
|
HRESULT WINAPI
|
||||||
|
SHGetPathCchFromIDListW(
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_Out_writes_(cchPathMax) LPWSTR pszPath,
|
||||||
|
_In_ SIZE_T cchPathMax)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
LPCITEMIDLIST pidlLast;
|
LPCITEMIDLIST pidlLast;
|
||||||
|
@ -1306,33 +1310,40 @@ BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
|
||||||
TRACE_(shell)("(pidl=%p,%p)\n", pidl, pszPath);
|
TRACE_(shell)("(pidl=%p,%p)\n", pidl, pszPath);
|
||||||
pdump(pidl);
|
pdump(pidl);
|
||||||
|
|
||||||
*pszPath = '\0';
|
*pszPath = UNICODE_NULL;
|
||||||
if (!pidl)
|
if (!pidl)
|
||||||
return FALSE;
|
return E_FAIL;
|
||||||
|
|
||||||
hr = SHBindToParent(pidl, &IID_IShellFolder, (VOID**)&psfFolder, &pidlLast);
|
hr = SHBindToParent(pidl, &IID_IShellFolder, (VOID**)&psfFolder, &pidlLast);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ERR("SHBindToParent failed: %x\n", hr);
|
ERR("SHBindToParent failed: %x\n", hr);
|
||||||
return FALSE;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwAttributes = SFGAO_FILESYSTEM;
|
dwAttributes = SFGAO_FILESYSTEM;
|
||||||
hr = IShellFolder_GetAttributesOf(psfFolder, 1, &pidlLast, &dwAttributes);
|
hr = IShellFolder_GetAttributesOf(psfFolder, 1, &pidlLast, &dwAttributes);
|
||||||
if (FAILED(hr) || !(dwAttributes & SFGAO_FILESYSTEM)) {
|
if (FAILED(hr) || !(dwAttributes & SFGAO_FILESYSTEM))
|
||||||
|
{
|
||||||
WARN("Wrong dwAttributes or GetAttributesOf failed: %x\n", hr);
|
WARN("Wrong dwAttributes or GetAttributesOf failed: %x\n", hr);
|
||||||
IShellFolder_Release(psfFolder);
|
IShellFolder_Release(psfFolder);
|
||||||
return FALSE;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IShellFolder_GetDisplayNameOf(psfFolder, pidlLast, SHGDN_FORPARSING, &strret);
|
hr = IShellFolder_GetDisplayNameOf(psfFolder, pidlLast, SHGDN_FORPARSING, &strret);
|
||||||
IShellFolder_Release(psfFolder);
|
IShellFolder_Release(psfFolder);
|
||||||
if (FAILED(hr)) return FALSE;
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
hr = StrRetToBufW(&strret, pidlLast, pszPath, MAX_PATH);
|
hr = StrRetToBufW(&strret, pidlLast, pszPath, cchPathMax);
|
||||||
|
|
||||||
TRACE_(shell)("-- %s, 0x%08x\n",debugstr_w(pszPath), hr);
|
TRACE_(shell)("-- %s, 0x%08x\n",debugstr_w(pszPath), hr);
|
||||||
return SUCCEEDED(hr);
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
|
||||||
|
{
|
||||||
|
return SUCCEEDED(SHGetPathCchFromIDListW(pidl, pszPath, MAX_PATH));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
|
@ -19,6 +19,7 @@ list(APPEND SOURCE
|
||||||
Int64ToString.cpp
|
Int64ToString.cpp
|
||||||
IShellFolderViewCB.cpp
|
IShellFolderViewCB.cpp
|
||||||
OpenAs_RunDLL.cpp
|
OpenAs_RunDLL.cpp
|
||||||
|
PathIsEqualOrSubFolder.cpp
|
||||||
PathResolve.cpp
|
PathResolve.cpp
|
||||||
SHAppBarMessage.cpp
|
SHAppBarMessage.cpp
|
||||||
SHChangeNotify.cpp
|
SHChangeNotify.cpp
|
||||||
|
|
41
modules/rostests/apitests/shell32/PathIsEqualOrSubFolder.cpp
Normal file
41
modules/rostests/apitests/shell32/PathIsEqualOrSubFolder.cpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS API Tests
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Tests for PathIsEqualOrSubFolder
|
||||||
|
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shelltest.h"
|
||||||
|
#include <undocshell.h>
|
||||||
|
|
||||||
|
START_TEST(PathIsEqualOrSubFolder)
|
||||||
|
{
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:", L"C:"), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:", L"C:\\"), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:\\", L"C:"), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:\\", L"C:\\"), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:\\", L"C:\\TestTestTest"), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:\\TestTestTest", L"C:\\"), FALSE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:\\TestTestTest", L"C:\\TestTestTest"), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(L"C:\\TestTestTest", L"C:\\TestTestTest\\"), TRUE);
|
||||||
|
|
||||||
|
WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH];
|
||||||
|
|
||||||
|
GetWindowsDirectoryW(szPath1, _countof(szPath1));
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath1, szPath1), TRUE);
|
||||||
|
|
||||||
|
GetWindowsDirectoryW(szPath2, _countof(szPath2));
|
||||||
|
PathAppendW(szPath2, L"TestTestTest");
|
||||||
|
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath1, szPath2), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath2, szPath1), FALSE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath2, szPath2), TRUE);
|
||||||
|
|
||||||
|
GetTempPathW(_countof(szPath1), szPath1);
|
||||||
|
GetTempPathW(_countof(szPath2), szPath2);
|
||||||
|
PathAppendW(szPath2, L"TestTestTest");
|
||||||
|
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath1, szPath2), TRUE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath2, szPath1), FALSE);
|
||||||
|
ok_int(PathIsEqualOrSubFolder(szPath2, szPath2), TRUE);
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ extern void func_Int64ToString(void);
|
||||||
extern void func_IShellFolderViewCB(void);
|
extern void func_IShellFolderViewCB(void);
|
||||||
extern void func_menu(void);
|
extern void func_menu(void);
|
||||||
extern void func_OpenAs_RunDLL(void);
|
extern void func_OpenAs_RunDLL(void);
|
||||||
|
extern void func_PathIsEqualOrSubFolder(void);
|
||||||
extern void func_PathResolve(void);
|
extern void func_PathResolve(void);
|
||||||
extern void func_SHAppBarMessage(void);
|
extern void func_SHAppBarMessage(void);
|
||||||
extern void func_SHChangeNotify(void);
|
extern void func_SHChangeNotify(void);
|
||||||
|
@ -57,6 +58,7 @@ const struct test winetest_testlist[] =
|
||||||
{ "IShellFolderViewCB", func_IShellFolderViewCB },
|
{ "IShellFolderViewCB", func_IShellFolderViewCB },
|
||||||
{ "menu", func_menu },
|
{ "menu", func_menu },
|
||||||
{ "OpenAs_RunDLL", func_OpenAs_RunDLL },
|
{ "OpenAs_RunDLL", func_OpenAs_RunDLL },
|
||||||
|
{ "PathIsEqualOrSubFolder", func_PathIsEqualOrSubFolder },
|
||||||
{ "PathResolve", func_PathResolve },
|
{ "PathResolve", func_PathResolve },
|
||||||
{ "SHAppBarMessage", func_SHAppBarMessage },
|
{ "SHAppBarMessage", func_SHAppBarMessage },
|
||||||
{ "SHChangeNotify", func_SHChangeNotify },
|
{ "SHChangeNotify", func_SHChangeNotify },
|
||||||
|
|
|
@ -498,6 +498,8 @@ BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2);
|
||||||
|
|
||||||
BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID *sOtherDirs);
|
BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID *sOtherDirs);
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsEqualOrSubFolder(_In_ LPCWSTR pszFile1OrCSIDL, _In_ LPCWSTR pszFile2);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Shell File Operations error codes - SHFileOperationA/W
|
* Shell File Operations error codes - SHFileOperationA/W
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue