mirror of
https://github.com/reactos/reactos.git
synced 2025-06-20 07:36:05 +00:00
[RSHELL]
* Implement a rudimentary but mostly functional (for start menu purposes) CMergedFolder class. It's still disabled by default because clicking on an item in a merged folder appears to fail to execute it. svn path=/branches/shell-experiments/; revision=63658
This commit is contained in:
parent
9ebe8b2e4e
commit
f03fef66d1
5 changed files with 449 additions and 106 deletions
|
@ -31,6 +31,7 @@ add_importlibs(rshell
|
||||||
uxtheme
|
uxtheme
|
||||||
shlwapi
|
shlwapi
|
||||||
shell32
|
shell32
|
||||||
|
comctl32
|
||||||
gdi32
|
gdi32
|
||||||
ole32
|
ole32
|
||||||
user32
|
user32
|
||||||
|
|
|
@ -1260,10 +1260,9 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
|
||||||
IEnumIDList * eidl;
|
IEnumIDList * eidl;
|
||||||
m_shellFolder->EnumObjects(GetToolbar(), SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
|
m_shellFolder->EnumObjects(GetToolbar(), SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
|
||||||
|
|
||||||
LPITEMIDLIST item = static_cast<LPITEMIDLIST>(CoTaskMemAlloc(sizeof(ITEMIDLIST)));
|
LPITEMIDLIST item = { 0 };
|
||||||
ULONG fetched;
|
hr = eidl->Next(1, &item, NULL);
|
||||||
hr = eidl->Next(1, &item, &fetched);
|
while (hr == S_OK)
|
||||||
while (SUCCEEDED(hr) && fetched > 0)
|
|
||||||
{
|
{
|
||||||
INT index = 0;
|
INT index = 0;
|
||||||
INT indexOpen = 0;
|
INT indexOpen = 0;
|
||||||
|
@ -1286,13 +1285,13 @@ HRESULT CMenuSFToolbar::FillToolbar(BOOL clearFirst)
|
||||||
DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
|
DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
|
||||||
|
|
||||||
// Fetch next item already, so we know if the current one is the last
|
// Fetch next item already, so we know if the current one is the last
|
||||||
hr = eidl->Next(1, &item, &fetched);
|
hr = eidl->Next(1, &item, NULL);
|
||||||
|
|
||||||
AddButton(++i, MenuString, attrs & SFGAO_FOLDER, index, dwData, FAILED(hr) || fetched == 0);
|
AddButton(++i, MenuString, attrs & SFGAO_FOLDER, index, dwData, hr != S_OK);
|
||||||
|
|
||||||
CoTaskMemFree(MenuString);
|
CoTaskMemFree(MenuString);
|
||||||
}
|
}
|
||||||
CoTaskMemFree(item);
|
ILFree(item);
|
||||||
|
|
||||||
// If no items were added, show the "empty" placeholder
|
// If no items were added, show the "empty" placeholder
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
|
|
@ -25,18 +25,33 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(CMergedFolder);
|
WINE_DEFAULT_DEBUG_CHANNEL(CMergedFolder);
|
||||||
|
|
||||||
|
struct LocalPidlInfo
|
||||||
|
{
|
||||||
|
int side; // -1 local, 0 shared, 1 common
|
||||||
|
LPITEMIDLIST pidl;
|
||||||
|
};
|
||||||
|
|
||||||
class CEnumMergedFolder :
|
class CEnumMergedFolder :
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
public IEnumIDList
|
public IEnumIDList
|
||||||
{
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CComPtr<IShellFolder> m_UserLocalFolder;
|
||||||
|
CComPtr<IShellFolder> m_AllUSersFolder;
|
||||||
CComPtr<IEnumIDList> m_UserLocal;
|
CComPtr<IEnumIDList> m_UserLocal;
|
||||||
CComPtr<IEnumIDList> m_AllUSers;
|
CComPtr<IEnumIDList> m_AllUSers;
|
||||||
BOOL m_FirstDone;
|
|
||||||
|
HWND m_HwndOwner;
|
||||||
|
SHCONTF m_Flags;
|
||||||
|
|
||||||
|
HDSA m_hDsa;
|
||||||
|
UINT m_hDsaIndex;
|
||||||
|
UINT m_hDsaCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CEnumMergedFolder() : m_UserLocal(NULL), m_AllUSers(NULL), m_FirstDone(FALSE) {}
|
CEnumMergedFolder();
|
||||||
virtual ~CEnumMergedFolder() {}
|
virtual ~CEnumMergedFolder();
|
||||||
|
|
||||||
DECLARE_NOT_AGGREGATABLE(CEnumMergedFolder)
|
DECLARE_NOT_AGGREGATABLE(CEnumMergedFolder)
|
||||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||||
|
@ -45,84 +60,346 @@ public:
|
||||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||||
END_COM_MAP()
|
END_COM_MAP()
|
||||||
|
|
||||||
HRESULT Begin(HWND hwndOwner, SHCONTF flags, IShellFolder * userLocal, IShellFolder * allUSers)
|
int DsaDeleteCallback(LocalPidlInfo * info);
|
||||||
{
|
|
||||||
HRESULT hr;
|
static int CALLBACK s_DsaDeleteCallback(void *pItem, void *pData);
|
||||||
hr = userLocal->EnumObjects(hwndOwner, flags, &m_UserLocal);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
HRESULT SetSources(IShellFolder * userLocal, IShellFolder * allUSers);
|
||||||
return hr;
|
HRESULT Begin(HWND hwndOwner, SHCONTF flags);
|
||||||
hr = userLocal->EnumObjects(hwndOwner, flags, &m_AllUSers);
|
HRESULT FindPidlInList(LPCITEMIDLIST pcidl, LocalPidlInfo * pinfo);
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
{
|
|
||||||
m_UserLocal = NULL;
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
m_FirstDone = FALSE;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Next(
|
virtual HRESULT STDMETHODCALLTYPE Next(
|
||||||
ULONG celt,
|
ULONG celt,
|
||||||
LPITEMIDLIST *rgelt,
|
LPITEMIDLIST *rgelt,
|
||||||
ULONG *pceltFetched)
|
ULONG *pceltFetched);
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
*pceltFetched = 0;
|
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE Reset();
|
||||||
if (!m_FirstDone)
|
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum);
|
||||||
{
|
|
||||||
hr = m_UserLocal->Next(celt, rgelt, pceltFetched);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
if (hr == S_FALSE)
|
|
||||||
m_FirstDone = true;
|
|
||||||
else if (celt < 2)
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD offset = *pceltFetched;
|
|
||||||
if (*pceltFetched < celt)
|
|
||||||
{
|
|
||||||
rgelt += *pceltFetched;
|
|
||||||
celt = (celt - *pceltFetched);
|
|
||||||
*pceltFetched = 0;
|
|
||||||
|
|
||||||
hr = m_AllUSers->Next(celt, rgelt, pceltFetched);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
*pceltFetched += offset;
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Skip(
|
|
||||||
ULONG celt)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Reset(
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (m_FirstDone)
|
|
||||||
m_AllUSers->Reset();
|
|
||||||
return m_UserLocal->Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE Clone(
|
|
||||||
IEnumIDList **ppenum)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CEnumMergedFolder::CEnumMergedFolder() :
|
||||||
|
m_UserLocalFolder(NULL),
|
||||||
|
m_AllUSersFolder(NULL),
|
||||||
|
m_UserLocal(NULL),
|
||||||
|
m_AllUSers(NULL),
|
||||||
|
m_HwndOwner(NULL),
|
||||||
|
m_Flags(0),
|
||||||
|
m_hDsaIndex(0)
|
||||||
|
{
|
||||||
|
m_hDsa = DSA_Create(sizeof(LocalPidlInfo), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
CEnumMergedFolder::~CEnumMergedFolder()
|
||||||
|
{
|
||||||
|
DSA_DestroyCallback(m_hDsa, s_DsaDeleteCallback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CEnumMergedFolder::DsaDeleteCallback(LocalPidlInfo * info)
|
||||||
|
{
|
||||||
|
ILFree(info->pidl);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CALLBACK CEnumMergedFolder::s_DsaDeleteCallback(void *pItem, void *pData)
|
||||||
|
{
|
||||||
|
CEnumMergedFolder * mf = (CEnumMergedFolder*) pData;
|
||||||
|
LocalPidlInfo * item = (LocalPidlInfo*) pItem;
|
||||||
|
return mf->DsaDeleteCallback(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CEnumMergedFolder::SetSources(IShellFolder * userLocal, IShellFolder * allUSers)
|
||||||
|
{
|
||||||
|
m_UserLocalFolder = userLocal;
|
||||||
|
m_AllUSersFolder = allUSers;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CEnumMergedFolder::Begin(HWND hwndOwner, SHCONTF flags)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (m_HwndOwner == hwndOwner && m_Flags == flags)
|
||||||
|
{
|
||||||
|
return Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Search conditions changed, recreating list...\n");
|
||||||
|
|
||||||
|
hr = m_UserLocalFolder->EnumObjects(hwndOwner, flags, &m_UserLocal);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
hr = m_AllUSersFolder->EnumObjects(hwndOwner, flags, &m_AllUSers);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
{
|
||||||
|
m_UserLocal = NULL;
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSA_EnumCallback(m_hDsa, s_DsaDeleteCallback, this);
|
||||||
|
DSA_DeleteAllItems(m_hDsa);
|
||||||
|
m_hDsaCount = 0;
|
||||||
|
|
||||||
|
HRESULT hr1 = S_OK;
|
||||||
|
HRESULT hr2 = S_OK;
|
||||||
|
LPITEMIDLIST pidl1 = NULL;
|
||||||
|
LPITEMIDLIST pidl2 = NULL;
|
||||||
|
int order = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (order <= 0)
|
||||||
|
{
|
||||||
|
if (hr1 == S_OK)
|
||||||
|
{
|
||||||
|
hr1 = m_UserLocal->Next(1, &pidl1, NULL);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr1))
|
||||||
|
return hr1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pidl1 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (order >= 0)
|
||||||
|
{
|
||||||
|
if (hr2 == S_OK)
|
||||||
|
{
|
||||||
|
hr2 = m_AllUSers->Next(1, &pidl2, NULL);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr2))
|
||||||
|
return hr2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pidl2 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hr1 == S_OK && hr2 == S_OK)
|
||||||
|
{
|
||||||
|
LPWSTR name1;
|
||||||
|
LPWSTR name2;
|
||||||
|
STRRET str1 = { STRRET_WSTR };
|
||||||
|
STRRET str2 = { STRRET_WSTR };
|
||||||
|
hr = m_UserLocalFolder->GetDisplayNameOf(pidl1, SHGDN_FORPARSING | SHGDN_INFOLDER, &str1);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
hr = m_AllUSersFolder->GetDisplayNameOf(pidl2, SHGDN_FORPARSING | SHGDN_INFOLDER, &str2);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
StrRetToStrW(&str1, pidl1, &name1);
|
||||||
|
StrRetToStrW(&str2, pidl2, &name2);
|
||||||
|
order = StrCmpW(name1, name2);
|
||||||
|
CoTaskMemFree(name1);
|
||||||
|
CoTaskMemFree(name2);
|
||||||
|
}
|
||||||
|
else if (hr1 == S_OK)
|
||||||
|
{
|
||||||
|
order = -1;
|
||||||
|
}
|
||||||
|
else if (hr2 == S_OK)
|
||||||
|
{
|
||||||
|
order = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalPidlInfo info;
|
||||||
|
if (order < 0)
|
||||||
|
{
|
||||||
|
info.side = -1;
|
||||||
|
info.pidl = ILClone(pidl1);
|
||||||
|
ILFree(pidl1);
|
||||||
|
}
|
||||||
|
else if (order > 0)
|
||||||
|
{
|
||||||
|
info.side = 1;
|
||||||
|
info.pidl = ILClone(pidl2);
|
||||||
|
ILFree(pidl2);
|
||||||
|
}
|
||||||
|
else // if (order == 0)
|
||||||
|
{
|
||||||
|
info.side = 0;
|
||||||
|
info.pidl = ILClone(pidl1);
|
||||||
|
ILFree(pidl1);
|
||||||
|
ILFree(pidl2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Inserting item %d with side %d and pidl { cb=%d }\n", m_hDsaCount, info.side, info.pidl->mkid.cb);
|
||||||
|
int idx = DSA_InsertItem(m_hDsa, DSA_APPEND, &info);
|
||||||
|
TRACE("New index: %d\n", idx);
|
||||||
|
|
||||||
|
m_hDsaCount++;
|
||||||
|
|
||||||
|
} while (hr1 == S_OK || hr2 == S_OK);
|
||||||
|
|
||||||
|
m_HwndOwner = hwndOwner;
|
||||||
|
m_Flags = flags;
|
||||||
|
|
||||||
|
return Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CEnumMergedFolder::FindPidlInList(LPCITEMIDLIST pcidl, LocalPidlInfo * pinfo)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("Searching for pidl { cb=%d } in a list of %d items\n", pcidl->mkid.cb, m_hDsaCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)m_hDsaCount; i++)
|
||||||
|
{
|
||||||
|
LocalPidlInfo * tinfo = (LocalPidlInfo *)DSA_GetItemPtr(m_hDsa, i);
|
||||||
|
if (!tinfo)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
LocalPidlInfo info = *tinfo;
|
||||||
|
|
||||||
|
TRACE("Comparing with item at %d with side %d and pidl { cb=%d }\n", i, info.side, info.pidl->mkid.cb);
|
||||||
|
|
||||||
|
if (info.side <= 0)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
LPWSTR name1;
|
||||||
|
LPWSTR name2;
|
||||||
|
STRRET str1 = { STRRET_WSTR, 0 };
|
||||||
|
STRRET str2 = { STRRET_WSTR, 0 };
|
||||||
|
hr = m_UserLocalFolder->GetDisplayNameOf(info->pidl, SHGDN_FORPARSING | SHGDN_INFOLDER, &str1);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
hr = m_UserLocalFolder->GetDisplayNameOf(pcidl, SHGDN_FORPARSING | SHGDN_INFOLDER, &str2);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
StrRetToStrW(&str1, info->pidl, &name1);
|
||||||
|
StrRetToStrW(&str2, pcidl, &name2);
|
||||||
|
int order = StrCmpW(name1, name2);
|
||||||
|
CoTaskMemFree(name1);
|
||||||
|
CoTaskMemFree(name2);
|
||||||
|
|
||||||
|
if (order == 0)
|
||||||
|
{
|
||||||
|
*pinfo = *info;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// FIXME: This works in windows.
|
||||||
|
hr = m_UserLocalFolder->CompareIDs(0, info.pidl, pcidl);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
*pinfo = info;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Comparison returned %d\n", (int) (short) (hr & 0xFFFF));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
LPWSTR name1;
|
||||||
|
LPWSTR name2;
|
||||||
|
STRRET str1 = { STRRET_WSTR, 0 };
|
||||||
|
STRRET str2 = { STRRET_WSTR, 0 };
|
||||||
|
hr = m_AllUSersFolder->GetDisplayNameOf(info->pidl, SHGDN_FORPARSING | SHGDN_INFOLDER, &str1);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
hr = m_AllUSersFolder->GetDisplayNameOf(pcidl, SHGDN_FORPARSING | SHGDN_INFOLDER, &str2);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
StrRetToStrW(&str1, info->pidl, &name1);
|
||||||
|
StrRetToStrW(&str2, pcidl, &name2);
|
||||||
|
int order = StrCmpW(name1, name2);
|
||||||
|
CoTaskMemFree(name1);
|
||||||
|
CoTaskMemFree(name2);
|
||||||
|
|
||||||
|
if (order == 0)
|
||||||
|
{
|
||||||
|
*pinfo = *info;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// FIXME: This works in windows.
|
||||||
|
hr = m_AllUSersFolder->CompareIDs(0, info.pidl, pcidl);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
*pinfo = info;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Comparison returned %d\n", (int) (short) (hr & 0xFFFF));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Pidl not found\n");
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Next(
|
||||||
|
ULONG celt,
|
||||||
|
LPITEMIDLIST *rgelt,
|
||||||
|
ULONG *pceltFetched)
|
||||||
|
{
|
||||||
|
if (pceltFetched) *pceltFetched = 0;
|
||||||
|
|
||||||
|
if (m_hDsaIndex == m_hDsaCount)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)celt;)
|
||||||
|
{
|
||||||
|
LocalPidlInfo * tinfo = (LocalPidlInfo *) DSA_GetItemPtr(m_hDsa, m_hDsaIndex);
|
||||||
|
if (!tinfo)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
LocalPidlInfo info = *tinfo;
|
||||||
|
|
||||||
|
TRACE("Returning next item at %d with side %d and pidl { cb=%d }\n", m_hDsaIndex, info.side, info.pidl->mkid.cb);
|
||||||
|
|
||||||
|
// FIXME: ILClone shouldn't be needed here! This should be causing leaks
|
||||||
|
if (rgelt) rgelt[i] = ILClone(info.pidl);
|
||||||
|
|
||||||
|
m_hDsaIndex++;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (m_hDsaIndex == m_hDsaCount)
|
||||||
|
{
|
||||||
|
if (pceltFetched) *pceltFetched = i;
|
||||||
|
return (i == (int)celt) ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pceltFetched) *pceltFetched = celt;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Skip(ULONG celt)
|
||||||
|
{
|
||||||
|
return Next(celt, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Reset()
|
||||||
|
{
|
||||||
|
m_hDsaIndex = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Clone(
|
||||||
|
IEnumIDList **ppenum)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// CMergedFolder
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
HRESULT WINAPI CMergedFolder_Constructor(IShellFolder* userLocal, IShellFolder* allUsers, REFIID riid, LPVOID *ppv)
|
HRESULT WINAPI CMergedFolder_Constructor(IShellFolder* userLocal, IShellFolder* allUsers, REFIID riid, LPVOID *ppv)
|
||||||
{
|
{
|
||||||
|
@ -148,7 +425,8 @@ HRESULT CMergedFolder::_SetSources(IShellFolder* userLocal, IShellFolder* allUse
|
||||||
{
|
{
|
||||||
m_UserLocal = userLocal;
|
m_UserLocal = userLocal;
|
||||||
m_AllUSers = allUsers;
|
m_AllUSers = allUsers;
|
||||||
return S_OK;
|
m_EnumSource = new CComObject<CEnumMergedFolder>();
|
||||||
|
return m_EnumSource->SetSources(m_UserLocal, m_AllUSers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IShellFolder
|
// IShellFolder
|
||||||
|
@ -169,9 +447,10 @@ HRESULT STDMETHODCALLTYPE CMergedFolder::EnumObjects(
|
||||||
SHCONTF grfFlags,
|
SHCONTF grfFlags,
|
||||||
IEnumIDList **ppenumIDList)
|
IEnumIDList **ppenumIDList)
|
||||||
{
|
{
|
||||||
CEnumMergedFolder * merged = new CComObject<CEnumMergedFolder>();
|
HRESULT hr = m_EnumSource->QueryInterface(IID_PPV_ARG(IEnumIDList, ppenumIDList));
|
||||||
*ppenumIDList = merged;
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return merged->Begin(hwndOwner, grfFlags, m_UserLocal, m_AllUSers);
|
return hr;
|
||||||
|
return m_EnumSource->Begin(hwndOwner, grfFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CMergedFolder::BindToObject(
|
HRESULT STDMETHODCALLTYPE CMergedFolder::BindToObject(
|
||||||
|
@ -180,15 +459,33 @@ HRESULT STDMETHODCALLTYPE CMergedFolder::BindToObject(
|
||||||
REFIID riid,
|
REFIID riid,
|
||||||
void **ppvOut)
|
void **ppvOut)
|
||||||
{
|
{
|
||||||
|
LocalPidlInfo info;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = m_UserLocal->BindToObject(pidl, pbcReserved, riid, ppvOut);
|
hr = m_EnumSource->FindPidlInList(pidl, &info);
|
||||||
if (SUCCEEDED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (info.side < 0)
|
||||||
|
return m_UserLocal->BindToObject(pidl, pbcReserved, riid, ppvOut);
|
||||||
|
if (info.side > 0)
|
||||||
|
return m_AllUSers->BindToObject(pidl, pbcReserved, riid, ppvOut);
|
||||||
|
|
||||||
|
if (riid != IID_IShellFolder)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
CComPtr<IShellFolder> fld1;
|
||||||
|
CComPtr<IShellFolder> fld2;
|
||||||
|
|
||||||
|
hr = m_UserLocal->BindToObject(pidl, pbcReserved, IID_PPV_ARG(IShellFolder, &fld1));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = m_AllUSers->BindToObject(pidl, pbcReserved, riid, ppvOut);
|
hr = m_AllUSers->BindToObject(pidl, pbcReserved, IID_PPV_ARG(IShellFolder, &fld2));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
return hr;
|
return CMergedFolder_Constructor(fld1, fld2, riid, ppvOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CMergedFolder::BindToStorage(
|
HRESULT STDMETHODCALLTYPE CMergedFolder::BindToStorage(
|
||||||
|
@ -206,8 +503,7 @@ HRESULT STDMETHODCALLTYPE CMergedFolder::CompareIDs(
|
||||||
LPCITEMIDLIST pidl1,
|
LPCITEMIDLIST pidl1,
|
||||||
LPCITEMIDLIST pidl2)
|
LPCITEMIDLIST pidl2)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
return m_UserLocal->CompareIDs(lParam, pidl1, pidl2);
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CMergedFolder::CreateViewObject(
|
HRESULT STDMETHODCALLTYPE CMergedFolder::CreateViewObject(
|
||||||
|
@ -224,16 +520,29 @@ HRESULT STDMETHODCALLTYPE CMergedFolder::GetAttributesOf(
|
||||||
LPCITEMIDLIST *apidl,
|
LPCITEMIDLIST *apidl,
|
||||||
SFGAOF *rgfInOut)
|
SFGAOF *rgfInOut)
|
||||||
{
|
{
|
||||||
|
LocalPidlInfo info;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = m_UserLocal->GetAttributesOf(cidl, apidl, rgfInOut);
|
for (int i = 0; i < (int)cidl; i++)
|
||||||
if (SUCCEEDED(hr))
|
{
|
||||||
return hr;
|
LPCITEMIDLIST pidl = apidl[i];
|
||||||
|
|
||||||
*rgfInOut = 0;
|
hr = m_EnumSource->FindPidlInList(pidl, &info);
|
||||||
hr = m_AllUSers->GetAttributesOf(cidl, apidl, rgfInOut);
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
return hr;
|
SFGAOF * pinOut1 = rgfInOut ? rgfInOut + i : NULL;
|
||||||
|
|
||||||
|
if (info.side <= 0)
|
||||||
|
hr = m_UserLocal->GetAttributesOf(1, &pidl, pinOut1);
|
||||||
|
else
|
||||||
|
hr = m_AllUSers->GetAttributesOf(1, &pidl, pinOut1);
|
||||||
|
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CMergedFolder::GetUIObjectOf(
|
HRESULT STDMETHODCALLTYPE CMergedFolder::GetUIObjectOf(
|
||||||
|
@ -244,15 +553,30 @@ HRESULT STDMETHODCALLTYPE CMergedFolder::GetUIObjectOf(
|
||||||
UINT *prgfInOut,
|
UINT *prgfInOut,
|
||||||
void **ppvOut)
|
void **ppvOut)
|
||||||
{
|
{
|
||||||
|
LocalPidlInfo info;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = m_UserLocal->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
|
for (int i = 0; i < (int)cidl; i++)
|
||||||
if (SUCCEEDED(hr))
|
{
|
||||||
return hr;
|
LPCITEMIDLIST pidl = apidl[i];
|
||||||
|
|
||||||
hr = m_AllUSers->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
|
hr = m_EnumSource->FindPidlInList(pidl, &info);
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
return hr;
|
UINT * pinOut1 = prgfInOut ? prgfInOut+i : NULL;
|
||||||
|
void** ppvOut1 = ppvOut ? ppvOut + i : NULL;
|
||||||
|
|
||||||
|
if (info.side <= 0)
|
||||||
|
hr = m_UserLocal->GetUIObjectOf(hwndOwner, 1, &pidl, riid, pinOut1, ppvOut1);
|
||||||
|
else
|
||||||
|
hr = m_AllUSers->GetUIObjectOf(hwndOwner, 1, &pidl, riid, pinOut1, ppvOut1);
|
||||||
|
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDisplayNameOf(
|
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDisplayNameOf(
|
||||||
|
@ -260,15 +584,21 @@ HRESULT STDMETHODCALLTYPE CMergedFolder::GetDisplayNameOf(
|
||||||
SHGDNF uFlags,
|
SHGDNF uFlags,
|
||||||
STRRET *lpName)
|
STRRET *lpName)
|
||||||
{
|
{
|
||||||
|
LocalPidlInfo info;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
hr = m_UserLocal->GetDisplayNameOf(pidl, uFlags, lpName);
|
hr = m_EnumSource->FindPidlInList(pidl, &info);
|
||||||
if (SUCCEEDED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = m_AllUSers->GetDisplayNameOf(pidl, uFlags, lpName);
|
if (info.side <= 0)
|
||||||
|
hr = m_UserLocal->GetDisplayNameOf(pidl, uFlags, lpName);
|
||||||
|
else
|
||||||
|
hr = m_AllUSers->GetDisplayNameOf(pidl, uFlags, lpName);
|
||||||
|
|
||||||
return hr;
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
return hr;
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CMergedFolder::SetNameOf(
|
HRESULT STDMETHODCALLTYPE CMergedFolder::SetNameOf(
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class CEnumMergedFolder;
|
||||||
|
|
||||||
class CMergedFolder :
|
class CMergedFolder :
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
public IShellFolder2
|
public IShellFolder2
|
||||||
|
@ -26,6 +28,7 @@ class CMergedFolder :
|
||||||
private:
|
private:
|
||||||
CComPtr<IShellFolder> m_UserLocal;
|
CComPtr<IShellFolder> m_UserLocal;
|
||||||
CComPtr<IShellFolder> m_AllUSers;
|
CComPtr<IShellFolder> m_AllUSers;
|
||||||
|
CComPtr<CEnumMergedFolder> m_EnumSource;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMergedFolder() {}
|
CMergedFolder() {}
|
||||||
|
|
|
@ -4716,8 +4716,18 @@ typedef struct {
|
||||||
_In_ PFNDSAENUMCALLBACK pfnCB,
|
_In_ PFNDSAENUMCALLBACK pfnCB,
|
||||||
_In_opt_ void *pData);
|
_In_opt_ void *pData);
|
||||||
|
|
||||||
|
WINCOMMCTRLAPI
|
||||||
|
VOID
|
||||||
|
WINAPI
|
||||||
|
DSA_EnumCallback(
|
||||||
|
_In_ HDSA hdsa,
|
||||||
|
_In_ PFNDSAENUMCALLBACK enumProc,
|
||||||
|
_In_opt_ LPVOID lParam);
|
||||||
|
|
||||||
WINCOMMCTRLAPI PVOID WINAPI DSA_GetItemPtr(_In_ HDSA hdsa, int i);
|
WINCOMMCTRLAPI PVOID WINAPI DSA_GetItemPtr(_In_ HDSA hdsa, int i);
|
||||||
|
|
||||||
|
WINCOMMCTRLAPI BOOL WINAPI DSA_DeleteAllItems(_In_ HDSA hdsa);
|
||||||
|
|
||||||
WINCOMMCTRLAPI
|
WINCOMMCTRLAPI
|
||||||
int
|
int
|
||||||
WINAPI
|
WINAPI
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue