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.

739 lines
19 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. //BUGBUG: These should be fetched from real header files
  19. #define CF_HDROP 15
  20. typedef struct _dropfilestruct {
  21. DWORD pFiles;
  22. POINT pt;
  23. BOOL fNC;
  24. BOOL fWide;
  25. } DROPFILESTRUCT;
  26. CLIPFORMAT g_cfEmbeddedObject=RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  27. CLIPFORMAT g_cfObjectDescriptor=RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  28. // List of formats offered by our data transfer object via EnumFormatEtc
  29. static FORMATETC s_arrGetFmtEtcs[] =
  30. {
  31. { g_cfEmbeddedObject, NULL, DVASPECT_CONTENT, -1, TYMED_ISTORAGE},
  32. { g_cfObjectDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  33. { CF_METAFILEPICT, NULL, DVASPECT_CONTENT, -1, TYMED_MFPICT}
  34. };
  35. //**********************************************************************
  36. //
  37. // CDataXferObj::Create
  38. //
  39. // Purpose:
  40. //
  41. // Creation routine for CDataXferObj
  42. //
  43. // Parameters:
  44. //
  45. // CSimpleSite FAR *lpSite - Pointer to source CSimpleSite
  46. // this is the container site of the
  47. // source OLE object to be transfered
  48. //
  49. // Return Value:
  50. //
  51. // None
  52. //
  53. // Function Calls:
  54. // Function Location
  55. //
  56. // StgCreateDocfile OLE API
  57. // assert C Runtime
  58. //
  59. // Comments:
  60. // reference count of CDataXferObj will be 0 on return.
  61. //
  62. //********************************************************************
  63. CDataXferObj FAR * CDataXferObj::Create(
  64. CSimpleSite FAR *lpSite,
  65. POINTL FAR* pPointl
  66. )
  67. {
  68. CDataXferObj FAR * lpTemp = new CDataXferObj();
  69. if (!lpTemp)
  70. return NULL;
  71. // create a sub-storage for the object
  72. HRESULT hErr = StgCreateDocfile(
  73. NULL,
  74. STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE |
  75. STGM_DELETEONRELEASE,
  76. 0,
  77. &lpTemp->m_lpObjStorage);
  78. assert(hErr == NOERROR);
  79. if (hErr != NOERROR)
  80. {
  81. delete lpTemp;
  82. return NULL;
  83. }
  84. // Clone the source object
  85. if (lpSite->m_lpOleObject)
  86. {
  87. // Object is loaded; ask the object to save into the new storage
  88. LPPERSISTSTORAGE pPersistStorage;
  89. if (lpSite->m_lpOleObject->QueryInterface(IID_IPersistStorage,
  90. (LPVOID FAR*)&pPersistStorage) != ResultFromScode(S_OK))
  91. {
  92. /* cannot find interface
  93. */
  94. return(NULL);
  95. }
  96. assert(pPersistStorage);
  97. if (OleSave(pPersistStorage, lpTemp->m_lpObjStorage, FALSE)
  98. != ResultFromScode(S_OK))
  99. {
  100. TestDebugOut("Fail in OleSave\n");
  101. }
  102. // pass NULL so that object application won't forget the real stg
  103. if (pPersistStorage->SaveCompleted(NULL) != ResultFromScode(S_OK))
  104. {
  105. TestDebugOut("Fail in IPersistStorage::SaveCompleted\n");
  106. }
  107. pPersistStorage->Release();
  108. }
  109. else
  110. {
  111. // Object not loaded so use cheaper IStorage CopyTo operation
  112. lpSite->m_lpObjStorage->CopyTo(0, NULL, NULL, lpTemp->m_lpObjStorage);
  113. }
  114. if (OleLoad(lpTemp->m_lpObjStorage, IID_IOleObject, NULL,
  115. (LPVOID FAR*)&lpTemp->m_lpOleObject)
  116. != ResultFromScode(S_OK))
  117. {
  118. /* we cannot load the embedded/linked object into the memory
  119. */
  120. return(NULL);
  121. }
  122. assert(lpTemp->m_lpOleObject);
  123. lpTemp->m_sizel = lpSite->m_sizel;
  124. if (pPointl)
  125. lpTemp->m_pointl = *pPointl;
  126. else
  127. lpTemp->m_pointl.x = lpTemp->m_pointl.y = 0;
  128. return lpTemp;
  129. }
  130. //**********************************************************************
  131. //
  132. // CDataXferObj::CDataXferObj
  133. //
  134. // Purpose:
  135. //
  136. // Constructor for CDataXferObj
  137. //
  138. // Parameters:
  139. //
  140. // CSimpleDoc FAR *lpDoc - Pointer to CSimpleDoc
  141. //
  142. // Return Value:
  143. //
  144. // None
  145. //
  146. // Function Calls:
  147. // Function Location
  148. //
  149. //
  150. //********************************************************************
  151. CDataXferObj::CDataXferObj (void)
  152. {
  153. // clear the reference count
  154. m_nCount = 0;
  155. m_lpObjStorage = NULL;
  156. m_lpOleObject = NULL;
  157. m_sizel.cx = m_sizel.cy = 0;
  158. m_pointl.x = m_pointl.y = 0;
  159. }
  160. //**********************************************************************
  161. //
  162. // CDataXferObj::~CDataXferObj
  163. //
  164. // Purpose:
  165. //
  166. // Destructor for CDataXferObj
  167. //
  168. // Parameters:
  169. //
  170. // None
  171. //
  172. // Return Value:
  173. //
  174. // None
  175. //
  176. // Function Calls:
  177. // Function Location
  178. //
  179. // TestDebugOut Windows API
  180. // IOleObject::Release Object
  181. // IStorage::Release OLE API
  182. //
  183. //
  184. //********************************************************************
  185. CDataXferObj::~CDataXferObj ()
  186. {
  187. TestDebugOut ("In CDataXferObj's Destructor \r\n");
  188. if (m_lpOleObject)
  189. {
  190. m_lpOleObject->Release();
  191. m_lpOleObject = NULL;
  192. // Release the storage for this object
  193. m_lpObjStorage->Release();
  194. m_lpObjStorage = NULL;
  195. }
  196. }
  197. //**********************************************************************
  198. //
  199. // CDataXferObj::QueryInterface
  200. //
  201. // Purpose:
  202. //
  203. // Used for interface negotiation of the CDataXferObj instance
  204. //
  205. // Parameters:
  206. //
  207. // REFIID riid - A reference to the interface that is
  208. // being queried.
  209. //
  210. // LPVOID FAR* ppvObj - An out parameter to return a pointer to
  211. // the interface.
  212. //
  213. // Return Value:
  214. //
  215. // S_OK - The interface is supported.
  216. // E_NOINTERFACE - The interface is not supported
  217. //
  218. // Function Calls:
  219. // Function Location
  220. //
  221. // TestDebugOut Windows API
  222. // IsEqualIID OLE API
  223. // ResultFromScode OLE API
  224. // CDataXferObj::AddRef DXFEROBJ.CPP
  225. //
  226. //
  227. //********************************************************************
  228. STDMETHODIMP CDataXferObj::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  229. {
  230. TestDebugOut("In CDataXferObj::QueryInterface\r\n");
  231. if (IsEqualIID( riid, IID_IUnknown) || IsEqualIID(riid, IID_IDataObject))
  232. {
  233. AddRef();
  234. *ppvObj = this;
  235. return NOERROR;
  236. }
  237. // unknown interface requested
  238. *ppvObj = NULL; // must set out pointer parameters to NULL
  239. return ResultFromScode(E_NOINTERFACE);
  240. }
  241. //**********************************************************************
  242. //
  243. // CDataXferObj::AddRef
  244. //
  245. // Purpose:
  246. //
  247. // Increments the reference count of the CDataXferObj instance
  248. //
  249. // Parameters:
  250. //
  251. // None
  252. //
  253. // Return Value:
  254. //
  255. // ULONG - The new reference count of the object
  256. //
  257. // Function Calls:
  258. // Function Location
  259. //
  260. // TestDebugOut Windows API
  261. //
  262. //
  263. //********************************************************************
  264. STDMETHODIMP_(ULONG) CDataXferObj::AddRef()
  265. {
  266. TestDebugOut("In CDataXferObj::AddRef\r\n");
  267. return ++m_nCount;
  268. }
  269. //**********************************************************************
  270. //
  271. // CDataXferObj::Release
  272. //
  273. // Purpose:
  274. //
  275. // Decrements the reference count of the CDataXferObj object
  276. //
  277. // Parameters:
  278. //
  279. // None
  280. //
  281. // Return Value:
  282. //
  283. // ULONG - The new reference count of the object.
  284. //
  285. // Function Calls:
  286. // Function Location
  287. //
  288. // TestDebugOut Windows API
  289. //
  290. //
  291. //********************************************************************
  292. STDMETHODIMP_(ULONG) CDataXferObj::Release()
  293. {
  294. TestDebugOut("In CDataXferObj::Release\r\n");
  295. if (--m_nCount == 0)
  296. {
  297. delete this;
  298. return 0;
  299. }
  300. return m_nCount;
  301. }
  302. /********************************************************************
  303. ** This IDataObject implementation is used for data transfer.
  304. **
  305. ** The following methods are NOT supported for data transfer:
  306. ** IDataObject::SetData -- return E_NOTIMPL
  307. ** IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
  308. ** ::DUnadvise
  309. ** ::EnumDAdvise
  310. ** IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
  311. ** (NOTE: must set pformatetcOut->ptd = NULL)
  312. *********************************************************************/
  313. //**********************************************************************
  314. //
  315. // CDataXferObj::QueryGetData
  316. //
  317. // Purpose:
  318. //
  319. // Called to determine if our object supports a particular
  320. // FORMATETC.
  321. //
  322. // Parameters:
  323. //
  324. // LPFORMATETC pformatetc - Pointer to the FORMATETC being queried for.
  325. //
  326. // Return Value:
  327. //
  328. // DV_E_FORMATETC - The FORMATETC is not supported
  329. // S_OK - The FORMATETC is supported.
  330. //
  331. //
  332. // Function Calls:
  333. // Function Location
  334. //
  335. // TestDebugOut Windows API
  336. // ResultFromScode OLE API
  337. //
  338. // Comments:
  339. // we support the following formats:
  340. // "Embedded Object"
  341. // "Object Descriptor"
  342. // CF_METAFILEPICT
  343. //
  344. //********************************************************************
  345. STDMETHODIMP CDataXferObj::QueryGetData (LPFORMATETC pformatetc)
  346. {
  347. SCODE sc = DV_E_FORMATETC;
  348. TestDebugOut("In CDataXferObj::QueryGetData\r\n");
  349. // check the validity of the formatetc.
  350. if ( (pformatetc->cfFormat == g_cfEmbeddedObject) &&
  351. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  352. (pformatetc->tymed == TYMED_ISTORAGE) )
  353. {
  354. sc = S_OK;
  355. }
  356. else if ( (pformatetc->cfFormat == g_cfObjectDescriptor) &&
  357. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  358. (pformatetc->tymed == TYMED_HGLOBAL) )
  359. {
  360. sc = S_OK;
  361. }
  362. else if ( (pformatetc->cfFormat == CF_METAFILEPICT) &&
  363. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  364. (pformatetc->tymed == TYMED_MFPICT) )
  365. {
  366. sc = S_OK;
  367. }
  368. else if ( (pformatetc->cfFormat == CF_HDROP) &&
  369. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  370. (pformatetc->tymed == TYMED_HGLOBAL) )
  371. {
  372. sc = S_OK;
  373. }
  374. return ResultFromScode(sc);
  375. }
  376. extern BOOL gfUseEmptyEnumerator;
  377. //**********************************************************************
  378. //
  379. // CDataXferObj::EnumFormatEtc
  380. //
  381. // Purpose:
  382. //
  383. // Enumerates the formats that can be used to store data
  384. //
  385. // Parameters:
  386. //
  387. // DWORD dwDirection - format to be enumerated
  388. //
  389. // LPENUMFORMATETC ppenumFormatEtc - where to return the
  390. // instantiated enumerator
  391. //
  392. // Return Value:
  393. //
  394. // S_OK - if the operation is successful
  395. // E_OUTOFMEMORY - if ran out of memory
  396. // E_NOTIMPL - if dwDirection is not supported
  397. //
  398. //
  399. // Function Calls:
  400. // Function Location
  401. //
  402. // TestDebugOut Windows API
  403. // ResultFromScode OLE API
  404. // OleStdEnumFmtEtc_Create OLE2UI
  405. //
  406. //**********************************************************************
  407. STDMETHODIMP CDataXferObj::EnumFormatEtc(
  408. DWORD dwDirection,
  409. LPENUMFORMATETC FAR* ppenumFormatEtc
  410. )
  411. {
  412. SCODE sc = E_NOTIMPL;
  413. TestDebugOut("In CDataXferObj::EnumFormatEtc\r\n");
  414. *ppenumFormatEtc = NULL;
  415. if( gfUseEmptyEnumerator == TRUE )
  416. {
  417. return E_FAIL;
  418. }
  419. if (dwDirection == DATADIR_GET)
  420. {
  421. *ppenumFormatEtc = OleStdEnumFmtEtc_Create(
  422. sizeof(s_arrGetFmtEtcs)/sizeof(s_arrGetFmtEtcs[0]),
  423. s_arrGetFmtEtcs);
  424. if (*ppenumFormatEtc == NULL)
  425. sc = E_OUTOFMEMORY;
  426. else
  427. sc = S_OK;
  428. }
  429. return ResultFromScode(sc);
  430. }
  431. //**********************************************************************
  432. //
  433. // CDataXferObj::GetData
  434. //
  435. // Purpose:
  436. //
  437. // Returns the data in the format specified in pformatetcIn.
  438. //
  439. // Parameters:
  440. //
  441. // LPFORMATETC pformatetcIn - The format requested by the caller
  442. //
  443. // LPSTGMEDIUM pmedium - The medium requested by the caller
  444. //
  445. // Return Value:
  446. //
  447. // DV_E_FORMATETC - Format not supported
  448. // S_OK - Success
  449. //
  450. // Function Calls:
  451. // Function Location
  452. //
  453. // TestDebugOut Windows API
  454. // OleStdGetOleObjectData OLE2UI API
  455. // OleStdGetMetafilePictFromOleObject OLE2UI API
  456. // OleStdGetObjectDescriptorDataFromOleObject OLE2UI API
  457. // ResultFromScode OLE API
  458. // IOleObject::QueryInterface Object
  459. //
  460. // Comments:
  461. // we support GetData for the following formats:
  462. // "Embedded Object"
  463. // "Object Descriptor"
  464. // CF_METAFILEPICT
  465. //
  466. //********************************************************************
  467. STDMETHODIMP CDataXferObj::GetData (
  468. LPFORMATETC pformatetcIn,
  469. LPSTGMEDIUM pmedium
  470. )
  471. {
  472. SCODE sc = DV_E_FORMATETC;
  473. TestDebugOut("In CDataXferObj::GetData\r\n");
  474. // we must set all out pointer parameters to NULL. */
  475. pmedium->tymed = TYMED_NULL;
  476. pmedium->pUnkForRelease = NULL; // we transfer ownership to caller
  477. pmedium->hGlobal = NULL;
  478. // Check the FORMATETC and fill pmedium if valid.
  479. if ( (pformatetcIn->cfFormat == g_cfEmbeddedObject) &&
  480. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  481. (pformatetcIn->tymed == TYMED_ISTORAGE) )
  482. {
  483. LPPERSISTSTORAGE pPersistStorage;
  484. /* render CF_EMBEDDEDOBJECT by asking the object to save
  485. ** into a temporary, DELETEONRELEASE IStorage allocated by us.
  486. */
  487. HRESULT hRes;
  488. if ((hRes=m_lpOleObject->QueryInterface(
  489. IID_IPersistStorage, (LPVOID FAR*)&pPersistStorage))
  490. != ResultFromScode(S_OK))
  491. {
  492. return(hRes);
  493. }
  494. assert(pPersistStorage);
  495. HRESULT hrErr = OleStdGetOleObjectData(
  496. pPersistStorage,
  497. pformatetcIn,
  498. pmedium,
  499. FALSE /* fUseMemory -- (use file-base stg) */
  500. );
  501. pPersistStorage->Release();
  502. sc = GetScode( hrErr );
  503. }
  504. else if ( (pformatetcIn->cfFormat == g_cfObjectDescriptor) &&
  505. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  506. (pformatetcIn->tymed == TYMED_HGLOBAL) )
  507. {
  508. // render CF_OBJECTDESCRIPTOR data
  509. pmedium->hGlobal = OleStdGetObjectDescriptorDataFromOleObject(
  510. m_lpOleObject,
  511. TEXT("Simple OLE 2.0 Container"), //string to identify source
  512. DVASPECT_CONTENT,
  513. m_pointl,
  514. (LPSIZEL)&m_sizel
  515. );
  516. if (! pmedium->hGlobal)
  517. sc = E_OUTOFMEMORY;
  518. else
  519. {
  520. pmedium->tymed = TYMED_HGLOBAL;
  521. sc = S_OK;
  522. }
  523. }
  524. else if ( (pformatetcIn->cfFormat == CF_METAFILEPICT) &&
  525. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  526. (pformatetcIn->tymed == TYMED_MFPICT) )
  527. {
  528. // render CF_METAFILEPICT by drawing the object into a metafile DC
  529. pmedium->hGlobal = OleStdGetMetafilePictFromOleObject(
  530. m_lpOleObject, DVASPECT_CONTENT, NULL, pformatetcIn->ptd);
  531. if (! pmedium->hGlobal)
  532. sc = E_OUTOFMEMORY;
  533. else
  534. {
  535. pmedium->tymed = TYMED_MFPICT;
  536. sc = S_OK;
  537. }
  538. }
  539. else if ( (pformatetcIn->cfFormat == CF_HDROP) &&
  540. (pformatetcIn->dwAspect == DVASPECT_CONTENT) &&
  541. (pformatetcIn->tymed == TYMED_HGLOBAL) )
  542. {
  543. // testing for Win3.1 style drag drop. If we offer
  544. // CF_HDROP ( basically, a list of filenames) in a data object
  545. // given to OLE DoDragDrop, then DoDragDrop will translate
  546. // OLE drag drop into Win3.1 drag drop for Win3.1 drop targets
  547. ULONG cbFile;
  548. char szFile[256];
  549. DROPFILESTRUCT *pdfs;
  550. char *pfile;
  551. cbFile = GetEnvironmentVariable("SystemRoot", szFile, sizeof(szFile));
  552. if( cbFile == 0 )
  553. {
  554. sc = E_FAIL;
  555. goto errRtn;
  556. }
  557. cbFile += sizeof("\\setup.txt");
  558. strcat(szFile, "\\setup.txt");
  559. pmedium->tymed = TYMED_HGLOBAL;
  560. pmedium->hGlobal = GlobalAlloc( GMEM_DDESHARE,
  561. sizeof(DROPFILESTRUCT) +
  562. cbFile + 3);
  563. if( pmedium->hGlobal )
  564. {
  565. pdfs = (DROPFILESTRUCT *)GlobalLock(pmedium->hGlobal);
  566. if( pdfs )
  567. {
  568. pdfs->pFiles = sizeof(DROPFILESTRUCT);
  569. pfile = (char *)((BYTE *)pdfs) + sizeof(DROPFILESTRUCT);
  570. pdfs->fNC = FALSE;
  571. pdfs->fWide = FALSE;
  572. pdfs->pt.x = 0;
  573. pdfs->pt.y = 0;
  574. strcpy(pfile, szFile);
  575. // double-NULL terminate it
  576. pfile[strlen(pfile)+2] = '\0';
  577. GlobalUnlock(pmedium->hGlobal);
  578. sc = S_OK;
  579. }
  580. else
  581. {
  582. sc = E_OUTOFMEMORY;
  583. }
  584. }
  585. else
  586. {
  587. sc = E_OUTOFMEMORY;
  588. }
  589. }
  590. errRtn:
  591. return ResultFromScode( sc );
  592. }
  593. //**********************************************************************
  594. //
  595. // CDataXferObj::GetDataHere
  596. //
  597. // Purpose:
  598. //
  599. // Called to get a data format in a caller supplied location
  600. //
  601. // Parameters:
  602. //
  603. // LPFORMATETC pformatetc - FORMATETC requested
  604. //
  605. // LPSTGMEDIUM pmedium - Medium to return the data
  606. //
  607. // Return Value:
  608. //
  609. // NOERROR - if OleStdGetOleObjectData success
  610. // DATA_E_FORMATETC - We don't support the requested format
  611. //
  612. // Function Calls:
  613. // Function Location
  614. //
  615. // TestDebugOut Windows API
  616. // OleStdGetOleObjectData OLE2UI API
  617. // IOleObject::QueryInterface Object
  618. //
  619. //
  620. //********************************************************************
  621. STDMETHODIMP CDataXferObj::GetDataHere (
  622. LPFORMATETC pformatetc,
  623. LPSTGMEDIUM pmedium
  624. )
  625. {
  626. SCODE sc = DV_E_FORMATETC;
  627. TestDebugOut("In CDataXferObj::GetDataHere\r\n");
  628. // NOTE: pmedium is an IN parameter. we should NOT set
  629. // pmedium->pUnkForRelease to NULL
  630. // Check the FORMATETC and fill pmedium if valid.
  631. if ( (pformatetc->cfFormat == g_cfEmbeddedObject) &&
  632. (pformatetc->dwAspect == DVASPECT_CONTENT) &&
  633. (pformatetc->tymed == TYMED_ISTORAGE) )
  634. {
  635. LPPERSISTSTORAGE pPersistStorage;
  636. /* render CF_EMBEDDEDOBJECT by asking the object to save
  637. ** into the IStorage allocated by the caller.
  638. */
  639. HRESULT hRes;
  640. if ((hRes=m_lpOleObject->QueryInterface(
  641. IID_IPersistStorage, (LPVOID FAR*)&pPersistStorage))
  642. != ResultFromScode(S_OK))
  643. {
  644. return(hRes);
  645. }
  646. assert(pPersistStorage);
  647. HRESULT hrErr = OleStdGetOleObjectData(
  648. pPersistStorage, pformatetc, pmedium,0 /*fUseMemory--N/A*/ );
  649. pPersistStorage->Release();
  650. sc = GetScode( hrErr );
  651. }
  652. return ResultFromScode( sc );
  653. }