1e5ea6041SMark Jansen /*
2e5ea6041SMark Jansen * PROJECT: shell32
3e5ea6041SMark Jansen * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4e5ea6041SMark Jansen * PURPOSE: SHGetAttributesFromDataObject implementation
5e5ea6041SMark Jansen * COPYRIGHT: Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
6e5ea6041SMark Jansen */
7e5ea6041SMark Jansen
8e5ea6041SMark Jansen
9e5ea6041SMark Jansen #include "precomp.h"
10e5ea6041SMark Jansen
11e5ea6041SMark Jansen WINE_DEFAULT_DEBUG_CHANNEL(shell);
12e5ea6041SMark Jansen
13e5ea6041SMark Jansen
14e5ea6041SMark Jansen static CLIPFORMAT g_DataObjectAttributes = 0;
15e5ea6041SMark Jansen static const DWORD dwDefaultAttributeMask = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_STORAGE | SFGAO_CANRENAME |
16e5ea6041SMark Jansen SFGAO_CANDELETE | SFGAO_READONLY | SFGAO_STREAM | SFGAO_FOLDER;
17e5ea6041SMark Jansen
18e5ea6041SMark Jansen struct DataObjectAttributes
19e5ea6041SMark Jansen {
20e5ea6041SMark Jansen DWORD dwMask;
21e5ea6041SMark Jansen DWORD dwAttributes;
22e5ea6041SMark Jansen UINT cItems;
23e5ea6041SMark Jansen };
24e5ea6041SMark Jansen
25e5ea6041SMark Jansen static_assert(sizeof(DataObjectAttributes) == 0xc, "Unexpected struct size!");
26e5ea6041SMark Jansen
27e5ea6041SMark Jansen
28e5ea6041SMark Jansen static
_BindToObject(PCUIDLIST_ABSOLUTE pidl,CComPtr<IShellFolder> & spFolder)29e5ea6041SMark Jansen HRESULT _BindToObject(PCUIDLIST_ABSOLUTE pidl, CComPtr<IShellFolder>& spFolder)
30e5ea6041SMark Jansen {
31*fa95a96eSWhindmar Saksit return SHBindToObject(NULL, pidl, IID_PPV_ARG(IShellFolder, &spFolder));
32e5ea6041SMark Jansen }
33e5ea6041SMark Jansen
34e5ea6041SMark Jansen EXTERN_C
SHGetAttributesFromDataObject(IDataObject * pDataObject,DWORD dwAttributeMask,DWORD * pdwAttributes,UINT * pcItems)35e5ea6041SMark Jansen HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject* pDataObject, DWORD dwAttributeMask, DWORD* pdwAttributes, UINT* pcItems)
36e5ea6041SMark Jansen {
37e5ea6041SMark Jansen DWORD dwAttributes = 0;
38e5ea6041SMark Jansen DWORD cItems = 0;
39e5ea6041SMark Jansen HRESULT hr = S_OK;
40e5ea6041SMark Jansen
41e5ea6041SMark Jansen TRACE("(%p, 0x%x, %p, %p)\n", pDataObject, dwAttributeMask, pdwAttributes, pcItems);
42e5ea6041SMark Jansen
43e5ea6041SMark Jansen if (!g_DataObjectAttributes)
44e5ea6041SMark Jansen g_DataObjectAttributes = (CLIPFORMAT)RegisterClipboardFormatW(L"DataObjectAttributes");
45e5ea6041SMark Jansen
46e5ea6041SMark Jansen if (pDataObject)
47e5ea6041SMark Jansen {
48e5ea6041SMark Jansen DataObjectAttributes data = {};
49e5ea6041SMark Jansen if (FAILED(DataObject_GetData(pDataObject, g_DataObjectAttributes, &data, sizeof(data))))
50e5ea6041SMark Jansen {
51e5ea6041SMark Jansen TRACE("No attributes yet, creating new\n");
52e5ea6041SMark Jansen memset(&data, 0, sizeof(data));
53e5ea6041SMark Jansen }
54e5ea6041SMark Jansen
55e5ea6041SMark Jansen DWORD dwQueryAttributes = dwAttributeMask | dwDefaultAttributeMask;
56e5ea6041SMark Jansen
57e5ea6041SMark Jansen if ((data.dwMask & dwQueryAttributes) != dwQueryAttributes)
58e5ea6041SMark Jansen {
59e5ea6041SMark Jansen CDataObjectHIDA hida(pDataObject);
60e5ea6041SMark Jansen CComPtr<IShellFolder> spFolder;
61e5ea6041SMark Jansen
62e5ea6041SMark Jansen if (!FAILED_UNEXPECTEDLY(hr = hida.hr()) &&
63e5ea6041SMark Jansen !FAILED_UNEXPECTEDLY(hr = _BindToObject(HIDA_GetPIDLFolder(hida), spFolder)))
64e5ea6041SMark Jansen {
65e5ea6041SMark Jansen CSimpleArray<PCUIDLIST_RELATIVE> apidl;
66e5ea6041SMark Jansen for (UINT n = 0; n < hida->cidl; ++n)
67e5ea6041SMark Jansen {
68e5ea6041SMark Jansen apidl.Add(HIDA_GetPIDLItem(hida, n));
69e5ea6041SMark Jansen }
70e5ea6041SMark Jansen
71e5ea6041SMark Jansen SFGAOF rgfInOut = dwQueryAttributes;
72e5ea6041SMark Jansen hr = spFolder->GetAttributesOf(apidl.GetSize(), apidl.GetData(), &rgfInOut);
73e5ea6041SMark Jansen if (!FAILED_UNEXPECTEDLY(hr))
74e5ea6041SMark Jansen {
75e5ea6041SMark Jansen data.dwMask = dwQueryAttributes;
76e5ea6041SMark Jansen // Only store what we asked for
77e5ea6041SMark Jansen data.dwAttributes = rgfInOut & dwQueryAttributes;
78e5ea6041SMark Jansen data.cItems = apidl.GetSize();
79e5ea6041SMark Jansen
80e5ea6041SMark Jansen hr = DataObject_SetData(pDataObject, g_DataObjectAttributes, &data, sizeof(data));
81e5ea6041SMark Jansen FAILED_UNEXPECTEDLY(hr);
82e5ea6041SMark Jansen }
83e5ea6041SMark Jansen }
84e5ea6041SMark Jansen }
85e5ea6041SMark Jansen
86e5ea6041SMark Jansen // Only give the user what they asked for, not everything else we have!
87e5ea6041SMark Jansen dwAttributes = data.dwAttributes & dwAttributeMask;
88e5ea6041SMark Jansen cItems = data.cItems;
89e5ea6041SMark Jansen }
90e5ea6041SMark Jansen
91e5ea6041SMark Jansen if (pdwAttributes)
92e5ea6041SMark Jansen *pdwAttributes = dwAttributes;
93e5ea6041SMark Jansen
94e5ea6041SMark Jansen if (pcItems)
95e5ea6041SMark Jansen *pcItems = cItems;
96e5ea6041SMark Jansen
97e5ea6041SMark Jansen return hr;
98e5ea6041SMark Jansen }
99d24675b6SWhindmar Saksit
SHELL_CIDA_ILCloneFull(_In_ const CIDA * pCIDA,_In_ UINT Index)100d24675b6SWhindmar Saksit PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index)
101d24675b6SWhindmar Saksit {
102d24675b6SWhindmar Saksit if (Index < pCIDA->cidl)
103d24675b6SWhindmar Saksit return ILCombine(HIDA_GetPIDLFolder(pCIDA), HIDA_GetPIDLItem(pCIDA, Index));
104d24675b6SWhindmar Saksit return NULL;
105d24675b6SWhindmar Saksit }
106d24675b6SWhindmar Saksit
SHELL_DataObject_ILCloneFullItem(_In_ IDataObject * pDO,_In_ UINT Index)107d24675b6SWhindmar Saksit PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index)
108d24675b6SWhindmar Saksit {
109d24675b6SWhindmar Saksit CDataObjectHIDA cida(pDO);
110d24675b6SWhindmar Saksit return SUCCEEDED(cida.hr()) ? SHELL_CIDA_ILCloneFull(cida, Index) : NULL;
111d24675b6SWhindmar Saksit }
112