Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

574 lines
17 KiB

  1. //**********************************************************************
  2. // File name: DXFEROBJ.CPP
  3. //
  4. // Implementation file for CDataXferObj, data transfer object
  5. // implementation of IDataObject interface.
  6. //
  7. // Functions:
  8. //
  9. // See DXFEROBJ.H for class definition
  10. //
  11. // Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved.
  12. //**********************************************************************
  13. #include "pre.h"
  14. #include "enumfetc.h"
  15. #include <assert.h>
  16. #include "dxferobj.h"
  17. #include "site.h"
  18. CLIPFORMAT g_cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  19. CLIPFORMAT g_cfObjectDescriptor =RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  20. // List of formats offered by our data transfer object via EnumFormatEtc
  21. static FORMATETC s_arrGetFmtEtcs[] =
  22. {
  23. { g_cfEmbeddedObject, NULL, DVASPECT_CONTENT, -1, TYMED_ISTORAGE},
  24. { g_cfObjectDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  25. { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT}
  26. };
  27. //**********************************************************************
  28. //
  29. // CDataXferObj::Create
  30. //
  31. // Purpose:
  32. //
  33. // Creation routine for CDataXferObj
  34. //
  35. // Parameters:
  36. //
  37. // CSimpleSite FAR *lpSite - Pointer to source CSimpleSite
  38. // this is the container site of the
  39. // source OLE object to be transfered
  40. //
  41. // Return Value:
  42. //
  43. // None
  44. //
  45. // Function Calls:
  46. // Function Location
  47. //
  48. // StgCreateDocfile OLE API
  49. // assert C Runtime
  50. //
  51. // Comments:
  52. // reference count of CDataXferObj will be 0 on return.
  53. //
  54. //********************************************************************
  55. CDataXferObj FAR * CDataXferObj::Create(
  56. CSimpleSite FAR *lpSite,
  57. POINTL FAR* pPointl
  58. )
  59. {
  60. CDataXferObj FAR * lpTemp = new CDataXferObj();
  61. if (!lpTemp)
  62. return NULL;
  63. // create a sub-storage for the object
  64. HRESULT hErr = StgCreateDocfile(
  65. NULL,
  66. STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE |
  67. STGM_DELETEONRELEASE,
  68. 0,
  69. &lpTemp->m_lpObjStorage);
  70. assert(hErr == NOERROR);
  71. if (hErr != NOERROR)
  72. {
  73. delete lpTemp;
  74. return NULL;
  75. }
  76. // Clone the source object
  77. if (lpSite->m_lpOleObject) {
  78. // Object is loaded; ask the object to save into the new storage
  79. LPPERSISTSTORAGE pPersistStorage;
  80. lpSite->m_lpOleObject->QueryInterface(IID_IPersistStorage,
  81. (LPVOID FAR*)&pPersistStorage);
  82. assert(pPersistStorage);
  83. OleSave(pPersistStorage, lpTemp->m_lpObjStorage, FALSE);
  84. // pass NULL so that object application won't forget the real stg
  85. pPersistStorage->SaveCompleted(NULL);
  86. pPersistStorage->Release();
  87. } else {
  88. // Object not loaded so use cheaper IStorage CopyTo operation
  89. lpSite->m_lpObjStorage->CopyTo(0, NULL, NULL, lpTemp->m_lpObjStorage);
  90. }
  91. OleLoad(lpTemp->m_lpObjStorage, IID_IOleObject, NULL,
  92. (LPVOID FAR*)&lpTemp->m_lpOleObject);
  93. assert(lpTemp->m_lpOleObject);
  94. lpTemp->m_sizel = lpSite->m_sizel;
  95. if (pPointl)
  96. lpTemp->m_pointl = *pPointl;
  97. else
  98. lpTemp->m_pointl.x = lpTemp->m_pointl.y = 0;
  99. return lpTemp;
  100. }
  101. //**********************************************************************
  102. //
  103. // CDataXferObj::CDataXferObj
  104. //
  105. // Purpose:
  106. //
  107. // Constructor for CDataXferObj
  108. //
  109. // Parameters:
  110. //
  111. // CSimpleDoc FAR *lpDoc - Pointer to CSimpleDoc
  112. //
  113. // Return Value:
  114. //
  115. // None
  116. //
  117. // Function Calls:
  118. // Function Location
  119. //
  120. // Comments:
  121. //
  122. //********************************************************************
  123. CDataXferObj::CDataXferObj (void)
  124. {
  125. // clear the reference count
  126. m_nCount = 0;
  127. m_lpObjStorage = NULL;
  128. m_lpOleObject = NULL;
  129. m_sizel.cx = m_sizel.cy = 0;
  130. m_pointl.x = m_pointl.y = 0;
  131. }
  132. //**********************************************************************
  133. //
  134. // CDataXferObj::~CDataXferObj
  135. //
  136. // Purpose:
  137. //
  138. // Destructor for CDataXferObj
  139. //
  140. // Parameters:
  141. //
  142. // None
  143. //
  144. // Return Value:
  145. //
  146. // None
  147. //
  148. // Function Calls:
  149. // Function Location
  150. //
  151. // TestDebugOut Windows API
  152. // IOleObject::Release Object
  153. // IStorage::Release OLE API
  154. //
  155. // Comments:
  156. //
  157. //********************************************************************
  158. CDataXferObj::~CDataXferObj ()
  159. {
  160. TestDebugOut ("In CDataXferObj's Destructor \r\n");
  161. if (m_lpOleObject)
  162. {
  163. m_lpOleObject->Release();
  164. m_lpOleObject = NULL;
  165. // Release the storage for this object
  166. m_lpObjStorage->Release();
  167. m_lpObjStorage = NULL;
  168. }
  169. }
  170. //**********************************************************************
  171. //
  172. // CDataXferObj::QueryInterface
  173. //
  174. // Purpose:
  175. //
  176. // Used for interface negotiation of the CDataXferObj instance
  177. //
  178. // Parameters:
  179. //
  180. // REFIID riid - A reference to the interface that is
  181. // being queried.
  182. //
  183. // LPVOID FAR* ppvObj - An out parameter to return a pointer to
  184. // the interface.
  185. //
  186. // Return Value:
  187. //
  188. // S_OK - The interface is supported.
  189. // E_NOINTERFACE - The interface is not supported
  190. //
  191. // Function Calls:
  192. // Function Location
  193. //
  194. // TestDebugOut Windows API
  195. // IsEqualIID OLE API
  196. // ResultFromScode OLE API
  197. // CDataXferObj::AddRef DXFEROBJ.CPP
  198. //
  199. // Comments:
  200. //
  201. //
  202. //********************************************************************
  203. STDMETHODIMP CDataXferObj::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  204. {
  205. TestDebugOut("In CDataXferObj::QueryInterface\r\n");
  206. if ( riid == IID_IUnknown || riid == IID_IDataObject)
  207. {
  208. AddRef();
  209. *ppvObj = this;
  210. return NOERROR;
  211. }
  212. // unknown interface requested
  213. *ppvObj = NULL; // must set out pointer parameters to NULL
  214. return ResultFromScode(E_NOINTERFACE);
  215. }
  216. //**********************************************************************
  217. //
  218. // CDataXferObj::AddRef
  219. //
  220. // Purpose:
  221. //
  222. // Increments the reference count of the CDataXferObj instance
  223. //
  224. // Parameters:
  225. //
  226. // None
  227. //
  228. // Return Value:
  229. //
  230. // ULONG - The new reference count of the object
  231. //
  232. // Function Calls:
  233. // Function Location
  234. //
  235. // TestDebugOut Windows API
  236. //
  237. // Comments:
  238. //
  239. //********************************************************************
  240. STDMETHODIMP_(ULONG) CDataXferObj::AddRef()
  241. {
  242. TestDebugOut("In CDataXferObj::AddRef\r\n");
  243. return ++m_nCount;
  244. }
  245. //**********************************************************************
  246. //
  247. // CDataXferObj::Release
  248. //
  249. // Purpose:
  250. //
  251. // Decrements the reference count of the CDataXferObj object
  252. //
  253. // Parameters:
  254. //
  255. // None
  256. //
  257. // Return Value:
  258. //
  259. // ULONG - The new reference count of the object.
  260. //
  261. // Function Calls:
  262. // Function Location
  263. //
  264. // TestDebugOut Windows API
  265. //
  266. // Comments:
  267. //
  268. //********************************************************************
  269. STDMETHODIMP_(ULONG) CDataXferObj::Release()
  270. {
  271. TestDebugOut("In CDataXferObj::Release\r\n");
  272. if (--m_nCount == 0) {
  273. delete this;
  274. return 0;
  275. }
  276. return m_nCount;
  277. }
  278. /********************************************************************
  279. ** This IDataObject implementation is used for data transfer.
  280. **
  281. ** The following methods are NOT supported for data transfer:
  282. ** IDataObject::SetData -- return E_NOTIMPL
  283. ** IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
  284. ** ::DUnadvise
  285. ** ::EnumDAdvise
  286. ** IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
  287. ** (NOTE: must set pformatetcOut->ptd = NULL)
  288. *********************************************************************/
  289. //**********************************************************************
  290. //
  291. // CDataXferObj::QueryGetData
  292. //
  293. // Purpose:
  294. //
  295. // Called to determine if our object supports a particular
  296. // FORMATETC.
  297. //
  298. // Parameters:
  299. //
  300. // LPFORMATETC pformatetc - Pointer to the FORMATETC being queried for.
  301. //
  302. // Return Value:
  303. //
  304. // DV_E_FORMATETC - The FORMATETC is not supported
  305. // S_OK - The FORMATETC is supported.
  306. //
  307. //
  308. // Function Calls:
  309. // Function Location
  310. //
  311. // TestDebugOut Windows API
  312. // ResultFromScode OLE API
  313. //
  314. // Comments:
  315. // we support the following formats:
  316. // "Embedded Object"
  317. // "Object Descriptor"
  318. // CF_METAFILEPICT
  319. //
  320. //********************************************************************
  321. STDMETHODIMP CDataXferObj::QueryGetData (LPFORMATETC pformatetc)
  322. {
  323. SCODE sc = DV_E_FORMATETC;
  324. TestDebugOut("In CDataXferObj::QueryGetData\r\n");
  325. // check the validity of the formatetc.
  326. if ( (pformatetc->cfFormat == g_cfEmbeddedObject) &&
  327. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  328. (pformatetc->tymed == TYMED_ISTORAGE) )
  329. sc = S_OK;
  330. else if ( (pformatetc->cfFormat == g_cfObjectDescriptor) &&
  331. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  332. (pformatetc->tymed == TYMED_HGLOBAL) )
  333. sc = S_OK;
  334. else if ( (pformatetc->cfFormat == CF_METAFILEPICT) &&
  335. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  336. (pformatetc->tymed == TYMED_MFPICT) )
  337. sc = S_OK;
  338. return ResultFromScode(sc);
  339. }
  340. STDMETHODIMP CDataXferObj::EnumFormatEtc(
  341. DWORD dwDirection,
  342. LPENUMFORMATETC FAR* ppenumFormatEtc
  343. )
  344. {
  345. SCODE sc = E_NOTIMPL;
  346. TestDebugOut("In CDataXferObj::EnumFormatEtc\r\n");
  347. *ppenumFormatEtc = NULL;
  348. if (dwDirection == DATADIR_GET) {
  349. *ppenumFormatEtc = OleStdEnumFmtEtc_Create(
  350. sizeof(s_arrGetFmtEtcs)/sizeof(s_arrGetFmtEtcs[0]),
  351. s_arrGetFmtEtcs);
  352. if (*ppenumFormatEtc == NULL)
  353. sc = E_OUTOFMEMORY;
  354. else
  355. sc = S_OK;
  356. }
  357. return ResultFromScode(sc);
  358. }
  359. //**********************************************************************
  360. //
  361. // CDataXferObj::GetData
  362. //
  363. // Purpose:
  364. //
  365. // Returns the data in the format specified in pformatetcIn.
  366. //
  367. // Parameters:
  368. //
  369. // LPFORMATETC pformatetcIn - The format requested by the caller
  370. //
  371. // LPSTGMEDIUM pmedium - The medium requested by the caller
  372. //
  373. // Return Value:
  374. //
  375. // DV_E_FORMATETC - Format not supported
  376. // S_OK - Success
  377. //
  378. // Function Calls:
  379. // Function Location
  380. //
  381. // TestDebugOut Windows API
  382. // OleStdGetOleObjectData OLE2UI API
  383. // OleStdGetMetafilePictFromOleObject OLE2UI API
  384. // ResultFromScode OLE API
  385. //
  386. // Comments:
  387. // we support GetData for the following formats:
  388. // "Embedded Object"
  389. // "Object Descriptor"
  390. // CF_METAFILEPICT
  391. //
  392. //********************************************************************
  393. STDMETHODIMP CDataXferObj::GetData (
  394. LPFORMATETC pformatetcIn,
  395. LPSTGMEDIUM pmedium
  396. )
  397. {
  398. SCODE sc = DV_E_FORMATETC;
  399. TestDebugOut("In CDataXferObj::GetData\r\n");
  400. // we must set all out pointer parameters to NULL. */
  401. pmedium->tymed = TYMED_NULL;
  402. pmedium->pUnkForRelease = NULL; // we transfer ownership to caller
  403. pmedium->hGlobal = NULL;
  404. // Check the FORMATETC and fill pmedium if valid.
  405. if ( (pformatetcIn->cfFormat == g_cfEmbeddedObject) &&
  406. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  407. (pformatetcIn->tymed == TYMED_ISTORAGE) ) {
  408. LPPERSISTSTORAGE pPersistStorage;
  409. /* render CF_EMBEDDEDOBJECT by asking the object to save
  410. ** into a temporary, DELETEONRELEASE IStorage allocated by us.
  411. */
  412. m_lpOleObject->QueryInterface(
  413. IID_IPersistStorage, (LPVOID FAR*)&pPersistStorage);
  414. assert(pPersistStorage);
  415. HRESULT hrErr = OleStdGetOleObjectData(
  416. pPersistStorage,
  417. pformatetcIn,
  418. pmedium,
  419. FALSE /* fUseMemory -- (use file-base stg) */
  420. );
  421. pPersistStorage->Release();
  422. sc = GetScode( hrErr );
  423. } else if ( (pformatetcIn->cfFormat == g_cfObjectDescriptor) &&
  424. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  425. (pformatetcIn->tymed == TYMED_HGLOBAL) ) {
  426. // render CF_OBJECTDESCRIPTOR data
  427. pmedium->hGlobal = OleStdGetObjectDescriptorDataFromOleObject(
  428. m_lpOleObject,
  429. "Simple OLE 2.0 Container", // string to identify source
  430. DVASPECT_CONTENT,
  431. m_pointl,
  432. (LPSIZEL)&m_sizel
  433. );
  434. if (! pmedium->hGlobal)
  435. sc = E_OUTOFMEMORY;
  436. else {
  437. pmedium->tymed = TYMED_HGLOBAL;
  438. sc = S_OK;
  439. }
  440. } else if ( (pformatetcIn->cfFormat == CF_METAFILEPICT) &&
  441. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  442. (pformatetcIn->tymed == TYMED_MFPICT) ) {
  443. // render CF_METAFILEPICT by drawing the object into a metafile DC
  444. pmedium->hGlobal = OleStdGetMetafilePictFromOleObject(
  445. m_lpOleObject, DVASPECT_CONTENT, NULL, pformatetcIn->ptd);
  446. if (! pmedium->hGlobal)
  447. sc = E_OUTOFMEMORY;
  448. else {
  449. pmedium->tymed = TYMED_MFPICT;
  450. sc = S_OK;
  451. }
  452. }
  453. return ResultFromScode( sc );
  454. }
  455. //**********************************************************************
  456. //
  457. // CDataXferObj::GetDataHere
  458. //
  459. // Purpose:
  460. //
  461. // Called to get a data format in a caller supplied location
  462. //
  463. // Parameters:
  464. //
  465. // LPFORMATETC pformatetc - FORMATETC requested
  466. //
  467. // LPSTGMEDIUM pmedium - Medium to return the data
  468. //
  469. // Return Value:
  470. //
  471. // DATA_E_FORMATETC - We don't support the requested format
  472. //
  473. // Function Calls:
  474. // Function Location
  475. //
  476. // TestDebugOut Windows API
  477. // OleStdGetOleObjectData OLE2UI API
  478. //
  479. // Comments:
  480. //
  481. //********************************************************************
  482. STDMETHODIMP CDataXferObj::GetDataHere (
  483. LPFORMATETC pformatetc,
  484. LPSTGMEDIUM pmedium
  485. )
  486. {
  487. SCODE sc = DV_E_FORMATETC;
  488. TestDebugOut("In CDataXferObj::GetDataHere\r\n");
  489. // NOTE: pmedium is an IN parameter. we should NOT set
  490. // pmedium->pUnkForRelease to NULL
  491. // Check the FORMATETC and fill pmedium if valid.
  492. if ( (pformatetc->cfFormat == g_cfEmbeddedObject) &&
  493. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  494. (pformatetc->tymed == TYMED_ISTORAGE) ) {
  495. LPPERSISTSTORAGE pPersistStorage;
  496. /* render CF_EMBEDDEDOBJECT by asking the object to save
  497. ** into the IStorage allocated by the caller.
  498. */
  499. m_lpOleObject->QueryInterface(
  500. IID_IPersistStorage, (LPVOID FAR*)&pPersistStorage);
  501. assert(pPersistStorage);
  502. HRESULT hrErr = OleStdGetOleObjectData(
  503. pPersistStorage, pformatetc, pmedium,0 /*fUseMemory--N/A*/ );
  504. pPersistStorage->Release();
  505. sc = GetScode( hrErr );
  506. }
  507. return ResultFromScode( sc );
  508. }