1025 lines
30 KiB
C
1025 lines
30 KiB
C
/*
|
|
* msvideo 16-bit functions
|
|
*
|
|
* Copyright 1998 Marcus Meissner
|
|
* Copyright 2000 Bradley Baetz
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winver.h"
|
|
#include "winnls.h"
|
|
#include "winreg.h"
|
|
#include "winuser.h"
|
|
#include "wine/winbase16.h"
|
|
#include "wownt32.h"
|
|
#include "vfw16.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
|
|
|
|
/* Drivers32 settings */
|
|
#define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32"
|
|
|
|
/* handle16 --> handle conversions */
|
|
#define HDRAWDIB_32(h16) ((HDRAWDIB)(ULONG_PTR)(h16))
|
|
#define HIC_32(h16) ((HIC)(ULONG_PTR)(h16))
|
|
|
|
/* handle --> handle16 conversions */
|
|
#define HDRVR_16(h32) (LOWORD(h32))
|
|
#define HDRAWDIB_16(h32) (LOWORD(h32))
|
|
#define HIC_16(h32) (LOWORD(h32))
|
|
|
|
/***********************************************************************
|
|
* DrawDibOpen [MSVIDEO.102]
|
|
*/
|
|
HDRAWDIB16 VFWAPI DrawDibOpen16(void)
|
|
{
|
|
return HDRAWDIB_16(DrawDibOpen());
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DrawDibClose [MSVIDEO.103]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibClose16(HDRAWDIB16 hdd)
|
|
{
|
|
return DrawDibClose(HDRAWDIB_32(hdd));
|
|
}
|
|
|
|
/************************************************************************
|
|
* DrawDibBegin [MSVIDEO.104]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibBegin16(HDRAWDIB16 hdd, HDC16 hdc, INT16 dxDst,
|
|
INT16 dyDst, LPBITMAPINFOHEADER lpbi, INT16 dxSrc,
|
|
INT16 dySrc, UINT16 wFlags)
|
|
{
|
|
return DrawDibBegin(HDRAWDIB_32(hdd), HDC_32(hdc), dxDst, dyDst, lpbi,
|
|
dxSrc, dySrc, wFlags);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DrawDibEnd [MSVIDEO.105]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibEnd16(HDRAWDIB16 hdd)
|
|
{
|
|
return DrawDibEnd(HDRAWDIB_32(hdd));
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DrawDibDraw [MSVIDEO.106]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibDraw16(HDRAWDIB16 hdd, HDC16 hdc, INT16 xDst, INT16 yDst,
|
|
INT16 dxDst, INT16 dyDst, LPBITMAPINFOHEADER lpbi,
|
|
LPVOID lpBits, INT16 xSrc, INT16 ySrc, INT16 dxSrc,
|
|
INT16 dySrc, UINT16 wFlags)
|
|
{
|
|
return DrawDibDraw(HDRAWDIB_32(hdd), HDC_32(hdc), xDst, yDst, dxDst,
|
|
dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, wFlags);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DrawDibGetPalette [MSVIDEO.108]
|
|
*/
|
|
HPALETTE16 VFWAPI DrawDibGetPalette16(HDRAWDIB16 hdd)
|
|
{
|
|
return HPALETTE_16(DrawDibGetPalette(HDRAWDIB_32(hdd)));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DrawDibSetPalette [MSVIDEO.110]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibSetPalette16(HDRAWDIB16 hdd, HPALETTE16 hpal)
|
|
{
|
|
return DrawDibSetPalette(HDRAWDIB_32(hdd), HPALETTE_32(hpal));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DrawDibRealize [MSVIDEO.112]
|
|
*/
|
|
UINT16 VFWAPI DrawDibRealize16(HDRAWDIB16 hdd, HDC16 hdc,
|
|
BOOL16 fBackground)
|
|
{
|
|
return (UINT16)DrawDibRealize(HDRAWDIB_32(hdd), HDC_32(hdc), fBackground);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* DrawDibProfileDisplay [MSVIDEO.114]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibProfileDisplay16(LPBITMAPINFOHEADER lpbi)
|
|
{
|
|
TRACE("(%p)\n", lpbi);
|
|
return DrawDibProfileDisplay(lpbi);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* DrawDibStart [MSVIDEO.118]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate)
|
|
{
|
|
return DrawDibStart(HDRAWDIB_32(hdd), rate);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* DrawDibStop [MSVIDEO.119]
|
|
*/
|
|
BOOL16 VFWAPI DrawDibStop16(HDRAWDIB16 hdd)
|
|
{
|
|
return DrawDibStop(HDRAWDIB_32(hdd));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICOpen [MSVIDEO.203]
|
|
*/
|
|
HIC16 VFWAPI ICOpen16(DWORD fccType, DWORD fccHandler, UINT16 wMode)
|
|
{
|
|
return HIC_16(ICOpen(fccType, fccHandler, wMode));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* _ICMessage [MSVIDEO.207]
|
|
*/
|
|
LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist )
|
|
{
|
|
LPWORD lpData;
|
|
SEGPTR segData;
|
|
LRESULT ret;
|
|
UINT16 i;
|
|
|
|
lpData = HeapAlloc(GetProcessHeap(), 0, cb);
|
|
|
|
TRACE("0x%08x, %u, %u, ...)\n", (DWORD) hic, msg, cb);
|
|
|
|
for (i = 0; i < cb / sizeof(WORD); i++)
|
|
{
|
|
lpData[i] = VA_ARG16(valist, WORD);
|
|
}
|
|
|
|
segData = MapLS(lpData);
|
|
ret = ICSendMessage16(hic, msg, segData, (DWORD) cb);
|
|
UnMapLS(segData);
|
|
HeapFree(GetProcessHeap(), 0, lpData);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICGetInfo [MSVIDEO.212]
|
|
*/
|
|
LRESULT VFWAPI ICGetInfo16(HIC16 hic, ICINFO16 * picinfo, DWORD cb)
|
|
{
|
|
LRESULT ret;
|
|
|
|
TRACE("(0x%08x,%p,%d)\n", (DWORD) hic, picinfo, cb);
|
|
ret = ICSendMessage16(hic, ICM_GETINFO, (DWORD) picinfo, cb);
|
|
TRACE(" -> 0x%08lx\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICLocate [MSVIDEO.213]
|
|
*/
|
|
HIC16 VFWAPI ICLocate16(DWORD fccType, DWORD fccHandler,
|
|
LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut,
|
|
WORD wFlags)
|
|
{
|
|
return HIC_16(ICLocate(fccType, fccHandler, lpbiIn, lpbiOut, wFlags));
|
|
}
|
|
|
|
/***********************************************************************
|
|
* _ICCompress [MSVIDEO.224]
|
|
*/
|
|
DWORD VFWAPIV ICCompress16(HIC16 hic, DWORD dwFlags,
|
|
LPBITMAPINFOHEADER lpbiOutput, LPVOID lpData,
|
|
LPBITMAPINFOHEADER lpbiInput, LPVOID lpBits,
|
|
LPDWORD lpckid, LPDWORD lpdwFlags,
|
|
LONG lFrameNum, DWORD dwFrameSize,
|
|
DWORD dwQuality, LPBITMAPINFOHEADER lpbiPrev,
|
|
LPVOID lpPrev)
|
|
{
|
|
DWORD ret;
|
|
ICCOMPRESS iccmp;
|
|
SEGPTR seg_iccmp;
|
|
|
|
TRACE("(0x%08x,%d,%p,%p,%p,%p,...)\n", (DWORD) hic, dwFlags,
|
|
lpbiOutput, lpData, lpbiInput, lpBits);
|
|
|
|
iccmp.dwFlags = dwFlags;
|
|
|
|
iccmp.lpbiOutput = lpbiOutput;
|
|
iccmp.lpOutput = lpData;
|
|
iccmp.lpbiInput = lpbiInput;
|
|
iccmp.lpInput = lpBits;
|
|
|
|
iccmp.lpckid = lpckid;
|
|
iccmp.lpdwFlags = lpdwFlags;
|
|
iccmp.lFrameNum = lFrameNum;
|
|
iccmp.dwFrameSize = dwFrameSize;
|
|
iccmp.dwQuality = dwQuality;
|
|
iccmp.lpbiPrev = lpbiPrev;
|
|
iccmp.lpPrev = lpPrev;
|
|
seg_iccmp = MapLS(&iccmp);
|
|
ret = ICSendMessage16(hic, ICM_COMPRESS, seg_iccmp, sizeof(ICCOMPRESS));
|
|
UnMapLS(seg_iccmp);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* _ICDecompress [MSVIDEO.230]
|
|
*/
|
|
DWORD VFWAPIV ICDecompress16(HIC16 hic, DWORD dwFlags,
|
|
LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData,
|
|
LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
|
|
{
|
|
ICDECOMPRESS icd;
|
|
SEGPTR segptr;
|
|
DWORD ret;
|
|
|
|
TRACE("(0x%08x,%d,%p,%p,%p,%p)\n", (DWORD) hic, dwFlags, lpbiFormat,
|
|
lpData, lpbi, lpBits);
|
|
|
|
icd.dwFlags = dwFlags;
|
|
icd.lpbiInput = lpbiFormat;
|
|
icd.lpInput = lpData;
|
|
icd.lpbiOutput = lpbi;
|
|
icd.lpOutput = lpBits;
|
|
icd.ckid = 0;
|
|
segptr = MapLS(&icd);
|
|
ret = ICSendMessage16(hic, ICM_DECOMPRESS, segptr, sizeof(ICDECOMPRESS));
|
|
UnMapLS(segptr);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* _ICDrawBegin [MSVIDEO.232]
|
|
*/
|
|
DWORD VFWAPIV ICDrawBegin16(HIC16 hic, /* [in] */
|
|
DWORD dwFlags, /* [in] flags */
|
|
HPALETTE16 hpal, /* [in] palette to draw with */
|
|
HWND16 hwnd, /* [in] window to draw to */
|
|
HDC16 hdc, /* [in] HDC to draw to */
|
|
INT16 xDst, /* [in] destination rectangle */
|
|
INT16 yDst, /* [in] */
|
|
INT16 dxDst, /* [in] */
|
|
INT16 dyDst, /* [in] */
|
|
LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw NOTE: SEGPTR */
|
|
INT16 xSrc, /* [in] source rectangle */
|
|
INT16 ySrc, /* [in] */
|
|
INT16 dxSrc, /* [in] */
|
|
INT16 dySrc, /* [in] */
|
|
DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */
|
|
DWORD dwScale) /* [in] */
|
|
{
|
|
DWORD ret;
|
|
ICDRAWBEGIN16 icdb;
|
|
SEGPTR seg_icdb;
|
|
|
|
TRACE ("(0x%08x,%d,0x%08x,0x%08x,0x%08x,%u,%u,%u,%u,%p,%u,%u,%u,%u,%d,%d)\n",
|
|
(DWORD) hic, dwFlags, (DWORD) hpal, (DWORD) hwnd, (DWORD) hdc,
|
|
xDst, yDst, dxDst, dyDst, lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate,
|
|
dwScale);
|
|
|
|
icdb.dwFlags = dwFlags;
|
|
icdb.hpal = hpal;
|
|
icdb.hwnd = hwnd;
|
|
icdb.hdc = hdc;
|
|
icdb.xDst = xDst;
|
|
icdb.yDst = yDst;
|
|
icdb.dxDst = dxDst;
|
|
icdb.dyDst = dyDst;
|
|
icdb.lpbi = lpbi; /* Keep this as SEGPTR for the mapping code to deal with */
|
|
icdb.xSrc = xSrc;
|
|
icdb.ySrc = ySrc;
|
|
icdb.dxSrc = dxSrc;
|
|
icdb.dySrc = dySrc;
|
|
icdb.dwRate = dwRate;
|
|
icdb.dwScale = dwScale;
|
|
seg_icdb = MapLS(&icdb);
|
|
ret = (DWORD) ICSendMessage16(hic, ICM_DRAW_BEGIN, seg_icdb,
|
|
sizeof(ICDRAWBEGIN16));
|
|
UnMapLS(seg_icdb);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* _ICDraw [MSVIDEO.234]
|
|
*/
|
|
DWORD VFWAPIV ICDraw16(HIC16 hic, DWORD dwFlags,
|
|
LPVOID lpFormat, /* [???] NOTE: SEGPTR */
|
|
LPVOID lpData, /* [???] NOTE: SEGPTR */
|
|
DWORD cbData, LONG lTime)
|
|
{
|
|
DWORD ret;
|
|
ICDRAW icd;
|
|
SEGPTR seg_icd;
|
|
|
|
TRACE("(0x%08x,0x%08x,%p,%p,%d,%d)\n", (DWORD) hic, dwFlags,
|
|
lpFormat, lpData, cbData, lTime);
|
|
icd.dwFlags = dwFlags;
|
|
icd.lpFormat = lpFormat;
|
|
icd.lpData = lpData;
|
|
icd.cbData = cbData;
|
|
icd.lTime = lTime;
|
|
seg_icd = MapLS(&icd);
|
|
ret = ICSendMessage16(hic, ICM_DRAW, seg_icd, sizeof(ICDRAW));
|
|
UnMapLS(seg_icd);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICGetDisplayFormat [MSVIDEO.239]
|
|
*/
|
|
HIC16 VFWAPI ICGetDisplayFormat16(HIC16 hic, LPBITMAPINFOHEADER lpbiIn,
|
|
LPBITMAPINFOHEADER lpbiOut, INT16 depth,
|
|
INT16 dx, INT16 dy)
|
|
{
|
|
return HIC_16(ICGetDisplayFormat(HIC_32(hic), lpbiIn, lpbiOut, depth,
|
|
dx, dy));
|
|
}
|
|
|
|
#define COPY(x,y) (x->y = x##16->y);
|
|
#define COPYPTR(x,y) (x->y = MapSL((SEGPTR)x##16->y));
|
|
|
|
/******************************************************************
|
|
* MSVIDEO_MapICDEX16To32
|
|
*
|
|
*
|
|
*/
|
|
static LPVOID MSVIDEO_MapICDEX16To32(LPDWORD lParam)
|
|
{
|
|
LPVOID ret;
|
|
|
|
ICDECOMPRESSEX *icdx = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESSEX));
|
|
ICDECOMPRESSEX16 *icdx16 = MapSL(*lParam);
|
|
ret = icdx16;
|
|
|
|
COPY(icdx, dwFlags);
|
|
COPYPTR(icdx, lpbiSrc);
|
|
COPYPTR(icdx, lpSrc);
|
|
COPYPTR(icdx, lpbiDst);
|
|
COPYPTR(icdx, lpDst);
|
|
COPY(icdx, xDst);
|
|
COPY(icdx, yDst);
|
|
COPY(icdx, dxDst);
|
|
COPY(icdx, dyDst);
|
|
COPY(icdx, xSrc);
|
|
COPY(icdx, ySrc);
|
|
COPY(icdx, dxSrc);
|
|
COPY(icdx, dySrc);
|
|
|
|
*lParam = (DWORD)(icdx);
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************
|
|
* MSVIDEO_MapMsg16To32
|
|
*
|
|
*
|
|
*/
|
|
static LPVOID MSVIDEO_MapMsg16To32(UINT msg, LPDWORD lParam1, LPDWORD lParam2)
|
|
{
|
|
LPVOID ret = 0;
|
|
|
|
TRACE("Mapping %d\n", msg);
|
|
|
|
switch (msg)
|
|
{
|
|
case DRV_LOAD:
|
|
case DRV_ENABLE:
|
|
case DRV_CLOSE:
|
|
case DRV_DISABLE:
|
|
case DRV_FREE:
|
|
case ICM_ABOUT:
|
|
case ICM_CONFIGURE:
|
|
case ICM_COMPRESS_END:
|
|
case ICM_DECOMPRESS_END:
|
|
case ICM_DECOMPRESSEX_END:
|
|
case ICM_SETQUALITY:
|
|
case ICM_DRAW_START_PLAY:
|
|
case ICM_DRAW_STOP_PLAY:
|
|
case ICM_DRAW_REALIZE:
|
|
case ICM_DRAW_RENDERBUFFER:
|
|
case ICM_DRAW_END:
|
|
break;
|
|
case DRV_OPEN:
|
|
case ICM_GETDEFAULTQUALITY:
|
|
case ICM_GETQUALITY:
|
|
case ICM_SETSTATE:
|
|
case ICM_DRAW_WINDOW:
|
|
case ICM_GETBUFFERSWANTED:
|
|
*lParam1 = (DWORD)MapSL(*lParam1);
|
|
break;
|
|
case ICM_GETINFO:
|
|
{
|
|
ICINFO *ici = HeapAlloc(GetProcessHeap(), 0, sizeof(ICINFO));
|
|
ICINFO16 *ici16;
|
|
|
|
ici16 = MapSL(*lParam1);
|
|
ret = ici16;
|
|
|
|
ici->dwSize = sizeof(ICINFO);
|
|
COPY(ici, fccType);
|
|
COPY(ici, fccHandler);
|
|
COPY(ici, dwFlags);
|
|
COPY(ici, dwVersion);
|
|
COPY(ici, dwVersionICM);
|
|
MultiByteToWideChar( CP_ACP, 0, ici16->szName, -1, ici->szName, 16 );
|
|
MultiByteToWideChar( CP_ACP, 0, ici16->szDescription, -1, ici->szDescription, 128 );
|
|
MultiByteToWideChar( CP_ACP, 0, ici16->szDriver, -1, ici->szDriver, 128 );
|
|
*lParam1 = (DWORD)(ici);
|
|
*lParam2 = sizeof(ICINFO);
|
|
}
|
|
break;
|
|
case ICM_COMPRESS:
|
|
{
|
|
ICCOMPRESS *icc = HeapAlloc(GetProcessHeap(), 0, sizeof(ICCOMPRESS));
|
|
ICCOMPRESS *icc16;
|
|
|
|
icc16 = MapSL(*lParam1);
|
|
ret = icc16;
|
|
|
|
COPY(icc, dwFlags);
|
|
COPYPTR(icc, lpbiOutput);
|
|
COPYPTR(icc, lpOutput);
|
|
COPYPTR(icc, lpbiInput);
|
|
COPYPTR(icc, lpInput);
|
|
COPYPTR(icc, lpckid);
|
|
COPYPTR(icc, lpdwFlags);
|
|
COPY(icc, lFrameNum);
|
|
COPY(icc, dwFrameSize);
|
|
COPY(icc, dwQuality);
|
|
COPYPTR(icc, lpbiPrev);
|
|
COPYPTR(icc, lpPrev);
|
|
|
|
*lParam1 = (DWORD)(icc);
|
|
*lParam2 = sizeof(ICCOMPRESS);
|
|
}
|
|
break;
|
|
case ICM_DECOMPRESS:
|
|
{
|
|
ICDECOMPRESS *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDECOMPRESS));
|
|
ICDECOMPRESS *icd16; /* Same structure except for the pointers */
|
|
|
|
icd16 = MapSL(*lParam1);
|
|
ret = icd16;
|
|
|
|
COPY(icd, dwFlags);
|
|
COPYPTR(icd, lpbiInput);
|
|
COPYPTR(icd, lpInput);
|
|
COPYPTR(icd, lpbiOutput);
|
|
COPYPTR(icd, lpOutput);
|
|
COPY(icd, ckid);
|
|
|
|
*lParam1 = (DWORD)(icd);
|
|
*lParam2 = sizeof(ICDECOMPRESS);
|
|
}
|
|
break;
|
|
case ICM_COMPRESS_BEGIN:
|
|
case ICM_COMPRESS_GET_FORMAT:
|
|
case ICM_COMPRESS_GET_SIZE:
|
|
case ICM_COMPRESS_QUERY:
|
|
case ICM_DECOMPRESS_GET_FORMAT:
|
|
case ICM_DECOMPRESS_QUERY:
|
|
case ICM_DECOMPRESS_BEGIN:
|
|
case ICM_DECOMPRESS_SET_PALETTE:
|
|
case ICM_DECOMPRESS_GET_PALETTE:
|
|
*lParam1 = (DWORD)MapSL(*lParam1);
|
|
*lParam2 = (DWORD)MapSL(*lParam2);
|
|
break;
|
|
case ICM_DECOMPRESSEX_QUERY:
|
|
if ((*lParam2 != sizeof(ICDECOMPRESSEX16)) && (*lParam2 != 0))
|
|
WARN("*lParam2 has unknown value %p\n", (ICDECOMPRESSEX16*)*lParam2);
|
|
/* FIXME: *lParm2 is meant to be 0 or an ICDECOMPRESSEX16*, but is sizeof(ICDECOMRPESSEX16)
|
|
* This is because of ICMessage(). Special case it?
|
|
{
|
|
LPVOID* addr = HeapAlloc(GetProcessHeap(), 0, 2*sizeof(LPVOID));
|
|
addr[0] = MSVIDEO_MapICDEX16To32(lParam1);
|
|
if (*lParam2)
|
|
addr[1] = MSVIDEO_MapICDEX16To32(lParam2);
|
|
else
|
|
addr[1] = 0;
|
|
|
|
ret = addr;
|
|
}
|
|
break;*/
|
|
case ICM_DECOMPRESSEX_BEGIN:
|
|
case ICM_DECOMPRESSEX:
|
|
ret = MSVIDEO_MapICDEX16To32(lParam1);
|
|
*lParam2 = sizeof(ICDECOMPRESSEX);
|
|
break;
|
|
case ICM_DRAW_BEGIN:
|
|
{
|
|
ICDRAWBEGIN *icdb = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWBEGIN));
|
|
ICDRAWBEGIN16 *icdb16 = MapSL(*lParam1);
|
|
ret = icdb16;
|
|
|
|
COPY(icdb, dwFlags);
|
|
icdb->hpal = HPALETTE_32(icdb16->hpal);
|
|
icdb->hwnd = HWND_32(icdb16->hwnd);
|
|
icdb->hdc = HDC_32(icdb16->hdc);
|
|
COPY(icdb, xDst);
|
|
COPY(icdb, yDst);
|
|
COPY(icdb, dxDst);
|
|
COPY(icdb, dyDst);
|
|
COPYPTR(icdb, lpbi);
|
|
COPY(icdb, xSrc);
|
|
COPY(icdb, ySrc);
|
|
COPY(icdb, dxSrc);
|
|
COPY(icdb, dySrc);
|
|
COPY(icdb, dwRate);
|
|
COPY(icdb, dwScale);
|
|
|
|
*lParam1 = (DWORD)(icdb);
|
|
*lParam2 = sizeof(ICDRAWBEGIN);
|
|
}
|
|
break;
|
|
case ICM_DRAW_SUGGESTFORMAT:
|
|
{
|
|
ICDRAWSUGGEST *icds = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAWSUGGEST));
|
|
ICDRAWSUGGEST16 *icds16 = MapSL(*lParam1);
|
|
|
|
ret = icds16;
|
|
|
|
COPY(icds, dwFlags);
|
|
COPYPTR(icds, lpbiIn);
|
|
COPYPTR(icds, lpbiSuggest);
|
|
COPY(icds, dxSrc);
|
|
COPY(icds, dySrc);
|
|
COPY(icds, dxDst);
|
|
COPY(icds, dyDst);
|
|
icds->hicDecompressor = HIC_32(icds16->hicDecompressor);
|
|
|
|
*lParam1 = (DWORD)(icds);
|
|
*lParam2 = sizeof(ICDRAWSUGGEST);
|
|
}
|
|
break;
|
|
case ICM_DRAW:
|
|
{
|
|
ICDRAW *icd = HeapAlloc(GetProcessHeap(), 0, sizeof(ICDRAW));
|
|
ICDRAW *icd16 = MapSL(*lParam1);
|
|
ret = icd16;
|
|
|
|
COPY(icd, dwFlags);
|
|
COPYPTR(icd, lpFormat);
|
|
COPYPTR(icd, lpData);
|
|
COPY(icd, cbData);
|
|
COPY(icd, lTime);
|
|
|
|
*lParam1 = (DWORD)(icd);
|
|
*lParam2 = sizeof(ICDRAW);
|
|
}
|
|
break;
|
|
case ICM_DRAW_START:
|
|
case ICM_DRAW_STOP:
|
|
break;
|
|
default:
|
|
FIXME("%d is not yet handled. Expect a crash.\n", msg);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#undef COPY
|
|
#undef COPYPTR
|
|
|
|
/******************************************************************
|
|
* MSVIDEO_UnmapMsg16To32
|
|
*
|
|
*
|
|
*/
|
|
static void MSVIDEO_UnmapMsg16To32(UINT msg, LPVOID data16, LPDWORD lParam1, LPDWORD lParam2)
|
|
{
|
|
TRACE("Unmapping %d\n", msg);
|
|
|
|
#define UNCOPY(x, y) (x##16->y = x->y);
|
|
|
|
switch (msg)
|
|
{
|
|
case ICM_GETINFO:
|
|
{
|
|
ICINFO *ici = (ICINFO*)(*lParam1);
|
|
ICINFO16 *ici16 = data16;
|
|
|
|
UNCOPY(ici, fccType);
|
|
UNCOPY(ici, fccHandler);
|
|
UNCOPY(ici, dwFlags);
|
|
UNCOPY(ici, dwVersion);
|
|
UNCOPY(ici, dwVersionICM);
|
|
WideCharToMultiByte( CP_ACP, 0, ici->szName, -1, ici16->szName,
|
|
sizeof(ici16->szName), NULL, NULL );
|
|
ici16->szName[sizeof(ici16->szName)-1] = 0;
|
|
WideCharToMultiByte( CP_ACP, 0, ici->szDescription, -1, ici16->szDescription,
|
|
sizeof(ici16->szDescription), NULL, NULL );
|
|
ici16->szDescription[sizeof(ici16->szDescription)-1] = 0;
|
|
/* This just gives garbage for some reason - BB
|
|
lstrcpynWtoA(ici16->szDriver, ici->szDriver, 128);*/
|
|
|
|
HeapFree(GetProcessHeap(), 0, ici);
|
|
}
|
|
break;
|
|
case ICM_DECOMPRESS_QUERY:
|
|
/*{
|
|
LPVOID* x = data16;
|
|
HeapFree(GetProcessHeap(), 0, x[0]);
|
|
if (x[1])
|
|
HeapFree(GetProcessHeap(), 0, x[1]);
|
|
}
|
|
break;*/
|
|
case ICM_COMPRESS:
|
|
case ICM_DECOMPRESS:
|
|
case ICM_DECOMPRESSEX_QUERY:
|
|
case ICM_DECOMPRESSEX_BEGIN:
|
|
case ICM_DECOMPRESSEX:
|
|
case ICM_DRAW_BEGIN:
|
|
case ICM_DRAW_SUGGESTFORMAT:
|
|
case ICM_DRAW:
|
|
HeapFree(GetProcessHeap(), 0, data16);
|
|
break;
|
|
default:
|
|
ERR("Unmapping unmapped msg %d\n", msg);
|
|
}
|
|
#undef UNCOPY
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICInfo [MSVIDEO.200]
|
|
*/
|
|
BOOL16 VFWAPI ICInfo16(DWORD fccType, DWORD fccHandler, ICINFO16 *lpicinfo)
|
|
{
|
|
BOOL16 ret;
|
|
LPVOID lpv;
|
|
DWORD lParam = (DWORD)lpicinfo;
|
|
DWORD size = ((ICINFO*)(MapSL((SEGPTR)lpicinfo)))->dwSize;
|
|
|
|
/* Use the mapping functions to map the ICINFO structure */
|
|
lpv = MSVIDEO_MapMsg16To32(ICM_GETINFO, &lParam, &size);
|
|
|
|
ret = ICInfo(fccType, fccHandler, (ICINFO*)lParam);
|
|
|
|
MSVIDEO_UnmapMsg16To32(ICM_GETINFO, lpv, &lParam, &size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************
|
|
* IC_Callback3216
|
|
*
|
|
*
|
|
*/
|
|
static LRESULT CALLBACK IC_Callback3216(DWORD pfn16, HIC hic, HDRVR hdrv, UINT msg, LPARAM lp1, LPARAM lp2)
|
|
{
|
|
WORD args[8];
|
|
DWORD ret = 0;
|
|
|
|
switch (msg)
|
|
{
|
|
case DRV_OPEN:
|
|
lp2 = (DWORD)MapLS((void*)lp2);
|
|
break;
|
|
}
|
|
args[7] = HIWORD(hic);
|
|
args[6] = LOWORD(hic);
|
|
args[5] = HDRVR_16(hdrv);
|
|
args[4] = msg;
|
|
args[3] = HIWORD(lp1);
|
|
args[2] = LOWORD(lp1);
|
|
args[1] = HIWORD(lp2);
|
|
args[0] = LOWORD(lp2);
|
|
WOWCallback16Ex( pfn16, WCB16_PASCAL, sizeof(args), args, &ret );
|
|
|
|
switch (msg)
|
|
{
|
|
case DRV_OPEN:
|
|
UnMapLS(lp2);
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#define MAX_THUNKS 32
|
|
|
|
#include "pshpack1.h"
|
|
static struct msvideo_thunk
|
|
{
|
|
BYTE popl_eax; /* popl %eax (return address) */
|
|
BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */
|
|
DWORD pfn16;
|
|
BYTE pushl_eax; /* pushl %eax */
|
|
BYTE jmp; /* ljmp WDML_InvokeCallback16 */
|
|
DWORD callback;
|
|
HIC16 hIC16; /* driver's handle */
|
|
} *MSVIDEO_Thunks;
|
|
#include "poppack.h"
|
|
|
|
static CRITICAL_SECTION msvideo_cs;
|
|
static CRITICAL_SECTION_DEBUG critsect_debug =
|
|
{
|
|
0, 0, &msvideo_cs,
|
|
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": msvideo_cs") }
|
|
};
|
|
static CRITICAL_SECTION msvideo_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
|
|
|
|
static struct msvideo_thunk* MSVIDEO_AddThunk(DWORD pfn16)
|
|
{
|
|
struct msvideo_thunk* thunk;
|
|
|
|
if (!MSVIDEO_Thunks)
|
|
{
|
|
MSVIDEO_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*MSVIDEO_Thunks), MEM_COMMIT,
|
|
PAGE_EXECUTE_READWRITE);
|
|
if (!MSVIDEO_Thunks) return NULL;
|
|
for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
|
|
{
|
|
thunk->popl_eax = 0x58; /* popl %eax */
|
|
thunk->pushl_func = 0x68; /* pushl $pfn16 */
|
|
thunk->pfn16 = 0;
|
|
thunk->pushl_eax = 0x50; /* pushl %eax */
|
|
thunk->jmp = 0xe9; /* jmp IC_Callback3216 */
|
|
thunk->callback = (char *)IC_Callback3216 - (char *)(&thunk->callback + 1);
|
|
thunk->hIC16 = 0;
|
|
}
|
|
}
|
|
for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
|
|
{
|
|
if (thunk->pfn16 == 0)
|
|
{
|
|
thunk->pfn16 = pfn16;
|
|
return thunk;
|
|
}
|
|
}
|
|
FIXME("Out of msvideo-thunks. Bump MAX_THUNKS\n");
|
|
return NULL;
|
|
}
|
|
|
|
static struct msvideo_thunk* MSVIDEO_HasThunk(HIC16 hic)
|
|
{
|
|
struct msvideo_thunk* thunk;
|
|
|
|
if (!MSVIDEO_Thunks)
|
|
return NULL;
|
|
|
|
for (thunk = MSVIDEO_Thunks; thunk < &MSVIDEO_Thunks[MAX_THUNKS]; thunk++)
|
|
{
|
|
if (thunk->hIC16 == hic) return thunk;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICOpenFunction [MSVIDEO.206]
|
|
*/
|
|
HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler)
|
|
{
|
|
HIC hic32;
|
|
struct msvideo_thunk* thunk;
|
|
|
|
EnterCriticalSection(&msvideo_cs);
|
|
if (!(thunk = MSVIDEO_AddThunk((DWORD)lpfnHandler)))
|
|
{
|
|
LeaveCriticalSection(&msvideo_cs);
|
|
return 0;
|
|
}
|
|
if ((hic32 = ICOpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)thunk)))
|
|
thunk->hIC16 = HIC_16(hic32);
|
|
else
|
|
thunk->pfn16 = 0;
|
|
LeaveCriticalSection(&msvideo_cs);
|
|
return HIC_16(hic32);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICSendMessage [MSVIDEO.205]
|
|
*/
|
|
LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2)
|
|
{
|
|
LRESULT ret = ICERR_BADHANDLE;
|
|
struct msvideo_thunk* thunk;
|
|
|
|
if ((thunk = MSVIDEO_HasThunk(hic)))
|
|
{
|
|
WORD args[8];
|
|
DWORD result;
|
|
|
|
/* FIXME: original code was passing hdrv first and hic second */
|
|
/* but this doesn't match what IC_Callback3216 does */
|
|
args[7] = HIWORD(hic);
|
|
args[6] = LOWORD(hic);
|
|
args[5] = 0; /* the 32bit also sets it to NULL */
|
|
args[4] = msg;
|
|
args[3] = HIWORD(lParam1);
|
|
args[2] = LOWORD(lParam1);
|
|
args[1] = HIWORD(lParam2);
|
|
args[0] = LOWORD(lParam2);
|
|
WOWCallback16Ex( thunk->pfn16, WCB16_PASCAL, sizeof(args), args, &result );
|
|
ret = result;
|
|
}
|
|
else
|
|
{
|
|
/* map the message for a 32 bit infrastructure, and pass it along */
|
|
void* data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2);
|
|
|
|
ret = ICSendMessage(HIC_32(hic), msg, lParam1, lParam2);
|
|
if (data16)
|
|
MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* ICClose [MSVIDEO.204]
|
|
*/
|
|
LRESULT WINAPI ICClose16(HIC16 hic)
|
|
{
|
|
BOOL ret = ICClose(HIC_32(hic));
|
|
|
|
EnterCriticalSection(&msvideo_cs);
|
|
if (ret)
|
|
{
|
|
struct msvideo_thunk* thunk;
|
|
if ((thunk = MSVIDEO_HasThunk(hic)))
|
|
{
|
|
thunk->pfn16 = 0;
|
|
thunk->hIC16 = 0;
|
|
}
|
|
else ret = FALSE;
|
|
}
|
|
LeaveCriticalSection(&msvideo_cs);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* VideoCapDriverDescAndVer [MSVIDEO.22]
|
|
*/
|
|
DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len,
|
|
LPSTR buf2, WORD buf2len)
|
|
{
|
|
static const char version_info_spec[] = "\\StringFileInfo\\040904E4\\FileDescription";
|
|
DWORD verhandle;
|
|
DWORD infosize;
|
|
UINT subblocklen;
|
|
char *s, buf[2048], fn[260];
|
|
LPBYTE infobuf;
|
|
LPVOID subblock;
|
|
DWORD i, cnt = 0, lRet;
|
|
DWORD bufLen, fnLen;
|
|
FILETIME lastWrite;
|
|
HKEY hKey;
|
|
BOOL found = FALSE;
|
|
|
|
TRACE("(%d,%p,%d,%p,%d)\n", nr, buf1, buf1len, buf2, buf2len);
|
|
lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, HKLM_DRIVERS32, 0, KEY_QUERY_VALUE, &hKey);
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
RegQueryInfoKeyA( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0);
|
|
for (i = 0; i < cnt; i++)
|
|
{
|
|
bufLen = sizeof(buf) / sizeof(buf[0]);
|
|
lRet = RegEnumKeyExA(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite);
|
|
if (lRet != ERROR_SUCCESS) continue;
|
|
if (strncasecmp(buf, "vid", 3)) continue;
|
|
if (nr--) continue;
|
|
fnLen = sizeof(fn);
|
|
lRet = RegQueryValueExA(hKey, buf, 0, 0, (LPBYTE)fn, &fnLen);
|
|
if (lRet == ERROR_SUCCESS) found = TRUE;
|
|
break;
|
|
}
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
/* search system.ini if not found in the registry */
|
|
if (!found && GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini"))
|
|
{
|
|
for (s = buf; *s; s += strlen(s) + 1)
|
|
{
|
|
if (strncasecmp(s, "vid", 3)) continue;
|
|
if (nr--) continue;
|
|
if (GetPrivateProfileStringA("drivers32", s, NULL, fn, sizeof(fn), "system.ini"))
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
TRACE("No more VID* entries found nr=%d\n", nr);
|
|
return 20;
|
|
}
|
|
infosize = GetFileVersionInfoSizeA(fn, &verhandle);
|
|
if (!infosize)
|
|
{
|
|
TRACE("%s has no fileversioninfo.\n", fn);
|
|
return 18;
|
|
}
|
|
infobuf = HeapAlloc(GetProcessHeap(), 0, infosize);
|
|
if (GetFileVersionInfoA(fn, verhandle, infosize, infobuf))
|
|
{
|
|
/* Yes, two space behind : */
|
|
/* FIXME: test for buflen */
|
|
snprintf(buf2, buf2len, "Version: %d.%d.%d.%d\n",
|
|
((WORD*)infobuf)[0x0f],
|
|
((WORD*)infobuf)[0x0e],
|
|
((WORD*)infobuf)[0x11],
|
|
((WORD*)infobuf)[0x10]
|
|
);
|
|
TRACE("version of %s is %s\n", fn, buf2);
|
|
}
|
|
else
|
|
{
|
|
TRACE("GetFileVersionInfoA failed for %s.\n", fn);
|
|
lstrcpynA(buf2, fn, buf2len); /* msvideo.dll appears to copy fn*/
|
|
}
|
|
/* FIXME: language problem? */
|
|
if (VerQueryValueA( infobuf,
|
|
version_info_spec,
|
|
&subblock,
|
|
&subblocklen
|
|
))
|
|
{
|
|
UINT copylen = min(subblocklen,buf1len-1);
|
|
memcpy(buf1, subblock, copylen);
|
|
buf1[copylen] = '\0';
|
|
TRACE("VQA returned %s\n", (LPCSTR)subblock);
|
|
}
|
|
else
|
|
{
|
|
TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n");
|
|
lstrcpynA(buf1, fn, buf1len); /* msvideo.dll appears to copy fn*/
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, infobuf);
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* DllEntryPoint (MSVIDEO.3)
|
|
*
|
|
* MSVIDEO DLL entry point
|
|
*
|
|
*/
|
|
BOOL WINAPI VIDEO_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
|
|
WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
|
|
{
|
|
switch (fdwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
break;
|
|
case DLL_PROCESS_DETACH:
|
|
DeleteCriticalSection(&msvideo_cs);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* MCIWndRegisterClass(MSVIDEO.251)
|
|
*/
|
|
BOOL CDECL MCIWndRegisterClass16(void)
|
|
{
|
|
return MCIWndRegisterClass();
|
|
}
|
|
|
|
static LRESULT (WINAPI *pMCIWndProc)(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
|
|
|
static LRESULT WINAPI MCIWndProc16(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
switch (msg)
|
|
{
|
|
case MCIWNDM_SENDSTRINGA:
|
|
case MCIWNDM_SETTIMEFORMATA:
|
|
lparam = (ULONG_PTR)MapSL(lparam);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return CallWindowProcA(pMCIWndProc, hwnd, msg, wparam, lparam);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* MCIWndCreate(MSVIDEO.250)
|
|
*/
|
|
HWND16 CDECL MCIWndCreate16(HWND16 parent, HINSTANCE16 hinst16,
|
|
DWORD style, LPSTR file)
|
|
{
|
|
HWND hwnd = MCIWndCreateA(HWND_32(parent), 0, style, file);
|
|
if (hwnd)
|
|
pMCIWndProc = (void *)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)MCIWndProc16);
|
|
return HWND_16(hwnd);
|
|
}
|