Leaked source code of windows server 2003
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.

1161 lines
32 KiB

  1. /*---------------------------------------------------------------------------
  2. | CDRAG.C
  3. | This file has the interfaces for the object transferred through the
  4. | Clipboard or through a Drag-Drop. These interfaces unlike the interfaces
  5. | implemented in the file OBJ.C transfer the state of the object at
  6. | Edit->Copy time or Drag-Drop time. The interfaces in OBJ.C transfer the
  7. | real-time Object Data.
  8. |
  9. | Created by: Vij Rajarajan (VijR)
  10. +---------------------------------------------------------------------------*/
  11. #define SERVERONLY
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #include "mpole.h"
  15. #include "mplayer.h"
  16. #include <malloc.h>
  17. #define OLESTDDELIM "!"
  18. #define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
  19. HANDLE GetMetafilePict (VOID);
  20. SCODE SaveMoniker (LPSTREAM lpstream);
  21. HANDLE PASCAL GetDib (VOID);
  22. HANDLE ghClipData = NULL; /* Holds the data handle at the time of Copy */
  23. HANDLE ghClipMetafile = NULL; /* to clipboard */
  24. HANDLE ghClipDib = NULL;
  25. /* Global flag to indicate OLE was initialized for drag.
  26. * This happens on a separate thread from the main window,
  27. * so we need to initialize and uninitialize independently.
  28. */
  29. BOOL gfOleInitForDrag = FALSE;
  30. extern LPDATAOBJECT gpClipboardDataObject;
  31. /**************************************************************************
  32. * CutOrCopyObject
  33. * Sets the clipboard with the IDataObject interface of the lpdoc
  34. * object passed as the argument. The function also saves a snapshot of
  35. * the state of the object in the globals ghClipMetafile, ghClipData,
  36. * and ghClipDib.
  37. **************************************************************************/
  38. void CutOrCopyObj (LPDOC lpdoc)
  39. {
  40. LPDATAOBJECT lpDataObj;
  41. lpDataObj = (LPDATAOBJECT)CreateClipDragDataObject(lpdoc,TRUE);
  42. if (lpDataObj != NULL) {
  43. if (ghClipData)
  44. GLOBALFREE(ghClipData);
  45. if (ghClipMetafile) {
  46. {
  47. // note that ghClipMetafile is set deep in PictureFromDib and contains
  48. // a handle to a windows metafile. Clean this up properly here. There may
  49. // be other memory/handle leaks caused by this coding of the metafile handle elsewhere.
  50. // SteveZ
  51. LPMETAFILEPICT pmfp;
  52. BOOL bReturn;
  53. DWORD dw;
  54. pmfp = (LPMETAFILEPICT)GLOBALLOCK(ghClipMetafile);
  55. bReturn = DeleteMetaFile(pmfp->hMF);
  56. if (!bReturn) {
  57. dw = GetLastError();
  58. }
  59. GLOBALUNLOCK(ghClipMetafile);
  60. }
  61. GLOBALFREE(ghClipMetafile);
  62. }
  63. if (ghClipDib)
  64. GLOBALFREE(ghClipDib);
  65. ghClipData = GetLink();
  66. ghClipMetafile = GetMetafilePict();
  67. ghClipDib = GetDib();
  68. OleSetClipboard(lpDataObj);
  69. IDataObject_Release(lpDataObj);
  70. gpClipboardDataObject = lpDataObj;
  71. }
  72. }
  73. /**************************************************************************
  74. * CreateClipDragDataObject:
  75. * This function returns an initialized instance of the CLIPDRAGDATA data
  76. * structure. fClipData = TRUE if the object is for the clipboard and
  77. * = FALSE if the object is for Drag-Drop operation.
  78. **************************************************************************/
  79. LPCLIPDRAGDATA CreateClipDragDataObject(LPDOC lpdoc, BOOL fClipData)
  80. {
  81. LPCLIPDRAGDATA lpclipdragdata;
  82. lpclipdragdata = malloc( sizeof(CLIPDRAGDATA) );
  83. if (lpclipdragdata == NULL)
  84. {
  85. DPF0("Malloc failed in CreateClipDragDataObject\n");
  86. return NULL;
  87. }
  88. lpclipdragdata->m_IDataObject.lpVtbl = &clipdragVtbl;
  89. lpclipdragdata->lpClipDragEnum = NULL;
  90. lpclipdragdata->m_IDropSource.lpVtbl = &dropsourceVtbl;
  91. lpclipdragdata->m_IDataObject.lpclipdragdata = lpclipdragdata;
  92. lpclipdragdata->m_IDropSource.lpclipdragdata = lpclipdragdata;
  93. lpclipdragdata->lpdoc = lpdoc;
  94. lpclipdragdata->cRef = 1;
  95. lpclipdragdata->fClipData = fClipData;
  96. return lpclipdragdata;
  97. }
  98. /**************************************************************************
  99. * DoDrag:
  100. * Initiates the Drag-Drop operation.
  101. **************************************************************************/
  102. void DoDrag(void)
  103. {
  104. DWORD dwEffect;
  105. LPCLIPDRAGDATA lpclipdragdata;
  106. if (!InitOLE(&gfOleInitForDrag, NULL))
  107. {
  108. DPF0("Initialization of OLE FAILED!! Can't do drag.\n");
  109. return;
  110. }
  111. lpclipdragdata = CreateClipDragDataObject ((LPDOC)&docMain, FALSE);
  112. if (lpclipdragdata)
  113. {
  114. HRESULT hr;
  115. hr = (HRESULT)DoDragDrop((IDataObject FAR*)&lpclipdragdata->m_IDataObject,
  116. (IDropSource FAR*)&lpclipdragdata->m_IDropSource,
  117. DROPEFFECT_COPY, &dwEffect);
  118. DPF("DoDragDrop returned %s\n", hr == S_OK ? "S_OK" : hr == DRAGDROP_S_DROP ? "DRAGDROP_S_DROP" : hr == DRAGDROP_S_CANCEL ? "DRAGDROP_S_CANCEL" : hr == E_OUTOFMEMORY ? "E_OUTOFMEMORY" : hr == E_UNEXPECTED ? "E_UNEXPECTED" : "<?>");
  119. IDataObject_Release((IDataObject *)&lpclipdragdata->m_IDataObject);
  120. }
  121. }
  122. void CleanUpDrag(void)
  123. {
  124. if (gfOleInitForDrag)
  125. {
  126. DPF("Uninitializing OLE for thread %d\n", GetCurrentThreadId());
  127. CoDisconnectObject((LPUNKNOWN)&docMain, 0);
  128. OleUninitialize();
  129. gfOleInitForDrag = FALSE;
  130. }
  131. }
  132. /**************************************************************************
  133. * GetObjectDescriptorData:
  134. * Packages an ObjectDescriptor data structure.
  135. **************************************************************************/
  136. HGLOBAL GetObjectDescriptorData(
  137. CLSID clsid,
  138. DWORD dwAspect,
  139. SIZEL sizel,
  140. POINTL pointl,
  141. DWORD dwStatus,
  142. LPTSTR lpszFullUserTypeName,
  143. LPTSTR lpszSrcOfCopy
  144. )
  145. {
  146. HGLOBAL hMem = NULL;
  147. IBindCtx FAR *pbc = NULL;
  148. LPOBJECTDESCRIPTOR lpOD;
  149. DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
  150. DWORD Offset;
  151. // Get the length of Full User Type Name:
  152. dwFullUserTypeNameLen = STRING_BYTE_COUNT_NULLOK(lpszFullUserTypeName);
  153. dwFullUserTypeNameLen *= (sizeof(WCHAR) / sizeof(TCHAR));
  154. // Get the Source of Copy string and its length:
  155. dwSrcOfCopyLen = STRING_BYTE_COUNT_NULLOK(lpszSrcOfCopy);
  156. dwSrcOfCopyLen *= (sizeof(WCHAR) / sizeof(TCHAR));
  157. if (lpszSrcOfCopy == NULL) {
  158. // No src moniker so use user type name as source string.
  159. lpszSrcOfCopy = lpszFullUserTypeName;
  160. dwSrcOfCopyLen = dwFullUserTypeNameLen;
  161. }
  162. // Allocate space for OBJECTDESCRIPTOR and the additional string data
  163. dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
  164. hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  165. dwObjectDescSize
  166. + dwFullUserTypeNameLen
  167. + dwSrcOfCopyLen);
  168. if (NULL == hMem)
  169. goto error;
  170. lpOD = (LPOBJECTDESCRIPTOR)GLOBALLOCK(hMem);
  171. if(!lpOD)
  172. goto error;
  173. // Set offset to copy strings at end of the object descriptor:
  174. Offset = dwObjectDescSize;
  175. // Set the FullUserTypeName offset and copy the string
  176. if (lpszFullUserTypeName)
  177. {
  178. lpOD->dwFullUserTypeName = Offset;
  179. #ifdef UNICODE
  180. lstrcpy((LPWSTR)(((LPBYTE)lpOD)+Offset), lpszFullUserTypeName);
  181. #else
  182. AnsiToUnicodeString(lpszFullUserTypeName, (LPWSTR)(((LPBYTE)lpOD)+Offset), -1);
  183. #endif
  184. Offset += dwFullUserTypeNameLen;
  185. }
  186. else lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present
  187. // Set the SrcOfCopy offset and copy the string
  188. if (lpszSrcOfCopy)
  189. {
  190. lpOD->dwSrcOfCopy = Offset;
  191. #ifdef UNICODE
  192. lstrcpy((LPWSTR)(((LPBYTE)lpOD)+Offset), lpszSrcOfCopy);
  193. #else
  194. AnsiToUnicodeString(lpszSrcOfCopy, (LPWSTR)(((LPBYTE)lpOD)+Offset), -1);
  195. #endif
  196. }
  197. else lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present
  198. // Initialize the rest of the OBJECTDESCRIPTOR
  199. lpOD->cbSize = dwObjectDescSize + dwFullUserTypeNameLen + dwSrcOfCopyLen;
  200. lpOD->clsid = clsid;
  201. lpOD->dwDrawAspect = dwAspect;
  202. lpOD->sizel = sizel;
  203. lpOD->pointl = pointl;
  204. lpOD->dwStatus = dwStatus;
  205. GLOBALUNLOCK(hMem);
  206. return hMem;
  207. error:
  208. if (hMem)
  209. {
  210. GLOBALUNLOCK(hMem);
  211. GLOBALFREE(hMem);
  212. }
  213. return NULL;
  214. }
  215. /**************************************************************************
  216. *************** IUnknown INTERFACE INPLEMENTATION.
  217. **************************************************************************/
  218. STDMETHODIMP ClipDragUnknownQueryInterface (
  219. LPCLIPDRAGDATA lpclipdragdata, // data object ptr
  220. REFIID riidReq, // IID required
  221. LPVOID FAR * lplpUnk // pre for returning the interface
  222. )
  223. {
  224. if ( IsEqualIID(riidReq, &IID_IDataObject) || IsEqualIID(riidReq, &IID_IUnknown) )
  225. {
  226. *lplpUnk = (LPVOID) lpclipdragdata;
  227. }
  228. else if ( IsEqualIID(riidReq, &IID_IDropSource))
  229. {
  230. *lplpUnk = (LPVOID) &lpclipdragdata->m_IDropSource;
  231. }
  232. else
  233. {
  234. *lplpUnk = (LPVOID) NULL;
  235. RETURN_RESULT(E_NOINTERFACE);
  236. }
  237. DPF("ClipDragAddRef: cRef = %d\n", lpclipdragdata->cRef + 1);
  238. lpclipdragdata->cRef++;
  239. return NOERROR;
  240. }
  241. STDMETHODIMP_(ULONG) ClipDragUnknownAddRef(
  242. LPCLIPDRAGDATA lpclipdragdata // data object ptr
  243. )
  244. {
  245. DPF("ClipDragAddRef: cRef = %d\n", lpclipdragdata->cRef + 1);
  246. return ++lpclipdragdata->cRef;
  247. }
  248. STDMETHODIMP_(ULONG) ClipDragUnknownRelease (
  249. LPCLIPDRAGDATA lpclipdragdata
  250. )
  251. {
  252. DPF("ClipDragRelease: cRef = %d\n", lpclipdragdata->cRef - 1);
  253. if ( --lpclipdragdata->cRef != 0 )
  254. return lpclipdragdata->cRef;
  255. free(lpclipdragdata);
  256. return 0;
  257. }
  258. /**************************************************************************
  259. ****************** IDataObject INTERFACE IMPLEMENTATION.
  260. **************************************************************************/
  261. STDMETHODIMP ClipDragQueryInterface (
  262. LPDATAOBJECT lpDataObj, // data object ptr
  263. REFIID riidReq, // IID required
  264. LPVOID FAR * lplpUnk // pre for returning the interface
  265. )
  266. {
  267. DPF("ClipDragQueryInterface\n");
  268. return
  269. ClipDragUnknownQueryInterface (
  270. (LPCLIPDRAGDATA) (( struct CDataObject FAR* )lpDataObj)->lpclipdragdata ,
  271. riidReq,
  272. lplpUnk
  273. );
  274. }
  275. STDMETHODIMP_(ULONG) ClipDragAddRef(
  276. LPDATAOBJECT lpDataObj // data object ptr
  277. )
  278. {
  279. return
  280. ClipDragUnknownAddRef (
  281. (LPCLIPDRAGDATA) (( struct CDataObject FAR* )lpDataObj)->lpclipdragdata
  282. );
  283. }
  284. STDMETHODIMP_(ULONG) ClipDragRelease (
  285. LPDATAOBJECT lpDataObj // data object ptr
  286. )
  287. {
  288. return
  289. ClipDragUnknownRelease (
  290. (LPCLIPDRAGDATA) (( struct CDataObject FAR* )lpDataObj)->lpclipdragdata
  291. );
  292. }
  293. /* Routines called by ClipDragGetData, one for each format supported:
  294. */
  295. HRESULT ClipDragGetData_EmbedSource(
  296. LPCLIPDRAGDATA lpclipdragdata,
  297. LPSTGMEDIUM lpMedium
  298. );
  299. HRESULT ClipDragGetData_ObjectDescriptor(
  300. LPCLIPDRAGDATA lpclipdragdata,
  301. LPSTGMEDIUM lpMedium
  302. );
  303. HRESULT ClipDragGetData_MetafilePict(
  304. LPCLIPDRAGDATA lpclipdragdata,
  305. LPSTGMEDIUM lpMedium
  306. );
  307. HRESULT ClipDragGetData_DIB(
  308. LPCLIPDRAGDATA lpclipdragdata,
  309. LPSTGMEDIUM lpMedium
  310. );
  311. /**************************************************************************
  312. * ClipDragGetData:
  313. * Returns the saved snapshot of the Object in the required format,
  314. * if available. If not, returns the current snapshot. We still write
  315. * out the OLE1 embedding to maintain backward compatibility.
  316. **************************************************************************/
  317. STDMETHODIMP ClipDragGetData (
  318. LPDATAOBJECT lpDataObj,
  319. LPFORMATETC lpformatetc,
  320. LPSTGMEDIUM lpMedium
  321. )
  322. {
  323. LPCLIPDRAGDATA lpclipdragdata;
  324. SCODE scode;
  325. STGMEDIUM stgm;
  326. CLIPFORMAT cfFormat;
  327. DWORD tymed;
  328. DPF("ClipDragGetData\n");
  329. if (lpMedium == NULL)
  330. RETURN_RESULT( E_FAIL);
  331. VERIFY_LINDEX(lpformatetc->lindex);
  332. memset(&stgm, 0, sizeof stgm);
  333. lpclipdragdata = (LPCLIPDRAGDATA) lpDataObj;
  334. cfFormat = lpformatetc->cfFormat;
  335. tymed = lpformatetc->tymed;
  336. if ((cfFormat == cfEmbedSource) && (tymed & TYMED_ISTORAGE))
  337. scode = ClipDragGetData_EmbedSource(lpclipdragdata, &stgm);
  338. else if ((cfFormat == cfObjectDescriptor) && (tymed & TYMED_HGLOBAL))
  339. scode = ClipDragGetData_ObjectDescriptor(lpclipdragdata, &stgm);
  340. else if ((cfFormat == CF_METAFILEPICT) && (tymed & TYMED_MFPICT))
  341. scode = ClipDragGetData_MetafilePict(lpclipdragdata, &stgm);
  342. else if ((cfFormat == CF_DIB) && (tymed & TYMED_HGLOBAL))
  343. scode = ClipDragGetData_DIB(lpclipdragdata, &stgm);
  344. else
  345. scode = DATA_E_FORMATETC;
  346. if (scode == S_OK)
  347. *lpMedium = stgm;
  348. RETURN_RESULT(scode);
  349. }
  350. #ifdef DEBUG
  351. BOOL WriteOLE2Class( )
  352. {
  353. HKEY hKey;
  354. TCHAR Data[8];
  355. DWORD Size;
  356. BOOL rc = FALSE;
  357. if( RegOpenKeyEx( HKEY_CLASSES_ROOT, TEXT( "MPlayer\\Debug" ), 0,
  358. KEY_READ, &hKey ) == ERROR_SUCCESS )
  359. {
  360. if( RegQueryValueEx( hKey, TEXT( "WriteOLE2Class" ), NULL, NULL,
  361. (LPBYTE)&Data, &Size ) == ERROR_SUCCESS )
  362. {
  363. if( Data[0] == TEXT( 'y' ) || Data[0] == TEXT( 'Y' ) )
  364. rc = TRUE;
  365. }
  366. RegCloseKey( hKey );
  367. }
  368. return rc;
  369. }
  370. #endif
  371. /*
  372. *
  373. */
  374. HRESULT ClipDragGetData_EmbedSource(
  375. LPCLIPDRAGDATA lpclipdragdata,
  376. LPSTGMEDIUM lpMedium
  377. )
  378. {
  379. SCODE scode;
  380. LPSTREAM lpstm = NULL;
  381. LPWSTR lpszUserType;
  382. HANDLE hGlobal = NULL;
  383. DWORD_PTR nNativeSz;
  384. ULONG cbWritten;
  385. scode = GetScode(StgCreateDocfile(NULL, /* Create temporary compound file */
  386. STGM_CREATE | STGM_SALL | STGM_DELETEONRELEASE,
  387. 0, /* Reserved */
  388. &lpMedium->pstg));
  389. if (scode != S_OK)
  390. RETURN_RESULT(scode);
  391. lpMedium->tymed = TYMED_ISTORAGE;
  392. lpMedium->pUnkForRelease = NULL;
  393. //Mark the Object as OLE1.
  394. #ifdef UNICODE
  395. lpszUserType = gachClassRoot;
  396. #else
  397. lpszUserType = AllocateUnicodeString(gachClassRoot);
  398. if (!lpszUserType)
  399. RETURN_RESULT(E_OUTOFMEMORY);
  400. #endif
  401. #ifdef DEBUG
  402. if(WriteOLE2Class())
  403. {
  404. DPF("ClipDragGetData_EmbedSource: Writing OLE2 class ID\n");
  405. scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_MPLAYER));
  406. }
  407. else
  408. #endif
  409. scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_OLE1MPLAYER));
  410. if (scode != S_OK)
  411. RETURN_RESULT(scode);
  412. scode = GetScode(WriteFmtUserTypeStg(lpMedium->pstg, cfMPlayer, lpszUserType));
  413. #ifndef UNICODE
  414. FreeUnicodeString(lpszUserType);
  415. #endif
  416. if (scode != S_OK)
  417. RETURN_RESULT(scode);
  418. //Write to \1Ole10Native stream so that this will be readable by OLE1 Mplayer
  419. scode = GetScode(IStorage_CreateStream(lpMedium->pstg,sz1Ole10Native,
  420. STGM_CREATE | STGM_SALL,0,0,&lpstm));
  421. if (scode != S_OK)
  422. RETURN_RESULT(scode);
  423. //Duplicate the handle we have saved.
  424. if(lpclipdragdata->fClipData && ghClipData)
  425. hGlobal = OleDuplicateData(ghClipData, cfEmbedSource, 0);
  426. else
  427. hGlobal = GetLink();
  428. if (!hGlobal)
  429. {
  430. GLOBALFREE(hGlobal);
  431. RETURN_RESULT(E_OUTOFMEMORY);
  432. }
  433. nNativeSz = GlobalSize(hGlobal);
  434. lpclipdragdata->lpdoc->native = GLOBALLOCK(hGlobal);
  435. if(!lpclipdragdata->lpdoc->native)
  436. {
  437. GLOBALUNLOCK(hGlobal);
  438. GLOBALFREE(hGlobal);
  439. RETURN_RESULT(E_OUTOFMEMORY); /* What's the right error here? */
  440. }
  441. scode = GetScode(IStream_Write(lpstm,&nNativeSz,4,&cbWritten));
  442. if (scode != S_OK)
  443. RETURN_RESULT(scode);
  444. scode = GetScode(IStream_Write(lpstm,lpclipdragdata->lpdoc->native,
  445. (ULONG)nNativeSz,&cbWritten));
  446. if (cbWritten != nNativeSz)
  447. scode = E_FAIL ;
  448. IStream_Release(lpstm);
  449. GLOBALUNLOCK(hGlobal);
  450. GLOBALFREE(hGlobal);
  451. lpstm = NULL;
  452. RETURN_RESULT(scode);
  453. }
  454. /*
  455. *
  456. */
  457. HRESULT ClipDragGetData_ObjectDescriptor(
  458. LPCLIPDRAGDATA lpclipdragdata,
  459. LPSTGMEDIUM lpMedium
  460. )
  461. {
  462. SIZEL sizel;
  463. POINTL pointl;
  464. TCHAR displayname[256];
  465. LPTSTR lpszdn = (LPTSTR)displayname;
  466. HGLOBAL hobjdesc;
  467. DWORD dwStatus = 0;
  468. static SZCODE aszDispFormat[] = TEXT("%"TS" : %"TS"");
  469. DPF("\n^^^^^^CDGetdata: OBJECTDESC");
  470. sizel.cx = extWidth;
  471. sizel.cy = extHeight;
  472. pointl.x = pointl.y = 0;
  473. wsprintf(displayname, aszDispFormat, (LPTSTR)gachClassRoot, (LPTSTR)gachWindowTitle);
  474. #ifdef DEBUG
  475. if(WriteOLE2Class())
  476. {
  477. DPF("ClipDragGetData_ObjectDescriptor: Getting OLE2 class\n");
  478. hobjdesc = GetObjectDescriptorData(CLSID_MPLAYER, DVASPECT_CONTENT,
  479. sizel, pointl, dwStatus, lpszdn, lpszdn);
  480. }
  481. else
  482. #endif
  483. hobjdesc = GetObjectDescriptorData(CLSID_OLE1MPLAYER, DVASPECT_CONTENT,
  484. sizel, pointl, dwStatus, lpszdn, lpszdn);
  485. if (hobjdesc)
  486. {
  487. lpMedium->hGlobal = hobjdesc;
  488. lpMedium->tymed = TYMED_HGLOBAL;
  489. lpMedium->pUnkForRelease = NULL;
  490. return NOERROR;
  491. }
  492. RETURN_RESULT(E_OUTOFMEMORY);
  493. }
  494. /*
  495. *
  496. */
  497. HRESULT ClipDragGetData_MetafilePict(
  498. LPCLIPDRAGDATA lpclipdragdata,
  499. LPSTGMEDIUM lpMedium
  500. )
  501. {
  502. SCODE scode;
  503. lpMedium->tymed = TYMED_MFPICT;
  504. if(lpclipdragdata->fClipData && ghClipMetafile)
  505. lpMedium->hGlobal = OleDuplicateData(ghClipMetafile, CF_METAFILEPICT, 0);
  506. else
  507. lpMedium->hGlobal = GetMetafilePict();
  508. if (lpMedium->hGlobal == NULL)
  509. scode = E_OUTOFMEMORY;
  510. else
  511. scode = S_OK;
  512. lpMedium->pUnkForRelease = NULL;
  513. RETURN_RESULT(scode);
  514. }
  515. /*
  516. *
  517. */
  518. HRESULT ClipDragGetData_DIB(
  519. LPCLIPDRAGDATA lpclipdragdata,
  520. LPSTGMEDIUM lpMedium
  521. )
  522. {
  523. SCODE scode;
  524. lpMedium->tymed = TYMED_HGLOBAL;
  525. if(lpclipdragdata->fClipData && ghClipDib)
  526. lpMedium->hGlobal = OleDuplicateData(ghClipDib, CF_DIB, 0);
  527. else
  528. /* We must make sure GetDib() happens on the main thread,
  529. * because otherwise MCI complains.
  530. */
  531. lpMedium->hGlobal = (HANDLE)SendMessage(ghwndApp, WM_GETDIB, 0, 0);
  532. if (lpMedium->hGlobal == NULL)
  533. scode = E_OUTOFMEMORY;
  534. else
  535. scode = S_OK;
  536. lpMedium->pUnkForRelease = NULL;
  537. RETURN_RESULT(scode);
  538. }
  539. /**************************************************************************
  540. * ClipDragGetDataHere:
  541. * Make the embedding by writing into the Stream Mplayer3EmbedSource.
  542. *
  543. **************************************************************************/
  544. STDMETHODIMP ClipDragGetDataHere (
  545. LPDATAOBJECT lpDataObj,
  546. LPFORMATETC lpformatetc,
  547. LPSTGMEDIUM lpMedium
  548. )
  549. {
  550. LPCLIPDRAGDATA lpclipdragdata;
  551. HANDLE hGlobal = NULL;
  552. DWORD_PTR nNativeSz;
  553. LPTSTR lpnative;
  554. ULONG cbWritten;
  555. DPF("ClipDragGetDataHere\n");
  556. if (lpMedium == NULL)
  557. RETURN_RESULT(E_FAIL);
  558. VERIFY_LINDEX(lpformatetc->lindex);
  559. lpclipdragdata = (LPCLIPDRAGDATA) lpDataObj;
  560. if (lpformatetc->cfFormat == cfEmbedSource)
  561. {
  562. SCODE scode;
  563. LPSTREAM lpstm = NULL;
  564. LPWSTR lpszUserType;
  565. if (lpMedium->tymed != TYMED_ISTORAGE)
  566. RETURN_RESULT(DATA_E_FORMATETC);
  567. #ifdef UNICODE
  568. lpszUserType = gachClassRoot;
  569. #else
  570. lpszUserType = AllocateUnicodeString(gachClassRoot);
  571. if (!lpszUserType)
  572. RETURN_RESULT(E_OUTOFMEMORY);
  573. #endif
  574. //Mark the object as OLE1 MPlayer object for backward compatibility:
  575. #ifdef DEBUG
  576. if(WriteOLE2Class())
  577. {
  578. DPF("ClipDragGetDataHere: Writing OLE2 class ID\n");
  579. scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_MPLAYER));
  580. }
  581. else
  582. #endif
  583. scode = GetScode(WriteClassStg(lpMedium->pstg, &CLSID_OLE1MPLAYER));
  584. if (scode != S_OK)
  585. RETURN_RESULT(scode);
  586. scode = GetScode(WriteFmtUserTypeStg(lpMedium->pstg, cfMPlayer, lpszUserType));
  587. #ifndef UNICODE
  588. FreeUnicodeString(lpszUserType);
  589. #endif
  590. if (scode != S_OK)
  591. RETURN_RESULT(scode);
  592. //Write to the \1Ole10Native stream so the object will be readable by OLE1 Mplayer
  593. if ((scode = GetScode(IStorage_CreateStream(lpMedium->pstg,
  594. sz1Ole10Native,
  595. STGM_CREATE | STGM_SALL,
  596. 0, 0, &lpstm))) != S_OK)
  597. RETURN_RESULT(scode);
  598. //Duplicate and give out the handle we have saved.
  599. if(lpclipdragdata->fClipData && ghClipData)
  600. hGlobal = OleDuplicateData(ghClipData, cfEmbedSource, 0);
  601. else
  602. hGlobal = GetLink();
  603. if (!hGlobal)
  604. {
  605. RETURN_RESULT(E_OUTOFMEMORY);
  606. }
  607. nNativeSz = GlobalSize(hGlobal);
  608. lpnative = GLOBALLOCK(hGlobal);
  609. if (!lpnative)
  610. {
  611. GLOBALUNLOCK(hGlobal);
  612. GLOBALFREE(hGlobal);
  613. RETURN_RESULT(E_OUTOFMEMORY);
  614. }
  615. scode = GetScode(IStream_Write(lpstm,&nNativeSz,4,&cbWritten));
  616. scode = GetScode(IStream_Write(lpstm,lpnative,(ULONG)nNativeSz,&cbWritten));
  617. if (cbWritten != nNativeSz) scode = E_FAIL ;
  618. IStream_Release(lpstm);
  619. GLOBALUNLOCK(hGlobal);
  620. GLOBALFREE(hGlobal);
  621. RETURN_RESULT( scode);
  622. } else
  623. RETURN_RESULT(DATA_E_FORMATETC);
  624. }
  625. STDMETHODIMP ClipDragQueryGetData (
  626. LPDATAOBJECT lpDataObj,
  627. LPFORMATETC lpformatetc
  628. )
  629. {
  630. DPF("ClipDragQueryGetData\n");
  631. if (lpformatetc->cfFormat == cfEmbedSource ||
  632. lpformatetc->cfFormat == CF_METAFILEPICT ||
  633. lpformatetc->cfFormat == CF_DIB ||
  634. lpformatetc->cfFormat == cfObjectDescriptor
  635. )
  636. return NOERROR;
  637. else
  638. RETURN_RESULT(DATA_E_FORMATETC);
  639. }
  640. STDMETHODIMP ClipDragGetCanonicalFormatEtc(
  641. LPDATAOBJECT lpDataObj,
  642. LPFORMATETC lpformatetc,
  643. LPFORMATETC lpformatetcOut
  644. )
  645. {
  646. DPF("ClipDragGetCanonicalFormatEtc\n");
  647. RETURN_RESULT(DATA_S_SAMEFORMATETC);
  648. }
  649. STDMETHODIMP ClipDragSetData (
  650. LPDATAOBJECT lpDataObj,
  651. LPFORMATETC lpformatetc,
  652. LPSTGMEDIUM lpmedium,
  653. BOOL fRelease
  654. )
  655. {
  656. DPF("ClipDragSetData\n");
  657. RETURN_RESULT(E_NOTIMPL);
  658. }
  659. STDMETHODIMP ClipDragEnumFormatEtc(
  660. LPDATAOBJECT lpDataObj,
  661. DWORD dwDirection,
  662. LPENUMFORMATETC FAR* ppenumFormatEtc
  663. ){
  664. LPCLIPDRAGENUM lpclipdragenum;
  665. if (ppenumFormatEtc != NULL)
  666. *ppenumFormatEtc = NULL;
  667. lpclipdragenum = _fmalloc(sizeof(CLIPDRAGENUM));
  668. if (lpclipdragenum == NULL)
  669. RETURN_RESULT(E_OUTOFMEMORY);
  670. lpclipdragenum->lpVtbl = &ClipDragEnumVtbl;
  671. lpclipdragenum->cRef = 1;
  672. lpclipdragenum->lpClipDragData = (LPCLIPDRAGDATA) lpDataObj;
  673. lpclipdragenum->cfNext = cfEmbedSource;
  674. lpclipdragenum->lpClipDragData->lpClipDragEnum = lpclipdragenum;
  675. *ppenumFormatEtc = (LPENUMFORMATETC) lpclipdragenum;
  676. return NOERROR;
  677. }
  678. STDMETHODIMP ClipDragAdvise(
  679. LPDATAOBJECT LPDATAOBJect,
  680. FORMATETC FAR* pFormatetc,
  681. DWORD advf,
  682. IAdviseSink FAR* pAdvSink,
  683. DWORD FAR* pdwConnection
  684. )
  685. {
  686. RETURN_RESULT(E_NOTIMPL);
  687. }
  688. STDMETHODIMP ClipDragUnadvise(
  689. LPDATAOBJECT LPDATAOBJect,
  690. DWORD dwConnection
  691. )
  692. {
  693. RETURN_RESULT(E_NOTIMPL);
  694. }
  695. STDMETHODIMP ClipDragEnumAdvise(
  696. LPDATAOBJECT LPDATAOBJect,
  697. LPENUMSTATDATA FAR* ppenumAdvise
  698. )
  699. {
  700. RETURN_RESULT(E_NOTIMPL);
  701. }
  702. /**************************************************************************
  703. **************** IDropSource INTERFACE IMPLEMENTAION.
  704. **************************************************************************/
  705. STDMETHODIMP DropSourceQueryInterface (
  706. LPDROPSOURCE lpdropsource, // data object ptr
  707. REFIID riidReq, // IID required
  708. LPVOID FAR * lplpUnk // pre for returning the interface
  709. )
  710. {
  711. return
  712. ClipDragUnknownQueryInterface (
  713. (LPCLIPDRAGDATA) ( ( struct CDropSource FAR* )lpdropsource)->lpclipdragdata ,
  714. riidReq,
  715. lplpUnk
  716. );
  717. }
  718. STDMETHODIMP_(ULONG) DropSourceAddRef(
  719. LPDROPSOURCE lpdropsource // data object ptr
  720. )
  721. {
  722. return
  723. ClipDragUnknownAddRef (
  724. (LPCLIPDRAGDATA) ( ( struct CDropSource FAR* )lpdropsource)->lpclipdragdata
  725. );
  726. }
  727. STDMETHODIMP_(ULONG) DropSourceRelease (
  728. LPDROPSOURCE lpdropsource // data object ptr
  729. )
  730. {
  731. return
  732. ClipDragUnknownRelease (
  733. (LPCLIPDRAGDATA) ( ( struct CDropSource FAR* )lpdropsource)->lpclipdragdata
  734. );
  735. }
  736. STDMETHODIMP DropSourceQueryContinueDrag (
  737. LPDROPSOURCE lpdropsource, // data object ptr
  738. BOOL fEscapePressed,
  739. DWORD grfKeyState
  740. )
  741. {
  742. if (fEscapePressed)
  743. {
  744. DPF("DropSourceQueryContinueDrag: fEscapePressed\n");
  745. RETURN_RESULT( DRAGDROP_S_CANCEL);
  746. }
  747. else if (!(grfKeyState & MK_LBUTTON))
  748. {
  749. DPF("DropSourceQueryContinueDrag: !(grfKeyState & MK_LBUTTON)\n");
  750. RETURN_RESULT(DRAGDROP_S_DROP);
  751. }
  752. else
  753. return NOERROR;
  754. }
  755. STDMETHODIMP DropSourceGiveFeedback (
  756. LPDROPSOURCE lpsropsource, // data object ptr
  757. DWORD dwEffect
  758. )
  759. {
  760. DPF("DropSourceGiveFeedback\n");
  761. RETURN_RESULT(DRAGDROP_S_USEDEFAULTCURSORS);
  762. }
  763. /**************************************************************************
  764. ************* IEnumFormatEtc INTERFACE IMPLEMENTATION.
  765. **************************************************************************/
  766. STDMETHODIMP ClipDragEnumQueryInterface
  767. (
  768. LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
  769. REFIID riidReq, // IID required
  770. LPVOID FAR* lplpUnk // pre for returning the interface
  771. )
  772. {
  773. LPCLIPDRAGENUM lpClipDragEnum;
  774. DPF("ClipDragEnumQueryInterface\n");
  775. lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
  776. if (IsEqualIID(riidReq, &IID_IEnumFORMATETC) || IsEqualIID(riidReq, &IID_IUnknown)) {
  777. *lplpUnk = (LPVOID) lpClipDragEnum;
  778. lpClipDragEnum->cRef++;
  779. return NOERROR;
  780. } else {
  781. *lplpUnk = (LPVOID) NULL;
  782. RETURN_RESULT( E_NOINTERFACE);
  783. }
  784. }
  785. STDMETHODIMP_(ULONG) ClipDragEnumAddRef
  786. (
  787. LPENUMFORMATETC lpEnumFormatEtc // Enumerator object ptr
  788. )
  789. {
  790. LPCLIPDRAGENUM lpClipDragEnum;
  791. lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
  792. return ++lpClipDragEnum->cRef;
  793. }
  794. STDMETHODIMP_(ULONG) ClipDragEnumRelease
  795. (
  796. LPENUMFORMATETC lpEnumFormatEtc // Enumerator object ptr
  797. )
  798. {
  799. LPCLIPDRAGENUM lpClipDragEnum;
  800. lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
  801. if (--lpClipDragEnum->cRef != 0)
  802. return lpClipDragEnum->cRef;
  803. // Remove Data object pointer (if one exists) to this
  804. //
  805. if (lpClipDragEnum->lpClipDragData != NULL)
  806. lpClipDragEnum->lpClipDragData->lpClipDragEnum = NULL;
  807. _ffree(lpClipDragEnum);
  808. return 0;
  809. }
  810. STDMETHODIMP ClipDragEnumNext
  811. (
  812. LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
  813. ULONG celt, // Number of items requested
  814. FORMATETC FAR rgelt[], // Buffer for retuend items
  815. ULONG FAR* pceltFetched // Number of items returned
  816. )
  817. {
  818. LPCLIPDRAGENUM lpClipDragEnum;
  819. int ce;
  820. LPFORMATETC pfe;
  821. DPF("ClipDragEnumNext\n");
  822. lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
  823. if (pceltFetched != NULL)
  824. *pceltFetched = 0;
  825. if (lpClipDragEnum->lpClipDragData == NULL) // data object gone
  826. RETURN_RESULT( E_FAIL);
  827. pfe = rgelt;
  828. pfe->lindex = DEF_LINDEX;
  829. for (ce = (int) celt; ce > 0 && lpClipDragEnum->cfNext != 0; ce--) {
  830. if (lpClipDragEnum->cfNext == cfEmbedSource) {
  831. pfe->cfFormat = cfEmbedSource;
  832. pfe->ptd = NULL;
  833. pfe->dwAspect = DVASPECT_CONTENT;
  834. pfe->tymed = TYMED_ISTORAGE;
  835. pfe++;
  836. lpClipDragEnum->cfNext = CF_METAFILEPICT;
  837. }
  838. else
  839. if (lpClipDragEnum->cfNext == CF_METAFILEPICT) {
  840. pfe->cfFormat = CF_METAFILEPICT;
  841. pfe->ptd = NULL;
  842. pfe->dwAspect = DVASPECT_CONTENT;
  843. pfe->tymed = TYMED_MFPICT;
  844. pfe++;
  845. lpClipDragEnum->cfNext = CF_DIB; //0;
  846. }
  847. else
  848. if (lpClipDragEnum->cfNext == CF_DIB) {
  849. pfe->cfFormat = CF_DIB;
  850. pfe->ptd = NULL;
  851. pfe->dwAspect = DVASPECT_CONTENT;
  852. pfe->tymed = TYMED_HGLOBAL;
  853. pfe++;
  854. lpClipDragEnum->cfNext = cfObjectDescriptor; //0;
  855. }
  856. else
  857. if (lpClipDragEnum->cfNext == cfObjectDescriptor) {
  858. pfe->cfFormat = cfObjectDescriptor;
  859. pfe->ptd = NULL;
  860. pfe->dwAspect = DVASPECT_CONTENT;
  861. pfe->tymed = TYMED_HGLOBAL;
  862. pfe++;
  863. lpClipDragEnum->cfNext = 0;
  864. }
  865. }
  866. if (pceltFetched != NULL)
  867. *pceltFetched = celt - ((ULONG) ce) ;
  868. RETURN_RESULT( (ce == 0) ? S_OK : S_FALSE);
  869. }
  870. STDMETHODIMP ClipDragEnumSkip
  871. (
  872. LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
  873. ULONG celt // Number of elements to skip
  874. )
  875. {
  876. LPCLIPDRAGENUM lpClipDragEnum;
  877. DPF("ClipDragEnumSkip\n");
  878. lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
  879. if (lpClipDragEnum->lpClipDragData == NULL) // data object gone
  880. RETURN_RESULT( E_FAIL);
  881. if (lpClipDragEnum->cfNext == cfEmbedSource)
  882. {
  883. if (celt == 1)
  884. lpClipDragEnum->cfNext = CF_METAFILEPICT;
  885. else if (celt == 2)
  886. lpClipDragEnum->cfNext = CF_DIB;
  887. else if (celt == 3)
  888. lpClipDragEnum->cfNext = cfObjectDescriptor;
  889. else if (celt > 3)
  890. goto ReturnFalse;
  891. }
  892. else
  893. if (lpClipDragEnum->cfNext == CF_METAFILEPICT)
  894. {
  895. if (celt == 1)
  896. lpClipDragEnum->cfNext = CF_DIB;
  897. else if (celt == 2)
  898. lpClipDragEnum->cfNext = cfObjectDescriptor;
  899. else if (celt > 2)
  900. goto ReturnFalse;
  901. }
  902. else
  903. if (lpClipDragEnum->cfNext == CF_DIB)
  904. {
  905. if (celt == 1)
  906. lpClipDragEnum->cfNext = cfObjectDescriptor;
  907. else if (celt > 1)
  908. goto ReturnFalse;
  909. }
  910. else
  911. if (lpClipDragEnum->cfNext == cfObjectDescriptor)
  912. {
  913. if (celt > 0)
  914. goto ReturnFalse;
  915. }
  916. else
  917. {
  918. ReturnFalse:
  919. RETURN_RESULT(S_FALSE);
  920. }
  921. return NOERROR;
  922. }
  923. STDMETHODIMP ClipDragEnumReset
  924. (
  925. LPENUMFORMATETC lpEnumFormatEtc // Enumerator object ptr
  926. )
  927. {
  928. LPCLIPDRAGENUM lpClipDragEnum;
  929. DPF("ClipDragEnumReset\n");
  930. lpClipDragEnum = (LPCLIPDRAGENUM) lpEnumFormatEtc;
  931. if (lpClipDragEnum->lpClipDragData == NULL) // data object gone
  932. RETURN_RESULT( E_FAIL);
  933. lpClipDragEnum->cfNext = cfEmbedSource;
  934. return NOERROR;
  935. }
  936. STDMETHODIMP ClipDragEnumClone
  937. (
  938. LPENUMFORMATETC lpEnumFormatEtc, // Enumerator object ptr
  939. LPENUMFORMATETC FAR* ppenum
  940. )
  941. {
  942. DPF("ClipDragEnumClone\n");
  943. if (ppenum != NULL)
  944. *ppenum = NULL;
  945. RETURN_RESULT( E_NOTIMPL);
  946. }