mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +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
|
||||
*/
|
||||
EXTERN_C BOOL
|
||||
WINAPI
|
||||
PathIsEqualOrSubFolder(LPWSTR lpFolder, LPWSTR lpSubFolder)
|
||||
{
|
||||
FIXME("PathIsEqualOrSubFolder() stub\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EXTERN_C HRESULT
|
||||
WINAPI
|
||||
SHGetUnreadMailCountW(HKEY hKeyUser,
|
||||
|
|
|
@ -747,3 +747,119 @@ SHStartNetConnectionDialogA(
|
|||
|
||||
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.
|
||||
*/
|
||||
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
|
||||
HRESULT WINAPI
|
||||
SHGetPathCchFromIDListW(
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_Out_writes_(cchPathMax) LPWSTR pszPath,
|
||||
_In_ SIZE_T cchPathMax)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPCITEMIDLIST pidlLast;
|
||||
|
@ -1306,33 +1310,40 @@ BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
|
|||
TRACE_(shell)("(pidl=%p,%p)\n", pidl, pszPath);
|
||||
pdump(pidl);
|
||||
|
||||
*pszPath = '\0';
|
||||
*pszPath = UNICODE_NULL;
|
||||
if (!pidl)
|
||||
return FALSE;
|
||||
return E_FAIL;
|
||||
|
||||
hr = SHBindToParent(pidl, &IID_IShellFolder, (VOID**)&psfFolder, &pidlLast);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERR("SHBindToParent failed: %x\n", hr);
|
||||
return FALSE;
|
||||
return hr;
|
||||
}
|
||||
|
||||
dwAttributes = SFGAO_FILESYSTEM;
|
||||
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);
|
||||
IShellFolder_Release(psfFolder);
|
||||
return FALSE;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
hr = IShellFolder_GetDisplayNameOf(psfFolder, pidlLast, SHGDN_FORPARSING, &strret);
|
||||
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);
|
||||
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
|
||||
IShellFolderViewCB.cpp
|
||||
OpenAs_RunDLL.cpp
|
||||
PathIsEqualOrSubFolder.cpp
|
||||
PathResolve.cpp
|
||||
SHAppBarMessage.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_menu(void);
|
||||
extern void func_OpenAs_RunDLL(void);
|
||||
extern void func_PathIsEqualOrSubFolder(void);
|
||||
extern void func_PathResolve(void);
|
||||
extern void func_SHAppBarMessage(void);
|
||||
extern void func_SHChangeNotify(void);
|
||||
|
@ -57,6 +58,7 @@ const struct test winetest_testlist[] =
|
|||
{ "IShellFolderViewCB", func_IShellFolderViewCB },
|
||||
{ "menu", func_menu },
|
||||
{ "OpenAs_RunDLL", func_OpenAs_RunDLL },
|
||||
{ "PathIsEqualOrSubFolder", func_PathIsEqualOrSubFolder },
|
||||
{ "PathResolve", func_PathResolve },
|
||||
{ "SHAppBarMessage", func_SHAppBarMessage },
|
||||
{ "SHChangeNotify", func_SHChangeNotify },
|
||||
|
|
|
@ -498,6 +498,8 @@ BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2);
|
|||
|
||||
BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID *sOtherDirs);
|
||||
|
||||
BOOL WINAPI PathIsEqualOrSubFolder(_In_ LPCWSTR pszFile1OrCSIDL, _In_ LPCWSTR pszFile2);
|
||||
|
||||
/****************************************************************************
|
||||
* Shell File Operations error codes - SHFileOperationA/W
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue