comparison foosdk/sdk/libPPUI/IDataObjectUtils.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #pragma once
2
3 #include <shlobj.h>
4 #include <ShlDisp.h> // IAsyncOperation
5 #include "pp-COM-macros.h"
6
7 namespace IDataObjectUtils {
8
9 class ReleaseStgMediumScope {
10 public:
11 ReleaseStgMediumScope(STGMEDIUM * medium) : m_medium(medium) {}
12 ~ReleaseStgMediumScope() {if (m_medium != NULL) ReleaseStgMedium(m_medium);}
13 private:
14 STGMEDIUM * m_medium;
15
16 PFC_CLASS_NOT_COPYABLE_EX(ReleaseStgMediumScope)
17 };
18
19 static constexpr DWORD DataBlockToSTGMEDIUM_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL;
20 static constexpr DWORD ExtractDataObjectContent_SupportedTymeds = TYMED_ISTREAM | TYMED_HGLOBAL;
21
22 HRESULT DataBlockToSTGMEDIUM(const void * blockPtr, t_size blockSize, STGMEDIUM * medium, DWORD tymed, bool bHere) throw();
23
24 HGLOBAL HGlobalFromMemblock(const void * ptr,t_size size);
25
26 HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, pfc::array_t<t_uint8> & out);
27 HRESULT ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, pfc::array_t<t_uint8> & out);
28
29 HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index);
30 HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format);
31
32 HRESULT ExtractDataObjectString(pfc::com_ptr_t<IDataObject> obj, pfc::string_base & out);
33 HRESULT SetDataObjectString(pfc::com_ptr_t<IDataObject> obj, const char * str);
34
35 HRESULT SetDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, const void * data, t_size dataSize);
36
37 HRESULT STGMEDIUMToDataBlock(const STGMEDIUM & med, pfc::array_t<t_uint8> & out);
38
39 HRESULT ExtractDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD & val);
40 HRESULT SetDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD val);
41
42 HRESULT PasteSucceeded(pfc::com_ptr_t<IDataObject> obj, DWORD effect);
43
44 class comparator_FORMATETC {
45 public:
46 static int compare(const FORMATETC & v1, const FORMATETC & v2) {
47 int val;
48 val = pfc::compare_t(v1.cfFormat,v2.cfFormat); if (val != 0) return val;
49 val = pfc::compare_t(v1.dwAspect,v2.dwAspect); if (val != 0) return val;
50 val = pfc::compare_t(v1.lindex, v2.lindex ); if (val != 0) return val;
51 return 0;
52 }
53 };
54
55 class CDataObjectBase : public IDataObject {
56 public:
57 COM_QI_SIMPLE(IDataObject)
58
59 HRESULT STDMETHODCALLTYPE GetData(FORMATETC * formatetc, STGMEDIUM * medium) override {
60 return GetData_internal(formatetc,medium,false);
61 }
62
63 HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC * formatetc, STGMEDIUM * medium) override {
64 return GetData_internal(formatetc,medium,true);
65 }
66
67 HRESULT STDMETHODCALLTYPE QueryGetData(FORMATETC * formatetc) override {
68 if (formatetc == NULL) return E_INVALIDARG;
69
70 if ((DataBlockToSTGMEDIUM_SupportedTymeds & formatetc->tymed) == 0) return DV_E_TYMED;
71
72 try {
73 return RenderDataTest(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex);
74 } PP_COM_CATCH;
75 }
76
77
78 HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(FORMATETC * in, FORMATETC * out) override {
79 //check this again
80 if (in == NULL || out == NULL)
81 return E_INVALIDARG;
82 *out = *in;
83 return DATA_S_SAMEFORMATETC;
84 }
85
86 HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD dwDirection,IEnumFORMATETC ** ppenumFormatetc) override {
87 if (dwDirection == DATADIR_GET) {
88 if (ppenumFormatetc == NULL) return E_INVALIDARG;
89 return CreateIEnumFORMATETC(ppenumFormatetc);
90 } else if (dwDirection == DATADIR_SET) {
91 return E_NOTIMPL;
92 } else {
93 return E_INVALIDARG;
94 }
95 }
96
97 HRESULT STDMETHODCALLTYPE SetData(FORMATETC * pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) override {
98 try {
99 ReleaseStgMediumScope relScope(fRelease ? pmedium : NULL);
100 if (pFormatetc == NULL || pmedium == NULL) return E_INVALIDARG;
101
102 /*TCHAR buf[256];
103 if (GetClipboardFormatName(pFormatetc->cfFormat,buf,PFC_TABSIZE(buf)) > 0) {
104 buf[PFC_TABSIZE(buf)-1] = 0;
105 OutputDebugString(TEXT("SetData: ")); OutputDebugString(buf); OutputDebugString(TEXT("\n"));
106 } else {
107 OutputDebugString(TEXT("SetData: unknown clipboard format.\n"));
108 }*/
109
110 pfc::array_t<t_uint8> temp;
111 HRESULT state = STGMEDIUMToDataBlock(*pmedium,temp);
112 if (FAILED(state)) return state;
113 m_entries.set(*pFormatetc,temp);
114 return S_OK;
115 } PP_COM_CATCH;
116 }
117 HRESULT STDMETHODCALLTYPE DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection) override { (void)pFormatetc; (void)advf; (void)pAdvSink; (void)pdwConnection; return OLE_E_ADVISENOTSUPPORTED; }
118 HRESULT STDMETHODCALLTYPE DUnadvise(DWORD dwConnection) override { (void)dwConnection; return OLE_E_ADVISENOTSUPPORTED; }
119 HRESULT STDMETHODCALLTYPE EnumDAdvise(IEnumSTATDATA** ppenumAdvise) override { (void)ppenumAdvise; return OLE_E_ADVISENOTSUPPORTED; }
120 protected:
121 typedef pfc::array_t<uint8_t> data_t;
122 virtual HRESULT RenderData(UINT format,DWORD aspect,LONG dataIndex, data_t & out) const {
123 FORMATETC fmt = {};
124 fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex;
125 const pfc::array_t<t_uint8> * entry = m_entries.query_ptr(fmt);
126 if (entry != NULL) {
127 out = * entry;
128 return S_OK;
129 }
130 return DV_E_FORMATETC;
131 }
132 virtual HRESULT RenderDataTest(UINT format,DWORD aspect,LONG dataIndex) const {
133 FORMATETC fmt = {};
134 fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = dataIndex;
135 if (m_entries.have_item(fmt)) return S_OK;
136 return DV_E_FORMATETC;
137 }
138 typedef pfc::list_base_t<FORMATETC> TFormatList;
139
140 static void AddFormat(TFormatList & out,UINT code) {
141 FORMATETC fmt = {};
142 fmt.dwAspect = DVASPECT_CONTENT;
143 fmt.lindex = -1;
144 fmt.cfFormat = (CLIPFORMAT)code;
145 for(t_size medWalk = 0; medWalk < 32; ++medWalk) {
146 const DWORD med = 1 << medWalk;
147 if ((DataBlockToSTGMEDIUM_SupportedTymeds & med) != 0) {
148 fmt.tymed = med;
149 out.add_item(fmt);
150 }
151 }
152 }
153
154 virtual void EnumFormats(TFormatList & out) const {
155 pfc::avltree_t<UINT> formats;
156 for(auto walk = m_entries.cfirst(); walk.is_valid(); ++walk) {
157 formats.add_item( walk->m_key.cfFormat );
158 }
159 for(auto walk = formats.cfirst(); walk.is_valid(); ++walk) {
160 AddFormat(out, *walk);
161 }
162 }
163 HRESULT CreateIEnumFORMATETC(IEnumFORMATETC ** outptr) const throw() {
164 try {
165 pfc::list_t<FORMATETC> out;
166 EnumFormats(out);
167 return SHCreateStdEnumFmtEtc((UINT)out.get_count(), out.get_ptr(), outptr);
168 } PP_COM_CATCH;
169 }
170 private:
171 HRESULT GetData_internal(FORMATETC * formatetc, STGMEDIUM * medium,bool bHere) {
172 if (formatetc == NULL || medium == NULL) return E_INVALIDARG;
173
174 try {
175 data_t out;
176 HRESULT hr = RenderData(formatetc->cfFormat,formatetc->dwAspect,formatetc->lindex,out);
177 if (FAILED(hr)) return hr;
178 return DataBlockToSTGMEDIUM(out.get_ptr(),out.get_size(),medium,formatetc->tymed,bHere);
179 } PP_COM_CATCH;
180 }
181
182 typedef pfc::map_t<FORMATETC, pfc::array_t<t_uint8>, comparator_FORMATETC> t_entries;
183 t_entries m_entries;
184 };
185
186 #ifdef __IDataObjectAsyncCapability_INTERFACE_DEFINED__
187 typedef IDataObjectAsyncCapability IDataObjectAsyncCapability_t;
188 #else
189 typedef IAsyncOperation IDataObjectAsyncCapability_t;
190 #endif
191
192 class CAsyncDataObjectBase : public CDataObjectBase, public IDataObjectAsyncCapability_t {
193 BOOL m_inOperation = FALSE;
194 BOOL m_asyncMode = TRUE;
195 protected:
196 COM_QI_BEGIN()
197 COM_QI_CHAIN(CDataObjectBase)
198 COM_QI_ENTRY(IDataObjectAsyncCapability_t)
199 COM_QI_END()
200 public:
201 HRESULT STDMETHODCALLTYPE SetAsyncMode(BOOL fDoOpAsync) override {
202 m_asyncMode = fDoOpAsync;
203 return S_OK;
204 }
205
206 HRESULT STDMETHODCALLTYPE GetAsyncMode(BOOL *pfIsOpAsync) override {
207 if ( pfIsOpAsync == nullptr ) return E_INVALIDARG;
208 *pfIsOpAsync = m_asyncMode;
209 return S_OK;
210 }
211
212 HRESULT STDMETHODCALLTYPE StartOperation(IBindCtx *pbcReserved) override {
213 (void)pbcReserved;
214 m_inOperation = TRUE;
215 return S_OK;
216 }
217
218 HRESULT STDMETHODCALLTYPE InOperation(BOOL *pfInAsyncOp) override {
219 if ( pfInAsyncOp == nullptr ) return E_INVALIDARG;
220 *pfInAsyncOp = m_inOperation;
221 return S_OK;
222 }
223
224 HRESULT STDMETHODCALLTYPE EndOperation(HRESULT hResult,IBindCtx *pbcReserved,DWORD dwEffects) override {
225 (void)hResult; (void)pbcReserved; (void)dwEffects;
226 m_inOperation = FALSE;
227 return S_OK;
228 }
229 };
230 }