From 2396faea94b68ed751a58809063c2f754dbb1111 Mon Sep 17 00:00:00 2001 From: Steven Edwards Date: Sat, 10 Jul 2004 21:19:46 +0000 Subject: [PATCH] Added msvfw32 ported from Wine. This fixes bug 388. svn path=/trunk/; revision=10068 --- reactos/lib/msvideo/.cvsignore | 9 + reactos/lib/msvideo/Makefile | 9 + reactos/lib/msvideo/Makefile.in | 22 + reactos/lib/msvideo/Makefile.ros-template | 21 + reactos/lib/msvideo/drawdib.c | 463 +++++++ reactos/lib/msvideo/mciwnd.c | 1419 +++++++++++++++++++++ reactos/lib/msvideo/msvfw32.rc | 38 + reactos/lib/msvideo/msvfw32.spec | 51 + reactos/lib/msvideo/msvfw32.spec.def | 43 + reactos/lib/msvideo/msvideo.spec | 68 + reactos/lib/msvideo/msvideo16.c | 910 +++++++++++++ reactos/lib/msvideo/msvideo_main.c | 1184 +++++++++++++++++ reactos/lib/msvideo/msvideo_private.h | 65 + reactos/lib/msvideo/vfw16.h | 130 ++ 14 files changed, 4432 insertions(+) create mode 100644 reactos/lib/msvideo/.cvsignore create mode 100644 reactos/lib/msvideo/Makefile create mode 100644 reactos/lib/msvideo/Makefile.in create mode 100644 reactos/lib/msvideo/Makefile.ros-template create mode 100644 reactos/lib/msvideo/drawdib.c create mode 100644 reactos/lib/msvideo/mciwnd.c create mode 100644 reactos/lib/msvideo/msvfw32.rc create mode 100644 reactos/lib/msvideo/msvfw32.spec create mode 100644 reactos/lib/msvideo/msvfw32.spec.def create mode 100644 reactos/lib/msvideo/msvideo.spec create mode 100644 reactos/lib/msvideo/msvideo16.c create mode 100644 reactos/lib/msvideo/msvideo_main.c create mode 100644 reactos/lib/msvideo/msvideo_private.h create mode 100644 reactos/lib/msvideo/vfw16.h diff --git a/reactos/lib/msvideo/.cvsignore b/reactos/lib/msvideo/.cvsignore new file mode 100644 index 00000000000..8f3b3e45db8 --- /dev/null +++ b/reactos/lib/msvideo/.cvsignore @@ -0,0 +1,9 @@ +*.coff +*.dll +*.sym +*.o +*.d +*.map +*.tmp +Makefile.ros +oleaut32.spec.def diff --git a/reactos/lib/msvideo/Makefile b/reactos/lib/msvideo/Makefile new file mode 100644 index 00000000000..36ab3ede514 --- /dev/null +++ b/reactos/lib/msvideo/Makefile @@ -0,0 +1,9 @@ +# $Id: Makefile,v 1.1 2004/07/10 21:19:46 sedwards Exp $ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = winedll + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/lib/msvideo/Makefile.in b/reactos/lib/msvideo/Makefile.in new file mode 100644 index 00000000000..b52a912c7be --- /dev/null +++ b/reactos/lib/msvideo/Makefile.in @@ -0,0 +1,22 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = msvfw32.dll +IMPORTS = winmm comctl32 version user32 gdi32 advapi32 kernel32 ntdll +ALTNAMES = msvideo.dll +EXTRALIBS = $(LIBUNICODE) + +SPEC_SRCS16 = $(ALTNAMES:.dll=.spec) + +C_SRCS = \ + mciwnd.c \ + msvideo_main.c \ + drawdib.c + +C_SRCS16 = \ + msvideo16.c + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/reactos/lib/msvideo/Makefile.ros-template b/reactos/lib/msvideo/Makefile.ros-template new file mode 100644 index 00000000000..6bca328078d --- /dev/null +++ b/reactos/lib/msvideo/Makefile.ros-template @@ -0,0 +1,21 @@ +# $Id: Makefile.ros-template,v 1.1 2004/07/10 21:19:46 sedwards Exp $ + +TARGET_NAME = msvfw32 + +TARGET_OBJECTS = @C_SRCS@ + +TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ + +TARGET_SDKLIBS = @IMPORTS@ libwine.a wine_uuid.a ntdll.a + +TARGET_BASE = $(TARGET_BASE_LIB_WINMM) + +TARGET_RC_SRCS = @RC_SRCS@ +TARGET_RC_BINSRC = @RC_BINSRC@ +TARGET_RC_BINARIES = @RC_BINARIES@ + +default: all + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/msvideo/drawdib.c b/reactos/lib/msvideo/drawdib.c new file mode 100644 index 00000000000..fa4c92ff35a --- /dev/null +++ b/reactos/lib/msvideo/drawdib.c @@ -0,0 +1,463 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: Some flags are ignored + * + * Handle palettes + */ + +#include +#include "msvideo_private.h" + +#include "wingdi.h" +#include "winuser.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msvideo); + +typedef struct tagWINE_HDD { + HDC hdc; + INT dxDst; + INT dyDst; + LPBITMAPINFOHEADER lpbi; + INT dxSrc; + INT dySrc; + HPALETTE hpal; /* Palette to use for the DIB */ + BOOL begun; /* DrawDibBegin has been called */ + LPBITMAPINFOHEADER lpbiOut; /* Output format */ + HIC hic; /* HIC for decompression */ + HDC hMemDC; /* DC for buffering */ + HBITMAP hOldDib; /* Original Dib */ + HBITMAP hDib; /* DibSection */ + LPVOID lpvbits; /* Buffer for holding decompressed dib */ + HDRAWDIB hSelf; + struct tagWINE_HDD* next; +} WINE_HDD; + +int num_colours(LPBITMAPINFOHEADER lpbi) +{ + if(lpbi->biClrUsed) + return lpbi->biClrUsed; + if(lpbi->biBitCount<=8) + return 1<biBitCount; + return 0; +} + +static WINE_HDD* HDD_FirstHdd /* = NULL */; + +static WINE_HDD* MSVIDEO_GetHddPtr(HDRAWDIB hd) +{ + WINE_HDD* hdd; + + for (hdd = HDD_FirstHdd; hdd != NULL && hdd->hSelf != hd; hdd = hdd->next); + return hdd; +} + +static DWORD HDD_HandleRef = 1; + +/*********************************************************************** + * DrawDibOpen [MSVFW32.@] + */ +HDRAWDIB VFWAPI DrawDibOpen(void) +{ + WINE_HDD* whdd; + + TRACE("(void)\n"); + + whdd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_HDD)); + TRACE("=> %p\n", whdd); + + while (MSVIDEO_GetHddPtr((HDRAWDIB)HDD_HandleRef) != NULL) HDD_HandleRef++; + whdd->hSelf = (HDRAWDIB)HDD_HandleRef++; + + whdd->next = HDD_FirstHdd; + HDD_FirstHdd = whdd; + + return whdd->hSelf; +} + +/*********************************************************************** + * DrawDibClose [MSVFW32.@] + */ +BOOL VFWAPI DrawDibClose(HDRAWDIB hdd) +{ + WINE_HDD* whdd = MSVIDEO_GetHddPtr(hdd); + WINE_HDD** p; + + TRACE("(%p)\n", hdd); + + if (!whdd) return FALSE; + + if (whdd->begun) DrawDibEnd(hdd); + + for (p = &HDD_FirstHdd; *p != NULL; p = &((*p)->next)) + { + if (*p == whdd) + { + *p = whdd->next; + break; + } + } + + HeapFree(GetProcessHeap(), 0, whdd); + + return TRUE; +} + +/*********************************************************************** + * DrawDibEnd [MSVFW32.@] + */ +BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd) +{ + BOOL ret = TRUE; + WINE_HDD *whdd = MSVIDEO_GetHddPtr(hdd); + + TRACE("(%p)\n", hdd); + + whdd->hpal = 0; /* Do not free this */ + whdd->hdc = 0; + if (whdd->lpbi) + { + HeapFree(GetProcessHeap(), 0, whdd->lpbi); + whdd->lpbi = NULL; + } + if (whdd->lpbiOut) + { + HeapFree(GetProcessHeap(), 0, whdd->lpbiOut); + whdd->lpbiOut = NULL; + } + + whdd->begun = FALSE; + + /*if (whdd->lpvbits) + HeapFree(GetProcessHeap(), 0, whdd->lpvbuf);*/ + + if (whdd->hMemDC) + { + SelectObject(whdd->hMemDC, whdd->hOldDib); + DeleteDC(whdd->hMemDC); + whdd->hMemDC = 0; + } + + if (whdd->hDib) DeleteObject(whdd->hDib); + whdd->hDib = 0; + + if (whdd->hic) + { + ICDecompressEnd(whdd->hic); + ICClose(whdd->hic); + whdd->hic = 0; + } + + whdd->lpvbits = NULL; + + return ret; +} + +/*********************************************************************** + * DrawDibBegin [MSVFW32.@] + */ +BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd, + HDC hdc, + INT dxDst, + INT dyDst, + LPBITMAPINFOHEADER lpbi, + INT dxSrc, + INT dySrc, + UINT wFlags) +{ + BOOL ret = TRUE; + WINE_HDD *whdd; + + TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08lx)\n", + hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, (DWORD)wFlags); + + TRACE("lpbi: %ld,%ld/%ld,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld\n", + lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes, + lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage, + lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed, + lpbi->biClrImportant); + + if (wFlags & ~(DDF_BUFFER)) + FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER)); + + whdd = MSVIDEO_GetHddPtr(hdd); + if (!whdd) return FALSE; + + if (whdd->begun) DrawDibEnd(hdd); + + if (lpbi->biCompression) + { + DWORD size = 0; + + whdd->hic = ICOpen(ICTYPE_VIDEO, lpbi->biCompression, ICMODE_DECOMPRESS); + if (!whdd->hic) + { + WARN("Could not open IC. biCompression == 0x%08lx\n", lpbi->biCompression); + ret = FALSE; + } + + if (ret) + { + size = ICDecompressGetFormat(whdd->hic, lpbi, NULL); + if (size == ICERR_UNSUPPORTED) + { + WARN("Codec doesn't support GetFormat, giving up.\n"); + ret = FALSE; + } + } + + if (ret) + { + whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, size); + + if (ICDecompressGetFormat(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK) + ret = FALSE; + } + + if (ret) + { + /* FIXME: Use Ex functions if available? */ + if (ICDecompressBegin(whdd->hic, lpbi, whdd->lpbiOut) != ICERR_OK) + ret = FALSE; + + TRACE("biSizeImage == %ld\n", whdd->lpbiOut->biSizeImage); + TRACE("biCompression == %ld\n", whdd->lpbiOut->biCompression); + TRACE("biBitCount == %d\n", whdd->lpbiOut->biBitCount); + } + } + else + { + DWORD dwSize; + /* No compression */ + TRACE("Not compressed!\n"); + dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD); + whdd->lpbiOut = HeapAlloc(GetProcessHeap(), 0, dwSize); + memcpy(whdd->lpbiOut, lpbi, dwSize); + } + + if (ret) + { + /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(), 0, whdd->lpbiOut->biSizeImage);*/ + + whdd->hMemDC = CreateCompatibleDC(hdc); + TRACE("Creating: %ld, %p\n", whdd->lpbiOut->biSize, whdd->lpvbits); + whdd->hDib = CreateDIBSection(whdd->hMemDC, (BITMAPINFO *)whdd->lpbiOut, DIB_RGB_COLORS, &(whdd->lpvbits), 0, 0); + if (!whdd->hDib) + { + TRACE("Error: %ld\n", GetLastError()); + } + TRACE("Created: %p,%p\n", whdd->hDib, whdd->lpvbits); + whdd->hOldDib = SelectObject(whdd->hMemDC, whdd->hDib); + } + + if (ret) + { + whdd->hdc = hdc; + whdd->dxDst = dxDst; + whdd->dyDst = dyDst; + whdd->lpbi = HeapAlloc(GetProcessHeap(), 0, lpbi->biSize); + memcpy(whdd->lpbi, lpbi, lpbi->biSize); + whdd->dxSrc = dxSrc; + whdd->dySrc = dySrc; + whdd->begun = TRUE; + whdd->hpal = 0; + } + else + { + if (whdd->hic) + ICClose(whdd->hic); + if (whdd->lpbiOut) + { + HeapFree(GetProcessHeap(), 0, whdd->lpbiOut); + whdd->lpbiOut = NULL; + } + } + + return ret; +} + +/********************************************************************** + * DrawDibDraw [MSVFW32.@] + */ +BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc, + INT xDst, INT yDst, INT dxDst, INT dyDst, + LPBITMAPINFOHEADER lpbi, + LPVOID lpBits, + INT xSrc, INT ySrc, INT dxSrc, INT dySrc, + UINT wFlags) +{ + WINE_HDD *whdd; + BOOL ret = TRUE; + + TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08lx)\n", + hdd, hdc, xDst, yDst, dxDst, dyDst, lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc, (DWORD)wFlags); + + whdd = MSVIDEO_GetHddPtr(hdd); + if (!whdd) return FALSE; + + if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME | DDF_UPDATE | DDF_DONTDRAW)) + FIXME("wFlags == 0x%08lx not handled\n", (DWORD)wFlags); + + if (!lpBits) + { + /* Undocumented? */ + lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD)); + } + + +#define CHANGED(x) (whdd->x != x) + + if ((!whdd->begun) || + (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) || + (!(wFlags & DDF_SAME_DRAW) && (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst)))) + { + TRACE("Something changed!\n"); + ret = DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, 0); + } + +#undef CHANGED + + if ((dxDst == -1) && (dyDst == -1)) + { + dxDst = dxSrc; + dyDst = dySrc; + } + + if (!(wFlags & DDF_UPDATE)) + { + /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */ + if ((lpbi->biCompression == BI_RGB) && (lpbi->biSizeImage == 0)) + lpbi->biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight; + + if (lpbi->biCompression) + { + DWORD flags = 0; + + TRACE("Compression == 0x%08lx\n", lpbi->biCompression); + + if (wFlags & DDF_NOTKEYFRAME) + flags |= ICDECOMPRESS_NOTKEYFRAME; + + ICDecompress(whdd->hic, flags, lpbi, lpBits, whdd->lpbiOut, whdd->lpvbits); + } + else + { + memcpy(whdd->lpvbits, lpBits, lpbi->biSizeImage); + } + } + if (!(wFlags & DDF_DONTDRAW) && whdd->hpal) + SelectPalette(hdc, whdd->hpal, FALSE); + + if (!(StretchBlt(whdd->hdc, xDst, yDst, dxDst, dyDst, whdd->hMemDC, xSrc, ySrc, dxSrc, dySrc, SRCCOPY))) + ret = FALSE; + + return ret; +} + +/************************************************************************* + * DrawDibStart [MSVFW32.@] + */ +BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) { + FIXME("(%p, %ld), stub\n", hdd, rate); + return TRUE; +} + +/************************************************************************* + * DrawDibStop [MSVFW32.@] + */ +BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) { + FIXME("(%p), stub\n", hdd); + return TRUE; +} + +/*********************************************************************** + * DrawDibSetPalette [MSVFW32.@] + */ +BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal) +{ + WINE_HDD *whdd; + + TRACE("(%p, %p)\n", hdd, hpal); + + whdd = MSVIDEO_GetHddPtr(hdd); + if (!whdd) return FALSE; + + whdd->hpal = hpal; + + if (whdd->begun) + { + SelectPalette(whdd->hdc, hpal, 0); + RealizePalette(whdd->hdc); + } + + return TRUE; +} + +/*********************************************************************** + * DrawDibGetPalette [MSVFW32.@] + */ +HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd) +{ + WINE_HDD *whdd; + + TRACE("(%p)\n", hdd); + + whdd = MSVIDEO_GetHddPtr(hdd); + if (!whdd) return FALSE; + + return whdd->hpal; +} + +/*********************************************************************** + * DrawDibRealize [MSVFW32.@] + */ +UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground) +{ + WINE_HDD *whdd; + HPALETTE oldPal; + UINT ret = 0; + + FIXME("(%p, %p, %d), stub\n", hdd, hdc, fBackground); + + whdd = MSVIDEO_GetHddPtr(hdd); + if (!whdd) return FALSE; + + if (!whdd || !(whdd->begun)) + { + ret = 0; + goto out; + } + + if (!whdd->hpal) + whdd->hpal = CreateHalftonePalette(hdc); + + oldPal = SelectPalette(hdc, whdd->hpal, fBackground); + ret = RealizePalette(hdc); + + out: + TRACE("=> %u\n", ret); + return ret; +} + +DWORD VFWAPI DrawDibProfileDisplay(LPBITMAPINFOHEADER lpbi) +{ + FIXME("(%p) stub\n", lpbi); + + return PD_CAN_DRAW_DIB; +} diff --git a/reactos/lib/msvideo/mciwnd.c b/reactos/lib/msvideo/mciwnd.c new file mode 100644 index 00000000000..9260c01e719 --- /dev/null +++ b/reactos/lib/msvideo/mciwnd.c @@ -0,0 +1,1419 @@ +/* + * Copyright 2000 Eric Pouech + * Copyright 2003 Dmitry Timoshkov + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: + * Add support for all remaining MCI_ commands and MCIWNDM_ messages. + * Add support for MCIWNDF_RECORD. + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" +#include "winternl.h" +#include "vfw.h" +#include "digitalv.h" +#include "commctrl.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mci); + +extern HMODULE MSVFW32_hModule; +static const WCHAR mciWndClassW[] = {'M','C','I','W','n','d','C','l','a','s','s',0}; + +typedef struct +{ + DWORD dwStyle; + MCIDEVICEID mci; + HDRVR hdrv; + int alias; + UINT dev_type; + UINT mode; + long position; + SIZE size; /* size of the original frame rect */ + int zoom; + LPWSTR lpName; + HWND hWnd, hwndOwner; + UINT uTimer; + MCIERROR lasterror; + WCHAR return_string[128]; + WORD active_timer, inactive_timer; +} MCIWndInfo; + +static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam); + +#define CTL_PLAYSTOP 0x3200 +#define CTL_MENU 0x3201 +#define CTL_TRACKBAR 0x3202 + +/*********************************************************************** + * MCIWndRegisterClass [MSVFW32.@] + * + * NOTE: Native always uses its own hInstance + */ +BOOL VFWAPIV MCIWndRegisterClass(void) +{ + WNDCLASSW wc; + + /* Since we are going to register a class belonging to MSVFW32 + * and later we will create windows with a different hInstance + * CS_GLOBALCLASS is needed. And because the second attempt + * to register a global class will fail we need to test whether + * the class was already registered. + */ + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS; + wc.lpfnWndProc = MCIWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(MCIWndInfo*); + wc.hInstance = MSVFW32_hModule; + wc.hIcon = 0; + wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW)); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = mciWndClassW; + + if (RegisterClassW(&wc)) return TRUE; + if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE; + + return FALSE; +} + +/*********************************************************************** + * MCIWndCreateW [MSVFW32.@] + */ +HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance, + DWORD dwStyle, LPCWSTR szFile) +{ + TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile)); + + MCIWndRegisterClass(); + + if (!hInstance) hInstance = GetModuleHandleW(0); + + if (hwndParent) + dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/; + else + dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + + return CreateWindowExW(0, mciWndClassW, NULL, + dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, 0, 300, 0, + hwndParent, 0, hInstance, (LPVOID)szFile); +} + +/*********************************************************************** + * MCIWndCreate [MSVFW32.@] + * MCIWndCreateA [MSVFW32.@] + */ +HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance, + DWORD dwStyle, LPCSTR szFile) +{ + HWND ret; + UNICODE_STRING fileW; + + if (szFile) + RtlCreateUnicodeStringFromAsciiz(&fileW, szFile); + else + fileW.Buffer = NULL; + + ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer); + + RtlFreeUnicodeString(&fileW); + return ret; +} + +static inline void MCIWND_notify_mode(MCIWndInfo *mwi) +{ + if (mwi->dwStyle & MCIWNDF_NOTIFYMODE) + { + UINT new_mode = SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0); + if (new_mode != mwi->mode) + { + mwi->mode = new_mode; + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)mwi->hWnd, new_mode); + } + } +} + +static inline void MCIWND_notify_pos(MCIWndInfo *mwi) +{ + if (mwi->dwStyle & MCIWNDF_NOTIFYPOS) + { + long new_pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0); + if (new_pos != mwi->position) + { + mwi->position = new_pos; + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)mwi->hWnd, new_pos); + } + } +} + +static inline void MCIWND_notify_size(MCIWndInfo *mwi) +{ + if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE) + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)mwi->hWnd, 0); +} + +static inline void MCIWND_notify_error(MCIWndInfo *mwi) +{ + if (mwi->dwStyle & MCIWNDF_NOTIFYERROR) + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)mwi->hWnd, (LPARAM)mwi->lasterror); +} + +static void MCIWND_UpdateState(MCIWndInfo *mwi) +{ + WCHAR buffer[1024]; + + if (!mwi->mci) + { + /* FIXME: get this from resources */ + static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0}; + SetWindowTextW(mwi->hWnd, no_deviceW); + return; + } + + MCIWND_notify_pos(mwi); + + if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR)) + SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position); + + if (!(mwi->dwStyle & MCIWNDF_SHOWALL)) + return; + + if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName) + strcpyW(buffer, mwi->lpName); + else + *buffer = 0; + + if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) + { + static const WCHAR spaceW[] = {' ',0}; + static const WCHAR l_braceW[] = {'(',0}; + + if (*buffer) strcatW(buffer, spaceW); + strcatW(buffer, l_braceW); + } + + if (mwi->dwStyle & MCIWNDF_SHOWPOS) + { + WCHAR posW[64]; + + posW[0] = 0; + SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW); + strcatW(buffer, posW); + } + + if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) + { + static const WCHAR dashW[] = {' ','-',' ',0}; + strcatW(buffer, dashW); + } + + if (mwi->dwStyle & MCIWNDF_SHOWMODE) + { + WCHAR modeW[64]; + + modeW[0] = 0; + SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW); + strcatW(buffer, modeW); + } + + if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) + { + static const WCHAR r_braceW[] = {')',0}; + strcatW(buffer, r_braceW); + } + + TRACE("=> '%s'\n", debugstr_w(buffer)); + SetWindowTextW(mwi->hWnd, buffer); +} + +static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs) +{ + HWND hChld; + MCIWndInfo *mwi; + static const WCHAR buttonW[] = {'b','u','t','t','o','n',0}; + + mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi)); + if (!mwi) return -1; + + SetWindowLongW(hWnd, 0, (LPARAM)mwi); + + mwi->dwStyle = cs->style; + /* There is no need to show stats if there is no caption */ + if ((mwi->dwStyle & WS_CAPTION) != WS_CAPTION) + mwi->dwStyle &= ~MCIWNDF_SHOWALL; + + mwi->hWnd = hWnd; + mwi->hwndOwner = cs->hwndParent; + mwi->active_timer = 500; + mwi->inactive_timer = 2000; + mwi->mode = MCI_MODE_NOT_READY; + mwi->position = -1; + mwi->zoom = 100; + + if (!(mwi->dwStyle & MCIWNDF_NOMENU)) + { + static const WCHAR menuW[] = {'M','e','n','u',0}; + + hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32, + hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L); + TRACE("Get Button2: %p\n", hChld); + } + + if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR)) + { + INITCOMMONCONTROLSEX init; + static const WCHAR playW[] = {'P','l','a','y',0}; + + /* adding the other elements: play/stop button, menu button, status */ + hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32, + hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L); + TRACE("Get Button1: %p\n", hChld); + + init.dwSize = sizeof(init); + init.dwICC = ICC_BAR_CLASSES; + InitCommonControlsEx(&init); + + hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32, + hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L); + TRACE("Get status: %p\n", hChld); + } + + /* This sets the default window size */ + SendMessageW(hWnd, MCI_CLOSE, 0, 0); + + if (cs->lpCreateParams) + { + LPARAM lParam; + + /* MCI wnd class is prepared to be embedded as an MDI child window */ + if (cs->dwExStyle & WS_EX_MDICHILD) + { + MDICREATESTRUCTW *mdics = (MDICREATESTRUCTW *)cs->lpCreateParams; + lParam = mdics->lParam; + } + else + lParam = (LPARAM)cs->lpCreateParams; + + /* If it's our internal class pointer, file name is a unicode string */ + if (cs->lpszClass == mciWndClassW) + SendMessageW(hWnd, MCIWNDM_OPENW, 0, lParam); + else + { + /* Otherwise let's try to figure out what string format is used */ + HWND parent = cs->hwndParent; + if (!parent) parent = GetWindow(hWnd, GW_OWNER); + + SendMessageW(hWnd, IsWindowUnicode(parent) ? MCIWNDM_OPENW : MCIWNDM_OPENA, 0, lParam); + } + } + + return 0; +} + +static void MCIWND_ToggleState(MCIWndInfo *mwi) +{ + switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0)) + { + case MCI_MODE_NOT_READY: + case MCI_MODE_RECORD: + case MCI_MODE_SEEK: + case MCI_MODE_OPEN: + TRACE("Cannot do much...\n"); + break; + + case MCI_MODE_PAUSE: + SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0); + break; + + case MCI_MODE_PLAY: + SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0); + break; + + case MCI_MODE_STOP: + SendMessageW(mwi->hWnd, MCI_STOP, 0, 0); + break; + } +} + +static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break; + case CTL_MENU: + case CTL_TRACKBAR: + default: + FIXME("support for command %04x not implement yet\n", LOWORD(wParam)); + } + return 0L; +} + +static void MCIWND_notify_media(MCIWndInfo *mwi) +{ + if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW)) + { + if (!mwi->lpName) + { + static const WCHAR empty_str[1]; + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str); + } + else + { + if (mwi->dwStyle & MCIWNDF_NOTIFYANSI) + { + char *ansi_name; + int len; + + len = WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, NULL, 0, NULL, NULL); + ansi_name = HeapAlloc(GetProcessHeap(), 0, len); + WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, ansi_name, len, NULL, NULL); + + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)ansi_name); + + HeapFree(GetProcessHeap(), 0, ansi_name); + } + else + SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)mwi->lpName); + } + } +} + +static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd) +{ + MCI_GENERIC_PARMS mci_generic; + + mci_generic.dwCallback = 0; + mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic); + + if (mwi->lasterror) + return mwi->lasterror; + + MCIWND_notify_mode(mwi); + MCIWND_UpdateState(mwi); + return 0; +} + +static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap) +{ + MCI_GETDEVCAPS_PARMS mci_devcaps; + + mci_devcaps.dwItem = cap; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS, + MCI_GETDEVCAPS_ITEM, + (DWORD_PTR)&mci_devcaps); + if (mwi->lasterror) + return 0; + + return mci_devcaps.dwReturn; +} + +static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) +{ + MCIWndInfo *mwi; + + TRACE("%p %04x %08x %08lx\n", hWnd, wMsg, wParam, lParam); + + mwi = (MCIWndInfo*)GetWindowLongW(hWnd, 0); + if (!mwi && wMsg != WM_CREATE) + return DefWindowProcW(hWnd, wMsg, wParam, lParam); + + switch (wMsg) + { + case WM_CREATE: + MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam); + break; + + case WM_DESTROY: + if (mwi->uTimer) + KillTimer(hWnd, mwi->uTimer); + + if (mwi->mci) + SendMessageW(hWnd, MCI_CLOSE, 0, 0); + + HeapFree(GetProcessHeap(), 0, mwi); + + DestroyWindow(GetDlgItem(hWnd, CTL_MENU)); + DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP)); + DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR)); + break; + + case WM_PAINT: + { + MCI_DGV_UPDATE_PARMS mci_update; + PAINTSTRUCT ps; + + mci_update.hDC = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps); + + mciSendCommandW(mwi->mci, MCI_UPDATE, + MCI_DGV_UPDATE_HDC | MCI_DGV_UPDATE_PAINT, + (DWORD_PTR)&mci_update); + + if (!wParam) EndPaint(hWnd, &ps); + return 1; + } + + case WM_COMMAND: + return MCIWND_Command(mwi, wParam, lParam); + + case WM_NCACTIVATE: + if (mwi->uTimer) + { + KillTimer(hWnd, mwi->uTimer); + mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL); + } + break; + + case WM_TIMER: + MCIWND_UpdateState(mwi); + return 0; + + case WM_SIZE: + SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE); + SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE); + SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE); + + if (!(mwi->dwStyle & MCIWNDF_NOAUTOSIZEMOVIE)) + { + RECT rc; + + rc.left = rc.top = 0; + rc.right = LOWORD(lParam); + rc.bottom = HIWORD(lParam); + if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR)) + rc.bottom -= 32; /* subtract the height of the playbar */ + SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc); + } + MCIWND_notify_size(mwi); + break; + + case MM_MCINOTIFY: + MCIWND_notify_mode(mwi); + MCIWND_UpdateState(mwi); + return 0; + + case MCIWNDM_OPENA: + { + UNICODE_STRING nameW; + TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam)); + RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam); + lParam = (LPARAM)nameW.Buffer; + } + /* fall through */ + case MCIWNDM_OPENW: + { + RECT rc; + HCURSOR hCursor; + MCI_OPEN_PARMSW mci_open; + MCI_GETDEVCAPS_PARMS mci_devcaps; + WCHAR aliasW[64]; + WCHAR drv_name[MAX_PATH]; + static const WCHAR formatW[] = {'%','d',0}; + static const WCHAR mci32W[] = {'m','c','i','3','2',0}; + static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0}; + + TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam)); + + if (wParam == MCIWNDOPENF_NEW) + { + SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam); + goto end_of_mci_open; + } + + if (mwi->uTimer) + { + KillTimer(hWnd, mwi->uTimer); + mwi->uTimer = 0; + } + + hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT); + hCursor = SetCursor(hCursor); + + mci_open.lpstrElementName = (LPWSTR)lParam; + wsprintfW(aliasW, formatW, (int)hWnd + 1); + mci_open.lpstrAlias = aliasW; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN, + MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT, + (DWORD_PTR)&mci_open); + SetCursor(hCursor); + + if (mwi->lasterror && !(mwi->dwStyle & MCIWNDF_NOERRORDLG)) + { + /* FIXME: get the caption from resources */ + static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0}; + WCHAR error_str[MAXERRORLENGTH]; + + mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH); + MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK); + MCIWND_notify_error(mwi); + goto end_of_mci_open; + } + + mwi->mci = mci_open.wDeviceID; + mwi->alias = (int)hWnd + 1; + + mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR)); + strcpyW(mwi->lpName, (LPWSTR)lParam); + + MCIWND_UpdateState(mwi); + + mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS, + MCI_GETDEVCAPS_ITEM, + (DWORD_PTR)&mci_devcaps); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + goto end_of_mci_open; + } + + mwi->dev_type = mci_devcaps.dwReturn; + + drv_name[0] = 0; + SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name); + if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL, + drv_name, MAX_PATH, system_iniW)) + mwi->hdrv = OpenDriver(drv_name, NULL, 0); + + if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO) + { + MCI_DGV_WINDOW_PARMSW mci_window; + + mci_window.hWnd = hWnd; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW, + MCI_DGV_WINDOW_HWND, + (DWORD_PTR)&mci_window); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + goto end_of_mci_open; + } + } + + if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0) + { + mwi->size.cx = rc.right - rc.left; + mwi->size.cy = rc.bottom - rc.top; + + rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100); + rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100); + SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc); + } + else + { + GetClientRect(hWnd, &rc); + rc.bottom = rc.top; + } + + if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR)) + rc.bottom += 32; /* add the height of the playbar */ + AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE); + SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, + rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L); + SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1, + SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0)); + mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL); + + MCIWND_notify_media(mwi); + +end_of_mci_open: + if (wMsg == MCIWNDM_OPENA) + HeapFree(GetProcessHeap(), 0, (void *)lParam); + return mwi->lasterror; + } + + case MCIWNDM_GETDEVICEID: + TRACE("MCIWNDM_GETDEVICEID\n"); + return mwi->mci; + + case MCIWNDM_GETALIAS: + TRACE("MCIWNDM_GETALIAS\n"); + return mwi->alias; + + case MCIWNDM_GET_SOURCE: + { + MCI_DGV_RECT_PARMS mci_rect; + + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE, + MCI_DGV_WHERE_SOURCE, + (DWORD_PTR)&mci_rect); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + *(RECT *)lParam = mci_rect.rc; + TRACE("MCIWNDM_GET_SOURCE: %s\n", wine_dbgstr_rect(&mci_rect.rc)); + return 0; + } + + case MCIWNDM_GET_DEST: + { + MCI_DGV_RECT_PARMS mci_rect; + + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE, + MCI_DGV_WHERE_DESTINATION, + (DWORD_PTR)&mci_rect); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + *(RECT *)lParam = mci_rect.rc; + TRACE("MCIWNDM_GET_DEST: %s\n", wine_dbgstr_rect(&mci_rect.rc)); + return 0; + } + + case MCIWNDM_PUT_SOURCE: + { + MCI_DGV_PUT_PARMS mci_put; + + mci_put.rc = *(RECT *)lParam; + TRACE("MCIWNDM_PUT_SOURCE: %s\n", wine_dbgstr_rect(&mci_put.rc)); + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT, + MCI_DGV_PUT_SOURCE, + (DWORD_PTR)&mci_put); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + return 0; + } + + case MCIWNDM_PUT_DEST: + { + MCI_DGV_PUT_PARMS mci_put; + + mci_put.rc = *(RECT *)lParam; + TRACE("MCIWNDM_PUT_DEST: %s\n", wine_dbgstr_rect(&mci_put.rc)); + + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT, + MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT, + (DWORD_PTR)&mci_put); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + return 0; + } + + case MCIWNDM_GETLENGTH: + { + MCI_STATUS_PARMS mci_status; + + mci_status.dwItem = MCI_STATUS_LENGTH; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS, + MCI_STATUS_ITEM, + (DWORD_PTR)&mci_status); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return 0; + } + TRACE("MCIWNDM_GETLENGTH: %ld\n", mci_status.dwReturn); + return mci_status.dwReturn; + } + + case MCIWNDM_GETSTART: + { + MCI_STATUS_PARMS mci_status; + + mci_status.dwItem = MCI_STATUS_POSITION; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS, + MCI_STATUS_ITEM | MCI_STATUS_START, + (DWORD_PTR)&mci_status); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return 0; + } + TRACE("MCIWNDM_GETSTART: %ld\n", mci_status.dwReturn); + return mci_status.dwReturn; + } + + case MCIWNDM_GETEND: + { + LRESULT start, length; + + start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0); + length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0); + TRACE("MCIWNDM_GETEND: %ld\n", start + length); + return (start + length); + } + + case MCIWNDM_GETPOSITIONA: + case MCIWNDM_GETPOSITIONW: + { + MCI_STATUS_PARMS mci_status; + + TRACE("MCIWNDM_GETPOSITION\n"); + + /* get position string if requested */ + if (wParam && lParam) + { + if (wMsg == MCIWNDM_GETPOSITIONA) + { + char cmd[64]; + + wsprintfA(cmd, "status %d position", mwi->alias); + mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0); + } + else + { + + WCHAR cmdW[64]; + static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0}; + + wsprintfW(cmdW, formatW, mwi->alias); + mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0); + } + + if (mwi->lasterror) + return 0; + } + + mci_status.dwItem = MCI_STATUS_POSITION; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS, + MCI_STATUS_ITEM, + (DWORD_PTR)&mci_status); + if (mwi->lasterror) + return 0; + + return mci_status.dwReturn; + } + + case MCIWNDM_GETMODEA: + case MCIWNDM_GETMODEW: + { + MCI_STATUS_PARMS mci_status; + + TRACE("MCIWNDM_GETMODE\n"); + + if (!mwi->mci) + return MCI_MODE_NOT_READY; + + /* get mode string if requested */ + if (wParam && lParam) + { + if (wMsg == MCIWNDM_GETMODEA) + { + char cmd[64]; + + wsprintfA(cmd, "status %d mode", mwi->alias); + mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0); + } + else + { + + WCHAR cmdW[64]; + static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0}; + + wsprintfW(cmdW, formatW, mwi->alias); + mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0); + } + + if (mwi->lasterror) + return MCI_MODE_NOT_READY; + } + + mci_status.dwItem = MCI_STATUS_MODE; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS, + MCI_STATUS_ITEM, + (DWORD_PTR)&mci_status); + if (mwi->lasterror) + return MCI_MODE_NOT_READY; + + return mci_status.dwReturn; + } + + case MCIWNDM_PLAYFROM: + { + MCI_PLAY_PARMS mci_play; + + TRACE("MCIWNDM_PLAYFROM %08lx\n", lParam); + + mci_play.dwCallback = (DWORD_PTR)hWnd; + mci_play.dwFrom = lParam; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY, + MCI_FROM | MCI_NOTIFY, + (DWORD_PTR)&mci_play); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + + MCIWND_notify_mode(mwi); + MCIWND_UpdateState(mwi); + return 0; + } + + case MCIWNDM_PLAYTO: + { + MCI_PLAY_PARMS mci_play; + + TRACE("MCIWNDM_PLAYTO %08lx\n", lParam); + + mci_play.dwCallback = (DWORD_PTR)hWnd; + mci_play.dwTo = lParam; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY, + MCI_TO | MCI_NOTIFY, + (DWORD_PTR)&mci_play); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + + MCIWND_notify_mode(mwi); + MCIWND_UpdateState(mwi); + return 0; + } + + case MCIWNDM_PLAYREVERSE: + { + MCI_PLAY_PARMS mci_play; + DWORD flags = MCI_NOTIFY; + + TRACE("MCIWNDM_PLAYREVERSE %08lx\n", lParam); + + mci_play.dwCallback = (DWORD_PTR)hWnd; + mci_play.dwFrom = lParam; + switch (mwi->dev_type) + { + default: + case MCI_DEVTYPE_ANIMATION: + flags |= MCI_ANIM_PLAY_REVERSE; + break; + + case MCI_DEVTYPE_DIGITAL_VIDEO: + flags |= MCI_DGV_PLAY_REVERSE; + break; + +#ifdef MCI_VCR_PLAY_REVERSE + case MCI_DEVTYPE_VCR: + flags |= MCI_VCR_PLAY_REVERSE; + break; +#endif + + case MCI_DEVTYPE_VIDEODISC: + flags |= MCI_VD_PLAY_REVERSE; + break; + + } + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY, + flags, (DWORD_PTR)&mci_play); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + + MCIWND_notify_mode(mwi); + MCIWND_UpdateState(mwi); + return 0; + } + + case MCIWNDM_GETERRORA: + mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam); + TRACE("MCIWNDM_GETERRORA: %s\n", debugstr_an((LPSTR)lParam, wParam)); + return mwi->lasterror; + + case MCIWNDM_GETERRORW: + mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam); + TRACE("MCIWNDM_GETERRORW: %s\n", debugstr_wn((LPWSTR)lParam, wParam)); + return mwi->lasterror; + + case MCIWNDM_SETOWNER: + TRACE("MCIWNDM_SETOWNER %p\n", (HWND)wParam); + mwi->hwndOwner = (HWND)wParam; + return 0; + + case MCIWNDM_SENDSTRINGA: + { + UNICODE_STRING stringW; + + TRACE("MCIWNDM_SENDSTRINGA %s\n", debugstr_a((LPCSTR)lParam)); + + RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam); + lParam = (LPARAM)stringW.Buffer; + } + /* fall through */ + case MCIWNDM_SENDSTRINGW: + { + WCHAR *cmdW, *p; + + TRACE("MCIWNDM_SENDSTRINGW %s\n", debugstr_w((LPCWSTR)lParam)); + + p = strchrW((LPCWSTR)lParam, ' '); + if (p) + { + static const WCHAR formatW[] = {'%','d',' ',0}; + int len, pos; + + pos = p - (WCHAR *)lParam + 1; + len = lstrlenW((LPCWSTR)lParam) + 64; + + cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR)); + wsprintfW(cmdW + pos, formatW, mwi->alias); + strcatW(cmdW, (WCHAR *)lParam + pos); + } + else + cmdW = (LPWSTR)lParam; + + mwi->lasterror = mciSendStringW(cmdW, mwi->return_string, + sizeof(mwi->return_string)/sizeof(mwi->return_string[0]), + 0); + if (mwi->lasterror) + MCIWND_notify_error(mwi); + + if (cmdW != (LPWSTR)lParam) + HeapFree(GetProcessHeap(), 0, cmdW); + + if (wMsg == MCIWNDM_SENDSTRINGA) + HeapFree(GetProcessHeap(), 0, (void *)lParam); + + MCIWND_UpdateState(mwi); + return mwi->lasterror; + } + + case MCIWNDM_RETURNSTRINGA: + WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL); + TRACE("MCIWNDM_RETURNTRINGA %s\n", debugstr_an((LPSTR)lParam, wParam)); + return mwi->lasterror; + + case MCIWNDM_RETURNSTRINGW: + strncpyW((LPWSTR)lParam, mwi->return_string, wParam); + TRACE("MCIWNDM_RETURNTRINGW %s\n", debugstr_wn((LPWSTR)lParam, wParam)); + return mwi->lasterror; + + case MCIWNDM_SETTIMERS: + TRACE("MCIWNDM_SETTIMERS active %d ms, inactive %d ms\n", (int)wParam, (int)lParam); + mwi->active_timer = (WORD)wParam; + mwi->inactive_timer = (WORD)lParam; + return 0; + + case MCIWNDM_SETACTIVETIMER: + TRACE("MCIWNDM_SETACTIVETIMER %d ms\n", (int)wParam); + mwi->active_timer = (WORD)wParam; + return 0; + + case MCIWNDM_SETINACTIVETIMER: + TRACE("MCIWNDM_SETINACTIVETIMER %d ms\n", (int)wParam); + mwi->inactive_timer = (WORD)wParam; + return 0; + + case MCIWNDM_GETACTIVETIMER: + TRACE("MCIWNDM_GETACTIVETIMER: %d ms\n", mwi->active_timer); + return mwi->active_timer; + + case MCIWNDM_GETINACTIVETIMER: + TRACE("MCIWNDM_GETINACTIVETIMER: %d ms\n", mwi->inactive_timer); + return mwi->inactive_timer; + + case MCIWNDM_CHANGESTYLES: + TRACE("MCIWNDM_CHANGESTYLES mask %08x, set %08lx\n", wParam, lParam); + /* FIXME: update the visual window state as well: + * add/remove trackbar, autosize, etc. + */ + mwi->dwStyle &= ~wParam; + mwi->dwStyle |= lParam & wParam; + return 0; + + case MCIWNDM_GETSTYLES: + TRACE("MCIWNDM_GETSTYLES: %08lx\n", mwi->dwStyle & 0xffff); + return mwi->dwStyle & 0xffff; + + case MCIWNDM_GETDEVICEA: + { + MCI_SYSINFO_PARMSA mci_sysinfo; + + mci_sysinfo.lpstrReturn = (LPSTR)lParam; + mci_sysinfo.dwRetSize = wParam; + mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO, + MCI_SYSINFO_INSTALLNAME, + (DWORD_PTR)&mci_sysinfo); + TRACE("MCIWNDM_GETDEVICEA: %s\n", debugstr_an((LPSTR)lParam, wParam)); + return 0; + } + + case MCIWNDM_GETDEVICEW: + { + MCI_SYSINFO_PARMSW mci_sysinfo; + + mci_sysinfo.lpstrReturn = (LPWSTR)lParam; + mci_sysinfo.dwRetSize = wParam; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO, + MCI_SYSINFO_INSTALLNAME, + (DWORD_PTR)&mci_sysinfo); + TRACE("MCIWNDM_GETDEVICEW: %s\n", debugstr_wn((LPWSTR)lParam, wParam)); + return 0; + } + + case MCIWNDM_VALIDATEMEDIA: + TRACE("MCIWNDM_VALIDATEMEDIA\n"); + if (mwi->mci) + { + SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0); + SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0); + } + return 0; + + case MCIWNDM_GETFILENAMEA: + TRACE("MCIWNDM_GETFILENAMEA: %s\n", debugstr_w(mwi->lpName)); + if (mwi->lpName) + WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL); + return 0; + + case MCIWNDM_GETFILENAMEW: + TRACE("MCIWNDM_GETFILENAMEW: %s\n", debugstr_w(mwi->lpName)); + if (mwi->lpName) + strncpyW((LPWSTR)lParam, mwi->lpName, wParam); + return 0; + + case MCIWNDM_GETTIMEFORMATA: + case MCIWNDM_GETTIMEFORMATW: + { + MCI_STATUS_PARMS mci_status; + + TRACE("MCIWNDM_GETTIMEFORMAT %08x %08lx\n", wParam, lParam); + + /* get format string if requested */ + if (wParam && lParam) + { + if (wMsg == MCIWNDM_GETTIMEFORMATA) + { + char cmd[64]; + + wsprintfA(cmd, "status %d time format", mwi->alias); + mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0); + if (mwi->lasterror) + return 0; + } + else + { + WCHAR cmdW[64]; + static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0}; + + wsprintfW(cmdW, formatW, mwi->alias); + mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0); + if (mwi->lasterror) + return 0; + } + } + + mci_status.dwItem = MCI_STATUS_TIME_FORMAT ; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS, + MCI_STATUS_ITEM, + (DWORD_PTR)&mci_status); + if (mwi->lasterror) + return 0; + + return mci_status.dwReturn; + } + + case MCIWNDM_SETTIMEFORMATA: + { + UNICODE_STRING stringW; + + TRACE("MCIWNDM_SETTIMEFORMATA %s\n", debugstr_a((LPSTR)lParam)); + + RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam); + lParam = (LPARAM)stringW.Buffer; + } + /* fall through */ + case MCIWNDM_SETTIMEFORMATW: + { + static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0}; + WCHAR *cmdW; + + TRACE("MCIWNDM_SETTIMEFORMATW %s\n", debugstr_w((LPWSTR)lParam)); + + if (mwi->mci) + { + cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR)); + wsprintfW(cmdW, formatW, mwi->alias); + strcatW(cmdW, (WCHAR *)lParam); + + mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0); + + /* fix the range tracking according to the new time format */ + if (!mwi->lasterror) + SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1, + SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0)); + } + + if (wMsg == MCIWNDM_SETTIMEFORMATA) + HeapFree(GetProcessHeap(), 0, (void *)lParam); + + return 0; + } + + case MCIWNDM_CAN_PLAY: + TRACE("MCIWNDM_CAN_PLAY\n"); + if (mwi->mci) + return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY); + return 0; + + case MCIWNDM_CAN_RECORD: + TRACE("MCIWNDM_CAN_RECORD\n"); + if (mwi->mci) + return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD); + return 0; + + case MCIWNDM_CAN_SAVE: + TRACE("MCIWNDM_CAN_SAVE\n"); + if (mwi->mci) + return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE); + return 0; + + case MCIWNDM_CAN_EJECT: + TRACE("MCIWNDM_CAN_EJECT\n"); + if (mwi->mci) + return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT); + return 0; + + case MCIWNDM_CAN_WINDOW: + TRACE("MCIWNDM_CAN_WINDOW\n"); + switch (mwi->dev_type) + { + case MCI_DEVTYPE_ANIMATION: + case MCI_DEVTYPE_DIGITAL_VIDEO: + case MCI_DEVTYPE_OVERLAY: + return 1; + } + return 0; + + case MCIWNDM_CAN_CONFIG: + TRACE("MCIWNDM_CAN_CONFIG\n"); + if (mwi->hdrv) + return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0); + return 0; + + case MCIWNDM_SETZOOM: + TRACE("MCIWNDM_SETZOOM %ld\n", lParam); + mwi->zoom = lParam; + + if (mwi->mci && !(mwi->dwStyle & MCIWNDF_NOAUTOSIZEWINDOW)) + { + RECT rc; + + rc.left = rc.top = 0; + rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100); + rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100); + + if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR)) + rc.bottom += 32; /* add the height of the playbar */ + AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE); + SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top, + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + } + return 0; + + case MCIWNDM_GETZOOM: + TRACE("MCIWNDM_GETZOOM: %d\n", mwi->zoom); + return mwi->zoom; + + case MCIWNDM_EJECT: + { + MCI_SET_PARMS mci_set; + + TRACE("MCIWNDM_EJECT\n"); + + mci_set.dwCallback = (DWORD_PTR)hWnd; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET, + MCI_SET_DOOR_OPEN | MCI_NOTIFY, + (DWORD_PTR)&mci_set); + MCIWND_notify_mode(mwi); + MCIWND_UpdateState(mwi); + return mwi->lasterror; + } + + case MCIWNDM_SETVOLUME: + case MCIWNDM_GETVOLUME: + case MCIWNDM_SETSPEED: + case MCIWNDM_GETSPEED: + case MCIWNDM_SETREPEAT: + case MCIWNDM_GETREPEAT: + case MCIWNDM_REALIZE: + case MCIWNDM_GETPALETTE: + case MCIWNDM_SETPALETTE: + case MCIWNDM_NEWA: + case MCIWNDM_NEWW: + case MCIWNDM_PALETTEKICK: + case MCIWNDM_OPENINTERFACE: + FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER); + return 0; + + case MCI_PLAY: + { + LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0); + return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end); + } + + case MCI_SEEK: + { + MCI_SEEK_PARMS mci_seek; + + switch (lParam) + { + case MCIWND_START: + lParam = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0); + break; + + case MCIWND_END: + lParam = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0); + break; + } + + mci_seek.dwTo = lParam; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SEEK, + MCI_TO, (DWORD_PTR)&mci_seek); + if (mwi->lasterror) + { + MCIWND_notify_error(mwi); + return mwi->lasterror; + } + /* update window to reflect the state */ + InvalidateRect(hWnd, NULL, TRUE); + return 0; + } + + case MCI_CLOSE: + { + RECT rc; + MCI_GENERIC_PARMS mci_generic; + + if (mwi->hdrv) + { + CloseDriver(mwi->hdrv, 0, 0); + mwi->hdrv = 0; + } + + if (mwi->mci) + { + mci_generic.dwCallback = 0; + mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE, + 0, (DWORD_PTR)&mci_generic); + mwi->mci = 0; + } + + mwi->mode = MCI_MODE_NOT_READY; + mwi->position = -1; + + if (mwi->lpName) + { + HeapFree(GetProcessHeap(), 0, mwi->lpName); + mwi->lpName = NULL; + } + MCIWND_UpdateState(mwi); + + GetClientRect(hWnd, &rc); + rc.bottom = rc.top; + if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR)) + rc.bottom += 32; /* add the height of the playbar */ + AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE); + SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, + rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + + MCIWND_notify_media(mwi); + return 0; + } + + case MCI_PAUSE: + case MCI_STEP: + case MCI_STOP: + case MCI_RESUME: + mci_generic_command(mwi, wMsg); + if (wMsg == MCI_STEP && !mwi->lasterror) + { + /* update window to reflect the state */ + InvalidateRect(hWnd, NULL, TRUE); + } + return mwi->lasterror; + + case MCI_CONFIGURE: + if (mwi->hdrv) + SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0); + return 0; + + case MCI_BREAK: + case MCI_CAPTURE: + case MCI_COPY: + case MCI_CUE: + case MCI_CUT: + case MCI_DELETE: + case MCI_ESCAPE: + case MCI_FREEZE: + case MCI_GETDEVCAPS: + /*case MCI_INDEX:*/ + case MCI_INFO: + case MCI_LIST: + case MCI_LOAD: + /*case MCI_MARK:*/ + case MCI_MONITOR: + case MCI_OPEN: + case MCI_PASTE: + case MCI_PUT: + case MCI_QUALITY: + case MCI_REALIZE: + case MCI_RECORD: + case MCI_RESERVE: + case MCI_RESTORE: + case MCI_SAVE: + case MCI_SET: + case MCI_SETAUDIO: + /*case MCI_SETTIMECODE:*/ + /*case MCI_SETTUNER:*/ + case MCI_SETVIDEO: + case MCI_SIGNAL: + case MCI_SPIN: + case MCI_STATUS: + case MCI_SYSINFO: + case MCI_UNDO: + case MCI_UNFREEZE: + case MCI_UPDATE: + case MCI_WHERE: + case MCI_WINDOW: + FIXME("support for MCI_ command %04x not implemented\n", wMsg); + return 0; + } + + if (wMsg >= WM_USER) + { + FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER); + return 0; + } + + if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD) + return DefMDIChildProcW(hWnd, wMsg, wParam, lParam); + + return DefWindowProcW(hWnd, wMsg, wParam, lParam); +} diff --git a/reactos/lib/msvideo/msvfw32.rc b/reactos/lib/msvideo/msvfw32.rc new file mode 100644 index 00000000000..3a0ff963fb5 --- /dev/null +++ b/reactos/lib/msvideo/msvfw32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "MSvideo support\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "msvfw32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "msvfw32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/lib/msvideo/msvfw32.spec b/reactos/lib/msvideo/msvfw32.spec new file mode 100644 index 00000000000..9590f91bf3a --- /dev/null +++ b/reactos/lib/msvideo/msvfw32.spec @@ -0,0 +1,51 @@ +# Yes, ICCompress,ICDecompress,MCIWnd* and ICDraw* are cdecl (VFWAPIV). +# The rest is stdcall (VFWAPI) however. -Marcus Meissner, 990124 + +2 stdcall VideoForWindowsVersion() + +@ stdcall DrawDibBegin(long long long long ptr long long long) +@ stub DrawDibChangePalette +@ stdcall DrawDibClose(long) +@ stdcall DrawDibDraw(long long long long long long ptr ptr long long long long long) +@ stdcall DrawDibEnd(long) +@ stub DrawDibGetBuffer +@ stdcall DrawDibGetPalette(long) +@ stdcall DrawDibOpen() +@ stdcall DrawDibProfileDisplay(ptr) +@ stdcall DrawDibRealize(long long long) +@ stdcall DrawDibSetPalette(long long) +@ stdcall DrawDibStart(long long) +@ stdcall DrawDibStop(long) +@ stub DrawDibTime +@ stub GetOpenFileNamePreview +@ stdcall GetOpenFileNamePreviewA(ptr) +@ stdcall GetOpenFileNamePreviewW(ptr) +@ stdcall GetSaveFileNamePreviewA(ptr) +@ stdcall GetSaveFileNamePreviewW(ptr) +@ stdcall ICClose(long) +@ cdecl ICCompress(long long ptr ptr ptr ptr ptr ptr long long long ptr ptr) +@ stdcall ICCompressorChoose(long long ptr ptr ptr ptr) +@ stdcall ICCompressorFree(ptr) +@ cdecl ICDecompress(long long ptr ptr ptr ptr) +@ cdecl ICDraw(long long ptr ptr long long) +@ cdecl ICDrawBegin(long long long long long long long long long ptr long long long long long long) +@ stdcall ICGetDisplayFormat(long ptr ptr long long long) +@ stdcall ICGetInfo(long ptr long) +@ stdcall ICImageCompress(long long ptr ptr ptr long ptr) +@ stdcall ICImageDecompress(long long ptr ptr ptr) +@ stdcall ICInfo(long long ptr) +@ stdcall ICInstall(long long ptr str long) +@ stdcall ICLocate(long long ptr ptr long) +@ stub ICMThunk +@ stdcall ICOpen(long long long) +@ stdcall ICOpenFunction(long long long ptr) +@ stdcall ICRemove(long long long) +@ stdcall ICSendMessage(long long long long) +@ stub ICSeqCompressFrame +@ stub ICSeqCompressFrameEnd +@ stub ICSeqCompressFrameStart +@ cdecl MCIWndCreate (long long long str) MCIWndCreateA +@ cdecl MCIWndCreateA (long long long str) +@ cdecl MCIWndCreateW (long long long wstr) +@ cdecl MCIWndRegisterClass() +@ stub StretchDIB diff --git a/reactos/lib/msvideo/msvfw32.spec.def b/reactos/lib/msvideo/msvfw32.spec.def new file mode 100644 index 00000000000..39fd23f5e5d --- /dev/null +++ b/reactos/lib/msvideo/msvfw32.spec.def @@ -0,0 +1,43 @@ +; File generated automatically from msvfw32.spec; do not edit! + +LIBRARY msvfw32.dll + +EXPORTS + VideoForWindowsVersion@0 @2 + DrawDibBegin@32 @3 + DrawDibClose@4 @5 + DrawDibDraw@52 @6 + DrawDibEnd@4 @7 + DrawDibGetPalette@4 @9 + DrawDibOpen@0 @10 + DrawDibProfileDisplay@4 @11 + DrawDibRealize@12 @12 + DrawDibSetPalette@8 @13 + DrawDibStart@8 @14 + DrawDibStop@4 @15 + GetOpenFileNamePreviewA@4 @18 + GetOpenFileNamePreviewW@4 @19 + GetSaveFileNamePreviewA@4 @20 + GetSaveFileNamePreviewW@4 @21 + ICClose@4 @22 + ICCompress @23 + ICCompressorChoose@24 @24 + ICCompressorFree@4 @25 + ICDecompress @26 + ICDraw @27 + ICDrawBegin @28 + ICGetDisplayFormat@24 @29 + ICGetInfo@12 @30 + ICImageCompress@28 @31 + ICImageDecompress@20 @32 + ICInfo@12 @33 + ICInstall@20 @34 + ICLocate@20 @35 + ICOpen@12 @37 + ICOpenFunction@16 @38 + ICRemove@12 @39 + ICSendMessage@16 @40 + MCIWndCreate=MCIWndCreateA @44 + MCIWndCreateA @45 + MCIWndCreateW @46 + MCIWndRegisterClass @47 diff --git a/reactos/lib/msvideo/msvideo.spec b/reactos/lib/msvideo/msvideo.spec new file mode 100644 index 00000000000..a6f9a876f20 --- /dev/null +++ b/reactos/lib/msvideo/msvideo.spec @@ -0,0 +1,68 @@ +2 pascal VideoForWindowsVersion() VideoForWindowsVersion +20 stub VIDEOGETNUMDEVS +21 stub VIDEOGETERRORTEXT +22 pascal VideoCapDriverDescAndVer(word ptr word ptr word) VideoCapDriverDescAndVer16 +28 stub VIDEOOPEN +29 stub VIDEOCLOSE +30 stub VIDEODIALOG +31 stub VIDEOFRAME +32 stub VIDEOCONFIGURE +33 stub VIDEOCONFIGURESTORAGE +34 stub VIDEOGETCHANNELCAPS +35 stub VIDEOUPDATE +40 stub VIDEOSTREAMADDBUFFER +41 stub VIDEOSTREAMFINI +42 stub VIDEOSTREAMGETERROR +43 stub VIDEOSTREAMGETPOSITION +44 stub VIDEOSTREAMINIT +46 stub VIDEOSTREAMPREPAREHEADER +47 stub VIDEOSTREAMRESET +49 stub VIDEOSTREAMSTART +50 stub VIDEOSTREAMSTOP +51 stub VIDEOSTREAMUNPREPAREHEADER +52 stub VIDEOSTREAMALLOCHDRANDBUFFER +53 stub VIDEOSTREAMFREEHDRANDBUFFER +60 stub VIDEOMESSAGE +102 pascal -ret16 DrawDibOpen() DrawDibOpen16 +103 pascal -ret16 DrawDibClose(word) DrawDibClose16 +104 pascal -ret16 DrawDibBegin(word word s_word s_word ptr s_word s_word word) DrawDibBegin16 +105 pascal -ret16 DrawDibEnd(word) DrawDibEnd16 +106 pascal -ret16 DrawDibDraw(word word s_word s_word s_word s_word ptr ptr s_word s_word s_word s_word word) DrawDibDraw16 +108 pascal -ret16 DrawDibGetPalette(word) DrawDibGetPalette16 +110 pascal -ret16 DrawDibSetPalette(word word) DrawDibSetPalette16 +111 stub DRAWDIBCHANGEPALETTE +112 pascal -ret16 DrawDibRealize(word word word) DrawDibRealize16 +113 stub DRAWDIBTIME +114 stub DRAWDIBPROFILEDISPLAY +115 stub STRETCHDIB +118 pascal -ret16 DrawDibStart(word long) DrawDibStart16 +119 pascal -ret16 DrawDibStop(word) DrawDibStop16 +120 stub DRAWDIBGETBUFFER +200 pascal -ret16 ICInfo(long long segptr) ICInfo16 +201 stub ICINSTALL +202 stub ICREMOVE +203 pascal -ret16 ICOpen(long long word) ICOpen16 +204 pascal ICClose(word) ICClose16 +205 pascal ICSendMessage(word word long long) ICSendMessage16 +206 pascal -ret16 ICOpenFunction(long long word segptr) ICOpenFunction16 +207 varargs _ICMessage(word word word) ICMessage16 +212 pascal ICGetInfo(word segptr long) ICGetInfo16 +213 pascal -ret16 ICLocate(long long ptr ptr word) ICLocate16 +224 cdecl _ICCompress(word long segptr segptr segptr segptr segptr segptr long long long segptr segptr) ICCompress16 +230 cdecl _ICDecompress(word long segptr segptr segptr segptr) ICDecompress16 +232 cdecl _ICDrawBegin(word long word word word s_word s_word s_word s_word segptr s_word s_word s_word s_word long long) ICDrawBegin16 +234 cdecl _ICDraw(word long segptr segptr long long) ICDraw16 +239 pascal -ret16 ICGetDisplayFormat(word ptr ptr s_word s_word s_word) ICGetDisplayFormat16 +240 stub ICIMAGECOMPRESS +241 stub ICIMAGEDECOMPRESS +242 stub ICCOMPRESSORCHOOSE +243 stub ICCOMPRESSORFREE +244 stub ICSEQCOMPRESSFRAMESTART +245 stub ICSEQCOMPRESSFRAMEEND +246 stub ICSEQCOMPRESSFRAME +250 stub _MCIWNDCREATE +251 stub _MCIWNDREGISTERCLASS +252 stub GETOPENFILENAMEPREVIEW +253 stub GETSAVEFILENAMEPREVIEW + +300 pascal DllEntryPoint(long word word word long word) VIDEO_LibMain diff --git a/reactos/lib/msvideo/msvideo16.c b/reactos/lib/msvideo/msvideo16.c new file mode 100644 index 00000000000..2d5596e9b9f --- /dev/null +++ b/reactos/lib/msvideo/msvideo16.c @@ -0,0 +1,910 @@ +/* + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define COM_NO_WINDOWS_H +#include +#include + +#include "msvideo_private.h" +#include "winver.h" +#include "winnls.h" +#include "winreg.h" +#include "vfw16.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msvideo); + +/* Drivers32 settings */ +#define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32" + +/*********************************************************************** + * 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); +} + +/************************************************************************* + * DrawDibStart [MSVIDEO.118] + */ +BOOL16 VFWAPI DrawDibStart16(HDRAWDIB16 hdd, DWORD rate) +{ + return DrawDibStart(HDRAWDIB_32(hdd), rate); +} + +/************************************************************************* + * DrawDibStop [MSVIDEO.119] + */ +BOOL16 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)); +} + +/*********************************************************************** + * ICClose [MSVIDEO.204] + */ +LRESULT WINAPI ICClose16(HIC16 hic) +{ + return ICClose(HIC_32(hic)); +} + +/*********************************************************************** + * _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%08lx, %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%08lx,%p,%ld)\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%08lx,%ld,%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%08lx,%ld,%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%08lx,%ld,0x%08lx,0x%08lx,0x%08lx,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\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%08lx,0x%08lx,%p,%p,%ld,%ld)\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 = (ICINFO16*)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(HIC hic, HDRVR hdrv, UINT msg, DWORD lp1, DWORD lp2) +{ + WINE_HIC* whic; + LRESULT ret = 0; + WORD args[8]; + + whic = MSVIDEO_GetHicPtr(hic); + if (whic) + { + switch (msg) + { + case DRV_OPEN: + lp2 = (DWORD)MapLS((void*)lp2); + break; + } + args[7] = HIWORD(hic); + args[6] = LOWORD(hic); + args[5] = HDRVR_16(whic->hdrv); + args[4] = msg; + args[3] = HIWORD(lp1); + args[2] = LOWORD(lp1); + args[1] = HIWORD(lp2); + args[0] = LOWORD(lp2); + WOWCallback16Ex( (DWORD)whic->driverproc16, WCB16_PASCAL, sizeof(args), args, &ret ); + + switch (msg) + { + case DRV_OPEN: + UnMapLS(lp2); + break; + } + } + else ret = ICERR_BADHANDLE; + return ret; +} + +/*********************************************************************** + * ICOpenFunction [MSVIDEO.206] + */ +HIC16 VFWAPI ICOpenFunction16(DWORD fccType, DWORD fccHandler, UINT16 wMode, FARPROC16 lpfnHandler) +{ + HIC hic32; + + hic32 = MSVIDEO_OpenFunction(fccType, fccHandler, wMode, + (DRIVERPROC)IC_Callback3216, (DWORD)lpfnHandler); + return HIC_16(hic32); +} + +/*********************************************************************** + * ICSendMessage [MSVIDEO.205] + */ +LRESULT VFWAPI ICSendMessage16(HIC16 hic, UINT16 msg, DWORD lParam1, DWORD lParam2) +{ + LRESULT ret = ICERR_BADHANDLE; + WINE_HIC* whic; + + whic = MSVIDEO_GetHicPtr(HIC_32(hic)); + if (whic) + { + /* we've got a 16 bit driver proc... call it directly */ + if (whic->driverproc16) + { + WORD args[8]; + + /* 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] = HDRVR_16(whic->hdrv); + args[4] = msg; + args[3] = HIWORD(lParam1); + args[2] = LOWORD(lParam1); + args[1] = HIWORD(lParam2); + args[0] = LOWORD(lParam2); + WOWCallback16Ex( (DWORD)whic->driverproc16, WCB16_PASCAL, sizeof(args), args, &ret ); + } + else + { + /* map the message for a 32 bit infrastructure, and pass it along */ + void* data16 = MSVIDEO_MapMsg16To32(msg, &lParam1, &lParam2); + + ret = MSVIDEO_SendMessage(whic, msg, lParam1, lParam2); + if (data16) + MSVIDEO_UnmapMsg16To32(msg, data16, &lParam1, &lParam2); + } + } + return ret; +} + +/*********************************************************************** + * VideoCapDriverDescAndVer [MSVIDEO.22] + */ +DWORD WINAPI VideoCapDriverDescAndVer16(WORD nr, LPSTR buf1, WORD buf1len, + LPSTR buf2, WORD buf2len) +{ + 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, 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 (nr || !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)) + { + char vbuf[200]; + /* Yes, two space behind : */ + /* FIXME: test for buflen */ + sprintf(vbuf, "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, vbuf); + strncpy(buf2, vbuf, buf2len); + } + else + { + TRACE("GetFileVersionInfoA failed for %s.\n", fn); + strncpy(buf2, fn, buf2len); /* msvideo.dll appears to copy fn*/ + } + /* FIXME: language problem? */ + if (VerQueryValueA( infobuf, + "\\StringFileInfo\\040904E4\\FileDescription", + &subblock, + &subblocklen + )) + { + TRACE("VQA returned %s\n", (LPCSTR)subblock); + strncpy(buf1, subblock, buf1len); + } + else + { + TRACE("VQA did not return on query \\StringFileInfo\\040904E4\\FileDescription?\n"); + strncpy(buf1, fn, buf1len); /* msvideo.dll appears to copy fn*/ + } + HeapFree(GetProcessHeap(), 0, infobuf); + return 0; +} + +/****************************************************************** + * IC_CallTo16 + * + * + */ +static LRESULT CALLBACK IC_CallTo16(HDRVR hdrv, HIC hic, UINT msg, LPARAM lp1, LPARAM lp2) +{ +#if 0 + WINE_HIC* whic = IC_GetPtr(hic); + LRESULT ret = 0; + + + if (whic->driverproc) + { + ret = whic->driverproc(hic, whic->hdrv, msg, lParam1, lParam2); + } + else + { + ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2); + } +#else + FIXME("No 32=>16 conversion yet\n"); +#endif + return 0; +} + +/************************************************************************** + * DllEntryPoint (MSVIDEO.300) + * + * 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: + /* hook in our 16 bit management functions */ + pFnCallTo16 = IC_CallTo16; + break; + case DLL_PROCESS_DETACH: + /* remove our 16 bit management functions */ + pFnCallTo16 = NULL; + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} diff --git a/reactos/lib/msvideo/msvideo_main.c b/reactos/lib/msvideo/msvideo_main.c new file mode 100644 index 00000000000..0d918edb32c --- /dev/null +++ b/reactos/lib/msvideo/msvideo_main.c @@ -0,0 +1,1184 @@ +/* + * Copyright 1998 Marcus Meissner + * Copyright 2000 Bradley Baetz + * Copyright 2003 Michael Günnewig + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: This all assumes 32 bit codecs + * Win95 appears to prefer 32 bit codecs, even from 16 bit code. + * There is the ICOpenFunction16 to worry about still, though. + * + * TODO + * - no thread safety + */ + +#include +#include + +#include "msvideo_private.h" +#include "winnls.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" + +#include "windowsx.h" + +#include "wine/debug.h" + +/* Drivers32 settings */ +#define HKLM_DRIVERS32 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32" + +WINE_DEFAULT_DEBUG_CHANNEL(msvideo); + +static inline const char *wine_dbgstr_fcc( DWORD fcc ) +{ + return wine_dbg_sprintf("%c%c%c%c", + LOBYTE(LOWORD(fcc)), HIBYTE(LOWORD(fcc)), + LOBYTE(HIWORD(fcc)), HIBYTE(HIWORD(fcc))); +} + +LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM) = NULL; + +static WINE_HIC* MSVIDEO_FirstHic /* = NULL */; + +typedef struct _reg_driver reg_driver; +struct _reg_driver +{ + DWORD fccType; + DWORD fccHandler; + DRIVERPROC proc; + LPWSTR name; + reg_driver* next; +}; + +static reg_driver* reg_driver_list = NULL; + +/* This one is a macro such that it works for both ASCII and Unicode */ +#define fourcc_to_string(str, fcc) do { \ + (str)[0] = LOBYTE(LOWORD(fcc)); \ + (str)[1] = HIBYTE(LOWORD(fcc)); \ + (str)[2] = LOBYTE(HIWORD(fcc)); \ + (str)[3] = HIBYTE(HIWORD(fcc)); \ + } while(0) + +HMODULE MSVFW32_hModule; + +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) +{ + TRACE("%p,%lx,%p\n", hinst, reason, reserved); + + switch(reason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinst); + MSVFW32_hModule = (HMODULE)hinst; + break; + } + return TRUE; +} + +static int compare_fourcc(DWORD fcc1, DWORD fcc2) +{ + char fcc_str1[4]; + char fcc_str2[4]; + fourcc_to_string(fcc_str1, fcc1); + fourcc_to_string(fcc_str2, fcc2); + return strncasecmp(fcc_str1, fcc_str2, 4); +} + +typedef BOOL (*enum_handler_t)(const char*, int, void*); + +static BOOL enum_drivers(DWORD fccType, enum_handler_t handler, void* param) +{ + CHAR buf[2048], fccTypeStr[5], *s; + DWORD i, cnt = 0, bufLen, lRet; + BOOL result = FALSE; + FILETIME lastWrite; + HKEY hKey; + + fourcc_to_string(fccTypeStr, fccType); + fccTypeStr[4] = '.'; + + /* first, go through the registry entries */ + 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, fccTypeStr, 5) || buf[9] != '=') continue; + if ((result = handler(buf, i, param))) break; + } + RegCloseKey( hKey ); + } + if (result) return result; + + /* if that didn't work, go through the values in system.ini */ + if (GetPrivateProfileSectionA("drivers32", buf, sizeof(buf), "system.ini")) + { + for (s = buf; *s; cnt++, s += strlen(s) + 1) + { + if (strncasecmp(s, fccTypeStr, 5) || s[9] != '=') continue; + if ((result = handler(s, cnt, param))) break; + } + } + + return result; +} + +/****************************************************************** + * MSVIDEO_GetHicPtr + * + * + */ +WINE_HIC* MSVIDEO_GetHicPtr(HIC hic) +{ + WINE_HIC* whic; + + for (whic = MSVIDEO_FirstHic; whic && whic->hic != hic; whic = whic->next); + return whic; +} + +/*********************************************************************** + * VideoForWindowsVersion [MSVFW32.2] + * VideoForWindowsVersion [MSVIDEO.2] + * Returns the version in major.minor form. + * In Windows95 this returns 0x040003b6 (4.950) + */ +DWORD WINAPI VideoForWindowsVersion(void) +{ + return 0x040003B6; /* 4.950 */ +} + +static BOOL ICInfo_enum_handler(const char *drv, int nr, void *param) +{ + ICINFO *lpicinfo = (ICINFO *)param; + DWORD fccHandler = mmioStringToFOURCCA(drv + 5, 0); + + /* exact match of fccHandler or nth driver found */ + if ((lpicinfo->fccHandler != nr) && (lpicinfo->fccHandler != fccHandler)) + return FALSE; + + lpicinfo->fccType = mmioStringToFOURCCA(drv, 0); + lpicinfo->fccHandler = fccHandler; + lpicinfo->dwFlags = 0; + lpicinfo->dwVersion = 0; + lpicinfo->dwVersionICM = 0x104; + lpicinfo->szName[0] = 0; + lpicinfo->szDescription[0] = 0; + MultiByteToWideChar(CP_ACP, 0, drv + 10, -1, lpicinfo->szDriver, + sizeof(lpicinfo->szDriver)/sizeof(WCHAR)); + + return TRUE; +} + +/*********************************************************************** + * ICInfo [MSVFW32.@] + * Get information about an installable compressor. Return TRUE if there + * is one. + * + * PARAMS + * fccType [I] type of compressor (e.g. 'vidc') + * fccHandler [I] real fcc for handler or th compressor + * lpicinfo [O] information about compressor + */ +BOOL VFWAPI ICInfo( DWORD fccType, DWORD fccHandler, ICINFO *lpicinfo) +{ + TRACE("(%s,%s/%08lx,%p)\n", + wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), fccHandler, lpicinfo); + + lpicinfo->fccHandler = fccHandler; + return enum_drivers(fccType, ICInfo_enum_handler, lpicinfo); +} + +static DWORD IC_HandleRef = 1; + +/*********************************************************************** + * ICInstall [MSVFW32.@] + */ +BOOL VFWAPI ICInstall(DWORD fccType, DWORD fccHandler, LPARAM lParam, LPSTR szDesc, UINT wFlags) +{ + reg_driver* driver; + unsigned len; + + TRACE("(%s,%s,%p,%p,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), (void*)lParam, szDesc, wFlags); + + /* Check if a driver is already registered */ + for (driver = reg_driver_list; driver; driver = driver->next) + { + if (!compare_fourcc(fccType, driver->fccType) && + !compare_fourcc(fccHandler, driver->fccHandler)) + break; + } + if (driver) return FALSE; + + /* Register the driver */ + driver = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(reg_driver)); + if (!driver) goto oom; + driver->fccType = fccType; + driver->fccHandler = fccHandler; + + switch(wFlags) + { + case ICINSTALL_FUNCTION: + driver->proc = (DRIVERPROC)lParam; + driver->name = NULL; + break; + case ICINSTALL_DRIVER: + driver->proc = NULL; + len = MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, NULL, 0); + driver->name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!driver->name) goto oom; + MultiByteToWideChar(CP_ACP, 0, (char*)lParam, -1, driver->name, len); + break; + default: + ERR("Invalid flags!\n"); + HeapFree(GetProcessHeap(), 0, driver); + return FALSE; + } + + /* Insert our driver in the list*/ + driver->next = reg_driver_list; + reg_driver_list = driver; + + return TRUE; + oom: + if (driver) HeapFree(GetProcessHeap(), 0, driver); + return FALSE; +} + +/*********************************************************************** + * ICRemove [MSVFW32.@] + */ +BOOL VFWAPI ICRemove(DWORD fccType, DWORD fccHandler, UINT wFlags) +{ + reg_driver** pdriver; + + TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wFlags); + + /* Check if a driver is already registered */ + for (pdriver = ®_driver_list; *pdriver; pdriver = &(*pdriver)->next) + { + if (!compare_fourcc(fccType, (*pdriver)->fccType) && + !compare_fourcc(fccHandler, (*pdriver)->fccHandler)) + break; + } + if (!*pdriver) + return FALSE; + + /* Remove the driver from the list */ + *pdriver = (*pdriver)->next; + if ((*pdriver)->name) + HeapFree(GetProcessHeap(), 0, (*pdriver)->name); + HeapFree(GetProcessHeap(), 0, *pdriver); + + return TRUE; +} + + +/*********************************************************************** + * ICOpen [MSVFW32.@] + * Opens an installable compressor. Return special handle. + */ +HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode) +{ + WCHAR codecname[10]; + ICOPEN icopen; + HDRVR hdrv; + WINE_HIC* whic; + BOOL bIs16; + static const WCHAR drv32W[] = {'d','r','i','v','e','r','s','3','2','\0'}; + reg_driver* driver; + + TRACE("(%s,%s,0x%08x)\n", wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode); + + /* Check if there is a registered driver that matches */ + driver = reg_driver_list; + while(driver) + if (!compare_fourcc(fccType, driver->fccType) && + !compare_fourcc(fccHandler, driver->fccHandler)) + break; + else + driver = driver->next; + + if (driver && driver->proc) + /* The driver has been registered at runtime with its driverproc */ + return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)driver->proc, (DWORD)NULL); + + /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the + * same layout as ICOPEN + */ + icopen.dwSize = sizeof(ICOPEN); + icopen.fccType = fccType; + icopen.fccHandler = fccHandler; + icopen.dwVersion = 0x00001000; /* FIXME */ + icopen.dwFlags = wMode; + icopen.dwError = 0; + icopen.pV1Reserved = NULL; + icopen.pV2Reserved = NULL; + icopen.dnDevNode = 0; /* FIXME */ + + if (!driver) { + /* The driver is registered in the registry */ + fourcc_to_string(codecname, fccType); + codecname[4] = '.'; + fourcc_to_string(codecname + 5, fccHandler); + codecname[9] = '\0'; + + hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen); + if (!hdrv) + { + if (fccType == streamtypeVIDEO) + { + codecname[0] = 'v'; + codecname[1] = 'i'; + codecname[2] = 'd'; + codecname[3] = 'c'; + + fccType = ICTYPE_VIDEO; + hdrv = OpenDriver(codecname, drv32W, (LPARAM)&icopen); + } + if (!hdrv) + return 0; + } + } else { + /* The driver has been registered at runtime with its name */ + hdrv = OpenDriver(driver->name, NULL, (LPARAM)&icopen); + if (!hdrv) + return 0; + } + bIs16 = GetDriverFlags(hdrv) & 0x10000000; /* undocumented flag: WINE_GDF_16BIT */ + + if (bIs16 && !pFnCallTo16) + { + FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n"); + return 0; + } + whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC)); + if (!whic) + { + CloseDriver(hdrv, 0, 0); + return FALSE; + } + whic->hdrv = hdrv; + /* FIXME: is the signature the real one ? */ + whic->driverproc = bIs16 ? (DRIVERPROC)pFnCallTo16 : NULL; + whic->driverproc16 = 0; + whic->type = fccType; + whic->handler = fccHandler; + while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++; + whic->hic = HIC_32(IC_HandleRef++); + whic->next = MSVIDEO_FirstHic; + MSVIDEO_FirstHic = whic; + + TRACE("=> %p\n", whic->hic); + return whic->hic; +} + +/*********************************************************************** + * MSVIDEO_OpenFunction + */ +HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, + DRIVERPROC lpfnHandler, DWORD lpfnHandler16) +{ + ICOPEN icopen; + WINE_HIC* whic; + + TRACE("(%s,%s,%d,%p,%08lx)\n", + wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), wMode, lpfnHandler, lpfnHandler16); + + icopen.dwSize = sizeof(ICOPEN); + icopen.fccType = fccType; + icopen.fccHandler = fccHandler; + icopen.dwVersion = 0x00001000; /* FIXME */ + icopen.dwFlags = wMode; + icopen.dwError = 0; + icopen.pV1Reserved = NULL; + icopen.pV2Reserved = NULL; + icopen.dnDevNode = 0; /* FIXME */ + + whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC)); + if (!whic) return 0; + + whic->driverproc = lpfnHandler; + whic->driverproc16 = lpfnHandler16; + while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++; + whic->hic = HIC_32(IC_HandleRef++); + whic->next = MSVIDEO_FirstHic; + MSVIDEO_FirstHic = whic; + + /* Now try opening/loading the driver. Taken from DRIVER_AddToList */ + /* What if the function is used more than once? */ + + if (MSVIDEO_SendMessage(whic, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) + { + WARN("DRV_LOAD failed for hic %p\n", whic->hic); + MSVIDEO_FirstHic = whic->next; + HeapFree(GetProcessHeap(), 0, whic); + return 0; + } + /* return value is not checked */ + MSVIDEO_SendMessage(whic, DRV_ENABLE, 0L, 0L); + + whic->driverId = (DWORD)MSVIDEO_SendMessage(whic, DRV_OPEN, 0, (DWORD)&icopen); + /* FIXME: What should we put here? */ + whic->hdrv = (HDRVR)0; + + if (whic->driverId == 0) + { + WARN("DRV_OPEN failed for hic %p\n", whic->hic); + MSVIDEO_FirstHic = whic->next; + HeapFree(GetProcessHeap(), 0, whic); + return 0; + } + + TRACE("=> %p\n", whic->hic); + return whic->hic; +} + +/*********************************************************************** + * ICOpenFunction [MSVFW32.@] + */ +HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler) +{ + return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)lpfnHandler, 0); +} + +/*********************************************************************** + * ICGetInfo [MSVFW32.@] + */ +LRESULT VFWAPI ICGetInfo(HIC hic, ICINFO *picinfo, DWORD cb) +{ + LRESULT ret; + WINE_HIC* whic = MSVIDEO_GetHicPtr(hic); + + TRACE("(%p,%p,%ld)\n", hic, picinfo, cb); + + whic = MSVIDEO_GetHicPtr(hic); + if (!whic) return ICERR_BADHANDLE; + if (!picinfo) return MMSYSERR_INVALPARAM; + + /* (WS) The field szDriver should be initialized because the driver + * is not obliged and often will not do it. Some applications, like + * VirtualDub, rely on this field and will occasionally crash if it + * goes unitialized. + */ + if (cb >= sizeof(ICINFO)) picinfo->szDriver[0] = '\0'; + + ret = ICSendMessage(hic, ICM_GETINFO, (DWORD)picinfo, cb); + + /* (WS) When szDriver was not supplied by the driver itself, apparently + * Windows will set its value equal to the driver file name. This can + * be obtained from the registry as we do here. + */ + if (cb >= sizeof(ICINFO) && picinfo->szDriver[0] == 0) + { + ICINFO ii; + + memset(&ii, 0, sizeof(ii)); + ii.dwSize = sizeof(ii); + ICInfo(picinfo->fccType, picinfo->fccHandler, &ii); + lstrcpyW(picinfo->szDriver, ii.szDriver); + } + + TRACE(" -> 0x%08lx\n", ret); + return ret; +} + +typedef struct { + DWORD fccType; + DWORD fccHandler; + LPBITMAPINFOHEADER lpbiIn; + LPBITMAPINFOHEADER lpbiOut; + WORD wMode; + DWORD querymsg; + HIC hic; +} driver_info_t; + +static HIC try_driver(driver_info_t *info) +{ + HIC hic; + + if ((hic = ICOpen(info->fccType, info->fccHandler, info->wMode))) + { + if (!ICSendMessage(hic, info->querymsg, (DWORD)info->lpbiIn, (DWORD)info->lpbiOut)) + return hic; + ICClose(hic); + } + return 0; +} + +static BOOL ICLocate_enum_handler(const char *drv, int nr, void *param) +{ + driver_info_t *info = (driver_info_t *)param; + info->fccHandler = mmioStringToFOURCCA(drv + 5, 0); + info->hic = try_driver(info); + return info->hic != 0; +} + +/*********************************************************************** + * ICLocate [MSVFW32.@] + */ +HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn, + LPBITMAPINFOHEADER lpbiOut, WORD wMode) +{ + driver_info_t info; + + TRACE("(%s,%s,%p,%p,0x%04x)\n", + wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode); + + info.fccType = fccType; + info.fccHandler = fccHandler; + info.lpbiIn = lpbiIn; + info.lpbiOut = lpbiOut; + info.wMode = wMode; + + switch (wMode) + { + case ICMODE_FASTCOMPRESS: + case ICMODE_COMPRESS: + info.querymsg = ICM_COMPRESS_QUERY; + break; + case ICMODE_FASTDECOMPRESS: + case ICMODE_DECOMPRESS: + info.querymsg = ICM_DECOMPRESS_QUERY; + break; + case ICMODE_DRAW: + info.querymsg = ICM_DRAW_QUERY; + break; + default: + WARN("Unknown mode (%d)\n", wMode); + return 0; + } + + /* Easy case: handler/type match, we just fire a query and return */ + info.hic = try_driver(&info); + /* If it didn't work, try each driver in turn. 32 bit codecs only. */ + /* FIXME: Move this to an init routine? */ + if (!info.hic) enum_drivers(fccType, ICLocate_enum_handler, &info); + + if (info.hic) + { + TRACE("=> %p\n", info.hic); + return info.hic; + } + + if (fccType == streamtypeVIDEO) + return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode); + + WARN("(%s,%s,%p,%p,0x%04x) not found!\n", + wine_dbgstr_fcc(fccType), wine_dbgstr_fcc(fccHandler), lpbiIn, lpbiOut, wMode); + return 0; +} + +/*********************************************************************** + * ICGetDisplayFormat [MSVFW32.@] + */ +HIC VFWAPI ICGetDisplayFormat( + HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut, + INT depth,INT dx,INT dy) +{ + HIC tmphic = hic; + + TRACE("(%p,%p,%p,%d,%d,%d)!\n",hic,lpbiIn,lpbiOut,depth,dx,dy); + + if (!tmphic) { + tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS); + if (!tmphic) + return tmphic; + } + if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth)) + dy = dx = 0; /* no resize needed */ + + /* Can we decompress it ? */ + if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0) + goto errout; /* no, sorry */ + + ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut); + + if (lpbiOut->biCompression != 0) { + FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n", + lpbiOut->biCompression); + } + if (lpbiOut->biSize < sizeof(*lpbiOut)) { + FIXME("Ooch, size of output BIH is too small (%ld)\n", + lpbiOut->biSize); + lpbiOut->biSize = sizeof(*lpbiOut); + } + if (!depth) { + HDC hdc; + + hdc = GetDC(0); + depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); + ReleaseDC(0,hdc); + if (depth==15) depth = 16; + if (depth<8) depth = 8; + } + if (lpbiIn->biBitCount == 8) + depth = 8; + + TRACE("=> %p\n", tmphic); + return tmphic; +errout: + if (hic!=tmphic) + ICClose(tmphic); + + TRACE("=> 0\n"); + return 0; +} + +/*********************************************************************** + * ICCompress [MSVFW32.@] + */ +DWORD VFWAPIV +ICCompress( + HIC 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) +{ + ICCOMPRESS iccmp; + + TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",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; + return ICSendMessage(hic,ICM_COMPRESS,(DWORD)&iccmp,sizeof(iccmp)); +} + +/*********************************************************************** + * ICDecompress [MSVFW32.@] + */ +DWORD VFWAPIV ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat, + LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits) +{ + ICDECOMPRESS icd; + DWORD ret; + + TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits); + + TRACE("lpBits[0] == %lx\n",((LPDWORD)lpBits)[0]); + + icd.dwFlags = dwFlags; + icd.lpbiInput = lpbiFormat; + icd.lpInput = lpData; + + icd.lpbiOutput = lpbi; + icd.lpOutput = lpBits; + icd.ckid = 0; + ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS)); + + TRACE("lpBits[0] == %lx\n",((LPDWORD)lpBits)[0]); + + TRACE("-> %ld\n",ret); + + return ret; +} + + +/*********************************************************************** + * ICCompressorChoose [MSVFW32.@] + */ +BOOL VFWAPI ICCompressorChoose(HWND hwnd, UINT uiFlags, LPVOID pvIn, + LPVOID lpData, PCOMPVARS pc, LPSTR lpszTitle) +{ + FIXME("(%p,0x%X,%p,%p,%p,%s),stub!\n",hwnd,uiFlags,pvIn,lpData,pc,lpszTitle); + + if (pc == NULL || pc->cbSize != sizeof(COMPVARS)) + return FALSE; + + if ((pc->dwFlags & ICMF_COMPVARS_VALID) == 0) { + pc->dwFlags = 0; + pc->fccType = pc->fccHandler = 0; + pc->hic = NULL; + pc->lpbiOut = NULL; + pc->lpBitsOut = pc->lpBitsPrev = pc->lpState = NULL; + pc->lQ = ICQUALITY_DEFAULT; + pc->lKey = -1; + pc->lDataRate = 300; /* kB */ + pc->lpState = NULL; + pc->cbState = 0; + } + if (pc->fccType == 0) + pc->fccType = ICTYPE_VIDEO; + + /* FIXME */ + + return FALSE; +} + + +/*********************************************************************** + * ICCompressorFree [MSVFW32.@] + */ +void VFWAPI ICCompressorFree(PCOMPVARS pc) +{ + TRACE("(%p)\n",pc); + + if (pc != NULL && pc->cbSize == sizeof(COMPVARS)) { + if (pc->hic != NULL) { + ICClose(pc->hic); + pc->hic = NULL; + } + if (pc->lpbiOut != NULL) { + GlobalFreePtr(pc->lpbiOut); + pc->lpbiOut = NULL; + } + if (pc->lpBitsOut != NULL) { + GlobalFreePtr(pc->lpBitsOut); + pc->lpBitsOut = NULL; + } + if (pc->lpBitsPrev != NULL) { + GlobalFreePtr(pc->lpBitsPrev); + pc->lpBitsPrev = NULL; + } + if (pc->lpState != NULL) { + GlobalFreePtr(pc->lpBitsPrev); + pc->lpState = NULL; + } + pc->dwFlags = 0; + } +} + + +/****************************************************************** + * MSVIDEO_SendMessage + * + * + */ +LRESULT MSVIDEO_SendMessage(WINE_HIC* whic, UINT msg, DWORD lParam1, DWORD lParam2) +{ + LRESULT ret; + +#define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",whic,lParam1,lParam2); break; + + switch (msg) { + /* DRV_* */ + XX(DRV_LOAD); + XX(DRV_ENABLE); + XX(DRV_OPEN); + XX(DRV_CLOSE); + XX(DRV_DISABLE); + XX(DRV_FREE); + /* ICM_RESERVED+X */ + XX(ICM_ABOUT); + XX(ICM_CONFIGURE); + XX(ICM_GET); + XX(ICM_GETINFO); + XX(ICM_GETDEFAULTQUALITY); + XX(ICM_GETQUALITY); + XX(ICM_GETSTATE); + XX(ICM_SETQUALITY); + XX(ICM_SET); + XX(ICM_SETSTATE); + /* ICM_USER+X */ + XX(ICM_COMPRESS_FRAMES_INFO); + XX(ICM_COMPRESS_GET_FORMAT); + XX(ICM_COMPRESS_GET_SIZE); + XX(ICM_COMPRESS_QUERY); + XX(ICM_COMPRESS_BEGIN); + XX(ICM_COMPRESS); + XX(ICM_COMPRESS_END); + XX(ICM_DECOMPRESS_GET_FORMAT); + XX(ICM_DECOMPRESS_QUERY); + XX(ICM_DECOMPRESS_BEGIN); + XX(ICM_DECOMPRESS); + XX(ICM_DECOMPRESS_END); + XX(ICM_DECOMPRESS_SET_PALETTE); + XX(ICM_DECOMPRESS_GET_PALETTE); + XX(ICM_DRAW_QUERY); + XX(ICM_DRAW_BEGIN); + XX(ICM_DRAW_GET_PALETTE); + XX(ICM_DRAW_START); + XX(ICM_DRAW_STOP); + XX(ICM_DRAW_END); + XX(ICM_DRAW_GETTIME); + XX(ICM_DRAW); + XX(ICM_DRAW_WINDOW); + XX(ICM_DRAW_SETTIME); + XX(ICM_DRAW_REALIZE); + XX(ICM_DRAW_FLUSH); + XX(ICM_DRAW_RENDERBUFFER); + XX(ICM_DRAW_START_PLAY); + XX(ICM_DRAW_STOP_PLAY); + XX(ICM_DRAW_SUGGESTFORMAT); + XX(ICM_DRAW_CHANGEPALETTE); + XX(ICM_GETBUFFERSWANTED); + XX(ICM_GETDEFAULTKEYFRAMERATE); + XX(ICM_DECOMPRESSEX_BEGIN); + XX(ICM_DECOMPRESSEX_QUERY); + XX(ICM_DECOMPRESSEX); + XX(ICM_DECOMPRESSEX_END); + XX(ICM_SET_STATUS_PROC); + default: + FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",whic,(DWORD)msg,lParam1,lParam2); + } + +#undef XX + + if (whic->driverproc) { + /* dwDriverId parameter is the value returned by the DRV_OPEN */ + ret = whic->driverproc(whic->driverId, whic->hdrv, msg, lParam1, lParam2); + } else { + ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2); + } + + TRACE(" -> 0x%08lx\n", ret); + return ret; +} + +/*********************************************************************** + * ICSendMessage [MSVFW32.@] + */ +LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2) +{ + WINE_HIC* whic = MSVIDEO_GetHicPtr(hic); + + if (!whic) return ICERR_BADHANDLE; + return MSVIDEO_SendMessage(whic, msg, lParam1, lParam2); +} + +/*********************************************************************** + * ICDrawBegin [MSVFW32.@] + */ +DWORD VFWAPIV ICDrawBegin( + HIC hic, /* [in] */ + DWORD dwFlags, /* [in] flags */ + HPALETTE hpal, /* [in] palette to draw with */ + HWND hwnd, /* [in] window to draw to */ + HDC hdc, /* [in] HDC to draw to */ + INT xDst, /* [in] destination rectangle */ + INT yDst, /* [in] */ + INT dxDst, /* [in] */ + INT dyDst, /* [in] */ + LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw */ + INT xSrc, /* [in] source rectangle */ + INT ySrc, /* [in] */ + INT dxSrc, /* [in] */ + INT dySrc, /* [in] */ + DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */ + DWORD dwScale) /* [in] */ +{ + + ICDRAWBEGIN icdb; + + TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n", + hic, dwFlags, hpal, hwnd, 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; + icdb.xSrc = xSrc; + icdb.ySrc = ySrc; + icdb.dxSrc = dxSrc; + icdb.dySrc = dySrc; + icdb.dwRate = dwRate; + icdb.dwScale = dwScale; + return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb)); +} + +/*********************************************************************** + * ICDraw [MSVFW32.@] + */ +DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) { + ICDRAW icd; + + TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic,dwFlags,lpFormat,lpData,cbData,lTime); + + icd.dwFlags = dwFlags; + icd.lpFormat = lpFormat; + icd.lpData = lpData; + icd.cbData = cbData; + icd.lTime = lTime; + + return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd)); +} + +/*********************************************************************** + * ICClose [MSVFW32.@] + */ +LRESULT WINAPI ICClose(HIC hic) +{ + WINE_HIC* whic = MSVIDEO_GetHicPtr(hic); + WINE_HIC** p; + + TRACE("(%p)\n",hic); + + if (!whic) return ICERR_BADHANDLE; + + if (whic->driverproc) + { + MSVIDEO_SendMessage(whic, DRV_CLOSE, 0, 0); + MSVIDEO_SendMessage(whic, DRV_DISABLE, 0, 0); + MSVIDEO_SendMessage(whic, DRV_FREE, 0, 0); + } + else + { + CloseDriver(whic->hdrv, 0, 0); + } + + /* remove whic from list */ + for (p = &MSVIDEO_FirstHic; *p != NULL; p = &((*p)->next)) + { + if ((*p) == whic) + { + *p = whic->next; + break; + } + } + + HeapFree(GetProcessHeap(), 0, whic); + return 0; +} + + + +/*********************************************************************** + * ICImageCompress [MSVFW32.@] + */ +HANDLE VFWAPI ICImageCompress( + HIC hic, UINT uiFlags, + LPBITMAPINFO lpbiIn, LPVOID lpBits, + LPBITMAPINFO lpbiOut, LONG lQuality, + LONG* plSize) +{ + FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n", + hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize); + + return NULL; +} + +/*********************************************************************** + * ICImageDecompress [MSVFW32.@] + */ + +HANDLE VFWAPI ICImageDecompress( + HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn, + LPVOID lpBits, LPBITMAPINFO lpbiOut) +{ + HGLOBAL hMem = NULL; + BYTE* pMem = NULL; + BOOL bReleaseIC = FALSE; + BYTE* pHdr = NULL; + LONG cbHdr = 0; + BOOL bSucceeded = FALSE; + BOOL bInDecompress = FALSE; + DWORD biSizeImage; + + TRACE("(%p,%08x,%p,%p,%p)\n", + hic, uiFlags, lpbiIn, lpBits, lpbiOut); + + if ( hic == NULL ) + { + hic = ICDecompressOpen( ICTYPE_VIDEO, 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL ); + if ( hic == NULL ) + { + WARN("no handler\n" ); + goto err; + } + bReleaseIC = TRUE; + } + if ( uiFlags != 0 ) + { + FIXME( "unknown flag %08x\n", uiFlags ); + goto err; + } + if ( lpbiIn == NULL || lpBits == NULL ) + { + WARN("invalid argument\n"); + goto err; + } + + if ( lpbiOut != NULL ) + { + if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ) + goto err; + cbHdr = sizeof(BITMAPINFOHEADER); + if ( lpbiOut->bmiHeader.biCompression == 3 ) + cbHdr += sizeof(DWORD)*3; + else + if ( lpbiOut->bmiHeader.biBitCount <= 8 ) + { + if ( lpbiOut->bmiHeader.biClrUsed == 0 ) + cbHdr += sizeof(RGBQUAD) * (1<bmiHeader.biBitCount); + else + cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed; + } + } + else + { + TRACE( "get format\n" ); + + cbHdr = ICDecompressGetFormatSize(hic,lpbiIn); + if ( cbHdr < sizeof(BITMAPINFOHEADER) ) + goto err; + pHdr = (BYTE*)HeapAlloc(GetProcessHeap(),0,cbHdr+sizeof(RGBQUAD)*256); + if ( pHdr == NULL ) + goto err; + ZeroMemory( pHdr, cbHdr+sizeof(RGBQUAD)*256 ); + if ( ICDecompressGetFormat( hic, lpbiIn, (BITMAPINFO*)pHdr ) != ICERR_OK ) + goto err; + lpbiOut = (BITMAPINFO*)pHdr; + if ( lpbiOut->bmiHeader.biBitCount <= 8 && + ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK && + lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount ) + { + if ( lpbiIn->bmiHeader.biClrUsed == 0 ) + memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<bmiHeader.biBitCount) ); + else + memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed ); + } + if ( lpbiOut->bmiHeader.biBitCount <= 8 && + lpbiOut->bmiHeader.biClrUsed == 0 ) + lpbiOut->bmiHeader.biClrUsed = 1<bmiHeader.biBitCount; + + lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed; + } + + biSizeImage = lpbiOut->bmiHeader.biSizeImage; + if ( biSizeImage == 0 ) + biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight); + + TRACE( "call ICDecompressBegin\n" ); + + if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK ) + goto err; + bInDecompress = TRUE; + + TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr, biSizeImage ); + + hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage ); + if ( hMem == NULL ) + { + WARN( "out of memory\n" ); + goto err; + } + pMem = (BYTE*)GlobalLock( hMem ); + if ( pMem == NULL ) + goto err; + memcpy( pMem, lpbiOut, cbHdr ); + + TRACE( "call ICDecompress\n" ); + if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK ) + goto err; + + bSucceeded = TRUE; +err: + if ( bInDecompress ) + ICDecompressEnd( hic ); + if ( bReleaseIC ) + ICClose(hic); + if ( pHdr != NULL ) + HeapFree(GetProcessHeap(),0,pHdr); + if ( pMem != NULL ) + GlobalUnlock( hMem ); + if ( !bSucceeded && hMem != NULL ) + { + GlobalFree(hMem); hMem = NULL; + } + + return (HANDLE)hMem; +} + +static BOOL GetFileNamePreview(LPVOID lpofn,BOOL bSave,BOOL bUnicode) +{ + CHAR szFunctionName[20]; + BOOL (*fnGetFileName)(LPVOID); + HMODULE hComdlg32; + BOOL ret; + + FIXME("(%p,%d,%d), semi-stub!\n",lpofn,bSave,bUnicode); + + lstrcpyA(szFunctionName, (bSave ? "GetSaveFileName" : "GetOpenFileName")); + lstrcatA(szFunctionName, (bUnicode ? "W" : "A")); + + hComdlg32 = LoadLibraryA("COMDLG32.DLL"); + if (hComdlg32 == NULL) + return FALSE; + + fnGetFileName = (LPVOID)GetProcAddress(hComdlg32, szFunctionName); + if (fnGetFileName == NULL) + return FALSE; + + /* FIXME: need to add OFN_ENABLEHOOK and our own handler */ + ret = fnGetFileName(lpofn); + + FreeLibrary(hComdlg32); + return ret; +} + +/*********************************************************************** + * GetOpenFileNamePreviewA [MSVFW32.@] + */ +BOOL WINAPI GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn) +{ + FIXME("(%p), semi-stub!\n", lpofn); + + return GetFileNamePreview(lpofn, FALSE, FALSE); +} + +/*********************************************************************** + * GetOpenFileNamePreviewW [MSVFW32.@] + */ +BOOL WINAPI GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn) +{ + FIXME("(%p), semi-stub!\n", lpofn); + + return GetFileNamePreview(lpofn, FALSE, TRUE); +} + +/*********************************************************************** + * GetSaveFileNamePreviewA [MSVFW32.@] + */ +BOOL WINAPI GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn) +{ + FIXME("(%p), semi-stub!\n", lpofn); + + return GetFileNamePreview(lpofn, TRUE, FALSE); +} + +/*********************************************************************** + * GetSaveFileNamePreviewW [MSVFW32.@] + */ +BOOL WINAPI GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn) +{ + FIXME("(%p), semi-stub!\n", lpofn); + + return GetFileNamePreview(lpofn, TRUE, TRUE); +} diff --git a/reactos/lib/msvideo/msvideo_private.h b/reactos/lib/msvideo/msvideo_private.h new file mode 100644 index 00000000000..bf0544f2f5e --- /dev/null +++ b/reactos/lib/msvideo/msvideo_private.h @@ -0,0 +1,65 @@ +/* + * Copyright 1999 Marcus Meissner + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_MSVIDEO_PRIVATE_H +#define __WINE_MSVIDEO_PRIVATE_H + +#define COM_NO_WINDOWS_H +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "commdlg.h" +#include "vfw.h" + +/* HIC struct (same layout as Win95 one) */ +typedef struct tagWINE_HIC { + DWORD magic; /* 00: 'Smag' */ + HANDLE curthread; /* 04: */ + DWORD type; /* 08: */ + DWORD handler; /* 0C: */ + HDRVR hdrv; /* 10: */ + DWORD private; /* 14:(handled by SendDriverMessage)*/ + DRIVERPROC driverproc; /* 18:(handled by SendDriverMessage)*/ + DWORD x1; /* 1c: name? */ + WORD x2; /* 20: */ + DWORD x3; /* 22: */ + /* 26: */ + DWORD driverproc16; /* Wine specific flags */ + HIC hic; + DWORD driverId; + struct tagWINE_HIC* next; +} WINE_HIC; + +HIC MSVIDEO_OpenFunction(DWORD, DWORD, UINT, DRIVERPROC, DWORD); +LRESULT MSVIDEO_SendMessage(WINE_HIC*, UINT, DWORD, DWORD); +WINE_HIC* MSVIDEO_GetHicPtr(HIC); + +extern LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM); + +/* 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)) + +#endif /* __WINE_MSVIDEO_PRIVATE_H */ diff --git a/reactos/lib/msvideo/vfw16.h b/reactos/lib/msvideo/vfw16.h new file mode 100644 index 00000000000..3257ed00039 --- /dev/null +++ b/reactos/lib/msvideo/vfw16.h @@ -0,0 +1,130 @@ +/* + * Copyright 1999 Marcus Meissner + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_VFW16_H +#define __WINE_VFW16_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "vfw.h" +#include "wownt32.h" +#include "wine/windef16.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef HANDLE16 HDRAWDIB16; + +#include "pshpack1.h" + +typedef struct { + DWORD dwSize; + DWORD fccType; + DWORD fccHandler; + DWORD dwFlags; + DWORD dwVersion; + DWORD dwVersionICM; + /* + * under Win16, normal chars are used + */ + CHAR szName[16]; + CHAR szDescription[128]; + CHAR szDriver[128]; +} ICINFO16; + +typedef struct { + DWORD dwFlags; + LPBITMAPINFOHEADER lpbiSrc; + LPVOID lpSrc; + LPBITMAPINFOHEADER lpbiDst; + LPVOID lpDst; + + INT16 xDst; /* destination rectangle */ + INT16 yDst; + INT16 dxDst; + INT16 dyDst; + + INT16 xSrc; /* source rectangle */ + INT16 ySrc; + INT16 dxSrc; + INT16 dySrc; +} ICDECOMPRESSEX16; + +typedef struct { + DWORD dwFlags; + HPALETTE16 hpal; + HWND16 hwnd; + HDC16 hdc; + INT16 xDst; + INT16 yDst; + INT16 dxDst; + INT16 dyDst; + LPBITMAPINFOHEADER lpbi; + INT16 xSrc; + INT16 ySrc; + INT16 dxSrc; + INT16 dySrc; + DWORD dwRate; + DWORD dwScale; +} ICDRAWBEGIN16; + +#include "poppack.h" + +typedef struct { + DWORD dwFlags; + LPBITMAPINFOHEADER lpbiIn; + LPBITMAPINFOHEADER lpbiSuggest; + INT16 dxSrc; + INT16 dySrc; + INT16 dxDst; + INT16 dyDst; + HIC16 hicDecompressor; +} ICDRAWSUGGEST16; + +DWORD VFWAPIV ICDraw16(HIC16,DWORD,LPVOID,LPVOID,DWORD,LONG); +DWORD VFWAPIV ICDrawBegin16(HIC16,DWORD,HPALETTE16,HWND16,HDC16,INT16, + INT16,INT16,INT16,LPBITMAPINFOHEADER, + INT16,INT16,INT16,INT16,DWORD,DWORD); +LRESULT WINAPI ICClose16(HIC16); +DWORD VFWAPIV ICCompress16(HIC16,DWORD,LPBITMAPINFOHEADER,LPVOID, + LPBITMAPINFOHEADER,LPVOID,LPDWORD, + LPDWORD,LONG,DWORD,DWORD, + LPBITMAPINFOHEADER,LPVOID); +DWORD VFWAPIV ICDecompress16(HIC16,DWORD,LPBITMAPINFOHEADER,LPVOID, + LPBITMAPINFOHEADER,LPVOID); +HIC16 VFWAPI ICGetDisplayFormat16(HIC16,LPBITMAPINFOHEADER, + LPBITMAPINFOHEADER,INT16,INT16, + INT16); +LRESULT VFWAPI ICGetInfo16(HIC16,ICINFO16 *,DWORD); +BOOL16 VFWAPI ICInfo16(DWORD,DWORD,ICINFO16 *); +HIC16 VFWAPI ICLocate16(DWORD,DWORD,LPBITMAPINFOHEADER, + LPBITMAPINFOHEADER,WORD); +LRESULT VFWAPIV ICMessage16( HIC16 hic, UINT16 msg, UINT16 cb, VA_LIST16 valist ); +HIC16 VFWAPI ICOpen16(DWORD,DWORD,UINT16); +HIC16 VFWAPI ICOpenFunction16(DWORD,DWORD,UINT16,FARPROC16); +LRESULT VFWAPI ICSendMessage16(HIC16,UINT16,DWORD,DWORD); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __WINE_VFW16_H */