[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:
Katayama Hirofumi MZ 2023-11-29 22:50:01 +09:00 committed by GitHub
parent ea8a49d81f
commit 2aeda3dc15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 183 additions and 18 deletions

View file

@ -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;
}