1010 lines
24 KiB
C
1010 lines
24 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* AVICLIP.C
|
||
|
*
|
||
|
* Clipboard support for AVIFile
|
||
|
*
|
||
|
* Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* You have a royalty-free right to use, modify, reproduce and
|
||
|
* distribute the Sample Files (and/or any modified version) in
|
||
|
* any way you find useful, provided that you agree that
|
||
|
* Microsoft has no warranty obligations or liability for any
|
||
|
* Sample Application Files which are modified.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include <win32.h>
|
||
|
#include <ole2.h>
|
||
|
#include <vfw.h>
|
||
|
#include "avimem.h"
|
||
|
#include "enumfetc.h"
|
||
|
#include "debug.h"
|
||
|
|
||
|
//#define TRYLINKS
|
||
|
#ifdef TRYLINKS
|
||
|
static SZCODE aszLink[] = TEXT("OwnerLink");
|
||
|
#endif
|
||
|
|
||
|
#ifndef _WIN32
|
||
|
#define AVIStreamInfoW AVIStreamInfo
|
||
|
#endif
|
||
|
|
||
|
/* From avifps.h.... */
|
||
|
BOOL FAR TaskHasExistingProxies(void);
|
||
|
|
||
|
#define OWNER_DISPLAY 0
|
||
|
|
||
|
STDMETHODIMP AVIClipQueryInterface(LPDATAOBJECT lpd, REFIID riid, LPVOID FAR* ppvObj);
|
||
|
STDMETHODIMP_(ULONG) AVIClipAddRef(LPDATAOBJECT lpd);
|
||
|
STDMETHODIMP_(ULONG) AVIClipRelease(LPDATAOBJECT lpd);
|
||
|
STDMETHODIMP AVIClipGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetcIn,
|
||
|
LPSTGMEDIUM pmedium );
|
||
|
STDMETHODIMP AVIClipGetDataHere(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
|
||
|
LPSTGMEDIUM pmedium );
|
||
|
STDMETHODIMP AVIClipQueryGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc );
|
||
|
STDMETHODIMP AVIClipGetCanonicalFormatEtc(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
|
||
|
LPFORMATETC pformatetcOut);
|
||
|
STDMETHODIMP AVIClipSetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
|
||
|
BOOL fRelease);
|
||
|
STDMETHODIMP AVIClipEnumFormatEtc(LPDATAOBJECT lpd, DWORD dwDirection,
|
||
|
LPENUMFORMATETC FAR* ppenumFormatEtc);
|
||
|
STDMETHODIMP AVIClipDAdvise(LPDATAOBJECT lpd, FORMATETC FAR* pFormatetc, DWORD advf,
|
||
|
LPADVISESINK pAdvSink, DWORD FAR* pdwConnection);
|
||
|
STDMETHODIMP AVIClipDUnadvise(LPDATAOBJECT lpd, DWORD dwConnection);
|
||
|
STDMETHODIMP AVIClipEnumDAdvise(LPDATAOBJECT lpd, LPENUMSTATDATA FAR* ppenumAdvise);
|
||
|
|
||
|
IDataObjectVtbl AVIClipVtbl = {
|
||
|
AVIClipQueryInterface,
|
||
|
AVIClipAddRef,
|
||
|
AVIClipRelease,
|
||
|
AVIClipGetData,
|
||
|
AVIClipGetDataHere,
|
||
|
AVIClipQueryGetData,
|
||
|
AVIClipGetCanonicalFormatEtc,
|
||
|
AVIClipSetData,
|
||
|
AVIClipEnumFormatEtc,
|
||
|
AVIClipDAdvise,
|
||
|
AVIClipDUnadvise,
|
||
|
AVIClipEnumDAdvise
|
||
|
};
|
||
|
|
||
|
#define N_FORMATS (sizeof(FormatList) / sizeof(FormatList[0]))
|
||
|
FORMATETC FormatList[] = {
|
||
|
// CF_WAVE must be first, see AVIPutFileOnClipboard
|
||
|
{CF_WAVE, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
|
||
|
{CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
|
||
|
// CF_PALETTE must be last, see AVIPutFileOnClipboard
|
||
|
{CF_PALETTE, NULL, DVASPECT_CONTENT, -1, TYMED_GDI}
|
||
|
};
|
||
|
|
||
|
#define AVICLIP_MAGIC 0x42424242
|
||
|
|
||
|
typedef struct {
|
||
|
IDataObjectVtbl FAR * lpVtbl;
|
||
|
DWORD Magic;
|
||
|
|
||
|
ULONG ulRefCount;
|
||
|
|
||
|
PAVIFILE pf;
|
||
|
|
||
|
WORD wFormats;
|
||
|
LPFORMATETC lpFormats;
|
||
|
|
||
|
//!!! what about IDataView
|
||
|
//!!! what about a IGetFrame
|
||
|
|
||
|
HWND hwndMci;
|
||
|
PGETFRAME pgf;
|
||
|
|
||
|
} AVICLIP, FAR * LPAVICLIP;
|
||
|
|
||
|
#if OWNER_DISPLAY
|
||
|
static LRESULT CALLBACK _loadds ClipboardWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LONG lParam);
|
||
|
static WNDPROC OldClipboardWindowProc;
|
||
|
static LPAVICLIP lpcClipboard;
|
||
|
#endif
|
||
|
|
||
|
#include "olehack.h"
|
||
|
|
||
|
long glOleRefCount = 0;
|
||
|
|
||
|
HRESULT FAR PASCAL InitOle(BOOL fForceLoad)
|
||
|
{
|
||
|
UINT w;
|
||
|
|
||
|
++glOleRefCount;
|
||
|
|
||
|
if ( glOleRefCount == 1 ) {
|
||
|
#ifdef DEBUG
|
||
|
HRESULT hr = OleInitialize(NULL);
|
||
|
if (hr != S_OK) {
|
||
|
DPF("InitOle: OleInitialize returned %8x (%x)\n", hr, GetLastError());
|
||
|
} else {
|
||
|
DPF2("InitOle: OleInitialize returned S_OK\n");
|
||
|
}
|
||
|
return(hr);
|
||
|
#else
|
||
|
return OleInitialize(NULL);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
void FAR PASCAL TermOle(void)
|
||
|
{
|
||
|
// Someone's calling us too many times... protect them from their selves
|
||
|
//
|
||
|
if (glOleRefCount == 0) {
|
||
|
DPF("TermOle called too many times...\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
--glOleRefCount;
|
||
|
|
||
|
if (glOleRefCount > 0) {
|
||
|
DPF2("Not freeing OLE32.DLL, extra init count still %d\n", glOleRefCount);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
OleUninitialize();
|
||
|
|
||
|
}
|
||
|
|
||
|
STDAPI AVIGetDataObject(PAVIFILE pf, LPDATAOBJECT FAR *ppDataObj)
|
||
|
{
|
||
|
LPAVICLIP lpc;
|
||
|
PAVISTREAM ps;
|
||
|
|
||
|
*ppDataObj = NULL;
|
||
|
if (pf == NULL) {
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
AVIFileAddRef(pf);
|
||
|
|
||
|
lpc = (LPAVICLIP) GlobalAllocPtr(GHND | GMEM_SHARE, sizeof(AVICLIP));
|
||
|
|
||
|
if (!lpc)
|
||
|
return ResultFromScode(AVIERR_MEMORY);
|
||
|
|
||
|
InitOle(TRUE);
|
||
|
|
||
|
lpc->lpVtbl = &AVIClipVtbl;
|
||
|
lpc->ulRefCount = 1;
|
||
|
lpc->pf = pf;
|
||
|
|
||
|
lpc->wFormats = N_FORMATS;
|
||
|
lpc->lpFormats = FormatList;
|
||
|
lpc->Magic = AVICLIP_MAGIC;
|
||
|
|
||
|
//
|
||
|
// if there is no video in the file, dont offer video
|
||
|
// CF_WAVE must be first.
|
||
|
//
|
||
|
if (AVIFileGetStream(pf, &ps, streamtypeVIDEO, 0L) != NOERROR) {
|
||
|
lpc->wFormats = 1;
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// if the video format is higher than 8bpp dont offer a palette
|
||
|
// CF_PALETTE must be last.
|
||
|
//
|
||
|
AVISTREAMINFOW strhdr;
|
||
|
BITMAPINFOHEADER bi;
|
||
|
DWORD dwcbFormat;
|
||
|
|
||
|
// get the stream header
|
||
|
AVIStreamInfoW(ps, &strhdr, sizeof(strhdr));
|
||
|
|
||
|
// now read the format of this thing
|
||
|
dwcbFormat = sizeof(bi);
|
||
|
AVIStreamReadFormat(ps, strhdr.dwStart, (LPVOID)&bi, (LONG FAR *)&dwcbFormat);
|
||
|
|
||
|
// if it is true color (i.e., > 8bpp) then don't use the palette
|
||
|
if (bi.biBitCount > 8) {
|
||
|
DPF("Turning off CF_PALETTE now\n");
|
||
|
lpc->wFormats--; // don't use CF_PALETTE
|
||
|
}
|
||
|
|
||
|
ps->lpVtbl->Release(ps);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// if there is no audio in the file, dont offer audio
|
||
|
// CF_WAVE must be first.
|
||
|
//
|
||
|
if (AVIFileGetStream(pf, &ps, streamtypeAUDIO, 0L) != NOERROR) {
|
||
|
lpc->wFormats--;
|
||
|
lpc->lpFormats++;
|
||
|
}
|
||
|
else {
|
||
|
ps->lpVtbl->Release(ps);
|
||
|
}
|
||
|
|
||
|
*ppDataObj = (LPDATAOBJECT) lpc;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************
|
||
|
* @doc EXTERNAL AVIPutFileOnClipboard
|
||
|
*
|
||
|
* @api HRESULT | AVIPutFileOnClipboard | Puts a file described by the passed
|
||
|
* in PAVIFILE onto the clipboard.
|
||
|
*
|
||
|
* @parm PAVIFILE | pfile | Handle representing the file to put on the clipboard.
|
||
|
*
|
||
|
* @comm
|
||
|
*
|
||
|
* @rdesc Returns zero on success or an error code.
|
||
|
*
|
||
|
* @xref AVIPutStreamOnClipboard AVIGetFromClipboard
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
STDAPI AVIPutFileOnClipboard(PAVIFILE pf)
|
||
|
{
|
||
|
LPDATAOBJECT lpd;
|
||
|
HRESULT hr;
|
||
|
|
||
|
InitOle(TRUE);
|
||
|
|
||
|
hr = AVIGetDataObject(pf, &lpd);
|
||
|
|
||
|
hr = OleSetClipboard(lpd);
|
||
|
|
||
|
if (lpd) {
|
||
|
lpd->lpVtbl->Release(lpd);
|
||
|
|
||
|
#if OWNER_DISPLAY
|
||
|
lpcClipboard = lpc;
|
||
|
|
||
|
//
|
||
|
// hook the clipboard owner so we can do OWNER_DISPLAY formats
|
||
|
//
|
||
|
{
|
||
|
HWND hwnd = GetClipboardOwner();
|
||
|
|
||
|
if (OldClipboardWindowProc == NULL) {
|
||
|
|
||
|
if (hwnd) {
|
||
|
OldClipboardWindowProc = (WNDPROC)SetWindowLong(hwnd,
|
||
|
GWL_WNDPROC, (LONG)ClipboardWindowProc);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (OpenClipboard(hwnd)) {
|
||
|
SetClipboardData(CF_OWNERDISPLAY, NULL);
|
||
|
CloseClipboard();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
TermOle();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/**************************************************************************
|
||
|
* @doc EXTERNAL AVIGetFromClipboard
|
||
|
*
|
||
|
* @api HRESULT | AVIGetFromClipboard | Get a file or stream off of the
|
||
|
* clipboard.
|
||
|
*
|
||
|
* @parm PAVIFILE FAR * | ppfile | Pointer to a variable that can
|
||
|
*
|
||
|
* @comm If <p ppfile> is not NULL, the function will first attempt to
|
||
|
* retrieve a file from the clipboard. Then, if <p ppstream> is not
|
||
|
* NULL, it will attempt to retrieve a stream.
|
||
|
*
|
||
|
* Any file or stream retrieved from the clipboard using this
|
||
|
* function should eventually be released with <f AVIStreamClose>
|
||
|
* or <f AVIFileClose>.
|
||
|
*
|
||
|
* @rdesc Returns zero on success or an error code. If there is no suitable
|
||
|
* data on the clipboard, no error code will be returned, but
|
||
|
* the returned variables will be NULL.
|
||
|
*
|
||
|
* @xref AVIPutStreamOnClipboard AVIGetFromClipboard
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
STDAPI AVIGetFromClipboard(PAVIFILE FAR * lppf)
|
||
|
{
|
||
|
LPDATAOBJECT lpd = NULL;
|
||
|
HRESULT hr = NOERROR;
|
||
|
FORMATETC fetc;
|
||
|
STGMEDIUM stg;
|
||
|
|
||
|
if (!lppf)
|
||
|
return ResultFromScode(E_POINTER);
|
||
|
|
||
|
*lppf = NULL;
|
||
|
|
||
|
InitOle(TRUE);
|
||
|
|
||
|
OleGetClipboard(&lpd);
|
||
|
|
||
|
if (lpd) {
|
||
|
#ifdef DEBUGXX
|
||
|
// Print out lots of stuff about what's on the clipboard....
|
||
|
{
|
||
|
LPENUMFORMATETC lpEnum = NULL;
|
||
|
TCHAR achTemp[256];
|
||
|
|
||
|
lpd->lpVtbl->EnumFormatEtc(lpd, DATADIR_GET, &lpEnum);
|
||
|
|
||
|
if (lpEnum) {
|
||
|
DPF("Formats available:\n");
|
||
|
while(lpEnum->lpVtbl->Next(lpEnum, 1,
|
||
|
(LPFORMATETC)&fetc,
|
||
|
NULL) == NOERROR) {
|
||
|
achTemp[0] = TEXT('\0');
|
||
|
GetClipboardFormatName(fetc.cfFormat, achTemp, sizeof(achTemp)/sizeof(achTemp[0]));
|
||
|
DPF("\t%u\t%lu\t%ls\n", fetc.cfFormat, fetc.tymed, (LPTSTR)achTemp);
|
||
|
|
||
|
if ((fetc.cfFormat == CF_WAVE) ||
|
||
|
(fetc.cfFormat == CF_DIB) ||
|
||
|
(fetc.cfFormat == CF_RIFF) ||
|
||
|
(fetc.cfFormat == CF_METAFILEPICT) ||
|
||
|
(fetc.cfFormat == CF_BITMAP) ||
|
||
|
(fetc.cfFormat == CF_PENDATA))
|
||
|
continue;
|
||
|
|
||
|
if (fetc.tymed & TYMED_HGLOBAL) {
|
||
|
fetc.tymed = TYMED_HGLOBAL;
|
||
|
hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
|
||
|
if (hr == 0) {
|
||
|
LPVOID lp = GlobalLock(stg.hGlobal);
|
||
|
DPF("%s\n", (LPSTR) lp);
|
||
|
|
||
|
GlobalUnlock(stg.hGlobal);
|
||
|
|
||
|
ReleaseStgMedium(&stg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
lpd->lpVtbl->QueryInterface(lpd, &IID_IAVIFile, lppf);
|
||
|
|
||
|
// Try for IAVIStream here?
|
||
|
|
||
|
#ifdef TRYLINKS
|
||
|
// See if there's a link to a type of file we can open....
|
||
|
if (!*lppf) {
|
||
|
UINT cfLink;
|
||
|
|
||
|
cfLink = RegisterClipboardFormat(aszLink);
|
||
|
|
||
|
fetc.cfFormat = cfLink;
|
||
|
fetc.ptd = 0;
|
||
|
fetc.dwAspect = DVASPECT_CONTENT;
|
||
|
fetc.lindex = -1;
|
||
|
fetc.tymed = TYMED_HGLOBAL;
|
||
|
|
||
|
hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
|
||
|
|
||
|
if (hr == 0) {
|
||
|
LPTSTR lp = GlobalLock(stg.hGlobal);
|
||
|
LPTSTR lpName;
|
||
|
|
||
|
lpName = lp + lstrlen(lp) + 1;
|
||
|
DPF("Got CF_LINK (%s/%s) data from clipboard...\n", lp,lpName);
|
||
|
hr = AVIFileOpen(lppf, lpName, OF_READ | OF_SHARE_DENY_WRITE, NULL);
|
||
|
|
||
|
if (hr == 0) {
|
||
|
DPF("Opened file from link!\n");
|
||
|
|
||
|
// !!! If the app name is "MPlayer", we could get
|
||
|
// the selection out of the data....
|
||
|
}
|
||
|
|
||
|
GlobalUnlock(stg.hGlobal);
|
||
|
ReleaseStgMedium(&stg);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (!*lppf) {
|
||
|
PAVISTREAM aps[2];
|
||
|
int cps = 0;
|
||
|
|
||
|
fetc.cfFormat = CF_DIB;
|
||
|
fetc.ptd = 0;
|
||
|
fetc.dwAspect = DVASPECT_CONTENT;
|
||
|
fetc.lindex = -1;
|
||
|
fetc.tymed = TYMED_HGLOBAL;
|
||
|
|
||
|
// CF_BITMAP, CF_PALETTE?
|
||
|
|
||
|
hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
|
||
|
|
||
|
if (hr == 0) {
|
||
|
DPF("Got CF_DIB data from clipboard...\n");
|
||
|
hr = AVIMakeStreamFromClipboard(CF_DIB, stg.hGlobal, &aps[cps]);
|
||
|
|
||
|
if (hr == 0) {
|
||
|
cps++;
|
||
|
}
|
||
|
|
||
|
ReleaseStgMedium(&stg);
|
||
|
}
|
||
|
|
||
|
fetc.cfFormat = CF_WAVE;
|
||
|
fetc.ptd = 0;
|
||
|
fetc.dwAspect = DVASPECT_CONTENT;
|
||
|
fetc.lindex = -1;
|
||
|
fetc.tymed = TYMED_HGLOBAL;
|
||
|
|
||
|
|
||
|
hr = lpd->lpVtbl->GetData(lpd, &fetc, &stg);
|
||
|
|
||
|
if (hr == 0) {
|
||
|
DPF("Got CF_WAVE data from clipboard...\n");
|
||
|
hr = AVIMakeStreamFromClipboard(CF_WAVE, stg.hGlobal, &aps[cps]);
|
||
|
|
||
|
if (hr == 0) {
|
||
|
cps++;
|
||
|
}
|
||
|
|
||
|
ReleaseStgMedium(&stg);
|
||
|
}
|
||
|
|
||
|
if (cps) {
|
||
|
hr = AVIMakeFileFromStreams(lppf, cps, aps);
|
||
|
|
||
|
while (cps-- > 0)
|
||
|
AVIStreamClose(aps[cps]);
|
||
|
} else
|
||
|
hr = ResultFromScode(AVIERR_NODATA);
|
||
|
}
|
||
|
|
||
|
lpd->lpVtbl->Release(lpd);
|
||
|
}
|
||
|
|
||
|
TermOle();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/**************************************************************************
|
||
|
* @doc EXTERNAL AVIClearClipboard
|
||
|
*
|
||
|
* @api HRESULT | AVIClearClipboard | Releases any file or stream that
|
||
|
* has been put on the Clipboard.
|
||
|
*
|
||
|
* @comm Applications should use this function before exiting if they use
|
||
|
* other Clipboard routines. Do not use this function just to
|
||
|
* clear the clipboard; it might not return until other
|
||
|
* applications have finished using the data placed on the Clipboard.
|
||
|
* Ideally, call this function after hiding your application's windows.
|
||
|
*
|
||
|
* @rdesc Returns zero on success or an error code.
|
||
|
*
|
||
|
* @xref AVIPutStreamOnClipboard AVIGetFromClipboard
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
STDAPI AVIClearClipboard(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
InitOle(TRUE);
|
||
|
|
||
|
hr = OleFlushClipboard();
|
||
|
|
||
|
while (TaskHasExistingProxies()) {
|
||
|
MSG msg;
|
||
|
|
||
|
DPF("AVIClearClipboard: Waiting while streams in use....\n");
|
||
|
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TermOle();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
typedef LPBITMAPINFOHEADER PDIB;
|
||
|
|
||
|
#ifndef BI_BITFIELDS
|
||
|
#define BI_BITFIELDS 3
|
||
|
#endif
|
||
|
|
||
|
#ifndef HALFTONE
|
||
|
#define HALFTONE COLORONCOLOR
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define DibCompression(lpbi) (DWORD)(((LPBITMAPINFOHEADER)(lpbi))->biCompression)
|
||
|
#define DibColors(lpbi) ((RGBQUAD FAR *)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
|
||
|
|
||
|
#define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
|
||
|
? (int)(1 << (int)(lpbi)->biBitCount) \
|
||
|
: (int)(lpbi)->biClrUsed)
|
||
|
|
||
|
|
||
|
/*
|
||
|
* CreateBIPalette()
|
||
|
*
|
||
|
* Given a Pointer to a BITMAPINFO struct will create a
|
||
|
* a GDI palette object from the color table.
|
||
|
*
|
||
|
*/
|
||
|
HPALETTE DibCreatePalette(PDIB pdib)
|
||
|
{
|
||
|
LOGPALETTE *pPal;
|
||
|
HPALETTE hpal = NULL;
|
||
|
int nNumColors;
|
||
|
int i;
|
||
|
RGBQUAD FAR * pRgb;
|
||
|
|
||
|
if (!pdib)
|
||
|
return NULL;
|
||
|
|
||
|
nNumColors = DibNumColors(pdib);
|
||
|
|
||
|
if (nNumColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
|
||
|
nNumColors = 0;
|
||
|
|
||
|
if (nNumColors > 0)
|
||
|
{
|
||
|
pRgb = DibColors(pdib);
|
||
|
pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
|
||
|
|
||
|
if (!pPal)
|
||
|
goto exit;
|
||
|
|
||
|
pPal->palNumEntries = (WORD) nNumColors;
|
||
|
pPal->palVersion = 0x300;
|
||
|
|
||
|
for (i = 0; i < nNumColors; i++)
|
||
|
{
|
||
|
pPal->palPalEntry[i].peRed = pRgb->rgbRed;
|
||
|
pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
|
||
|
pPal->palPalEntry[i].peBlue = pRgb->rgbBlue;
|
||
|
pPal->palPalEntry[i].peFlags = (BYTE)0;
|
||
|
|
||
|
pRgb++;
|
||
|
}
|
||
|
|
||
|
hpal = CreatePalette(pPal);
|
||
|
LocalFree((HLOCAL)pPal);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#ifdef _WIN32
|
||
|
HDC hdc = GetDC(NULL);
|
||
|
hpal = CreateHalftonePalette(hdc);
|
||
|
ReleaseDC(NULL, hdc);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
return hpal;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipQueryInterface(LPDATAOBJECT lpd, REFIID riid, LPVOID FAR* ppvObj)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
SCODE scode;
|
||
|
|
||
|
if (IsEqualIID(riid, &IID_IDataObject) ||
|
||
|
IsEqualIID(riid, &IID_IUnknown)) {
|
||
|
|
||
|
DPF2("Clip %p: Usage++=%lx\n", lpd, lpc->ulRefCount + 1);
|
||
|
|
||
|
++lpc->ulRefCount;
|
||
|
*ppvObj = lpd;
|
||
|
scode = S_OK;
|
||
|
}
|
||
|
else if (lpc->pf && IsEqualIID(riid, &IID_IAVIFile)) {
|
||
|
AVIFileAddRef(lpc->pf);
|
||
|
*ppvObj = lpc->pf;
|
||
|
scode = S_OK;
|
||
|
}
|
||
|
else { // unsupported interface
|
||
|
*ppvObj = NULL;
|
||
|
scode = E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
return ResultFromScode(scode);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) AVIClipAddRef(LPDATAOBJECT lpd)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
DPF2("Clip %p: Usage++=%lx\n", lpd, lpc->ulRefCount + 1);
|
||
|
|
||
|
return ++lpc->ulRefCount;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) AVIClipRelease(LPDATAOBJECT lpd)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
DPF2("Clip %p: Usage--=%lx\n", lpd, lpc->ulRefCount - 1);
|
||
|
|
||
|
if (--lpc->ulRefCount)
|
||
|
return lpc->ulRefCount;
|
||
|
|
||
|
if (lpc->pf)
|
||
|
AVIFileClose(lpc->pf);
|
||
|
|
||
|
if (lpc->pgf)
|
||
|
AVIStreamGetFrameClose(lpc->pgf);
|
||
|
|
||
|
if (lpc->hwndMci)
|
||
|
DestroyWindow(lpc->hwndMci);
|
||
|
|
||
|
#if OWNER_DISPLAY
|
||
|
if (lpc == lpcClipboard)
|
||
|
lpcClipboard = NULL;
|
||
|
#endif
|
||
|
|
||
|
GlobalFreePtr(lpc);
|
||
|
TermOle();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
// *** IDataObject METHODIMPs ***
|
||
|
STDMETHODIMP AVIClipGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetcIn,
|
||
|
LPSTGMEDIUM pmedium )
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
SCODE sc = S_OK;
|
||
|
|
||
|
LPVOID lp;
|
||
|
LPBITMAPINFOHEADER lpbi;
|
||
|
DWORD cb;
|
||
|
PGETFRAME pgf = NULL;
|
||
|
PAVISTREAM ps = NULL;
|
||
|
|
||
|
pmedium->pUnkForRelease = NULL;
|
||
|
|
||
|
if (pformatetcIn->cfFormat == CF_DIB ||
|
||
|
pformatetcIn->cfFormat == CF_PALETTE) {
|
||
|
|
||
|
AVIFileGetStream(lpc->pf, &ps, streamtypeVIDEO, 0L);
|
||
|
|
||
|
if (!ps) {
|
||
|
sc = E_FAIL;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
pgf = AVIStreamGetFrameOpen(ps, NULL);
|
||
|
|
||
|
if (!pgf) {
|
||
|
DPF("AVIClipGetData: AVIStreamGetFrameOpen failed!\n");
|
||
|
sc = E_FAIL;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
lpbi = AVIStreamGetFrame(pgf, 0);
|
||
|
|
||
|
if (! lpbi) {
|
||
|
DPF("AVIClipGetData: AVIStreamGetFrame failed!\n");
|
||
|
sc = E_OUTOFMEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if (pformatetcIn->cfFormat == CF_DIB) {
|
||
|
DPF("Building CF_DIB data\n");
|
||
|
// Verify caller asked for correct medium
|
||
|
if (!(pformatetcIn->tymed & TYMED_HGLOBAL)) {
|
||
|
sc = DATA_E_FORMATETC;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
cb = lpbi->biSize +
|
||
|
lpbi->biClrUsed * sizeof(RGBQUAD) +
|
||
|
lpbi->biSizeImage;
|
||
|
pmedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb);
|
||
|
|
||
|
if (!pmedium->hGlobal) {
|
||
|
sc = E_OUTOFMEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
lp = GlobalLock(pmedium->hGlobal);
|
||
|
|
||
|
hmemcpy(lp, lpbi, cb);
|
||
|
|
||
|
GlobalUnlock(pmedium->hGlobal);
|
||
|
|
||
|
pmedium->tymed = TYMED_HGLOBAL;
|
||
|
} else /* if (pformatetcIn->cfFormat == CF_PALETTE) */ {
|
||
|
HPALETTE hpal;
|
||
|
|
||
|
// Verify caller asked for correct medium
|
||
|
if (!(pformatetcIn->tymed & TYMED_GDI)) {
|
||
|
sc = DATA_E_FORMATETC;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
hpal = DibCreatePalette(lpbi);
|
||
|
|
||
|
pmedium->hGlobal = hpal;
|
||
|
pmedium->tymed = TYMED_GDI;
|
||
|
DPF("Building CF_PALETTE data: hpal = %p\n", (UINT_PTR) hpal);
|
||
|
}
|
||
|
} else if (pformatetcIn->cfFormat == CF_WAVE) {
|
||
|
LONG cbFormat;
|
||
|
AVISTREAMINFOW strhdr;
|
||
|
#define formtypeWAVE mmioFOURCC('W', 'A', 'V', 'E')
|
||
|
#define ckidWAVEFORMAT mmioFOURCC('f', 'm', 't', ' ')
|
||
|
#define ckidWAVEDATA mmioFOURCC('d', 'a', 't', 'a')
|
||
|
|
||
|
DPF("Building CF_WAVE data\n");
|
||
|
AVIFileGetStream(lpc->pf, &ps, streamtypeAUDIO, 0L);
|
||
|
|
||
|
if (!ps) {
|
||
|
sc = E_FAIL;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
AVIStreamInfoW(ps, &strhdr, sizeof(strhdr));
|
||
|
|
||
|
AVIStreamReadFormat(ps, strhdr.dwStart, NULL, &cbFormat);
|
||
|
|
||
|
cb = strhdr.dwLength * strhdr.dwSampleSize +
|
||
|
cbFormat + 5 * sizeof(DWORD) + 2 * sizeof(DWORD);
|
||
|
|
||
|
pmedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb);
|
||
|
|
||
|
if (!pmedium->hGlobal) {
|
||
|
sc = E_OUTOFMEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
lp = GlobalLock(pmedium->hGlobal);
|
||
|
|
||
|
*((DWORD _huge *)lp)++ = FOURCC_RIFF;
|
||
|
*((DWORD _huge *)lp)++ = cb - 2 * sizeof(DWORD);
|
||
|
*((DWORD _huge *)lp)++ = formtypeWAVE;
|
||
|
|
||
|
*((DWORD _huge *)lp)++ = ckidWAVEFORMAT;
|
||
|
*((DWORD _huge *)lp)++ = cbFormat;
|
||
|
|
||
|
AVIStreamReadFormat(ps, strhdr.dwStart, lp, &cbFormat);
|
||
|
|
||
|
lp = (BYTE _huge *) lp + cbFormat;
|
||
|
|
||
|
cb = strhdr.dwLength * strhdr.dwSampleSize;
|
||
|
*((DWORD UNALIGNED _huge *)lp)++ = ckidWAVEDATA;
|
||
|
*((DWORD UNALIGNED _huge *)lp)++ = cb;
|
||
|
|
||
|
AVIStreamRead(ps, strhdr.dwStart, strhdr.dwLength, lp, cb, NULL, NULL);
|
||
|
|
||
|
GlobalUnlock(pmedium->hGlobal);
|
||
|
|
||
|
pmedium->tymed = TYMED_HGLOBAL;
|
||
|
} else {
|
||
|
sc = DATA_E_FORMATETC;
|
||
|
|
||
|
//goto error;
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pgf)
|
||
|
AVIStreamGetFrameClose(pgf);
|
||
|
if (ps)
|
||
|
AVIStreamClose(ps);
|
||
|
|
||
|
DPF2("GetData returns %lx\n", (DWORD) sc);
|
||
|
return ResultFromScode(sc);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipGetDataHere(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
|
||
|
LPSTGMEDIUM pmedium )
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
return ResultFromScode(DATA_E_FORMATETC);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipQueryGetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc )
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
PAVISTREAM ps = NULL;
|
||
|
|
||
|
// set defaults for passing to AVIFileGetStream
|
||
|
UINT type = TYMED_HGLOBAL; // except for CF_PALETTE
|
||
|
FOURCC streamtype = streamtypeVIDEO; // except for CF_WAVE
|
||
|
|
||
|
switch (pformatetc->cfFormat) {
|
||
|
|
||
|
case CF_PALETTE:
|
||
|
type = TYMED_GDI;
|
||
|
break;
|
||
|
|
||
|
case CF_DIB:
|
||
|
// everything is set up
|
||
|
break;
|
||
|
|
||
|
case CF_WAVE:
|
||
|
streamtype = streamtypeAUDIO;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return ResultFromScode(DATA_E_FORMATETC);
|
||
|
}
|
||
|
|
||
|
AVIFileGetStream(lpc->pf, &ps, streamtype, 0L);
|
||
|
if (ps) {
|
||
|
ps->lpVtbl->Release(ps);
|
||
|
if (pformatetc->tymed & type) {
|
||
|
return NOERROR;
|
||
|
}
|
||
|
}
|
||
|
return ResultFromScode(DATA_E_FORMATETC);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipGetCanonicalFormatEtc(LPDATAOBJECT lpd, LPFORMATETC pformatetc,
|
||
|
LPFORMATETC pformatetcOut)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
return ResultFromScode(E_NOTIMPL);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipSetData(LPDATAOBJECT lpd, LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
|
||
|
BOOL fRelease)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
return ResultFromScode(E_FAIL);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipEnumFormatEtc(LPDATAOBJECT lpd, DWORD dwDirection,
|
||
|
LPENUMFORMATETC FAR* ppenumFormatEtc)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
SCODE sc = S_OK;
|
||
|
if (dwDirection == DATADIR_GET) {
|
||
|
// Build an enumerator....
|
||
|
*ppenumFormatEtc = OleStdEnumFmtEtc_Create(
|
||
|
lpc->wFormats, lpc->lpFormats);
|
||
|
|
||
|
if (*ppenumFormatEtc == NULL)
|
||
|
sc = E_OUTOFMEMORY;
|
||
|
} else if (dwDirection == DATADIR_SET) {
|
||
|
/* OLE2NOTE: a document that is used to transfer data
|
||
|
** (either via the clipboard or drag/drop does NOT
|
||
|
** accept SetData on ANY format!
|
||
|
*/
|
||
|
sc = E_NOTIMPL;
|
||
|
goto error;
|
||
|
} else {
|
||
|
sc = E_INVALIDARG;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return ResultFromScode(sc);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP AVIClipDAdvise(LPDATAOBJECT lpd, FORMATETC FAR* pFormatetc, DWORD advf,
|
||
|
LPADVISESINK pAdvSink, DWORD FAR* pdwConnection)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipDUnadvise(LPDATAOBJECT lpd, DWORD dwConnection)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP AVIClipEnumDAdvise(LPDATAOBJECT lpd, LPENUMSTATDATA FAR* ppenumAdvise)
|
||
|
{
|
||
|
LPAVICLIP lpc = (LPAVICLIP) lpd;
|
||
|
|
||
|
return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
|
||
|
}
|
||
|
|
||
|
#if OWNER_DISPLAY
|
||
|
|
||
|
/**************************************************************************
|
||
|
* @doc INTERNAL AVIFILE
|
||
|
*
|
||
|
* @api ClipboardWindowProc
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
static LRESULT CALLBACK _loadds ClipboardWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LONG lParam)
|
||
|
{
|
||
|
WNDPROC x;
|
||
|
HWND hwndViewer;
|
||
|
PAINTSTRUCT ps;
|
||
|
RECT rc;
|
||
|
LPAVICLIP lpc;
|
||
|
|
||
|
switch (msg) {
|
||
|
case WM_DESTROY:
|
||
|
case WM_DESTROYCLIPBOARD:
|
||
|
DPF("WM_DESTROYCLIPBOARD\n");
|
||
|
|
||
|
x = OldClipboardWindowProc;
|
||
|
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)x);
|
||
|
OldClipboardWindowProc = NULL;
|
||
|
return (*x)(hwnd, msg, wParam, lParam);
|
||
|
|
||
|
case WM_RENDERFORMAT:
|
||
|
DPF("WM_RENDERFORMAT cf=%d\n", (int)wParam);
|
||
|
break;
|
||
|
|
||
|
case WM_PAINTCLIPBOARD:
|
||
|
DPF("WM_PAINTCLIPBOARD\n");
|
||
|
|
||
|
hwndViewer = (HWND)wParam;
|
||
|
|
||
|
if (!lParam)
|
||
|
break;
|
||
|
|
||
|
lpc = lpcClipboard;
|
||
|
|
||
|
if (lpc == NULL)
|
||
|
break;
|
||
|
|
||
|
ps = *(LPPAINTSTRUCT)GlobalLock((HGLOBAL)lParam);
|
||
|
|
||
|
FillRect(ps.hdc, &ps.rcPaint, GetStockObject(DKGRAY_BRUSH));
|
||
|
|
||
|
GlobalUnlock((HGLOBAL) lParam);
|
||
|
return 0;
|
||
|
break;
|
||
|
|
||
|
case WM_SIZECLIPBOARD:
|
||
|
DPF("WM_SIZECLIPBOARD\n");
|
||
|
|
||
|
hwndViewer = (HWND)wParam;
|
||
|
|
||
|
lpc = lpcClipboard;
|
||
|
|
||
|
if (lpc == NULL)
|
||
|
break;
|
||
|
|
||
|
if (lParam)
|
||
|
rc = *(LPRECT)GlobalLock((HGLOBAL)lParam);
|
||
|
else
|
||
|
SetRectEmpty(&rc);
|
||
|
|
||
|
if (IsRectEmpty(&rc)) {
|
||
|
}
|
||
|
else {
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_VSCROLLCLIPBOARD:
|
||
|
case WM_HSCROLLCLIPBOARD:
|
||
|
DPF("WM_VHSCROLLCLIPBOARD\n");
|
||
|
hwndViewer = (HWND)wParam;
|
||
|
break;
|
||
|
|
||
|
case WM_ASKCBFORMATNAME:
|
||
|
DPF("WM_ASKCBFORMATNAME\n");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return OldClipboardWindowProc(hwnd, msg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|