[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
This commit is contained in:
David Quintana 2015-03-14 03:15:36 +00:00
parent d2d2431614
commit 6928fadeff
6 changed files with 257 additions and 338 deletions

View file

@ -11,6 +11,11 @@
#include <ntquery.h>
#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<CComMultiThreadModelNoCS>,
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<CComMultiThreadModelNoCS>,
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<IShellFolder> 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<CNtObjectFolderContextMenu>(m_shellPidl, cidl, apidl, riid, ppvOut);
//return CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, ContextMenuCallback, 0, NULL, (IContextMenu**) ppvOut);
CComPtr<IContextMenu> 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<CNtObjectFolderExtractIcon>(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<IQueryAssociations> 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<IShellFolder> 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;
}

View file

@ -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()

View file

@ -93,7 +93,7 @@ struct RegPidlEntry
DWORD contentType;
USHORT contentsLength;
WCHAR entryName[0];
WCHAR entryName[ANYSIZE_ARRAY];
};

View file

@ -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 <gigaherz@gmail.com>
*/
* 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 <gigaherz@gmail.com>
*/
#include "precomp.h"
#include "ntobjutil.h"
#include <ntquery.h>
#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<CComMultiThreadModelNoCS>,
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<CComMultiThreadModelNoCS>,
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<IShellFolder> 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<CRegistryFolderContextMenu>(m_shellPidl, cidl, apidl, riid, ppvOut);
//return CDefFolderMenu_Create2(m_shellPidl, hwndOwner, cidl, apidl, this, ContextMenuCallback, 0, NULL, (IContextMenu**) ppvOut);
CComPtr<IContextMenu> 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<CRegistryFolderExtractIcon>(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<IQueryAssociations> 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<IShellFolder> 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;
}

View file

@ -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()

View file

@ -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
{