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.

1009 lines
24 KiB

  1. /****************************************************************************
  2. *
  3. * AVICLIP.C
  4. *
  5. * Clipboard support for AVIFile
  6. *
  7. * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved.
  8. *
  9. * You have a royalty-free right to use, modify, reproduce and
  10. * distribute the Sample Files (and/or any modified version) in
  11. * any way you find useful, provided that you agree that
  12. * Microsoft has no warranty obligations or liability for any
  13. * Sample Application Files which are modified.
  14. *
  15. ***************************************************************************/
  16. #include <win32.h>
  17. #include <ole2.h>
  18. #include <vfw.h>
  19. #include "avimem.h"
  20. #include "enumfetc.h"
  21. #include "debug.h"
  22. //#define TRYLINKS
  23. #ifdef TRYLINKS
  24. static SZCODE aszLink[] = TEXT("OwnerLink");
  25. #endif
  26. #ifndef _WIN32
  27. #define AVIStreamInfoW AVIStreamInfo
  28. #endif
  29. /* From avifps.h.... */
  30. BOOL FAR TaskHasExistingProxies(void);
  31. #define OWNER_DISPLAY 0
  32. STDMETHODIMP AVIClipQueryInterface(LPDATAOBJECT lpd, REFIID riid, LPVOID FAR* ppvObj);
  33. STDMETHODIMP_(ULONG) AVIClipAddRef(LPDATAOBJECT lpd);
  34. STDMETHODIMP_(ULONG) AVIClipRelease(LPDATAOBJECT lpd);
  35. STDMETHODIMP AVIClipGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetcIn,
  36. LPSTGMEDIUM pmedium );
  37. STDMETHODIMP AVIClipGetDataHere(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
  38. LPSTGMEDIUM pmedium );
  39. STDMETHODIMP AVIClipQueryGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc );
  40. STDMETHODIMP AVIClipGetCanonicalFormatEtc(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
  41. LPFORMATETC pformatetcOut);
  42. STDMETHODIMP AVIClipSetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
  43. BOOL fRelease);
  44. STDMETHODIMP AVIClipEnumFormatEtc(LPDATAOBJECT lpd, DWORD dwDirection,
  45. LPENUMFORMATETC FAR* ppenumFormatEtc);
  46. STDMETHODIMP AVIClipDAdvise(LPDATAOBJECT lpd, FORMATETC FAR* pFormatetc, DWORD advf,
  47. LPADVISESINK pAdvSink, DWORD FAR* pdwConnection);
  48. STDMETHODIMP AVIClipDUnadvise(LPDATAOBJECT lpd, DWORD dwConnection);
  49. STDMETHODIMP AVIClipEnumDAdvise(LPDATAOBJECT lpd, LPENUMSTATDATA FAR* ppenumAdvise);
  50. IDataObjectVtbl AVIClipVtbl = {
  51. AVIClipQueryInterface,
  52. AVIClipAddRef,
  53. AVIClipRelease,
  54. AVIClipGetData,
  55. AVIClipGetDataHere,
  56. AVIClipQueryGetData,
  57. AVIClipGetCanonicalFormatEtc,
  58. AVIClipSetData,
  59. AVIClipEnumFormatEtc,
  60. AVIClipDAdvise,
  61. AVIClipDUnadvise,
  62. AVIClipEnumDAdvise
  63. };
  64. #define N_FORMATS (sizeof(FormatList) / sizeof(FormatList[0]))
  65. FORMATETC FormatList[] = {
  66. // CF_WAVE must be first, see AVIPutFileOnClipboard
  67. {CF_WAVE, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  68. {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  69. // CF_PALETTE must be last, see AVIPutFileOnClipboard
  70. {CF_PALETTE, NULL, DVASPECT_CONTENT, -1, TYMED_GDI}
  71. };
  72. #define AVICLIP_MAGIC 0x42424242
  73. typedef struct {
  74. IDataObjectVtbl FAR * lpVtbl;
  75. DWORD Magic;
  76. ULONG ulRefCount;
  77. PAVIFILE pf;
  78. WORD wFormats;
  79. LPFORMATETC lpFormats;
  80. //!!! what about IDataView
  81. //!!! what about a IGetFrame
  82. HWND hwndMci;
  83. PGETFRAME pgf;
  84. } AVICLIP, FAR * LPAVICLIP;
  85. #if OWNER_DISPLAY
  86. static LRESULT CALLBACK _loadds ClipboardWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LONG lParam);
  87. static WNDPROC OldClipboardWindowProc;
  88. static LPAVICLIP lpcClipboard;
  89. #endif
  90. #include "olehack.h"
  91. long glOleRefCount = 0;
  92. HRESULT FAR PASCAL InitOle(BOOL fForceLoad)
  93. {
  94. UINT w;
  95. ++glOleRefCount;
  96. if ( glOleRefCount == 1 ) {
  97. #ifdef DEBUG
  98. HRESULT hr = OleInitialize(NULL);
  99. if (hr != S_OK) {
  100. DPF("InitOle: OleInitialize returned %8x (%x)\n", hr, GetLastError());
  101. } else {
  102. DPF2("InitOle: OleInitialize returned S_OK\n");
  103. }
  104. return(hr);
  105. #else
  106. return OleInitialize(NULL);
  107. #endif
  108. }
  109. return S_OK;
  110. }
  111. void FAR PASCAL TermOle(void)
  112. {
  113. // Someone's calling us too many times... protect them from their selves
  114. //
  115. if (glOleRefCount == 0) {
  116. DPF("TermOle called too many times...\n");
  117. return;
  118. }
  119. --glOleRefCount;
  120. if (glOleRefCount > 0) {
  121. DPF2("Not freeing OLE32.DLL, extra init count still %d\n", glOleRefCount);
  122. return;
  123. }
  124. OleUninitialize();
  125. }
  126. STDAPI AVIGetDataObject(PAVIFILE pf, LPDATAOBJECT FAR *ppDataObj)
  127. {
  128. LPAVICLIP lpc;
  129. PAVISTREAM ps;
  130. *ppDataObj = NULL;
  131. if (pf == NULL) {
  132. return NOERROR;
  133. }
  134. AVIFileAddRef(pf);
  135. lpc = (LPAVICLIP) GlobalAllocPtr(GHND | GMEM_SHARE, sizeof(AVICLIP));
  136. if (!lpc)
  137. return ResultFromScode(AVIERR_MEMORY);
  138. InitOle(TRUE);
  139. lpc->lpVtbl = &AVIClipVtbl;
  140. lpc->ulRefCount = 1;
  141. lpc->pf = pf;
  142. lpc->wFormats = N_FORMATS;
  143. lpc->lpFormats = FormatList;
  144. lpc->Magic = AVICLIP_MAGIC;
  145. //
  146. // if there is no video in the file, dont offer video
  147. // CF_WAVE must be first.
  148. //
  149. if (AVIFileGetStream(pf, &ps, streamtypeVIDEO, 0L) != NOERROR) {
  150. lpc->wFormats = 1;
  151. }
  152. else {
  153. //
  154. // if the video format is higher than 8bpp dont offer a palette
  155. // CF_PALETTE must be last.
  156. //
  157. AVISTREAMINFOW strhdr;
  158. BITMAPINFOHEADER bi;
  159. DWORD dwcbFormat;
  160. // get the stream header
  161. AVIStreamInfoW(ps, &strhdr, sizeof(strhdr));
  162. // now read the format of this thing
  163. dwcbFormat = sizeof(bi);
  164. AVIStreamReadFormat(ps, strhdr.dwStart, (LPVOID)&bi, (LONG FAR *)&dwcbFormat);
  165. // if it is true color (i.e., > 8bpp) then don't use the palette
  166. if (bi.biBitCount > 8) {
  167. DPF("Turning off CF_PALETTE now\n");
  168. lpc->wFormats--; // don't use CF_PALETTE
  169. }
  170. ps->lpVtbl->Release(ps);
  171. }
  172. //
  173. // if there is no audio in the file, dont offer audio
  174. // CF_WAVE must be first.
  175. //
  176. if (AVIFileGetStream(pf, &ps, streamtypeAUDIO, 0L) != NOERROR) {
  177. lpc->wFormats--;
  178. lpc->lpFormats++;
  179. }
  180. else {
  181. ps->lpVtbl->Release(ps);
  182. }
  183. *ppDataObj = (LPDATAOBJECT) lpc;
  184. return 0;
  185. }
  186. /**************************************************************************
  187. * @doc EXTERNAL AVIPutFileOnClipboard
  188. *
  189. * @api HRESULT | AVIPutFileOnClipboard | Puts a file described by the passed
  190. * in PAVIFILE onto the clipboard.
  191. *
  192. * @parm PAVIFILE | pfile | Handle representing the file to put on the clipboard.
  193. *
  194. * @comm
  195. *
  196. * @rdesc Returns zero on success or an error code.
  197. *
  198. * @xref AVIPutStreamOnClipboard AVIGetFromClipboard
  199. *
  200. *************************************************************************/
  201. STDAPI AVIPutFileOnClipboard(PAVIFILE pf)
  202. {
  203. LPDATAOBJECT lpd;
  204. HRESULT hr;
  205. InitOle(TRUE);
  206. hr = AVIGetDataObject(pf, &lpd);
  207. hr = OleSetClipboard(lpd);
  208. if (lpd) {
  209. lpd->lpVtbl->Release(lpd);
  210. #if OWNER_DISPLAY
  211. lpcClipboard = lpc;
  212. //
  213. // hook the clipboard owner so we can do OWNER_DISPLAY formats
  214. //
  215. {
  216. HWND hwnd = GetClipboardOwner();
  217. if (OldClipboardWindowProc == NULL) {
  218. if (hwnd) {
  219. OldClipboardWindowProc = (WNDPROC)SetWindowLong(hwnd,
  220. GWL_WNDPROC, (LONG)ClipboardWindowProc);
  221. }
  222. }
  223. if (OpenClipboard(hwnd)) {
  224. SetClipboardData(CF_OWNERDISPLAY, NULL);
  225. CloseClipboard();
  226. }
  227. }
  228. #endif
  229. }
  230. TermOle();
  231. return hr;
  232. }
  233. /**************************************************************************
  234. * @doc EXTERNAL AVIGetFromClipboard
  235. *
  236. * @api HRESULT | AVIGetFromClipboard | Get a file or stream off of the
  237. * clipboard.
  238. *
  239. * @parm PAVIFILE FAR * | ppfile | Pointer to a variable that can
  240. *
  241. * @comm If <p ppfile> is not NULL, the function will first attempt to
  242. * retrieve a file from the clipboard. Then, if <p ppstream> is not
  243. * NULL, it will attempt to retrieve a stream.
  244. *
  245. * Any file or stream retrieved from the clipboard using this
  246. * function should eventually be released with <f AVIStreamClose>
  247. * or <f AVIFileClose>.
  248. *
  249. * @rdesc Returns zero on success or an error code. If there is no suitable
  250. * data on the clipboard, no error code will be returned, but
  251. * the returned variables will be NULL.
  252. *
  253. * @xref AVIPutStreamOnClipboard AVIGetFromClipboard
  254. *
  255. *************************************************************************/
  256. STDAPI AVIGetFromClipboard(PAVIFILE FAR * lppf)
  257. {
  258. LPDATAOBJECT lpd = NULL;
  259. HRESULT hr = NOERROR;
  260. FORMATETC fetc;
  261. STGMEDIUM stg;
  262. if (!lppf)
  263. return ResultFromScode(E_POINTER);
  264. *lppf = NULL;
  265. InitOle(TRUE);
  266. OleGetClipboard(&lpd);
  267. if (lpd) {
  268. #ifdef DEBUGXX
  269. // Print out lots of stuff about what's on the clipboard....
  270. {
  271. LPENUMFORMATETC lpEnum = NULL;
  272. TCHAR achTemp[256];
  273. lpd->lpVtbl->EnumFormatEtc(lpd, DATADIR_GET, &lpEnum);
  274. if (lpEnum) {
  275. DPF("Formats available:\n");
  276. while(lpEnum->lpVtbl->Next(lpEnum, 1,
  277. (LPFORMATETC)&fetc,
  278. NULL) == NOERROR) {
  279. achTemp[0] = TEXT('\0');
  280. GetClipboardFormatName(fetc.cfFormat, achTemp, sizeof(achTemp)/sizeof(achTemp[0]));
  281. DPF("\t%u\t%lu\t%ls\n", fetc.cfFormat, fetc.tymed, (LPTSTR)achTemp);
  282. if ((fetc.cfFormat == CF_WAVE) ||
  283. (fetc.cfFormat == CF_DIB) ||
  284. (fetc.cfFormat == CF_RIFF) ||
  285. (fetc.cfFormat == CF_METAFILEPICT) ||
  286. (fetc.cfFormat == CF_BITMAP) ||
  287. (fetc.cfFormat == CF_PENDATA))
  288. continue;
  289. if (fetc.tymed & TYMED_HGLOBAL) {
  290. fetc.tymed = TYMED_HGLOBAL;
  291. hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
  292. if (hr == 0) {
  293. LPVOID lp = GlobalLock(stg.hGlobal);
  294. DPF("%s\n", (LPSTR) lp);
  295. GlobalUnlock(stg.hGlobal);
  296. ReleaseStgMedium(&stg);
  297. }
  298. }
  299. }
  300. }
  301. }
  302. #endif
  303. lpd->lpVtbl->QueryInterface(lpd, &IID_IAVIFile, lppf);
  304. // Try for IAVIStream here?
  305. #ifdef TRYLINKS
  306. // See if there's a link to a type of file we can open....
  307. if (!*lppf) {
  308. UINT cfLink;
  309. cfLink = RegisterClipboardFormat(aszLink);
  310. fetc.cfFormat = cfLink;
  311. fetc.ptd = 0;
  312. fetc.dwAspect = DVASPECT_CONTENT;
  313. fetc.lindex = -1;
  314. fetc.tymed = TYMED_HGLOBAL;
  315. hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
  316. if (hr == 0) {
  317. LPTSTR lp = GlobalLock(stg.hGlobal);
  318. LPTSTR lpName;
  319. lpName = lp + lstrlen(lp) + 1;
  320. DPF("Got CF_LINK (%s/%s) data from clipboard...\n", lp,lpName);
  321. hr = AVIFileOpen(lppf, lpName, OF_READ | OF_SHARE_DENY_WRITE, NULL);
  322. if (hr == 0) {
  323. DPF("Opened file from link!\n");
  324. // !!! If the app name is "MPlayer", we could get
  325. // the selection out of the data....
  326. }
  327. GlobalUnlock(stg.hGlobal);
  328. ReleaseStgMedium(&stg);
  329. }
  330. }
  331. #endif
  332. if (!*lppf) {
  333. PAVISTREAM aps[2];
  334. int cps = 0;
  335. fetc.cfFormat = CF_DIB;
  336. fetc.ptd = 0;
  337. fetc.dwAspect = DVASPECT_CONTENT;
  338. fetc.lindex = -1;
  339. fetc.tymed = TYMED_HGLOBAL;
  340. // CF_BITMAP, CF_PALETTE?
  341. hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
  342. if (hr == 0) {
  343. DPF("Got CF_DIB data from clipboard...\n");
  344. hr = AVIMakeStreamFromClipboard(CF_DIB, stg.hGlobal, &aps[cps]);
  345. if (hr == 0) {
  346. cps++;
  347. }
  348. ReleaseStgMedium(&stg);
  349. }
  350. fetc.cfFormat = CF_WAVE;
  351. fetc.ptd = 0;
  352. fetc.dwAspect = DVASPECT_CONTENT;
  353. fetc.lindex = -1;
  354. fetc.tymed = TYMED_HGLOBAL;
  355. hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
  356. if (hr == 0) {
  357. DPF("Got CF_WAVE data from clipboard...\n");
  358. hr = AVIMakeStreamFromClipboard(CF_WAVE, stg.hGlobal, &aps[cps]);
  359. if (hr == 0) {
  360. cps++;
  361. }
  362. ReleaseStgMedium(&stg);
  363. }
  364. if (cps) {
  365. hr = AVIMakeFileFromStreams(lppf, cps, aps);
  366. while (cps-- > 0)
  367. AVIStreamClose(aps[cps]);
  368. } else
  369. hr = ResultFromScode(AVIERR_NODATA);
  370. }
  371. lpd->lpVtbl->Release(lpd);
  372. }
  373. TermOle();
  374. return hr;
  375. }
  376. /**************************************************************************
  377. * @doc EXTERNAL AVIClearClipboard
  378. *
  379. * @api HRESULT | AVIClearClipboard | Releases any file or stream that
  380. * has been put on the Clipboard.
  381. *
  382. * @comm Applications should use this function before exiting if they use
  383. * other Clipboard routines. Do not use this function just to
  384. * clear the clipboard; it might not return until other
  385. * applications have finished using the data placed on the Clipboard.
  386. * Ideally, call this function after hiding your application's windows.
  387. *
  388. * @rdesc Returns zero on success or an error code.
  389. *
  390. * @xref AVIPutStreamOnClipboard AVIGetFromClipboard
  391. *
  392. *************************************************************************/
  393. STDAPI AVIClearClipboard(void)
  394. {
  395. HRESULT hr;
  396. InitOle(TRUE);
  397. hr = OleFlushClipboard();
  398. while (TaskHasExistingProxies()) {
  399. MSG msg;
  400. DPF("AVIClearClipboard: Waiting while streams in use....\n");
  401. while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  402. TranslateMessage(&msg);
  403. DispatchMessage(&msg);
  404. }
  405. }
  406. TermOle();
  407. return hr;
  408. }
  409. typedef LPBITMAPINFOHEADER PDIB;
  410. #ifndef BI_BITFIELDS
  411. #define BI_BITFIELDS 3
  412. #endif
  413. #ifndef HALFTONE
  414. #define HALFTONE COLORONCOLOR
  415. #endif
  416. #define DibCompression(lpbi) (DWORD)(((LPBITMAPINFOHEADER)(lpbi))->biCompression)
  417. #define DibColors(lpbi) ((RGBQUAD FAR *)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
  418. #define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
  419. ? (int)(1 << (int)(lpbi)->biBitCount) \
  420. : (int)(lpbi)->biClrUsed)
  421. /*
  422. * CreateBIPalette()
  423. *
  424. * Given a Pointer to a BITMAPINFO struct will create a
  425. * a GDI palette object from the color table.
  426. *
  427. */
  428. HPALETTE DibCreatePalette(PDIB pdib)
  429. {
  430. LOGPALETTE *pPal;
  431. HPALETTE hpal = NULL;
  432. int nNumColors;
  433. int i;
  434. RGBQUAD FAR * pRgb;
  435. if (!pdib)
  436. return NULL;
  437. nNumColors = DibNumColors(pdib);
  438. if (nNumColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
  439. nNumColors = 0;
  440. if (nNumColors > 0)
  441. {
  442. pRgb = DibColors(pdib);
  443. pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  444. if (!pPal)
  445. goto exit;
  446. pPal->palNumEntries = (WORD) nNumColors;
  447. pPal->palVersion = 0x300;
  448. for (i = 0; i < nNumColors; i++)
  449. {
  450. pPal->palPalEntry[i].peRed = pRgb->rgbRed;
  451. pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  452. pPal->palPalEntry[i].peBlue = pRgb->rgbBlue;
  453. pPal->palPalEntry[i].peFlags = (BYTE)0;
  454. pRgb++;
  455. }
  456. hpal = CreatePalette(pPal);
  457. LocalFree((HLOCAL)pPal);
  458. }
  459. else
  460. {
  461. #ifdef _WIN32
  462. HDC hdc = GetDC(NULL);
  463. hpal = CreateHalftonePalette(hdc);
  464. ReleaseDC(NULL, hdc);
  465. #endif
  466. }
  467. exit:
  468. return hpal;
  469. }
  470. STDMETHODIMP AVIClipQueryInterface(LPDATAOBJECT lpd, REFIID riid, LPVOID FAR* ppvObj)
  471. {
  472. LPAVICLIP lpc = (LPAVICLIP) lpd;
  473. SCODE scode;
  474. if (IsEqualIID(riid, &IID_IDataObject) ||
  475. IsEqualIID(riid, &IID_IUnknown)) {
  476. DPF2("Clip %p: Usage++=%lx\n", lpd, lpc->ulRefCount + 1);
  477. ++lpc->ulRefCount;
  478. *ppvObj = lpd;
  479. scode = S_OK;
  480. }
  481. else if (lpc->pf && IsEqualIID(riid, &IID_IAVIFile)) {
  482. AVIFileAddRef(lpc->pf);
  483. *ppvObj = lpc->pf;
  484. scode = S_OK;
  485. }
  486. else { // unsupported interface
  487. *ppvObj = NULL;
  488. scode = E_NOINTERFACE;
  489. }
  490. return ResultFromScode(scode);
  491. }
  492. STDMETHODIMP_(ULONG) AVIClipAddRef(LPDATAOBJECT lpd)
  493. {
  494. LPAVICLIP lpc = (LPAVICLIP) lpd;
  495. DPF2("Clip %p: Usage++=%lx\n", lpd, lpc->ulRefCount + 1);
  496. return ++lpc->ulRefCount;
  497. }
  498. STDMETHODIMP_(ULONG) AVIClipRelease(LPDATAOBJECT lpd)
  499. {
  500. LPAVICLIP lpc = (LPAVICLIP) lpd;
  501. DPF2("Clip %p: Usage--=%lx\n", lpd, lpc->ulRefCount - 1);
  502. if (--lpc->ulRefCount)
  503. return lpc->ulRefCount;
  504. if (lpc->pf)
  505. AVIFileClose(lpc->pf);
  506. if (lpc->pgf)
  507. AVIStreamGetFrameClose(lpc->pgf);
  508. if (lpc->hwndMci)
  509. DestroyWindow(lpc->hwndMci);
  510. #if OWNER_DISPLAY
  511. if (lpc == lpcClipboard)
  512. lpcClipboard = NULL;
  513. #endif
  514. GlobalFreePtr(lpc);
  515. TermOle();
  516. return 0;
  517. }
  518. // *** IDataObject METHODIMPs ***
  519. STDMETHODIMP AVIClipGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetcIn,
  520. LPSTGMEDIUM pmedium )
  521. {
  522. LPAVICLIP lpc = (LPAVICLIP) lpd;
  523. SCODE sc = S_OK;
  524. LPVOID lp;
  525. LPBITMAPINFOHEADER lpbi;
  526. DWORD cb;
  527. PGETFRAME pgf = NULL;
  528. PAVISTREAM ps = NULL;
  529. pmedium->pUnkForRelease = NULL;
  530. if (pformatetcIn->cfFormat == CF_DIB ||
  531. pformatetcIn->cfFormat == CF_PALETTE) {
  532. AVIFileGetStream(lpc->pf, &ps, streamtypeVIDEO, 0L);
  533. if (!ps) {
  534. sc = E_FAIL;
  535. goto error;
  536. }
  537. pgf = AVIStreamGetFrameOpen(ps, NULL);
  538. if (!pgf) {
  539. DPF("AVIClipGetData: AVIStreamGetFrameOpen failed!\n");
  540. sc = E_FAIL;
  541. goto error;
  542. }
  543. lpbi = AVIStreamGetFrame(pgf, 0);
  544. if (! lpbi) {
  545. DPF("AVIClipGetData: AVIStreamGetFrame failed!\n");
  546. sc = E_OUTOFMEMORY;
  547. goto error;
  548. }
  549. if (pformatetcIn->cfFormat == CF_DIB) {
  550. DPF("Building CF_DIB data\n");
  551. // Verify caller asked for correct medium
  552. if (!(pformatetcIn->tymed & TYMED_HGLOBAL)) {
  553. sc = DATA_E_FORMATETC;
  554. goto error;
  555. }
  556. cb = lpbi->biSize +
  557. lpbi->biClrUsed * sizeof(RGBQUAD) +
  558. lpbi->biSizeImage;
  559. pmedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb);
  560. if (!pmedium->hGlobal) {
  561. sc = E_OUTOFMEMORY;
  562. goto error;
  563. }
  564. lp = GlobalLock(pmedium->hGlobal);
  565. hmemcpy(lp, lpbi, cb);
  566. GlobalUnlock(pmedium->hGlobal);
  567. pmedium->tymed = TYMED_HGLOBAL;
  568. } else /* if (pformatetcIn->cfFormat == CF_PALETTE) */ {
  569. HPALETTE hpal;
  570. // Verify caller asked for correct medium
  571. if (!(pformatetcIn->tymed & TYMED_GDI)) {
  572. sc = DATA_E_FORMATETC;
  573. goto error;
  574. }
  575. hpal = DibCreatePalette(lpbi);
  576. pmedium->hGlobal = hpal;
  577. pmedium->tymed = TYMED_GDI;
  578. DPF("Building CF_PALETTE data: hpal = %p\n", (UINT_PTR) hpal);
  579. }
  580. } else if (pformatetcIn->cfFormat == CF_WAVE) {
  581. LONG cbFormat;
  582. AVISTREAMINFOW strhdr;
  583. #define formtypeWAVE mmioFOURCC('W', 'A', 'V', 'E')
  584. #define ckidWAVEFORMAT mmioFOURCC('f', 'm', 't', ' ')
  585. #define ckidWAVEDATA mmioFOURCC('d', 'a', 't', 'a')
  586. DPF("Building CF_WAVE data\n");
  587. AVIFileGetStream(lpc->pf, &ps, streamtypeAUDIO, 0L);
  588. if (!ps) {
  589. sc = E_FAIL;
  590. goto error;
  591. }
  592. AVIStreamInfoW(ps, &strhdr, sizeof(strhdr));
  593. AVIStreamReadFormat(ps, strhdr.dwStart, NULL, &cbFormat);
  594. cb = strhdr.dwLength * strhdr.dwSampleSize +
  595. cbFormat + 5 * sizeof(DWORD) + 2 * sizeof(DWORD);
  596. pmedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb);
  597. if (!pmedium->hGlobal) {
  598. sc = E_OUTOFMEMORY;
  599. goto error;
  600. }
  601. lp = GlobalLock(pmedium->hGlobal);
  602. *((DWORD _huge *)lp)++ = FOURCC_RIFF;
  603. *((DWORD _huge *)lp)++ = cb - 2 * sizeof(DWORD);
  604. *((DWORD _huge *)lp)++ = formtypeWAVE;
  605. *((DWORD _huge *)lp)++ = ckidWAVEFORMAT;
  606. *((DWORD _huge *)lp)++ = cbFormat;
  607. AVIStreamReadFormat(ps, strhdr.dwStart, lp, &cbFormat);
  608. lp = (BYTE _huge *) lp + cbFormat;
  609. cb = strhdr.dwLength * strhdr.dwSampleSize;
  610. *((DWORD UNALIGNED _huge *)lp)++ = ckidWAVEDATA;
  611. *((DWORD UNALIGNED _huge *)lp)++ = cb;
  612. AVIStreamRead(ps, strhdr.dwStart, strhdr.dwLength, lp, cb, NULL, NULL);
  613. GlobalUnlock(pmedium->hGlobal);
  614. pmedium->tymed = TYMED_HGLOBAL;
  615. } else {
  616. sc = DATA_E_FORMATETC;
  617. //goto error;
  618. }
  619. error:
  620. if (pgf)
  621. AVIStreamGetFrameClose(pgf);
  622. if (ps)
  623. AVIStreamClose(ps);
  624. DPF2("GetData returns %lx\n", (DWORD) sc);
  625. return ResultFromScode(sc);
  626. }
  627. STDMETHODIMP AVIClipGetDataHere(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
  628. LPSTGMEDIUM pmedium )
  629. {
  630. LPAVICLIP lpc = (LPAVICLIP) lpd;
  631. return ResultFromScode(DATA_E_FORMATETC);
  632. }
  633. STDMETHODIMP AVIClipQueryGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc )
  634. {
  635. LPAVICLIP lpc = (LPAVICLIP) lpd;
  636. PAVISTREAM ps = NULL;
  637. // set defaults for passing to AVIFileGetStream
  638. UINT type = TYMED_HGLOBAL; // except for CF_PALETTE
  639. FOURCC streamtype = streamtypeVIDEO; // except for CF_WAVE
  640. switch (pformatetc->cfFormat) {
  641. case CF_PALETTE:
  642. type = TYMED_GDI;
  643. break;
  644. case CF_DIB:
  645. // everything is set up
  646. break;
  647. case CF_WAVE:
  648. streamtype = streamtypeAUDIO;
  649. break;
  650. default:
  651. return ResultFromScode(DATA_E_FORMATETC);
  652. }
  653. AVIFileGetStream(lpc->pf, &ps, streamtype, 0L);
  654. if (ps) {
  655. ps->lpVtbl->Release(ps);
  656. if (pformatetc->tymed & type) {
  657. return NOERROR;
  658. }
  659. }
  660. return ResultFromScode(DATA_E_FORMATETC);
  661. }
  662. STDMETHODIMP AVIClipGetCanonicalFormatEtc(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
  663. LPFORMATETC pformatetcOut)
  664. {
  665. LPAVICLIP lpc = (LPAVICLIP) lpd;
  666. return ResultFromScode(E_NOTIMPL);
  667. }
  668. STDMETHODIMP AVIClipSetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
  669. BOOL fRelease)
  670. {
  671. LPAVICLIP lpc = (LPAVICLIP) lpd;
  672. return ResultFromScode(E_FAIL);
  673. }
  674. STDMETHODIMP AVIClipEnumFormatEtc(LPDATAOBJECT lpd, DWORD dwDirection,
  675. LPENUMFORMATETC FAR* ppenumFormatEtc)
  676. {
  677. LPAVICLIP lpc = (LPAVICLIP) lpd;
  678. SCODE sc = S_OK;
  679. if (dwDirection == DATADIR_GET) {
  680. // Build an enumerator....
  681. *ppenumFormatEtc = OleStdEnumFmtEtc_Create(
  682. lpc->wFormats, lpc->lpFormats);
  683. if (*ppenumFormatEtc == NULL)
  684. sc = E_OUTOFMEMORY;
  685. } else if (dwDirection == DATADIR_SET) {
  686. /* OLE2NOTE: a document that is used to transfer data
  687. ** (either via the clipboard or drag/drop does NOT
  688. ** accept SetData on ANY format!
  689. */
  690. sc = E_NOTIMPL;
  691. goto error;
  692. } else {
  693. sc = E_INVALIDARG;
  694. goto error;
  695. }
  696. error:
  697. return ResultFromScode(sc);
  698. }
  699. STDMETHODIMP AVIClipDAdvise(LPDATAOBJECT lpd, FORMATETC FAR* pFormatetc, DWORD advf,
  700. LPADVISESINK pAdvSink, DWORD FAR* pdwConnection)
  701. {
  702. LPAVICLIP lpc = (LPAVICLIP) lpd;
  703. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  704. }
  705. STDMETHODIMP AVIClipDUnadvise(LPDATAOBJECT lpd, DWORD dwConnection)
  706. {
  707. LPAVICLIP lpc = (LPAVICLIP) lpd;
  708. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  709. }
  710. STDMETHODIMP AVIClipEnumDAdvise(LPDATAOBJECT lpd, LPENUMSTATDATA FAR* ppenumAdvise)
  711. {
  712. LPAVICLIP lpc = (LPAVICLIP) lpd;
  713. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  714. }
  715. #if OWNER_DISPLAY
  716. /**************************************************************************
  717. * @doc INTERNAL AVIFILE
  718. *
  719. * @api ClipboardWindowProc
  720. *
  721. *************************************************************************/
  722. static LRESULT CALLBACK _loadds ClipboardWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LONG lParam)
  723. {
  724. WNDPROC x;
  725. HWND hwndViewer;
  726. PAINTSTRUCT ps;
  727. RECT rc;
  728. LPAVICLIP lpc;
  729. switch (msg) {
  730. case WM_DESTROY:
  731. case WM_DESTROYCLIPBOARD:
  732. DPF("WM_DESTROYCLIPBOARD\n");
  733. x = OldClipboardWindowProc;
  734. SetWindowLong(hwnd, GWL_WNDPROC, (LONG)x);
  735. OldClipboardWindowProc = NULL;
  736. return (*x)(hwnd, msg, wParam, lParam);
  737. case WM_RENDERFORMAT:
  738. DPF("WM_RENDERFORMAT cf=%d\n", (int)wParam);
  739. break;
  740. case WM_PAINTCLIPBOARD:
  741. DPF("WM_PAINTCLIPBOARD\n");
  742. hwndViewer = (HWND)wParam;
  743. if (!lParam)
  744. break;
  745. lpc = lpcClipboard;
  746. if (lpc == NULL)
  747. break;
  748. ps = *(LPPAINTSTRUCT)GlobalLock((HGLOBAL)lParam);
  749. FillRect(ps.hdc, &ps.rcPaint, GetStockObject(DKGRAY_BRUSH));
  750. GlobalUnlock((HGLOBAL) lParam);
  751. return 0;
  752. break;
  753. case WM_SIZECLIPBOARD:
  754. DPF("WM_SIZECLIPBOARD\n");
  755. hwndViewer = (HWND)wParam;
  756. lpc = lpcClipboard;
  757. if (lpc == NULL)
  758. break;
  759. if (lParam)
  760. rc = *(LPRECT)GlobalLock((HGLOBAL)lParam);
  761. else
  762. SetRectEmpty(&rc);
  763. if (IsRectEmpty(&rc)) {
  764. }
  765. else {
  766. }
  767. break;
  768. case WM_VSCROLLCLIPBOARD:
  769. case WM_HSCROLLCLIPBOARD:
  770. DPF("WM_VHSCROLLCLIPBOARD\n");
  771. hwndViewer = (HWND)wParam;
  772. break;
  773. case WM_ASKCBFORMATNAME:
  774. DPF("WM_ASKCBFORMATNAME\n");
  775. break;
  776. }
  777. return OldClipboardWindowProc(hwnd, msg, wParam, lParam);
  778. }
  779. #endif