mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[SHELL32] Fix ParseDisplayName Part 2 (#6740)
Follow-up to #6721. Reduce SHParseDisplayName failures. JIRA issue: CORE-19495 - Re-implement CFSFolder::ParseDisplayName method to validate the names. - Add CFSFolder::_ParseSimple, CFSFolder::_GetFindDataFromName, and CFSFolder::_CreateIDListFromName helper methods. - Add PathIsDotOrDotDotW, PathIsValidElement, PathIsDosDevice, and SHILAppend helper functions. - Delete GetNextElementW and add Shell_NextElement function.
This commit is contained in:
parent
f61e14f554
commit
7fdec96009
6 changed files with 288 additions and 138 deletions
|
@ -4,7 +4,7 @@
|
||||||
* PURPOSE: file system folder
|
* PURPOSE: file system folder
|
||||||
* COPYRIGHT: Copyright 1997 Marcus Meissner
|
* COPYRIGHT: Copyright 1997 Marcus Meissner
|
||||||
* Copyright 1998, 1999, 2002 Juergen Schmied
|
* Copyright 1998, 1999, 2002 Juergen Schmied
|
||||||
* Copyright 2019 Katayama Hirofumi MZ
|
* Copyright 2019-2024 Katayama Hirofumi MZ
|
||||||
* Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
|
* Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -539,46 +539,6 @@ static const shvheader GenericSFHeader[] = {
|
||||||
|
|
||||||
#define GENERICSHELLVIEWCOLUMNS 6
|
#define GENERICSHELLVIEWCOLUMNS 6
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* SHELL32_CreatePidlFromBindCtx [internal]
|
|
||||||
*
|
|
||||||
* If the caller bound File System Bind Data, assume it is the
|
|
||||||
* find data for the path.
|
|
||||||
* This allows binding of paths that don't exist.
|
|
||||||
*/
|
|
||||||
LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
|
|
||||||
{
|
|
||||||
IFileSystemBindData *fsbd = NULL;
|
|
||||||
LPITEMIDLIST pidl = NULL;
|
|
||||||
IUnknown *param = NULL;
|
|
||||||
WIN32_FIND_DATAW wfd;
|
|
||||||
HRESULT r;
|
|
||||||
|
|
||||||
TRACE("%p %s\n", pbc, debugstr_w(path));
|
|
||||||
|
|
||||||
if (!pbc)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* see if the caller bound File System Bind Data */
|
|
||||||
r = pbc->GetObjectParam((LPOLESTR)STR_FILE_SYS_BIND_DATA, ¶m);
|
|
||||||
if (FAILED(r))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
r = param->QueryInterface(IID_PPV_ARG(IFileSystemBindData,&fsbd));
|
|
||||||
if (SUCCEEDED(r))
|
|
||||||
{
|
|
||||||
r = fsbd->GetFindData(&wfd);
|
|
||||||
if (SUCCEEDED(r))
|
|
||||||
{
|
|
||||||
lstrcpynW(&wfd.cFileName[0], path, MAX_PATH);
|
|
||||||
pidl = _ILCreateFromFindDataW(&wfd);
|
|
||||||
}
|
|
||||||
fsbd->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pidl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder)
|
static HRESULT SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, LPCWSTR KeyName, CLSID* pclsidFolder)
|
||||||
{
|
{
|
||||||
WCHAR wszCLSIDValue[CHARS_IN_GUID];
|
WCHAR wszCLSIDValue[CHARS_IN_GUID];
|
||||||
|
@ -705,6 +665,91 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT CFSFolder::_ParseSimple(
|
||||||
|
_In_ LPOLESTR lpszDisplayName,
|
||||||
|
_Out_ WIN32_FIND_DATAW *pFind,
|
||||||
|
_Out_ LPITEMIDLIST *ppidl)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
LPWSTR pchNext = lpszDisplayName;
|
||||||
|
|
||||||
|
*ppidl = NULL;
|
||||||
|
|
||||||
|
LPITEMIDLIST pidl;
|
||||||
|
for (hr = S_OK; SUCCEEDED(hr); hr = SHILAppend(pidl, ppidl))
|
||||||
|
{
|
||||||
|
hr = Shell_NextElement(&pchNext, pFind->cFileName, _countof(pFind->cFileName), FALSE);
|
||||||
|
if (hr != S_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (pchNext)
|
||||||
|
pFind->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
|
||||||
|
pidl = _ILCreateFromFindDataW(pFind);
|
||||||
|
if (!pidl)
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
if (*ppidl)
|
||||||
|
{
|
||||||
|
ILFree(*ppidl);
|
||||||
|
*ppidl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CFSFolder::_GetFindDataFromName(_In_ LPCWSTR pszName, _Out_ WIN32_FIND_DATAW *pFind)
|
||||||
|
{
|
||||||
|
WCHAR szPath[MAX_PATH];
|
||||||
|
lstrcpynW(szPath, m_sPathTarget, _countof(szPath));
|
||||||
|
PathAppendW(szPath, pszName);
|
||||||
|
|
||||||
|
HANDLE hFind = ::FindFirstFileW(szPath, pFind);
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
::FindClose(hFind);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CFSFolder::_CreateIDListFromName(LPCWSTR pszName, DWORD attrs, IBindCtx *pbc, LPITEMIDLIST *ppidl)
|
||||||
|
{
|
||||||
|
*ppidl = NULL;
|
||||||
|
|
||||||
|
if (PathIsDosDevice(pszName))
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_BAD_DEVICE);
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW FindData = { 0 };
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (attrs == ULONG_MAX) // Invalid attributes
|
||||||
|
{
|
||||||
|
if (!_GetFindDataFromName(pszName, &FindData))
|
||||||
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
||||||
|
}
|
||||||
|
else // Pretend as an item of attrs
|
||||||
|
{
|
||||||
|
StringCchCopyW(FindData.cFileName, _countof(FindData.cFileName), pszName);
|
||||||
|
FindData.dwFileAttributes = attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
*ppidl = _ILCreateFromFindDataW(&FindData);
|
||||||
|
if (!*ppidl)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* CFSFolder::ParseDisplayName {SHELL32}
|
* CFSFolder::ParseDisplayName {SHELL32}
|
||||||
*
|
*
|
||||||
|
@ -736,13 +781,6 @@ HRESULT WINAPI CFSFolder::ParseDisplayName(HWND hwndOwner,
|
||||||
DWORD *pchEaten, PIDLIST_RELATIVE *ppidl,
|
DWORD *pchEaten, PIDLIST_RELATIVE *ppidl,
|
||||||
DWORD *pdwAttributes)
|
DWORD *pdwAttributes)
|
||||||
{
|
{
|
||||||
HRESULT hr = E_INVALIDARG;
|
|
||||||
LPCWSTR szNext = NULL;
|
|
||||||
WCHAR szElement[MAX_PATH];
|
|
||||||
WCHAR szPath[MAX_PATH];
|
|
||||||
LPITEMIDLIST pidlTemp = NULL;
|
|
||||||
DWORD len;
|
|
||||||
|
|
||||||
TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
|
TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
|
||||||
this, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
|
this, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
|
||||||
pchEaten, ppidl, pdwAttributes);
|
pchEaten, ppidl, pdwAttributes);
|
||||||
|
@ -750,68 +788,85 @@ HRESULT WINAPI CFSFolder::ParseDisplayName(HWND hwndOwner,
|
||||||
if (!ppidl)
|
if (!ppidl)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if (!lpszDisplayName)
|
|
||||||
{
|
|
||||||
*ppidl = NULL;
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppidl = NULL;
|
*ppidl = NULL;
|
||||||
|
|
||||||
if (pchEaten)
|
if (!lpszDisplayName)
|
||||||
*pchEaten = 0; /* strange but like the original */
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if (*lpszDisplayName)
|
HRESULT hr;
|
||||||
|
WIN32_FIND_DATAW FindData;
|
||||||
|
if (SHIsFileSysBindCtx(pbc, &FindData) == S_OK)
|
||||||
{
|
{
|
||||||
/* get the next element */
|
CComHeapPtr<ITEMIDLIST> pidlTemp;
|
||||||
szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
|
hr = _ParseSimple(lpszDisplayName, &FindData, &pidlTemp);
|
||||||
|
if (SUCCEEDED(hr) && pdwAttributes && *pdwAttributes)
|
||||||
pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, szElement);
|
|
||||||
if (pidlTemp != NULL)
|
|
||||||
{
|
{
|
||||||
/* We are creating an id list without ensuring that the items exist.
|
LPCITEMIDLIST pidlLast = ILFindLastID(pidlTemp);
|
||||||
If we have a remaining path, this must be a folder.
|
GetAttributesOf(1, &pidlLast, pdwAttributes);
|
||||||
We have to do it now because it is set as a file by default */
|
|
||||||
if (szNext)
|
|
||||||
{
|
|
||||||
pidlTemp->mkid.abID[0] = PT_FOLDER;
|
|
||||||
}
|
|
||||||
hr = S_OK;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* build the full pathname to the element */
|
|
||||||
lstrcpynW(szPath, m_sPathTarget, MAX_PATH - 1);
|
|
||||||
PathAddBackslashW(szPath);
|
|
||||||
len = wcslen(szPath);
|
|
||||||
lstrcpynW(szPath + len, szElement, MAX_PATH - len);
|
|
||||||
|
|
||||||
/* get the pidl */
|
if (SUCCEEDED(hr))
|
||||||
hr = _ILCreateFromPathW(szPath, &pidlTemp);
|
*ppidl = pidlTemp.Detach();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
INT cchElement = lstrlenW(lpszDisplayName) + 1;
|
||||||
|
LPWSTR pszElement = (LPWSTR)alloca(cchElement * sizeof(WCHAR));
|
||||||
|
LPWSTR pchNext = lpszDisplayName;
|
||||||
|
hr = Shell_NextElement(&pchNext, pszElement, cchElement, TRUE);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = _CreateIDListFromName(pszElement, ULONG_MAX, pbc, ppidl);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
if (pchNext) // Is there the next element?
|
||||||
|
{
|
||||||
|
// pszElement seems like a directory
|
||||||
|
if (_GetFindDataFromName(pszElement, &FindData) &&
|
||||||
|
(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
|
{
|
||||||
|
hr = _CreateIDListFromName(pszElement, FILE_ATTRIBUTE_DIRECTORY, pbc, ppidl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// pszElement seems like a non-directory
|
||||||
|
if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
|
||||||
|
hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) &&
|
||||||
|
(BindCtx_GetMode(pbc, 0) & STGM_CREATE))
|
||||||
|
{
|
||||||
|
// Pretend like a normal file
|
||||||
|
hr = _CreateIDListFromName(pszElement, FILE_ATTRIBUTE_NORMAL, pbc, ppidl);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
if (szNext && *szNext)
|
if (pchNext) // Is there next?
|
||||||
{
|
{
|
||||||
/* try to analyse the next element */
|
CComPtr<IShellFolder> psfChild;
|
||||||
hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
|
hr = BindToObject(*ppidl, pbc, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||||
&pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
DWORD chEaten;
|
||||||
|
CComHeapPtr<ITEMIDLIST> pidlChild;
|
||||||
|
hr = psfChild->ParseDisplayName(hwndOwner, pbc, pchNext, &chEaten, &pidlChild,
|
||||||
|
pdwAttributes);
|
||||||
|
|
||||||
|
// Append pidlChild to ppidl
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = SHILAppend(pidlChild.Detach(), ppidl);
|
||||||
}
|
}
|
||||||
else
|
else if (pdwAttributes && *pdwAttributes)
|
||||||
{
|
{
|
||||||
/* it's the last element */
|
GetAttributesOf(1, (LPCITEMIDLIST*)ppidl, pdwAttributes);
|
||||||
if (pdwAttributes && *pdwAttributes)
|
|
||||||
hr = SHELL32_GetFSItemAttributes(this, pidlTemp, pdwAttributes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
*ppidl = pidlTemp;
|
|
||||||
else
|
|
||||||
*ppidl = NULL;
|
|
||||||
|
|
||||||
TRACE("(%p)->(-- pidl=%p ret=0x%08x)\n", this, ppidl ? *ppidl : 0, hr);
|
TRACE("(%p)->(-- pidl=%p ret=0x%08x)\n", this, ppidl ? *ppidl : 0, hr);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
|
|
|
@ -33,6 +33,14 @@ class CFSFolder :
|
||||||
HRESULT _CreateExtensionUIObject(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut);
|
HRESULT _CreateExtensionUIObject(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut);
|
||||||
HRESULT _GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut);
|
HRESULT _GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut);
|
||||||
HRESULT _GetIconHandler(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut);
|
HRESULT _GetIconHandler(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut);
|
||||||
|
|
||||||
|
HRESULT _ParseSimple(
|
||||||
|
_In_ LPOLESTR lpszDisplayName,
|
||||||
|
_Out_ WIN32_FIND_DATAW *pFind,
|
||||||
|
_Out_ LPITEMIDLIST *ppidl);
|
||||||
|
BOOL _GetFindDataFromName(_In_ LPCWSTR pszName, _Out_ WIN32_FIND_DATAW *pFind);
|
||||||
|
HRESULT _CreateIDListFromName(LPCWSTR pszName, DWORD attrs, IBindCtx *pbc, LPITEMIDLIST *ppidl);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CFSFolder();
|
CFSFolder();
|
||||||
~CFSFolder();
|
~CFSFolder();
|
||||||
|
|
|
@ -161,8 +161,9 @@ Shell_TranslateIDListAlias(
|
||||||
_In_ DWORD dwFlags);
|
_In_ DWORD dwFlags);
|
||||||
|
|
||||||
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName);
|
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName);
|
||||||
|
DWORD BindCtx_GetMode(_In_ IBindCtx *pbc, _In_ DWORD dwDefault);
|
||||||
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid);
|
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid);
|
||||||
HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW **ppFindData);
|
HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW *pFindData);
|
||||||
BOOL Shell_FailForceReturn(_In_ HRESULT hr);
|
BOOL Shell_FailForceReturn(_In_ HRESULT hr);
|
||||||
|
|
||||||
EXTERN_C INT
|
EXTERN_C INT
|
||||||
|
@ -211,4 +212,9 @@ BindCtx_RegisterObjectParam(
|
||||||
_In_opt_ IUnknown *punk,
|
_In_opt_ IUnknown *punk,
|
||||||
_Out_ LPBC *ppbc);
|
_Out_ LPBC *ppbc);
|
||||||
|
|
||||||
|
BOOL PathIsDotOrDotDotW(_In_ LPCWSTR pszPath);
|
||||||
|
BOOL PathIsValidElement(_In_ LPCWSTR pszPath);
|
||||||
|
BOOL PathIsDosDevice(_In_ LPCWSTR pszName);
|
||||||
|
HRESULT SHILAppend(_Inout_ LPITEMIDLIST pidl, _Inout_ LPITEMIDLIST *ppidl);
|
||||||
|
|
||||||
#endif /* _PRECOMP_H__ */
|
#endif /* _PRECOMP_H__ */
|
||||||
|
|
|
@ -36,14 +36,18 @@ typedef struct {
|
||||||
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
|
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
|
||||||
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
|
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
|
||||||
|
|
||||||
LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut);
|
HRESULT
|
||||||
|
Shell_NextElement(
|
||||||
|
_Inout_ LPWSTR *ppch,
|
||||||
|
_Out_ LPWSTR pszOut,
|
||||||
|
_In_ INT cchOut,
|
||||||
|
_In_ BOOL bValidate);
|
||||||
|
|
||||||
HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut,
|
HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut,
|
||||||
LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes);
|
LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes);
|
||||||
|
|
||||||
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet);
|
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet);
|
||||||
|
|
||||||
LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path);
|
|
||||||
|
|
||||||
HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
|
HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
|
||||||
|
|
||||||
HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
|
HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
|
||||||
|
|
|
@ -26,45 +26,54 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
/***************************************************************************
|
HRESULT
|
||||||
* GetNextElement (internal function)
|
Shell_NextElement(
|
||||||
*
|
_Inout_ LPWSTR *ppch,
|
||||||
* Gets a part of a string till the first backslash.
|
_Out_ LPWSTR pszOut,
|
||||||
*
|
_In_ INT cchOut,
|
||||||
* PARAMETERS
|
_In_ BOOL bValidate)
|
||||||
* pszNext [IN] string to get the element from
|
|
||||||
* pszOut [IN] pointer to buffer which receives string
|
|
||||||
* dwOut [IN] length of pszOut
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* LPSTR pointer to first, not yet parsed char
|
|
||||||
*/
|
|
||||||
|
|
||||||
LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut)
|
|
||||||
{
|
{
|
||||||
LPCWSTR pszTail = pszNext;
|
*pszOut = UNICODE_NULL;
|
||||||
DWORD dwCopy;
|
|
||||||
|
|
||||||
TRACE ("(%s %p 0x%08x)\n", debugstr_w (pszNext), pszOut, dwOut);
|
if (!*ppch)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
*pszOut = 0x0000;
|
HRESULT hr;
|
||||||
|
LPWSTR pchNext = wcschr(*ppch, L'\\');
|
||||||
|
if (pchNext)
|
||||||
|
{
|
||||||
|
if (*ppch < pchNext)
|
||||||
|
{
|
||||||
|
/* Get an element */
|
||||||
|
StringCchCopyNW(pszOut, cchOut, *ppch, pchNext - *ppch);
|
||||||
|
++pchNext;
|
||||||
|
|
||||||
if (!pszNext || !*pszNext)
|
if (!*pchNext)
|
||||||
return NULL;
|
pchNext = NULL; /* No next */
|
||||||
|
|
||||||
while (*pszTail && (*pszTail != (WCHAR) '\\'))
|
hr = S_OK;
|
||||||
pszTail++;
|
}
|
||||||
|
else /* Double backslashes found? */
|
||||||
|
{
|
||||||
|
pchNext = NULL;
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* No more next */
|
||||||
|
{
|
||||||
|
StringCchCopyW(pszOut, cchOut, *ppch);
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
dwCopy = pszTail - pszNext + 1;
|
*ppch = pchNext; /* Go next */
|
||||||
lstrcpynW (pszOut, pszNext, (dwOut < dwCopy) ? dwOut : dwCopy);
|
|
||||||
|
|
||||||
if (*pszTail)
|
if (hr == S_OK && bValidate && !PathIsValidElement(pszOut))
|
||||||
pszTail++;
|
{
|
||||||
else
|
*pszOut = UNICODE_NULL;
|
||||||
pszTail = NULL;
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE ("--(%s %s 0x%08x %p)\n", debugstr_w (pszNext), debugstr_w (pszOut), dwOut, pszTail);
|
return hr;
|
||||||
return pszTail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc,
|
HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc,
|
||||||
|
|
|
@ -9,6 +9,68 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
BOOL PathIsDotOrDotDotW(_In_ LPCWSTR pszPath)
|
||||||
|
{
|
||||||
|
if (pszPath[0] != L'.')
|
||||||
|
return FALSE;
|
||||||
|
return !pszPath[1] || (pszPath[1] == L'.' && !pszPath[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PATH_VALID_ELEMENT ( \
|
||||||
|
PATH_CHAR_CLASS_DOT | PATH_CHAR_CLASS_SEMICOLON | PATH_CHAR_CLASS_COMMA | \
|
||||||
|
PATH_CHAR_CLASS_SPACE | PATH_CHAR_CLASS_OTHER_VALID \
|
||||||
|
)
|
||||||
|
|
||||||
|
BOOL PathIsValidElement(_In_ LPCWSTR pszPath)
|
||||||
|
{
|
||||||
|
if (!*pszPath || PathIsDotOrDotDotW(pszPath))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (LPCWSTR pch = pszPath; *pch; ++pch)
|
||||||
|
{
|
||||||
|
if (!PathIsValidCharW(*pch, PATH_VALID_ELEMENT))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL PathIsDosDevice(_In_ LPCWSTR pszName)
|
||||||
|
{
|
||||||
|
WCHAR szPath[MAX_PATH];
|
||||||
|
StringCchCopyW(szPath, _countof(szPath), pszName);
|
||||||
|
PathRemoveExtensionW(szPath);
|
||||||
|
|
||||||
|
if (lstrcmpiW(szPath, L"NUL") == 0 || lstrcmpiW(szPath, L"PRN") == 0 ||
|
||||||
|
lstrcmpiW(szPath, L"CON") == 0 || lstrcmpiW(szPath, L"AUX") == 0)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_wcsnicmp(szPath, L"LPT", 3) == 0 || _wcsnicmp(szPath, L"COM", 3) == 0)
|
||||||
|
{
|
||||||
|
if ((L'0' <= szPath[3] && szPath[3] <= L'9') && szPath[4] == UNICODE_NULL)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT SHILAppend(_Inout_ LPITEMIDLIST pidl, _Inout_ LPITEMIDLIST *ppidl)
|
||||||
|
{
|
||||||
|
LPITEMIDLIST pidlOld = *ppidl;
|
||||||
|
if (!pidlOld)
|
||||||
|
{
|
||||||
|
*ppidl = pidl;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = SHILCombine(*ppidl, pidl, ppidl);
|
||||||
|
ILFree(pidlOld);
|
||||||
|
ILFree(pidl);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
OpenEffectiveToken(
|
OpenEffectiveToken(
|
||||||
_In_ DWORD DesiredAccess,
|
_In_ DWORD DesiredAccess,
|
||||||
|
@ -49,6 +111,19 @@ BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD BindCtx_GetMode(_In_ IBindCtx *pbc, _In_ DWORD dwDefault)
|
||||||
|
{
|
||||||
|
if (!pbc)
|
||||||
|
return dwDefault;
|
||||||
|
|
||||||
|
BIND_OPTS BindOpts = { sizeof(BindOpts) };
|
||||||
|
HRESULT hr = pbc->GetBindOptions(&BindOpts);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return dwDefault;
|
||||||
|
|
||||||
|
return BindOpts.grfMode;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid)
|
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid)
|
||||||
{
|
{
|
||||||
if (!pbc)
|
if (!pbc)
|
||||||
|
@ -61,7 +136,7 @@ BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid)
|
||||||
return pclsid && SHSkipJunction(pbc, pclsid);
|
return pclsid && SHSkipJunction(pbc, pclsid);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW **ppFindData)
|
HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW *pFindData)
|
||||||
{
|
{
|
||||||
CComPtr<IUnknown> punk;
|
CComPtr<IUnknown> punk;
|
||||||
CComPtr<IFileSystemBindData> pBindData;
|
CComPtr<IFileSystemBindData> pBindData;
|
||||||
|
@ -72,17 +147,10 @@ HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW *
|
||||||
if (FAILED(punk->QueryInterface(IID_PPV_ARG(IFileSystemBindData, &pBindData))))
|
if (FAILED(punk->QueryInterface(IID_PPV_ARG(IFileSystemBindData, &pBindData))))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
if (pFindData)
|
||||||
if (ppFindData)
|
pBindData->GetFindData(pFindData);
|
||||||
{
|
|
||||||
*ppFindData = (WIN32_FIND_DATAW*)LocalAlloc(LPTR, sizeof(WIN32_FIND_DATAW));
|
|
||||||
if (*ppFindData)
|
|
||||||
pBindData->GetFindData(*ppFindData);
|
|
||||||
else
|
|
||||||
hr = E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL Shell_FailForceReturn(_In_ HRESULT hr)
|
BOOL Shell_FailForceReturn(_In_ HRESULT hr)
|
||||||
|
|
Loading…
Reference in a new issue