2 * PROJECT: ReactOS Font Shell Extension
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: CFontMenu implementation
5 * COPYRIGHT: Copyright 2019,2020 Mark Jansen (mark.jansen@reactos.org)
10 WINE_DEFAULT_DEBUG_CHANNEL(fontext
);
14 static inline void DumpDataObjectFormats(IDataObject
* pObject
)
16 CComPtr
<IEnumFORMATETC
> pEnumFmt
;
17 HRESULT hr
= pObject
->EnumFormatEtc(DATADIR_GET
, &pEnumFmt
);
19 if (FAILED_UNEXPECTEDLY(hr
))
23 while (S_OK
== pEnumFmt
->Next(1, &fmt
, NULL
))
26 GetClipboardFormatNameA(fmt
.cfFormat
, szBuf
, sizeof(szBuf
));
27 ERR("Format: %s\n", szBuf
);
28 ERR("Tymed: %u\n", fmt
.tymed
);
29 if (fmt
.tymed
& TYMED_HGLOBAL
)
31 ERR("TYMED_HGLOBAL supported\n");
38 HRESULT
_CDataObject_CreateInstance(PCIDLIST_ABSOLUTE folder
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
39 REFIID riid
, LPVOID
* ppvOut
)
41 HRESULT hr
= CIDLData_CreateFromIDArray(folder
, cidl
, apidl
, (IDataObject
**)ppvOut
);
42 if (FAILED_UNEXPECTEDLY(hr
))
45 // Now that we have an IDataObject with the shell itemid list (CFSTR_SHELLIDLIST, aka HIDA) format
46 // we will augment this IDataObject with the CF_HDROP format. (Full filepaths)
47 // This enabled the objects for the 'copy' and drag to copy actions
49 CComHeapPtr
<BYTE
> data
;
51 // First we allocate room for the DROPFILES structure
52 data
.AllocateBytes(sizeof(DROPFILES
));
53 UINT offset
= sizeof(DROPFILES
);
55 // Then we walk all files
56 for (UINT n
= 0; n
< cidl
; ++n
)
58 const FontPidlEntry
* fontEntry
= _FontFromIL(apidl
[n
]);
61 CStringW File
= g_FontCache
->Filename(fontEntry
, true);
64 // Now append the path (+ nullterminator) to the buffer
65 UINT len
= offset
+ (File
.GetLength() + 1) * sizeof(WCHAR
);
66 data
.ReallocateBytes(len
);
69 ERR("Unable to allocate memory for the CF_HDROP\n");
73 StringCbCopyW((STRSAFE_LPWSTR
)(dataPtr
+ offset
), len
- offset
, File
);
78 ERR("No file found for %S\n", fontEntry
->Name
);
83 // Append the final nullterminator (double null terminated list)
84 data
.ReallocateBytes(offset
+ sizeof(UNICODE_NULL
));
85 LPWSTR str
= (LPWSTR
)((BYTE
*)data
+ offset
);
87 offset
+= sizeof(UNICODE_NULL
);
89 // Fill in the required fields
90 DROPFILES
* pDrop
= (DROPFILES
*)(BYTE
*)data
;
92 pDrop
->pFiles
= sizeof(DROPFILES
);
94 pDrop
->pt
.x
= pDrop
->pt
.y
= 0;
97 // Prepare the format descriptors
98 STGMEDIUM medium
= {0};
99 medium
.tymed
= TYMED_HGLOBAL
;
101 // Copy the data to an HGLOBAL
102 medium
.hGlobal
= GlobalAlloc(GHND
, offset
);
105 LPVOID blob
= GlobalLock(medium
.hGlobal
);
108 CopyMemory(blob
, (BYTE
*)data
, offset
);
109 GlobalUnlock(medium
.hGlobal
);
111 CComPtr
<IDataObject
> spDataObject(*(IDataObject
**)ppvOut
);
114 FORMATETC etc
= { CF_HDROP
, NULL
, DVASPECT_CONTENT
, -1, TYMED_HGLOBAL
};
115 hr
= spDataObject
->SetData(&etc
, &medium
, TRUE
);
120 ERR("Unable to lock the hGlobal?!\n");
125 ERR("Unable to allocate %u bytes for the hGlobal\n", offset
);