oledobj1.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_OLE3_SEG
  12. #pragma code_seg(AFX_OLE3_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. /////////////////////////////////////////////////////////////////////////////
  20. // COleDataObject constructors
  21. COleDataObject::COleDataObject()
  22. {
  23. m_lpEnumerator = NULL;
  24. m_lpDataObject = NULL;
  25. m_bAutoRelease = TRUE;
  26. m_bClipboard = FALSE;
  27. }
  28. void COleDataObject::Attach(LPDATAOBJECT lpDataObject, BOOL bAutoRelease)
  29. {
  30. ASSERT(lpDataObject != NULL);
  31. Release(); // detach previous
  32. m_lpDataObject = lpDataObject;
  33. m_bAutoRelease = bAutoRelease;
  34. }
  35. void COleDataObject::Release()
  36. {
  37. RELEASE(m_lpEnumerator);
  38. if (m_lpDataObject != NULL)
  39. {
  40. if (m_bAutoRelease)
  41. m_lpDataObject->Release();
  42. m_lpDataObject = NULL;
  43. }
  44. m_bClipboard = FALSE;
  45. }
  46. LPDATAOBJECT COleDataObject::Detach()
  47. {
  48. EnsureClipboardObject();
  49. LPDATAOBJECT lpDataObject = m_lpDataObject;
  50. m_lpDataObject = NULL; // detach without Release
  51. m_bClipboard = FALSE;
  52. return lpDataObject;
  53. }
  54. LPDATAOBJECT COleDataObject::GetIDataObject(BOOL bAddRef)
  55. {
  56. EnsureClipboardObject();
  57. LPDATAOBJECT lpDataObject = m_lpDataObject;
  58. if (bAddRef && lpDataObject != NULL)
  59. lpDataObject->AddRef();
  60. return lpDataObject;
  61. }
  62. /////////////////////////////////////////////////////////////////////////////
  63. // COleDataObject attributes
  64. void COleDataObject::BeginEnumFormats()
  65. {
  66. EnsureClipboardObject();
  67. ASSERT(m_bClipboard || m_lpDataObject != NULL);
  68. // release old enumerator
  69. RELEASE(m_lpEnumerator);
  70. if (m_lpDataObject == NULL)
  71. return;
  72. // get the new enumerator
  73. SCODE sc = m_lpDataObject->EnumFormatEtc(DATADIR_GET, &m_lpEnumerator);
  74. ASSERT(sc != S_OK || m_lpEnumerator != NULL);
  75. }
  76. BOOL COleDataObject::GetNextFormat(LPFORMATETC lpFormatEtc)
  77. {
  78. ASSERT(m_bClipboard || m_lpDataObject != NULL);
  79. ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  80. // return FALSE if enumerator is already NULL
  81. if (m_lpEnumerator == NULL)
  82. return FALSE;
  83. // attempt to retrieve the next format with the enumerator
  84. SCODE sc = m_lpEnumerator->Next(1, lpFormatEtc, NULL);
  85. // if enumerator fails, stop the enumeration
  86. if (sc != S_OK)
  87. {
  88. RELEASE(m_lpEnumerator);
  89. return FALSE; // enumeration has ended
  90. }
  91. // otherwise, continue
  92. return TRUE;
  93. }
  94. CFile* COleDataObject::GetFileData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
  95. {
  96. EnsureClipboardObject();
  97. ASSERT(m_bClipboard || m_lpDataObject != NULL);
  98. if (m_lpDataObject == NULL)
  99. return NULL;
  100. ASSERT(lpFormatEtc == NULL ||
  101. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  102. // fill in FORMATETC struct
  103. FORMATETC formatEtc;
  104. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  105. formatEtc.tymed = TYMED_FILE|TYMED_MFPICT|TYMED_HGLOBAL|TYMED_ISTREAM;
  106. // attempt to get the data
  107. STGMEDIUM stgMedium;
  108. SCODE sc = m_lpDataObject->GetData(lpFormatEtc, &stgMedium);
  109. if (FAILED(sc))
  110. return FALSE;
  111. // STGMEDIUMs with pUnkForRelease need to be copied first
  112. if (stgMedium.pUnkForRelease != NULL)
  113. {
  114. STGMEDIUM stgMediumDest;
  115. stgMediumDest.tymed = TYMED_NULL;
  116. stgMediumDest.pUnkForRelease = NULL;
  117. if (!_AfxCopyStgMedium(lpFormatEtc->cfFormat, &stgMediumDest, &stgMedium))
  118. {
  119. ::ReleaseStgMedium(&stgMedium);
  120. return FALSE;
  121. }
  122. // release original and replace with new
  123. ::ReleaseStgMedium(&stgMedium);
  124. stgMedium = stgMediumDest;
  125. }
  126. // convert it to a file, depending on data
  127. CString strFileName;
  128. CFile* pFile = NULL;
  129. TRY
  130. {
  131. switch (stgMedium.tymed)
  132. {
  133. case TYMED_FILE:
  134. strFileName = stgMedium.lpszFileName;
  135. pFile = new CFile;
  136. if (!pFile->Open(strFileName,
  137. CFile::modeReadWrite|CFile::shareExclusive))
  138. {
  139. delete pFile;
  140. pFile = NULL;
  141. break;
  142. }
  143. // caller is responsible for deleting the actual file,
  144. // but we free the file name.
  145. CoTaskMemFree(stgMedium.lpszFileName);
  146. break;
  147. case TYMED_MFPICT:
  148. case TYMED_HGLOBAL:
  149. pFile = new CSharedFile;
  150. ((CSharedFile*)pFile)->SetHandle(stgMedium.hGlobal);
  151. break;
  152. case TYMED_ISTREAM:
  153. pFile = new COleStreamFile(stgMedium.pstm);
  154. break;
  155. default:
  156. // type not supported, so return error
  157. ::ReleaseStgMedium(&stgMedium);
  158. break;
  159. }
  160. }
  161. CATCH_ALL(e)
  162. {
  163. delete pFile;
  164. pFile = NULL;
  165. DELETE_EXCEPTION(e);
  166. }
  167. END_CATCH_ALL
  168. // store newly created CFile* and return
  169. return pFile;
  170. }
  171. HGLOBAL COleDataObject::GetGlobalData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
  172. {
  173. EnsureClipboardObject();
  174. ASSERT(m_bClipboard || m_lpDataObject != NULL);
  175. if (m_lpDataObject == NULL)
  176. return NULL;
  177. ASSERT(lpFormatEtc == NULL ||
  178. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  179. // fill in FORMATETC struct
  180. FORMATETC formatEtc;
  181. BOOL bFillFormatEtc = (lpFormatEtc == NULL);
  182. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  183. if (bFillFormatEtc)
  184. lpFormatEtc->tymed = TYMED_HGLOBAL|TYMED_MFPICT;
  185. ASSERT((lpFormatEtc->tymed & (TYMED_HGLOBAL|TYMED_MFPICT)) != 0);
  186. // attempt to get the data
  187. STGMEDIUM stgMedium;
  188. SCODE sc = m_lpDataObject->GetData(lpFormatEtc, &stgMedium);
  189. if (FAILED(sc))
  190. return FALSE;
  191. // handle just hGlobal types
  192. switch (stgMedium.tymed)
  193. {
  194. case TYMED_MFPICT:
  195. case TYMED_HGLOBAL:
  196. if (stgMedium.pUnkForRelease == NULL)
  197. return stgMedium.hGlobal;
  198. STGMEDIUM stgMediumDest;
  199. stgMediumDest.tymed = TYMED_NULL;
  200. stgMediumDest.pUnkForRelease = NULL;
  201. if (!_AfxCopyStgMedium(lpFormatEtc->cfFormat, &stgMediumDest, &stgMedium))
  202. {
  203. ::ReleaseStgMedium(&stgMedium);
  204. return NULL;
  205. }
  206. ::ReleaseStgMedium(&stgMedium);
  207. return stgMediumDest.hGlobal;
  208. // default -- falls through to error condition...
  209. }
  210. ::ReleaseStgMedium(&stgMedium);
  211. return NULL;
  212. }
  213. BOOL COleDataObject::GetData(CLIPFORMAT cfFormat, LPSTGMEDIUM lpStgMedium,
  214. LPFORMATETC lpFormatEtc)
  215. {
  216. EnsureClipboardObject();
  217. ASSERT(m_bClipboard || m_lpDataObject != NULL);
  218. if (m_lpDataObject == NULL)
  219. return FALSE;
  220. ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM), FALSE));
  221. // fill in FORMATETC struct
  222. FORMATETC formatEtc;
  223. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  224. // attempt to get the data
  225. SCODE sc = m_lpDataObject->GetData(lpFormatEtc, lpStgMedium);
  226. if (FAILED(sc))
  227. return FALSE;
  228. return TRUE;
  229. }
  230. BOOL COleDataObject::IsDataAvailable(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
  231. {
  232. if (m_bClipboard)
  233. {
  234. // it is faster and more reliable to ask the real Win32 clipboard
  235. // instead of the OLE clipboard.
  236. return ::IsClipboardFormatAvailable(cfFormat);
  237. }
  238. else
  239. {
  240. ASSERT(m_lpDataObject != NULL);
  241. ASSERT(lpFormatEtc == NULL ||
  242. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  243. // fill in FORMATETC struct
  244. FORMATETC formatEtc;
  245. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  246. // attempt to get the data
  247. return m_lpDataObject->QueryGetData(lpFormatEtc) == S_OK;
  248. }
  249. }
  250. /////////////////////////////////////////////////////////////////////////////
  251. // clipboard API wrappers
  252. BOOL COleDataObject::AttachClipboard()
  253. {
  254. ASSERT(AfxIsValidAddress(this, sizeof(COleDataObject)));
  255. ASSERT(m_lpDataObject == NULL); // need to call release?
  256. ASSERT(!m_bClipboard); // already attached to clipboard?
  257. // set special "clipboard" flag for optimizations
  258. m_bClipboard = TRUE;
  259. return TRUE;
  260. }
  261. void COleDataObject::EnsureClipboardObject()
  262. {
  263. ASSERT(AfxIsValidAddress(this, sizeof(COleDataObject)));
  264. if (m_bClipboard && m_lpDataObject == NULL)
  265. {
  266. // get clipboard using OLE API
  267. LPDATAOBJECT lpDataObject;
  268. SCODE sc = ::OleGetClipboard(&lpDataObject);
  269. // attach COleDataObject wrapper to IDataObject from clipboard
  270. if (sc == S_OK)
  271. Attach(lpDataObject, TRUE);
  272. }
  273. }
  274. /////////////////////////////////////////////////////////////////////////////