From 6928fadeff5669c9043867711e7dd997d02ee4d6 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Sat, 14 Mar 2015 03:15:36 +0000 Subject: [PATCH] [NTOBJSHEX] * Replace the custom context menu classes with the default implementation from shell32. As a side-effect, navigation now works in ReactOS. * Make use of the default implementations of IDataObject and IQueryAssociations from shell32 (required by the IContextMenu implementation of Win2003). * Fix initialization of the NT Object Folder's pidl. * Make CompareIDs recursive. * Fix the recursivity in GetDisplayNameOf, when called with FORPARSING. NOTE: There is still some issue with GetDisplayNameOf, where the address shown in the addressbar seems to skip path components. svn path=/trunk/; revision=66674 --- reactos/dll/shellext/ntobjshex/ntobjns.cpp | 269 +++++++---------- reactos/dll/shellext/ntobjshex/ntobjns.h | 2 + reactos/dll/shellext/ntobjshex/ntobjutil.h | 2 +- reactos/dll/shellext/ntobjshex/regfolder.cpp | 275 +++++++----------- reactos/dll/shellext/ntobjshex/regfolder.h | 2 + .../resources/rgs/ntobjectfolder.rgs | 45 +-- 6 files changed, 257 insertions(+), 338 deletions(-) diff --git a/reactos/dll/shellext/ntobjshex/ntobjns.cpp b/reactos/dll/shellext/ntobjshex/ntobjns.cpp index cf803554b38..584f658fb46 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjns.cpp +++ b/reactos/dll/shellext/ntobjshex/ntobjns.cpp @@ -11,6 +11,11 @@ #include #include "util.h" +#define DFM_MERGECONTEXTMENU 1 // uFlags LPQCMINFO +#define DFM_INVOKECOMMAND 2 // idCmd pszArgs +#define DFM_INVOKECOMMANDEX 12 // idCmd PDFMICS +#define DFM_GETDEFSTATICID 14 // idCmd * 0 + #define SHCIDS_ALLFIELDS 0x80000000L #define SHCIDS_CANONICALONLY 0x10000000L @@ -33,158 +38,6 @@ enum NtObjectColumns NTOBJECT_COLUMN_LINKTARGET = 3, }; -class CNtObjectFolderContextMenu : - public CComObjectRootEx, - public IContextMenu -{ - PCIDLIST_ABSOLUTE m_pcidlFolder; - PCITEMID_CHILD m_pcidlChild; - UINT m_idFirst; - - enum ItemOffsets - { - ITEM_Open = 0, - ITEM_OpenNewWindow - }; - -public: - CNtObjectFolderContextMenu() : - m_pcidlFolder(NULL), - m_pcidlChild(NULL), - m_idFirst(0) - { - - } - - virtual ~CNtObjectFolderContextMenu() - { - if (m_pcidlFolder) - ILFree((LPITEMIDLIST) m_pcidlFolder); - if (m_pcidlChild) - ILFree((LPITEMIDLIST) m_pcidlChild); - } - - HRESULT Initialize(PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl) - { - m_pcidlFolder = ILClone(parent); - if (cidl != 1) - return E_INVALIDARG; - m_pcidlChild = ILClone(apidl[0]); - return S_OK; - } - - // IContextMenu - virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) - { - MENUITEMINFOW mii; - - m_idFirst = idCmdFirst; - - const NtPidlEntry * entry = (NtPidlEntry *) m_pcidlChild; - - static WCHAR open [] = L"Open"; - static WCHAR opennewwindow [] = L"Open in new window"; - - if ((entry->objectType == DIRECTORY_OBJECT) || - (entry->objectType == SYMBOLICLINK_OBJECT) || - (entry->objectType == KEY_OBJECT)) - { - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = (idCmdFirst = m_idFirst + ITEM_Open); - mii.dwTypeData = open; - mii.cch = _countof(open); - mii.fState = MFS_ENABLED | MFS_DEFAULT; - mii.hSubMenu = NULL; - InsertMenuItemW(hmenu, idCmdFirst, TRUE, &mii); - - if (!(uFlags & CMF_DEFAULTONLY) && idCmdFirst <= idCmdLast) - { - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = (idCmdFirst = m_idFirst + ITEM_OpenNewWindow); - mii.dwTypeData = opennewwindow; - mii.cch = _countof(opennewwindow); - mii.fState = MFS_ENABLED; - mii.hSubMenu = NULL; - InsertMenuItemW(hmenu, idCmdFirst, FALSE, &mii); - } - } - - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst - m_idFirst); - } - - virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici) - { - LPITEMIDLIST fullPidl = ILCombine(m_pcidlFolder, m_pcidlChild); - - if (LOWORD(lpici->lpVerb) == (m_idFirst + ITEM_Open) || !lpici->lpVerb) - { - SHELLEXECUTEINFO sei = { 0 }; - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME; - sei.lpIDList = fullPidl; - sei.lpClass = L"folder"; - sei.hwnd = lpici->hwnd; - sei.nShow = lpici->nShow; - sei.lpVerb = L"open"; - BOOL bRes = ::ShellExecuteEx(&sei); - - ILFree(fullPidl); - - return bRes ? S_OK : HRESULT_FROM_WIN32(GetLastError()); - } - else if (LOWORD(lpici->lpVerb) == (m_idFirst + ITEM_OpenNewWindow)) - { - SHELLEXECUTEINFO sei = { 0 }; - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME; - sei.lpIDList = fullPidl; - sei.lpClass = L"folder"; - sei.hwnd = lpici->hwnd; - sei.nShow = lpici->nShow; - sei.lpVerb = L"opennewwindow"; - BOOL bRes = ::ShellExecuteEx(&sei); - - ILFree(fullPidl); - - return bRes ? S_OK : HRESULT_FROM_WIN32(GetLastError()); - } - return E_NOTIMPL; - } - - virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax) - { - if (idCmd == m_idFirst) - { - if (uType == GCS_VERBW) - { - return StringCchCopyW((LPWSTR) pszName, cchMax, L"open"); - } - } - else if (idCmd == (m_idFirst + 1)) - { - if (uType == GCS_VERBW) - { - return StringCchCopyW((LPWSTR) pszName, cchMax, L"opennewwindow"); - } - } - return E_NOTIMPL; - } - - DECLARE_NOT_AGGREGATABLE(CNtObjectFolderContextMenu) - DECLARE_PROTECT_FINAL_CONSTRUCT() - - BEGIN_COM_MAP(CNtObjectFolderContextMenu) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) - END_COM_MAP() - -}; - class CNtObjectFolderExtractIcon : public CComObjectRootEx, public IExtractIconW @@ -517,6 +370,17 @@ public: return flags & mask; } + BOOL IsFolder(LPCITEMIDLIST pcidl) + { + NtPidlEntry * entry; + HRESULT hr = FindPidlInList(pcidl, &entry); + if (FAILED_UNEXPECTEDLY(hr)) + return FALSE; + + return (entry->objectType == DIRECTORY_OBJECT) || + (entry->objectType == SYMBOLICLINK_OBJECT) || + (entry->objectType == KEY_OBJECT); + } }; class CNtObjectFolderEnum : @@ -716,7 +580,9 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject( return E_ACCESSDENIED; WCHAR path[MAX_PATH]; + StringCbCopyW(path, _countof(path), m_NtPath); + PathAppendW(path, info->entryName); LPITEMIDLIST first = ILCloneFirst(pidl); @@ -795,7 +661,36 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::CompareIDs( LPCITEMIDLIST pidl2) { TRACE("CompareIDs\n"); - return m_PidlManager->CompareIDs(lParam, pidl1, pidl2); + + HRESULT hr = m_PidlManager->CompareIDs(lParam, pidl1, pidl2); + if (hr != S_OK) + return hr; + + LPCITEMIDLIST rest1 = ILGetNext(pidl1); + LPCITEMIDLIST rest2 = ILGetNext(pidl2); + + bool hasNext1 = (rest1->mkid.cb > 0); + bool hasNext2 = (rest2->mkid.cb > 0); + + if (hasNext1 || hasNext2) + { + if (hasNext1 && !hasNext2) + return MAKE_HRESULT(0, 0, (USHORT) -1); + + if (hasNext2 && !hasNext1) + return MAKE_HRESULT(0, 0, (USHORT) 1); + + LPCITEMIDLIST first1 = ILCloneFirst(pidl1); + + CComPtr psfNext; + hr = BindToObject(first1, NULL, IID_PPV_ARG(IShellFolder, &psfNext)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return psfNext->CompareIDs(lParam, rest1, rest2); + } + + return S_OK; } HRESULT STDMETHODCALLTYPE CNtObjectFolder::CreateViewObject( @@ -856,10 +751,29 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetUIObjectOf( { TRACE("GetUIObjectOf\n"); - if (IsEqualIID(riid, IID_IContextMenu)) + if (IsEqualIID(riid, IID_IContextMenu) || + IsEqualIID(riid, IID_IContextMenu2) || + IsEqualIID(riid, IID_IContextMenu3)) { - return ShellObjectCreatorInit(m_shellPidl, cidl, apidl, riid, ppvOut); - //return CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, ContextMenuCallback, 0, NULL, (IContextMenu**) ppvOut); + CComPtr pcm; + + HKEY keys [1]; + + int nkeys = _countof(keys); + if (cidl == 1 && m_PidlManager->IsFolder(apidl[0])) + { + RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0); + } + else + { + nkeys = 0; + } + + HRESULT hr = CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, DefCtxMenuCallback, nkeys, keys, &pcm); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return pcm->QueryInterface(riid, ppvOut); } if (IsEqualIID(riid, IID_IExtractIconW)) @@ -867,6 +781,28 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetUIObjectOf( return ShellObjectCreatorInit(m_shellPidl, cidl, apidl, riid, ppvOut); } + if (IsEqualIID(riid, IID_IDataObject)) + { + return CIDLData_CreateFromIDArray(m_shellPidl, cidl, apidl, (IDataObject**)ppvOut); + } + + if (IsEqualIID(riid, IID_IQueryAssociations)) + { + if (cidl == 1 && m_PidlManager->IsFolder(apidl[0])) + { + CComPtr pqa; + HRESULT hr = AssocCreate(CLSID_QueryAssociations, IID_PPV_ARG(IQueryAssociations, &pqa)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = pqa->Init(ASSOCF_INIT_DEFAULTTOFOLDER, L"NTObjShEx.NTDirectory", NULL, hwndOwner); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return pqa->QueryInterface(riid, ppvOut); + } + } + return E_NOTIMPL; } @@ -899,12 +835,13 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDisplayNameOf( if (FAILED_UNEXPECTEDLY(hr)) return hr; + LPCITEMIDLIST pidlFirst = ILCloneFirst(pidl); LPCITEMIDLIST pidlNext = ILGetNext(pidl); if (pidlNext && pidlNext->mkid.cb > 0) { CComPtr psfChild; - hr = BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); + hr = BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -921,6 +858,8 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDisplayNameOf( PathAppendW(path, temp); } + + ILFree((LPITEMIDLIST)pidlFirst); } else { @@ -971,7 +910,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::Initialize(LPCITEMIDLIST pidl) // Internal HRESULT STDMETHODCALLTYPE CNtObjectFolder::Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath) { - TRACE("INITIALIZE %p CNtObjectFolder with ntPath %S\n", this, ntPath); + m_shellPidl = ILClone(pidl); if (!m_PidlManager) m_PidlManager = new CNtObjectPidlManager(); @@ -1273,3 +1212,17 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::MessageSFVCB(UINT uMsg, WPARAM wParam } return E_NOTIMPL; } + +HRESULT CNtObjectFolder::DefCtxMenuCallback(IShellFolder * /*psf*/, HWND /*hwnd*/, IDataObject * /*pdtobj*/, UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/) +{ + switch (uMsg) + { + case DFM_MERGECONTEXTMENU: + return S_OK; + case DFM_INVOKECOMMAND: + case DFM_INVOKECOMMANDEX: + case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default + return S_FALSE; + } + return E_NOTIMPL; +} diff --git a/reactos/dll/shellext/ntobjshex/ntobjns.h b/reactos/dll/shellext/ntobjshex/ntobjns.h index a42dee2021e..efb9519b75b 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjns.h +++ b/reactos/dll/shellext/ntobjshex/ntobjns.h @@ -137,6 +137,8 @@ public: // Internal HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath); + static HRESULT CALLBACK DefCtxMenuCallback(IShellFolder *, HWND, IDataObject *, UINT, WPARAM, LPARAM); + DECLARE_REGISTRY_RESOURCEID(IDR_NTOBJECTFOLDER) DECLARE_NOT_AGGREGATABLE(CNtObjectFolder) DECLARE_PROTECT_FINAL_CONSTRUCT() diff --git a/reactos/dll/shellext/ntobjshex/ntobjutil.h b/reactos/dll/shellext/ntobjshex/ntobjutil.h index 6e40951953e..66f4dd25678 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjutil.h +++ b/reactos/dll/shellext/ntobjshex/ntobjutil.h @@ -93,7 +93,7 @@ struct RegPidlEntry DWORD contentType; USHORT contentsLength; - WCHAR entryName[0]; + WCHAR entryName[ANYSIZE_ARRAY]; }; diff --git a/reactos/dll/shellext/ntobjshex/regfolder.cpp b/reactos/dll/shellext/ntobjshex/regfolder.cpp index a27083acedb..298b6b41188 100644 --- a/reactos/dll/shellext/ntobjshex/regfolder.cpp +++ b/reactos/dll/shellext/ntobjshex/regfolder.cpp @@ -1,16 +1,21 @@ /* -* PROJECT: ReactOS shell extensions -* LICENSE: GPL - See COPYING in the top level directory -* FILE: dll\shellext\ntobjshex\ntobjns.cpp -* PURPOSE: NT Object Namespace shell extension -* PROGRAMMERS: David Quintana -*/ + * PROJECT: ReactOS shell extensions + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll\shellext\ntobjshex\ntobjns.cpp + * PURPOSE: NT Object Namespace shell extension + * PROGRAMMERS: David Quintana + */ #include "precomp.h" #include "ntobjutil.h" #include #include "util.h" +#define DFM_MERGECONTEXTMENU 1 // uFlags LPQCMINFO +#define DFM_INVOKECOMMAND 2 // idCmd pszArgs +#define DFM_INVOKECOMMANDEX 12 // idCmd PDFMICS +#define DFM_GETDEFSTATICID 14 // idCmd * 0 + #define SHCIDS_ALLFIELDS 0x80000000L #define SHCIDS_CANONICALONLY 0x10000000L @@ -32,156 +37,6 @@ enum RegistryColumns REGISTRY_COLUMN_VALUE = 2, }; -class CRegistryFolderContextMenu : - public CComObjectRootEx, - public IContextMenu -{ - PCIDLIST_ABSOLUTE m_pcidlFolder; - PCITEMID_CHILD m_pcidlChild; - UINT m_idFirst; - - enum ItemOffsets - { - ITEM_Open = 0, - ITEM_OpenNewWindow - }; - -public: - CRegistryFolderContextMenu() : - m_pcidlFolder(NULL), - m_pcidlChild(NULL), - m_idFirst(0) - { - - } - - virtual ~CRegistryFolderContextMenu() - { - if (m_pcidlFolder) - ILFree((LPITEMIDLIST) m_pcidlFolder); - if (m_pcidlChild) - ILFree((LPITEMIDLIST) m_pcidlChild); - } - - HRESULT Initialize(PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl) - { - m_pcidlFolder = ILClone(parent); - if (cidl != 1) - return E_INVALIDARG; - m_pcidlChild = ILClone(apidl[0]); - return S_OK; - } - - // IContextMenu - virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) - { - MENUITEMINFOW mii; - - m_idFirst = idCmdFirst; - - const RegPidlEntry * entry = (RegPidlEntry *) m_pcidlChild; - - static WCHAR open [] = L"Open"; - static WCHAR opennewwindow [] = L"Open in new window"; - - if (entry->entryType == REG_ENTRY_KEY) - { - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = (idCmdFirst = m_idFirst + ITEM_Open); - mii.dwTypeData = open; - mii.cch = _countof(open); - mii.fState = MFS_ENABLED | MFS_DEFAULT; - mii.hSubMenu = NULL; - InsertMenuItemW(hmenu, idCmdFirst, TRUE, &mii); - - if (!(uFlags & CMF_DEFAULTONLY) && idCmdFirst <= idCmdLast) - { - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = (idCmdFirst = m_idFirst + ITEM_OpenNewWindow); - mii.dwTypeData = opennewwindow; - mii.cch = _countof(opennewwindow); - mii.fState = MFS_ENABLED; - mii.hSubMenu = NULL; - InsertMenuItemW(hmenu, idCmdFirst, FALSE, &mii); - } - } - - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst - m_idFirst); - } - - virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici) - { - LPITEMIDLIST fullPidl = ILCombine(m_pcidlFolder, m_pcidlChild); - - if (LOWORD(lpici->lpVerb) == (m_idFirst + ITEM_Open) || !lpici->lpVerb) - { - SHELLEXECUTEINFO sei = { 0 }; - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME; - sei.lpIDList = fullPidl; - sei.lpClass = L"folder"; - sei.hwnd = lpici->hwnd; - sei.nShow = lpici->nShow; - sei.lpVerb = L"open"; - BOOL bRes = ::ShellExecuteEx(&sei); - - ILFree(fullPidl); - - return bRes ? S_OK : HRESULT_FROM_WIN32(GetLastError()); - } - else if (LOWORD(lpici->lpVerb) == (m_idFirst + ITEM_OpenNewWindow)) - { - SHELLEXECUTEINFO sei = { 0 }; - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME; - sei.lpIDList = fullPidl; - sei.lpClass = L"folder"; - sei.hwnd = lpici->hwnd; - sei.nShow = lpici->nShow; - sei.lpVerb = L"opennewwindow"; - BOOL bRes = ::ShellExecuteEx(&sei); - - ILFree(fullPidl); - - return bRes ? S_OK : HRESULT_FROM_WIN32(GetLastError()); - } - return E_NOTIMPL; - } - - virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax) - { - if (idCmd == m_idFirst) - { - if (uType == GCS_VERBW) - { - return StringCchCopyW((LPWSTR) pszName, cchMax, L"open"); - } - } - else if (idCmd == (m_idFirst + 1)) - { - if (uType == GCS_VERBW) - { - return StringCchCopyW((LPWSTR) pszName, cchMax, L"opennewwindow"); - } - } - return E_NOTIMPL; - } - - DECLARE_NOT_AGGREGATABLE(CRegistryFolderContextMenu) - DECLARE_PROTECT_FINAL_CONSTRUCT() - - BEGIN_COM_MAP(CRegistryFolderContextMenu) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) - END_COM_MAP() - -}; - class CRegistryFolderExtractIcon : public CComObjectRootEx, public IExtractIconW @@ -497,6 +352,16 @@ public: return flags & mask; } + BOOL IsFolder(LPCITEMIDLIST pcidl) + { + RegPidlEntry * entry; + HRESULT hr = FindPidlInList(pcidl, &entry); + if (FAILED_UNEXPECTEDLY(hr)) + return FALSE; + + return (entry->entryType == REG_ENTRY_KEY); + } + HRESULT FormatContentsForDisplay(RegPidlEntry * info, PCWSTR * strContents) { PVOID td = (((PBYTE) info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR)); @@ -565,7 +430,6 @@ public: } } - }; class CRegistryFolderEnum : @@ -803,7 +667,36 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::CompareIDs( LPCITEMIDLIST pidl2) { TRACE("CompareIDs\n"); - return m_PidlManager->CompareIDs(lParam, pidl1, pidl2); + + HRESULT hr = m_PidlManager->CompareIDs(lParam, pidl1, pidl2); + if (hr != S_OK) + return hr; + + LPCITEMIDLIST rest1 = ILGetNext(pidl1); + LPCITEMIDLIST rest2 = ILGetNext(pidl2); + + bool hasNext1 = (rest1->mkid.cb > 0); + bool hasNext2 = (rest2->mkid.cb > 0); + + if (hasNext1 || hasNext2) + { + if (hasNext1 && !hasNext2) + return MAKE_HRESULT(0, 0, (USHORT) -1); + + if (hasNext2 && !hasNext1) + return MAKE_HRESULT(0, 0, (USHORT) 1); + + LPCITEMIDLIST first1 = ILCloneFirst(pidl1); + + CComPtr psfNext; + hr = BindToObject(first1, NULL, IID_PPV_ARG(IShellFolder, &psfNext)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return psfNext->CompareIDs(lParam, rest1, rest2); + } + + return S_OK; } HRESULT STDMETHODCALLTYPE CRegistryFolder::CreateViewObject( @@ -864,10 +757,29 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetUIObjectOf( { TRACE("GetUIObjectOf\n"); - if (IsEqualIID(riid, IID_IContextMenu)) + if (IsEqualIID(riid, IID_IContextMenu) || + IsEqualIID(riid, IID_IContextMenu2) || + IsEqualIID(riid, IID_IContextMenu3)) { - return ShellObjectCreatorInit(m_shellPidl, cidl, apidl, riid, ppvOut); - //return CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, ContextMenuCallback, 0, NULL, (IContextMenu**) ppvOut); + CComPtr pcm; + + HKEY keys [1]; + + int nkeys = _countof(keys); + if (cidl == 1 && m_PidlManager->IsFolder(apidl[0])) + { + RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0); + } + else + { + nkeys = 0; + } + + HRESULT hr = CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, DefCtxMenuCallback, nkeys, keys, &pcm); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return pcm->QueryInterface(riid, ppvOut); } if (IsEqualIID(riid, IID_IExtractIconW)) @@ -875,6 +787,28 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetUIObjectOf( return ShellObjectCreatorInit(m_shellPidl, cidl, apidl, riid, ppvOut); } + if (IsEqualIID(riid, IID_IDataObject)) + { + return CIDLData_CreateFromIDArray(m_shellPidl, cidl, apidl, (IDataObject**) ppvOut); + } + + if (IsEqualIID(riid, IID_IQueryAssociations)) + { + if (cidl == 1 && m_PidlManager->IsFolder(apidl[0])) + { + CComPtr pqa; + HRESULT hr = AssocCreate(CLSID_QueryAssociations, IID_PPV_ARG(IQueryAssociations, &pqa)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = pqa->Init(ASSOCF_INIT_DEFAULTTOFOLDER, L"NTObjShEx.RegFolder", NULL, hwndOwner); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return pqa->QueryInterface(riid, ppvOut); + } + } + return E_NOTIMPL; } @@ -907,12 +841,13 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDisplayNameOf( if (FAILED_UNEXPECTEDLY(hr)) return hr; + LPCITEMIDLIST pidlFirst = ILCloneFirst(pidl); LPCITEMIDLIST pidlNext = ILGetNext(pidl); if (pidlNext && pidlNext->mkid.cb > 0) { CComPtr psfChild; - hr = BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); + hr = BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -929,6 +864,8 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDisplayNameOf( PathAppendW(path, temp); } + + ILFree((LPITEMIDLIST) pidlFirst); } else { @@ -1219,3 +1156,17 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::MessageSFVCB(UINT uMsg, WPARAM wParam } return E_NOTIMPL; } + +HRESULT CRegistryFolder::DefCtxMenuCallback(IShellFolder * /*psf*/, HWND /*hwnd*/, IDataObject * /*pdtobj*/, UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/) +{ + switch (uMsg) + { + case DFM_MERGECONTEXTMENU: + return S_OK; + case DFM_INVOKECOMMAND: + case DFM_INVOKECOMMANDEX: + case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default + return S_FALSE; + } + return E_NOTIMPL; +} diff --git a/reactos/dll/shellext/ntobjshex/regfolder.h b/reactos/dll/shellext/ntobjshex/regfolder.h index de642a9fd7e..1eed9c82759 100644 --- a/reactos/dll/shellext/ntobjshex/regfolder.h +++ b/reactos/dll/shellext/ntobjshex/regfolder.h @@ -138,6 +138,8 @@ public: // Internal HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath); + static HRESULT CALLBACK DefCtxMenuCallback(IShellFolder *, HWND, IDataObject *, UINT, WPARAM, LPARAM); + DECLARE_REGISTRY_RESOURCEID(IDR_NTOBJECTFOLDER) DECLARE_NOT_AGGREGATABLE(CRegistryFolder) DECLARE_PROTECT_FINAL_CONSTRUCT() diff --git a/reactos/dll/shellext/ntobjshex/resources/rgs/ntobjectfolder.rgs b/reactos/dll/shellext/ntobjshex/resources/rgs/ntobjectfolder.rgs index 7a578cf409f..b4b1cb56070 100644 --- a/reactos/dll/shellext/ntobjshex/resources/rgs/ntobjectfolder.rgs +++ b/reactos/dll/shellext/ntobjshex/resources/rgs/ntobjectfolder.rgs @@ -1,22 +1,33 @@ HKCR { - NoRemove CLSID - { - ForceRemove {845B0FB2-66E0-416B-8F91-314E23F7C12D} = s 'NT Object Namespace Extension' - { - InprocServer32 = s '%MODULE%' - { - val ThreadingModel = s 'Both' - } - val InfoTip = s 'Allows browsing of the NT Object Namespace' - DefaultIcon = s '%MODULE%,0' - ShellFolder - { - val Attributes = d '0xA8000000' - val BrowserFlags = d '0x22' - } - } - } + NTObjShEx.NTDirectory.1 = s 'NT Namespace Directory Class' + { + CLSID = s '{845B0FB2-66E0-416B-8F91-314E23F7C12D}' + } + NTObjShEx.NTDirectory = s 'NT Namespace Directory Class' + { + CLSID = s '{845B0FB2-66E0-416B-8F91-314E23F7C12D}' + CurVer = s 'WMIFldr.CWMIFldr.1' + } + NoRemove CLSID + { + ForceRemove {845B0FB2-66E0-416B-8F91-314E23F7C12D} = s 'NT Object Namespace Extension' + { + ProgID = s 'NTObjShEx.NTDirectory.1' + VersionIndependentProgID = s 'NTObjShEx.NTDirectory' + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Both' + } + val InfoTip = s 'Allows browsing of the NT Object Namespace' + DefaultIcon = s '%MODULE%,0' + ShellFolder + { + val Attributes = d '0xA8000000' + val BrowserFlags = d '0x22' + } + } + } } HKLM {