diff --git a/reactos/dll/shellext/ntobjshex/foldercommon.h b/reactos/dll/shellext/ntobjshex/foldercommon.h index f6ffc2c5887..247dd4e3030 100644 --- a/reactos/dll/shellext/ntobjshex/foldercommon.h +++ b/reactos/dll/shellext/ntobjshex/foldercommon.h @@ -187,11 +187,6 @@ public: LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, first); - if (IsSymLink(info)) - { - return RedirectToSymLink(info, first, rest, pbcReserved, (IShellFolder**)ppvOut); - } - CComPtr 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 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 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; diff --git a/reactos/dll/shellext/ntobjshex/ntobjfolder.cpp b/reactos/dll/shellext/ntobjshex/ntobjfolder.cpp index fdc2183001f..725ed78c6d3 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjfolder.cpp +++ b/reactos/dll/shellext/ntobjshex/ntobjfolder.cpp @@ -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 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 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 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 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) || diff --git a/reactos/dll/shellext/ntobjshex/ntobjfolder.h b/reactos/dll/shellext/ntobjshex/ntobjfolder.h index 2bee6afaf7e..5be5e64d650 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjfolder.h +++ b/reactos/dll/shellext/ntobjshex/ntobjfolder.h @@ -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); diff --git a/reactos/dll/shellext/ntobjshex/regfolder.cpp b/reactos/dll/shellext/ntobjshex/regfolder.cpp index fdbe93eb880..6ac41d4ad58 100644 --- a/reactos/dll/shellext/ntobjshex/regfolder.cpp +++ b/reactos/dll/shellext/ntobjshex/regfolder.cpp @@ -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); diff --git a/reactos/dll/shellext/ntobjshex/regfolder.h b/reactos/dll/shellext/ntobjshex/regfolder.h index 6d251636633..3d1fe654098 100644 --- a/reactos/dll/shellext/ntobjshex/regfolder.h +++ b/reactos/dll/shellext/ntobjshex/regfolder.h @@ -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);