mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +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);
|
||||
|
||||
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;
|
||||
|
|
|
@ -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) ||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue