mirror of
https://github.com/reactos/reactos.git
synced 2025-04-05 05:01:03 +00:00
[SHELL32] Don't display non-enumerable nor non-folder items in Explorer tree (#7189)
This partially implements RegFolder required items as described by Geoff Chappell. CORE-19176 CORE-14061
This commit is contained in:
parent
a75ed2acd9
commit
6ae11ba09d
18 changed files with 606 additions and 309 deletions
|
@ -231,6 +231,7 @@ private:
|
|||
CComPtr<IShellFolderViewCB> m_pShellFolderViewCB;
|
||||
CComPtr<IShellBrowser> m_pShellBrowser;
|
||||
CComPtr<ICommDlgBrowser> m_pCommDlgBrowser;
|
||||
CComPtr<IFolderFilter> m_pFolderFilter;
|
||||
CComPtr<IShellFolderViewDual> m_pShellFolderViewDual;
|
||||
CListView m_ListView;
|
||||
HWND m_hWndParent;
|
||||
|
@ -636,14 +637,16 @@ HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder)
|
|||
HRESULT CDefView::IncludeObject(PCUITEMID_CHILD pidl)
|
||||
{
|
||||
HRESULT ret = S_OK;
|
||||
|
||||
if (m_pCommDlgBrowser && !(GetCommDlgViewFlags() & CDB2GVF_NOINCLUDEITEM))
|
||||
{
|
||||
TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
|
||||
ret = m_pCommDlgBrowser->IncludeObject(this, pidl);
|
||||
TRACE("-- returns 0x%08x\n", ret);
|
||||
}
|
||||
|
||||
else if (m_pFolderFilter)
|
||||
{
|
||||
ret = m_pFolderFilter->ShouldShow(m_pSFParent, m_pidlParent, pidl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1484,7 +1487,7 @@ HRESULT CDefView::FillList(BOOL IsRefreshCommand)
|
|||
DWORD dwFetched;
|
||||
HRESULT hRes;
|
||||
HDPA hdpa;
|
||||
DWORD dFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS;
|
||||
DWORD dFlags = SHCONTF_NONFOLDERS | ((m_FolderSettings.fFlags & FWF_NOSUBFOLDERS) ? 0 : SHCONTF_FOLDERS);
|
||||
|
||||
TRACE("%p\n", this);
|
||||
|
||||
|
@ -4006,6 +4009,9 @@ HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, ISh
|
|||
*old_cb = m_pShellFolderViewCB.Detach();
|
||||
|
||||
m_pShellFolderViewCB = new_cb;
|
||||
m_pFolderFilter = NULL;
|
||||
if (new_cb)
|
||||
new_cb->QueryInterface(IID_PPV_ARG(IFolderFilter, &m_pFolderFilter));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,33 +96,6 @@ BOOL CEnumIDListBase::DeleteList()
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* HasItemWithCLSID()
|
||||
*/
|
||||
BOOL CEnumIDListBase::HasItemWithCLSID(LPITEMIDLIST pidl)
|
||||
{
|
||||
ENUMLIST *pCur;
|
||||
IID *ptr = _ILGetGUIDPointer(pidl);
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
REFIID refid = *ptr;
|
||||
pCur = mpFirst;
|
||||
|
||||
while(pCur)
|
||||
{
|
||||
LPGUID curid = _ILGetGUIDPointer(pCur->pidl);
|
||||
if (curid && IsEqualGUID(*curid, refid))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
pCur = pCur->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT CEnumIDListBase::AppendItemsFromEnumerator(IEnumIDList* pEnum)
|
||||
{
|
||||
LPITEMIDLIST pidl;
|
||||
|
|
|
@ -27,7 +27,7 @@ class CEnumIDListBase :
|
|||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumIDList
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
ENUMLIST *mpFirst;
|
||||
ENUMLIST *mpLast;
|
||||
ENUMLIST *mpCurrent;
|
||||
|
@ -37,7 +37,19 @@ public:
|
|||
BOOL AddToEnumList(LPITEMIDLIST pidl);
|
||||
BOOL DeleteList();
|
||||
BOOL HasItemWithCLSID(LPITEMIDLIST pidl);
|
||||
HRESULT AppendItemsFromEnumerator(IEnumIDList* pEnum);
|
||||
HRESULT AppendItemsFromEnumerator(IEnumIDList* pEnum);
|
||||
|
||||
template <class T> BOOL HasItemWithCLSIDImpl(LPCITEMIDLIST pidl)
|
||||
{
|
||||
const CLSID * const pClsid = static_cast<T*>(this)->GetPidlClsid((PCUITEMID_CHILD)pidl);
|
||||
for (ENUMLIST *pCur = mpFirst; pClsid && pCur; pCur = pCur->pNext)
|
||||
{
|
||||
const CLSID * const pEnumClsid = static_cast<T*>(this)->GetPidlClsid((PCUITEMID_CHILD)pCur->pidl);
|
||||
if (pEnumClsid && IsEqualCLSID(*pClsid, *pEnumClsid))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// *** IEnumIDList methods ***
|
||||
STDMETHOD(Next)(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) override;
|
||||
|
|
|
@ -23,6 +23,15 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
static const REGFOLDERINFO g_RegFolderInfo =
|
||||
{
|
||||
PT_CONTROLS_NEWREGITEM,
|
||||
0, NULL,
|
||||
CLSID_ControlPanel,
|
||||
L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}",
|
||||
L"ControlPanel",
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* control panel implementation in shell namespace
|
||||
*/
|
||||
|
@ -627,11 +636,10 @@ HRESULT WINAPI CControlPanelFolder::Initialize(PCIDLIST_ABSOLUTE pidl)
|
|||
pidlRoot = ILClone(pidl);
|
||||
|
||||
/* Create the inner reg folder */
|
||||
REGFOLDERINITDATA RegInit = { static_cast<IShellFolder*>(this), &g_RegFolderInfo };
|
||||
HRESULT hr;
|
||||
hr = CRegFolder_CreateInstance(&CLSID_ControlPanel,
|
||||
hr = CRegFolder_CreateInstance(&RegInit,
|
||||
pidlRoot,
|
||||
L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}",
|
||||
L"ControlPanel",
|
||||
IID_PPV_ARG(IShellFolder2, &m_regFolder));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
|
|
@ -25,11 +25,35 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
extern BOOL SHELL32_IsShellFolderNamespaceItemHidden(LPCWSTR SubKey, REFCLSID Clsid);
|
||||
|
||||
static const REQUIREDREGITEM g_RequiredItems[] =
|
||||
{
|
||||
{ CLSID_MyComputer, "sysdm.cpl", 0x50 },
|
||||
{ CLSID_NetworkPlaces, "ncpa.cpl", 0x58 },
|
||||
{ CLSID_Internet, "inetcpl.cpl", 0x68 },
|
||||
};
|
||||
static const REGFOLDERINFO g_RegFolderInfo =
|
||||
{
|
||||
PT_DESKTOP_REGITEM,
|
||||
_countof(g_RequiredItems), g_RequiredItems,
|
||||
CLSID_ShellDesktop,
|
||||
L"",
|
||||
L"Desktop",
|
||||
};
|
||||
|
||||
static BOOL IsSelf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
||||
{
|
||||
return cidl == 0 || (cidl == 1 && apidl && _ILIsEmpty(apidl[0]));
|
||||
}
|
||||
|
||||
static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
|
||||
{
|
||||
if (pidl && pidl->mkid.cb == 2 + 2 + sizeof(CLSID) && pidl->mkid.abID[0] == PT_GUID)
|
||||
return (const CLSID*)(&pidl->mkid.abID[2]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CDesktopFolder::ShellUrlParseDisplayName(
|
||||
HWND hwndOwner,
|
||||
|
@ -153,49 +177,13 @@ The CDesktopFolderEnum class should create two enumerators, one for each of the
|
|||
system folders, and enumerate the contents of each folder. Since the CRegFolder
|
||||
implementation of IShellFolder::EnumObjects enumerates the virtual items, the
|
||||
CDesktopFolderEnum is only responsible for returning the physical items.
|
||||
CDesktopFolderEnum is incorrect where it filters My Computer from the enumeration
|
||||
if the new start menu is used. The CDesktopViewCallback is responsible for filtering
|
||||
it from the view by handling the IncludeObject query to return S_FALSE. The enumerator
|
||||
always shows My Computer.
|
||||
CDesktopFolderViewCB is responsible for filtering hidden regitems.
|
||||
The enumerator always shows My Computer.
|
||||
*/
|
||||
|
||||
/* Undocumented functions from shdocvw */
|
||||
extern "C" HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl);
|
||||
|
||||
static const WCHAR ClassicStartMenuW[] = L"SOFTWARE\\Microsoft\\Windows\\"
|
||||
L"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
|
||||
|
||||
static INT
|
||||
IsNamespaceExtensionHidden(const WCHAR *iid)
|
||||
{
|
||||
DWORD Result, dwResult;
|
||||
dwResult = sizeof(DWORD);
|
||||
|
||||
if (RegGetValueW(HKEY_CURRENT_USER, /* FIXME use NewStartPanel when activated */
|
||||
ClassicStartMenuW,
|
||||
iid,
|
||||
RRF_RT_DWORD,
|
||||
NULL,
|
||||
&Result,
|
||||
&dwResult) != ERROR_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static INT IsNamespaceExtensionHidden(LPCITEMIDLIST pidl)
|
||||
{
|
||||
GUID const *clsid = _ILGetGUIDPointer (pidl);
|
||||
if (!clsid)
|
||||
return -1;
|
||||
|
||||
WCHAR pwszGuid[CHARS_IN_GUID];
|
||||
SHELL32_GUIDToStringW(*clsid, pwszGuid);
|
||||
return IsNamespaceExtensionHidden(pwszGuid);
|
||||
}
|
||||
|
||||
class CDesktopFolderEnum :
|
||||
public CEnumIDListBase
|
||||
{
|
||||
|
@ -204,85 +192,20 @@ class CDesktopFolderEnum :
|
|||
// CComPtr fCommonDesktopEnumerator;
|
||||
public:
|
||||
|
||||
void AddItemsFromClassicStartMenuKey(HKEY hKeyRoot)
|
||||
HRESULT WINAPI Initialize(IShellFolder *pRegFolder, SHCONTF dwFlags, IEnumIDList *pRegEnumerator,
|
||||
IEnumIDList *pDesktopEnumerator, IEnumIDList *pCommonDesktopEnumerator)
|
||||
{
|
||||
DWORD dwResult;
|
||||
HKEY hkey;
|
||||
DWORD j = 0, dwVal, Val, dwType, dwIID;
|
||||
LONG r;
|
||||
WCHAR iid[50];
|
||||
LPITEMIDLIST pidl;
|
||||
|
||||
dwResult = RegOpenKeyExW(hKeyRoot, ClassicStartMenuW, 0, KEY_READ, &hkey);
|
||||
if (dwResult != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
while(1)
|
||||
{
|
||||
dwVal = sizeof(Val);
|
||||
dwIID = sizeof(iid) / sizeof(WCHAR);
|
||||
|
||||
r = RegEnumValueW(hkey, j++, iid, &dwIID, NULL, &dwType, (LPBYTE)&Val, &dwVal);
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
if (Val == 0 && dwType == REG_DWORD)
|
||||
{
|
||||
pidl = _ILCreateGuidFromStrW(iid);
|
||||
if (pidl != NULL)
|
||||
{
|
||||
if (!HasItemWithCLSID(pidl))
|
||||
AddToEnumList(pidl);
|
||||
else
|
||||
SHFree(pidl);
|
||||
}
|
||||
}
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
HRESULT WINAPI Initialize(DWORD dwFlags,IEnumIDList * pRegEnumerator, IEnumIDList *pDesktopEnumerator, IEnumIDList *pCommonDesktopEnumerator)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPITEMIDLIST pidl;
|
||||
|
||||
static const WCHAR MyDocumentsClassString[] = L"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
|
||||
static const WCHAR InternetClassString[] = L"{871C5380-42A0-1069-A2EA-08002B30309D}";
|
||||
|
||||
TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags);
|
||||
|
||||
/* enumerate the root folders */
|
||||
if (dwFlags & SHCONTF_FOLDERS)
|
||||
{
|
||||
AddToEnumList(_ILCreateMyComputer());
|
||||
if (IsNamespaceExtensionHidden(MyDocumentsClassString) < 1)
|
||||
AddToEnumList(_ILCreateMyDocuments());
|
||||
if (IsNamespaceExtensionHidden(InternetClassString) < 1)
|
||||
AddToEnumList(_ILCreateIExplore());
|
||||
|
||||
DWORD dwFetched;
|
||||
while((S_OK == pRegEnumerator->Next(1, &pidl, &dwFetched)) && dwFetched)
|
||||
{
|
||||
if (IsNamespaceExtensionHidden(pidl) < 1)
|
||||
{
|
||||
if (!HasItemWithCLSID(pidl))
|
||||
AddToEnumList(pidl);
|
||||
else
|
||||
SHFree(pidl);
|
||||
}
|
||||
}
|
||||
AddItemsFromClassicStartMenuKey(HKEY_LOCAL_MACHINE);
|
||||
AddItemsFromClassicStartMenuKey(HKEY_CURRENT_USER);
|
||||
}
|
||||
AppendItemsFromEnumerator(pRegEnumerator);
|
||||
|
||||
/* Enumerate the items in the two fs folders */
|
||||
AppendItemsFromEnumerator(pDesktopEnumerator);
|
||||
AppendItemsFromEnumerator(pCommonDesktopEnumerator);
|
||||
|
||||
return ret ? S_OK : E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_COM_MAP(CDesktopFolderEnum)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
|
@ -337,10 +260,9 @@ HRESULT WINAPI CDesktopFolder::FinalConstruct()
|
|||
return hr;
|
||||
|
||||
/* Create the inner reg folder */
|
||||
hr = CRegFolder_CreateInstance(&CLSID_ShellDesktop,
|
||||
REGFOLDERINITDATA RegInit = { static_cast<IShellFolder*>(this), &g_RegFolderInfo };
|
||||
hr = CRegFolder_CreateInstance(&RegInit,
|
||||
pidlRoot,
|
||||
L"",
|
||||
L"Desktop",
|
||||
IID_PPV_ARG(IShellFolder2, &m_regFolder));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
@ -621,7 +543,8 @@ HRESULT WINAPI CDesktopFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUM
|
|||
if (FAILED(hr))
|
||||
ERR("EnumObjects for shared desktop fs folder failed\n");
|
||||
|
||||
return ShellObjectCreatorInit<CDesktopFolderEnum>(dwFlags,pRegEnumerator, pDesktopEnumerator, pCommonDesktopEnumerator, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
|
||||
return ShellObjectCreatorInit<CDesktopFolderEnum>(m_regFolder, dwFlags, pRegEnumerator, pDesktopEnumerator,
|
||||
pCommonDesktopEnumerator, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -726,8 +649,14 @@ HRESULT WINAPI CDesktopFolder::CreateViewObject(
|
|||
}
|
||||
else if (IsEqualIID (riid, IID_IShellView))
|
||||
{
|
||||
SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this};
|
||||
hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
|
||||
CComPtr<CDesktopFolderViewCB> sfviewcb;
|
||||
if (SUCCEEDED(hr = ShellObjectCreator(sfviewcb)))
|
||||
{
|
||||
SFV_CREATE create = { sizeof(create), this, NULL, sfviewcb };
|
||||
hr = SHCreateShellFolderView(&create, (IShellView**)ppvOut);
|
||||
if (SUCCEEDED(hr))
|
||||
sfviewcb->Initialize((IShellView*)*ppvOut);
|
||||
}
|
||||
}
|
||||
TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
|
||||
return hr;
|
||||
|
@ -1102,6 +1031,48 @@ HRESULT WINAPI CDesktopFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IData
|
|||
return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* CDesktopFolderViewCB
|
||||
*/
|
||||
|
||||
bool CDesktopFolderViewCB::IsProgmanHostedBrowser(IShellView *psv)
|
||||
{
|
||||
FOLDERSETTINGS settings;
|
||||
return SUCCEEDED(psv->GetCurrentInfo(&settings)) && (settings.fFlags & FWF_DESKTOP);
|
||||
}
|
||||
|
||||
bool CDesktopFolderViewCB::IsProgmanHostedBrowser()
|
||||
{
|
||||
enum { Uninitialized = 0, NotHosted, IsHosted };
|
||||
C_ASSERT(Uninitialized == 0);
|
||||
if (m_IsProgmanHosted == Uninitialized)
|
||||
m_IsProgmanHosted = m_pShellView && IsProgmanHostedBrowser(m_pShellView) ? IsHosted : NotHosted;
|
||||
return m_IsProgmanHosted == IsHosted;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDesktopFolderViewCB::ShouldShow(IShellFolder *psf, PCIDLIST_ABSOLUTE pidlFolder, PCUITEMID_CHILD pidlItem)
|
||||
{
|
||||
const CLSID* pClsid;
|
||||
if (IsProgmanHostedBrowser() && (pClsid = IsRegItem(pidlItem)) != NULL)
|
||||
{
|
||||
const BOOL NewStart = SHELL_GetSetting(SSF_STARTPANELON, fStartPanelOn);
|
||||
LPCWSTR SubKey = NewStart ? L"HideDesktopIcons\\NewStartPanel" : L"HideDesktopIcons\\ClassicStartMenu";
|
||||
return SHELL32_IsShellFolderNamespaceItemHidden(SubKey, *pClsid) ? S_FALSE : S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDesktopFolderViewCB::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case SFVM_VIEWRELEASE:
|
||||
m_pShellView = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHGetDesktopFolder [SHELL32.@]
|
||||
*/
|
||||
|
|
|
@ -145,4 +145,33 @@ class CDesktopFolder :
|
|||
END_COM_MAP()
|
||||
};
|
||||
|
||||
class CDesktopFolderViewCB :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolderViewCB,
|
||||
public IFolderFilter
|
||||
{
|
||||
IShellView *m_pShellView; // Not ref-counted!
|
||||
UINT8 m_IsProgmanHosted;
|
||||
|
||||
public:
|
||||
CDesktopFolderViewCB() : m_IsProgmanHosted(0) {}
|
||||
void Initialize(IShellView *psv) { m_pShellView = psv; }
|
||||
static bool IsProgmanHostedBrowser(IShellView *psv);
|
||||
bool IsProgmanHostedBrowser();
|
||||
|
||||
// IShellFolderViewCB
|
||||
STDMETHOD(MessageSFVCB)(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
|
||||
|
||||
// IFolderFilter
|
||||
STDMETHOD(ShouldShow)(IShellFolder *psf, PCIDLIST_ABSOLUTE pidlFolder, PCUITEMID_CHILD pidlItem) override;
|
||||
STDMETHODIMP GetEnumFlags(IShellFolder*, PCIDLIST_ABSOLUTE, HWND*, DWORD*) override { return E_NOTIMPL; }
|
||||
|
||||
DECLARE_NO_REGISTRY()
|
||||
DECLARE_NOT_AGGREGATABLE(CDesktopFolderViewCB)
|
||||
BEGIN_COM_MAP(CDesktopFolderViewCB)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IFolderFilter, IFolderFilter)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
#endif /* _CDESKTOPFOLDER_H_ */
|
||||
|
|
|
@ -55,6 +55,29 @@ static int iDriveTypeIds[7] = { IDS_DRIVE_FIXED, /* DRIVE_UNKNOWN */
|
|||
IDS_DRIVE_FIXED /* DRIVE_RAMDISK*/
|
||||
};
|
||||
|
||||
static const REQUIREDREGITEM g_RequiredItems[] =
|
||||
{
|
||||
{ CLSID_ControlPanel, 0, 0x50 },
|
||||
};
|
||||
static const REGFOLDERINFO g_RegFolderInfo =
|
||||
{
|
||||
PT_COMPUTER_REGITEM,
|
||||
_countof(g_RequiredItems), g_RequiredItems,
|
||||
CLSID_MyComputer,
|
||||
L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
|
||||
L"MyComputer",
|
||||
};
|
||||
|
||||
static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
|
||||
{
|
||||
if (pidl && pidl->mkid.cb == 2 + 2 + sizeof(CLSID))
|
||||
{
|
||||
if (pidl->mkid.abID[0] == PT_SHELLEXT || pidl->mkid.abID[0] == PT_GUID) // FIXME: Remove PT_GUID when CRegFolder is fixed
|
||||
return (const CLSID*)(&pidl->mkid.abID[2]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL _ILGetDriveType(LPCITEMIDLIST pidl)
|
||||
{
|
||||
WCHAR szDrive[8];
|
||||
|
@ -66,6 +89,16 @@ BOOL _ILGetDriveType(LPCITEMIDLIST pidl)
|
|||
return ::GetDriveTypeW(szDrive);
|
||||
}
|
||||
|
||||
BOOL SHELL32_IsShellFolderNamespaceItemHidden(LPCWSTR SubKey, REFCLSID Clsid)
|
||||
{
|
||||
// If this function returns true, the item should be hidden in DefView but not in the Explorer folder tree.
|
||||
WCHAR path[MAX_PATH], name[CHARS_IN_GUID];
|
||||
wsprintfW(path, L"%s\\%s", REGSTR_PATH_EXPLORER, SubKey);
|
||||
SHELL32_GUIDToStringW(Clsid, name);
|
||||
DWORD data = 0, size = sizeof(data);
|
||||
return !RegGetValueW(HKEY_CURRENT_USER, path, name, RRF_RT_DWORD, NULL, &data, &size) && data;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* IShellFolder implementation
|
||||
*/
|
||||
|
@ -643,10 +676,9 @@ HRESULT WINAPI CDrivesFolder::FinalConstruct()
|
|||
if (pidlRoot == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT hr = CRegFolder_CreateInstance(&CLSID_MyComputer,
|
||||
REGFOLDERINITDATA RegInit = { static_cast<IShellFolder*>(this), &g_RegFolderInfo };
|
||||
HRESULT hr = CRegFolder_CreateInstance(&RegInit,
|
||||
pidlRoot,
|
||||
L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
|
||||
L"MyComputer",
|
||||
IID_PPV_ARG(IShellFolder2, &m_regFolder));
|
||||
|
||||
return hr;
|
||||
|
@ -901,7 +933,7 @@ HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVO
|
|||
}
|
||||
else if (IsEqualIID(riid, IID_IShellView))
|
||||
{
|
||||
SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this};
|
||||
SFV_CREATE sfvparams = { sizeof(SFV_CREATE), this, NULL, static_cast<IShellFolderViewCB*>(this) };
|
||||
hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut);
|
||||
}
|
||||
TRACE("-- (%p)->(interface=%p)\n", this, ppvOut);
|
||||
|
@ -937,11 +969,17 @@ HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY a
|
|||
*rgfInOut &= ~SFGAO_CANRENAME; // CD-ROM drive cannot rename
|
||||
}
|
||||
else if (_ILIsControlPanel(apidl[i]))
|
||||
{
|
||||
*rgfInOut &= dwControlPanelAttributes;
|
||||
}
|
||||
else if (_ILIsSpecialFolder(*apidl))
|
||||
{
|
||||
m_regFolder->GetAttributesOf(1, &apidl[i], rgfInOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Got unknown pidl type!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1302,6 +1340,16 @@ HRESULT WINAPI CDrivesFolder::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* CDrivesFolder::ShouldShow
|
||||
*/
|
||||
HRESULT WINAPI CDrivesFolder::ShouldShow(IShellFolder *psf, PCIDLIST_ABSOLUTE pidlFolder, PCUITEMID_CHILD pidlItem)
|
||||
{
|
||||
if (const CLSID* pClsid = IsRegItem(pidlItem))
|
||||
return SHELL32_IsShellFolderNamespaceItemHidden(L"HideMyComputerIcons", *pClsid) ? S_FALSE : S_OK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* IContextMenuCB interface */
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ class CDrivesFolder :
|
|||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolder2,
|
||||
public IPersistFolder2,
|
||||
public IContextMenuCB
|
||||
public IContextMenuCB,
|
||||
public IShellFolderViewCB, // Only exists so DefView can get IFolderFilter
|
||||
public IFolderFilter
|
||||
{
|
||||
private:
|
||||
/* both paths are parsible from the desktop */
|
||||
|
@ -73,6 +75,13 @@ class CDrivesFolder :
|
|||
// IContextMenuCB
|
||||
STDMETHOD(CallBack)(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
|
||||
|
||||
// IShellFolderViewCB
|
||||
STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) override { return E_NOTIMPL; }
|
||||
|
||||
// IFolderFilter
|
||||
STDMETHOD(ShouldShow)(IShellFolder *psf, PCIDLIST_ABSOLUTE pidlFolder, PCUITEMID_CHILD pidlItem) override;
|
||||
STDMETHODIMP GetEnumFlags(IShellFolder*, PCIDLIST_ABSOLUTE, HWND*, DWORD*) override { return E_NOTIMPL; }
|
||||
|
||||
DECLARE_REGISTRY_RESOURCEID(IDR_MYCOMPUTER)
|
||||
DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(CDrivesFolder)
|
||||
|
||||
|
@ -85,6 +94,8 @@ class CDrivesFolder :
|
|||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IContextMenuCB, IContextMenuCB)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IFolderFilter, IFolderFilter)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
|
|
|
@ -596,13 +596,33 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
|
|||
|
||||
BOOL bDirectory = (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
|
||||
if (SFGAO_VALIDATE & *pdwAttributes)
|
||||
{
|
||||
STRRET strret;
|
||||
LPWSTR path;
|
||||
if (SUCCEEDED(psf->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret)) &&
|
||||
SUCCEEDED(StrRetToStrW(&strret, pidl, &path)))
|
||||
{
|
||||
BOOL exists = PathFileExistsW(path);
|
||||
SHFree(path);
|
||||
if (!exists)
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bDirectory)
|
||||
{
|
||||
// https://git.reactos.org/?p=reactos.git;a=blob;f=dll/shellext/zipfldr/res/zipfldr.rgs;hb=032b5aacd233cd7b83ab6282aad638c161fdc400#l9
|
||||
WCHAR szFileName[MAX_PATH];
|
||||
LPWSTR pExtension;
|
||||
BOOL hasName = _ILSimpleGetTextW(pidl, szFileName, _countof(szFileName));
|
||||
|
||||
if (_ILSimpleGetTextW(pidl, szFileName, _countof(szFileName)) && (pExtension = PathFindExtensionW(szFileName)))
|
||||
// Vista+ feature: Hidden files with a leading tilde treated as super-hidden
|
||||
// See https://devblogs.microsoft.com/oldnewthing/20170526-00/?p=96235
|
||||
if (hasName && szFileName[0] == '~' && (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
|
||||
dwShellAttributes |= SFGAO_HIDDEN | SFGAO_SYSTEM;
|
||||
|
||||
if (hasName && (pExtension = PathFindExtensionW(szFileName)))
|
||||
{
|
||||
CLSID clsidFile;
|
||||
// FIXME: Cache this?
|
||||
|
@ -626,7 +646,7 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
|
|||
::RegCloseKey(hkey);
|
||||
|
||||
// This should be presented as directory!
|
||||
bDirectory = TRUE;
|
||||
bDirectory = (dwAttributes & SFGAO_FOLDER) != 0 || dwAttributes == 0;
|
||||
TRACE("Treating '%S' as directory!\n", szFileName);
|
||||
}
|
||||
}
|
||||
|
@ -650,10 +670,26 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
|
|||
}
|
||||
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
dwShellAttributes |= SFGAO_HIDDEN;
|
||||
dwShellAttributes |= SFGAO_HIDDEN | SFGAO_GHOSTED;
|
||||
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
dwShellAttributes |= SFGAO_READONLY;
|
||||
dwShellAttributes |= SFGAO_READONLY;
|
||||
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
|
||||
dwShellAttributes |= SFGAO_SYSTEM;
|
||||
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
||||
dwShellAttributes |= SFGAO_COMPRESSED;
|
||||
|
||||
if (dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED)
|
||||
dwShellAttributes |= SFGAO_ENCRYPTED;
|
||||
|
||||
if ((SFGAO_NONENUMERATED & *pdwAttributes) && (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
|
||||
{
|
||||
SHCONTF shcf = SHELL_GetDefaultFolderEnumSHCONTF();
|
||||
if ((!(shcf & SHCONTF_INCLUDEHIDDEN)) || ((dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) && !(shcf & SHCONTF_INCLUDESUPERHIDDEN)))
|
||||
dwShellAttributes |= SFGAO_NONENUMERATED;
|
||||
}
|
||||
|
||||
if (SFGAO_LINK & *pdwAttributes)
|
||||
{
|
||||
|
|
|
@ -16,117 +16,115 @@
|
|||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The required-regitem design is based on the research by Geoff Chappell
|
||||
* https://www.geoffchappell.com/studies/windows/shell/shell32/classes/regfolder.htm
|
||||
*/
|
||||
|
||||
#include <precomp.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL (shell);
|
||||
|
||||
HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf,
|
||||
HWND hwnd,
|
||||
IDataObject *pdtobj,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
#define DEFAULTSORTORDERINDEX 0x80 // The default for registry items according to Geoff Chappell
|
||||
|
||||
static HRESULT CRegItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl, IShellFolder *psf, IContextMenu **ppcm);
|
||||
|
||||
static inline UINT GetRegItemCLSIDOffset(PIDLTYPE type)
|
||||
{
|
||||
if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
|
||||
return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
|
||||
|
||||
PIDLIST_ABSOLUTE pidlFolder;
|
||||
PUITEMID_CHILD *apidl;
|
||||
UINT cidl;
|
||||
HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (_ILIsMyComputer(apidl[0]))
|
||||
{
|
||||
if (!SHELL_ExecuteControlPanelCPL(hwnd, L"sysdm.cpl"))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
else if (_ILIsDesktop(apidl[0]))
|
||||
{
|
||||
if (!SHELL_ExecuteControlPanelCPL(hwnd, L"desk.cpl"))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
else if (_ILIsNetHood(apidl[0]))
|
||||
{
|
||||
// FIXME path!
|
||||
if (32 >= (UINT_PTR)ShellExecuteW(NULL,
|
||||
L"open",
|
||||
L"explorer.exe",
|
||||
L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
|
||||
NULL,
|
||||
SW_SHOWDEFAULT))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
else if (_ILIsBitBucket(apidl[0]))
|
||||
{
|
||||
/* FIXME: detect the drive path of bitbucket if appropiate */
|
||||
if (!SH_ShowRecycleBinProperties(L'C'))
|
||||
hr = E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Tell the caller to run the default action */
|
||||
hr = S_FALSE;
|
||||
}
|
||||
|
||||
SHFree(pidlFolder);
|
||||
_ILFreeaPidl(apidl, cidl);
|
||||
|
||||
return hr;
|
||||
return type == PT_CONTROLS_NEWREGITEM ? 14 : 4;
|
||||
}
|
||||
|
||||
HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
|
||||
HWND hwnd,
|
||||
UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl,
|
||||
IShellFolder *psf,
|
||||
IContextMenu **ppcm)
|
||||
static LPITEMIDLIST CreateRegItem(PIDLTYPE type, REFCLSID clsid, BYTE order = 0)
|
||||
{
|
||||
HKEY hKeys[10];
|
||||
UINT cKeys = 0;
|
||||
|
||||
GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
|
||||
if (pGuid)
|
||||
#if 1 // FIXME: CControlPanelFolder is not ready for this yet
|
||||
if (type == PT_CONTROLS_NEWREGITEM)
|
||||
type = PT_CONTROLS_OLDREGITEM;
|
||||
#endif
|
||||
const UINT offset = GetRegItemCLSIDOffset(type);
|
||||
const UINT cb = offset + sizeof(CLSID), cbTotal = cb + sizeof(WORD);
|
||||
LPITEMIDLIST pidl = (LPITEMIDLIST)SHAlloc(cbTotal);
|
||||
if (pidl)
|
||||
{
|
||||
WCHAR key[60];
|
||||
wcscpy(key, L"CLSID\\");
|
||||
StringFromGUID2(*pGuid, &key[6], 39);
|
||||
AddClassKeyToArray(key, hKeys, &cKeys);
|
||||
ZeroMemory(pidl, cbTotal); // Note: This also initializes the terminator WORD
|
||||
pidl->mkid.cb = cb;
|
||||
pidl->mkid.abID[0] = type;
|
||||
pidl->mkid.abID[1] = order;
|
||||
*(CLSID*)(SIZE_T(pidl) + offset) = clsid;
|
||||
}
|
||||
return pidl;
|
||||
}
|
||||
|
||||
// FIXME: CRegFolder should be aggregated by its outer folder and should
|
||||
// provide the attributes for all required non-registry folders.
|
||||
// It currently does not so we have to ask the outer folder ourself so
|
||||
// that we get the correct attributes for My Computer etc.
|
||||
CComPtr<IShellFolder> pOuterSF;
|
||||
SHBindToObject(NULL, pidlFolder, IID_PPV_ARG(IShellFolder, &pOuterSF));
|
||||
|
||||
SFGAOF att = (psf && cidl) ? SHGetAttributes(pOuterSF ? pOuterSF.p : psf, apidl[0], SFGAO_FOLDER) : 0;
|
||||
if (att & SFGAO_FOLDER)
|
||||
AddClassKeyToArray(L"Folder", hKeys, &cKeys);
|
||||
|
||||
return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm);
|
||||
static LPITEMIDLIST CreateRegItem(PIDLTYPE type, LPCWSTR clsidstr)
|
||||
{
|
||||
CLSID clsid;
|
||||
return SUCCEEDED(CLSIDFromString(clsidstr, &clsid)) ? CreateRegItem(type, clsid) : NULL;
|
||||
}
|
||||
|
||||
HRESULT FormatGUIDKey(LPWSTR KeyName, SIZE_T KeySize, LPCWSTR RegPath, const GUID* riid)
|
||||
{
|
||||
WCHAR xriid[40];
|
||||
|
||||
if (!StringFromGUID2(*riid, xriid, _countof(xriid) - 1))
|
||||
return E_FAIL;
|
||||
|
||||
WCHAR xriid[CHARS_IN_GUID];
|
||||
StringFromGUID2(*riid, xriid, _countof(xriid));
|
||||
return StringCchPrintfW(KeyName, KeySize, RegPath, xriid);
|
||||
}
|
||||
|
||||
static DWORD SHELL_QueryCLSIDValue(_In_ REFCLSID clsid, _In_opt_ LPCWSTR SubKey, _In_opt_ LPCWSTR Value, _In_opt_ PVOID pData, _In_opt_ PDWORD pSize)
|
||||
{
|
||||
WCHAR Path[MAX_PATH];
|
||||
wcscpy(Path, L"CLSID\\");
|
||||
StringFromGUID2(clsid, Path + 6, 39);
|
||||
if (SubKey)
|
||||
{
|
||||
wcscpy(Path + 6 + 38, L"\\");
|
||||
wcscpy(Path + 6 + 39, SubKey);
|
||||
}
|
||||
return RegGetValueW(HKEY_CLASSES_ROOT, Path, Value, RRF_RT_ANY, NULL, pData, pSize);
|
||||
}
|
||||
|
||||
static bool HasCLSIDShellFolderValue(REFCLSID clsid, LPCWSTR Value)
|
||||
{
|
||||
return SHELL_QueryCLSIDValue(clsid, L"ShellFolder", Value, NULL, NULL) == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
struct CRegFolderInfo
|
||||
{
|
||||
const REGFOLDERINFO *m_pInfo;
|
||||
|
||||
void InitializeFolderInfo(const REGFOLDERINFO *pInfo)
|
||||
{
|
||||
m_pInfo = pInfo;
|
||||
}
|
||||
|
||||
const CLSID* IsRegItem(LPCITEMIDLIST pidl) const
|
||||
{
|
||||
if (pidl && pidl->mkid.cb >= sizeof(WORD) + 1 + 1 + sizeof(GUID))
|
||||
{
|
||||
if (pidl->mkid.abID[0] == m_pInfo->PidlType)
|
||||
return (CLSID*)(SIZE_T(pidl) + GetCLSIDOffset());
|
||||
if (pidl->mkid.abID[0] == PT_CONTROLS_OLDREGITEM)
|
||||
return (CLSID*)(SIZE_T(pidl) + GetRegItemCLSIDOffset(PT_CONTROLS_OLDREGITEM));
|
||||
}
|
||||
if (const IID* pIID = _ILGetGUIDPointer(pidl))
|
||||
{
|
||||
FIXME("Unexpected GUID PIDL type %#x\n", pidl->mkid.abID[0]);
|
||||
return pIID; // FIXME: Remove this when all folders have been fixed
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPITEMIDLIST CreateItem(size_t i) const
|
||||
{
|
||||
const REQUIREDREGITEM &item = GetAt(i);
|
||||
return CreateRegItem(GetPidlType(), item.clsid, item.Order);
|
||||
}
|
||||
|
||||
LPCWSTR GetParsingPath() const { return m_pInfo->pszParsingPath; }
|
||||
UINT GetCLSIDOffset() const { return GetRegItemCLSIDOffset(m_pInfo->PidlType); }
|
||||
PIDLTYPE GetPidlType() const { return m_pInfo->PidlType; }
|
||||
UINT GetRequiredItemsCount() const { return m_pInfo->Count; }
|
||||
const REQUIREDREGITEM& GetAt(size_t i) const { return m_pInfo->Items[i]; }
|
||||
};
|
||||
|
||||
HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut)
|
||||
{
|
||||
CComPtr<IDefaultExtractIconInit> initIcon;
|
||||
|
@ -213,47 +211,52 @@ HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVO
|
|||
}
|
||||
|
||||
class CRegFolderEnum :
|
||||
public CEnumIDListBase
|
||||
public CEnumIDListBase,
|
||||
public CRegFolderInfo
|
||||
{
|
||||
SHCONTF m_SHCTF;
|
||||
public:
|
||||
CRegFolderEnum();
|
||||
~CRegFolderEnum();
|
||||
HRESULT Initialize(LPCWSTR lpszEnumKeyName, DWORD dwFlags);
|
||||
HRESULT AddItemsFromKey(HKEY hkey_root, LPCWSTR szRepPath);
|
||||
HRESULT Initialize(const REGFOLDERINFO *pInfo, IShellFolder *pSF, DWORD dwFlags);
|
||||
HRESULT AddItemsFromKey(IShellFolder *pSF, HKEY hkey_root, LPCWSTR szRepPath);
|
||||
|
||||
const CLSID* GetPidlClsid(PCUITEMID_CHILD pidl) { return IsRegItem(pidl); }
|
||||
BOOL HasItemWithCLSID(LPCITEMIDLIST pidl) { return HasItemWithCLSIDImpl<CRegFolderEnum>(pidl); }
|
||||
|
||||
BEGIN_COM_MAP(CRegFolderEnum)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
CRegFolderEnum::CRegFolderEnum()
|
||||
HRESULT CRegFolderEnum::Initialize(const REGFOLDERINFO *pInfo, IShellFolder *pSF, DWORD dwFlags)
|
||||
{
|
||||
}
|
||||
|
||||
CRegFolderEnum::~CRegFolderEnum()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CRegFolderEnum::Initialize(LPCWSTR lpszEnumKeyName, DWORD dwFlags)
|
||||
{
|
||||
WCHAR KeyName[MAX_PATH];
|
||||
|
||||
InitializeFolderInfo(pInfo);
|
||||
m_SHCTF = (SHCONTF)dwFlags;
|
||||
if (!(dwFlags & SHCONTF_FOLDERS))
|
||||
return S_OK;
|
||||
|
||||
HRESULT hr = StringCchPrintfW(KeyName, MAX_PATH,
|
||||
WCHAR KeyName[MAX_PATH];
|
||||
HRESULT hr = StringCchPrintfW(KeyName, _countof(KeyName),
|
||||
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\%s\\Namespace",
|
||||
lpszEnumKeyName);
|
||||
pInfo->pszEnumKeyName);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
AddItemsFromKey(HKEY_LOCAL_MACHINE, KeyName);
|
||||
AddItemsFromKey(HKEY_CURRENT_USER, KeyName);
|
||||
|
||||
// First add the required items and then the items from the registry
|
||||
SFGAOF query = SHELL_CreateFolderEnumItemAttributeQuery(m_SHCTF, TRUE);
|
||||
for (size_t i = 0; i < GetRequiredItemsCount(); ++i)
|
||||
{
|
||||
LPITEMIDLIST pidl = CreateItem(i);
|
||||
if (pidl && SHELL_IncludeItemInFolderEnum(pSF, pidl, query, m_SHCTF))
|
||||
AddToEnumList(pidl);
|
||||
else
|
||||
ILFree(pidl);
|
||||
}
|
||||
AddItemsFromKey(pSF, HKEY_LOCAL_MACHINE, KeyName);
|
||||
AddItemsFromKey(pSF, HKEY_CURRENT_USER, KeyName);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CRegFolderEnum::AddItemsFromKey(HKEY hkey_root, LPCWSTR szRepPath)
|
||||
HRESULT CRegFolderEnum::AddItemsFromKey(IShellFolder *pSF, HKEY hkey_root, LPCWSTR szRepPath)
|
||||
{
|
||||
WCHAR name[MAX_PATH];
|
||||
HKEY hkey;
|
||||
|
@ -275,13 +278,16 @@ HRESULT CRegFolderEnum::AddItemsFromKey(HKEY hkey_root, LPCWSTR szRepPath)
|
|||
|
||||
if (*name == '{')
|
||||
{
|
||||
LPITEMIDLIST pidl = _ILCreateGuidFromStrW(name);
|
||||
|
||||
if (pidl)
|
||||
AddToEnumList(pidl);
|
||||
if (LPITEMIDLIST pidl = CreateRegItem(GetPidlType(), name))
|
||||
{
|
||||
SFGAOF query = SHELL_CreateFolderEnumItemAttributeQuery(m_SHCTF, TRUE);
|
||||
if (SHELL_IncludeItemInFolderEnum(pSF, pidl, query, m_SHCTF) && !HasItemWithCLSID(pidl))
|
||||
AddToEnumList(pidl);
|
||||
else
|
||||
ILFree(pidl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
return S_OK;
|
||||
|
@ -301,12 +307,11 @@ enum REGFOLDERCOLUMNINDEX
|
|||
|
||||
class CRegFolder :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolder2
|
||||
public IShellFolder2,
|
||||
public CRegFolderInfo
|
||||
{
|
||||
private:
|
||||
GUID m_guid;
|
||||
CAtlStringW m_rootPath;
|
||||
CAtlStringW m_enumKeyName;
|
||||
IShellFolder *m_pOuterFolder; // Not ref-counted
|
||||
CComHeapPtr<ITEMIDLIST> m_pidlRoot;
|
||||
|
||||
HRESULT GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
|
||||
|
@ -315,7 +320,19 @@ class CRegFolder :
|
|||
public:
|
||||
CRegFolder();
|
||||
~CRegFolder();
|
||||
HRESULT WINAPI Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName);
|
||||
HRESULT WINAPI Initialize(PREGFOLDERINITDATA pInit, LPCITEMIDLIST pidlRoot);
|
||||
|
||||
const REQUIREDREGITEM* IsRequiredItem(LPCITEMIDLIST pidl) const
|
||||
{
|
||||
const CLSID* const pCLSID = IsRegItem(pidl);
|
||||
for (size_t i = 0; pCLSID && i < GetRequiredItemsCount(); ++i)
|
||||
{
|
||||
const REQUIREDREGITEM &item = GetAt(i);
|
||||
if (item.clsid == *pCLSID)
|
||||
return &item;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// IShellFolder
|
||||
STDMETHOD(ParseDisplayName)(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes) override;
|
||||
|
@ -356,17 +373,10 @@ CRegFolder::~CRegFolder()
|
|||
{
|
||||
}
|
||||
|
||||
HRESULT WINAPI CRegFolder::Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName)
|
||||
HRESULT WINAPI CRegFolder::Initialize(PREGFOLDERINITDATA pInit, LPCITEMIDLIST pidlRoot)
|
||||
{
|
||||
memcpy(&m_guid, pGuid, sizeof(m_guid));
|
||||
|
||||
m_rootPath = lpszPath;
|
||||
if (!m_rootPath)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
m_enumKeyName = lpszEnumKeyName;
|
||||
if (!m_enumKeyName)
|
||||
return E_OUTOFMEMORY;
|
||||
InitializeFolderInfo(pInit->pInfo);
|
||||
m_pOuterFolder = pInit->psfOuter;
|
||||
|
||||
m_pidlRoot.Attach(ILClone(pidlRoot));
|
||||
if (!m_pidlRoot)
|
||||
|
@ -442,7 +452,7 @@ HRESULT WINAPI CRegFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR l
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
CComHeapPtr<ITEMIDLIST> pidlTemp(_ILCreateGuid(PT_GUID, clsid));
|
||||
CComHeapPtr<ITEMIDLIST> pidlTemp(CreateRegItem(GetPidlType(), clsid));
|
||||
if (!pidlTemp)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
|
@ -471,7 +481,8 @@ HRESULT WINAPI CRegFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR l
|
|||
|
||||
HRESULT WINAPI CRegFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
|
||||
{
|
||||
return ShellObjectCreatorInit<CRegFolderEnum>(m_enumKeyName, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
|
||||
return ShellObjectCreatorInit<CRegFolderEnum>(m_pInfo, m_pOuterFolder, dwFlags,
|
||||
IID_PPV_ARG(IEnumIDList, ppEnumIDList));
|
||||
}
|
||||
|
||||
HRESULT WINAPI CRegFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
|
||||
|
@ -529,14 +540,10 @@ HRESULT WINAPI CRegFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, P
|
|||
|
||||
/* Guid folders come first compared to everything else */
|
||||
/* And Drives come before folders in My Computer */
|
||||
if (_ILIsMyComputer(m_pidlRoot))
|
||||
{
|
||||
if (GetPidlType() == PT_COMPUTER_REGITEM)
|
||||
return MAKE_COMPARE_HRESULT(clsid1 ? 1 : -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MAKE_COMPARE_HRESULT(clsid1 ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT WINAPI CRegFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
|
||||
|
@ -591,7 +598,7 @@ HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
|
||||
hr = CRegItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
|
||||
}
|
||||
else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
|
||||
{
|
||||
|
@ -626,7 +633,7 @@ HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags,
|
|||
/* parsing name like ::{...} */
|
||||
pszPath[0] = ':';
|
||||
pszPath[1] = ':';
|
||||
SHELL32_GUIDToStringW(m_guid, &pszPath[2]);
|
||||
SHELL32_GUIDToStringW(m_pInfo->clsid, &pszPath[2]);
|
||||
strRet->uType = STRRET_WSTR;
|
||||
strRet->pOleStr = pszPath;
|
||||
return S_OK;
|
||||
|
@ -635,7 +642,7 @@ HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags,
|
|||
{
|
||||
BOOL bRet;
|
||||
WCHAR wstrName[MAX_PATH+1];
|
||||
bRet = HCR_GetClassNameW(m_guid, wstrName, MAX_PATH);
|
||||
bRet = HCR_GetClassNameW(m_pInfo->clsid, wstrName, MAX_PATH);
|
||||
if (!bRet)
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -698,7 +705,7 @@ HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags,
|
|||
PWCHAR pItemName = pszPath; // GET_SHGDN_RELATION(dwFlags) == SHGDN_INFOLDER
|
||||
if (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER)
|
||||
{
|
||||
hr = StringCchCopyW(pszPath, cchPath, m_rootPath);
|
||||
hr = StringCchCopyW(pszPath, cchPath, GetParsingPath());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pathlen = wcslen(pszPath);
|
||||
|
@ -861,8 +868,79 @@ HRESULT WINAPI CRegFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/* In latest windows version this is exported but it takes different arguments! */
|
||||
HRESULT CRegFolder_CreateInstance(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName, REFIID riid, void **ppv)
|
||||
static HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, HWND hwnd, IDataObject *pdtobj,
|
||||
UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return ShellObjectCreatorInit<CRegFolder>(pGuid, pidlRoot, lpszPath, lpszEnumKeyName, riid, ppv);
|
||||
if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
|
||||
return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
|
||||
|
||||
PIDLIST_ABSOLUTE pidlFolder;
|
||||
PUITEMID_CHILD *apidl;
|
||||
UINT cidl;
|
||||
HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
CRegFolder *pRegFolder = static_cast<CRegFolder*>(psf);
|
||||
const REQUIREDREGITEM* pRequired = pRegFolder->IsRequiredItem(apidl[0]);
|
||||
if (pRequired && pRequired->pszCpl)
|
||||
{
|
||||
WCHAR buf[MAX_PATH];
|
||||
wsprintfW(buf, L"%hs", const_cast<LPCSTR>(pRequired->pszCpl));
|
||||
hr = SHELL_ExecuteControlPanelCPL(hwnd, buf) ? S_OK : E_FAIL;
|
||||
}
|
||||
#if 0 // Should never happen, CDesktopFolder.cpp handles this
|
||||
else if (_ILIsDesktop(pidlFolder) && _ILIsDesktop(apidl[0]))
|
||||
{
|
||||
hr = SHELL_ExecuteControlPanelCPL(hwnd, L"desk.cpl") ? S_OK : E_FAIL;
|
||||
}
|
||||
#endif
|
||||
else if (_ILIsDesktop(pidlFolder) && _ILIsBitBucket(apidl[0]))
|
||||
{
|
||||
FIXME("Use SHOpenPropSheet on Recyclers PropertySheetHandlers from the registry\n");
|
||||
hr = SH_ShowRecycleBinProperties(L'C') ? S_OK : E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE; // Tell the caller to run the default action
|
||||
}
|
||||
|
||||
SHFree(pidlFolder);
|
||||
_ILFreeaPidl(apidl, cidl);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT CRegItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl, IShellFolder *psf, IContextMenu **ppcm)
|
||||
{
|
||||
HKEY hKeys[3];
|
||||
UINT cKeys = 0;
|
||||
|
||||
const GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
|
||||
if (pGuid)
|
||||
{
|
||||
WCHAR key[sizeof("CLSID\\") + 38];
|
||||
wcscpy(key, L"CLSID\\");
|
||||
StringFromGUID2(*pGuid, &key[6], 39);
|
||||
AddClassKeyToArray(key, hKeys, &cKeys);
|
||||
}
|
||||
|
||||
// FIXME: CRegFolder should be aggregated by its outer folder and should
|
||||
// provide the attributes for all required non-registry folders.
|
||||
// It currently does not so we have to ask the outer folder ourself so
|
||||
// that we get the correct attributes for My Computer etc.
|
||||
CComPtr<IShellFolder> pOuterSF;
|
||||
SHBindToObject(NULL, pidlFolder, IID_PPV_ARG(IShellFolder, &pOuterSF));
|
||||
|
||||
SFGAOF att = (psf && cidl) ? SHGetAttributes(pOuterSF ? pOuterSF.p : psf, apidl[0], SFGAO_FOLDER) : 0;
|
||||
if ((att & SFGAO_FOLDER) && (!pGuid || !HasCLSIDShellFolderValue(*pGuid, L"HideFolderVerbs")))
|
||||
AddClassKeyToArray(L"Folder", hKeys, &cKeys);
|
||||
|
||||
return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm);
|
||||
}
|
||||
|
||||
/* In latest windows version this is exported but it takes different arguments! */
|
||||
HRESULT CRegFolder_CreateInstance(PREGFOLDERINITDATA pInit, LPCITEMIDLIST pidlRoot, REFIID riid, void **ppv)
|
||||
{
|
||||
return ShellObjectCreatorInit<CRegFolder>(pInit, pidlRoot, riid, ppv);
|
||||
}
|
||||
|
|
|
@ -226,8 +226,7 @@ HRESULT CDesktopBrowser::Initialize(IShellDesktopTray *ShellDesk)
|
|||
if (!m_hWnd)
|
||||
return E_FAIL;
|
||||
|
||||
CSFV csfv = {sizeof(CSFV), psfDesktop};
|
||||
hRet = SHCreateShellFolderViewEx(&csfv, &m_ShellView);
|
||||
hRet = psfDesktop->CreateViewObject(m_hWnd, IID_PPV_ARG(IShellView, &m_ShellView));
|
||||
if (FAILED_UNEXPECTEDLY(hRet))
|
||||
return hRet;
|
||||
|
||||
|
|
|
@ -47,11 +47,53 @@ https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_co
|
|||
#define SHFSF_COL_FATTS 4 // File attributes
|
||||
#define SHFSF_COL_COMMENT 5
|
||||
|
||||
typedef struct _REQUIREDREGITEM
|
||||
{
|
||||
REFCLSID clsid;
|
||||
LPCSTR pszCpl;
|
||||
BYTE Order; // According to Geoff Chappell, required items have a fixed sort order
|
||||
} REQUIREDREGITEM;
|
||||
|
||||
typedef struct _REGFOLDERINFO
|
||||
{
|
||||
PIDLTYPE PidlType;
|
||||
BYTE Count; // Count of required items
|
||||
const REQUIREDREGITEM *Items;
|
||||
REFCLSID clsid;
|
||||
LPCWSTR pszParsingPath;
|
||||
LPCWSTR pszEnumKeyName;
|
||||
} REGFOLDERINFO;
|
||||
|
||||
typedef struct _REGFOLDERINITDATA
|
||||
{
|
||||
IShellFolder *psfOuter;
|
||||
const REGFOLDERINFO *pInfo;
|
||||
} REGFOLDERINITDATA, *PREGFOLDERINITDATA;
|
||||
|
||||
HRESULT CRegFolder_CreateInstance(PREGFOLDERINITDATA pInit, LPCITEMIDLIST pidlRoot, REFIID riid, void **ppv);
|
||||
|
||||
#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
|
||||
#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
|
||||
#define IS_SHGDN_FOR_PARSING(flags) ( ((flags) & (SHGDN_FORADDRESSBAR | SHGDN_FORPARSING)) == SHGDN_FORPARSING)
|
||||
#define IS_SHGDN_DESKTOPABSOLUTEPARSING(flags) ( ((flags) & (SHGDN_FORADDRESSBAR | SHGDN_FORPARSING | 0xFF)) == SHGDN_FORPARSING)
|
||||
|
||||
static inline SFGAOF
|
||||
SHELL_CreateFolderEnumItemAttributeQuery(SHCONTF Flags, BOOL ForRegItem)
|
||||
{
|
||||
SFGAOF query = SFGAO_FOLDER | (ForRegItem ? SFGAO_NONENUMERATED : 0);
|
||||
if (!(Flags & SHCONTF_INCLUDEHIDDEN))
|
||||
query |= SFGAO_HIDDEN;
|
||||
if (!(Flags & SHCONTF_INCLUDESUPERHIDDEN))
|
||||
query |= SFGAO_HIDDEN | SFGAO_SYSTEM;
|
||||
return query;
|
||||
}
|
||||
|
||||
SHCONTF
|
||||
SHELL_GetDefaultFolderEnumSHCONTF();
|
||||
|
||||
BOOL
|
||||
SHELL_IncludeItemInFolderEnum(IShellFolder *pSF, PCUITEMID_CHILD pidl, SFGAOF Query, SHCONTF Flags);
|
||||
|
||||
HRESULT
|
||||
Shell_NextElement(
|
||||
_Inout_ LPWSTR *ppch,
|
||||
|
|
|
@ -26,6 +26,34 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
SHCONTF SHELL_GetDefaultFolderEnumSHCONTF()
|
||||
{
|
||||
SHCONTF Flags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
|
||||
SHELLSTATE ss;
|
||||
SHGetSetSettings(&ss, SSF_SHOWALLOBJECTS | SSF_SHOWSUPERHIDDEN, FALSE);
|
||||
if (ss.fShowAllObjects)
|
||||
Flags |= SHCONTF_INCLUDEHIDDEN;
|
||||
if (ss.fShowSuperHidden)
|
||||
Flags |= SHCONTF_INCLUDESUPERHIDDEN;
|
||||
return Flags;
|
||||
}
|
||||
|
||||
BOOL SHELL_IncludeItemInFolderEnum(IShellFolder *pSF, PCUITEMID_CHILD pidl, SFGAOF Query, SHCONTF Flags)
|
||||
{
|
||||
if (SUCCEEDED(pSF->GetAttributesOf(1, &pidl, &Query)))
|
||||
{
|
||||
if (Query & SFGAO_NONENUMERATED)
|
||||
return FALSE;
|
||||
if ((Query & SFGAO_HIDDEN) && !(Flags & SHCONTF_INCLUDEHIDDEN))
|
||||
return FALSE;
|
||||
if ((Query & (SFGAO_HIDDEN | SFGAO_SYSTEM)) == (SFGAO_HIDDEN | SFGAO_SYSTEM) && !(Flags & SHCONTF_INCLUDESUPERHIDDEN))
|
||||
return FALSE;
|
||||
if ((Flags & (SHCONTF_FOLDERS | SHCONTF_NONFOLDERS)) != (SHCONTF_FOLDERS | SHCONTF_NONFOLDERS))
|
||||
return (Flags & SHCONTF_FOLDERS) ? (Query & SFGAO_FOLDER) : !(Query & SFGAO_FOLDER);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Shell_NextElement(
|
||||
_Inout_ LPWSTR *ppch,
|
||||
|
|
|
@ -1767,7 +1767,6 @@ LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID)
|
|||
}
|
||||
return _ILCreateGuid(PT_GUID, &iid);
|
||||
}
|
||||
#endif
|
||||
|
||||
LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID)
|
||||
{
|
||||
|
@ -1784,6 +1783,7 @@ LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID)
|
|||
}
|
||||
return _ILCreateGuid(PT_GUID, &iid);
|
||||
}
|
||||
#endif /* __REACTOS__ */
|
||||
|
||||
LPITEMIDLIST _ILCreateFromFindDataW( const WIN32_FIND_DATAW *wfd )
|
||||
{
|
||||
|
|
|
@ -104,6 +104,18 @@ extern "C" {
|
|||
#define PT_IESPECIAL2 0xb1
|
||||
#define PT_SHARE 0xc3
|
||||
|
||||
#ifdef __REACTOS__
|
||||
#define PT_DESKTOP_REGITEM 0x1F // => SHDID_ROOT_REGITEM
|
||||
#define PT_COMPUTER_REGITEM 0x2E // => SHDID_COMPUTER_OTHER
|
||||
#define PT_FS 0x30 // Win95 SHSimpleIDListFromPath
|
||||
#define PT_FS_FOLDER_FLAG 0x01
|
||||
#define PT_FS_FILE_FLAG 0x02
|
||||
#define PT_FS_UNICODE_FLAG 0x04
|
||||
// PT_NET_REGITEM 0x4? // => SHDID_NET_OTHER
|
||||
#define PT_CONTROLS_OLDREGITEM 0x70
|
||||
#define PT_CONTROLS_NEWREGITEM 0x71
|
||||
#endif
|
||||
|
||||
#include "pshpack1.h"
|
||||
typedef BYTE PIDLTYPE;
|
||||
|
||||
|
@ -263,9 +275,11 @@ BOOL _ILIsEmpty (LPCITEMIDLIST pidl) { return _ILIsDesktop(pidl)
|
|||
*/
|
||||
LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid) DECLSPEC_HIDDEN;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
/* Like _ILCreateGuid, but using the string szGUID. */
|
||||
LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID) DECLSPEC_HIDDEN;
|
||||
LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID) DECLSPEC_HIDDEN;
|
||||
#endif
|
||||
|
||||
/* Commonly used PIDLs representing file system objects. */
|
||||
LPITEMIDLIST _ILCreateDesktop (void) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -90,8 +90,6 @@ HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC
|
|||
HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN;
|
||||
HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT CRegFolder_CreateInstance(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, LPCWSTR lpszEnumKeyName, REFIID riid, void **ppv);
|
||||
|
||||
/* initialisation for FORMATETC */
|
||||
#define InitFormatEtc(fe, cf, med) \
|
||||
{\
|
||||
|
|
|
@ -195,6 +195,7 @@ interface IShellFolder : IUnknown
|
|||
cpp_quote("#define SFGAO_HASPROPSHEET 0x00000040L")
|
||||
cpp_quote("#define SFGAO_DROPTARGET 0x00000100L")
|
||||
cpp_quote("#define SFGAO_CAPABILITYMASK 0x00000177L")
|
||||
cpp_quote("#define SFGAO_SYSTEM 0x00001000L")
|
||||
cpp_quote("#define SFGAO_ENCRYPTED 0x00002000L")
|
||||
cpp_quote("#define SFGAO_ISSLOW 0x00004000L")
|
||||
cpp_quote("#define SFGAO_GHOSTED 0x00008000L")
|
||||
|
@ -1485,6 +1486,38 @@ interface ICommDlgBrowser3 : ICommDlgBrowser2
|
|||
[in] IShellView *ppshv);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* IFolderFilterSite & IFolderFilter interfaces
|
||||
*/
|
||||
[
|
||||
object,
|
||||
uuid(C0A651F5-B48B-11d2-B5ED-006097C686F6),
|
||||
pointer_default(unique)
|
||||
]
|
||||
interface IFolderFilterSite : IUnknown
|
||||
{
|
||||
HRESULT SetFilter([in] IUnknown* punk);
|
||||
}
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(9CC22886-DC8E-11d2-B1D0-00C04F8EEB3E),
|
||||
pointer_default(unique)
|
||||
]
|
||||
interface IFolderFilter : IUnknown
|
||||
{
|
||||
HRESULT ShouldShow(
|
||||
[in] IShellFolder* psf,
|
||||
[in, unique] PCIDLIST_ABSOLUTE pidlFolder,
|
||||
[in] PCUITEMID_CHILD pidlItem);
|
||||
|
||||
HRESULT GetEnumFlags(
|
||||
[in] IShellFolder* psf,
|
||||
[in] PCIDLIST_ABSOLUTE pidlFolder,
|
||||
[out] HWND *phwnd,
|
||||
[in, out] DWORD *pgrfFlags);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* IDockingWindow interface
|
||||
*/
|
||||
|
|
|
@ -293,6 +293,17 @@ HRESULT inline ShellDebugObjectCreator(REFIID riid, R ** ppv)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
HRESULT inline ShellObjectCreator(CComPtr<T> &objref)
|
||||
{
|
||||
_CComObject<T> *pobj;
|
||||
HRESULT hResult = _CComObject<T>::CreateInstance(&pobj);
|
||||
objref = pobj; // AddRef() gets called here
|
||||
if (FAILED(hResult))
|
||||
return hResult;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
HRESULT inline ShellObjectCreator(REFIID riid, void ** ppv)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue