mirror of
https://github.com/reactos/reactos.git
synced 2024-11-19 21:48:10 +00:00
104 lines
3.2 KiB
C++
104 lines
3.2 KiB
C++
|
/*
|
||
|
* PROJECT: shell32
|
||
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||
|
* PURPOSE: SHGetAttributesFromDataObject implementation
|
||
|
* COPYRIGHT: Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||
|
|
||
|
|
||
|
static CLIPFORMAT g_DataObjectAttributes = 0;
|
||
|
static const DWORD dwDefaultAttributeMask = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_STORAGE | SFGAO_CANRENAME |
|
||
|
SFGAO_CANDELETE | SFGAO_READONLY | SFGAO_STREAM | SFGAO_FOLDER;
|
||
|
|
||
|
struct DataObjectAttributes
|
||
|
{
|
||
|
DWORD dwMask;
|
||
|
DWORD dwAttributes;
|
||
|
UINT cItems;
|
||
|
};
|
||
|
|
||
|
static_assert(sizeof(DataObjectAttributes) == 0xc, "Unexpected struct size!");
|
||
|
|
||
|
|
||
|
static
|
||
|
HRESULT _BindToObject(PCUIDLIST_ABSOLUTE pidl, CComPtr<IShellFolder>& spFolder)
|
||
|
{
|
||
|
CComPtr<IShellFolder> spDesktop;
|
||
|
HRESULT hr = SHGetDesktopFolder(&spDesktop);
|
||
|
if (FAILED(hr))
|
||
|
return hr;
|
||
|
|
||
|
return spDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &spFolder));
|
||
|
}
|
||
|
|
||
|
EXTERN_C
|
||
|
HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject* pDataObject, DWORD dwAttributeMask, DWORD* pdwAttributes, UINT* pcItems)
|
||
|
{
|
||
|
DWORD dwAttributes = 0;
|
||
|
DWORD cItems = 0;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
TRACE("(%p, 0x%x, %p, %p)\n", pDataObject, dwAttributeMask, pdwAttributes, pcItems);
|
||
|
|
||
|
if (!g_DataObjectAttributes)
|
||
|
g_DataObjectAttributes = (CLIPFORMAT)RegisterClipboardFormatW(L"DataObjectAttributes");
|
||
|
|
||
|
if (pDataObject)
|
||
|
{
|
||
|
DataObjectAttributes data = {};
|
||
|
if (FAILED(DataObject_GetData(pDataObject, g_DataObjectAttributes, &data, sizeof(data))))
|
||
|
{
|
||
|
TRACE("No attributes yet, creating new\n");
|
||
|
memset(&data, 0, sizeof(data));
|
||
|
}
|
||
|
|
||
|
DWORD dwQueryAttributes = dwAttributeMask | dwDefaultAttributeMask;
|
||
|
|
||
|
if ((data.dwMask & dwQueryAttributes) != dwQueryAttributes)
|
||
|
{
|
||
|
CDataObjectHIDA hida(pDataObject);
|
||
|
CComPtr<IShellFolder> spFolder;
|
||
|
|
||
|
if (!FAILED_UNEXPECTEDLY(hr = hida.hr()) &&
|
||
|
!FAILED_UNEXPECTEDLY(hr = _BindToObject(HIDA_GetPIDLFolder(hida), spFolder)))
|
||
|
{
|
||
|
CSimpleArray<PCUIDLIST_RELATIVE> apidl;
|
||
|
for (UINT n = 0; n < hida->cidl; ++n)
|
||
|
{
|
||
|
apidl.Add(HIDA_GetPIDLItem(hida, n));
|
||
|
}
|
||
|
|
||
|
SFGAOF rgfInOut = dwQueryAttributes;
|
||
|
hr = spFolder->GetAttributesOf(apidl.GetSize(), apidl.GetData(), &rgfInOut);
|
||
|
if (!FAILED_UNEXPECTEDLY(hr))
|
||
|
{
|
||
|
data.dwMask = dwQueryAttributes;
|
||
|
// Only store what we asked for
|
||
|
data.dwAttributes = rgfInOut & dwQueryAttributes;
|
||
|
data.cItems = apidl.GetSize();
|
||
|
|
||
|
hr = DataObject_SetData(pDataObject, g_DataObjectAttributes, &data, sizeof(data));
|
||
|
FAILED_UNEXPECTEDLY(hr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Only give the user what they asked for, not everything else we have!
|
||
|
dwAttributes = data.dwAttributes & dwAttributeMask;
|
||
|
cItems = data.cItems;
|
||
|
}
|
||
|
|
||
|
if (pdwAttributes)
|
||
|
*pdwAttributes = dwAttributes;
|
||
|
|
||
|
if (pcItems)
|
||
|
*pcItems = cItems;
|
||
|
|
||
|
return hr;
|
||
|
}
|