mirror of
https://github.com/reactos/reactos.git
synced 2024-10-31 20:02:55 +00:00
[SHELL32][SDK] Fix ParseDisplayName Part 1 (#6721)
JIRA issue: CORE-19495 - Implement SHParseDisplayName and CDesktopFolder::ParseDisplayName. - Add CStubFolderBase, CShellUrlStub, CFileUrlStub, CIDListUrlStub, and CHttpUrlStub helper classes. - Add SHGetSpecialFolderID and Shell_ParseSpecialFolder helper functions. - Add BindCtx_ContainsObject, BindCtx_GetUIWindow, BindCtx_RegisterObjectParam, SHBindToObject, SHBindToObjectEx, SHCoInitializeAnyApartment, SHGetAttributes, SHGetNameAndFlagsW, SHIsFileSysBindCtx, SHSkipJunctionBinding, Shell_DisplayNameOf, and Shell_FailForceReturn helper functions. - Modify CSIDL data.
This commit is contained in:
parent
e85ef799fe
commit
d05dcf6a02
|
@ -24,6 +24,223 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
STDMETHODIMP
|
||||||
|
CShellUrlStub::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
|
||||||
|
{
|
||||||
|
LPWSTR pch;
|
||||||
|
INT cch, csidl;
|
||||||
|
HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
||||||
|
PARSEDURLW ParsedURL = { sizeof(ParsedURL) };
|
||||||
|
|
||||||
|
::ParseURLW(lpszDisplayName, &ParsedURL);
|
||||||
|
|
||||||
|
DWORD attrs = (pdwAttributes ? *pdwAttributes : 0) | SFGAO_STREAM;
|
||||||
|
if (ParsedURL.pszSuffix[0] == L':' && ParsedURL.pszSuffix[1] == L':')
|
||||||
|
{
|
||||||
|
CComPtr<IShellFolder> psfDesktop;
|
||||||
|
hr = SHGetDesktopFolder(&psfDesktop);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CComPtr<IBindCtx> pBindCtx;
|
||||||
|
hr = ::CreateBindCtx(0, &pBindCtx);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
BIND_OPTS BindOps = { sizeof(BindOps) };
|
||||||
|
BindOps.grfMode = STGM_CREATE;
|
||||||
|
pBindCtx->SetBindOptions(&BindOps);
|
||||||
|
hr = psfDesktop->ParseDisplayName(hwndOwner, pBindCtx,
|
||||||
|
(LPWSTR)ParsedURL.pszSuffix,
|
||||||
|
pchEaten, ppidl, &attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
csidl = Shell_ParseSpecialFolder(ParsedURL.pszSuffix, &pch, &cch);
|
||||||
|
if (csidl == -1)
|
||||||
|
{
|
||||||
|
ERR("\n");
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CComHeapPtr<ITEMIDLIST> pidlLocation;
|
||||||
|
hr = SHGetFolderLocation(hwndOwner, (csidl | CSIDL_FLAG_CREATE), NULL, 0, &pidlLocation);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (pch && *pch)
|
||||||
|
{
|
||||||
|
CComPtr<IShellFolder> psfFolder;
|
||||||
|
hr = SHBindToObject(NULL, pidlLocation, IID_PPV_ARG(IShellFolder, &psfFolder));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CComHeapPtr<ITEMIDLIST> pidlNew;
|
||||||
|
hr = psfFolder->ParseDisplayName(hwndOwner, pbc, pch, pchEaten, &pidlNew, &attrs);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = SHILCombine(pidlLocation, pidlNew, ppidl);
|
||||||
|
if (pchEaten)
|
||||||
|
*pchEaten += cch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (attrs)
|
||||||
|
hr = SHGetNameAndFlagsW(pidlLocation, 0, NULL, 0, &attrs);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (pchEaten)
|
||||||
|
*pchEaten = cch;
|
||||||
|
*ppidl = pidlLocation.Detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: SHWindowsPolicy
|
||||||
|
if (SUCCEEDED(hr) && (attrs & SFGAO_STREAM) &&
|
||||||
|
!BindCtx_ContainsObject(pbc, STR_PARSE_SHELL_PROTOCOL_TO_FILE_OBJECTS))
|
||||||
|
{
|
||||||
|
ILFree(*ppidl);
|
||||||
|
*ppidl = NULL;
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdwAttributes)
|
||||||
|
*pdwAttributes = attrs;
|
||||||
|
|
||||||
|
// FIXME: SHWindowsPolicy
|
||||||
|
if (FAILED(hr) && !Shell_FailForceReturn(hr))
|
||||||
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP
|
||||||
|
CFileUrlStub::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
|
||||||
|
{
|
||||||
|
WCHAR szPath[MAX_PATH];
|
||||||
|
DWORD cchPath = _countof(szPath);
|
||||||
|
HRESULT hr = PathCreateFromUrlW(lpszDisplayName, szPath, &cchPath, 0);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
CComPtr<IShellFolder> psfDesktop;
|
||||||
|
hr = SHGetDesktopFolder(&psfDesktop);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
return psfDesktop->ParseDisplayName(hwndOwner, pbc, szPath, pchEaten, ppidl, pdwAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP
|
||||||
|
CIDListUrlStub::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL; // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP
|
||||||
|
CHttpUrlStub::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL; // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CDesktopFolder::_TryUrlJunctions(
|
||||||
|
LPCWSTR pcszURL,
|
||||||
|
IBindCtx *pBindCtx,
|
||||||
|
IShellFolder **ppShellFolder,
|
||||||
|
LPITEMIDLIST *ppidl)
|
||||||
|
{
|
||||||
|
PARSEDURLW ParsedURL = { sizeof(ParsedURL) };
|
||||||
|
::ParseURLW(pcszURL, &ParsedURL);
|
||||||
|
|
||||||
|
*ppShellFolder = NULL;
|
||||||
|
switch (ParsedURL.nScheme)
|
||||||
|
{
|
||||||
|
case URL_SCHEME_FILE:
|
||||||
|
*ppShellFolder = &m_FileUrlStub;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case URL_SCHEME_HTTP:
|
||||||
|
case URL_SCHEME_HTTPS:
|
||||||
|
if (!BindCtx_ContainsObject(pBindCtx, STR_PARSE_PREFER_FOLDER_BROWSING))
|
||||||
|
break;
|
||||||
|
*ppShellFolder = &m_HttpUrlStub;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case URL_SCHEME_SHELL:
|
||||||
|
*ppShellFolder = &m_ShellUrlStub;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case URL_SCHEME_MSSHELLROOTED:
|
||||||
|
*ppShellFolder = NULL; // FIXME
|
||||||
|
break;
|
||||||
|
|
||||||
|
case URL_SCHEME_MSSHELLIDLIST:
|
||||||
|
*ppShellFolder = &m_IDListUrlStub;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!*ppShellFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CDesktopFolder::_GetParentForParsing(
|
||||||
|
LPCWSTR pszPath,
|
||||||
|
IBindCtx *pbc,
|
||||||
|
IShellFolder **ppParentFolder,
|
||||||
|
LPITEMIDLIST *ppidlParent)
|
||||||
|
{
|
||||||
|
WCHAR wch = *pszPath;
|
||||||
|
if (((L'A' <= wch && wch <= L'Z') || (L'a' <= wch && wch <= L'z')) && (pszPath[1] == ':'))
|
||||||
|
*ppidlParent = _ILCreateMyComputer();
|
||||||
|
else if (PathIsUNCW(pszPath))
|
||||||
|
*ppidlParent = _ILCreateNetwork();
|
||||||
|
else if (UrlIsW(pszPath, URLIS_URL) && !SHSkipJunctionBinding(pbc, NULL))
|
||||||
|
_TryUrlJunctions(pszPath, pbc, ppParentFolder, ppidlParent);
|
||||||
|
|
||||||
|
if (!*ppParentFolder && *ppidlParent)
|
||||||
|
SHBindToObject(NULL, *ppidlParent, IID_PPV_ARG(IShellFolder, ppParentFolder));
|
||||||
|
|
||||||
|
return *ppParentFolder != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CDesktopFolder::_ChildParseDisplayName(
|
||||||
|
IShellFolder *pParentFolder,
|
||||||
|
LPCITEMIDLIST pidlParent,
|
||||||
|
HWND hwndOwner,
|
||||||
|
IBindCtx *pBindCtx,
|
||||||
|
LPWSTR lpszDisplayName,
|
||||||
|
DWORD *pchEaten,
|
||||||
|
LPITEMIDLIST *ppidl,
|
||||||
|
DWORD *pdwAttributes)
|
||||||
|
{
|
||||||
|
LPITEMIDLIST pidlChild;
|
||||||
|
HRESULT hr = pParentFolder->ParseDisplayName(hwndOwner, pBindCtx, lpszDisplayName,
|
||||||
|
pchEaten, &pidlChild, pdwAttributes);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (pidlParent)
|
||||||
|
{
|
||||||
|
*ppidl = ILCombine(pidlParent, pidlChild);
|
||||||
|
ILFree(pidlChild);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppidl = pidlChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*ppidl ? S_OK : E_OUTOFMEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CDesktopFolder should create two file system folders internally, one representing the
|
CDesktopFolder should create two file system folders internally, one representing the
|
||||||
user's desktop folder, and the other representing the common desktop folder. It should
|
user's desktop folder, and the other representing the common desktop folder. It should
|
||||||
|
@ -285,11 +502,6 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
|
||||||
PIDLIST_RELATIVE *ppidl,
|
PIDLIST_RELATIVE *ppidl,
|
||||||
DWORD *pdwAttributes)
|
DWORD *pdwAttributes)
|
||||||
{
|
{
|
||||||
LPCWSTR szNext = NULL;
|
|
||||||
LPITEMIDLIST pidlTemp = NULL;
|
|
||||||
PARSEDURLW urldata;
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -302,78 +514,98 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
|
||||||
if (!lpszDisplayName)
|
if (!lpszDisplayName)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if (pchEaten)
|
if (!*lpszDisplayName)
|
||||||
*pchEaten = 0; /* strange but like the original */
|
{
|
||||||
|
*ppidl = _ILCreateMyComputer();
|
||||||
urldata.cbSize = sizeof(urldata);
|
return (*ppidl ? S_OK : E_OUTOFMEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
|
if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
|
||||||
{
|
{
|
||||||
return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
|
return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl,
|
||||||
|
pdwAttributes);
|
||||||
}
|
}
|
||||||
else if (PathGetDriveNumberW (lpszDisplayName) >= 0)
|
|
||||||
|
HRESULT hr = E_INVALIDARG;
|
||||||
|
CComHeapPtr<ITEMIDLIST> pidlParent;
|
||||||
|
CComPtr<IShellFolder> pParentFolder;
|
||||||
|
if (_GetParentForParsing(lpszDisplayName, pbc, &pParentFolder, &pidlParent))
|
||||||
{
|
{
|
||||||
/* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */
|
if (pchEaten)
|
||||||
pidlTemp = _ILCreateMyComputer ();
|
*pchEaten = 0;
|
||||||
szNext = lpszDisplayName;
|
|
||||||
}
|
hr = _ChildParseDisplayName(pParentFolder,
|
||||||
else if (PathIsUNCW(lpszDisplayName))
|
pidlParent,
|
||||||
{
|
hwndOwner,
|
||||||
pidlTemp = _ILCreateNetwork();
|
pbc,
|
||||||
szNext = lpszDisplayName;
|
lpszDisplayName,
|
||||||
}
|
pchEaten,
|
||||||
else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) )
|
ppidl,
|
||||||
{
|
pdwAttributes);
|
||||||
*ppidl = pidlTemp;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
else if (SUCCEEDED(ParseURLW(lpszDisplayName, &urldata)))
|
|
||||||
{
|
|
||||||
if (urldata.nScheme == URL_SCHEME_SHELL) /* handle shell: urls */
|
|
||||||
{
|
|
||||||
TRACE ("-- shell url: %s\n", debugstr_w(urldata.pszSuffix));
|
|
||||||
pidlTemp = _ILCreateGuidFromStrW(urldata.pszSuffix + 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return IEParseDisplayNameWithBCW(CP_ACP, lpszDisplayName, pbc, ppidl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*lpszDisplayName)
|
|
||||||
{
|
|
||||||
/* it's a filesystem path on the desktop. Let a FSFolder parse it */
|
|
||||||
hr = m_DesktopFSFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (BindCtx_ContainsObject(pbc, STR_PARSE_TRANSLATE_ALIASES))
|
||||||
|
{
|
||||||
|
LPITEMIDLIST pidlAlias;
|
||||||
|
if (SUCCEEDED(Shell_TranslateIDListAlias(*ppidl, NULL, &pidlAlias, 0xFFFF)))
|
||||||
|
{
|
||||||
|
ILFree(*ppidl);
|
||||||
|
*ppidl = pidlAlias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Shell_FailForceReturn(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
return m_SharedDesktopFSFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
|
if (BindCtx_ContainsObject(pbc, STR_DONT_PARSE_RELATIVE))
|
||||||
}
|
return E_INVALIDARG;
|
||||||
else
|
|
||||||
pidlTemp = _ILCreateMyComputer();
|
|
||||||
|
|
||||||
szNext = NULL;
|
if (SHIsFileSysBindCtx(pbc, NULL) == S_OK)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
BIND_OPTS BindOps = { sizeof(BindOps) };
|
||||||
|
BOOL bCreate = FALSE;
|
||||||
|
if (pbc && SUCCEEDED(pbc->GetBindOptions(&BindOps)) && (BindOps.grfMode & STGM_CREATE))
|
||||||
|
{
|
||||||
|
BindOps.grfMode &= ~STGM_CREATE;
|
||||||
|
bCreate = TRUE;
|
||||||
|
pbc->SetBindOptions(&BindOps);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && pidlTemp)
|
if (m_DesktopFSFolder)
|
||||||
{
|
{
|
||||||
if (szNext && *szNext)
|
hr = m_DesktopFSFolder->ParseDisplayName(hwndOwner,
|
||||||
{
|
pbc,
|
||||||
hr = SHELL32_ParseNextElement(this, hwndOwner, pbc,
|
lpszDisplayName,
|
||||||
&pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
|
pchEaten,
|
||||||
}
|
ppidl,
|
||||||
else
|
pdwAttributes);
|
||||||
{
|
|
||||||
if (pdwAttributes && *pdwAttributes)
|
|
||||||
{
|
|
||||||
GetAttributesOf(1, &pidlTemp, pdwAttributes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (FAILED(hr) && m_SharedDesktopFSFolder)
|
||||||
*ppidl = pidlTemp;
|
{
|
||||||
else
|
hr = m_SharedDesktopFSFolder->ParseDisplayName(hwndOwner,
|
||||||
*ppidl = NULL;
|
pbc,
|
||||||
|
lpszDisplayName,
|
||||||
|
pchEaten,
|
||||||
|
ppidl,
|
||||||
|
pdwAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr) && bCreate && m_DesktopFSFolder)
|
||||||
|
{
|
||||||
|
BindOps.grfMode |= STGM_CREATE;
|
||||||
|
pbc->SetBindOptions(&BindOps);
|
||||||
|
hr = m_DesktopFSFolder->ParseDisplayName(hwndOwner,
|
||||||
|
pbc,
|
||||||
|
lpszDisplayName,
|
||||||
|
pchEaten,
|
||||||
|
ppidl,
|
||||||
|
pdwAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
|
TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,73 @@
|
||||||
#ifndef _CDESKTOPFOLDER_H_
|
#ifndef _CDESKTOPFOLDER_H_
|
||||||
#define _CDESKTOPFOLDER_H_
|
#define _CDESKTOPFOLDER_H_
|
||||||
|
|
||||||
|
class CStubFolderBase : public IShellFolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CStubFolderBase() { }
|
||||||
|
|
||||||
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj) override { return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP_(ULONG) AddRef() override { return 3; }
|
||||||
|
STDMETHODIMP_(ULONG) Release() override { return 2; }
|
||||||
|
|
||||||
|
// IShellFolder methods
|
||||||
|
STDMETHODIMP ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
|
||||||
|
DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
|
||||||
|
REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName,
|
||||||
|
DWORD dwFlags, PITEMID_CHILD *pPidlOut) override
|
||||||
|
{ return E_NOTIMPL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CShellUrlStub : public CStubFolderBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STDMETHODIMP
|
||||||
|
ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFileUrlStub : public CStubFolderBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STDMETHODIMP
|
||||||
|
ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CIDListUrlStub : public CStubFolderBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STDMETHODIMP
|
||||||
|
ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHttpUrlStub : public CStubFolderBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
STDMETHODIMP
|
||||||
|
ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten,
|
||||||
|
PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
|
||||||
|
};
|
||||||
|
|
||||||
class CDesktopFolder :
|
class CDesktopFolder :
|
||||||
public CComCoClass<CDesktopFolder, &CLSID_ShellDesktop>,
|
public CComCoClass<CDesktopFolder, &CLSID_ShellDesktop>,
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
@ -37,11 +104,37 @@ class CDesktopFolder :
|
||||||
CComPtr<IShellFolder2> m_SharedDesktopFSFolder;
|
CComPtr<IShellFolder2> m_SharedDesktopFSFolder;
|
||||||
CComPtr<IShellFolder2> m_regFolder;
|
CComPtr<IShellFolder2> m_regFolder;
|
||||||
|
|
||||||
|
// Stub URL objects
|
||||||
|
CShellUrlStub m_ShellUrlStub;
|
||||||
|
CFileUrlStub m_FileUrlStub;
|
||||||
|
CIDListUrlStub m_IDListUrlStub;
|
||||||
|
CHttpUrlStub m_HttpUrlStub;
|
||||||
|
|
||||||
LPWSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
|
LPWSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
|
||||||
LPITEMIDLIST pidlRoot; /* absolute pidl */
|
LPITEMIDLIST pidlRoot; /* absolute pidl */
|
||||||
|
|
||||||
HRESULT _GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf);
|
HRESULT _GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf);
|
||||||
|
|
||||||
|
BOOL _TryUrlJunctions(
|
||||||
|
LPCWSTR pcszURL,
|
||||||
|
IBindCtx *pBindCtx,
|
||||||
|
IShellFolder **ppShellFolder,
|
||||||
|
LPITEMIDLIST *ppidl);
|
||||||
|
BOOL _GetParentForParsing(
|
||||||
|
LPCWSTR pszPath,
|
||||||
|
IBindCtx *pbc,
|
||||||
|
IShellFolder **ppParentFolder,
|
||||||
|
LPITEMIDLIST *ppidlParent);
|
||||||
|
HRESULT _ChildParseDisplayName(
|
||||||
|
IShellFolder *pParentFolder,
|
||||||
|
LPCITEMIDLIST pidlParent,
|
||||||
|
HWND hwndOwner,
|
||||||
|
IBindCtx *pBindCtx,
|
||||||
|
LPWSTR lpszDisplayName,
|
||||||
|
DWORD *pchEaten,
|
||||||
|
LPITEMIDLIST *ppidl,
|
||||||
|
DWORD *pdwAttributes);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDesktopFolder();
|
CDesktopFolder();
|
||||||
~CDesktopFolder();
|
~CDesktopFolder();
|
||||||
|
|
|
@ -153,4 +153,62 @@ public:
|
||||||
END_MSG_MAP()
|
END_MSG_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
Shell_TranslateIDListAlias(
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ HANDLE hToken,
|
||||||
|
_Out_ LPITEMIDLIST *ppidlAlias,
|
||||||
|
_In_ DWORD dwFlags);
|
||||||
|
|
||||||
|
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName);
|
||||||
|
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid);
|
||||||
|
HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW **ppFindData);
|
||||||
|
BOOL Shell_FailForceReturn(_In_ HRESULT hr);
|
||||||
|
|
||||||
|
EXTERN_C INT
|
||||||
|
Shell_ParseSpecialFolder(_In_ LPCWSTR pszStart, _Out_ LPWSTR *ppch, _Out_ INT *pcch);
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
Shell_DisplayNameOf(
|
||||||
|
_In_ IShellFolder *psf,
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ DWORD dwFlags,
|
||||||
|
_Out_ LPWSTR pszBuf,
|
||||||
|
_In_ UINT cchBuf);
|
||||||
|
|
||||||
|
HRESULT SHBindToObject(
|
||||||
|
_In_opt_ IShellFolder *psf,
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ REFIID riid,
|
||||||
|
_Out_ void **ppvObj);
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
SHBindToObjectEx(
|
||||||
|
_In_opt_ IShellFolder *pShellFolder,
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_opt_ IBindCtx *pBindCtx,
|
||||||
|
_In_ REFIID riid,
|
||||||
|
_Out_ void **ppvObj);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes);
|
||||||
|
HRESULT SHCoInitializeAnyApartment(VOID);
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
SHGetNameAndFlagsW(
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ DWORD dwFlags,
|
||||||
|
_Out_opt_ LPWSTR pszText,
|
||||||
|
_In_ UINT cchBuf,
|
||||||
|
_Inout_opt_ DWORD *pdwAttributes);
|
||||||
|
|
||||||
|
EXTERN_C HWND BindCtx_GetUIWindow(_In_ IBindCtx *pBindCtx);
|
||||||
|
|
||||||
|
EXTERN_C HRESULT
|
||||||
|
BindCtx_RegisterObjectParam(
|
||||||
|
_In_ IBindCtx *pBindCtx,
|
||||||
|
_In_ LPOLESTR pszKey,
|
||||||
|
_In_opt_ IUnknown *punk,
|
||||||
|
_Out_ LPBC *ppbc);
|
||||||
|
|
||||||
#endif /* _PRECOMP_H__ */
|
#endif /* _PRECOMP_H__ */
|
||||||
|
|
|
@ -31,6 +31,316 @@ OpenEffectiveToken(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
Shell_TranslateIDListAlias(
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ HANDLE hToken,
|
||||||
|
_Out_ LPITEMIDLIST *ppidlAlias,
|
||||||
|
_In_ DWORD dwFlags)
|
||||||
|
{
|
||||||
|
return E_FAIL; //FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName)
|
||||||
|
{
|
||||||
|
CComPtr<IUnknown> punk;
|
||||||
|
if (!pBindCtx || FAILED(pBindCtx->GetObjectParam(const_cast<LPWSTR>(pszName), &punk)))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid)
|
||||||
|
{
|
||||||
|
if (!pbc)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
BIND_OPTS BindOps = { sizeof(BindOps) };
|
||||||
|
if (SUCCEEDED(pbc->GetBindOptions(&BindOps)) && BindOps.grfFlags == OLECONTF_LINKS)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return pclsid && SHSkipJunction(pbc, pclsid);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT SHIsFileSysBindCtx(_In_ IBindCtx *pBindCtx, _Out_opt_ WIN32_FIND_DATAW **ppFindData)
|
||||||
|
{
|
||||||
|
CComPtr<IUnknown> punk;
|
||||||
|
CComPtr<IFileSystemBindData> pBindData;
|
||||||
|
|
||||||
|
if (!pBindCtx || FAILED(pBindCtx->GetObjectParam((LPWSTR)STR_FILE_SYS_BIND_DATA, &punk)))
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
if (FAILED(punk->QueryInterface(IID_PPV_ARG(IFileSystemBindData, &pBindData))))
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (ppFindData)
|
||||||
|
{
|
||||||
|
*ppFindData = (WIN32_FIND_DATAW*)LocalAlloc(LPTR, sizeof(WIN32_FIND_DATAW));
|
||||||
|
if (*ppFindData)
|
||||||
|
pBindData->GetFindData(*ppFindData);
|
||||||
|
else
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Shell_FailForceReturn(_In_ HRESULT hr)
|
||||||
|
{
|
||||||
|
DWORD code = HRESULT_CODE(hr);
|
||||||
|
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case ERROR_BAD_NETPATH:
|
||||||
|
case ERROR_BAD_NET_NAME:
|
||||||
|
case ERROR_CANCELLED:
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (ERROR_FILE_NOT_FOUND <= code && code <= ERROR_PATH_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
SHBindToObjectEx(
|
||||||
|
_In_opt_ IShellFolder *pShellFolder,
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_opt_ IBindCtx *pBindCtx,
|
||||||
|
_In_ REFIID riid,
|
||||||
|
_Out_ void **ppvObj)
|
||||||
|
{
|
||||||
|
CComPtr<IShellFolder> psfDesktop;
|
||||||
|
|
||||||
|
*ppvObj = NULL;
|
||||||
|
|
||||||
|
if (!pShellFolder)
|
||||||
|
{
|
||||||
|
SHGetDesktopFolder(&psfDesktop);
|
||||||
|
if (!psfDesktop)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
pShellFolder = psfDesktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
if (_ILIsDesktop(pidl))
|
||||||
|
hr = pShellFolder->QueryInterface(riid, ppvObj);
|
||||||
|
else
|
||||||
|
hr = pShellFolder->BindToObject(pidl, pBindCtx, riid, ppvObj);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && !*ppvObj)
|
||||||
|
hr = E_FAIL;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT SHBindToObject(
|
||||||
|
_In_opt_ IShellFolder *psf,
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ REFIID riid,
|
||||||
|
_Out_ void **ppvObj)
|
||||||
|
{
|
||||||
|
return SHBindToObjectEx(psf, pidl, NULL, riid, ppvObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
Shell_DisplayNameOf(
|
||||||
|
_In_ IShellFolder *psf,
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ DWORD dwFlags,
|
||||||
|
_Out_ LPWSTR pszBuf,
|
||||||
|
_In_ UINT cchBuf)
|
||||||
|
{
|
||||||
|
*pszBuf = UNICODE_NULL;
|
||||||
|
STRRET sr;
|
||||||
|
HRESULT hr = psf->GetDisplayNameOf(pidl, dwFlags, &sr);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
return StrRetToBufW(&sr, pidl, pszBuf, cchBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes)
|
||||||
|
{
|
||||||
|
LPCITEMIDLIST pidlLast;
|
||||||
|
|
||||||
|
if (psf)
|
||||||
|
{
|
||||||
|
psf->AddRef();
|
||||||
|
pidlLast = pidl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!psf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DWORD oldAttrs = dwAttributes;
|
||||||
|
if (FAILED(psf->GetAttributesOf(1, &pidlLast, &dwAttributes)))
|
||||||
|
dwAttributes = 0;
|
||||||
|
else
|
||||||
|
dwAttributes &= oldAttrs;
|
||||||
|
|
||||||
|
if ((dwAttributes & SFGAO_FOLDER) &&
|
||||||
|
(dwAttributes & SFGAO_STREAM) &&
|
||||||
|
!(dwAttributes & SFGAO_STORAGEANCESTOR) &&
|
||||||
|
(oldAttrs & SFGAO_STORAGEANCESTOR) &&
|
||||||
|
(SHGetObjectCompatFlags(psf, NULL) & 0x200))
|
||||||
|
{
|
||||||
|
dwAttributes &= ~(SFGAO_STREAM | SFGAO_STORAGEANCESTOR);
|
||||||
|
dwAttributes |= SFGAO_STORAGEANCESTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psf)
|
||||||
|
psf->Release();
|
||||||
|
|
||||||
|
return dwAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT SHCoInitializeAnyApartment(VOID)
|
||||||
|
{
|
||||||
|
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
if (FAILED(hr))
|
||||||
|
hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
SHGetNameAndFlagsW(
|
||||||
|
_In_ LPCITEMIDLIST pidl,
|
||||||
|
_In_ DWORD dwFlags,
|
||||||
|
_Out_opt_ LPWSTR pszText,
|
||||||
|
_In_ UINT cchBuf,
|
||||||
|
_Inout_opt_ DWORD *pdwAttributes)
|
||||||
|
{
|
||||||
|
if (pszText)
|
||||||
|
*pszText = UNICODE_NULL;
|
||||||
|
|
||||||
|
HRESULT hrCoInit = SHCoInitializeAnyApartment();
|
||||||
|
|
||||||
|
CComPtr<IShellFolder> psfFolder;
|
||||||
|
LPCITEMIDLIST ppidlLast;
|
||||||
|
HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psfFolder), &ppidlLast);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (pszText)
|
||||||
|
hr = Shell_DisplayNameOf(psfFolder, ppidlLast, dwFlags, pszText, cchBuf);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (pdwAttributes)
|
||||||
|
*pdwAttributes = SHGetAttributes(psfFolder, ppidlLast, *pdwAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hrCoInit))
|
||||||
|
CoUninitialize();
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_C HWND
|
||||||
|
BindCtx_GetUIWindow(_In_ IBindCtx *pBindCtx)
|
||||||
|
{
|
||||||
|
HWND hWnd = NULL;
|
||||||
|
|
||||||
|
CComPtr<IUnknown> punk;
|
||||||
|
if (pBindCtx && SUCCEEDED(pBindCtx->GetObjectParam((LPWSTR)L"UI During Binding", &punk)))
|
||||||
|
IUnknown_GetWindow(punk, &hWnd);
|
||||||
|
|
||||||
|
return hWnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CDummyOleWindow : public IOleWindow
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
LONG m_cRefs;
|
||||||
|
HWND m_hWnd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CDummyOleWindow() : m_cRefs(1), m_hWnd(NULL) { }
|
||||||
|
virtual ~CDummyOleWindow() { }
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj) override
|
||||||
|
{
|
||||||
|
static const QITAB c_tab[] =
|
||||||
|
{
|
||||||
|
QITABENT(CDummyOleWindow, IOleWindow),
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
return ::QISearch(this, c_tab, riid, ppvObj);
|
||||||
|
}
|
||||||
|
STDMETHODIMP_(ULONG) AddRef() override
|
||||||
|
{
|
||||||
|
return ++m_cRefs;
|
||||||
|
}
|
||||||
|
STDMETHODIMP_(ULONG) Release() override
|
||||||
|
{
|
||||||
|
if (--m_cRefs == 0)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return m_cRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IOleWindow methods
|
||||||
|
STDMETHODIMP GetWindow(HWND *phWnd) override
|
||||||
|
{
|
||||||
|
*phWnd = m_hWnd;
|
||||||
|
if (!m_hWnd)
|
||||||
|
return E_NOTIMPL;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) override
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EXTERN_C HRESULT
|
||||||
|
BindCtx_RegisterObjectParam(
|
||||||
|
_In_ IBindCtx *pBindCtx,
|
||||||
|
_In_ LPOLESTR pszKey,
|
||||||
|
_In_opt_ IUnknown *punk,
|
||||||
|
_Out_ LPBC *ppbc)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
CDummyOleWindow *pUnknown = NULL;
|
||||||
|
|
||||||
|
*ppbc = pBindCtx;
|
||||||
|
|
||||||
|
if (pBindCtx)
|
||||||
|
{
|
||||||
|
pBindCtx->AddRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = CreateBindCtx(0, ppbc);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!punk)
|
||||||
|
punk = pUnknown = new CDummyOleWindow();
|
||||||
|
|
||||||
|
hr = (*ppbc)->RegisterObjectParam(pszKey, punk);
|
||||||
|
|
||||||
|
if (pUnknown)
|
||||||
|
pUnknown->Release();
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
(*ppbc)->Release();
|
||||||
|
*ppbc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* SHSetFolderPathA (SHELL32.231)
|
* SHSetFolderPathA (SHELL32.231)
|
||||||
*
|
*
|
||||||
|
|
|
@ -54,6 +54,15 @@ extern BOOL WINAPI Free(LPVOID);
|
||||||
static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl);
|
static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl);
|
||||||
static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl);
|
static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl);
|
||||||
|
|
||||||
|
EXTERN_C HWND BindCtx_GetUIWindow(_In_ IBindCtx *pBindCtx);
|
||||||
|
|
||||||
|
EXTERN_C HRESULT
|
||||||
|
BindCtx_RegisterObjectParam(
|
||||||
|
_In_ IBindCtx *pBindCtx,
|
||||||
|
_In_ LPOLESTR pszKey,
|
||||||
|
_In_opt_ IUnknown *punk,
|
||||||
|
_Out_ LPBC *ppbc);
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* ILGetDisplayNameExA
|
* ILGetDisplayNameExA
|
||||||
*
|
*
|
||||||
|
@ -1396,39 +1405,59 @@ HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCI
|
||||||
HRESULT WINAPI SHParseDisplayName(LPCWSTR pszName, IBindCtx *pbc,
|
HRESULT WINAPI SHParseDisplayName(LPCWSTR pszName, IBindCtx *pbc,
|
||||||
LPITEMIDLIST *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut)
|
LPITEMIDLIST *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut)
|
||||||
{
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
LPWSTR pszNameDup;
|
||||||
IShellFolder *psfDesktop;
|
IShellFolder *psfDesktop;
|
||||||
HRESULT hr=E_FAIL;
|
IBindCtx *pBindCtx = NULL;
|
||||||
ULONG dwAttr=sfgaoIn;
|
|
||||||
|
|
||||||
if(!ppidl)
|
TRACE("(%s, %p, %p, 0x%X, %p)\n", pszName, pbc, ppidl, sfgaoIn, psfgaoOut);
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
if (!pszName)
|
|
||||||
{
|
|
||||||
*ppidl = NULL;
|
*ppidl = NULL;
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (psfgaoOut)
|
||||||
|
*psfgaoOut = 0;
|
||||||
|
|
||||||
|
pszNameDup = StrDupW(pszName);
|
||||||
|
if (!pszNameDup)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
psfDesktop = NULL;
|
||||||
hr = SHGetDesktopFolder(&psfDesktop);
|
hr = SHGetDesktopFolder(&psfDesktop);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
*ppidl = NULL;
|
LocalFree(pszNameDup);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IShellFolder_ParseDisplayName(psfDesktop, (HWND)NULL, pbc, (LPOLESTR)pszName, (ULONG *)NULL, ppidl, &dwAttr);
|
if (!pbc)
|
||||||
|
{
|
||||||
IShellFolder_Release(psfDesktop);
|
hr = BindCtx_RegisterObjectParam(NULL, STR_PARSE_TRANSLATE_ALIASES, NULL, &pBindCtx);
|
||||||
|
pbc = pBindCtx;
|
||||||
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
if (psfgaoOut) *psfgaoOut = dwAttr;
|
ULONG sfgao = sfgaoIn, cchEaten;
|
||||||
}
|
HWND hwndUI = BindCtx_GetUIWindow(pbc);
|
||||||
else
|
hr = psfDesktop->lpVtbl->ParseDisplayName(psfDesktop,
|
||||||
{
|
hwndUI,
|
||||||
*ppidl = NULL;
|
pbc,
|
||||||
|
pszNameDup,
|
||||||
|
&cchEaten,
|
||||||
|
ppidl,
|
||||||
|
(psfgaoOut ? &sfgao : NULL));
|
||||||
|
if (SUCCEEDED(hr) && psfgaoOut)
|
||||||
|
*psfgaoOut = (sfgao & sfgaoIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalFree(pszNameDup);
|
||||||
|
|
||||||
|
if (psfDesktop)
|
||||||
|
psfDesktop->lpVtbl->Release(psfDesktop);
|
||||||
|
|
||||||
|
if (pBindCtx)
|
||||||
|
pBindCtx->lpVtbl->Release(pBindCtx);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1104,14 +1104,14 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
{ /* 0x03 - CSIDL_CONTROLS (.CPL files) */
|
{ /* 0x03 - CSIDL_CONTROLS (.CPL files) */
|
||||||
&FOLDERID_ControlPanelFolder,
|
&FOLDERID_ControlPanelFolder,
|
||||||
CSIDL_Type_SystemPath,
|
CSIDL_Type_SystemPath,
|
||||||
NULL,
|
L"ControlPanelFolder",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_CONTROL_PANEL
|
-IDI_SHELL_CONTROL_PANEL
|
||||||
},
|
},
|
||||||
{ /* 0x04 - CSIDL_PRINTERS */
|
{ /* 0x04 - CSIDL_PRINTERS */
|
||||||
&FOLDERID_PrintersFolder,
|
&FOLDERID_PrintersFolder,
|
||||||
CSIDL_Type_SystemPath,
|
CSIDL_Type_SystemPath,
|
||||||
NULL,
|
L"PrintersFolder",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_PRINTERS_FOLDER
|
-IDI_SHELL_PRINTERS_FOLDER
|
||||||
},
|
},
|
||||||
|
@ -1151,7 +1151,7 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
{ /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */
|
{ /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */
|
||||||
&FOLDERID_RecycleBinFolder,
|
&FOLDERID_RecycleBinFolder,
|
||||||
CSIDL_Type_Disallowed,
|
CSIDL_Type_Disallowed,
|
||||||
NULL,
|
L"RecycleBinFolder",
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
{ /* 0x0b - CSIDL_STARTMENU */
|
{ /* 0x0b - CSIDL_STARTMENU */
|
||||||
|
@ -1210,14 +1210,14 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
{ /* 0x11 - CSIDL_DRIVES */
|
{ /* 0x11 - CSIDL_DRIVES */
|
||||||
&FOLDERID_ComputerFolder,
|
&FOLDERID_ComputerFolder,
|
||||||
CSIDL_Type_Disallowed,
|
CSIDL_Type_Disallowed,
|
||||||
NULL,
|
L"MyComputerFolder",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_COMPUTER_FOLDER
|
-IDI_SHELL_COMPUTER_FOLDER
|
||||||
},
|
},
|
||||||
{ /* 0x12 - CSIDL_NETWORK */
|
{ /* 0x12 - CSIDL_NETWORK */
|
||||||
&FOLDERID_NetworkFolder,
|
&FOLDERID_NetworkFolder,
|
||||||
CSIDL_Type_Disallowed,
|
CSIDL_Type_Disallowed,
|
||||||
NULL,
|
L"NetworkPlacesFolder",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_NETWORK_FOLDER
|
-IDI_SHELL_NETWORK_FOLDER
|
||||||
},
|
},
|
||||||
|
@ -1341,21 +1341,21 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
{ /* 0x24 - CSIDL_WINDOWS */
|
{ /* 0x24 - CSIDL_WINDOWS */
|
||||||
&FOLDERID_Windows,
|
&FOLDERID_Windows,
|
||||||
CSIDL_Type_WindowsPath,
|
CSIDL_Type_WindowsPath,
|
||||||
NULL,
|
L"Windows",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_SYSTEM_GEAR
|
-IDI_SHELL_SYSTEM_GEAR
|
||||||
},
|
},
|
||||||
{ /* 0x25 - CSIDL_SYSTEM */
|
{ /* 0x25 - CSIDL_SYSTEM */
|
||||||
&FOLDERID_System,
|
&FOLDERID_System,
|
||||||
CSIDL_Type_SystemPath,
|
CSIDL_Type_SystemPath,
|
||||||
NULL,
|
L"System",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_SYSTEM_GEAR
|
-IDI_SHELL_SYSTEM_GEAR
|
||||||
},
|
},
|
||||||
{ /* 0x26 - CSIDL_PROGRAM_FILES */
|
{ /* 0x26 - CSIDL_PROGRAM_FILES */
|
||||||
&FOLDERID_ProgramFiles,
|
&FOLDERID_ProgramFiles,
|
||||||
CSIDL_Type_CurrVer,
|
CSIDL_Type_CurrVer,
|
||||||
L"ProgramFilesDir",
|
L"ProgramFiles",
|
||||||
MAKEINTRESOURCEW(IDS_PROGRAM_FILES),
|
MAKEINTRESOURCEW(IDS_PROGRAM_FILES),
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
0
|
0
|
||||||
|
@ -1390,21 +1390,21 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
{ /* 0x2a - CSIDL_PROGRAM_FILESX86 */
|
{ /* 0x2a - CSIDL_PROGRAM_FILESX86 */
|
||||||
&FOLDERID_ProgramFilesX86,
|
&FOLDERID_ProgramFilesX86,
|
||||||
CSIDL_Type_CurrVer,
|
CSIDL_Type_CurrVer,
|
||||||
L"ProgramFilesDir (x86)",
|
L"ProgramFilesX86",
|
||||||
L"Program Files (x86)",
|
L"Program Files (x86)",
|
||||||
-IDI_SHELL_PROGRAMS_FOLDER
|
-IDI_SHELL_PROGRAMS_FOLDER
|
||||||
},
|
},
|
||||||
{ /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */
|
{ /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */
|
||||||
&FOLDERID_ProgramFilesCommon,
|
&FOLDERID_ProgramFilesCommon,
|
||||||
CSIDL_Type_CurrVer,
|
CSIDL_Type_CurrVer,
|
||||||
L"CommonFilesDir",
|
L"ProgramFilesCommon",
|
||||||
MAKEINTRESOURCEW(IDS_PROGRAM_FILES_COMMON),
|
MAKEINTRESOURCEW(IDS_PROGRAM_FILES_COMMON),
|
||||||
-IDI_SHELL_PROGRAMS_FOLDER
|
-IDI_SHELL_PROGRAMS_FOLDER
|
||||||
},
|
},
|
||||||
{ /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */
|
{ /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */
|
||||||
&FOLDERID_ProgramFilesCommonX86,
|
&FOLDERID_ProgramFilesCommonX86,
|
||||||
CSIDL_Type_CurrVer,
|
CSIDL_Type_CurrVer,
|
||||||
L"CommonFilesDir (x86)",
|
L"ProgramFilesCommonX86",
|
||||||
L"Program Files (x86)\\Common Files",
|
L"Program Files (x86)\\Common Files",
|
||||||
-IDI_SHELL_PROGRAMS_FOLDER
|
-IDI_SHELL_PROGRAMS_FOLDER
|
||||||
},
|
},
|
||||||
|
@ -1436,7 +1436,7 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
{ /* 0x31 - CSIDL_CONNECTIONS */
|
{ /* 0x31 - CSIDL_CONNECTIONS */
|
||||||
&FOLDERID_ConnectionsFolder,
|
&FOLDERID_ConnectionsFolder,
|
||||||
CSIDL_Type_Disallowed,
|
CSIDL_Type_Disallowed,
|
||||||
NULL,
|
L"ConnectionsFolder",
|
||||||
NULL,
|
NULL,
|
||||||
-IDI_SHELL_NETWORK_CONNECTIONS
|
-IDI_SHELL_NETWORK_CONNECTIONS
|
||||||
},
|
},
|
||||||
|
@ -1842,6 +1842,43 @@ static const CSIDL_DATA CSIDL_Data[] =
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
INT SHGetSpecialFolderID(_In_ LPCWSTR pszName)
|
||||||
|
{
|
||||||
|
UINT csidl;
|
||||||
|
|
||||||
|
for (csidl = 0; csidl < _countof(CSIDL_Data); ++csidl)
|
||||||
|
{
|
||||||
|
const CSIDL_DATA *pData = &CSIDL_Data[csidl];
|
||||||
|
if (pData->szValueName && lstrcmpiW(pszName, pData->szValueName) == 0)
|
||||||
|
return csidl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
INT Shell_ParseSpecialFolder(_In_ LPCWSTR pszStart, _Out_ LPWSTR *ppch, _Out_ INT *pcch)
|
||||||
|
{
|
||||||
|
LPCWSTR pszPath, pchBackslash;
|
||||||
|
WCHAR szPath[MAX_PATH];
|
||||||
|
|
||||||
|
pchBackslash = StrChrW(pszStart, L'\\');
|
||||||
|
if (pchBackslash)
|
||||||
|
{
|
||||||
|
*ppch = (LPWSTR)(pchBackslash + 1);
|
||||||
|
*pcch = (pchBackslash - pszStart) + 1;
|
||||||
|
StrCpyNW(szPath, pszStart, max(*pcch, _countof(szPath)));
|
||||||
|
pszPath = szPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppch = NULL;
|
||||||
|
*pcch = lstrlenW(pszStart);
|
||||||
|
pszPath = pszStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SHGetSpecialFolderID(pszPath);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest);
|
static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -219,6 +219,12 @@ interface IShellFolder : IUnknown
|
||||||
cpp_quote("#define SFGAO_STORAGECAPMASK 0x70C50008L")
|
cpp_quote("#define SFGAO_STORAGECAPMASK 0x70C50008L")
|
||||||
cpp_quote("#define SFGAO_PKEYSFGAOMASK 0x81044000L")
|
cpp_quote("#define SFGAO_PKEYSFGAOMASK 0x81044000L")
|
||||||
|
|
||||||
|
cpp_quote("#define STR_PARSE_SHELL_PROTOCOL_TO_FILE_OBJECTS L\"Parse Shell Protocol To File Objects\"")
|
||||||
|
cpp_quote("#define STR_FILE_SYS_BIND_DATA L\"File System Bind Data\"")
|
||||||
|
cpp_quote("#define STR_PARSE_PREFER_FOLDER_BROWSING L\"Parse Prefer Folder Browsing\"")
|
||||||
|
cpp_quote("#define STR_PARSE_TRANSLATE_ALIASES L\"Parse Translate Aliases\"")
|
||||||
|
cpp_quote("#define STR_DONT_PARSE_RELATIVE L\"Don't Parse Relative\"")
|
||||||
|
|
||||||
typedef ULONG SFGAOF;
|
typedef ULONG SFGAOF;
|
||||||
|
|
||||||
HRESULT ParseDisplayName(
|
HRESULT ParseDisplayName(
|
||||||
|
|
|
@ -322,6 +322,8 @@ IContextMenu_Invoke(
|
||||||
_In_ LPCSTR lpVerb,
|
_In_ LPCSTR lpVerb,
|
||||||
_In_ UINT uFlags);
|
_In_ UINT uFlags);
|
||||||
|
|
||||||
|
DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif /* defined(__cplusplus) */
|
#endif /* defined(__cplusplus) */
|
||||||
|
|
Loading…
Reference in a new issue