xref: /reactos/dll/win32/shell32/shldataobject.cpp (revision fa95a96e)
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