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.

1023 lines
26 KiB

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