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 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
48 WCHAR FontsDir
[MAX_PATH
];
49 hr
= SHGetFolderPathW(NULL
, CSIDL_FONTS
, NULL
, 0, FontsDir
);
50 if (FAILED_UNEXPECTEDLY(hr
))
52 StringCchCatW(FontsDir
, _countof(FontsDir
), L
"\\");
54 CComHeapPtr
<BYTE
> data
;
56 // First we allocate room for the DROPFILES structure
57 data
.AllocateBytes(sizeof(DROPFILES
));
58 UINT offset
= sizeof(DROPFILES
);
60 // Then we walk all files
61 for (UINT n
= 0; n
< cidl
; ++n
)
63 const FontPidlEntry
* fontEntry
= _FontFromIL(apidl
[n
]);
66 CStringW File
= g_FontCache
->Filename(fontEntry
);
69 // Ensure this is a full path
70 if (PathIsRelativeW(File
))
72 File
= FontsDir
+ File
;
75 // Now append the path (+ nullterminator) to the buffer
76 UINT len
= offset
+ (File
.GetLength() + 1) * sizeof(WCHAR
);
77 data
.ReallocateBytes(len
);
80 ERR("Unable to allocate memory for the CF_HDROP\n");
84 StringCbCopyW((STRSAFE_LPWSTR
)(dataPtr
+ offset
), len
- offset
, File
);
89 ERR("No file found for %S\n", fontEntry
->Name
);
94 // Append the final nullterminator (double null terminated list)
95 data
.ReallocateBytes(offset
+ sizeof(UNICODE_NULL
));
96 LPWSTR str
= (LPWSTR
)((BYTE
*)data
+ offset
);
98 offset
+= sizeof(UNICODE_NULL
);
100 // Fill in the required fields
101 DROPFILES
* pDrop
= (DROPFILES
*)(BYTE
*)data
;
103 pDrop
->pFiles
= sizeof(DROPFILES
);
105 pDrop
->pt
.x
= pDrop
->pt
.y
= 0;
108 // Prepare the format descriptors
109 STGMEDIUM medium
= {0};
110 medium
.tymed
= TYMED_HGLOBAL
;
112 // Copy the data to an HGLOBAL
113 medium
.hGlobal
= GlobalAlloc(GHND
, offset
);
116 LPVOID blob
= GlobalLock(medium
.hGlobal
);
119 CopyMemory(blob
, (BYTE
*)data
, offset
);
120 GlobalUnlock(medium
.hGlobal
);
122 CComPtr
<IDataObject
> spDataObject(*(IDataObject
**)ppvOut
);
125 FORMATETC etc
= { CF_HDROP
, NULL
, DVASPECT_CONTENT
, -1, TYMED_HGLOBAL
};
126 hr
= spDataObject
->SetData(&etc
, &medium
, TRUE
);
131 ERR("Unable to lock the hGlobal?!\n");
136 ERR("Unable to allocate %u bytes for the hGlobal\n", offset
);