📄 msvideo_main.c
字号:
/*
* Copyright 1998 Marcus Meissner
* Copyright 2000 Bradley Baetz
* Copyright 2003 Michael G黱newig
*
* 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 <stdio.h>
#include <string.h>
#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 <n>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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -