mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:15:58 +00:00
[SHELL32] Multiple drives property sheet support (#7787)
Supports multiple drives in a single property sheet CORE-20025
This commit is contained in:
parent
d769f5675d
commit
7f49ae633b
8 changed files with 163 additions and 53 deletions
|
@ -689,11 +689,39 @@ CDrvDefExt::~CDrvDefExt()
|
|||
|
||||
}
|
||||
|
||||
struct CDrop
|
||||
{
|
||||
HRESULT hr;
|
||||
STGMEDIUM stgm;
|
||||
HDROP hDrop;
|
||||
|
||||
explicit CDrop(IDataObject *pDO)
|
||||
{
|
||||
FORMATETC format = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
hDrop = SUCCEEDED(hr = pDO->GetData(&format, &stgm)) ? (HDROP)stgm.hGlobal : NULL;
|
||||
}
|
||||
|
||||
~CDrop()
|
||||
{
|
||||
if (hDrop)
|
||||
ReleaseStgMedium(&stgm);
|
||||
}
|
||||
|
||||
UINT GetCount()
|
||||
{
|
||||
return DragQueryFileW(hDrop, -1, NULL, 0);
|
||||
}
|
||||
};
|
||||
|
||||
static inline bool
|
||||
IsValidDrivePath(PCWSTR Path)
|
||||
{
|
||||
return GetDriveTypeW(Path) > DRIVE_NO_ROOT_DIR;
|
||||
}
|
||||
|
||||
HRESULT WINAPI
|
||||
CDrvDefExt::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pDataObj, HKEY hkeyProgID)
|
||||
{
|
||||
FORMATETC format;
|
||||
STGMEDIUM stgm;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p %p %p %p\n", this, pidlFolder, pDataObj, hkeyProgID);
|
||||
|
@ -701,24 +729,20 @@ CDrvDefExt::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pDataObj, HKEY
|
|||
if (!pDataObj)
|
||||
return E_FAIL;
|
||||
|
||||
format.cfFormat = CF_HDROP;
|
||||
format.ptd = NULL;
|
||||
format.dwAspect = DVASPECT_CONTENT;
|
||||
format.lindex = -1;
|
||||
format.tymed = TYMED_HGLOBAL;
|
||||
|
||||
hr = pDataObj->GetData(&format, &stgm);
|
||||
if (FAILED(hr))
|
||||
CDrop drop(pDataObj);
|
||||
if (FAILED_UNEXPECTEDLY(hr = drop.hr))
|
||||
return hr;
|
||||
|
||||
if (!DragQueryFileW((HDROP)stgm.hGlobal, 0, m_wszDrive, _countof(m_wszDrive)))
|
||||
if (!DragQueryFileW(drop.hDrop, 0, m_wszDrive, _countof(m_wszDrive)))
|
||||
{
|
||||
ERR("DragQueryFileW failed\n");
|
||||
ReleaseStgMedium(&stgm);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
ReleaseStgMedium(&stgm);
|
||||
if (drop.GetCount() > 1)
|
||||
m_Multiple = pDataObj;
|
||||
|
||||
TRACE("Drive properties %ls\n", m_wszDrive);
|
||||
|
||||
return S_OK;
|
||||
|
@ -745,37 +769,75 @@ CDrvDefExt::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI
|
||||
CDrvDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
HRESULT
|
||||
CDrvDefExt::AddMainPage(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
HPROPSHEETPAGE hPage;
|
||||
WCHAR szTitle[MAX_PATH], *pszTitle = NULL;
|
||||
if (m_Multiple)
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidl(SHSimpleIDListFromPathW(m_wszDrive));
|
||||
if (SUCCEEDED(SHGetNameAndFlagsW(pidl, SHGDN_INFOLDER, szTitle, _countof(szTitle), NULL)))
|
||||
pszTitle = szTitle;
|
||||
}
|
||||
|
||||
HPROPSHEETPAGE hPage;
|
||||
hPage = SH_CreatePropertySheetPageEx(IDD_DRIVE_PROPERTIES, GeneralPageProc, (LPARAM)this,
|
||||
NULL, &PropSheetPageLifetimeCallback<CDrvDefExt>);
|
||||
pszTitle, &PropSheetPageLifetimeCallback<CDrvDefExt>);
|
||||
HRESULT hr = AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
else
|
||||
AddRef(); // For PropSheetPageLifetimeCallback
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (GetDriveTypeW(m_wszDrive) == DRIVE_FIXED)
|
||||
HRESULT WINAPI
|
||||
CDrvDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
HRESULT hr = AddMainPage(pfnAddPage, lParam);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (m_Multiple)
|
||||
{
|
||||
hPage = SH_CreatePropertySheetPage(IDD_DRIVE_TOOLS,
|
||||
ExtraPageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
CDrop drop(m_Multiple);
|
||||
UINT count = SUCCEEDED(drop.hr) ? drop.GetCount() : 0;
|
||||
for (UINT i = 0; ++i < count;) // Skipping the first drive since it already has a page
|
||||
{
|
||||
CComPtr<CDrvDefExt> SheetExt;
|
||||
if (FAILED_UNEXPECTEDLY(hr = ShellObjectCreator(SheetExt)))
|
||||
continue;
|
||||
if (!DragQueryFileW(drop.hDrop, i, SheetExt->m_wszDrive, _countof(SheetExt->m_wszDrive)))
|
||||
continue;
|
||||
if (!IsValidDrivePath(SheetExt->m_wszDrive))
|
||||
continue;
|
||||
|
||||
SheetExt->m_Multiple = m_Multiple;
|
||||
SheetExt->AddMainPage(pfnAddPage, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetDriveTypeW(m_wszDrive) != DRIVE_REMOTE)
|
||||
else
|
||||
{
|
||||
hPage = SH_CreatePropertySheetPage(IDD_DRIVE_HARDWARE,
|
||||
HardwarePageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
HPROPSHEETPAGE hPage;
|
||||
if (GetDriveTypeW(m_wszDrive) == DRIVE_FIXED)
|
||||
{
|
||||
hPage = SH_CreatePropertySheetPage(IDD_DRIVE_TOOLS,
|
||||
ExtraPageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
}
|
||||
|
||||
if (GetDriveTypeW(m_wszDrive) != DRIVE_REMOTE)
|
||||
{
|
||||
hPage = SH_CreatePropertySheetPage(IDD_DRIVE_HARDWARE,
|
||||
HardwarePageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
|
|
@ -38,6 +38,9 @@ private:
|
|||
|
||||
WCHAR m_wszDrive[MAX_PATH];
|
||||
UINT m_FreeSpacePerc;
|
||||
CComPtr<IDataObject> m_Multiple;
|
||||
|
||||
HRESULT AddMainPage(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
|
||||
|
||||
public:
|
||||
CDrvDefExt();
|
||||
|
|
|
@ -17,6 +17,9 @@ SHELL_GetCaptionFromDataObject(IDataObject *pDO, LPWSTR Buf, UINT cchBuf)
|
|||
{
|
||||
hr = SHGetNameAndFlagsW(pidl, SHGDN_INFOLDER, Buf, cchBuf, NULL);
|
||||
ILFree(pidl);
|
||||
|
||||
if (SUCCEEDED(hr) && DataObject_GetHIDACount(pDO) > 1)
|
||||
StringCchCatW(Buf, cchBuf, L", ...");
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
@ -130,7 +133,15 @@ FSFolderItemPropDialogInitCallback(LPCWSTR InitString, IDataObject *pDO, HKEY *h
|
|||
CDataObjectHIDA cida(pDO);
|
||||
if (SUCCEEDED(cida.hr()) && cida->cidl)
|
||||
{
|
||||
#if 0
|
||||
CCidaChildArrayHelper items(cida);
|
||||
if (FAILED(hr = items.hr()))
|
||||
return hr;
|
||||
#else
|
||||
// Note: Since we are only passing a single item to AddFSClassKeysToArray,
|
||||
// we don't need the rest of the array to be valid.
|
||||
PCUITEMID_CHILD pidl = HIDA_GetPIDLItem(cida, 0);
|
||||
#endif
|
||||
AddFSClassKeysToArray(1, &pidl, hKeys, cKeys); // Add file-type specific pages
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +165,7 @@ SHELL32_ShowFilesystemItemPropertiesDialogAsync(IDataObject *pDO)
|
|||
ShellPropSheetDialog::PFNINITIALIZE InitFunc = NULL;
|
||||
LPCWSTR InitString = NULL;
|
||||
|
||||
if (_ILIsDrive(HIDA_GetPIDLItem(cida, 0)))
|
||||
if (cida->cidl && _ILIsDrive(HIDA_GetPIDLItem(cida, 0)))
|
||||
{
|
||||
pClsid = &CLSID_ShellDrvDefExt;
|
||||
InitFunc = ClassPropDialogInitCallback;
|
||||
|
@ -169,6 +180,18 @@ SHELL32_ShowFilesystemItemPropertiesDialogAsync(IDataObject *pDO)
|
|||
return Dialog.ShowAsync(pClsid, pDO, InitFunc, InitString);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL32_ShowFilesystemItemsPropertiesDialogAsync(HWND hOwner, IDataObject *pDO)
|
||||
{
|
||||
if (DataObject_GetHIDACount(pDO) == 1)
|
||||
return SHELL32_ShowFilesystemItemPropertiesDialogAsync(pDO);
|
||||
|
||||
ERR("SHMultiFileProperties is not implemented yet\n");
|
||||
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
SHELL_ErrorBox(hOwner, hr);
|
||||
return hr; // TODO: return SHMultiFileProperties(pDO, 0);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL32_ShowShellExtensionProperties(const CLSID *pClsid, IDataObject *pDO)
|
||||
{
|
||||
|
|
|
@ -172,6 +172,8 @@ SHELL32_ShowPropertiesDialog(IDataObject *pdtobj);
|
|||
HRESULT
|
||||
SHELL32_ShowFilesystemItemPropertiesDialogAsync(IDataObject *pDO);
|
||||
HRESULT
|
||||
SHELL32_ShowFilesystemItemsPropertiesDialogAsync(HWND hOwner, IDataObject *pDO);
|
||||
HRESULT
|
||||
SHELL32_ShowShellExtensionProperties(const CLSID *pClsid, IDataObject *pDO);
|
||||
HRESULT
|
||||
SHELL_ShowItemIDListProperties(LPCITEMIDLIST pidl);
|
||||
|
@ -296,6 +298,7 @@ BOOL PathIsDosDevice(_In_ LPCWSTR pszName);
|
|||
HRESULT SHELL32_GetDllFromRundll32CommandLine(LPCWSTR pszCmd, LPWSTR pszOut, SIZE_T cchMax);
|
||||
HRESULT SHILAppend(_Inout_ LPITEMIDLIST pidl, _Inout_ LPITEMIDLIST *ppidl);
|
||||
|
||||
HRESULT DataObject_GetHIDACount(IDataObject *pdo);
|
||||
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index);
|
||||
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index);
|
||||
HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO);
|
||||
|
|
|
@ -98,6 +98,15 @@ HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject* pDataObject, DWORD dwA
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DataObject_GetHIDACount(IDataObject *pdo)
|
||||
{
|
||||
if (!pdo)
|
||||
return E_INVALIDARG;
|
||||
CDataObjectHIDA cida(pdo);
|
||||
HRESULT hr = cida.hr();
|
||||
return SUCCEEDED(hr) ? cida->cidl : hr;
|
||||
}
|
||||
|
||||
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index)
|
||||
{
|
||||
if (Index < pCIDA->cidl)
|
||||
|
@ -120,8 +129,10 @@ HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO)
|
|||
HRESULT hr = cida.hr();
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PCUITEMID_CHILD items = HIDA_GetPIDLItem(cida, 0);
|
||||
hr = SHCreateFileDataObject(HIDA_GetPIDLFolder(cida), cida->cidl, &items, NULL, ppDO);
|
||||
CCidaChildArrayHelper items(cida);
|
||||
if (FAILED(hr = items.hr()))
|
||||
return hr;
|
||||
hr = SHCreateFileDataObject(HIDA_GetPIDLFolder(cida), cida->cidl, items.GetItems(), NULL, ppDO);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
POINT pt;
|
||||
|
|
|
@ -509,16 +509,7 @@ SHELL32_ShowPropertiesDialog(IDataObject *pdtobj)
|
|||
{
|
||||
if (!pdtobj)
|
||||
return E_INVALIDARG;
|
||||
|
||||
CDataObjectHIDA cida(pdtobj);
|
||||
if (FAILED_UNEXPECTEDLY(cida.hr()))
|
||||
return cida.hr();
|
||||
if (cida->cidl > 1)
|
||||
{
|
||||
ERR("SHMultiFileProperties is not yet implemented\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
return SHELL32_ShowFilesystemItemPropertiesDialogAsync(pdtobj);
|
||||
return SHELL32_ShowFilesystemItemsPropertiesDialogAsync(NULL, pdtobj);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
|
|
@ -84,15 +84,6 @@ SHParseDarwinIDFromCacheW(LPCWSTR lpUnknown1, LPWSTR lpUnknown2)
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT DataObject_GetHIDACount(IDataObject *pdo)
|
||||
{
|
||||
if (!pdo)
|
||||
return E_INVALIDARG;
|
||||
CDataObjectHIDA cida(pdo);
|
||||
HRESULT hr = cida.hr();
|
||||
return SUCCEEDED(hr) ? cida->cidl : hr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unimplemented
|
||||
*/
|
||||
|
|
|
@ -91,6 +91,7 @@ SHELL_CreateFallbackExtractIconForNoAssocFile(REFIID riid, LPVOID *ppvOut)
|
|||
return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct ClipboardViewerChain
|
||||
{
|
||||
HWND m_hWndNext = HWND_BOTTOM;
|
||||
|
@ -124,3 +125,28 @@ struct ClipboardViewerChain
|
|||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct CCidaChildArrayHelper
|
||||
{
|
||||
// Note: This just creates an array pointing to the items and has the same lifetime as the CIDA.
|
||||
// Use _ILCopyCidaToaPidl if you need the items to outlive the CIDA!
|
||||
explicit CCidaChildArrayHelper(const CIDA *pCida)
|
||||
{
|
||||
m_hr = E_OUTOFMEMORY;
|
||||
m_array = (PCUIDLIST_RELATIVE_ARRAY)SHAlloc(pCida->cidl * sizeof(LPITEMIDLIST));
|
||||
if (m_array)
|
||||
{
|
||||
m_hr = S_OK;
|
||||
for (UINT i = 0; i < pCida->cidl; ++i)
|
||||
*(LPITEMIDLIST*)(&m_array[i]) = (LPITEMIDLIST)HIDA_GetPIDLItem(pCida, i);
|
||||
}
|
||||
}
|
||||
~CCidaChildArrayHelper() { SHFree((LPITEMIDLIST*)m_array); }
|
||||
|
||||
HRESULT hr() const { return m_hr; }
|
||||
PCUIDLIST_RELATIVE_ARRAY GetItems() const { return m_array; }
|
||||
|
||||
HRESULT m_hr;
|
||||
PCUIDLIST_RELATIVE_ARRAY m_array;
|
||||
};
|
||||
#endif // __cplusplus
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue