https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6ae11ba09d4fa8d16336a…
commit 6ae11ba09d4fa8d16336a1ed40a112b3df19a474
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Thu Aug 29 20:45:59 2024 +0200
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Aug 29 20:45:59 2024 +0200
[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
---
dll/win32/shell32/CDefView.cpp | 12 +-
dll/win32/shell32/CEnumIDListBase.cpp | 27 --
dll/win32/shell32/CEnumIDListBase.h | 16 +-
dll/win32/shell32/folders/CControlPanelFolder.cpp | 14 +-
dll/win32/shell32/folders/CDesktopFolder.cpp | 197 +++++------
dll/win32/shell32/folders/CDesktopFolder.h | 29 ++
dll/win32/shell32/folders/CDrivesFolder.cpp | 56 +++-
dll/win32/shell32/folders/CDrivesFolder.h | 13 +-
dll/win32/shell32/folders/CFSFolder.cpp | 44 ++-
dll/win32/shell32/folders/CRegFolder.cpp | 362 +++++++++++++--------
dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp | 3 +-
dll/win32/shell32/shfldr.h | 42 +++
dll/win32/shell32/shlfolder.cpp | 28 ++
dll/win32/shell32/wine/pidl.c | 2 +-
dll/win32/shell32/wine/pidl.h | 14 +
dll/win32/shell32/wine/shell32_main.h | 2 -
sdk/include/psdk/shobjidl.idl | 33 ++
sdk/include/reactos/shellutils.h | 11 +
18 files changed, 601 insertions(+), 304 deletions(-)
diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp
index 7617f85e5d7..bb3e88239c2 100644
--- a/dll/win32/shell32/CDefView.cpp
+++ b/dll/win32/shell32/CDefView.cpp
@@ -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;
}
diff --git a/dll/win32/shell32/CEnumIDListBase.cpp
b/dll/win32/shell32/CEnumIDListBase.cpp
index 47adf6e2ea8..d0a79b350d1 100644
--- a/dll/win32/shell32/CEnumIDListBase.cpp
+++ b/dll/win32/shell32/CEnumIDListBase.cpp
@@ -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;
diff --git a/dll/win32/shell32/CEnumIDListBase.h b/dll/win32/shell32/CEnumIDListBase.h
index 65ec9058c42..68ce0966617 100644
--- a/dll/win32/shell32/CEnumIDListBase.h
+++ b/dll/win32/shell32/CEnumIDListBase.h
@@ -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;
diff --git a/dll/win32/shell32/folders/CControlPanelFolder.cpp
b/dll/win32/shell32/folders/CControlPanelFolder.cpp
index 58d5c36353c..729112d68e8 100644
--- a/dll/win32/shell32/folders/CControlPanelFolder.cpp
+++ b/dll/win32/shell32/folders/CControlPanelFolder.cpp
@@ -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;
diff --git a/dll/win32/shell32/folders/CDesktopFolder.cpp
b/dll/win32/shell32/folders/CDesktopFolder.cpp
index c95828dc6fc..ee1c10834dc 100644
--- a/dll/win32/shell32/folders/CDesktopFolder.cpp
+++ b/dll/win32/shell32/folders/CDesktopFolder.cpp
@@ -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.@]
*/
diff --git a/dll/win32/shell32/folders/CDesktopFolder.h
b/dll/win32/shell32/folders/CDesktopFolder.h
index 66eda8df0ee..0f8ea5a35a2 100644
--- a/dll/win32/shell32/folders/CDesktopFolder.h
+++ b/dll/win32/shell32/folders/CDesktopFolder.h
@@ -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_ */
diff --git a/dll/win32/shell32/folders/CDrivesFolder.cpp
b/dll/win32/shell32/folders/CDrivesFolder.cpp
index 9cc549a842a..56422f83946 100644
--- a/dll/win32/shell32/folders/CDrivesFolder.cpp
+++ b/dll/win32/shell32/folders/CDrivesFolder.cpp
@@ -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 */
diff --git a/dll/win32/shell32/folders/CDrivesFolder.h
b/dll/win32/shell32/folders/CDrivesFolder.h
index 7958027b545..a4222b88362 100644
--- a/dll/win32/shell32/folders/CDrivesFolder.h
+++ b/dll/win32/shell32/folders/CDrivesFolder.h
@@ -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()
};
diff --git a/dll/win32/shell32/folders/CFSFolder.cpp
b/dll/win32/shell32/folders/CFSFolder.cpp
index 8b444f05635..bde0d6dbb42 100644
--- a/dll/win32/shell32/folders/CFSFolder.cpp
+++ b/dll/win32/shell32/folders/CFSFolder.cpp
@@ -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/zi…
WCHAR szFileName[MAX_PATH];
LPWSTR pExtension;
+ BOOL hasName = _ILSimpleGetTextW(pidl, szFileName, _countof(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 (_ILSimpleGetTextW(pidl, szFileName, _countof(szFileName)) &&
(pExtension = PathFindExtensionW(szFileName)))
+ 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)
{
diff --git a/dll/win32/shell32/folders/CRegFolder.cpp
b/dll/win32/shell32/folders/CRegFolder.cpp
index 8d8223c3924..510727a6b67 100644
--- a/dll/win32/shell32/folders/CRegFolder.cpp
+++ b/dll/win32/shell32/folders/CRegFolder.cpp
@@ -16,116 +16,114 @@
* 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/regfold…
*/
#include <precomp.h>
WINE_DEFAULT_DEBUG_CHANNEL (shell);
-HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf,
- HWND hwnd,
- IDataObject *pdtobj,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES)
- return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
+#define DEFAULTSORTORDERINDEX 0x80 // The default for registry items according to Geoff
Chappell
- PIDLIST_ABSOLUTE pidlFolder;
- PUITEMID_CHILD *apidl;
- UINT cidl;
- HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl,
&cidl);
- if (FAILED_UNEXPECTEDLY(hr))
- return hr;
+static HRESULT CRegItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND
hwnd, UINT cidl,
+ PCUITEMID_CHILD_ARRAY apidl,
IShellFolder *psf, IContextMenu **ppcm);
- 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
+static inline UINT GetRegItemCLSIDOffset(PIDLTYPE type)
+{
+ return type == PT_CONTROLS_NEWREGITEM ? 14 : 4;
+}
+
+static LPITEMIDLIST CreateRegItem(PIDLTYPE type, REFCLSID clsid, BYTE order = 0)
+{
+#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)
{
- /* Tell the caller to run the default action */
- hr = S_FALSE;
+ 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;
+}
- SHFree(pidlFolder);
- _ILFreeaPidl(apidl, cidl);
-
- return hr;
+static LPITEMIDLIST CreateRegItem(PIDLTYPE type, LPCWSTR clsidstr)
+{
+ CLSID clsid;
+ return SUCCEEDED(CLSIDFromString(clsidstr, &clsid)) ? CreateRegItem(type, clsid)
: NULL;
}
-HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
- HWND hwnd,
- UINT cidl,
- PCUITEMID_CHILD_ARRAY apidl,
- IShellFolder *psf,
- IContextMenu **ppcm)
+HRESULT FormatGUIDKey(LPWSTR KeyName, SIZE_T KeySize, LPCWSTR RegPath, const GUID* riid)
{
- HKEY hKeys[10];
- UINT cKeys = 0;
+ WCHAR xriid[CHARS_IN_GUID];
+ StringFromGUID2(*riid, xriid, _countof(xriid));
+ return StringCchPrintfW(KeyName, KeySize, RegPath, xriid);
+}
- GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
- if (pGuid)
+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)
{
- WCHAR key[60];
- wcscpy(key, L"CLSID\\");
- StringFromGUID2(*pGuid, &key[6], 39);
- AddClassKeyToArray(key, hKeys, &cKeys);
+ wcscpy(Path + 6 + 38, L"\\");
+ wcscpy(Path + 6 + 39, SubKey);
}
+ return RegGetValueW(HKEY_CLASSES_ROOT, Path, Value, RRF_RT_ANY, NULL, pData, pSize);
+}
- // 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 bool HasCLSIDShellFolderValue(REFCLSID clsid, LPCWSTR Value)
+{
+ return SHELL_QueryCLSIDValue(clsid, L"ShellFolder", Value, NULL, NULL) ==
ERROR_SUCCESS;
}
-HRESULT FormatGUIDKey(LPWSTR KeyName, SIZE_T KeySize, LPCWSTR RegPath, const GUID* riid)
+struct CRegFolderInfo
{
- WCHAR xriid[40];
+ const REGFOLDERINFO *m_pInfo;
- if (!StringFromGUID2(*riid, xriid, _countof(xriid) - 1))
- return E_FAIL;
+ void InitializeFolderInfo(const REGFOLDERINFO *pInfo)
+ {
+ m_pInfo = pInfo;
+ }
- return StringCchPrintfW(KeyName, KeySize, RegPath, xriid);
-}
+ 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)
{
@@ -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;
}
+static HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, HWND hwnd,
IDataObject *pdtobj,
+ UINT uMsg, WPARAM wParam, LPARAM
lParam)
+{
+ 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(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR
lpszPath, LPCWSTR lpszEnumKeyName, REFIID riid, void **ppv)
+HRESULT CRegFolder_CreateInstance(PREGFOLDERINITDATA pInit, LPCITEMIDLIST pidlRoot,
REFIID riid, void **ppv)
{
- return ShellObjectCreatorInit<CRegFolder>(pGuid, pidlRoot, lpszPath,
lpszEnumKeyName, riid, ppv);
+ return ShellObjectCreatorInit<CRegFolder>(pInit, pidlRoot, riid, ppv);
}
diff --git a/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp
b/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp
index 11c65fb9819..d14c1c15626 100644
--- a/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp
+++ b/dll/win32/shell32/shelldesktop/CDesktopBrowser.cpp
@@ -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;
diff --git a/dll/win32/shell32/shfldr.h b/dll/win32/shell32/shfldr.h
index 2b055833464..ff397123b8e 100644
--- a/dll/win32/shell32/shfldr.h
+++ b/dll/win32/shell32/shfldr.h
@@ -47,11 +47,53 @@
https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobji…
#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,
diff --git a/dll/win32/shell32/shlfolder.cpp b/dll/win32/shell32/shlfolder.cpp
index a6ea823212f..1d32793d746 100644
--- a/dll/win32/shell32/shlfolder.cpp
+++ b/dll/win32/shell32/shlfolder.cpp
@@ -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,
diff --git a/dll/win32/shell32/wine/pidl.c b/dll/win32/shell32/wine/pidl.c
index 09b09112adb..54751ded772 100644
--- a/dll/win32/shell32/wine/pidl.c
+++ b/dll/win32/shell32/wine/pidl.c
@@ -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 )
{
diff --git a/dll/win32/shell32/wine/pidl.h b/dll/win32/shell32/wine/pidl.h
index b25481bd6c8..304ce1cc19b 100644
--- a/dll/win32/shell32/wine/pidl.h
+++ b/dll/win32/shell32/wine/pidl.h
@@ -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;
diff --git a/dll/win32/shell32/wine/shell32_main.h
b/dll/win32/shell32/wine/shell32_main.h
index db03e2ad794..73bebc71d3b 100644
--- a/dll/win32/shell32/wine/shell32_main.h
+++ b/dll/win32/shell32/wine/shell32_main.h
@@ -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) \
{\
diff --git a/sdk/include/psdk/shobjidl.idl b/sdk/include/psdk/shobjidl.idl
index a31a145190b..8738863eb55 100644
--- a/sdk/include/psdk/shobjidl.idl
+++ b/sdk/include/psdk/shobjidl.idl
@@ -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
*/
diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h
index 17d7e0e74e7..825e834897b 100644
--- a/sdk/include/reactos/shellutils.h
+++ b/sdk/include/reactos/shellutils.h
@@ -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)
{