mirror of
https://github.com/reactos/reactos.git
synced 2025-04-29 10:39:07 +00:00
[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:
parent
d2d2431614
commit
6928fadeff
6 changed files with 257 additions and 338 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -93,7 +93,7 @@ struct RegPidlEntry
|
|||
DWORD contentType;
|
||||
USHORT contentsLength;
|
||||
|
||||
WCHAR entryName[0];
|
||||
WCHAR entryName[ANYSIZE_ARRAY];
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue