mirror of
https://github.com/reactos/reactos.git
synced 2025-01-05 22:12:46 +00:00
[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:
parent
1777a8d251
commit
1c5588d156
5 changed files with 97 additions and 85 deletions
|
@ -187,11 +187,6 @@ public:
|
||||||
|
|
||||||
LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, first);
|
LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, first);
|
||||||
|
|
||||||
if (IsSymLink(info))
|
|
||||||
{
|
|
||||||
return RedirectToSymLink(info, first, rest, pbcReserved, (IShellFolder**)ppvOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
CComPtr<IShellFolder> psfChild;
|
CComPtr<IShellFolder> psfChild;
|
||||||
hr = InternalBindToObject(path, info, first, rest, fullPidl, pbcReserved, &psfChild);
|
hr = InternalBindToObject(path, info, first, rest, fullPidl, pbcReserved, &psfChild);
|
||||||
|
|
||||||
|
@ -225,17 +220,15 @@ protected:
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
IShellFolder** ppsfChild) PURE;
|
IShellFolder** ppsfChild) PURE;
|
||||||
|
|
||||||
public:
|
virtual HRESULT STDMETHODCALLTYPE ResolveSymLink(
|
||||||
virtual HRESULT STDMETHODCALLTYPE RedirectToSymLink(
|
|
||||||
const TItemId * info,
|
const TItemId * info,
|
||||||
LPITEMIDLIST first,
|
LPITEMIDLIST * fullPidl)
|
||||||
LPCITEMIDLIST rest,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
IShellFolder ** ppsfChild)
|
|
||||||
{
|
{
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
|
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
|
||||||
LPCITEMIDLIST pidl,
|
LPCITEMIDLIST pidl,
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
|
@ -422,7 +415,40 @@ public:
|
||||||
|
|
||||||
HKEY keys[1];
|
HKEY keys[1];
|
||||||
|
|
||||||
|
LPITEMIDLIST parent = m_shellPidl;
|
||||||
|
|
||||||
|
CComPtr<IShellFolder> psfParent = this;
|
||||||
|
|
||||||
|
LPCITEMIDLIST child;
|
||||||
|
|
||||||
int nkeys = _countof(keys);
|
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]))
|
if (cidl == 1 && IsFolder(apidl[0]))
|
||||||
{
|
{
|
||||||
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
||||||
|
@ -434,7 +460,7 @@ public:
|
||||||
nkeys = 0;
|
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))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
@ -635,10 +661,30 @@ protected:
|
||||||
const TItemId * entry,
|
const TItemId * entry,
|
||||||
PULONG inMask) PURE;
|
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 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)
|
virtual BOOL STDMETHODCALLTYPE IsSymLink(const TItemId * info)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -125,72 +125,56 @@ BOOL STDMETHODCALLTYPE CNtObjectFolder::IsSymLink(const NtPidlEntry * info)
|
||||||
return info->objectType == SYMBOLICLINK_OBJECT;
|
return info->objectType == SYMBOLICLINK_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::RedirectToSymLink(
|
HRESULT STDMETHODCALLTYPE CNtObjectFolder::ResolveSymLink(
|
||||||
const NtPidlEntry * info,
|
const NtPidlEntry * info,
|
||||||
LPITEMIDLIST first,
|
LPITEMIDLIST * fullPidl)
|
||||||
LPCITEMIDLIST rest,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
IShellFolder ** ppsfChild)
|
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
WCHAR wbLink[MAX_PATH] = { 0 };
|
WCHAR wbLink[MAX_PATH] = { 0 };
|
||||||
UNICODE_STRING link;
|
UNICODE_STRING link;
|
||||||
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
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))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
WCHAR path[MAX_PATH];
|
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);
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
CComPtr<IShellFolder> psfDesktop;
|
CComPtr<IShellFolder> psfDesktop;
|
||||||
hr = SHGetDesktopFolder(&psfDesktop);
|
hr = SHGetDesktopFolder(&psfDesktop);
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
LPITEMIDLIST pidl;
|
return psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, fullPidl, NULL);
|
||||||
|
|
||||||
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 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(
|
HRESULT STDMETHODCALLTYPE CNtObjectFolder::InternalBindToObject(
|
||||||
|
@ -487,15 +471,6 @@ ULONG CNtObjectFolder::ConvertAttributes(const NtPidlEntry * entry, PULONG inMas
|
||||||
return flags & mask;
|
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)
|
BOOL CNtObjectFolder::IsFolder(const NtPidlEntry * info)
|
||||||
{
|
{
|
||||||
return (info->objectType == DIRECTORY_OBJECT) ||
|
return (info->objectType == DIRECTORY_OBJECT) ||
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
SHCONTF grfFlags,
|
SHCONTF grfFlags,
|
||||||
IEnumIDList **ppenumIDList);
|
IEnumIDList **ppenumIDList);
|
||||||
|
|
||||||
|
protected:
|
||||||
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
||||||
PWSTR path,
|
PWSTR path,
|
||||||
const NtPidlEntry * info,
|
const NtPidlEntry * info,
|
||||||
|
@ -71,13 +72,12 @@ public:
|
||||||
LPITEMIDLIST fullPidl,
|
LPITEMIDLIST fullPidl,
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
IShellFolder** ppsfChild);
|
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(
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
SHCOLSTATEF *pcsFlags);
|
SHCOLSTATEF *pcsFlags);
|
||||||
|
@ -105,7 +105,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const NtPidlEntry * first, const NtPidlEntry * second);
|
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const NtPidlEntry * first, const NtPidlEntry * second);
|
||||||
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(const NtPidlEntry * entry, PULONG inMask);
|
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 IsFolder(const NtPidlEntry * info);
|
||||||
virtual BOOL STDMETHODCALLTYPE IsSymLink(const NtPidlEntry * info);
|
virtual BOOL STDMETHODCALLTYPE IsSymLink(const NtPidlEntry * info);
|
||||||
|
|
||||||
|
|
|
@ -419,15 +419,6 @@ ULONG CRegistryFolder::ConvertAttributes(const RegPidlEntry * entry, PULONG inMa
|
||||||
return flags & mask;
|
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)
|
BOOL CRegistryFolder::IsFolder(const RegPidlEntry * info)
|
||||||
{
|
{
|
||||||
return (info->entryType == REG_ENTRY_KEY) ||(info->entryType == REG_ENTRY_ROOT);
|
return (info->entryType == REG_ENTRY_KEY) ||(info->entryType == REG_ENTRY_ROOT);
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
SHCONTF grfFlags,
|
SHCONTF grfFlags,
|
||||||
IEnumIDList **ppenumIDList);
|
IEnumIDList **ppenumIDList);
|
||||||
|
|
||||||
|
protected:
|
||||||
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
||||||
PWSTR path,
|
PWSTR path,
|
||||||
const RegPidlEntry * info,
|
const RegPidlEntry * info,
|
||||||
|
@ -72,6 +73,7 @@ public:
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
IShellFolder** ppsfChild);
|
IShellFolder** ppsfChild);
|
||||||
|
|
||||||
|
public:
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
SHCOLSTATEF *pcsFlags);
|
SHCOLSTATEF *pcsFlags);
|
||||||
|
@ -99,7 +101,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const RegPidlEntry * first, const RegPidlEntry * second);
|
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const RegPidlEntry * first, const RegPidlEntry * second);
|
||||||
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(const RegPidlEntry * entry, PULONG inMask);
|
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(const RegPidlEntry * entry, PULONG inMask);
|
||||||
virtual BOOL STDMETHODCALLTYPE IsFolder(LPCITEMIDLIST pcidl);
|
|
||||||
virtual BOOL STDMETHODCALLTYPE IsFolder(const RegPidlEntry * info);
|
virtual BOOL STDMETHODCALLTYPE IsFolder(const RegPidlEntry * info);
|
||||||
|
|
||||||
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const RegPidlEntry ** pentry);
|
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const RegPidlEntry ** pentry);
|
||||||
|
|
Loading…
Reference in a new issue