[SHELL32] Fix ParseDisplayName Part 4 (#6747)

Follow-up to #6746. Reduce SHParseDisplayName
failures.
JIRA issue: CORE-19495
- Re-implement CDrivesFolder::ParseDisplayName
  method.
This commit is contained in:
Katayama Hirofumi MZ 2024-04-15 03:25:20 +09:00 committed by GitHub
parent 63e5885b37
commit b1de3bfb2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -4,7 +4,7 @@
* Copyright 1997 Marcus Meissner * Copyright 1997 Marcus Meissner
* Copyright 1998, 1999, 2002 Juergen Schmied * Copyright 1998, 1999, 2002 Juergen Schmied
* Copyright 2009 Andrew Hill * Copyright 2009 Andrew Hill
* Copyright 2017-2019 Katayama Hirofumi MZ * Copyright 2017-2024 Katayama Hirofumi MZ
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -658,67 +658,70 @@ HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLEST
DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes) DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes)
{ {
HRESULT hr = E_INVALIDARG; HRESULT hr = E_INVALIDARG;
LPCWSTR szNext = NULL;
LPITEMIDLIST pidlTemp = NULL;
INT nDriveNumber;
TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this, TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
pchEaten, ppidl, pdwAttributes); pchEaten, ppidl, pdwAttributes);
*ppidl = 0; if (!ppidl)
if (pchEaten) return hr;
*pchEaten = 0; /* strange but like the original */
*ppidl = NULL;
if (!lpszDisplayName)
return hr;
/* handle CLSID paths */ /* handle CLSID paths */
if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') if (lpszDisplayName[0] == L':' && lpszDisplayName[1] == L':')
return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
nDriveNumber = PathGetDriveNumberW(lpszDisplayName);
if (nDriveNumber < 0)
return E_INVALIDARG;
/* check if this drive actually exists */
if ((::GetLogicalDrives() & (1 << nDriveNumber)) == 0)
{ {
return HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE); return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl,
pdwAttributes);
} }
pidlTemp = _ILCreateDrive(lpszDisplayName); if (lpszDisplayName[0] &&
if (!pidlTemp) ((L'A' <= lpszDisplayName[0] && lpszDisplayName[0] <= L'Z') ||
return E_OUTOFMEMORY; (L'a' <= lpszDisplayName[0] && lpszDisplayName[0] <= L'z')) &&
lpszDisplayName[1] == L':' && lpszDisplayName[2] == L'\\')
{
// "C:\..."
WCHAR szRoot[8];
PathBuildRootW(szRoot, ((*lpszDisplayName - 1) & 0x1F));
if (lpszDisplayName[2] == L'\\') if (SHIsFileSysBindCtx(pbc, NULL) != S_OK && !(BindCtx_GetMode(pbc, 0) & STGM_CREATE))
{
szNext = &lpszDisplayName[3];
}
if (szNext && *szNext)
{
hr = SHELL32_ParseNextElement (this, hwndOwner, pbc, &pidlTemp,
(LPOLESTR) szNext, pchEaten, pdwAttributes);
}
else
{
hr = S_OK;
if (pdwAttributes && *pdwAttributes)
{ {
if (_ILIsDrive(pidlTemp)) if (::GetDriveType(szRoot) == DRIVE_NO_ROOT_DIR)
{ return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
*pdwAttributes &= dwDriveAttributes; }
if (_ILGetDriveType(pidlTemp) == DRIVE_CDROM) CComHeapPtr<ITEMIDLIST> pidlTemp(_ILCreateDrive(szRoot));
*pdwAttributes &= ~SFGAO_CANRENAME; // CD-ROM drive cannot rename if (!pidlTemp)
} return E_OUTOFMEMORY;
else if (_ILIsSpecialFolder(pidlTemp))
m_regFolder->GetAttributesOf(1, &pidlTemp, pdwAttributes); if (lpszDisplayName[3])
else {
ERR("Got unknown pidl\n"); CComPtr<IShellFolder> pChildFolder;
hr = BindToObject(pidlTemp, pbc, IID_PPV_ARG(IShellFolder, &pChildFolder));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
ULONG chEaten;
CComHeapPtr<ITEMIDLIST> pidlChild;
hr = pChildFolder->ParseDisplayName(hwndOwner, pbc, &lpszDisplayName[3], &chEaten,
&pidlChild, pdwAttributes);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = SHILCombine(pidlTemp, pidlChild, ppidl);
}
else
{
*ppidl = pidlTemp.Detach();
if (pdwAttributes && *pdwAttributes)
GetAttributesOf(1, (PCUITEMID_CHILD_ARRAY)ppidl, pdwAttributes);
hr = S_OK;
} }
} }
*ppidl = pidlTemp;
TRACE("(%p)->(-- ret=0x%08x)\n", this, hr); TRACE("(%p)->(-- ret=0x%08x)\n", this, hr);
return hr; return hr;