mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 15:11:41 +00:00
[NTOBJSHEX]
* Added a common superclass for the ntobj and registry folders. * Refactored the ntobj and registry folders to make use of this superclass. * Removed the concept of a "pidl helper", since it works best to just have the methods be part of the folders. * Cleaned up the ItemID comparison logic. svn path=/trunk/; revision=75175
This commit is contained in:
parent
f369525725
commit
504d12bfff
8 changed files with 1341 additions and 1756 deletions
10
reactos/dll/shellext/ntobjshex/foldercommon.cpp
Normal file
10
reactos/dll/shellext/ntobjshex/foldercommon.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS shell extensions
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: dll/shellext/ntobjshex/ntobjfolder.cpp
|
||||||
|
* PURPOSE: NT Object Namespace shell extension
|
||||||
|
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
#include <ntquery.h>
|
676
reactos/dll/shellext/ntobjshex/foldercommon.h
Normal file
676
reactos/dll/shellext/ntobjshex/foldercommon.h
Normal file
|
@ -0,0 +1,676 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS shell extensions
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: dll/shellext/ntobjshex/ntobjfolder.h
|
||||||
|
* PURPOSE: NT Object Namespace shell extension
|
||||||
|
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern const GUID CLSID_NtObjectFolder;
|
||||||
|
|
||||||
|
class CFolderViewCB :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
public IShellFolderViewCB
|
||||||
|
{
|
||||||
|
IShellView* m_View;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CFolderViewCB() : m_View(NULL) {}
|
||||||
|
virtual ~CFolderViewCB() {}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
case SFVM_DEFVIEWMODE:
|
||||||
|
{
|
||||||
|
FOLDERVIEWMODE* pViewMode = (FOLDERVIEWMODE*)lParam;
|
||||||
|
*pViewMode = FVM_DETAILS;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
case SFVM_COLUMNCLICK:
|
||||||
|
return S_FALSE;
|
||||||
|
case SFVM_BACKGROUNDENUM:
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DbgPrint("MessageSFVCB unimplemented %d %08x %08x\n", uMsg, wParam, lParam);
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Initialize(IShellView* psv)
|
||||||
|
{
|
||||||
|
m_View = psv;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_NOT_AGGREGATABLE(CFolderViewCB)
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CFolderViewCB)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
||||||
|
END_COM_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class TSelf, typename TItemId, class TExtractIcon>
|
||||||
|
class CCommonFolder :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
public IShellFolder2,
|
||||||
|
public IPersistFolder2
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
WCHAR m_NtPath[MAX_PATH];
|
||||||
|
|
||||||
|
LPITEMIDLIST m_shellPidl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CCommonFolder() :
|
||||||
|
m_shellPidl(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~CCommonFolder()
|
||||||
|
{
|
||||||
|
if (m_shellPidl)
|
||||||
|
ILFree(m_shellPidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IShellFolder
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(
|
||||||
|
HWND hwndOwner,
|
||||||
|
LPBC pbcReserved,
|
||||||
|
LPOLESTR lpszDisplayName,
|
||||||
|
ULONG *pchEaten,
|
||||||
|
LPITEMIDLIST *ppidl,
|
||||||
|
ULONG *pdwAttributes)
|
||||||
|
{
|
||||||
|
if (!ppidl)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
if (pchEaten)
|
||||||
|
*pchEaten = 0;
|
||||||
|
|
||||||
|
if (pdwAttributes)
|
||||||
|
*pdwAttributes = 0;
|
||||||
|
|
||||||
|
TRACE("CCommonFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName, m_NtPath);
|
||||||
|
|
||||||
|
const TItemId * info;
|
||||||
|
IEnumIDList * it;
|
||||||
|
HRESULT hr = EnumObjects(hwndOwner, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &it);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
PWSTR end = StrChrW(lpszDisplayName, '\\');
|
||||||
|
int length = end ? end - lpszDisplayName : wcslen(lpszDisplayName);
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
hr = it->Next(1, ppidl, NULL);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (hr != S_OK)
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
|
|
||||||
|
hr = GetInfoFromPidl(*ppidl, &info);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (StrCmpNW(info->entryName, lpszDisplayName, length) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if has remaining path to parse (and the path didn't just terminate in a backslash)
|
||||||
|
if (end && wcslen(end) > 1)
|
||||||
|
{
|
||||||
|
CComPtr<IShellFolder> psfChild;
|
||||||
|
hr = BindToObject(*ppidl, pbcReserved, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
LPITEMIDLIST child;
|
||||||
|
hr = psfChild->ParseDisplayName(hwndOwner, pbcReserved, end + 1, pchEaten, &child, pdwAttributes);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
LPITEMIDLIST old = *ppidl;
|
||||||
|
*ppidl = ILCombine(old, child);
|
||||||
|
ILFree(old);
|
||||||
|
|
||||||
|
// Count the path separator
|
||||||
|
if (pchEaten)
|
||||||
|
(*pchEaten) += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pdwAttributes)
|
||||||
|
*pdwAttributes = ConvertAttributes(info, pdwAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pchEaten)
|
||||||
|
*pchEaten += wcslen(info->entryName);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
|
||||||
|
HWND hwndOwner,
|
||||||
|
SHCONTF grfFlags,
|
||||||
|
IEnumIDList **ppenumIDList) PURE;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE BindToObject(
|
||||||
|
LPCITEMIDLIST pidl,
|
||||||
|
LPBC pbcReserved,
|
||||||
|
REFIID riid,
|
||||||
|
void **ppvOut)
|
||||||
|
{
|
||||||
|
const TItemId * info;
|
||||||
|
|
||||||
|
if (IsEqualIID(riid, IID_IShellFolder))
|
||||||
|
{
|
||||||
|
HRESULT hr = GetInfoFromPidl(pidl, &info);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
|
||||||
|
StringCbCopyW(path, _countof(path), m_NtPath);
|
||||||
|
PathAppendW(path, info->entryName);
|
||||||
|
|
||||||
|
LPITEMIDLIST first = ILCloneFirst(pidl);
|
||||||
|
LPCITEMIDLIST rest = ILGetNext(pidl);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
ILFree(fullPidl);
|
||||||
|
ILFree(first);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (hr == S_FALSE)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
if (rest->mkid.cb > 0)
|
||||||
|
{
|
||||||
|
return psfChild->BindToObject(rest, pbcReserved, riid, ppvOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
return psfChild->QueryInterface(riid, ppvOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
||||||
|
PWSTR path,
|
||||||
|
const TItemId * info,
|
||||||
|
LPITEMIDLIST first,
|
||||||
|
LPCITEMIDLIST rest,
|
||||||
|
LPITEMIDLIST fullPidl,
|
||||||
|
LPBC pbcReserved,
|
||||||
|
IShellFolder** ppsfChild) PURE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE RedirectToSymLink(
|
||||||
|
const TItemId * info,
|
||||||
|
LPITEMIDLIST first,
|
||||||
|
LPCITEMIDLIST rest,
|
||||||
|
LPBC pbcReserved,
|
||||||
|
IShellFolder ** ppsfChild)
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
|
||||||
|
LPCITEMIDLIST pidl,
|
||||||
|
LPBC pbcReserved,
|
||||||
|
REFIID riid,
|
||||||
|
void **ppvObj)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CompareIDs(
|
||||||
|
LPARAM lParam,
|
||||||
|
LPCITEMIDLIST pidl1,
|
||||||
|
LPCITEMIDLIST pidl2)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("CompareIDs %d\n", lParam);
|
||||||
|
|
||||||
|
const TItemId * id1;
|
||||||
|
hr = GetInfoFromPidl(pidl1, &id1);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
const TItemId * id2;
|
||||||
|
hr = GetInfoFromPidl(pidl2, &id2);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
hr = CompareIDs(lParam, id1, id2);
|
||||||
|
if (hr != S_EQUAL)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
// The wollowing snipped is basically SHELL32_CompareChildren
|
||||||
|
|
||||||
|
PUIDLIST_RELATIVE rest1 = ILGetNext(pidl1);
|
||||||
|
PUIDLIST_RELATIVE rest2 = ILGetNext(pidl2);
|
||||||
|
|
||||||
|
bool isEmpty1 = (rest1->mkid.cb == 0);
|
||||||
|
bool isEmpty2 = (rest2->mkid.cb == 0);
|
||||||
|
|
||||||
|
if (isEmpty1 || isEmpty1)
|
||||||
|
return MAKE_COMPARE_HRESULT(isEmpty2 - isEmpty1);
|
||||||
|
|
||||||
|
LPCITEMIDLIST first1 = ILCloneFirst(pidl1);
|
||||||
|
if (!first1)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
CComPtr<IShellFolder> psfNext;
|
||||||
|
hr = BindToObject(first1, NULL, IID_PPV_ARG(IShellFolder, &psfNext));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
return psfNext->CompareIDs(lParam, rest1, rest2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CompareName(
|
||||||
|
LPARAM lParam,
|
||||||
|
const TItemId * first,
|
||||||
|
const TItemId * second)
|
||||||
|
{
|
||||||
|
bool f1 = IsFolder(first);
|
||||||
|
bool f2 = IsFolder(second);
|
||||||
|
|
||||||
|
HRESULT hr = MAKE_COMPARE_HRESULT(f2 - f1);
|
||||||
|
if (hr != S_EQUAL)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
bool canonical = (lParam & 0xFFFF0000) == SHCIDS_CANONICALONLY;
|
||||||
|
if (canonical)
|
||||||
|
{
|
||||||
|
// Shortcut: avoid comparing contents if not necessary when the results are not for display.
|
||||||
|
hr = MAKE_COMPARE_HRESULT(second->entryNameLength - first->entryNameLength);
|
||||||
|
if (hr != S_EQUAL)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
int minlength = min(first->entryNameLength, second->entryNameLength);
|
||||||
|
if (minlength > 0)
|
||||||
|
{
|
||||||
|
hr = MAKE_COMPARE_HRESULT(memcmp(first->entryName, second->entryName, minlength));
|
||||||
|
if (hr != S_EQUAL)
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_EQUAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minlength = min(first->entryNameLength, second->entryNameLength);
|
||||||
|
if (minlength > 0)
|
||||||
|
{
|
||||||
|
hr = MAKE_COMPARE_HRESULT(StrCmpNW(first->entryName, second->entryName, minlength / sizeof(WCHAR)));
|
||||||
|
if (hr != S_EQUAL)
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MAKE_COMPARE_HRESULT(second->entryNameLength - first->entryNameLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CreateViewObject(
|
||||||
|
HWND hwndOwner,
|
||||||
|
REFIID riid,
|
||||||
|
void **ppvOut)
|
||||||
|
{
|
||||||
|
if (!IsEqualIID(riid, IID_IShellView))
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
_CComObject<CFolderViewCB> *pcb;
|
||||||
|
|
||||||
|
HRESULT hr = _CComObject<CFolderViewCB>::CreateInstance(&pcb);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
pcb->AddRef();
|
||||||
|
|
||||||
|
SFV_CREATE sfv;
|
||||||
|
sfv.cbSize = sizeof(sfv);
|
||||||
|
sfv.pshf = this;
|
||||||
|
sfv.psvOuter = NULL;
|
||||||
|
sfv.psfvcb = pcb;
|
||||||
|
|
||||||
|
IShellView* view;
|
||||||
|
|
||||||
|
hr = SHCreateShellFolderView(&sfv, &view);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
pcb->Initialize(view);
|
||||||
|
|
||||||
|
pcb->Release();
|
||||||
|
|
||||||
|
*ppvOut = view;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetAttributesOf(
|
||||||
|
UINT cidl,
|
||||||
|
PCUITEMID_CHILD_ARRAY apidl,
|
||||||
|
SFGAOF *rgfInOut)
|
||||||
|
{
|
||||||
|
const TItemId * info;
|
||||||
|
|
||||||
|
TRACE("GetAttributesOf %d\n", cidl);
|
||||||
|
|
||||||
|
if (cidl == 0)
|
||||||
|
{
|
||||||
|
*rgfInOut &= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)cidl; i++)
|
||||||
|
{
|
||||||
|
PCUITEMID_CHILD pidl = apidl[i];
|
||||||
|
|
||||||
|
HRESULT hr = GetInfoFromPidl(pidl, &info);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
// Update attributes.
|
||||||
|
*rgfInOut = ConvertAttributes(info, rgfInOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetUIObjectOf(
|
||||||
|
HWND hwndOwner,
|
||||||
|
UINT cidl,
|
||||||
|
PCUITEMID_CHILD_ARRAY apidl,
|
||||||
|
REFIID riid,
|
||||||
|
UINT *prgfInOut,
|
||||||
|
void **ppvOut)
|
||||||
|
{
|
||||||
|
DWORD res;
|
||||||
|
TRACE("GetUIObjectOf\n");
|
||||||
|
|
||||||
|
if (IsEqualIID(riid, IID_IContextMenu) ||
|
||||||
|
IsEqualIID(riid, IID_IContextMenu2) ||
|
||||||
|
IsEqualIID(riid, IID_IContextMenu3))
|
||||||
|
{
|
||||||
|
CComPtr<IContextMenu> pcm;
|
||||||
|
|
||||||
|
HKEY keys[1];
|
||||||
|
|
||||||
|
int nkeys = _countof(keys);
|
||||||
|
if (cidl == 1 && IsFolder(apidl[0]))
|
||||||
|
{
|
||||||
|
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
||||||
|
if (!NT_SUCCESS(res))
|
||||||
|
return HRESULT_FROM_NT(res);
|
||||||
|
}
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
return ShellObjectCreatorInit<TExtractIcon>(m_NtPath, 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 && 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetDisplayNameOf(
|
||||||
|
LPCITEMIDLIST pidl,
|
||||||
|
SHGDNF uFlags,
|
||||||
|
STRRET *lpName)
|
||||||
|
{
|
||||||
|
const TItemId * info;
|
||||||
|
|
||||||
|
TRACE("GetDisplayNameOf %p\n", pidl);
|
||||||
|
|
||||||
|
HRESULT hr = GetInfoFromPidl(pidl, &info);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (GET_SHGDN_FOR(uFlags) & SHGDN_FOREDITING)
|
||||||
|
{
|
||||||
|
hr = MakeStrRetFromString(info->entryName, info->entryNameLength, lpName);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR path[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
|
if (GET_SHGDN_FOR(uFlags) & SHGDN_FORPARSING)
|
||||||
|
{
|
||||||
|
if (GET_SHGDN_RELATION(uFlags) != SHGDN_INFOLDER)
|
||||||
|
{
|
||||||
|
hr = GetFullName(m_shellPidl, uFlags, path, _countof(path));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PathAppendW(path, info->entryName);
|
||||||
|
|
||||||
|
LPCITEMIDLIST pidlNext = ILGetNext(pidl);
|
||||||
|
if (pidlNext && pidlNext->mkid.cb > 0)
|
||||||
|
{
|
||||||
|
LPITEMIDLIST pidlFirst = ILCloneFirst(pidl);
|
||||||
|
|
||||||
|
CComPtr<IShellFolder> psfChild;
|
||||||
|
hr = BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
WCHAR temp[MAX_PATH];
|
||||||
|
STRRET childName;
|
||||||
|
|
||||||
|
hr = psfChild->GetDisplayNameOf(pidlNext, uFlags | SHGDN_INFOLDER, &childName);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = StrRetToBufW(&childName, pidlNext, temp, _countof(temp));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
PathAppendW(path, temp);
|
||||||
|
|
||||||
|
ILFree(pidlFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = MakeStrRetFromString(path, lpName);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE SetNameOf(
|
||||||
|
HWND hwnd,
|
||||||
|
LPCITEMIDLIST pidl,
|
||||||
|
LPCOLESTR lpszName,
|
||||||
|
SHGDNF uFlags,
|
||||||
|
LPITEMIDLIST *ppidlOut)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IShellFolder2
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultSearchGUID(
|
||||||
|
GUID *lpguid)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE EnumSearches(
|
||||||
|
IEnumExtraSearch **ppenum)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumn(
|
||||||
|
DWORD dwReserved,
|
||||||
|
ULONG *pSort,
|
||||||
|
ULONG *pDisplay)
|
||||||
|
{
|
||||||
|
if (pSort)
|
||||||
|
*pSort = 0;
|
||||||
|
if (pDisplay)
|
||||||
|
*pDisplay = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
||||||
|
UINT iColumn,
|
||||||
|
SHCOLSTATEF *pcsFlags) PURE;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetDetailsEx(
|
||||||
|
LPCITEMIDLIST pidl,
|
||||||
|
const SHCOLUMNID *pscid,
|
||||||
|
VARIANT *pv) PURE;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetDetailsOf(
|
||||||
|
LPCITEMIDLIST pidl,
|
||||||
|
UINT iColumn,
|
||||||
|
SHELLDETAILS *psd) PURE;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE MapColumnToSCID(
|
||||||
|
UINT iColumn,
|
||||||
|
SHCOLUMNID *pscid) PURE;
|
||||||
|
|
||||||
|
// IPersist
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *lpClassId)
|
||||||
|
{
|
||||||
|
if (!lpClassId)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
*lpClassId = CLSID_NtObjectFolder;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPersistFolder
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
m_shellPidl = ILClone(pidl);
|
||||||
|
|
||||||
|
StringCbCopy(m_NtPath, _countof(m_NtPath), L"\\");
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPersistFolder2
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetCurFolder(LPITEMIDLIST * pidl)
|
||||||
|
{
|
||||||
|
if (pidl)
|
||||||
|
*pidl = ILClone(m_shellPidl);
|
||||||
|
if (!m_shellPidl)
|
||||||
|
return S_FALSE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
protected:
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CompareIDs(
|
||||||
|
LPARAM lParam,
|
||||||
|
const TItemId * first,
|
||||||
|
const TItemId * second) PURE;
|
||||||
|
|
||||||
|
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(
|
||||||
|
const TItemId * entry,
|
||||||
|
PULONG inMask) PURE;
|
||||||
|
|
||||||
|
virtual BOOL STDMETHODCALLTYPE IsFolder(LPCITEMIDLIST pcidl) PURE;
|
||||||
|
|
||||||
|
virtual BOOL STDMETHODCALLTYPE IsFolder(const TItemId * info) PURE;
|
||||||
|
|
||||||
|
virtual BOOL STDMETHODCALLTYPE IsSymLink(const TItemId * info)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const TItemId ** pentry) PURE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static HRESULT CALLBACK 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_REGISTRY_RESOURCEID(IDR_REGISTRYFOLDER)
|
||||||
|
DECLARE_NOT_AGGREGATABLE(TSelf)
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(TSelf)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
};
|
|
@ -16,9 +16,7 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <precomp.h>
|
#include "precomp.h"
|
||||||
|
|
||||||
#include "ntobjenum.h"
|
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
|
WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
|
||||||
|
|
|
@ -7,20 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "ntobjenum.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
|
|
||||||
|
|
||||||
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
|
|
||||||
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
|
WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
|
||||||
|
|
||||||
|
@ -38,27 +24,20 @@ enum NtObjectColumns
|
||||||
NTOBJECT_COLUMN_END
|
NTOBJECT_COLUMN_END
|
||||||
};
|
};
|
||||||
|
|
||||||
class CNtObjectFolderExtractIcon :
|
CNtObjectFolderExtractIcon::CNtObjectFolderExtractIcon() :
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
m_pcidlChild(NULL),
|
||||||
public IExtractIconW
|
m_NtPath(NULL)
|
||||||
{
|
|
||||||
PCITEMID_CHILD m_pcidlChild;
|
|
||||||
LPCWSTR m_NtPath;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CNtObjectFolderExtractIcon() :
|
|
||||||
m_pcidlChild(NULL), m_NtPath(NULL)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CNtObjectFolderExtractIcon()
|
CNtObjectFolderExtractIcon::~CNtObjectFolderExtractIcon()
|
||||||
{
|
{
|
||||||
if (m_pcidlChild)
|
if (m_pcidlChild)
|
||||||
ILFree((LPITEMIDLIST) m_pcidlChild);
|
ILFree((LPITEMIDLIST) m_pcidlChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Initialize(LPCWSTR ntPath, UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
HRESULT CNtObjectFolderExtractIcon::Initialize(LPCWSTR ntPath, PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
||||||
{
|
{
|
||||||
m_NtPath = ntPath;
|
m_NtPath = ntPath;
|
||||||
if (cidl != 1)
|
if (cidl != 1)
|
||||||
|
@ -67,7 +46,7 @@ public:
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetIconLocation(
|
HRESULT STDMETHODCALLTYPE CNtObjectFolderExtractIcon::GetIconLocation(
|
||||||
UINT uFlags,
|
UINT uFlags,
|
||||||
LPWSTR szIconFile,
|
LPWSTR szIconFile,
|
||||||
UINT cchMax,
|
UINT cchMax,
|
||||||
|
@ -112,7 +91,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Extract(
|
HRESULT STDMETHODCALLTYPE CNtObjectFolderExtractIcon::Extract(
|
||||||
LPCWSTR pszFile,
|
LPCWSTR pszFile,
|
||||||
UINT nIconIndex,
|
UINT nIconIndex,
|
||||||
HICON *phiconLarge,
|
HICON *phiconLarge,
|
||||||
|
@ -122,275 +101,18 @@ public:
|
||||||
return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
|
return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_NOT_AGGREGATABLE(CNtObjectFolderExtractIcon)
|
|
||||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
||||||
|
|
||||||
BEGIN_COM_MAP(CNtObjectFolderExtractIcon)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW)
|
|
||||||
END_COM_MAP()
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class CNtObjectPidlHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static HRESULT CompareIDs(LPARAM lParam, const NtPidlEntry * first, const NtPidlEntry * second)
|
|
||||||
{
|
|
||||||
if ((lParam & 0xFFFF0000) == SHCIDS_ALLFIELDS)
|
|
||||||
{
|
|
||||||
if (lParam != 0)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
int minsize = min(first->cb, second->cb);
|
|
||||||
int ord = memcmp(second, first, minsize);
|
|
||||||
|
|
||||||
if (ord != 0)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) ord);
|
|
||||||
|
|
||||||
if (second->cb > first->cb)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) 1);
|
|
||||||
if (second->cb < first->cb)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) -1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool canonical = ((lParam & 0xFFFF0000) == SHCIDS_CANONICALONLY);
|
|
||||||
|
|
||||||
switch (lParam & 0xFFFF)
|
|
||||||
{
|
|
||||||
case NTOBJECT_COLUMN_NAME:
|
|
||||||
{
|
|
||||||
bool f1 = (first->objectType == KEY_OBJECT) || (first->objectType == DIRECTORY_OBJECT);
|
|
||||||
bool f2 = (second->objectType == KEY_OBJECT) || (second->objectType == DIRECTORY_OBJECT);
|
|
||||||
|
|
||||||
if (f1 && !f2)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) -1);
|
|
||||||
if (f2 && !f1)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) 1);
|
|
||||||
|
|
||||||
if (canonical)
|
|
||||||
{
|
|
||||||
// Shortcut: avoid comparing contents if not necessary when the results are not for display.
|
|
||||||
if (second->entryNameLength > first->entryNameLength)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) 1);
|
|
||||||
if (second->entryNameLength < first->entryNameLength)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) -1);
|
|
||||||
|
|
||||||
int minlength = min(first->entryNameLength, second->entryNameLength);
|
|
||||||
if (minlength > 0)
|
|
||||||
{
|
|
||||||
int ord = memcmp(first->entryName, second->entryName, minlength);
|
|
||||||
if (ord != 0)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) ord);
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int minlength = min(first->entryNameLength, second->entryNameLength);
|
|
||||||
if (minlength > 0)
|
|
||||||
{
|
|
||||||
int ord = StrCmpNW(first->entryName, second->entryName, minlength / sizeof(WCHAR));
|
|
||||||
if (ord != 0)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) ord);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (second->entryNameLength > first->entryNameLength)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) 1);
|
|
||||||
if (second->entryNameLength < first->entryNameLength)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) -1);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case NTOBJECT_COLUMN_TYPE:
|
|
||||||
{
|
|
||||||
int ord = second->objectType - first->objectType;
|
|
||||||
if (ord > 0)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) 1);
|
|
||||||
if (ord < 0)
|
|
||||||
return MAKE_HRESULT(0, 0, (USHORT) -1);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
case NTOBJECT_COLUMN_LINKTARGET:
|
|
||||||
{
|
|
||||||
// Can't sort by value
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
DbgPrint("Unsupported sorting mode.\n");
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT CompareIDs(LPARAM lParam, const NtPidlEntry * first, LPCITEMIDLIST pcidl)
|
|
||||||
{
|
|
||||||
LPCITEMIDLIST p = pcidl;
|
|
||||||
NtPidlEntry * second = (NtPidlEntry*) &(p->mkid);
|
|
||||||
if ((second->cb < sizeof(NtPidlEntry)) || (second->magic != NT_OBJECT_PIDL_MAGIC))
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
return CompareIDs(lParam, first, second);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT CompareIDs(LPARAM lParam, LPCITEMIDLIST pcidl1, LPCITEMIDLIST pcidl2)
|
|
||||||
{
|
|
||||||
LPCITEMIDLIST p = pcidl1;
|
|
||||||
NtPidlEntry * first = (NtPidlEntry*) &(p->mkid);
|
|
||||||
if ((first->cb < sizeof(NtPidlEntry)) || (first->magic != NT_OBJECT_PIDL_MAGIC))
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
return CompareIDs(lParam, first, pcidl2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ULONG ConvertAttributes(const NtPidlEntry * entry, PULONG inMask)
|
|
||||||
{
|
|
||||||
ULONG mask = inMask ? *inMask : 0xFFFFFFFF;
|
|
||||||
ULONG flags = SFGAO_HASPROPSHEET | SFGAO_CANLINK;
|
|
||||||
|
|
||||||
if (entry->objectType == DIRECTORY_OBJECT)
|
|
||||||
flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
|
||||||
|
|
||||||
if (entry->objectType == SYMBOLICLINK_OBJECT)
|
|
||||||
flags |= SFGAO_LINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
|
||||||
|
|
||||||
if (entry->objectType == KEY_OBJECT)
|
|
||||||
flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
|
||||||
|
|
||||||
return flags & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL IsFolder(LPCITEMIDLIST pcidl)
|
|
||||||
{
|
|
||||||
NtPidlEntry * entry = (NtPidlEntry*) &(pcidl->mkid);
|
|
||||||
if ((entry->cb < sizeof(NtPidlEntry)) || (entry->magic != NT_OBJECT_PIDL_MAGIC))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return (entry->objectType == DIRECTORY_OBJECT) ||
|
|
||||||
(entry->objectType == SYMBOLICLINK_OBJECT) ||
|
|
||||||
(entry->objectType == KEY_OBJECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const NtPidlEntry ** pentry)
|
|
||||||
{
|
|
||||||
NtPidlEntry * entry = (NtPidlEntry*) &(pcidl->mkid);
|
|
||||||
|
|
||||||
if (entry->cb < sizeof(NtPidlEntry))
|
|
||||||
{
|
|
||||||
DbgPrint("PCIDL too small %l (required %l)\n", entry->cb, sizeof(NtPidlEntry));
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry->magic != NT_OBJECT_PIDL_MAGIC)
|
|
||||||
{
|
|
||||||
DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry->magic, NT_OBJECT_PIDL_MAGIC);
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pentry = entry;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// CNtObjectFolder
|
// CNtObjectFolder
|
||||||
|
|
||||||
CNtObjectFolder::CNtObjectFolder() :
|
CNtObjectFolder::CNtObjectFolder()
|
||||||
m_shellPidl(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CNtObjectFolder::~CNtObjectFolder()
|
CNtObjectFolder::~CNtObjectFolder()
|
||||||
{
|
{
|
||||||
if (m_shellPidl)
|
|
||||||
ILFree(m_shellPidl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IShellFolder
|
// IShellFolder
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::ParseDisplayName(
|
|
||||||
HWND hwndOwner,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
LPOLESTR lpszDisplayName,
|
|
||||||
ULONG *pchEaten,
|
|
||||||
LPITEMIDLIST *ppidl,
|
|
||||||
ULONG *pdwAttributes)
|
|
||||||
{
|
|
||||||
if (!ppidl)
|
|
||||||
return E_POINTER;
|
|
||||||
|
|
||||||
if (pchEaten)
|
|
||||||
*pchEaten = 0;
|
|
||||||
|
|
||||||
if (pdwAttributes)
|
|
||||||
*pdwAttributes = 0;
|
|
||||||
|
|
||||||
TRACE("CNtObjectFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName, m_NtPath);
|
|
||||||
|
|
||||||
const NtPidlEntry * info;
|
|
||||||
IEnumIDList * it;
|
|
||||||
HRESULT hr = GetEnumNTDirectory(m_NtPath, &it);
|
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
PWSTR end = StrChrW(lpszDisplayName, '\\');
|
|
||||||
int length = end ? end - lpszDisplayName : wcslen(lpszDisplayName);
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
hr = it->Next(1, ppidl, NULL);
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
if (hr != S_OK)
|
|
||||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
||||||
|
|
||||||
hr = CNtObjectPidlHelper::GetInfoFromPidl(*ppidl, &info);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
if (StrCmpNW(info->entryName, lpszDisplayName, length) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if has remaining path to parse (and the path didn't just terminate in a backslash)
|
|
||||||
if (end && wcslen(end) > 1)
|
|
||||||
{
|
|
||||||
CComPtr<IShellFolder> psfChild;
|
|
||||||
hr = BindToObject(*ppidl, pbcReserved, IID_PPV_ARG(IShellFolder, &psfChild));
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
LPITEMIDLIST child;
|
|
||||||
hr = psfChild->ParseDisplayName(hwndOwner, pbcReserved, end + 1, pchEaten, &child, pdwAttributes);
|
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
LPITEMIDLIST old = *ppidl;
|
|
||||||
*ppidl = ILCombine(old, child);
|
|
||||||
ILFree(old);
|
|
||||||
|
|
||||||
// Count the path separator
|
|
||||||
if (pchEaten)
|
|
||||||
(*pchEaten) += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pdwAttributes)
|
|
||||||
*pdwAttributes = CNtObjectPidlHelper::ConvertAttributes(info, pdwAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pchEaten)
|
|
||||||
*pchEaten += wcslen(info->entryName);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::EnumObjects(
|
HRESULT STDMETHODCALLTYPE CNtObjectFolder::EnumObjects(
|
||||||
HWND hwndOwner,
|
HWND hwndOwner,
|
||||||
|
@ -400,32 +122,20 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::EnumObjects(
|
||||||
return GetEnumNTDirectory(m_NtPath, ppenumIDList);
|
return GetEnumNTDirectory(m_NtPath, ppenumIDList);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
BOOL STDMETHODCALLTYPE CNtObjectFolder::IsSymLink(const NtPidlEntry * info)
|
||||||
LPCITEMIDLIST pidl,
|
{
|
||||||
|
return info->objectType == SYMBOLICLINK_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CNtObjectFolder::RedirectToSymLink(
|
||||||
|
const NtPidlEntry * info,
|
||||||
|
LPITEMIDLIST first,
|
||||||
|
LPCITEMIDLIST rest,
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
REFIID riid,
|
IShellFolder ** ppsfChild)
|
||||||
void **ppvOut)
|
|
||||||
{
|
{
|
||||||
const NtPidlEntry * info;
|
HRESULT hr;
|
||||||
|
|
||||||
if (IsEqualIID(riid, IID_IShellFolder))
|
|
||||||
{
|
|
||||||
HRESULT hr = CNtObjectPidlHelper::GetInfoFromPidl(pidl, &info);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
WCHAR path[MAX_PATH];
|
|
||||||
|
|
||||||
StringCbCopyW(path, _countof(path), m_NtPath);
|
|
||||||
PathAppendW(path, info->entryName);
|
|
||||||
|
|
||||||
LPITEMIDLIST first = ILCloneFirst(pidl);
|
|
||||||
LPCITEMIDLIST rest = ILGetNext(pidl);
|
|
||||||
|
|
||||||
LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, first);
|
|
||||||
|
|
||||||
if (info->objectType == SYMBOLICLINK_OBJECT)
|
|
||||||
{
|
|
||||||
WCHAR wbLink[MAX_PATH] = { 0 };
|
WCHAR wbLink[MAX_PATH] = { 0 };
|
||||||
UNICODE_STRING link;
|
UNICODE_STRING link;
|
||||||
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
||||||
|
@ -434,10 +144,14 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
|
||||||
if (link.Length > 0)
|
if (link.Length > 0)
|
||||||
{
|
{
|
||||||
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;
|
CComPtr<IShellFolder> psfDesktop;
|
||||||
hr = SHGetDesktopFolder(&psfDesktop);
|
hr = SHGetDesktopFolder(&psfDesktop);
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
@ -447,7 +161,11 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
return psfDesktop->BindToObject(rest, pbcReserved, riid, ppvOut);
|
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}");
|
StringCbCopyW(path, _countof(path), L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
|
||||||
|
@ -465,291 +183,34 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
CComPtr<IShellFolder> psfChild;
|
CComPtr<IShellFolder> psfChild;
|
||||||
hr = psfDesktop->BindToObject(pidl, NULL, riid, ppvOut);
|
hr = psfDesktop->BindToObject(pidl, pbcReserved, IID_PPV_ARG(IShellFolder, ppsfChild));
|
||||||
ILFree(pidl);
|
ILFree(pidl);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
}
|
|
||||||
else
|
return S_FALSE;;
|
||||||
{
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CComPtr<IShellFolder> psfChild;
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CNtObjectFolder::InternalBindToObject(
|
||||||
|
PWSTR path,
|
||||||
|
const NtPidlEntry * info,
|
||||||
|
LPITEMIDLIST first,
|
||||||
|
LPCITEMIDLIST rest,
|
||||||
|
LPITEMIDLIST fullPidl,
|
||||||
|
LPBC pbcReserved,
|
||||||
|
IShellFolder** ppsfChild)
|
||||||
|
{
|
||||||
|
|
||||||
if (info->objectType == KEY_OBJECT)
|
if (info->objectType == KEY_OBJECT)
|
||||||
{
|
{
|
||||||
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, (HKEY) NULL, IID_PPV_ARG(IShellFolder, &psfChild));
|
return ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, (HKEY) NULL, IID_PPV_ARG(IShellFolder, ppsfChild));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = ShellObjectCreatorInit<CNtObjectFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, &psfChild));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ILFree(fullPidl);
|
return ShellObjectCreatorInit<CNtObjectFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, ppsfChild));
|
||||||
ILFree(first);
|
|
||||||
|
|
||||||
if (rest->mkid.cb > 0)
|
|
||||||
{
|
|
||||||
return psfChild->BindToObject(rest, pbcReserved, riid, ppvOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
return psfChild->QueryInterface(riid, ppvOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToStorage(
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
REFIID riid,
|
|
||||||
void **ppvObj)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::CompareIDs(
|
|
||||||
LPARAM lParam,
|
|
||||||
LPCITEMIDLIST pidl1,
|
|
||||||
LPCITEMIDLIST pidl2)
|
|
||||||
{
|
|
||||||
TRACE("CompareIDs\n");
|
|
||||||
|
|
||||||
HRESULT hr = CNtObjectPidlHelper::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(
|
|
||||||
HWND hwndOwner,
|
|
||||||
REFIID riid,
|
|
||||||
void **ppvOut)
|
|
||||||
{
|
|
||||||
if (!IsEqualIID(riid, IID_IShellView))
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
|
|
||||||
SFV_CREATE sfv;
|
|
||||||
sfv.cbSize = sizeof(sfv);
|
|
||||||
sfv.pshf = static_cast<IShellFolder*>(this);
|
|
||||||
sfv.psvOuter = NULL;
|
|
||||||
sfv.psfvcb = static_cast<IShellFolderViewCB*>(this);
|
|
||||||
|
|
||||||
return SHCreateShellFolderView(&sfv, (IShellView**) ppvOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetAttributesOf(
|
|
||||||
UINT cidl,
|
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
|
||||||
SFGAOF *rgfInOut)
|
|
||||||
{
|
|
||||||
const NtPidlEntry * info;
|
|
||||||
|
|
||||||
TRACE("GetAttributesOf %d\n", cidl);
|
|
||||||
|
|
||||||
if (cidl == 0)
|
|
||||||
{
|
|
||||||
*rgfInOut &= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < (int) cidl; i++)
|
|
||||||
{
|
|
||||||
PCUITEMID_CHILD pidl = apidl[i];
|
|
||||||
|
|
||||||
HRESULT hr = CNtObjectPidlHelper::GetInfoFromPidl(pidl, &info);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
// Update attributes.
|
|
||||||
*rgfInOut = CNtObjectPidlHelper::ConvertAttributes(info, rgfInOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetUIObjectOf(
|
|
||||||
HWND hwndOwner,
|
|
||||||
UINT cidl,
|
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
|
||||||
REFIID riid,
|
|
||||||
UINT *prgfInOut,
|
|
||||||
void **ppvOut)
|
|
||||||
{
|
|
||||||
DWORD res;
|
|
||||||
TRACE("GetUIObjectOf\n");
|
|
||||||
|
|
||||||
if (IsEqualIID(riid, IID_IContextMenu) ||
|
|
||||||
IsEqualIID(riid, IID_IContextMenu2) ||
|
|
||||||
IsEqualIID(riid, IID_IContextMenu3))
|
|
||||||
{
|
|
||||||
CComPtr<IContextMenu> pcm;
|
|
||||||
|
|
||||||
HKEY keys[1];
|
|
||||||
|
|
||||||
int nkeys = _countof(keys);
|
|
||||||
if (cidl == 1 && CNtObjectPidlHelper::IsFolder(apidl[0]))
|
|
||||||
{
|
|
||||||
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
|
||||||
if (!NT_SUCCESS(res))
|
|
||||||
return HRESULT_FROM_NT(res);
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
return ShellObjectCreatorInit<CNtObjectFolderExtractIcon>(m_NtPath, 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 && CNtObjectPidlHelper::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDisplayNameOf(
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
SHGDNF uFlags,
|
|
||||||
STRRET *lpName)
|
|
||||||
{
|
|
||||||
const NtPidlEntry * info;
|
|
||||||
|
|
||||||
TRACE("GetDisplayNameOf %p\n", pidl);
|
|
||||||
|
|
||||||
HRESULT hr = CNtObjectPidlHelper::GetInfoFromPidl(pidl, &info);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
if (GET_SHGDN_FOR(uFlags) & SHGDN_FOREDITING)
|
|
||||||
{
|
|
||||||
hr = MakeStrRetFromString(info->entryName, info->entryNameLength, lpName);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR path[MAX_PATH] = { 0 };
|
|
||||||
|
|
||||||
if (GET_SHGDN_FOR(uFlags) & SHGDN_FORPARSING)
|
|
||||||
{
|
|
||||||
if (GET_SHGDN_RELATION(uFlags) != SHGDN_INFOLDER)
|
|
||||||
{
|
|
||||||
hr = GetFullName(m_shellPidl, uFlags, path, _countof(path));
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PathAppendW(path, info->entryName);
|
|
||||||
|
|
||||||
LPCITEMIDLIST pidlNext = ILGetNext(pidl);
|
|
||||||
if (pidlNext && pidlNext->mkid.cb > 0)
|
|
||||||
{
|
|
||||||
LPITEMIDLIST pidlFirst = ILCloneFirst(pidl);
|
|
||||||
|
|
||||||
CComPtr<IShellFolder> psfChild;
|
|
||||||
hr = BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
WCHAR temp[MAX_PATH];
|
|
||||||
STRRET childName;
|
|
||||||
|
|
||||||
hr = psfChild->GetDisplayNameOf(pidlNext, uFlags | SHGDN_INFOLDER, &childName);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
hr = StrRetToBufW(&childName, pidlNext, temp, _countof(temp));
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
PathAppendW(path, temp);
|
|
||||||
|
|
||||||
ILFree(pidlFirst);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = MakeStrRetFromString(path, lpName);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::SetNameOf(
|
|
||||||
HWND hwnd,
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
LPCOLESTR lpszName,
|
|
||||||
SHGDNF uFlags,
|
|
||||||
LPITEMIDLIST *ppidlOut)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPersist
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetClassID(CLSID *lpClassId)
|
|
||||||
{
|
|
||||||
if (!lpClassId)
|
|
||||||
return E_POINTER;
|
|
||||||
|
|
||||||
*lpClassId = CLSID_NtObjectFolder;
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPersistFolder
|
// IPersistFolder
|
||||||
|
@ -772,43 +233,6 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::Initialize(LPCITEMIDLIST pidl, PCWSTR
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPersistFolder2
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetCurFolder(LPITEMIDLIST * pidl)
|
|
||||||
{
|
|
||||||
if (pidl)
|
|
||||||
*pidl = ILClone(m_shellPidl);
|
|
||||||
if (!m_shellPidl)
|
|
||||||
return S_FALSE;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IShellFolder2
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultSearchGUID(
|
|
||||||
GUID *lpguid)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::EnumSearches(
|
|
||||||
IEnumExtraSearch **ppenum)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultColumn(
|
|
||||||
DWORD dwReserved,
|
|
||||||
ULONG *pSort,
|
|
||||||
ULONG *pDisplay)
|
|
||||||
{
|
|
||||||
if (pSort)
|
|
||||||
*pSort = 0;
|
|
||||||
if (pDisplay)
|
|
||||||
*pDisplay = 0;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultColumnState(
|
HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultColumnState(
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
SHCOLSTATEF *pcsFlags)
|
SHCOLSTATEF *pcsFlags)
|
||||||
|
@ -822,7 +246,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultColumnState(
|
||||||
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
|
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
case NTOBJECT_COLUMN_LINKTARGET:
|
case NTOBJECT_COLUMN_LINKTARGET:
|
||||||
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_SLOW;
|
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT | SHCOLSTATE_SLOW;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -840,7 +264,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsEx(
|
||||||
|
|
||||||
if (pidl)
|
if (pidl)
|
||||||
{
|
{
|
||||||
HRESULT hr = CNtObjectPidlHelper::GetInfoFromPidl(pidl, &info);
|
HRESULT hr = GetInfoFromPidl(pidl, &info);
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
@ -907,7 +331,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||||
|
|
||||||
if (pidl)
|
if (pidl)
|
||||||
{
|
{
|
||||||
HRESULT hr = CNtObjectPidlHelper::GetInfoFromPidl(pidl, &info);
|
HRESULT hr = GetInfoFromPidl(pidl, &info);
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
@ -1011,34 +435,92 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::MapColumnToSCID(
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
HRESULT CNtObjectFolder::CompareIDs(LPARAM lParam, const NtPidlEntry * first, const NtPidlEntry * second)
|
||||||
{
|
{
|
||||||
switch (uMsg)
|
HRESULT hr;
|
||||||
|
|
||||||
|
LPARAM sortMode = lParam & 0xFFFF0000;
|
||||||
|
LPARAM column = lParam & 0x0000FFFF;
|
||||||
|
|
||||||
|
if (sortMode == SHCIDS_ALLFIELDS)
|
||||||
{
|
{
|
||||||
case SFVM_DEFVIEWMODE:
|
if (column != 0)
|
||||||
{
|
return E_INVALIDARG;
|
||||||
FOLDERVIEWMODE* pViewMode = (FOLDERVIEWMODE*) lParam;
|
|
||||||
*pViewMode = FVM_DETAILS;
|
int minsize = min(first->cb, second->cb);
|
||||||
return S_OK;
|
hr = MAKE_COMPARE_HRESULT(memcmp(second, first, minsize));
|
||||||
}
|
if (hr != S_EQUAL)
|
||||||
case SFVM_COLUMNCLICK:
|
return hr;
|
||||||
return S_FALSE;
|
|
||||||
case SFVM_BACKGROUNDENUM:
|
return MAKE_COMPARE_HRESULT(second->cb - first->cb);
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CNtObjectFolder::DefCtxMenuCallback(IShellFolder * /*psf*/, HWND /*hwnd*/, IDataObject * /*pdtobj*/, UINT uMsg, WPARAM /*wParam*/, LPARAM /*lParam*/)
|
switch (column)
|
||||||
{
|
{
|
||||||
switch (uMsg)
|
case NTOBJECT_COLUMN_NAME:
|
||||||
|
return CompareName(lParam, first, second);
|
||||||
|
|
||||||
|
case NTOBJECT_COLUMN_TYPE:
|
||||||
|
return MAKE_COMPARE_HRESULT(second->objectType - first->objectType);
|
||||||
|
|
||||||
|
case NTOBJECT_COLUMN_LINKTARGET:
|
||||||
|
// Can't sort by link target yet
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
DbgPrint("Unsupported sorting mode.\n");
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG CNtObjectFolder::ConvertAttributes(const NtPidlEntry * entry, PULONG inMask)
|
||||||
{
|
{
|
||||||
case DFM_MERGECONTEXTMENU:
|
ULONG mask = inMask ? *inMask : 0xFFFFFFFF;
|
||||||
|
ULONG flags = SFGAO_HASPROPSHEET | SFGAO_CANLINK;
|
||||||
|
|
||||||
|
if (entry->objectType == DIRECTORY_OBJECT)
|
||||||
|
flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
||||||
|
|
||||||
|
if (entry->objectType == SYMBOLICLINK_OBJECT)
|
||||||
|
flags |= SFGAO_LINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
||||||
|
|
||||||
|
if (entry->objectType == KEY_OBJECT)
|
||||||
|
flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
||||||
|
|
||||||
|
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) ||
|
||||||
|
(info->objectType == SYMBOLICLINK_OBJECT) ||
|
||||||
|
(info->objectType == KEY_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CNtObjectFolder::GetInfoFromPidl(LPCITEMIDLIST pcidl, const NtPidlEntry ** pentry)
|
||||||
|
{
|
||||||
|
NtPidlEntry * entry = (NtPidlEntry*) &(pcidl->mkid);
|
||||||
|
|
||||||
|
if (entry->cb < sizeof(NtPidlEntry))
|
||||||
|
{
|
||||||
|
DbgPrint("PCIDL too small %l (required %l)\n", entry->cb, sizeof(NtPidlEntry));
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->magic != NT_OBJECT_PIDL_MAGIC)
|
||||||
|
{
|
||||||
|
DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry->magic, NT_OBJECT_PIDL_MAGIC);
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pentry = entry;
|
||||||
return S_OK;
|
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;
|
|
||||||
}
|
}
|
|
@ -9,94 +9,74 @@
|
||||||
|
|
||||||
extern const GUID CLSID_NtObjectFolder;
|
extern const GUID CLSID_NtObjectFolder;
|
||||||
|
|
||||||
|
class CNtObjectFolderExtractIcon :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
public IExtractIconW
|
||||||
|
{
|
||||||
|
PCWSTR m_NtPath;
|
||||||
|
PCIDLIST_ABSOLUTE m_pcidlFolder;
|
||||||
|
PCITEMID_CHILD m_pcidlChild;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CNtObjectFolderExtractIcon();
|
||||||
|
|
||||||
|
virtual ~CNtObjectFolderExtractIcon();
|
||||||
|
|
||||||
|
HRESULT Initialize(LPCWSTR ntPath, PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl);
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetIconLocation(
|
||||||
|
UINT uFlags,
|
||||||
|
LPWSTR szIconFile,
|
||||||
|
UINT cchMax,
|
||||||
|
INT *piIndex,
|
||||||
|
UINT *pwFlags);
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Extract(
|
||||||
|
LPCWSTR pszFile,
|
||||||
|
UINT nIconIndex,
|
||||||
|
HICON *phiconLarge,
|
||||||
|
HICON *phiconSmall,
|
||||||
|
UINT nIconSize);
|
||||||
|
|
||||||
|
DECLARE_NOT_AGGREGATABLE(CNtObjectFolderExtractIcon)
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CNtObjectFolderExtractIcon)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class CNtObjectFolder :
|
class CNtObjectFolder :
|
||||||
public CComCoClass<CNtObjectFolder, &CLSID_NtObjectFolder>,
|
public CComCoClass<CNtObjectFolder, &CLSID_NtObjectFolder>,
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CCommonFolder<CNtObjectFolder, NtPidlEntry, CNtObjectFolderExtractIcon>
|
||||||
public IShellFolder2,
|
|
||||||
public IPersistFolder2,
|
|
||||||
public IShellFolderViewCB
|
|
||||||
{
|
{
|
||||||
WCHAR m_NtPath[MAX_PATH];
|
|
||||||
|
|
||||||
LPITEMIDLIST m_shellPidl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CNtObjectFolder();
|
CNtObjectFolder();
|
||||||
virtual ~CNtObjectFolder();
|
virtual ~CNtObjectFolder();
|
||||||
|
|
||||||
// IShellFolder
|
// IShellFolder
|
||||||
virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(
|
|
||||||
HWND hwndOwner,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
LPOLESTR lpszDisplayName,
|
|
||||||
ULONG *pchEaten,
|
|
||||||
LPITEMIDLIST *ppidl,
|
|
||||||
ULONG *pdwAttributes);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
|
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
|
||||||
HWND hwndOwner,
|
HWND hwndOwner,
|
||||||
SHCONTF grfFlags,
|
SHCONTF grfFlags,
|
||||||
IEnumIDList **ppenumIDList);
|
IEnumIDList **ppenumIDList);
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE BindToObject(
|
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
||||||
LPCITEMIDLIST pidl,
|
PWSTR path,
|
||||||
|
const NtPidlEntry * info,
|
||||||
|
LPITEMIDLIST first,
|
||||||
|
LPCITEMIDLIST rest,
|
||||||
|
LPITEMIDLIST fullPidl,
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
REFIID riid,
|
IShellFolder** ppsfChild);
|
||||||
void **ppvOut);
|
virtual HRESULT STDMETHODCALLTYPE RedirectToSymLink(
|
||||||
|
const NtPidlEntry * info,
|
||||||
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
|
LPITEMIDLIST first,
|
||||||
LPCITEMIDLIST pidl,
|
LPCITEMIDLIST rest,
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
REFIID riid,
|
IShellFolder ** ppsfChild);
|
||||||
void **ppvObj);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE CompareIDs(
|
|
||||||
LPARAM lParam,
|
|
||||||
LPCITEMIDLIST pidl1,
|
|
||||||
LPCITEMIDLIST pidl2);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE CreateViewObject(
|
|
||||||
HWND hwndOwner,
|
|
||||||
REFIID riid,
|
|
||||||
void **ppvOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetAttributesOf(
|
|
||||||
UINT cidl,
|
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
|
||||||
SFGAOF *rgfInOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetUIObjectOf(
|
|
||||||
HWND hwndOwner,
|
|
||||||
UINT cidl,
|
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
|
||||||
REFIID riid,
|
|
||||||
UINT *prgfInOut,
|
|
||||||
void **ppvOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayNameOf(
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
SHGDNF uFlags,
|
|
||||||
STRRET *lpName);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE SetNameOf(
|
|
||||||
HWND hwnd,
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
LPCOLESTR lpszName,
|
|
||||||
SHGDNF uFlags,
|
|
||||||
LPITEMIDLIST *ppidlOut);
|
|
||||||
|
|
||||||
// IShellFolder2
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultSearchGUID(
|
|
||||||
GUID *lpguid);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE EnumSearches(
|
|
||||||
IEnumExtraSearch **ppenum);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumn(
|
|
||||||
DWORD dwReserved,
|
|
||||||
ULONG *pSort,
|
|
||||||
ULONG *pDisplay);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
|
@ -116,34 +96,22 @@ public:
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
SHCOLUMNID *pscid);
|
SHCOLUMNID *pscid);
|
||||||
|
|
||||||
// IPersist
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *lpClassId);
|
|
||||||
|
|
||||||
// IPersistFolder
|
// IPersistFolder
|
||||||
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl);
|
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl);
|
||||||
|
|
||||||
// IPersistFolder2
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetCurFolder(LPITEMIDLIST * pidl);
|
|
||||||
|
|
||||||
// IShellFolderViewCB
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath);
|
HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath);
|
||||||
|
|
||||||
static HRESULT CALLBACK DefCtxMenuCallback(IShellFolder *, HWND, IDataObject *, UINT, WPARAM, LPARAM);
|
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);
|
||||||
|
|
||||||
DECLARE_REGISTRY_RESOURCEID(IDR_NTOBJECTFOLDER)
|
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const NtPidlEntry ** pentry);
|
||||||
DECLARE_NOT_AGGREGATABLE(CNtObjectFolder)
|
|
||||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
||||||
|
|
||||||
BEGIN_COM_MAP(CNtObjectFolder)
|
HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents);
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
|
||||||
END_COM_MAP()
|
|
||||||
|
|
||||||
|
HRESULT FormatContentsForDisplay(const NtPidlEntry * info, HKEY rootKey, LPCWSTR ntPath, PCWSTR * strContents);
|
||||||
};
|
};
|
|
@ -46,5 +46,23 @@ extern HINSTANCE g_hInstance;
|
||||||
DEFINE_GUID(CLSID_NtObjectFolder,
|
DEFINE_GUID(CLSID_NtObjectFolder,
|
||||||
0x845b0fb2, 0x66e0, 0x416b, 0x8f, 0x91, 0x31, 0x4e, 0x23, 0xf7, 0xc1, 0x2d);
|
0x845b0fb2, 0x66e0, 0x416b, 0x8f, 0x91, 0x31, 0x4e, 0x23, 0xf7, 0xc1, 0x2d);
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
|
||||||
|
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
|
||||||
|
|
||||||
|
#include <rtlfuncs.h>
|
||||||
|
#include <ntquery.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "ntobjenum.h"
|
||||||
|
|
||||||
|
#include "foldercommon.h"
|
||||||
#include "ntobjfolder.h"
|
#include "ntobjfolder.h"
|
||||||
#include "regfolder.h"
|
#include "regfolder.h"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,17 +9,48 @@
|
||||||
|
|
||||||
extern const GUID CLSID_RegistryFolder;
|
extern const GUID CLSID_RegistryFolder;
|
||||||
|
|
||||||
|
class CRegistryFolderExtractIcon :
|
||||||
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
|
public IExtractIconW
|
||||||
|
{
|
||||||
|
PCIDLIST_ABSOLUTE m_pcidlFolder;
|
||||||
|
PCITEMID_CHILD m_pcidlChild;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CRegistryFolderExtractIcon();
|
||||||
|
|
||||||
|
virtual ~CRegistryFolderExtractIcon();
|
||||||
|
|
||||||
|
HRESULT Initialize(LPCWSTR ntPath, PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl);
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetIconLocation(
|
||||||
|
UINT uFlags,
|
||||||
|
LPWSTR szIconFile,
|
||||||
|
UINT cchMax,
|
||||||
|
INT *piIndex,
|
||||||
|
UINT *pwFlags);
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Extract(
|
||||||
|
LPCWSTR pszFile,
|
||||||
|
UINT nIconIndex,
|
||||||
|
HICON *phiconLarge,
|
||||||
|
HICON *phiconSmall,
|
||||||
|
UINT nIconSize);
|
||||||
|
|
||||||
|
DECLARE_NOT_AGGREGATABLE(CRegistryFolderExtractIcon)
|
||||||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
|
||||||
|
BEGIN_COM_MAP(CRegistryFolderExtractIcon)
|
||||||
|
COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW)
|
||||||
|
END_COM_MAP()
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class CRegistryFolder :
|
class CRegistryFolder :
|
||||||
public CComCoClass<CRegistryFolder, &CLSID_RegistryFolder>,
|
public CComCoClass<CRegistryFolder, &CLSID_RegistryFolder>,
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CCommonFolder<CRegistryFolder, RegPidlEntry, CRegistryFolderExtractIcon>
|
||||||
public IShellFolder2,
|
|
||||||
public IPersistFolder2,
|
|
||||||
public IShellFolderViewCB
|
|
||||||
{
|
{
|
||||||
HKEY m_hRoot;
|
HKEY m_hRoot;
|
||||||
WCHAR m_NtPath[MAX_PATH];
|
|
||||||
|
|
||||||
LPITEMIDLIST m_shellPidl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -27,77 +58,19 @@ public:
|
||||||
virtual ~CRegistryFolder();
|
virtual ~CRegistryFolder();
|
||||||
|
|
||||||
// IShellFolder
|
// IShellFolder
|
||||||
virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(
|
|
||||||
HWND hwndOwner,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
LPOLESTR lpszDisplayName,
|
|
||||||
ULONG *pchEaten,
|
|
||||||
LPITEMIDLIST *ppidl,
|
|
||||||
ULONG *pdwAttributes);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
|
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
|
||||||
HWND hwndOwner,
|
HWND hwndOwner,
|
||||||
SHCONTF grfFlags,
|
SHCONTF grfFlags,
|
||||||
IEnumIDList **ppenumIDList);
|
IEnumIDList **ppenumIDList);
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE BindToObject(
|
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(
|
||||||
LPCITEMIDLIST pidl,
|
PWSTR path,
|
||||||
|
const RegPidlEntry * info,
|
||||||
|
LPITEMIDLIST first,
|
||||||
|
LPCITEMIDLIST rest,
|
||||||
|
LPITEMIDLIST fullPidl,
|
||||||
LPBC pbcReserved,
|
LPBC pbcReserved,
|
||||||
REFIID riid,
|
IShellFolder** ppsfChild);
|
||||||
void **ppvOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
LPBC pbcReserved,
|
|
||||||
REFIID riid,
|
|
||||||
void **ppvObj);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE CompareIDs(
|
|
||||||
LPARAM lParam,
|
|
||||||
LPCITEMIDLIST pidl1,
|
|
||||||
LPCITEMIDLIST pidl2);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE CreateViewObject(
|
|
||||||
HWND hwndOwner,
|
|
||||||
REFIID riid,
|
|
||||||
void **ppvOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetAttributesOf(
|
|
||||||
UINT cidl,
|
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
|
||||||
SFGAOF *rgfInOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetUIObjectOf(
|
|
||||||
HWND hwndOwner,
|
|
||||||
UINT cidl,
|
|
||||||
PCUITEMID_CHILD_ARRAY apidl,
|
|
||||||
REFIID riid,
|
|
||||||
UINT *prgfInOut,
|
|
||||||
void **ppvOut);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayNameOf(
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
SHGDNF uFlags,
|
|
||||||
STRRET *lpName);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE SetNameOf(
|
|
||||||
HWND hwnd,
|
|
||||||
LPCITEMIDLIST pidl,
|
|
||||||
LPCOLESTR lpszName,
|
|
||||||
SHGDNF uFlags,
|
|
||||||
LPITEMIDLIST *ppidlOut);
|
|
||||||
|
|
||||||
// IShellFolder2
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultSearchGUID(
|
|
||||||
GUID *lpguid);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE EnumSearches(
|
|
||||||
IEnumExtraSearch **ppenum);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumn(
|
|
||||||
DWORD dwReserved,
|
|
||||||
ULONG *pSort,
|
|
||||||
ULONG *pDisplay);
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
|
@ -117,34 +90,21 @@ public:
|
||||||
UINT iColumn,
|
UINT iColumn,
|
||||||
SHCOLUMNID *pscid);
|
SHCOLUMNID *pscid);
|
||||||
|
|
||||||
// IPersist
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *lpClassId);
|
|
||||||
|
|
||||||
// IPersistFolder
|
// IPersistFolder
|
||||||
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl);
|
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl);
|
||||||
|
|
||||||
// IPersistFolder2
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE GetCurFolder(LPITEMIDLIST * pidl);
|
|
||||||
|
|
||||||
// IShellFolderViewCB
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath, HKEY hRoot);
|
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath, HKEY hRoot);
|
||||||
|
|
||||||
static HRESULT CALLBACK DefCtxMenuCallback(IShellFolder *, HWND, IDataObject *, UINT, WPARAM, LPARAM);
|
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);
|
||||||
|
|
||||||
DECLARE_REGISTRY_RESOURCEID(IDR_REGISTRYFOLDER)
|
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const RegPidlEntry ** pentry);
|
||||||
DECLARE_NOT_AGGREGATABLE(CRegistryFolder)
|
|
||||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
|
||||||
|
|
||||||
BEGIN_COM_MAP(CRegistryFolder)
|
HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents);
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
|
||||||
END_COM_MAP()
|
|
||||||
|
|
||||||
|
HRESULT FormatContentsForDisplay(const RegPidlEntry * info, HKEY rootKey, LPCWSTR ntPath, PCWSTR * strContents);
|
||||||
};
|
};
|
Loading…
Add table
Add a link
Reference in a new issue