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.

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