diff foosdk/sdk/libPPUI/IDataObjectUtils.cpp @ 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/libPPUI/IDataObjectUtils.cpp	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,187 @@
+#include "stdafx.h"
+
+#include "IDataObjectUtils.h"
+
+HRESULT IDataObjectUtils::DataBlockToSTGMEDIUM(const void * blockPtr, t_size blockSize, STGMEDIUM * medium, DWORD tymed, bool bHere) throw() {
+	try {
+		if (bHere) {
+			switch(tymed) {
+			case TYMED_ISTREAM:
+				{
+					if (medium->pstm == NULL) return E_INVALIDARG;
+					ULONG written = 0;
+					HRESULT state;
+					state = medium->pstm->Write(blockPtr, pfc::downcast_guarded<ULONG>(blockSize),&written);
+					if (FAILED(state)) return state;
+					if (written != blockSize) return STG_E_MEDIUMFULL;
+					return S_OK;
+				}
+			default:
+				return DV_E_TYMED;
+			}
+		} else {
+			if (tymed & TYMED_HGLOBAL) {
+				HGLOBAL hMem = HGlobalFromMemblock(blockPtr, blockSize);
+				if (hMem == NULL) return E_OUTOFMEMORY;
+				medium->tymed = TYMED_HGLOBAL;
+				medium->hGlobal = hMem;
+				medium->pUnkForRelease = NULL;
+				return S_OK;
+			}
+			if (tymed & TYMED_ISTREAM) {
+				HRESULT state;
+				HGLOBAL hMem = HGlobalFromMemblock(blockPtr, blockSize);
+				if (hMem == NULL) return E_OUTOFMEMORY;
+				medium->tymed = TYMED_ISTREAM;
+				pfc::com_ptr_t<IStream> stream;
+				if (FAILED( state = CreateStreamOnHGlobal(hMem,TRUE,stream.receive_ptr()) ) ) {
+					GlobalFree(hMem);
+					return state;
+				}
+				{
+					LARGE_INTEGER wtf = {};
+					if (FAILED( state = stream->Seek(wtf,STREAM_SEEK_END,NULL) ) ) {
+						return state;
+					}
+				}
+				medium->pstm = stream.detach();
+				medium->pUnkForRelease = NULL;
+				return S_OK;
+			}
+			return DV_E_TYMED;
+		}
+	} catch(pfc::exception_not_implemented const &) {
+		return E_NOTIMPL;
+	} catch(std::bad_alloc const &) {
+		return E_OUTOFMEMORY;
+	} catch(...) {
+		return E_UNEXPECTED;
+	}
+}
+
+
+HGLOBAL IDataObjectUtils::HGlobalFromMemblock(const void * ptr,t_size size) {
+	HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE,size);
+	if (handle != NULL) {
+		void * destptr = GlobalLock(handle);
+		if (destptr == NULL) {
+			GlobalFree(handle);
+			handle = NULL;
+		} else {
+			memcpy(destptr,ptr,size);
+			GlobalUnlock(handle);
+		}
+	}
+	return handle;
+}
+
+HRESULT IDataObjectUtils::ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, pfc::array_t<t_uint8> & out) {
+	FORMATETC fmt = {};
+	fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = index;
+	fmt.tymed = TYMED_HGLOBAL /* | TYMED_ISTREAM*/;
+
+	STGMEDIUM med = {};
+	HRESULT state;
+	if (FAILED( state = obj->GetData(&fmt,&med) ) ) return state;
+	ReleaseStgMediumScope relScope(&med);
+	return STGMEDIUMToDataBlock(med, out);	
+}
+
+HRESULT IDataObjectUtils::STGMEDIUMToDataBlock(const STGMEDIUM & med, pfc::array_t<t_uint8> & out) {
+	switch(med.tymed) {
+		case TYMED_HGLOBAL:
+			{
+				CGlobalLockScope lock(med.hGlobal);
+				out.set_data_fromptr( (const t_uint8*) lock.GetPtr(), lock.GetSize() );
+			}
+			return S_OK;
+		case TYMED_ISTREAM:
+			{
+				HRESULT state;
+				IStream * stream = med.pstm;
+				LARGE_INTEGER offset = {};
+				STATSTG stats = {};
+				if (FAILED( state = stream->Stat(&stats,STATFLAG_NONAME ) ) ) return state;
+				t_size toRead = pfc::downcast_guarded<t_size>(stats.cbSize.QuadPart);
+				out.set_size(toRead);
+				if (FAILED( state = stream->Seek(offset,STREAM_SEEK_SET,NULL) ) ) return state;
+				ULONG cbRead = 0;
+				if (FAILED( state = stream->Read(out.get_ptr(), pfc::downcast_guarded<ULONG>(toRead), &cbRead) ) ) return state;
+				if (cbRead != toRead) return E_UNEXPECTED;
+			}
+			return S_OK;
+		default:
+			return DV_E_TYMED;
+	}
+}
+
+HRESULT IDataObjectUtils::ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, pfc::array_t<t_uint8> & out) {
+	return ExtractDataObjectContent(obj, format, DVASPECT_CONTENT, -1, out);
+}
+
+HRESULT IDataObjectUtils::ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index) {
+	FORMATETC fmt = {};
+	fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = index;
+	for(t_uint32 walk = 0; walk < 32; ++walk) {
+		const DWORD tymed = 1 << walk;
+		if ((ExtractDataObjectContent_SupportedTymeds & tymed) != 0) {
+			fmt.tymed = tymed;
+			HRESULT state = obj->QueryGetData(&fmt);
+			if (SUCCEEDED(state)) {
+				if (state == S_OK) return S_OK;
+			} else {
+				if (state != DV_E_TYMED) return state;
+			}
+		}
+	}
+	return E_FAIL;
+}
+
+HRESULT IDataObjectUtils::ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format) {
+	return ExtractDataObjectContentTest(obj,format,DVASPECT_CONTENT,-1);
+}
+
+HRESULT IDataObjectUtils::ExtractDataObjectString(pfc::com_ptr_t<IDataObject> obj, pfc::string_base & out) {
+	pfc::array_t<t_uint8> data;
+	HRESULT state;
+	state = ExtractDataObjectContent(obj,CF_UNICODETEXT,data);
+	if (SUCCEEDED(state)) {
+		out = pfc::stringcvt::string_utf8_from_os_ex( (const wchar_t*) data.get_ptr(), data.get_size() / sizeof(wchar_t) );
+		return S_OK;
+	}
+	state = ExtractDataObjectContent(obj,CF_TEXT,data);
+	if (SUCCEEDED(state)) {
+		out = pfc::stringcvt::string_utf8_from_os_ex( (const char*) data.get_ptr(), data.get_size() / sizeof(char) );
+		return S_OK;
+	}
+	return E_FAIL;
+}
+
+HRESULT IDataObjectUtils::SetDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, const void * data, t_size dataSize) {
+	STGMEDIUM med = {};
+	FORMATETC fmt = {};
+	fmt.cfFormat = (CLIPFORMAT)format; fmt.dwAspect = aspect; fmt.lindex = index; fmt.tymed = TYMED_HGLOBAL;
+	HRESULT state;
+	if (FAILED(state = DataBlockToSTGMEDIUM(data,dataSize,&med,TYMED_HGLOBAL,false))) return state;
+	return obj->SetData(&fmt,&med,TRUE);
+}
+
+HRESULT IDataObjectUtils::SetDataObjectString(pfc::com_ptr_t<IDataObject> obj, const char * str) {
+	pfc::stringcvt::string_wide_from_utf8 s(str);
+	return SetDataObjectContent(obj,CF_UNICODETEXT,DVASPECT_CONTENT,-1,s.get_ptr(), (s.length()+1) * sizeof(s[0]));
+}
+
+HRESULT IDataObjectUtils::ExtractDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD & val) {
+	HRESULT state;
+	pfc::array_t<t_uint8> buffer;
+	if (FAILED( state = ExtractDataObjectContent(obj, format, DVASPECT_CONTENT, -1, buffer) ) ) return state;
+	if (buffer.get_size() < sizeof(val)) return E_UNEXPECTED;
+	val = *(DWORD*) buffer.get_ptr();
+	return S_OK;
+}
+HRESULT IDataObjectUtils::SetDataObjectDWORD(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD val) {
+	return SetDataObjectContent(obj,format,DVASPECT_CONTENT,-1,&val,sizeof(val));
+}
+HRESULT IDataObjectUtils::PasteSucceeded(pfc::com_ptr_t<IDataObject> obj, DWORD effect) {
+	return SetDataObjectDWORD(obj, RegisterClipboardFormat(CFSTR_PASTESUCCEEDED), effect);
+}