[NTOBJSHEX]

Make nt object symlinks work more like shortcuts. Fixes the addressbar not quite knowing what to show when you click on a symlink.

svn path=/trunk/; revision=75177
This commit is contained in:
David Quintana 2017-06-23 23:23:17 +00:00
parent 1777a8d251
commit 1c5588d156
5 changed files with 97 additions and 85 deletions

View file

@ -187,11 +187,6 @@ public:
LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, first);
if (IsSymLink(info))
{
return RedirectToSymLink(info, first, rest, pbcReserved, (IShellFolder**)ppvOut);
}
CComPtr<IShellFolder> psfChild;
hr = InternalBindToObject(path, info, first, rest, fullPidl, pbcReserved, &psfChild);
@ -225,17 +220,15 @@ protected:
LPBC pbcReserved,
IShellFolder** ppsfChild) PURE;
public:
virtual HRESULT STDMETHODCALLTYPE RedirectToSymLink(
virtual HRESULT STDMETHODCALLTYPE ResolveSymLink(
const TItemId * info,
LPITEMIDLIST first,
LPCITEMIDLIST rest,
LPBC pbcReserved,
IShellFolder ** ppsfChild)
LPITEMIDLIST * fullPidl)
{
return E_NOTIMPL;
}
public:
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
@ -422,7 +415,40 @@ public:
HKEY keys[1];
LPITEMIDLIST parent = m_shellPidl;
CComPtr<IShellFolder> psfParent = this;
LPCITEMIDLIST child;
int nkeys = _countof(keys);
if (cidl == 1 && IsSymLink(apidl[0]))
{
const TItemId * info;
HRESULT hr = GetInfoFromPidl(apidl[0], &info);
if (FAILED(hr))
return hr;
LPITEMIDLIST target;
hr = ResolveSymLink(info, &target);
if (FAILED(hr))
return hr;
CComPtr<IShellFolder> psfTarget;
hr = ::SHBindToParent(target, IID_PPV_ARG(IShellFolder, &psfTarget), &child);
if (FAILED(hr))
{
ILFree(target);
return hr;
}
parent = ILClone(target);
ILRemoveLastID(parent);
psfParent = psfTarget;
apidl = &child;
}
if (cidl == 1 && IsFolder(apidl[0]))
{
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
@ -434,7 +460,7 @@ public:
nkeys = 0;
}
HRESULT hr = CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, DefCtxMenuCallback, nkeys, keys, &pcm);
HRESULT hr = CDefFolderMenu_Create2(parent, hwndOwner, cidl, apidl, psfParent, DefCtxMenuCallback, nkeys, keys, &pcm);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
@ -635,10 +661,30 @@ protected:
const TItemId * entry,
PULONG inMask) PURE;
virtual BOOL STDMETHODCALLTYPE IsFolder(LPCITEMIDLIST pcidl) PURE;
virtual BOOL STDMETHODCALLTYPE IsFolder(LPCITEMIDLIST pcidl)
{
const TItemId * info;
HRESULT hr = GetInfoFromPidl(pcidl, &info);
if (FAILED(hr))
return hr;
return IsFolder(info);
}
virtual BOOL STDMETHODCALLTYPE IsFolder(const TItemId * info) PURE;
virtual BOOL STDMETHODCALLTYPE IsSymLink(LPCITEMIDLIST pcidl)
{
const TItemId * info;
HRESULT hr = GetInfoFromPidl(pcidl, &info);
if (FAILED(hr))
return hr;
return IsSymLink(info);
}
virtual BOOL STDMETHODCALLTYPE IsSymLink(const TItemId * info)
{
return FALSE;

View file

@ -125,72 +125,56 @@ BOOL STDMETHODCALLTYPE CNtObjectFolder::IsSymLink(const NtPidlEntry * info)
return info->objectType == SYMBOLICLINK_OBJECT;
}
HRESULT STDMETHODCALLTYPE CNtObjectFolder::RedirectToSymLink(
HRESULT STDMETHODCALLTYPE CNtObjectFolder::ResolveSymLink(
const NtPidlEntry * info,
LPITEMIDLIST first,
LPCITEMIDLIST rest,
LPBC pbcReserved,
IShellFolder ** ppsfChild)
LPITEMIDLIST * fullPidl)
{
HRESULT hr;
WCHAR wbLink[MAX_PATH] = { 0 };
UNICODE_STRING link;
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
hr = GetNTObjectSymbolicLinkTarget(m_NtPath, info->entryName, &link);
*fullPidl = NULL;
HRESULT hr = GetNTObjectSymbolicLinkTarget(m_NtPath, info->entryName, &link);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
WCHAR path[MAX_PATH];
if (link.Length > 0)
if (link.Length == 0)
return E_UNEXPECTED;
if (link.Buffer[1] == L':' && isalphaW(link.Buffer[0]))
{
if (link.Buffer[1] == L':' && isalphaW(link.Buffer[0]))
{
StringCbCopyNW(path, _countof(path), link.Buffer, link.Length);
CComPtr<IShellFolder> psfDesktop;
hr = SHGetDesktopFolder(&psfDesktop);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, &first, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = psfDesktop->BindToObject(rest, pbcReserved, IID_PPV_ARG(IShellFolder, ppsfChild));
if (FAILED(hr))
return hr;
return S_FALSE;;
}
StringCbCopyW(path, _countof(path), L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
PathAppend(path, link.Buffer);
StringCbCopyNW(path, _countof(path), link.Buffer, link.Length);
CComPtr<IShellFolder> psfDesktop;
hr = SHGetDesktopFolder(&psfDesktop);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
LPITEMIDLIST pidl;
hr = psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, &pidl, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComPtr<IShellFolder> psfChild;
hr = psfDesktop->BindToObject(pidl, pbcReserved, IID_PPV_ARG(IShellFolder, ppsfChild));
ILFree(pidl);
if (FAILED(hr))
return hr;
return S_FALSE;;
return psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, fullPidl, NULL);
}
return E_UNEXPECTED;
StringCbCopyW(path, _countof(path), L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
PathAppend(path, link.Buffer);
CComPtr<IShellFolder> psfDesktop;
hr = SHGetDesktopFolder(&psfDesktop);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
LPITEMIDLIST pidl;
hr = psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, &pidl, NULL);
if (FAILED(hr))
return hr;
*fullPidl = pidl;
DumpIdList(pidl);
return S_OK;
}
HRESULT STDMETHODCALLTYPE CNtObjectFolder::InternalBindToObject(
@ -487,15 +471,6 @@ ULONG CNtObjectFolder::ConvertAttributes(const NtPidlEntry * entry, PULONG inMas
return flags & mask;
}
BOOL CNtObjectFolder::IsFolder(LPCITEMIDLIST pcidl)
{
NtPidlEntry * info = (NtPidlEntry*) &(pcidl->mkid);
if ((info->cb < sizeof(NtPidlEntry)) || (info->magic != NT_OBJECT_PIDL_MAGIC))
return FALSE;
return IsFolder(info);
}
BOOL CNtObjectFolder::IsFolder(const NtPidlEntry * info)
{
return (info->objectType == DIRECTORY_OBJECT) ||

View file

@ -63,6 +63,7 @@ public:
SHCONTF grfFlags,
IEnumIDList **ppenumIDList);
protected:
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
PWSTR path,
const NtPidlEntry * info,
@ -71,13 +72,12 @@ public:
LPITEMIDLIST fullPidl,
LPBC pbcReserved,
IShellFolder** ppsfChild);
virtual HRESULT STDMETHODCALLTYPE RedirectToSymLink(
const NtPidlEntry * info,
LPITEMIDLIST first,
LPCITEMIDLIST rest,
LPBC pbcReserved,
IShellFolder ** ppsfChild);
virtual HRESULT STDMETHODCALLTYPE ResolveSymLink(
const NtPidlEntry * info,
LPITEMIDLIST * fullPidl);
public:
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
UINT iColumn,
SHCOLSTATEF *pcsFlags);
@ -105,7 +105,6 @@ public:
protected:
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const NtPidlEntry * first, const NtPidlEntry * second);
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(const NtPidlEntry * entry, PULONG inMask);
virtual BOOL STDMETHODCALLTYPE IsFolder(LPCITEMIDLIST pcidl);
virtual BOOL STDMETHODCALLTYPE IsFolder(const NtPidlEntry * info);
virtual BOOL STDMETHODCALLTYPE IsSymLink(const NtPidlEntry * info);

View file

@ -419,15 +419,6 @@ ULONG CRegistryFolder::ConvertAttributes(const RegPidlEntry * entry, PULONG inMa
return flags & mask;
}
BOOL CRegistryFolder::IsFolder(LPCITEMIDLIST pcidl)
{
RegPidlEntry * entry = (RegPidlEntry*) &(pcidl->mkid);
if ((entry->cb < sizeof(RegPidlEntry)) || (entry->magic != REGISTRY_PIDL_MAGIC))
return FALSE;
return IsFolder(entry);
}
BOOL CRegistryFolder::IsFolder(const RegPidlEntry * info)
{
return (info->entryType == REG_ENTRY_KEY) ||(info->entryType == REG_ENTRY_ROOT);

View file

@ -63,6 +63,7 @@ public:
SHCONTF grfFlags,
IEnumIDList **ppenumIDList);
protected:
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
PWSTR path,
const RegPidlEntry * info,
@ -72,6 +73,7 @@ public:
LPBC pbcReserved,
IShellFolder** ppsfChild);
public:
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
UINT iColumn,
SHCOLSTATEF *pcsFlags);
@ -99,7 +101,6 @@ public:
protected:
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const RegPidlEntry * first, const RegPidlEntry * second);
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(const RegPidlEntry * entry, PULONG inMask);
virtual BOOL STDMETHODCALLTYPE IsFolder(LPCITEMIDLIST pcidl);
virtual BOOL STDMETHODCALLTYPE IsFolder(const RegPidlEntry * info);
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const RegPidlEntry ** pentry);