foobar2000 SDK  2015-08-03
IDataObjectUtils.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
3 #ifdef _WIN32
4 
5 HRESULT IDataObjectUtils::DataBlockToSTGMEDIUM(const void * blockPtr, t_size blockSize, STGMEDIUM * medium, DWORD tymed, bool bHere) throw() {
6  try {
7  if (bHere) {
8  switch(tymed) {
9  case TYMED_ISTREAM:
10  {
11  if (medium->pstm == NULL) return E_INVALIDARG;
12  ULONG written = 0;
13  HRESULT state;
14  state = medium->pstm->Write(blockPtr, pfc::downcast_guarded<ULONG>(blockSize),&written);
15  if (FAILED(state)) return state;
16  if (written != blockSize) return STG_E_MEDIUMFULL;
17  return S_OK;
18  }
19  default:
20  return DV_E_TYMED;
21  }
22  } else {
23  if (tymed & TYMED_HGLOBAL) {
24  HGLOBAL hMem = HGlobalFromMemblock(blockPtr, blockSize);
25  if (hMem == NULL) return E_OUTOFMEMORY;
26  medium->tymed = TYMED_HGLOBAL;
27  medium->hGlobal = hMem;
28  medium->pUnkForRelease = NULL;
29  return S_OK;
30  }
31  if (tymed & TYMED_ISTREAM) {
32  HRESULT state;
33  HGLOBAL hMem = HGlobalFromMemblock(blockPtr, blockSize);
34  if (hMem == NULL) return E_OUTOFMEMORY;
35  medium->tymed = TYMED_ISTREAM;
37  if (FAILED( state = CreateStreamOnHGlobal(hMem,TRUE,stream.receive_ptr()) ) ) {
38  GlobalFree(hMem);
39  return state;
40  }
41  {
42  LARGE_INTEGER wtf = {};
43  if (FAILED( state = stream->Seek(wtf,STREAM_SEEK_END,NULL) ) ) {
44  return state;
45  }
46  }
47  medium->pstm = stream.detach();
48  medium->pUnkForRelease = NULL;
49  return S_OK;
50  }
51  return DV_E_TYMED;
52  }
53  } catch(pfc::exception_not_implemented) {
54  return E_NOTIMPL;
55  } catch(std::bad_alloc) {
56  return E_OUTOFMEMORY;
57  } catch(...) {
58  return E_UNEXPECTED;
59  }
60 }
61 
62 
63 HGLOBAL IDataObjectUtils::HGlobalFromMemblock(const void * ptr,t_size size) {
64  HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE,size);
65  if (handle != NULL) {
66  void * destptr = GlobalLock(handle);
67  if (destptr == NULL) {
68  GlobalFree(handle);
69  handle = NULL;
70  } else {
71  memcpy(destptr,ptr,size);
72  GlobalUnlock(handle);
73  }
74  }
75  return handle;
76 }
77 
78 HRESULT IDataObjectUtils::ExtractDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, pfc::array_t<t_uint8> & out) {
79  FORMATETC fmt = {};
80  fmt.cfFormat = format; fmt.dwAspect = aspect; fmt.lindex = index;
81  fmt.tymed = TYMED_HGLOBAL /* | TYMED_ISTREAM*/;
82 
83  STGMEDIUM med = {};
84  HRESULT state;
85  if (FAILED( state = obj->GetData(&fmt,&med) ) ) return state;
86  ReleaseStgMediumScope relScope(&med);
87  return STGMEDIUMToDataBlock(med, out);
88 }
89 
90 HRESULT IDataObjectUtils::STGMEDIUMToDataBlock(const STGMEDIUM & med, pfc::array_t<t_uint8> & out) {
91  switch(med.tymed) {
92  case TYMED_HGLOBAL:
93  {
94  CGlobalLockScope lock(med.hGlobal);
95  out.set_data_fromptr( (const t_uint8*) lock.GetPtr(), lock.GetSize() );
96  }
97  return S_OK;
98  case TYMED_ISTREAM:
99  {
100  HRESULT state;
101  IStream * stream = med.pstm;
102  LARGE_INTEGER offset = {};
103  STATSTG stats = {};
104  if (FAILED( state = stream->Stat(&stats,STATFLAG_NONAME ) ) ) return state;
105  t_size toRead = pfc::downcast_guarded<t_size>(stats.cbSize.QuadPart);
106  out.set_size(toRead);
107  if (FAILED( state = stream->Seek(offset,STREAM_SEEK_SET,NULL) ) ) return state;
108  ULONG cbRead = 0;
109  if (FAILED( state = stream->Read(out.get_ptr(), pfc::downcast_guarded<ULONG>(toRead), &cbRead) ) ) return state;
110  if (cbRead != toRead) return E_UNEXPECTED;
111  }
112  return S_OK;
113  default:
114  return DV_E_TYMED;
115  }
116 }
117 
119  return ExtractDataObjectContent(obj, format, DVASPECT_CONTENT, -1, out);
120 }
121 
122 HRESULT IDataObjectUtils::ExtractDataObjectContentTest(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index) {
123  FORMATETC fmt = {};
124  fmt.cfFormat = format; fmt.dwAspect = aspect; fmt.lindex = index;
125  for(t_uint32 walk = 0; walk < 32; ++walk) {
126  const DWORD tymed = 1 << walk;
127  if ((ExtractDataObjectContent_SupportedTymeds & tymed) != 0) {
128  fmt.tymed = tymed;
129  HRESULT state = obj->QueryGetData(&fmt);
130  if (SUCCEEDED(state)) {
131  if (state == S_OK) return S_OK;
132  } else {
133  if (state != DV_E_TYMED) return state;
134  }
135  }
136  }
137  return E_FAIL;
138 }
139 
141  return ExtractDataObjectContentTest(obj,format,DVASPECT_CONTENT,-1);
142 }
143 
146  HRESULT state;
147  state = ExtractDataObjectContent(obj,CF_UNICODETEXT,data);
148  if (SUCCEEDED(state)) {
149  out = pfc::stringcvt::string_utf8_from_os_ex( (const wchar_t*) data.get_ptr(), data.get_size() / sizeof(wchar_t) );
150  return S_OK;
151  }
152  state = ExtractDataObjectContent(obj,CF_TEXT,data);
153  if (SUCCEEDED(state)) {
154  out = pfc::stringcvt::string_utf8_from_os_ex( (const char*) data.get_ptr(), data.get_size() / sizeof(char) );
155  return S_OK;
156  }
157  return E_FAIL;
158 }
159 
160 HRESULT IDataObjectUtils::SetDataObjectContent(pfc::com_ptr_t<IDataObject> obj, UINT format, DWORD aspect, LONG index, const void * data, t_size dataSize) {
161  STGMEDIUM med = {};
162  FORMATETC fmt = {};
163  fmt.cfFormat = format; fmt.dwAspect = aspect; fmt.lindex = index; fmt.tymed = TYMED_HGLOBAL;
164  HRESULT state;
165  if (FAILED(state = DataBlockToSTGMEDIUM(data,dataSize,&med,TYMED_HGLOBAL,false))) return state;
166  return obj->SetData(&fmt,&med,TRUE);
167 }
168 
171  return SetDataObjectContent(obj,CF_UNICODETEXT,DVASPECT_CONTENT,-1,s.get_ptr(), (s.length()+1) * sizeof(s[0]));
172 }
173 
175  HRESULT state;
176  pfc::array_t<t_uint8> buffer;
177  if (FAILED( state = ExtractDataObjectContent(obj, format, DVASPECT_CONTENT, -1, buffer) ) ) return state;
178  if (buffer.get_size() < sizeof(val)) return E_UNEXPECTED;
179  val = *(DWORD*) buffer.get_ptr();
180  return S_OK;
181 }
183  return SetDataObjectContent(obj,format,DVASPECT_CONTENT,-1,&val,sizeof(val));
184 }
186  return SetDataObjectDWORD(obj, RegisterClipboardFormat(CFSTR_PASTESUCCEEDED), effect);
187 }
188 
189 #endif // _WIN32
const t_item * get_ptr() const
Definition: array.h:213
uint8_t t_uint8
Definition: int_types.h:9
HRESULT DataBlockToSTGMEDIUM(const void *blockPtr, t_size blockSize, STGMEDIUM *medium, DWORD tymed, bool bHere)
HRESULT SetDataObjectString(pfc::com_ptr_t< IDataObject > obj, const char *str)
T ** receive_ptr()
Definition: com_ptr_t.h:73
HRESULT ExtractDataObjectString(pfc::com_ptr_t< IDataObject > obj, pfc::string_base &out)
void * GetPtr() const
Definition: win-objects.h:77
HRESULT ExtractDataObjectContentTest(pfc::com_ptr_t< IDataObject > obj, UINT format, DWORD aspect, LONG index)
HRESULT ExtractDataObjectContent(pfc::com_ptr_t< IDataObject > obj, UINT format, DWORD aspect, LONG index, pfc::array_t< t_uint8 > &out)
size_t t_size
Definition: int_types.h:48
HRESULT PasteSucceeded(pfc::com_ptr_t< IDataObject > obj, DWORD effect)
void set_size(t_size p_size)
Definition: array.h:104
const wchar_t * get_ptr() const
Definition: string_conv.h:133
HRESULT ExtractDataObjectDWORD(pfc::com_ptr_t< IDataObject > obj, UINT format, DWORD &val)
T * detach()
Definition: com_ptr_t.h:57
HRESULT STGMEDIUMToDataBlock(const STGMEDIUM &med, pfc::array_t< t_uint8 > &out)
HRESULT SetDataObjectContent(pfc::com_ptr_t< IDataObject > obj, UINT format, DWORD aspect, LONG index, const void *data, t_size dataSize)
void set_data_fromptr(const t_source *p_buffer, t_size p_count)
Warning: buffer pointer must not point to buffer allocated by this array (fixme). ...
Definition: array.h:139
HGLOBAL HGlobalFromMemblock(const void *ptr, t_size size)
HRESULT SetDataObjectDWORD(pfc::com_ptr_t< IDataObject > obj, UINT format, DWORD val)
static const DWORD ExtractDataObjectContent_SupportedTymeds
t_size GetSize() const
Definition: win-objects.h:78
t_size get_size() const
Definition: array.h:130
uint32_t t_uint32
Definition: int_types.h:5