mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
Removed the wine loader.
Original commit message from CVS: Removed the wine loader.
This commit is contained in:
parent
dcc6193959
commit
2427113b1d
19 changed files with 2 additions and 6987 deletions
|
@ -1,9 +1,4 @@
|
|||
if HAVE_CPU_I386
|
||||
GSTARCH_SUBDS = winloader
|
||||
else
|
||||
GSTARCH_SUBDS =
|
||||
endif
|
||||
|
||||
SUBDIRS = riff colorspace getbits putbits idct videoscale audio $(GSTARCH_SUBDS)
|
||||
SUBDIRS = riff colorspace getbits putbits idct videoscale audio
|
||||
|
||||
DIST_SUBDIRS = riff colorspace getbits putbits videoscale winloader audio idct
|
||||
DIST_SUBDIRS = riff colorspace getbits putbits videoscale audio idct
|
||||
|
|
7
libs/winloader/.gitignore
vendored
7
libs/winloader/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
|
@ -1,14 +0,0 @@
|
|||
filterdir = $(libdir)/gst
|
||||
|
||||
filter_LTLIBRARIES = libwinloader.la
|
||||
|
||||
# compiler manages to screw something up here... must reduce optimizations
|
||||
CFLAGS += -O0 -funroll-loops
|
||||
|
||||
libwinloader_la_SOURCES = win32.c driver.c elfdll.c ext.c module.c \
|
||||
pe_image.c pe_resource.c registry.c resource.c stubs.s vfl.c afl.c
|
||||
|
||||
noinst_HEADERS = wineacm.h win32.h registry.h avifmt.h
|
||||
|
||||
DEFINES=-rdynamic -fPIC -D__WINE__ -Ddbg_printf=__vprintf -DTRACE=__vprintf
|
||||
CFLAGS += $(DEFINES)
|
|
@ -1,759 +0,0 @@
|
|||
/**************************************************************************
|
||||
|
||||
|
||||
This file will contain an interface to ACM drivers.
|
||||
Its content will be based mainly on wine/dlls/msacm32
|
||||
actually, for audio decompression only the following functions
|
||||
are needed:
|
||||
|
||||
acmStreamOpen ( takes formats of src and dest, returns stream handle )
|
||||
acmStreamPrepareHeader ( takes stream handler and info on data )
|
||||
acmStreamConvert ( the same as PrepareHeader )
|
||||
acmStreamUnprepareHeader
|
||||
acmStreamClose
|
||||
acmStreamSize
|
||||
maybe acmStreamReset
|
||||
|
||||
In future I'll also add functions for format enumeration,
|
||||
but not right now.
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wine/winbase.h>
|
||||
#include <wine/windef.h>
|
||||
#include <wine/winuser.h>
|
||||
#include <wine/vfw.h>
|
||||
#include <wine/winestring.h>
|
||||
#include <wine/driver.h>
|
||||
#include <wine/winerror.h>
|
||||
#include <wine/msacm.h>
|
||||
#include <wine/msacmdrv.h>
|
||||
#include "wineacm.h"
|
||||
#pragma pack(1)
|
||||
#define OpenDriverA DrvOpen
|
||||
extern HDRVR VFWAPI DrvOpen(long);
|
||||
#define CloseDriver DrvClose
|
||||
extern HDRVR VFWAPI DrvClose(long);
|
||||
|
||||
static PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
|
||||
{
|
||||
return (PWINE_ACMSTREAM)has;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverAddA (MSACM32.2)
|
||||
*/
|
||||
MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
|
||||
LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
|
||||
{
|
||||
if (!phadid)
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
||||
/* Check if any unknown flags */
|
||||
if (fdwAdd &
|
||||
~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
|
||||
ACM_DRIVERADDF_GLOBAL))
|
||||
return MMSYSERR_INVALFLAG;
|
||||
|
||||
/* Check if any incompatible flags */
|
||||
if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
|
||||
(fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
|
||||
return MMSYSERR_INVALFLAG;
|
||||
|
||||
/* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
|
||||
* LoadDriver on it, to be sure we can call SendDriverMessage on the
|
||||
* hDrvr handle.
|
||||
*/
|
||||
*phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, hinstModule);
|
||||
|
||||
/* FIXME: lParam, dwPriority and fdwAdd ignored */
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverClose (MSACM32.4)
|
||||
*/
|
||||
MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
|
||||
{
|
||||
PWINE_ACMDRIVER p;
|
||||
PWINE_ACMDRIVER* tp;
|
||||
|
||||
if (fdwClose)
|
||||
return MMSYSERR_INVALFLAG;
|
||||
|
||||
p = MSACM_GetDriver(had);
|
||||
if (!p)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
|
||||
for (tp = &(p->obj.pACMDriverID->pACMDriverList); *tp; *tp = (*tp)->pNextACMDriver) {
|
||||
if (*tp == p) {
|
||||
*tp = (*tp)->pNextACMDriver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->hDrvr && !p->obj.pACMDriverID->pACMDriverList)
|
||||
CloseDriver(p->hDrvr);
|
||||
|
||||
HeapFree(MSACM_hHeap, 0, p);
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverEnum (MSACM32.7)
|
||||
*/
|
||||
MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
|
||||
{
|
||||
PWINE_ACMDRIVERID p;
|
||||
DWORD fdwSupport;
|
||||
|
||||
if (!fnCallback) {
|
||||
return MMSYSERR_INVALPARAM;
|
||||
}
|
||||
|
||||
if (fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED)) {
|
||||
return MMSYSERR_INVALFLAG;
|
||||
}
|
||||
|
||||
for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
|
||||
fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
|
||||
if (!p->bEnabled) {
|
||||
if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
|
||||
fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
(*fnCallback)((HACMDRIVERID) p, dwInstance, fdwSupport);
|
||||
}
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverID (MSACM32.8)
|
||||
*/
|
||||
MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
|
||||
{
|
||||
PWINE_ACMOBJ pao;
|
||||
|
||||
pao = MSACM_GetObj(hao);
|
||||
if (!pao)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
|
||||
if (!phadid)
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
||||
if (fdwDriverID)
|
||||
return MMSYSERR_INVALFLAG;
|
||||
|
||||
*phadid = (HACMDRIVERID) pao->pACMDriverID;
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverMessage (MSACM32.9)
|
||||
* FIXME
|
||||
* Not implemented
|
||||
*/
|
||||
LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
|
||||
{
|
||||
PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
|
||||
if (!pad)
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
||||
/* FIXME: Check if uMsg legal */
|
||||
|
||||
if (!SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2))
|
||||
return MMSYSERR_NOTSUPPORTED;
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverOpen (MSACM32.10)
|
||||
*/
|
||||
MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
|
||||
{
|
||||
PWINE_ACMDRIVERID padid;
|
||||
PWINE_ACMDRIVER pad;
|
||||
ICOPEN icopen;
|
||||
HDRVR hdrv;
|
||||
|
||||
|
||||
|
||||
TRACE("(%p, %x, %08lu)\n", phad, hadid, fdwOpen);
|
||||
|
||||
if (!phad)
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
||||
padid = MSACM_GetDriverID(hadid);
|
||||
if (!padid)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
|
||||
if (fdwOpen)
|
||||
return MMSYSERR_INVALFLAG;
|
||||
|
||||
pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
|
||||
if (!pad) return MMSYSERR_NOMEM;
|
||||
|
||||
pad->obj.pACMDriverID = padid;
|
||||
icopen.fccType = mmioFOURCC('a', 'u', 'd', 'c');
|
||||
icopen.fccHandler = (long)padid->pszFileName;
|
||||
icopen.dwSize = sizeof(ICOPEN);
|
||||
icopen.dwFlags = 0;
|
||||
|
||||
if (!padid->hInstModule)
|
||||
pad->hDrvr = OpenDriverA((long)&icopen);
|
||||
else
|
||||
pad->hDrvr = padid->hInstModule;
|
||||
|
||||
if (!pad->hDrvr) {
|
||||
HeapFree(MSACM_hHeap, 0, pad);
|
||||
return MMSYSERR_ERROR;
|
||||
}
|
||||
|
||||
pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc");
|
||||
|
||||
/* insert new pad at beg of list */
|
||||
pad->pNextACMDriver = padid->pACMDriverList;
|
||||
padid->pACMDriverList = pad;
|
||||
|
||||
/* FIXME: Create a WINE_ACMDRIVER32 */
|
||||
*phad = (HACMDRIVER)pad;
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmDriverRemove (MSACM32.12)
|
||||
*/
|
||||
MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
|
||||
{
|
||||
PWINE_ACMDRIVERID padid;
|
||||
|
||||
padid = MSACM_GetDriverID(hadid);
|
||||
if (!padid)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
|
||||
if (fdwRemove)
|
||||
return MMSYSERR_INVALFLAG;
|
||||
|
||||
MSACM_UnregisterDriver(padid);
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
HANDLE MSACM_hHeap = (HANDLE) NULL;
|
||||
PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
|
||||
PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_RegisterDriver32()
|
||||
*/
|
||||
PWINE_ACMDRIVERID MSACM_RegisterDriver(LPSTR pszDriverAlias, LPSTR pszFileName,
|
||||
HINSTANCE hinstModule)
|
||||
//
|
||||
// File names are stored in driver.c. I reuse this variable to store driver ID
|
||||
// in it. If it's <0x10000, it is primary codec for corresponding format.
|
||||
//
|
||||
{
|
||||
PWINE_ACMDRIVERID padid;
|
||||
|
||||
TRACE("('%s', '%x', 0x%08x)\n", pszDriverAlias, pszFileName, hinstModule);
|
||||
|
||||
padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
|
||||
padid->pszDriverAlias = (char*)malloc(strlen(pszDriverAlias)+1);
|
||||
strcpy(padid->pszDriverAlias, pszDriverAlias);
|
||||
// 1~strdup(pszDriverAlias);
|
||||
padid->pszFileName = pszFileName;
|
||||
padid->hInstModule = hinstModule;
|
||||
padid->bEnabled = TRUE;
|
||||
padid->pACMDriverList = NULL;
|
||||
padid->pNextACMDriverID = NULL;
|
||||
padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
|
||||
if (MSACM_pLastACMDriverID)
|
||||
MSACM_pLastACMDriverID->pNextACMDriverID = padid;
|
||||
MSACM_pLastACMDriverID = padid;
|
||||
if (!MSACM_pFirstACMDriverID)
|
||||
MSACM_pFirstACMDriverID = padid;
|
||||
|
||||
return padid;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_RegisterAllDrivers32()
|
||||
*/
|
||||
void MSACM_RegisterAllDrivers(void)
|
||||
{
|
||||
LPSTR pszBuffer;
|
||||
DWORD dwBufferLength;
|
||||
|
||||
if (MSACM_pFirstACMDriverID)
|
||||
return;
|
||||
|
||||
MSACM_RegisterDriver("divxa32", (LPSTR)0x161, 0);
|
||||
MSACM_RegisterDriver("msadp32", (LPSTR)0x2, 0);
|
||||
MSACM_RegisterDriver("l3codeca", (LPSTR)0x55, 0);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_UnregisterDriver32()
|
||||
*/
|
||||
PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
|
||||
{
|
||||
PWINE_ACMDRIVERID pNextACMDriverID;
|
||||
|
||||
while (p->pACMDriverList)
|
||||
acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
|
||||
|
||||
if (p->pszDriverAlias)
|
||||
HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
|
||||
// if (p->pszFileName)
|
||||
// HeapFree(MSACM_hHeap, 0, p->pszFileName);
|
||||
|
||||
if (p == MSACM_pFirstACMDriverID)
|
||||
MSACM_pFirstACMDriverID = p->pNextACMDriverID;
|
||||
if (p == MSACM_pLastACMDriverID)
|
||||
MSACM_pLastACMDriverID = p->pPrevACMDriverID;
|
||||
|
||||
if (p->pPrevACMDriverID)
|
||||
p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
|
||||
if (p->pNextACMDriverID)
|
||||
p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
|
||||
|
||||
pNextACMDriverID = p->pNextACMDriverID;
|
||||
|
||||
HeapFree(MSACM_hHeap, 0, p);
|
||||
|
||||
return pNextACMDriverID;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_UnregisterAllDrivers32()
|
||||
* FIXME
|
||||
* Where should this function be called?
|
||||
*/
|
||||
void MSACM_UnregisterAllDrivers(void)
|
||||
{
|
||||
PWINE_ACMDRIVERID p;
|
||||
|
||||
for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_GetDriverID32()
|
||||
*/
|
||||
PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
|
||||
{
|
||||
return (PWINE_ACMDRIVERID)hDriverID;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_GetDriver32()
|
||||
*/
|
||||
PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
|
||||
{
|
||||
return (PWINE_ACMDRIVER)hDriver;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MSACM_GetObj32()
|
||||
*/
|
||||
PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj)
|
||||
{
|
||||
return (PWINE_ACMOBJ)hObj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* acmStreamOpen (MSACM32.40)
|
||||
*/
|
||||
MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
|
||||
PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
|
||||
DWORD dwInstance, DWORD fdwOpen)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
PWINE_ACMDRIVER wad;
|
||||
MMRESULT ret;
|
||||
int wfxSrcSize;
|
||||
int wfxDstSize;
|
||||
|
||||
TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
|
||||
phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
|
||||
|
||||
TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
|
||||
pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
|
||||
pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize);
|
||||
|
||||
TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
|
||||
pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
|
||||
pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
|
||||
|
||||
#define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize))
|
||||
wfxSrcSize = SIZEOF_WFX(pwfxSrc);
|
||||
wfxDstSize = SIZEOF_WFX(pwfxDst);
|
||||
#undef SIZEOF_WFX
|
||||
|
||||
was = HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0));
|
||||
if (was == NULL)
|
||||
return MMSYSERR_NOMEM;
|
||||
|
||||
was->drvInst.cbStruct = sizeof(was->drvInst);
|
||||
was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
|
||||
memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
|
||||
was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
|
||||
memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
|
||||
if (pwfltr) {
|
||||
was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
|
||||
memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
|
||||
} else {
|
||||
was->drvInst.pwfltr = NULL;
|
||||
}
|
||||
was->drvInst.dwCallback = dwCallback;
|
||||
was->drvInst.dwInstance = dwInstance;
|
||||
was->drvInst.fdwOpen = fdwOpen;
|
||||
was->drvInst.fdwDriver = 0L;
|
||||
was->drvInst.dwDriver = 0L;
|
||||
was->drvInst.has = (HACMSTREAM)was;
|
||||
|
||||
if (had) {
|
||||
if (!(wad = MSACM_GetDriver(had))) {
|
||||
ret = MMSYSERR_INVALPARAM;
|
||||
goto errCleanUp;
|
||||
}
|
||||
|
||||
was->obj.pACMDriverID = wad->obj.pACMDriverID;
|
||||
was->pDrv = wad;
|
||||
was->hAcmDriver = 0; /* not to close it in acmStreamClose */
|
||||
|
||||
ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
|
||||
if (ret != MMSYSERR_NOERROR)
|
||||
goto errCleanUp;
|
||||
} else {
|
||||
PWINE_ACMDRIVERID wadi;
|
||||
short drv_tag;
|
||||
ret = ACMERR_NOTPOSSIBLE;
|
||||
/* if(pwfxSrc->wFormatTag==1)//compression
|
||||
drv_tag=pwfxDst->wFormatTag;
|
||||
else
|
||||
if(pwfxDst->wFormatTag==1)//decompression
|
||||
drv_tag=pwfxSrc->wFormatTag;
|
||||
else
|
||||
goto errCleanUp;
|
||||
|
||||
ret=acmDriverOpen2(drv_tag);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
if ((wad = MSACM_GetDriver(had)) != 0) {
|
||||
was->obj.pACMDriverID = wad->obj.pACMDriverID;
|
||||
was->pDrv = wad;
|
||||
was->hAcmDriver = had;
|
||||
|
||||
ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
if (fdwOpen & ACM_STREAMOPENF_QUERY) {
|
||||
acmDriverClose(had, 0L);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
acmDriverClose(had, 0L);*/
|
||||
if(MSACM_pFirstACMDriverID==NULL)
|
||||
MSACM_RegisterAllDrivers();
|
||||
|
||||
for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) {
|
||||
ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
if ((wad = MSACM_GetDriver(had)) != 0) {
|
||||
was->obj.pACMDriverID = wad->obj.pACMDriverID;
|
||||
was->pDrv = wad;
|
||||
was->hAcmDriver = had;
|
||||
|
||||
ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
if (fdwOpen & ACM_STREAMOPENF_QUERY) {
|
||||
acmDriverClose(had, 0L);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// no match, close this acm driver and try next one
|
||||
acmDriverClose(had, 0L);
|
||||
}
|
||||
}
|
||||
if (ret != MMSYSERR_NOERROR) {
|
||||
ret = ACMERR_NOTPOSSIBLE;
|
||||
goto errCleanUp;
|
||||
}
|
||||
}
|
||||
ret = MMSYSERR_NOERROR;
|
||||
if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
|
||||
if (phas)
|
||||
*phas = (HACMSTREAM)was;
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
errCleanUp:
|
||||
if (phas)
|
||||
*phas = (HACMSTREAM)0;
|
||||
HeapFree(MSACM_hHeap, 0, was);
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
MMRESULT ret;
|
||||
|
||||
TRACE("(0x%08x, %ld)\n", has, fdwClose);
|
||||
|
||||
if ((was = ACM_GetStream(has)) == NULL) {
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
}
|
||||
ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
if (was->hAcmDriver)
|
||||
acmDriverClose(was->hAcmDriver, 0L);
|
||||
HeapFree(MSACM_hHeap, 0, was);
|
||||
}
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmStreamConvert (MSACM32.38)
|
||||
*/
|
||||
MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash,
|
||||
DWORD fdwConvert)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
MMRESULT ret = MMSYSERR_NOERROR;
|
||||
PACMDRVSTREAMHEADER padsh;
|
||||
|
||||
TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwConvert);
|
||||
|
||||
if ((was = ACM_GetStream(has)) == NULL)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
||||
if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
|
||||
return ACMERR_UNPREPARED;
|
||||
|
||||
/* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
|
||||
* size. some fields are private to msacm internals, and are exposed
|
||||
* in ACMSTREAMHEADER in the dwReservedDriver array
|
||||
*/
|
||||
padsh = (PACMDRVSTREAMHEADER)pash;
|
||||
|
||||
/* check that pointers have not been modified */
|
||||
if (padsh->pbPreparedSrc != padsh->pbSrc ||
|
||||
padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
|
||||
padsh->pbPreparedDst != padsh->pbDst ||
|
||||
padsh->cbPreparedDstLength < padsh->cbDstLength) {
|
||||
return MMSYSERR_INVALPARAM;
|
||||
}
|
||||
|
||||
padsh->fdwConvert = fdwConvert;
|
||||
|
||||
ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CONVERT, (DWORD)&was->drvInst, (DWORD)padsh);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE;
|
||||
}
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* acmStreamPrepareHeader (MSACM32.41)
|
||||
*/
|
||||
MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
|
||||
DWORD fdwPrepare)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
MMRESULT ret = MMSYSERR_NOERROR;
|
||||
PACMDRVSTREAMHEADER padsh;
|
||||
|
||||
TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwPrepare);
|
||||
|
||||
if ((was = ACM_GetStream(has)) == NULL)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
|
||||
return MMSYSERR_INVALPARAM;
|
||||
if (fdwPrepare)
|
||||
ret = MMSYSERR_INVALFLAG;
|
||||
|
||||
if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
/* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
|
||||
* size. some fields are private to msacm internals, and are exposed
|
||||
* in ACMSTREAMHEADER in the dwReservedDriver array
|
||||
*/
|
||||
padsh = (PACMDRVSTREAMHEADER)pash;
|
||||
|
||||
padsh->fdwConvert = fdwPrepare;
|
||||
padsh->padshNext = NULL;
|
||||
padsh->fdwDriver = padsh->dwDriver = 0L;
|
||||
|
||||
padsh->fdwPrepared = 0;
|
||||
padsh->dwPrepared = 0;
|
||||
padsh->pbPreparedSrc = 0;
|
||||
padsh->cbPreparedSrcLength = 0;
|
||||
padsh->pbPreparedDst = 0;
|
||||
padsh->cbPreparedDstLength = 0;
|
||||
|
||||
ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_PREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
|
||||
if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
|
||||
ret = MMSYSERR_NOERROR;
|
||||
padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
|
||||
padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
|
||||
padsh->fdwPrepared = padsh->fdwStatus;
|
||||
padsh->dwPrepared = 0;
|
||||
padsh->pbPreparedSrc = padsh->pbSrc;
|
||||
padsh->cbPreparedSrcLength = padsh->cbSrcLength;
|
||||
padsh->pbPreparedDst = padsh->pbDst;
|
||||
padsh->cbPreparedDstLength = padsh->cbDstLength;
|
||||
} else {
|
||||
padsh->fdwPrepared = 0;
|
||||
padsh->dwPrepared = 0;
|
||||
padsh->pbPreparedSrc = 0;
|
||||
padsh->cbPreparedSrcLength = 0;
|
||||
padsh->pbPreparedDst = 0;
|
||||
padsh->cbPreparedDstLength = 0;
|
||||
}
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmStreamReset (MSACM32.42)
|
||||
*/
|
||||
MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
MMRESULT ret = MMSYSERR_NOERROR;
|
||||
|
||||
TRACE("(0x%08x, %ld)\n", has, fdwReset);
|
||||
|
||||
if (fdwReset) {
|
||||
ret = MMSYSERR_INVALFLAG;
|
||||
} else if ((was = ACM_GetStream(has)) == NULL) {
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
} else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
|
||||
ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_RESET, (DWORD)&was->drvInst, 0);
|
||||
}
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmStreamSize (MSACM32.43)
|
||||
*/
|
||||
MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
|
||||
LPDWORD pdwOutputBytes, DWORD fdwSize)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
ACMDRVSTREAMSIZE adss;
|
||||
MMRESULT ret;
|
||||
|
||||
TRACE("(0x%08x, %ld, %p, %ld)\n", has, cbInput, pdwOutputBytes, fdwSize);
|
||||
|
||||
if ((was = ACM_GetStream(has)) == NULL) {
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
}
|
||||
if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
|
||||
return MMSYSERR_INVALFLAG;
|
||||
}
|
||||
|
||||
*pdwOutputBytes = 0L;
|
||||
|
||||
switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
|
||||
case ACM_STREAMSIZEF_DESTINATION:
|
||||
adss.cbDstLength = cbInput;
|
||||
adss.cbSrcLength = 0;
|
||||
break;
|
||||
case ACM_STREAMSIZEF_SOURCE:
|
||||
adss.cbSrcLength = cbInput;
|
||||
adss.cbDstLength = 0;
|
||||
break;
|
||||
default:
|
||||
return MMSYSERR_INVALFLAG;
|
||||
}
|
||||
|
||||
adss.cbStruct = sizeof(adss);
|
||||
adss.fdwSize = fdwSize;
|
||||
ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_SIZE,
|
||||
(DWORD)&was->drvInst, (DWORD)&adss);
|
||||
if (ret == MMSYSERR_NOERROR) {
|
||||
switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
|
||||
case ACM_STREAMSIZEF_DESTINATION:
|
||||
*pdwOutputBytes = adss.cbSrcLength;
|
||||
break;
|
||||
case ACM_STREAMSIZEF_SOURCE:
|
||||
*pdwOutputBytes = adss.cbDstLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TRACE("=> (%d) [%lu]\n", ret, *pdwOutputBytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* acmStreamUnprepareHeader (MSACM32.44)
|
||||
*/
|
||||
MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
|
||||
DWORD fdwUnprepare)
|
||||
{
|
||||
PWINE_ACMSTREAM was;
|
||||
MMRESULT ret = MMSYSERR_NOERROR;
|
||||
PACMDRVSTREAMHEADER padsh;
|
||||
|
||||
TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwUnprepare);
|
||||
|
||||
if ((was = ACM_GetStream(has)) == NULL)
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
||||
if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
|
||||
return ACMERR_UNPREPARED;
|
||||
|
||||
/* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
|
||||
* size. some fields are private to msacm internals, and are exposed
|
||||
* in ACMSTREAMHEADER in the dwReservedDriver array
|
||||
*/
|
||||
padsh = (PACMDRVSTREAMHEADER)pash;
|
||||
|
||||
/* check that pointers have not been modified */
|
||||
if (padsh->pbPreparedSrc != padsh->pbSrc ||
|
||||
padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
|
||||
padsh->pbPreparedDst != padsh->pbDst ||
|
||||
padsh->cbPreparedDstLength < padsh->cbDstLength) {
|
||||
return MMSYSERR_INVALPARAM;
|
||||
}
|
||||
|
||||
padsh->fdwConvert = fdwUnprepare;
|
||||
|
||||
ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_UNPREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
|
||||
if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
|
||||
ret = MMSYSERR_NOERROR;
|
||||
padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
|
||||
}
|
||||
TRACE("=> (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
/****************************************************************************
|
||||
*
|
||||
* AVIFMT - AVI file format definitions
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef AVIFMT
|
||||
#define AVIFMT
|
||||
|
||||
#ifndef NOAVIFMT
|
||||
|
||||
#ifndef __WINE_WINDEF_H
|
||||
#include <wine/windef.h>
|
||||
#endif
|
||||
|
||||
#ifndef __WINE_MMSYSTEM_H
|
||||
typedef DWORD FOURCC;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4200)
|
||||
#endif
|
||||
|
||||
/* The following is a short description of the AVI file format. Please
|
||||
* see the accompanying documentation for a full explanation.
|
||||
*
|
||||
* An AVI file is the following RIFF form:
|
||||
*
|
||||
* RIFF('AVI'
|
||||
* LIST('hdrl'
|
||||
* avih(<MainAVIHeader>)
|
||||
* LIST ('strl'
|
||||
* strh(<Stream header>)
|
||||
* strf(<Stream format>)
|
||||
* ... additional header data
|
||||
* LIST('movi'
|
||||
* { LIST('rec'
|
||||
* SubChunk...
|
||||
* )
|
||||
* | SubChunk } ....
|
||||
* )
|
||||
* [ <AVIIndex> ]
|
||||
* )
|
||||
*
|
||||
* The main file header specifies how many streams are present. For
|
||||
* each one, there must be a stream header chunk and a stream format
|
||||
* chunk, enlosed in a 'strl' LIST chunk. The 'strf' chunk contains
|
||||
* type-specific format information; for a video stream, this should
|
||||
* be a BITMAPINFO structure, including palette. For an audio stream,
|
||||
* this should be a WAVEFORMAT (or PCMWAVEFORMAT) structure.
|
||||
*
|
||||
* The actual data is contained in subchunks within the 'movi' LIST
|
||||
* chunk. The first two characters of each data chunk are the
|
||||
* stream number with which that data is associated.
|
||||
*
|
||||
* Some defined chunk types:
|
||||
* Video Streams:
|
||||
* ##db: RGB DIB bits
|
||||
* ##dc: RLE8 compressed DIB bits
|
||||
* ##pc: Palette Change
|
||||
*
|
||||
* Audio Streams:
|
||||
* ##wb: waveform audio bytes
|
||||
*
|
||||
* The grouping into LIST 'rec' chunks implies only that the contents of
|
||||
* the chunk should be read into memory at the same time. This
|
||||
* grouping is used for files specifically intended to be played from
|
||||
* CD-ROM.
|
||||
*
|
||||
* The index chunk at the end of the file should contain one entry for
|
||||
* each data chunk in the file.
|
||||
*
|
||||
* Limitations for the current software:
|
||||
* Only one video stream and one audio stream are allowed.
|
||||
* The streams must start at the beginning of the file.
|
||||
*
|
||||
*
|
||||
* To register codec types please obtain a copy of the Multimedia
|
||||
* Developer Registration Kit from:
|
||||
*
|
||||
* Microsoft Corporation
|
||||
* Multimedia Systems Group
|
||||
* Product Marketing
|
||||
* One Microsoft Way
|
||||
* Redmond, WA 98052-6399
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef mmioFOURCC
|
||||
#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
|
||||
( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) | \
|
||||
( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
|
||||
#endif
|
||||
|
||||
/* Macro to make a TWOCC out of two characters */
|
||||
#ifndef aviTWOCC
|
||||
#define aviTWOCC(ch0, ch1) ((WORD)(BYTE)(ch0) | ((WORD)(BYTE)(ch1) << 8))
|
||||
#endif
|
||||
|
||||
typedef WORD TWOCC;
|
||||
|
||||
/* form types, list types, and chunk types */
|
||||
#define formtypeAVI mmioFOURCC('A', 'V', 'I', ' ')
|
||||
#define listtypeAVIHEADER mmioFOURCC('h', 'd', 'r', 'l')
|
||||
#define ckidAVIMAINHDR mmioFOURCC('a', 'v', 'i', 'h')
|
||||
#define listtypeSTREAMHEADER mmioFOURCC('s', 't', 'r', 'l')
|
||||
#define ckidSTREAMHEADER mmioFOURCC('s', 't', 'r', 'h')
|
||||
#define ckidSTREAMFORMAT mmioFOURCC('s', 't', 'r', 'f')
|
||||
#define ckidSTREAMHANDLERDATA mmioFOURCC('s', 't', 'r', 'd')
|
||||
#define ckidSTREAMNAME mmioFOURCC('s', 't', 'r', 'n')
|
||||
|
||||
#define listtypeAVIMOVIE mmioFOURCC('m', 'o', 'v', 'i')
|
||||
#define listtypeAVIRECORD mmioFOURCC('r', 'e', 'c', ' ')
|
||||
|
||||
#define ckidAVINEWINDEX mmioFOURCC('i', 'd', 'x', '1')
|
||||
|
||||
/*
|
||||
** Stream types for the <fccType> field of the stream header.
|
||||
*/
|
||||
#define streamtypeVIDEO mmioFOURCC('v', 'i', 'd', 's')
|
||||
#define streamtypeAUDIO mmioFOURCC('a', 'u', 'd', 's')
|
||||
#define streamtypeMIDI mmioFOURCC('m', 'i', 'd', 's')
|
||||
#define streamtypeTEXT mmioFOURCC('t', 'x', 't', 's')
|
||||
|
||||
/* Basic chunk types */
|
||||
#define cktypeDIBbits aviTWOCC('d', 'b')
|
||||
#define cktypeDIBcompressed aviTWOCC('d', 'c')
|
||||
#define cktypePALchange aviTWOCC('p', 'c')
|
||||
#define cktypeWAVEbytes aviTWOCC('w', 'b')
|
||||
|
||||
/* Chunk id to use for extra chunks for padding. */
|
||||
#define ckidAVIPADDING mmioFOURCC('J', 'U', 'N', 'K')
|
||||
|
||||
/*
|
||||
** Useful macros
|
||||
**
|
||||
** Warning: These are nasty macro, and MS C 6.0 compiles some of them
|
||||
** incorrectly if optimizations are on. Ack.
|
||||
*/
|
||||
|
||||
/* Macro to get stream number out of a FOURCC ckid */
|
||||
#define FromHex(n) (((n) >= 'A') ? ((n) + 10 - 'A') : ((n) - '0'))
|
||||
#define StreamFromFOURCC(fcc) ((WORD) ((FromHex(LOBYTE(LOWORD(fcc))) << 4) + \
|
||||
(FromHex(HIBYTE(LOWORD(fcc))))))
|
||||
|
||||
/* Macro to get TWOCC chunk type out of a FOURCC ckid */
|
||||
#define TWOCCFromFOURCC(fcc) HIWORD(fcc)
|
||||
|
||||
/* Macro to make a ckid for a chunk out of a TWOCC and a stream number
|
||||
** from 0-255.
|
||||
*/
|
||||
#define ToHex(n) ((BYTE) (((n) > 9) ? ((n) - 10 + 'A') : ((n) + '0')))
|
||||
#define MAKEAVICKID(tcc, stream) \
|
||||
MAKELONG((ToHex((stream) & 0x0f) << 8) | \
|
||||
(ToHex(((stream) & 0xf0) >> 4)), tcc)
|
||||
|
||||
/*
|
||||
** Main AVI File Header
|
||||
*/
|
||||
|
||||
/* flags for use in <dwFlags> in AVIFileHdr */
|
||||
#define AVIF_HASINDEX 0x00000010 // Index at end of file?
|
||||
#define AVIF_MUSTUSEINDEX 0x00000020
|
||||
#define AVIF_ISINTERLEAVED 0x00000100
|
||||
#define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
|
||||
#define AVIF_WASCAPTUREFILE 0x00010000
|
||||
#define AVIF_COPYRIGHTED 0x00020000
|
||||
|
||||
/* The AVI File Header LIST chunk should be padded to this size */
|
||||
#define AVI_HEADERSIZE 2048 // size of AVI header list
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwMicroSecPerFrame; // frame display rate (or 0L)
|
||||
DWORD dwMaxBytesPerSec; // max. transfer rate
|
||||
DWORD dwPaddingGranularity; // pad to multiples of this
|
||||
// size; normally 2K.
|
||||
DWORD dwFlags; // the ever-present flags
|
||||
DWORD dwTotalFrames; // # frames in file
|
||||
DWORD dwInitialFrames;
|
||||
DWORD dwStreams;
|
||||
DWORD dwSuggestedBufferSize;
|
||||
|
||||
DWORD dwWidth;
|
||||
DWORD dwHeight;
|
||||
|
||||
DWORD dwReserved[4];
|
||||
} MainAVIHeader;
|
||||
|
||||
/*
|
||||
** Stream header
|
||||
*/
|
||||
|
||||
#define AVISF_DISABLED 0x00000001
|
||||
|
||||
#define AVISF_VIDEO_PALCHANGES 0x00010000
|
||||
|
||||
|
||||
typedef struct {
|
||||
FOURCC fccType;
|
||||
FOURCC fccHandler;
|
||||
DWORD dwFlags; /* Contains AVITF_* flags */
|
||||
WORD wPriority;
|
||||
WORD wLanguage;
|
||||
DWORD dwInitialFrames;
|
||||
DWORD dwScale;
|
||||
DWORD dwRate; /* dwRate / dwScale == samples/second */
|
||||
DWORD dwStart;
|
||||
DWORD dwLength; /* In units above... */
|
||||
DWORD dwSuggestedBufferSize;
|
||||
DWORD dwQuality;
|
||||
DWORD dwSampleSize;
|
||||
RECT rcFrame;
|
||||
} AVIStreamHeader;
|
||||
|
||||
/* Flags for index */
|
||||
#define AVIIF_LIST 0x00000001L // chunk is a 'LIST'
|
||||
#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame.
|
||||
|
||||
#define AVIIF_NOTIME 0x00000100L // this frame doesn't take any time
|
||||
#define AVIIF_COMPUSE 0x0FFF0000L // these bits are for compressor use
|
||||
|
||||
#define FOURCC_RIFF mmioFOURCC('R', 'I', 'F', 'F')
|
||||
#define FOURCC_LIST mmioFOURCC('L', 'I', 'S', 'T')
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD ckid;
|
||||
DWORD dwFlags;
|
||||
DWORD dwChunkOffset; // Position of chunk
|
||||
DWORD dwChunkLength; // Length of chunk
|
||||
} AVIINDEXENTRY;
|
||||
|
||||
#define AVISTREAMREAD_CONVENIENT (-1L)
|
||||
|
||||
/*
|
||||
** Palette change chunk
|
||||
**
|
||||
** Used in video streams.
|
||||
*/
|
||||
#endif /* NOAVIFMT */
|
||||
#endif
|
|
@ -1,313 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <wine/driver.h>
|
||||
#include <wine/pe_image.h>
|
||||
#include <wine/winreg.h>
|
||||
#include <wine/vfw.h>
|
||||
#include <registry.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define STORE_ALL \
|
||||
__asm__ ( \
|
||||
"push %%ebx\n\t" \
|
||||
"push %%ecx\n\t" \
|
||||
"push %%edx\n\t" \
|
||||
"push %%esi\n\t" \
|
||||
"push %%edi\n\t"::)
|
||||
|
||||
#define REST_ALL \
|
||||
__asm__ ( \
|
||||
"pop %%edi\n\t" \
|
||||
"pop %%esi\n\t" \
|
||||
"pop %%edx\n\t" \
|
||||
"pop %%ecx\n\t" \
|
||||
"pop %%ebx\n\t"::)
|
||||
|
||||
|
||||
#define WIN32_PATH GST_WIN32_LIBDIR
|
||||
|
||||
typedef struct {
|
||||
UINT uDriverSignature;
|
||||
HINSTANCE hDriverModule;
|
||||
DRIVERPROC DriverProc;
|
||||
DWORD dwDriverID;
|
||||
} DRVR;
|
||||
|
||||
typedef DRVR *PDRVR;
|
||||
typedef DRVR *NPDRVR;
|
||||
typedef DRVR *LPDRVR;
|
||||
|
||||
static DWORD dwDrvID = 0;
|
||||
|
||||
LRESULT WINAPI SendDriverMessage( HDRVR hDriver, UINT message,
|
||||
LPARAM lParam1, LPARAM lParam2 )
|
||||
{
|
||||
DRVR* module=(DRVR*)hDriver;
|
||||
int result;
|
||||
#ifdef DETAILED_OUT
|
||||
printf("SendDriverMessage: driver %X, message %X, arg1 %X, arg2 %X\n", hDriver, message, lParam1, lParam2);
|
||||
#endif
|
||||
if(module==0)return -1;
|
||||
if(module->hDriverModule==0)return -1;
|
||||
if(module->DriverProc==0)return -1;
|
||||
STORE_ALL;
|
||||
result=module->DriverProc(module->dwDriverID,1,message,lParam1,lParam2);
|
||||
REST_ALL;
|
||||
#ifdef DETAILED_OUT
|
||||
printf("\t\tResult: %X\n", result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static NPDRVR DrvAlloc(HDRVR*lpDriver, LPUINT lpDrvResult)
|
||||
{
|
||||
NPDRVR npDriver;
|
||||
/* allocate and lock handle */
|
||||
if (lpDriver)
|
||||
{
|
||||
if (*lpDriver = (HDRVR) malloc(sizeof(DRVR)) )
|
||||
{
|
||||
if (npDriver = (NPDRVR) *lpDriver)
|
||||
{
|
||||
*lpDrvResult = MMSYSERR_NOERROR;
|
||||
return (npDriver);
|
||||
}
|
||||
free((NPDRVR)*lpDriver);
|
||||
}
|
||||
return (*lpDrvResult = MMSYSERR_NOMEM, (NPDRVR) 0);
|
||||
}
|
||||
return (*lpDrvResult = MMSYSERR_INVALPARAM, (NPDRVR) 0);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HMODULE handle;
|
||||
char name[64];
|
||||
int usage;
|
||||
}codec_t;
|
||||
|
||||
static codec_t avi_codecs[]={
|
||||
{0, WIN32_PATH"/divxc32.dll", 0}, //0
|
||||
{0, WIN32_PATH"/ir50_32.dll", 0},
|
||||
{0, WIN32_PATH"/ir41_32.dll", 0},
|
||||
{0, WIN32_PATH"/ir32_32.dll", 0},
|
||||
{0, WIN32_PATH"/mpg4c32.dll", 0},
|
||||
{0, WIN32_PATH"/iccvid.dll", 0}, //5
|
||||
{0, WIN32_PATH"/libvideodll.so", 0},
|
||||
{0, WIN32_PATH"/divxa32.acm", 0},
|
||||
{0, WIN32_PATH"/msadp32.acm", 0},
|
||||
{0, WIN32_PATH"/ativcr1.dll", 0},
|
||||
{0, WIN32_PATH"/ativcr2.dll", 0}, //10
|
||||
{0, WIN32_PATH"/i263_32.drv", 0},
|
||||
{0, WIN32_PATH"/l3codeca.acm", 0},
|
||||
// {0, WIN32_PATH"/atiyvu9.dll", 0},
|
||||
};
|
||||
|
||||
|
||||
static void DrvFree(HDRVR hDriver)
|
||||
{
|
||||
int i;
|
||||
if(hDriver)
|
||||
if(((DRVR*)hDriver)->hDriverModule)
|
||||
if(((DRVR*)hDriver)->DriverProc)
|
||||
(((DRVR*)hDriver)->DriverProc)(((DRVR*)hDriver)->dwDriverID, hDriver, DRV_CLOSE, 0, 0);
|
||||
if(hDriver)
|
||||
for(i=0; i<sizeof(avi_codecs)/sizeof(avi_codecs[0]); i++)
|
||||
if(avi_codecs[i].handle==((DRVR*)hDriver)->hDriverModule)
|
||||
{
|
||||
avi_codecs[i].usage--;
|
||||
if(avi_codecs[i].usage==0)
|
||||
{
|
||||
avi_codecs[i].handle=0;
|
||||
if(((DRVR*)hDriver)->hDriverModule)
|
||||
if(((DRVR*)hDriver)->DriverProc)
|
||||
(((DRVR*)hDriver)->DriverProc)(0, hDriver, DRV_FREE, 0, 0);
|
||||
FreeLibrary(((DRVR*)hDriver)->hDriverModule);
|
||||
if (hDriver)
|
||||
free((NPDRVR)hDriver);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrvClose(HDRVR hdrvr)
|
||||
{
|
||||
DrvFree(hdrvr);
|
||||
}
|
||||
|
||||
HDRVR
|
||||
//DrvOpen(LPCSTR lpszDriverName, LPCSTR lpszSectionName, LPARAM lParam2)
|
||||
DrvOpen(LPARAM lParam2)
|
||||
{
|
||||
int drv_id;
|
||||
char filename[MAX_PATH], *f;
|
||||
UINT uDrvResult;
|
||||
HDRVR hDriver;
|
||||
NPDRVR npDriver;
|
||||
char unknown[0x24];
|
||||
int seg;
|
||||
int qwe;
|
||||
int regs[10];
|
||||
|
||||
int fccHandler=*((int*)lParam2+2);
|
||||
int fccType=*((int*)lParam2+1);
|
||||
if(fccType==0x63646976)//vidc
|
||||
switch(fccHandler)
|
||||
{
|
||||
case mmioFOURCC('D', 'I', 'V', '3'):
|
||||
case mmioFOURCC('D', 'I', 'V', '4'):
|
||||
case mmioFOURCC('d', 'i', 'v', '3'):
|
||||
case mmioFOURCC('d', 'i', 'v', '4'):
|
||||
case mmioFOURCC('M', 'P', '4', '1'):
|
||||
case mmioFOURCC('M', 'P', '4', '2'):
|
||||
case mmioFOURCC('M', 'P', '4', '3'):
|
||||
printf("Video in DivX ;-) format\n");
|
||||
drv_id=0;
|
||||
break;
|
||||
case mmioFOURCC('I', 'V', '5', '0'):
|
||||
case mmioFOURCC('i', 'v', '5', '0'):
|
||||
printf("Video in Indeo Video 5 format\n");
|
||||
drv_id=1;
|
||||
break;
|
||||
case mmioFOURCC('I', 'V', '4', '1'):
|
||||
case mmioFOURCC('i', 'v', '4', '1'):
|
||||
printf("Video in Indeo Video 4.1 format\n");
|
||||
drv_id=2;
|
||||
break;
|
||||
case mmioFOURCC('I', 'V', '3', '2'):
|
||||
case mmioFOURCC('i', 'v', '3', '2'):
|
||||
printf("Video in Indeo Video 3.2 format\n");
|
||||
drv_id=3;
|
||||
break;
|
||||
|
||||
case mmioFOURCC('m', 'p', '4', '1'):
|
||||
case mmioFOURCC('m', 'p', '4', '2'):
|
||||
case mmioFOURCC('m', 'p', '4', '3'):
|
||||
case mmioFOURCC('M', 'P', 'G', '4'):
|
||||
printf("Video in Microsoft MPEG-4 format\n");
|
||||
drv_id=4;
|
||||
break;
|
||||
case mmioFOURCC('c', 'v', 'i', 'd'):
|
||||
printf("Video in Cinepak format\n");
|
||||
drv_id=5;
|
||||
break;
|
||||
case mmioFOURCC('V', 'C', 'R', '1'):
|
||||
drv_id=9;
|
||||
break;
|
||||
case mmioFOURCC('V', 'C', 'R', '2'):
|
||||
drv_id=10;
|
||||
break;
|
||||
case mmioFOURCC('i', '2', '6', '3'):
|
||||
case mmioFOURCC('I', '2', '6', '3'):
|
||||
drv_id=11;
|
||||
break;
|
||||
// case mmioFOURCC('Y', 'V', 'U', '9'):
|
||||
// drv_id=12;
|
||||
// break;
|
||||
default:
|
||||
printf("Unknown codec %X='%c%c%c%c'\n", fccHandler,
|
||||
fccHandler&0xFF, (fccHandler&0xFF00)>>8,
|
||||
(fccHandler&0xFF0000)>>16, (fccHandler&0xFF000000)>>24);
|
||||
return (HDRVR)0;
|
||||
}
|
||||
else
|
||||
switch(fccHandler)
|
||||
{
|
||||
case 0x160://DivX audio
|
||||
case 0x161://DivX audio
|
||||
drv_id=7;
|
||||
break;
|
||||
case 0x2://MS ADPCM
|
||||
drv_id=8;
|
||||
break;
|
||||
case 0x55://MPEG Layer 3
|
||||
printf("MPEG Layer 3 ( 0x55 )\n");
|
||||
drv_id=12;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown ACM codec 0x%X\n", fccHandler);
|
||||
return (HDRVR)0;
|
||||
}
|
||||
|
||||
if (!(npDriver = DrvAlloc(&hDriver, &uDrvResult)))
|
||||
return ((HDRVR) 0);
|
||||
|
||||
if(avi_codecs[drv_id].handle==0)
|
||||
{
|
||||
if (!(avi_codecs[drv_id].handle=npDriver->hDriverModule = LoadLibraryA(avi_codecs[drv_id].name)))
|
||||
{
|
||||
printf("Can't open library %s\n", avi_codecs[drv_id].name);
|
||||
DrvFree(hDriver);
|
||||
return ((HDRVR) 0);
|
||||
}
|
||||
else avi_codecs[drv_id].usage=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
npDriver->hDriverModule=avi_codecs[drv_id].handle;
|
||||
avi_codecs[drv_id].usage++;
|
||||
}
|
||||
|
||||
// 14c0
|
||||
if(drv_id==0)
|
||||
{
|
||||
int newkey;
|
||||
int bitrate;
|
||||
int count=4;
|
||||
if(RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\LinuxLoader\\Divx", 0, 0, &newkey)!=0)
|
||||
goto no_reg;
|
||||
if(RegQueryValueExA(newkey, "BitRate", 0, 0, &bitrate, &count)!=0)
|
||||
{
|
||||
RegCloseKey(newkey);
|
||||
goto no_reg;
|
||||
}
|
||||
// printf("Setting default bitrate from %f to %d\n",
|
||||
// *(double*)((char*)npDriver->hDriverModule+0x14c0), bitrate);
|
||||
|
||||
*(double*)((char*)npDriver->hDriverModule+0x14c0)=bitrate;
|
||||
RegCloseKey(newkey);
|
||||
no_reg:
|
||||
;
|
||||
}
|
||||
|
||||
if (!(npDriver->DriverProc = (DRIVERPROC)
|
||||
GetProcAddress(npDriver->hDriverModule, "DriverProc")))
|
||||
{
|
||||
printf("Library %s is not a valid codec\n", avi_codecs[drv_id].name);
|
||||
FreeLibrary(npDriver->hDriverModule);
|
||||
DrvFree(hDriver);
|
||||
return ((HDRVR) 0);
|
||||
}
|
||||
|
||||
TRACE("DriverProc == %X\n", npDriver->DriverProc);
|
||||
npDriver->dwDriverID = ++dwDrvID;
|
||||
|
||||
if (avi_codecs[drv_id].usage==1)
|
||||
{
|
||||
STORE_ALL;
|
||||
(npDriver->DriverProc)(0, hDriver, DRV_LOAD, 0, 0);
|
||||
REST_ALL;
|
||||
TRACE("DRV_LOAD Ok!\n");
|
||||
STORE_ALL;
|
||||
(npDriver->DriverProc)(0, hDriver, DRV_ENABLE, 0, 0);
|
||||
REST_ALL;
|
||||
TRACE("DRV_ENABLE Ok!\n");
|
||||
}
|
||||
|
||||
// open driver
|
||||
STORE_ALL;
|
||||
npDriver->dwDriverID=(npDriver->DriverProc)(npDriver->dwDriverID, hDriver, DRV_OPEN,
|
||||
(LPARAM) (LPSTR) unknown, lParam2);
|
||||
REST_ALL;
|
||||
|
||||
TRACE("DRV_OPEN Ok!(%X)\n", npDriver->dwDriverID);
|
||||
|
||||
if (uDrvResult)
|
||||
{
|
||||
DrvFree(hDriver);
|
||||
hDriver = (HDRVR) 0;
|
||||
}
|
||||
return (hDriver);
|
||||
}
|
||||
|
|
@ -1,304 +0,0 @@
|
|||
/*
|
||||
* Elf-dll loader functions
|
||||
*
|
||||
* Copyright 1999 Bertho A. Stultiens
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wine/config.h>
|
||||
#include <wine/windef.h>
|
||||
//#include <wine/global.h>
|
||||
//#include <wine/process.h>
|
||||
#include <wine/module.h>
|
||||
#include <wine/heap.h>
|
||||
#include <wine/elfdll.h>
|
||||
#include <wine/debugtools.h>
|
||||
#include <wine/winerror.h>
|
||||
|
||||
//DEFAULT_DEBUG_CHANNEL(elfdll)
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
struct modref_list_t;
|
||||
|
||||
typedef struct modref_list_t
|
||||
{
|
||||
WINE_MODREF* wm;
|
||||
struct modref_list_t *next;
|
||||
struct modref_list_t *prev;
|
||||
}
|
||||
modref_list;
|
||||
|
||||
|
||||
//WINE_MODREF *local_wm=NULL;
|
||||
extern modref_list* local_wm;
|
||||
|
||||
|
||||
/*------------------ HACKS -----------------*/
|
||||
extern DWORD fixup_imports(WINE_MODREF *wm);
|
||||
extern void dump_exports(HMODULE hModule);
|
||||
/*---------------- END HACKS ---------------*/
|
||||
|
||||
char *extra_ld_library_path = "/usr/lib/win32";
|
||||
|
||||
struct elfdll_image
|
||||
{
|
||||
HMODULE pe_module_start;
|
||||
DWORD pe_module_size;
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* ELFDLL_dlopen
|
||||
*
|
||||
* Wrapper for dlopen to search the EXTRA_LD_LIBRARY_PATH from wine.conf
|
||||
* manually because libdl.so caches the environment and does not accept our
|
||||
* changes.
|
||||
*/
|
||||
void *ELFDLL_dlopen(const char *libname, int flags)
|
||||
{
|
||||
char buffer[256];
|
||||
int namelen;
|
||||
void *handle;
|
||||
char *ldpath;
|
||||
|
||||
/* First try the default path search of dlopen() */
|
||||
handle = dlopen(libname, flags);
|
||||
if(handle)
|
||||
return handle;
|
||||
|
||||
/* Now try to construct searches through our extra search-path */
|
||||
namelen = strlen(libname);
|
||||
ldpath = extra_ld_library_path;
|
||||
while(ldpath && *ldpath)
|
||||
{
|
||||
int len;
|
||||
char *cptr;
|
||||
char *from;
|
||||
|
||||
from = ldpath;
|
||||
cptr = strchr(ldpath, ':');
|
||||
if(!cptr)
|
||||
{
|
||||
len = strlen(ldpath);
|
||||
ldpath = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = cptr - ldpath;
|
||||
ldpath = cptr + 1;
|
||||
}
|
||||
|
||||
if(len + namelen + 1 >= sizeof(buffer))
|
||||
{
|
||||
ERR("Buffer overflow! Check EXTRA_LD_LIBRARY_PATH or increase buffer size.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(buffer, from, len);
|
||||
if(len)
|
||||
{
|
||||
buffer[len] = '/';
|
||||
strcpy(buffer + len + 1, libname);
|
||||
}
|
||||
else
|
||||
strcpy(buffer + len, libname);
|
||||
|
||||
TRACE("Trying dlopen('%s', %d)\n", buffer, flags);
|
||||
|
||||
handle = dlopen(buffer, flags);
|
||||
if(handle)
|
||||
return handle;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* get_sobasename (internal)
|
||||
*
|
||||
*/
|
||||
static LPSTR get_sobasename(LPCSTR path, LPSTR name)
|
||||
{
|
||||
char *cptr;
|
||||
|
||||
/* Strip the path from the library name */
|
||||
if((cptr = strrchr(path, '/')))
|
||||
{
|
||||
char *cp = strrchr(cptr+1, '\\');
|
||||
if(cp && cp > cptr)
|
||||
cptr = cp;
|
||||
}
|
||||
else
|
||||
cptr = strrchr(path, '\\');
|
||||
|
||||
if(!cptr)
|
||||
cptr = (char *)path; /* No '/' nor '\\' in path */
|
||||
else
|
||||
cptr++;
|
||||
|
||||
strcpy(name, cptr);
|
||||
cptr = strrchr(name, '.');
|
||||
if(cptr)
|
||||
*cptr = '\0'; /* Strip extension */
|
||||
|
||||
/* Convert to lower case.
|
||||
* This must be done manually because it is not sure that
|
||||
* other modules are accessible.
|
||||
*/
|
||||
for(cptr = name; *cptr; cptr++)
|
||||
*cptr = tolower(*cptr);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* ELFDLL_CreateModref (internal)
|
||||
*
|
||||
* INPUT
|
||||
* hModule - the header from the elf-dll's data-segment
|
||||
* path - requested path from original call
|
||||
*
|
||||
* OUTPUT
|
||||
* A WINE_MODREF pointer to the new object
|
||||
*
|
||||
* BUGS
|
||||
* - Does not handle errors due to dependencies correctly
|
||||
* - path can be wrong
|
||||
*/
|
||||
#define RVA(base, va) (((DWORD)base) + ((DWORD)va))
|
||||
|
||||
static WINE_MODREF *ELFDLL_CreateModref(HMODULE hModule, LPCSTR path)
|
||||
{
|
||||
// IMAGE_NT_HEADERS *nt = PE_HEADER(hModule);
|
||||
IMAGE_DATA_DIRECTORY *dir;
|
||||
IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL;
|
||||
WINE_MODREF *wm;
|
||||
int len;
|
||||
HANDLE procheap = GetProcessHeap();
|
||||
|
||||
wm = (WINE_MODREF *)HeapAlloc(procheap, HEAP_ZERO_MEMORY, sizeof(*wm));
|
||||
if(!wm)
|
||||
return NULL;
|
||||
|
||||
wm->module = hModule;
|
||||
wm->type = MODULE32_ELF; /* FIXME */
|
||||
|
||||
// dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
|
||||
// if(dir->Size)
|
||||
// wm->binfmt.pe.pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(hModule, dir->VirtualAddress);
|
||||
|
||||
// dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT;
|
||||
// if(dir->Size)
|
||||
// pe_import = wm->binfmt.pe.pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(hModule, dir->VirtualAddress);
|
||||
|
||||
// dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE;
|
||||
// if(dir->Size)
|
||||
// wm->binfmt.pe.pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(hModule, dir->VirtualAddress);
|
||||
|
||||
|
||||
wm->filename = malloc(strlen(path)+1);
|
||||
strcpy(wm->filename, path);
|
||||
wm->modname = strrchr( wm->filename, '\\' );
|
||||
if (!wm->modname) wm->modname = wm->filename;
|
||||
else wm->modname++;
|
||||
/*
|
||||
len = GetShortPathNameA( wm->filename, NULL, 0 );
|
||||
wm->short_filename = (char *)HeapAlloc( procheap, 0, len+1 );
|
||||
GetShortPathNameA( wm->filename, wm->short_filename, len+1 );
|
||||
wm->short_modname = strrchr( wm->short_filename, '\\' );
|
||||
if (!wm->short_modname) wm->short_modname = wm->short_filename;
|
||||
else wm->short_modname++;
|
||||
*/
|
||||
/* Link MODREF into process list */
|
||||
|
||||
// EnterCriticalSection( &PROCESS_Current()->crit_section );
|
||||
|
||||
if(local_wm)
|
||||
{
|
||||
local_wm->next=malloc(sizeof(modref_list));
|
||||
local_wm->next->prev=local_wm;
|
||||
local_wm->next->next=NULL;
|
||||
local_wm->next->wm=wm;
|
||||
local_wm=local_wm->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
local_wm=malloc(sizeof(modref_list));
|
||||
local_wm->next=local_wm->prev=NULL;
|
||||
local_wm->wm=wm;
|
||||
}
|
||||
|
||||
// LeaveCriticalSection( &PROCESS_Current()->crit_section );
|
||||
return wm;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ELFDLL_LoadLibraryExA (internal)
|
||||
*
|
||||
* Implementation of elf-dll loading for PE modules
|
||||
*/
|
||||
WINE_MODREF *ELFDLL_LoadLibraryExA(LPCSTR path, DWORD flags)
|
||||
{
|
||||
LPVOID dlhandle;
|
||||
struct elfdll_image *image;
|
||||
char name[129];
|
||||
char soname[129];
|
||||
WINE_MODREF *wm;
|
||||
|
||||
get_sobasename(path, name);
|
||||
strcpy(soname, name);
|
||||
strcat(soname, ".so");
|
||||
|
||||
/* Try to open the elf-dll */
|
||||
dlhandle = ELFDLL_dlopen(soname, RTLD_LAZY);
|
||||
if(!dlhandle)
|
||||
{
|
||||
WARN("Could not load %s (%s)\n", soname, dlerror());
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the 'dllname_elfdll_image' variable */
|
||||
/* strcpy(soname, name);
|
||||
strcat(soname, "_elfdll_image");
|
||||
image = (struct elfdll_image *)dlsym(dlhandle, soname);
|
||||
if(!image)
|
||||
{
|
||||
ERR("Could not get elfdll image descriptor %s (%s)\n", soname, dlerror());
|
||||
dlclose(dlhandle);
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*/
|
||||
wm = ELFDLL_CreateModref((int)dlhandle, path);
|
||||
if(!wm)
|
||||
{
|
||||
ERR("Could not create WINE_MODREF for %s\n", path);
|
||||
dlclose(dlhandle);
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wm;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* ELFDLL_UnloadLibrary (internal)
|
||||
*
|
||||
* Unload an elf-dll completely from memory and deallocate the modref
|
||||
*/
|
||||
void ELFDLL_UnloadLibrary(WINE_MODREF *wm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /*HAVE_LIBDL*/
|
|
@ -1,554 +0,0 @@
|
|||
/********************************************************
|
||||
*
|
||||
*
|
||||
* Stub functions for Wine module
|
||||
*
|
||||
*
|
||||
********************************************************/
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <wine/windef.h>
|
||||
//#include <wine/winbase.h>
|
||||
int dbg_header_err( const char *dbg_channel, const char *func )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int dbg_header_warn( const char *dbg_channel, const char *func )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int dbg_header_fixme( const char *dbg_channel, const char *func )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int dbg_header_trace( const char *dbg_channel, const char *func )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int dbg_vprintf( const char *format, ... )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int __vprintf( const char *format, ... )
|
||||
{
|
||||
#ifdef DETAILED_OUT
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vprintf(format, va);
|
||||
va_end(va);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetProcessHeap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* HeapAlloc(int heap, int flags, int size)
|
||||
{
|
||||
if(flags & 0x8)
|
||||
return calloc(size, 1);
|
||||
else
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
int HeapFree(int heap, int flags, void* mem)
|
||||
{
|
||||
free(mem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int last_error;
|
||||
|
||||
int GetLastError()
|
||||
{
|
||||
return last_error;
|
||||
}
|
||||
|
||||
int SetLastError(int error)
|
||||
{
|
||||
return last_error=error;
|
||||
}
|
||||
|
||||
int ReadFile(int handle, void* mem, unsigned long size, long* result, long flags)
|
||||
{
|
||||
*result=read(handle, mem, size);
|
||||
return *result;
|
||||
}
|
||||
int lstrcmpiA(const char* c1, const char* c2)
|
||||
{
|
||||
return strcasecmp(c1,c2);
|
||||
}
|
||||
int lstrcpynA(char* dest, const char* src, int num)
|
||||
{
|
||||
return strncmp(dest,src,num);
|
||||
}
|
||||
int lstrlenA(const char* s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
int lstrlenW(const short* s)
|
||||
{
|
||||
int l;
|
||||
if(!s)
|
||||
return 0;
|
||||
l=0;
|
||||
while(s[l])
|
||||
l++;
|
||||
return l;
|
||||
}
|
||||
int lstrcpynWtoA(char* dest, const char* src, int count)
|
||||
{
|
||||
int moved=0;
|
||||
if((dest==0) || (src==0))
|
||||
return 0;
|
||||
while(moved<count)
|
||||
{
|
||||
*dest=*src;
|
||||
moved++;
|
||||
if(*src==0)
|
||||
return moved;
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
int wcsnicmp(const unsigned short* s1, const unsigned short* s2, int n)
|
||||
{
|
||||
if(s1==0)
|
||||
return;
|
||||
if(s2==0)
|
||||
return;
|
||||
while(n>0)
|
||||
{
|
||||
if(*s1<*s2)
|
||||
return -1;
|
||||
else
|
||||
if(*s1>*s2)
|
||||
return 1;
|
||||
else
|
||||
if(*s1==0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
n--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int IsBadReadPtr(void* data, int size)
|
||||
{
|
||||
if(size==0)
|
||||
return 0;
|
||||
if(data==NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
char* HEAP_strdupA(const char* string)
|
||||
{
|
||||
// return strdup(string);
|
||||
char* answ=malloc(strlen(string)+1);
|
||||
strcpy(answ, string);
|
||||
return answ;
|
||||
}
|
||||
short* HEAP_strdupAtoW(void* heap, void* hz, const char* string)
|
||||
{
|
||||
int size, i;
|
||||
short* answer;
|
||||
if(string==0)
|
||||
return 0;
|
||||
size=strlen(string);
|
||||
answer=malloc(size+size+2);
|
||||
for(i=0; i<=size; i++)
|
||||
answer[i]=(short)string[i];
|
||||
return answer;
|
||||
}
|
||||
char* HEAP_strdupWtoA(void* heap, void* hz, const short* string)
|
||||
{
|
||||
int size, i;
|
||||
char* answer;
|
||||
if(string==0)
|
||||
return 0;
|
||||
size=0;
|
||||
while(string[size])
|
||||
size++;
|
||||
answer=malloc(size+2);
|
||||
for(i=0; i<=size; i++)
|
||||
answer[i]=(char)string[i];
|
||||
return answer;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_dommap
|
||||
*/
|
||||
|
||||
//#define MAP_PRIVATE
|
||||
//#define MAP_SHARED
|
||||
#undef MAP_ANON
|
||||
LPVOID FILE_dommap( int unix_handle, LPVOID start,
|
||||
DWORD size_high, DWORD size_low,
|
||||
DWORD offset_high, DWORD offset_low,
|
||||
int prot, int flags )
|
||||
{
|
||||
int fd = -1;
|
||||
int pos;
|
||||
LPVOID ret;
|
||||
|
||||
if (size_high || offset_high)
|
||||
printf("offsets larger than 4Gb not supported\n");
|
||||
|
||||
if (unix_handle == -1)
|
||||
{
|
||||
#ifdef MAP_ANON
|
||||
// printf("Anonymous\n");
|
||||
flags |= MAP_ANON;
|
||||
#else
|
||||
static int fdzero = -1;
|
||||
|
||||
if (fdzero == -1)
|
||||
{
|
||||
if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
|
||||
{
|
||||
perror( "/dev/zero: open" );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
fd = fdzero;
|
||||
#endif /* MAP_ANON */
|
||||
/* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
|
||||
#ifdef MAP_SHARED
|
||||
flags &= ~MAP_SHARED;
|
||||
#endif
|
||||
#ifdef MAP_PRIVATE
|
||||
flags |= MAP_PRIVATE;
|
||||
#endif
|
||||
}
|
||||
else fd = unix_handle;
|
||||
// printf("fd %x, start %x, size %x, pos %x, prot %x\n",fd,start,size_low, offset_low, prot);
|
||||
// if ((ret = mmap( start, size_low, prot,
|
||||
// flags, fd, offset_low )) != (LPVOID)-1)
|
||||
if ((ret = mmap( start, size_low, prot,
|
||||
MAP_PRIVATE | MAP_FIXED, fd, offset_low )) != (LPVOID)-1)
|
||||
{
|
||||
// printf("address %08x\n", *(int*)ret);
|
||||
// printf("%x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// printf("mmap %d\n", errno);
|
||||
|
||||
/* mmap() failed; if this is because the file offset is not */
|
||||
/* page-aligned (EINVAL), or because the underlying filesystem */
|
||||
/* does not support mmap() (ENOEXEC), we do it by hand. */
|
||||
|
||||
if (unix_handle == -1) return ret;
|
||||
if ((errno != ENOEXEC) && (errno != EINVAL)) return ret;
|
||||
if (prot & PROT_WRITE)
|
||||
{
|
||||
/* We cannot fake shared write mappings */
|
||||
#ifdef MAP_SHARED
|
||||
if (flags & MAP_SHARED) return ret;
|
||||
#endif
|
||||
#ifdef MAP_PRIVATE
|
||||
if (!(flags & MAP_PRIVATE)) return ret;
|
||||
#endif
|
||||
}
|
||||
/* printf( "FILE_mmap: mmap failed (%d), faking it\n", errno );*/
|
||||
/* Reserve the memory with an anonymous mmap */
|
||||
ret = FILE_dommap( -1, start, size_high, size_low, 0, 0,
|
||||
PROT_READ | PROT_WRITE, flags );
|
||||
if (ret == (LPVOID)-1)
|
||||
// {
|
||||
// perror(
|
||||
return ret;
|
||||
/* Now read in the file */
|
||||
if ((pos = lseek( fd, offset_low, SEEK_SET )) == -1)
|
||||
{
|
||||
FILE_munmap( ret, size_high, size_low );
|
||||
// printf("lseek\n");
|
||||
return (LPVOID)-1;
|
||||
}
|
||||
read( fd, ret, size_low );
|
||||
lseek( fd, pos, SEEK_SET ); /* Restore the file pointer */
|
||||
mprotect( ret, size_low, prot ); /* Set the right protection */
|
||||
// printf("address %08x\n", *(int*)ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FILE_munmap
|
||||
*/
|
||||
int FILE_munmap( LPVOID start, DWORD size_high, DWORD size_low )
|
||||
{
|
||||
if (size_high)
|
||||
printf("offsets larger than 4Gb not supported\n");
|
||||
return munmap( start, size_low );
|
||||
}
|
||||
static int mapping_size=0;
|
||||
|
||||
struct file_mapping_s;
|
||||
typedef struct file_mapping_s
|
||||
{
|
||||
int mapping_size;
|
||||
char* name;
|
||||
HANDLE handle;
|
||||
struct file_mapping_s* next;
|
||||
struct file_mapping_s* prev;
|
||||
}file_mapping;
|
||||
static file_mapping* fm=0;
|
||||
|
||||
|
||||
|
||||
#define PAGE_NOACCESS 0x01
|
||||
#define PAGE_READONLY 0x02
|
||||
#define PAGE_READWRITE 0x04
|
||||
#define PAGE_WRITECOPY 0x08
|
||||
#define PAGE_EXECUTE 0x10
|
||||
#define PAGE_EXECUTE_READ 0x20
|
||||
#define PAGE_EXECUTE_READWRITE 0x40
|
||||
#define PAGE_EXECUTE_WRITECOPY 0x80
|
||||
#define PAGE_GUARD 0x100
|
||||
#define PAGE_NOCACHE 0x200
|
||||
|
||||
HANDLE CreateFileMappingA(int hFile, void* lpAttr,
|
||||
DWORD flProtect, DWORD dwMaxHigh, DWORD dwMaxLow, const char* name)
|
||||
{
|
||||
unsigned int len;
|
||||
HANDLE answer;
|
||||
int anon=0;
|
||||
int mmap_access=0;
|
||||
if(hFile<0)
|
||||
{
|
||||
anon=1;
|
||||
hFile=open("/dev/zero", O_RDWR);
|
||||
if(hFile<0)
|
||||
return 0;
|
||||
}
|
||||
if(!anon)
|
||||
{
|
||||
len=lseek(hFile, 0, SEEK_END);
|
||||
lseek(hFile, 0, SEEK_SET);
|
||||
}
|
||||
else len=dwMaxLow;
|
||||
|
||||
if(flProtect & PAGE_READONLY)
|
||||
mmap_access |=PROT_READ;
|
||||
else
|
||||
mmap_access |=PROT_READ|PROT_WRITE;
|
||||
|
||||
answer=(HANDLE)mmap(NULL, len, mmap_access, MAP_PRIVATE, hFile, 0);
|
||||
if(anon)
|
||||
close(hFile);
|
||||
if(answer!=(HANDLE)-1)
|
||||
{
|
||||
if(fm==0)
|
||||
{
|
||||
fm=malloc(sizeof(file_mapping));
|
||||
fm->prev=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fm->next=malloc(sizeof(file_mapping));
|
||||
fm->next->prev=fm;
|
||||
fm=fm->next;
|
||||
}
|
||||
fm->next=NULL;
|
||||
fm->handle=answer;
|
||||
if(name)
|
||||
{
|
||||
fm->name=malloc(strlen(name)+1);
|
||||
strcpy(fm->name, name);
|
||||
}
|
||||
else
|
||||
fm->name=NULL;
|
||||
fm->mapping_size=len;
|
||||
|
||||
if(anon)
|
||||
close(hFile);
|
||||
return answer;
|
||||
}
|
||||
return (HANDLE)0;
|
||||
}
|
||||
int UnmapViewOfFile(HANDLE handle)
|
||||
{
|
||||
file_mapping* p;
|
||||
int result;
|
||||
if(fm==0)
|
||||
return (HANDLE)0;
|
||||
for(p=fm; p; p=p->next)
|
||||
{
|
||||
if(p->handle==handle)
|
||||
{
|
||||
result=munmap((void*)handle, p->mapping_size);
|
||||
if(p->next)p->next->prev=p->prev;
|
||||
if(p->prev)p->prev->next=p->next;
|
||||
if(p->name)
|
||||
free(p->name);
|
||||
if(p==fm)
|
||||
fm=p->prev;
|
||||
free(p);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//static int va_size=0;
|
||||
struct virt_alloc_s;
|
||||
typedef struct virt_alloc_s
|
||||
{
|
||||
int mapping_size;
|
||||
char* address;
|
||||
struct virt_alloc_s* next;
|
||||
struct virt_alloc_s* prev;
|
||||
int state;
|
||||
}virt_alloc;
|
||||
static virt_alloc* vm=0;
|
||||
#define MEM_COMMIT 0x00001000
|
||||
#define MEM_RESERVE 0x00002000
|
||||
|
||||
void* VirtualAlloc(void* address, DWORD size, DWORD type, DWORD protection)
|
||||
{
|
||||
void* answer;
|
||||
int fd=open("/dev/zero", O_RDWR);
|
||||
size=(size+0xffff)&(~0xffff);
|
||||
// printf("VirtualAlloc(0x%08X, %d)\n", address
|
||||
if(address!=0)
|
||||
{
|
||||
//check whether we can allow to allocate this
|
||||
virt_alloc* str=vm;
|
||||
while(str)
|
||||
{
|
||||
if((unsigned)address>=(unsigned)str->address+str->mapping_size)
|
||||
{
|
||||
str=str->prev;
|
||||
continue;
|
||||
}
|
||||
if((unsigned)address+size<(unsigned)str->address)
|
||||
{
|
||||
str=str->prev;
|
||||
continue;
|
||||
}
|
||||
if(str->state==0)
|
||||
{
|
||||
#warning FIXME
|
||||
if(((unsigned)address+size<(unsigned)str->address+str->mapping_size) && (type & MEM_COMMIT))
|
||||
{
|
||||
close(fd);
|
||||
return address; //returning previously reserved memory
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
answer=mmap(address, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE, fd, 0);
|
||||
}
|
||||
else
|
||||
answer=mmap(address, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
// answer=FILE_dommap(-1, address, 0, size, 0, 0,
|
||||
// PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
|
||||
close(fd);
|
||||
if(answer==(void*)-1)
|
||||
{
|
||||
printf("Error no %d\n", errno);
|
||||
printf("VirtualAlloc(0x%08X, %d) failed\n", address, size);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
virt_alloc *new_vm=malloc(sizeof(virt_alloc));
|
||||
new_vm->mapping_size=size;
|
||||
new_vm->address=answer;
|
||||
new_vm->prev=vm;
|
||||
if(type & MEM_RESERVE)
|
||||
new_vm->state=0;
|
||||
else
|
||||
new_vm->state=1;
|
||||
if(vm)
|
||||
vm->next=new_vm;
|
||||
vm=new_vm;
|
||||
vm->next=0;
|
||||
// if(va_size!=0)
|
||||
// printf("Multiple VirtualAlloc!\n");
|
||||
// printf("answer=0x%08x\n", answer);
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
int VirtualFree(void* address, int t1, int t2)//not sure
|
||||
{
|
||||
virt_alloc* str=vm;
|
||||
int answer;
|
||||
while(str)
|
||||
{
|
||||
if(address!=str->address)
|
||||
{
|
||||
str=str->prev;
|
||||
continue;
|
||||
}
|
||||
answer=munmap(str->address, str->mapping_size);
|
||||
if(str->next)str->next->prev=str->prev;
|
||||
if(str->prev)str->prev->next=str->next;
|
||||
if(vm==str)vm=0;
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WideCharToMultiByte(unsigned int codepage, long flags, const short* src,
|
||||
int srclen,char* dest, int destlen, const char* defch, int* used_defch)
|
||||
{
|
||||
int i;
|
||||
if(src==0)
|
||||
return 0;
|
||||
if(dest==0)
|
||||
{
|
||||
for(i=0; i<srclen; i++)
|
||||
{
|
||||
src++;
|
||||
if(*src==0)
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
if(used_defch)
|
||||
*used_defch=0;
|
||||
for(i=0; i<min(srclen, destlen); i++)
|
||||
{
|
||||
*dest=(char)*src;
|
||||
dest++;
|
||||
src++;
|
||||
if(*dest==0)
|
||||
return i+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int MultiByteToWideChar(unsigned int codepage,long flags, const char* src, int srclen,
|
||||
short* dest, int destlen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
HANDLE OpenFileMappingA(long access, long prot, char* name)
|
||||
{
|
||||
file_mapping* p;
|
||||
if(fm==0)
|
||||
return (HANDLE)0;
|
||||
if(name==0)
|
||||
return (HANDLE)0;
|
||||
for(p=fm; p; p=p->prev)
|
||||
{
|
||||
if(p->name==0)
|
||||
continue;
|
||||
if(strcmp(p->name, name)==0)
|
||||
return p->handle;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,617 +0,0 @@
|
|||
/*
|
||||
* Modules
|
||||
*
|
||||
* Copyright 1995 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
/*
|
||||
#ifdef __linux__
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ldt.h>
|
||||
#else
|
||||
#define LDT_ENTRIES 8192
|
||||
#define LDT_ENTRY_SIZE 8
|
||||
|
||||
struct modify_ldt_ldt_s {
|
||||
unsigned int entry_number;
|
||||
unsigned long base_addr;
|
||||
unsigned int limit;
|
||||
unsigned int seg_32bit:1;
|
||||
unsigned int contents:2;
|
||||
unsigned int read_exec_only:1;
|
||||
unsigned int limit_in_pages:1;
|
||||
unsigned int seg_not_present:1;
|
||||
unsigned int useable:1;
|
||||
};
|
||||
|
||||
#define MODIFY_LDT_CONTENTS_DATA 0
|
||||
#define MODIFY_LDT_CONTENTS_STACK 1
|
||||
#define MODIFY_LDT_CONTENTS_CODE 2
|
||||
#define __NR_modify_ldt 123
|
||||
#endif
|
||||
|
||||
*/
|
||||
#include <wine/windef.h>
|
||||
#include <wine/winerror.h>
|
||||
#include <wine/heap.h>
|
||||
#include <wine/module.h>
|
||||
#include <wine/pe_image.h>
|
||||
#include <wine/debugtools.h>
|
||||
|
||||
struct modref_list_t;
|
||||
|
||||
typedef struct modref_list_t
|
||||
{
|
||||
WINE_MODREF* wm;
|
||||
struct modref_list_t *next;
|
||||
struct modref_list_t *prev;
|
||||
}
|
||||
modref_list;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LDT_EntryToBytes
|
||||
*
|
||||
* Convert an ldt_entry structure to the raw bytes of the descriptor.
|
||||
*/
|
||||
/*static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content )
|
||||
{
|
||||
*buffer++ = ((content->base_addr & 0x0000ffff) << 16) |
|
||||
(content->limit & 0x0ffff);
|
||||
*buffer = (content->base_addr & 0xff000000) |
|
||||
((content->base_addr & 0x00ff0000)>>16) |
|
||||
(content->limit & 0xf0000) |
|
||||
(content->contents << 10) |
|
||||
((content->read_exec_only == 0) << 9) |
|
||||
((content->seg_32bit != 0) << 22) |
|
||||
((content->limit_in_pages != 0) << 23) |
|
||||
0xf000;
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// funcs:
|
||||
//
|
||||
// 0 read LDT
|
||||
// 1 write old mode
|
||||
// 0x11 write
|
||||
//
|
||||
/*
|
||||
static int modify_ldt( int func, struct modify_ldt_ldt_s *ptr,
|
||||
unsigned long count )
|
||||
{
|
||||
int res;
|
||||
#ifdef __PIC__
|
||||
__asm__ __volatile__( "pushl %%ebx\n\t"
|
||||
"movl %2,%%ebx\n\t"
|
||||
"int $0x80\n\t"
|
||||
"popl %%ebx"
|
||||
: "=a" (res)
|
||||
: "0" (__NR_modify_ldt),
|
||||
"r" (func),
|
||||
"c" (ptr),
|
||||
"d" (sizeof(struct modify_ldt_ldt_s)*count) );
|
||||
#else
|
||||
__asm__ __volatile__("int $0x80"
|
||||
: "=a" (res)
|
||||
: "0" (__NR_modify_ldt),
|
||||
"b" (func),
|
||||
"c" (ptr),
|
||||
"d" (sizeof(struct modify_ldt_ldt_s)*count) );
|
||||
#endif
|
||||
if (res >= 0) return res;
|
||||
errno = -res;
|
||||
return -1;
|
||||
}
|
||||
static int fs_installed=0;
|
||||
static char* fs_seg=0;
|
||||
static int install_fs()
|
||||
{
|
||||
struct modify_ldt_ldt_s array;
|
||||
int fd;
|
||||
int ret;
|
||||
void* prev_struct;
|
||||
|
||||
if(fs_installed)
|
||||
return 0;
|
||||
|
||||
fd=open("/dev/zero", O_RDWR);
|
||||
fs_seg=mmap((void*)0xbf000000, 0x30000, PROT_READ | PROT_WRITE, MAP_PRIVATE,
|
||||
fd, 0);
|
||||
if(fs_seg==0)
|
||||
{
|
||||
printf("ERROR: Couldn't allocate memory for fs segment\n");
|
||||
return -1;
|
||||
}
|
||||
array.base_addr=((int)fs_seg+0xffff) & 0xffff0000;
|
||||
array.entry_number=0x1;
|
||||
array.limit=array.base_addr+getpagesize()-1;
|
||||
array.seg_32bit=1;
|
||||
array.read_exec_only=0;
|
||||
array.seg_not_present=0;
|
||||
array.contents=MODIFY_LDT_CONTENTS_DATA;
|
||||
array.limit_in_pages=0;
|
||||
#ifdef linux
|
||||
ret=modify_ldt(0x1, &array, 1);
|
||||
if(ret<0)
|
||||
{
|
||||
perror("install_fs");
|
||||
MESSAGE("Couldn't install fs segment, expect segfault\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
{
|
||||
long d[2];
|
||||
|
||||
LDT_EntryToBytes( d, &array );
|
||||
ret = i386_set_ldt(0x1, (union descriptor *)d, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
perror("install_fs");
|
||||
MESSAGE("Did you reconfigure the kernel with \"options USER_LDT\"?\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__asm__
|
||||
(
|
||||
"movl $0xf,%eax\n\t"
|
||||
// "pushw %ax\n\t"
|
||||
"movw %ax, %fs\n\t"
|
||||
);
|
||||
prev_struct=malloc(8);
|
||||
*(void**)array.base_addr=prev_struct;
|
||||
printf("prev_struct: 0x%X\n", prev_struct);
|
||||
close(fd);
|
||||
|
||||
fs_installed=1;
|
||||
return 0;
|
||||
};
|
||||
static int uninstall_fs()
|
||||
{
|
||||
printf("Uninstalling FS segment\n");
|
||||
if(fs_seg==0)
|
||||
return -1;
|
||||
munmap(fs_seg, 0x30000);
|
||||
fs_installed=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
//WINE_MODREF *local_wm=NULL;
|
||||
modref_list* local_wm=NULL;
|
||||
|
||||
WINE_MODREF *MODULE_FindModule(LPCSTR m)
|
||||
{
|
||||
modref_list* list=local_wm;
|
||||
TRACE("Module %s request\n", m);
|
||||
if(list==NULL)
|
||||
return NULL;
|
||||
while(strcmp(m, list->wm->filename))
|
||||
{
|
||||
printf("%s: %x\n", list->wm->filename, list->wm->module);
|
||||
list=list->prev;
|
||||
if(list==NULL)
|
||||
return NULL;
|
||||
}
|
||||
TRACE("Resolved to %s\n", list->wm->filename);
|
||||
return list->wm;
|
||||
}
|
||||
|
||||
void MODULE_RemoveFromList(WINE_MODREF *mod)
|
||||
{
|
||||
modref_list* list=local_wm;
|
||||
if(list==0)
|
||||
return;
|
||||
if(mod==0)
|
||||
return;
|
||||
if((list->prev==NULL)&&(list->next==NULL))
|
||||
{
|
||||
free(list);
|
||||
local_wm=NULL;
|
||||
// uninstall_fs();
|
||||
return;
|
||||
}
|
||||
for(;list;list=list->prev)
|
||||
{
|
||||
if(list->wm==mod)
|
||||
{
|
||||
if(list->prev)
|
||||
list->prev->next=list->next;
|
||||
if(list->next)
|
||||
list->next->prev=list->prev;
|
||||
if(list==local_wm)
|
||||
local_wm=list->prev;
|
||||
free(list);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WINE_MODREF *MODULE32_LookupHMODULE(HMODULE m)
|
||||
{
|
||||
modref_list* list=local_wm;
|
||||
TRACE("Module %X request\n", m);
|
||||
if(list==NULL)
|
||||
return NULL;
|
||||
while(m!=list->wm->module)
|
||||
{
|
||||
// printf("Checking list %X wm %X module %X\n",
|
||||
// list, list->wm, list->wm->module);
|
||||
list=list->prev;
|
||||
if(list==NULL)
|
||||
return NULL;
|
||||
}
|
||||
TRACE("LookupHMODULE hit %X\n", list->wm);
|
||||
return list->wm;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE_InitDll
|
||||
*/
|
||||
static WIN_BOOL MODULE_InitDll( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
|
||||
{
|
||||
WIN_BOOL retv = TRUE;
|
||||
|
||||
static LPCSTR typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH",
|
||||
"THREAD_ATTACH", "THREAD_DETACH" };
|
||||
assert( wm );
|
||||
|
||||
|
||||
/* Skip calls for modules loaded with special load flags */
|
||||
|
||||
if ( ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
|
||||
|| ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )
|
||||
return TRUE;
|
||||
|
||||
|
||||
TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved );
|
||||
|
||||
/* Call the initialization routine */
|
||||
switch ( wm->type )
|
||||
{
|
||||
case MODULE32_PE:
|
||||
retv = PE_InitDLL( wm, type, lpReserved );
|
||||
break;
|
||||
|
||||
case MODULE32_ELF:
|
||||
/* no need to do that, dlopen() already does */
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR("wine_modref type %d not handled.\n", wm->type );
|
||||
retv = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The state of the module list may have changed due to the call
|
||||
to PE_InitDLL. We cannot assume that this module has not been
|
||||
deleted. */
|
||||
TRACE("(%p,%s,%p) - RETURN %d\n", wm, typeName[type], lpReserved, retv );
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE_DllProcessAttach
|
||||
*
|
||||
* Send the process attach notification to all DLLs the given module
|
||||
* depends on (recursively). This is somewhat complicated due to the fact that
|
||||
*
|
||||
* - we have to respect the module dependencies, i.e. modules implicitly
|
||||
* referenced by another module have to be initialized before the module
|
||||
* itself can be initialized
|
||||
*
|
||||
* - the initialization routine of a DLL can itself call LoadLibrary,
|
||||
* thereby introducing a whole new set of dependencies (even involving
|
||||
* the 'old' modules) at any time during the whole process
|
||||
*
|
||||
* (Note that this routine can be recursively entered not only directly
|
||||
* from itself, but also via LoadLibrary from one of the called initialization
|
||||
* routines.)
|
||||
*
|
||||
* Furthermore, we need to rearrange the main WINE_MODREF list to allow
|
||||
* the process *detach* notifications to be sent in the correct order.
|
||||
* This must not only take into account module dependencies, but also
|
||||
* 'hidden' dependencies created by modules calling LoadLibrary in their
|
||||
* attach notification routine.
|
||||
*
|
||||
* The strategy is rather simple: we move a WINE_MODREF to the head of the
|
||||
* list after the attach notification has returned. This implies that the
|
||||
* detach notifications are called in the reverse of the sequence the attach
|
||||
* notifications *returned*.
|
||||
*
|
||||
* NOTE: Assumes that the process critical section is held!
|
||||
*
|
||||
*/
|
||||
WIN_BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved )
|
||||
{
|
||||
WIN_BOOL retv = TRUE;
|
||||
int i;
|
||||
assert( wm );
|
||||
|
||||
/* prevent infinite recursion in case of cyclical dependencies */
|
||||
if ( ( wm->flags & WINE_MODREF_MARKER )
|
||||
|| ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) )
|
||||
return retv;
|
||||
|
||||
TRACE("(%s,%p) - START\n", wm->modname, lpReserved );
|
||||
|
||||
/* Tag current MODREF to prevent recursive loop */
|
||||
wm->flags |= WINE_MODREF_MARKER;
|
||||
|
||||
/* Recursively attach all DLLs this one depends on */
|
||||
/* for ( i = 0; retv && i < wm->nDeps; i++ )
|
||||
if ( wm->deps[i] )
|
||||
retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved );
|
||||
*/
|
||||
/* Call DLL entry point */
|
||||
|
||||
//local_wm=wm;
|
||||
if(local_wm)
|
||||
{
|
||||
local_wm->next=malloc(sizeof(modref_list));
|
||||
local_wm->next->prev=local_wm;
|
||||
local_wm->next->next=NULL;
|
||||
local_wm->next->wm=wm;
|
||||
local_wm=local_wm->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
local_wm=malloc(sizeof(modref_list));
|
||||
local_wm->next=local_wm->prev=NULL;
|
||||
local_wm->wm=wm;
|
||||
}
|
||||
/* Remove recursion flag */
|
||||
wm->flags &= ~WINE_MODREF_MARKER;
|
||||
|
||||
if ( retv )
|
||||
{
|
||||
retv = MODULE_InitDll( wm, DLL_PROCESS_ATTACH, lpReserved );
|
||||
if ( retv )
|
||||
wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
|
||||
}
|
||||
|
||||
|
||||
TRACE("(%s,%p) - END\n", wm->modname, lpReserved );
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE_DllProcessDetach
|
||||
*
|
||||
* Send DLL process detach notifications. See the comment about calling
|
||||
* sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag
|
||||
* is set, only DLLs with zero refcount are notified.
|
||||
*/
|
||||
void MODULE_DllProcessDetach( WINE_MODREF* wm, WIN_BOOL bForceDetach, LPVOID lpReserved )
|
||||
{
|
||||
// WINE_MODREF *wm=local_wm;
|
||||
wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED;
|
||||
MODULE_InitDll( wm, DLL_PROCESS_DETACH, lpReserved );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LoadLibraryExA (KERNEL32)
|
||||
*/
|
||||
HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
||||
{
|
||||
WINE_MODREF *wm;
|
||||
|
||||
if(!libname)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
// if(fs_installed==0)
|
||||
// install_fs();
|
||||
|
||||
|
||||
wm = MODULE_LoadLibraryExA( libname, hfile, flags );
|
||||
if ( wm )
|
||||
{
|
||||
if ( !MODULE_DllProcessAttach( wm, NULL ) )
|
||||
{
|
||||
WARN_(module)("Attach failed for module '%s', \n", libname);
|
||||
MODULE_FreeLibrary(wm);
|
||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
||||
MODULE_RemoveFromList(wm);
|
||||
wm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return wm ? wm->module : 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MODULE_LoadLibraryExA (internal)
|
||||
*
|
||||
* Load a PE style module according to the load order.
|
||||
*
|
||||
* The HFILE parameter is not used and marked reserved in the SDK. I can
|
||||
* only guess that it should force a file to be mapped, but I rather
|
||||
* ignore the parameter because it would be extremely difficult to
|
||||
* integrate this with different types of module represenations.
|
||||
*
|
||||
*/
|
||||
WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
WINE_MODREF *pwm;
|
||||
int i;
|
||||
// module_loadorder_t *plo;
|
||||
|
||||
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
TRACE("Trying native dll '%s'\n", libname);
|
||||
pwm = PE_LoadLibraryExA(libname, flags);
|
||||
#ifdef HAVE_LIBDL
|
||||
if(!pwm)
|
||||
{
|
||||
TRACE("Trying ELF dll '%s'\n", libname);
|
||||
pwm=(WINE_MODREF*)ELFDLL_LoadLibraryExA(libname, flags);
|
||||
}
|
||||
#endif
|
||||
// printf("0x%08x\n", pwm);
|
||||
// break;
|
||||
if(pwm)
|
||||
{
|
||||
/* Initialize DLL just loaded */
|
||||
TRACE("Loaded module '%s' at 0x%08x, \n", libname, pwm->module);
|
||||
/* Set the refCount here so that an attach failure will */
|
||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||
pwm->refCount++;
|
||||
|
||||
SetLastError( err ); /* restore last error */
|
||||
return pwm;
|
||||
}
|
||||
|
||||
|
||||
WARN("Failed to load module '%s'; error=0x%08lx, \n", libname, GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* LoadLibraryA (KERNEL32)
|
||||
*/
|
||||
HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
|
||||
return LoadLibraryExA(libname,0,0);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FreeLibrary
|
||||
*/
|
||||
WIN_BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
|
||||
{
|
||||
WIN_BOOL retv = FALSE;
|
||||
WINE_MODREF *wm;
|
||||
|
||||
wm=MODULE32_LookupHMODULE(hLibModule);
|
||||
// wm=local_wm;
|
||||
|
||||
if ( !wm || !hLibModule )
|
||||
{
|
||||
SetLastError( ERROR_INVALID_HANDLE );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
retv = MODULE_FreeLibrary( wm );
|
||||
|
||||
MODULE_RemoveFromList(wm);
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MODULE_DecRefCount
|
||||
*
|
||||
* NOTE: Assumes that the process critical section is held!
|
||||
*/
|
||||
static void MODULE_DecRefCount( WINE_MODREF *wm )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( wm->flags & WINE_MODREF_MARKER )
|
||||
return;
|
||||
|
||||
if ( wm->refCount <= 0 )
|
||||
return;
|
||||
|
||||
--wm->refCount;
|
||||
TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount );
|
||||
|
||||
if ( wm->refCount == 0 )
|
||||
{
|
||||
wm->flags |= WINE_MODREF_MARKER;
|
||||
|
||||
for ( i = 0; i < wm->nDeps; i++ )
|
||||
if ( wm->deps[i] )
|
||||
MODULE_DecRefCount( wm->deps[i] );
|
||||
|
||||
wm->flags &= ~WINE_MODREF_MARKER;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MODULE_FreeLibrary
|
||||
*
|
||||
* NOTE: Assumes that the process critical section is held!
|
||||
*/
|
||||
WIN_BOOL MODULE_FreeLibrary( WINE_MODREF *wm )
|
||||
{
|
||||
TRACE("(%s) - START\n", wm->modname );
|
||||
|
||||
/* Recursively decrement reference counts */
|
||||
//MODULE_DecRefCount( wm );
|
||||
|
||||
/* Call process detach notifications */
|
||||
MODULE_DllProcessDetach( wm, FALSE, NULL );
|
||||
|
||||
PE_UnloadLibrary(wm);
|
||||
|
||||
TRACE("END\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetProcAddress (KERNEL32.257)
|
||||
*/
|
||||
FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
|
||||
{
|
||||
return MODULE_GetProcAddress( hModule, function, TRUE );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MODULE_GetProcAddress (internal)
|
||||
*/
|
||||
FARPROC MODULE_GetProcAddress(
|
||||
HMODULE hModule, /* [in] current module handle */
|
||||
LPCSTR function, /* [in] function to be looked up */
|
||||
WIN_BOOL snoop )
|
||||
{
|
||||
WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
|
||||
// WINE_MODREF *wm=local_wm;
|
||||
FARPROC retproc;
|
||||
|
||||
if (HIWORD(function))
|
||||
TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function);
|
||||
else
|
||||
TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function);
|
||||
if (!wm) {
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return (FARPROC)0;
|
||||
}
|
||||
switch (wm->type)
|
||||
{
|
||||
case MODULE32_PE:
|
||||
retproc = PE_FindExportedFunction( wm, function, snoop );
|
||||
if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
return retproc;
|
||||
#ifdef HAVE_LIBDL
|
||||
case MODULE32_ELF:
|
||||
retproc = (FARPROC) dlsym( wm->module, function);
|
||||
if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
|
||||
return retproc;
|
||||
#endif
|
||||
default:
|
||||
ERR("wine_modref type %d not handled.\n",wm->type);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return (FARPROC)0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,920 +0,0 @@
|
|||
/*
|
||||
* Copyright 1994 Eric Youndale & Erik Bos
|
||||
* Copyright 1995 Martin von Löwis
|
||||
* Copyright 1996-98 Marcus Meissner
|
||||
*
|
||||
* based on Eric Youndale's pe-test and:
|
||||
*
|
||||
* ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
|
||||
* make that:
|
||||
* ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
|
||||
*/
|
||||
/* Notes:
|
||||
* Before you start changing something in this file be aware of the following:
|
||||
*
|
||||
* - There are several functions called recursively. In a very subtle and
|
||||
* obscure way. DLLs can reference each other recursively etc.
|
||||
* - If you want to enhance, speed up or clean up something in here, think
|
||||
* twice WHY it is implemented in that strange way. There is usually a reason.
|
||||
* Though sometimes it might just be lazyness ;)
|
||||
* - In PE_MapImage, right before fixup_imports() all external and internal
|
||||
* state MUST be correct since this function can be called with the SAME image
|
||||
* AGAIN. (Thats recursion for you.) That means MODREF.module and
|
||||
* NE_MODULE.module32.
|
||||
* - Sometimes, we can't use Linux mmap() to mmap() the images directly.
|
||||
*
|
||||
* The problem is, that there is not direct 1:1 mapping from a diskimage and
|
||||
* a memoryimage. The headers at the start are mapped linear, but the sections
|
||||
* are not. Older x86 pe binaries are 512 byte aligned in file and 4096 byte
|
||||
* aligned in memory. Linux likes them 4096 byte aligned in memory (due to
|
||||
* x86 pagesize, this cannot be fixed without a rather large kernel rewrite)
|
||||
* and 'blocksize' file-aligned (offsets). Since we have 512/1024/2048 (CDROM)
|
||||
* and other byte blocksizes, we can't always do this. We *can* do this for
|
||||
* newer pe binaries produced by MSVC 5 and later, since they are also aligned
|
||||
* to 4096 byte boundaries on disk.
|
||||
*/
|
||||
|
||||
#include <wine/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <wine/windef.h>
|
||||
#include <wine/winbase.h>
|
||||
#include <wine/winerror.h>
|
||||
#include <wine/heap.h>
|
||||
#include <wine/pe_image.h>
|
||||
#include <wine/module.h>
|
||||
#include <wine/debugtools.h>
|
||||
|
||||
#include "win32.h"
|
||||
|
||||
#define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x)))
|
||||
|
||||
#define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
|
||||
|
||||
extern void* LookupExternal(const char* library, int ordinal);
|
||||
extern void* LookupExternalByName(const char* library, const char* name);
|
||||
|
||||
void dump_exports( HMODULE hModule )
|
||||
{
|
||||
char *Module;
|
||||
int i, j;
|
||||
u_short *ordinal;
|
||||
u_long *function,*functions;
|
||||
u_char **name;
|
||||
unsigned int load_addr = hModule;
|
||||
|
||||
DWORD rva_start = PE_HEADER(hModule)->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start);
|
||||
|
||||
Module = (char*)RVA(pe_exports->Name);
|
||||
TRACE("*******EXPORT DATA*******\n");
|
||||
TRACE("Module name is %s, %ld functions, %ld names\n",
|
||||
Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames);
|
||||
|
||||
ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals);
|
||||
functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions);
|
||||
name=(u_char**) RVA(pe_exports->AddressOfNames);
|
||||
|
||||
TRACE(" Ord RVA Addr Name\n" );
|
||||
for (i=0;i<pe_exports->NumberOfFunctions;i++, function++)
|
||||
{
|
||||
if (!*function) continue;
|
||||
if (TRACE_ON(win32))
|
||||
{
|
||||
DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) );
|
||||
|
||||
for (j = 0; j < pe_exports->NumberOfNames; j++)
|
||||
if (ordinal[j] == i)
|
||||
{
|
||||
DPRINTF( " %s", (char*)RVA(name[j]) );
|
||||
break;
|
||||
}
|
||||
if ((*function >= rva_start) && (*function <= rva_end))
|
||||
DPRINTF(" (forwarded -> %s)", (char *)RVA(*function));
|
||||
DPRINTF("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up the specified function or ordinal in the exportlist:
|
||||
* If it is a string:
|
||||
* - look up the name in the Name list.
|
||||
* - look up the ordinal with that index.
|
||||
* - use the ordinal as offset into the functionlist
|
||||
* If it is a ordinal:
|
||||
* - use ordinal-pe_export->Base as offset into the functionlist
|
||||
*/
|
||||
FARPROC PE_FindExportedFunction(
|
||||
WINE_MODREF *wm,
|
||||
LPCSTR funcName,
|
||||
WIN_BOOL snoop )
|
||||
{
|
||||
u_short * ordinals;
|
||||
u_long * function;
|
||||
u_char ** name, *ename = NULL;
|
||||
int i, ordinal;
|
||||
PE_MODREF *pem = &(wm->binfmt.pe);
|
||||
IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export;
|
||||
unsigned int load_addr = wm->module;
|
||||
u_long rva_start, rva_end, addr;
|
||||
char * forward;
|
||||
|
||||
if (HIWORD(funcName))
|
||||
TRACE("(%s)\n",funcName);
|
||||
else
|
||||
TRACE("(%d)\n",(int)funcName);
|
||||
if (!exports) {
|
||||
/* Not a fatal problem, some apps do
|
||||
* GetProcAddress(0,"RegisterPenApp") which triggers this
|
||||
* case.
|
||||
*/
|
||||
WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
|
||||
return NULL;
|
||||
}
|
||||
ordinals= (u_short*) RVA(exports->AddressOfNameOrdinals);
|
||||
function= (u_long*) RVA(exports->AddressOfFunctions);
|
||||
name = (u_char **) RVA(exports->AddressOfNames);
|
||||
forward = NULL;
|
||||
rva_start = PE_HEADER(wm->module)->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
|
||||
if (HIWORD(funcName))
|
||||
{
|
||||
|
||||
int min = 0, max = exports->NumberOfNames - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int res, pos = (min + max) / 2;
|
||||
ename = RVA(name[pos]);
|
||||
if (!(res = strcmp( ename, funcName )))
|
||||
{
|
||||
ordinal = ordinals[pos];
|
||||
goto found;
|
||||
}
|
||||
if (res > 0) max = pos - 1;
|
||||
else min = pos + 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < exports->NumberOfNames; i++)
|
||||
{
|
||||
ename = RVA(name[i]);
|
||||
if (!strcmp( ename, funcName ))
|
||||
{
|
||||
ERR( "%s.%s required a linear search\n", wm->modname, funcName );
|
||||
ordinal = ordinals[i];
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ordinal = LOWORD(funcName) - exports->Base;
|
||||
if (snoop && name)
|
||||
{
|
||||
for (i = 0; i < exports->NumberOfNames; i++)
|
||||
if (ordinals[i] == ordinal)
|
||||
{
|
||||
ename = RVA(name[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
if (ordinal >= exports->NumberOfFunctions)
|
||||
{
|
||||
TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
|
||||
return NULL;
|
||||
}
|
||||
addr = function[ordinal];
|
||||
if (!addr) return NULL;
|
||||
if ((addr < rva_start) || (addr >= rva_end))
|
||||
{
|
||||
FARPROC proc = RVA(addr);
|
||||
if (snoop)
|
||||
{
|
||||
if (!ename) ename = "@";
|
||||
// proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc);
|
||||
TRACE("SNOOP_GetProcAddress n/a\n");
|
||||
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
else
|
||||
{
|
||||
WINE_MODREF *wm;
|
||||
char *forward = RVA(addr);
|
||||
char module[256];
|
||||
char *end = strchr(forward, '.');
|
||||
|
||||
if (!end) return NULL;
|
||||
if (end - forward >= sizeof(module)) return NULL;
|
||||
memcpy( module, forward, end - forward );
|
||||
module[end-forward] = 0;
|
||||
if (!(wm = MODULE_FindModule( module )))
|
||||
{
|
||||
ERR("module not found for forward '%s'\n", forward );
|
||||
return NULL;
|
||||
}
|
||||
return MODULE_GetProcAddress( wm->module, end + 1, snoop );
|
||||
}
|
||||
}
|
||||
|
||||
DWORD fixup_imports( WINE_MODREF *wm )
|
||||
{
|
||||
IMAGE_IMPORT_DESCRIPTOR *pe_imp;
|
||||
PE_MODREF *pem;
|
||||
unsigned int load_addr = wm->module;
|
||||
int i,characteristics_detection=1;
|
||||
char *modname;
|
||||
|
||||
assert(wm->type==MODULE32_PE);
|
||||
pem = &(wm->binfmt.pe);
|
||||
if (pem->pe_export)
|
||||
modname = (char*) RVA(pem->pe_export->Name);
|
||||
else
|
||||
modname = "<unknown>";
|
||||
|
||||
|
||||
TRACE("Dumping imports list\n");
|
||||
|
||||
|
||||
pe_imp = pem->pe_import;
|
||||
if (!pe_imp) return 0;
|
||||
|
||||
/* We assume that we have at least one import with !0 characteristics and
|
||||
* detect broken imports with all characteristsics 0 (notably Borland) and
|
||||
* switch the detection off for them.
|
||||
*/
|
||||
for (i = 0; pe_imp->Name ; pe_imp++) {
|
||||
if (!i && !pe_imp->u.Characteristics)
|
||||
characteristics_detection = 0;
|
||||
if (characteristics_detection && !pe_imp->u.Characteristics)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (!i) return 0;
|
||||
|
||||
|
||||
wm->nDeps = i;
|
||||
wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
|
||||
|
||||
/* load the imported modules. They are automatically
|
||||
* added to the modref list of the process.
|
||||
*/
|
||||
|
||||
for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) {
|
||||
WINE_MODREF *wmImp;
|
||||
IMAGE_IMPORT_BY_NAME *pe_name;
|
||||
PIMAGE_THUNK_DATA import_list,thunk_list;
|
||||
char *name = (char *) RVA(pe_imp->Name);
|
||||
|
||||
if (characteristics_detection && !pe_imp->u.Characteristics)
|
||||
break;
|
||||
|
||||
//#warning FIXME: here we should fill imports
|
||||
TRACE("Loading imports for %s.dll\n", name);
|
||||
|
||||
if (pe_imp->u.OriginalFirstThunk != 0) {
|
||||
TRACE("Microsoft style imports used\n");
|
||||
import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
|
||||
thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
|
||||
|
||||
while (import_list->u1.Ordinal) {
|
||||
if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
|
||||
int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
|
||||
|
||||
// TRACE("--- Ordinal %s,%d\n", name, ordinal);
|
||||
|
||||
thunk_list->u1.Function=LookupExternal(
|
||||
name, ordinal);
|
||||
} else {
|
||||
pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
|
||||
// TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
|
||||
thunk_list->u1.Function=LookupExternalByName(
|
||||
name, pe_name->Name);
|
||||
}
|
||||
import_list++;
|
||||
thunk_list++;
|
||||
}
|
||||
} else {
|
||||
TRACE("Borland style imports used\n");
|
||||
thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
|
||||
while (thunk_list->u1.Ordinal) {
|
||||
if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
|
||||
|
||||
int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
|
||||
|
||||
TRACE("--- Ordinal %s.%d\n",name,ordinal);
|
||||
thunk_list->u1.Function=LookupExternal(
|
||||
name, ordinal);
|
||||
} else {
|
||||
pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
|
||||
TRACE("--- %s %s.%d\n",
|
||||
pe_name->Name,name,pe_name->Hint);
|
||||
thunk_list->u1.Function=LookupExternalByName(
|
||||
name, pe_name->Name);
|
||||
}
|
||||
thunk_list++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int calc_vma_size( HMODULE hModule )
|
||||
{
|
||||
int i,vma_size = 0;
|
||||
IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule);
|
||||
|
||||
TRACE("Dump of segment table\n");
|
||||
TRACE(" Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
|
||||
for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
TRACE("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
|
||||
pe_seg->Name,
|
||||
pe_seg->Misc.VirtualSize,
|
||||
pe_seg->VirtualAddress,
|
||||
pe_seg->SizeOfRawData,
|
||||
pe_seg->PointerToRawData,
|
||||
pe_seg->PointerToRelocations,
|
||||
pe_seg->PointerToLinenumbers,
|
||||
pe_seg->NumberOfRelocations,
|
||||
pe_seg->NumberOfLinenumbers,
|
||||
pe_seg->Characteristics);
|
||||
vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData);
|
||||
vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->Misc.VirtualSize);
|
||||
pe_seg++;
|
||||
}
|
||||
return vma_size;
|
||||
}
|
||||
|
||||
static void do_relocations( unsigned int load_addr, IMAGE_BASE_RELOCATION *r )
|
||||
{
|
||||
int delta = load_addr - PE_HEADER(load_addr)->OptionalHeader.ImageBase;
|
||||
int hdelta = (delta >> 16) & 0xFFFF;
|
||||
int ldelta = delta & 0xFFFF;
|
||||
|
||||
if(delta == 0)
|
||||
|
||||
return;
|
||||
while(r->VirtualAddress)
|
||||
{
|
||||
char *page = (char*) RVA(r->VirtualAddress);
|
||||
int count = (r->SizeOfBlock - 8)/2;
|
||||
int i;
|
||||
TRACE_(fixup)("%x relocations for page %lx\n",
|
||||
count, r->VirtualAddress);
|
||||
|
||||
for(i=0;i<count;i++)
|
||||
{
|
||||
int offset = r->TypeOffset[i] & 0xFFF;
|
||||
int type = r->TypeOffset[i] >> 12;
|
||||
// TRACE_(fixup)("patching %x type %x\n", offset, type);
|
||||
switch(type)
|
||||
{
|
||||
case IMAGE_REL_BASED_ABSOLUTE: break;
|
||||
case IMAGE_REL_BASED_HIGH:
|
||||
*(short*)(page+offset) += hdelta;
|
||||
break;
|
||||
case IMAGE_REL_BASED_LOW:
|
||||
*(short*)(page+offset) += ldelta;
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGHLOW:
|
||||
*(int*)(page+offset) += delta;
|
||||
|
||||
break;
|
||||
case IMAGE_REL_BASED_HIGHADJ:
|
||||
FIXME("Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
|
||||
break;
|
||||
case IMAGE_REL_BASED_MIPS_JMPADDR:
|
||||
FIXME("Is this a MIPS machine ???\n");
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown fixup type\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* PE_LoadImage
|
||||
* Load one PE format DLL/EXE into memory
|
||||
*
|
||||
* Unluckily we can't just mmap the sections where we want them, for
|
||||
* (at least) Linux does only support offsets which are page-aligned.
|
||||
*
|
||||
* BUT we have to map the whole image anyway, for Win32 programs sometimes
|
||||
* want to access them. (HMODULE32 point to the start of it)
|
||||
*/
|
||||
HMODULE PE_LoadImage( int handle, LPCSTR filename, WORD *version )
|
||||
{
|
||||
HMODULE hModule;
|
||||
HANDLE mapping;
|
||||
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
IMAGE_SECTION_HEADER *pe_sec;
|
||||
IMAGE_DATA_DIRECTORY *dir;
|
||||
BY_HANDLE_FILE_INFORMATION bhfi;
|
||||
int i, rawsize, lowest_va, vma_size, file_size = 0;
|
||||
DWORD load_addr = 0, aoep, reloc = 0;
|
||||
// struct get_read_fd_request *req = get_req_buffer();
|
||||
int unix_handle = handle;
|
||||
int page_size = getpagesize();
|
||||
|
||||
|
||||
// if ( GetFileInformationByHandle( hFile, &bhfi ) )
|
||||
// file_size = bhfi.nFileSizeLow;
|
||||
file_size=lseek(handle, 0, SEEK_END);
|
||||
lseek(handle, 0, SEEK_SET);
|
||||
|
||||
//#warning fix CreateFileMappingA
|
||||
mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY | SEC_COMMIT,
|
||||
0, 0, NULL );
|
||||
if (!mapping)
|
||||
{
|
||||
WARN("CreateFileMapping error %ld\n", GetLastError() );
|
||||
return 0;
|
||||
}
|
||||
// hModule = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
||||
hModule=(HMODULE)mapping;
|
||||
// CloseHandle( mapping );
|
||||
if (!hModule)
|
||||
{
|
||||
WARN("MapViewOfFile error %ld\n", GetLastError() );
|
||||
return 0;
|
||||
}
|
||||
if ( *(WORD*)hModule !=IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
WARN("%s image doesn't have DOS signature, but 0x%04x\n", filename,*(WORD*)hModule);
|
||||
goto error;
|
||||
}
|
||||
|
||||
nt = PE_HEADER( hModule );
|
||||
|
||||
|
||||
if ( nt->Signature != IMAGE_NT_SIGNATURE )
|
||||
{
|
||||
WARN("%s image doesn't have PE signature, but 0x%08lx\n", filename, nt->Signature );
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 )
|
||||
{
|
||||
MESSAGE("Trying to load PE image for unsupported architecture (");
|
||||
switch (nt->FileHeader.Machine)
|
||||
{
|
||||
case IMAGE_FILE_MACHINE_UNKNOWN: MESSAGE("Unknown"); break;
|
||||
case IMAGE_FILE_MACHINE_I860: MESSAGE("I860"); break;
|
||||
case IMAGE_FILE_MACHINE_R3000: MESSAGE("R3000"); break;
|
||||
case IMAGE_FILE_MACHINE_R4000: MESSAGE("R4000"); break;
|
||||
case IMAGE_FILE_MACHINE_R10000: MESSAGE("R10000"); break;
|
||||
case IMAGE_FILE_MACHINE_ALPHA: MESSAGE("Alpha"); break;
|
||||
case IMAGE_FILE_MACHINE_POWERPC: MESSAGE("PowerPC"); break;
|
||||
default: MESSAGE("Unknown-%04x", nt->FileHeader.Machine); break;
|
||||
}
|
||||
MESSAGE(")\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
pe_sec = PE_SECTIONS( hModule );
|
||||
rawsize = 0; lowest_va = 0x10000;
|
||||
for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
if (lowest_va > pe_sec[i].VirtualAddress)
|
||||
lowest_va = pe_sec[i].VirtualAddress;
|
||||
if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
|
||||
continue;
|
||||
if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize)
|
||||
rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData;
|
||||
}
|
||||
|
||||
|
||||
if ( file_size && file_size < rawsize )
|
||||
{
|
||||
ERR("PE module is too small (header: %d, filesize: %d), "
|
||||
"probably truncated download?\n",
|
||||
rawsize, file_size );
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
aoep = nt->OptionalHeader.AddressOfEntryPoint;
|
||||
if (aoep && (aoep < lowest_va))
|
||||
FIXME("VIRUS WARNING: '%s' has an invalid entrypoint (0x%08lx) "
|
||||
"below the first virtual address (0x%08x) "
|
||||
"(possibly infected by Tchernobyl/SpaceFiller virus)!\n",
|
||||
filename, aoep, lowest_va );
|
||||
|
||||
|
||||
/* FIXME: Hack! While we don't really support shared sections yet,
|
||||
* this checks for those special cases where the whole DLL
|
||||
* consists only of shared sections and is mapped into the
|
||||
* shared address space > 2GB. In this case, we assume that
|
||||
* the module got mapped at its base address. Thus we simply
|
||||
* check whether the module has actually been mapped there
|
||||
* and use it, if so. This is needed to get Win95 USER32.DLL
|
||||
* to work (until we support shared sections properly).
|
||||
*/
|
||||
|
||||
if ( nt->OptionalHeader.ImageBase & 0x80000000 )
|
||||
{
|
||||
HMODULE sharedMod = (HMODULE)nt->OptionalHeader.ImageBase;
|
||||
IMAGE_NT_HEADERS *sharedNt = (PIMAGE_NT_HEADERS)
|
||||
( (LPBYTE)sharedMod + ((LPBYTE)nt - (LPBYTE)hModule) );
|
||||
|
||||
/* Well, this check is not really comprehensive,
|
||||
but should be good enough for now ... */
|
||||
if ( !IsBadReadPtr( (LPBYTE)sharedMod, sizeof(IMAGE_DOS_HEADER) )
|
||||
&& memcmp( (LPBYTE)sharedMod, (LPBYTE)hModule, sizeof(IMAGE_DOS_HEADER) ) == 0
|
||||
&& !IsBadReadPtr( sharedNt, sizeof(IMAGE_NT_HEADERS) )
|
||||
&& memcmp( sharedNt, nt, sizeof(IMAGE_NT_HEADERS) ) == 0 )
|
||||
{
|
||||
UnmapViewOfFile( (LPVOID)hModule );
|
||||
return sharedMod;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
load_addr = nt->OptionalHeader.ImageBase;
|
||||
vma_size = calc_vma_size( hModule );
|
||||
|
||||
load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE );
|
||||
if (load_addr == 0)
|
||||
{
|
||||
|
||||
FIXME("We need to perform base relocations for %s\n", filename);
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC;
|
||||
if (dir->Size)
|
||||
reloc = dir->VirtualAddress;
|
||||
else
|
||||
{
|
||||
FIXME( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n",
|
||||
filename,
|
||||
(nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)?
|
||||
"stripped during link" : "unknown reason" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* FIXME: If we need to relocate a system DLL (base > 2GB) we should
|
||||
* really make sure that the *new* base address is also > 2GB.
|
||||
* Some DLLs really check the MSB of the module handle :-/
|
||||
*/
|
||||
if ( nt->OptionalHeader.ImageBase & 0x80000000 )
|
||||
ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" );
|
||||
|
||||
load_addr = (DWORD)VirtualAlloc( NULL, vma_size,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE );
|
||||
if (!load_addr) {
|
||||
FIXME_(win32)(
|
||||
"FATAL: Couldn't load module %s (out of memory, %d needed)!\n", filename, vma_size);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Load addr is %lx (base %lx), range %x\n",
|
||||
load_addr, nt->OptionalHeader.ImageBase, vma_size );
|
||||
TRACE_(segment)("Loading %s at %lx, range %x\n",
|
||||
filename, load_addr, vma_size );
|
||||
|
||||
#if 0
|
||||
|
||||
*(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule;
|
||||
*PE_HEADER( load_addr ) = *nt;
|
||||
memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule),
|
||||
sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections );
|
||||
|
||||
|
||||
memcpy( load_addr, hModule, lowest_fa );
|
||||
#endif
|
||||
|
||||
if ((void*)FILE_dommap( handle, (void *)load_addr, 0, nt->OptionalHeader.SizeOfHeaders,
|
||||
0, 0, PROT_EXEC | PROT_WRITE | PROT_READ,
|
||||
MAP_PRIVATE | MAP_FIXED ) != (void*)load_addr)
|
||||
{
|
||||
ERR_(win32)( "Critical Error: failed to map PE header to necessary address.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
pe_sec = PE_SECTIONS( hModule );
|
||||
for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++)
|
||||
{
|
||||
if (!pe_sec->SizeOfRawData || !pe_sec->PointerToRawData) continue;
|
||||
TRACE("%s: mmaping section %s at %p off %lx size %lx/%lx\n",
|
||||
filename, pe_sec->Name, (void*)RVA(pe_sec->VirtualAddress),
|
||||
pe_sec->PointerToRawData, pe_sec->SizeOfRawData, pe_sec->Misc.VirtualSize );
|
||||
if ((void*)FILE_dommap( unix_handle, (void*)RVA(pe_sec->VirtualAddress),
|
||||
0, pe_sec->SizeOfRawData, 0, pe_sec->PointerToRawData,
|
||||
PROT_EXEC | PROT_WRITE | PROT_READ,
|
||||
MAP_PRIVATE | MAP_FIXED ) != (void*)RVA(pe_sec->VirtualAddress))
|
||||
{
|
||||
|
||||
ERR_(win32)( "Critical Error: failed to map PE section to necessary address.\n");
|
||||
goto error;
|
||||
}
|
||||
if ((pe_sec->SizeOfRawData < pe_sec->Misc.VirtualSize) &&
|
||||
(pe_sec->SizeOfRawData & (page_size-1)))
|
||||
{
|
||||
DWORD end = (pe_sec->SizeOfRawData & ~(page_size-1)) + page_size;
|
||||
if (end > pe_sec->Misc.VirtualSize) end = pe_sec->Misc.VirtualSize;
|
||||
TRACE("clearing %p - %p\n",
|
||||
RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData,
|
||||
RVA(pe_sec->VirtualAddress) + end );
|
||||
memset( (char*)RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, 0,
|
||||
end - pe_sec->SizeOfRawData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( reloc )
|
||||
do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) );
|
||||
|
||||
|
||||
*version = ( (nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 )
|
||||
| (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
|
||||
|
||||
|
||||
UnmapViewOfFile( (LPVOID)hModule );
|
||||
return (HMODULE)load_addr;
|
||||
|
||||
error:
|
||||
if (unix_handle != -1) close( unix_handle );
|
||||
if (load_addr) VirtualFree( (LPVOID)load_addr, 0, MEM_RELEASE );
|
||||
UnmapViewOfFile( (LPVOID)hModule );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_CreateModule
|
||||
*
|
||||
* Create WINE_MODREF structure for loaded HMODULE32, link it into
|
||||
* process modref_list, and fixup all imports.
|
||||
*
|
||||
* Note: hModule must point to a correctly allocated PE image,
|
||||
* with base relocations applied; the 16-bit dummy module
|
||||
* associated to hModule must already exist.
|
||||
*
|
||||
* Note: This routine must always be called in the context of the
|
||||
* process that is to own the module to be created.
|
||||
*/
|
||||
WINE_MODREF *PE_CreateModule( HMODULE hModule,
|
||||
LPCSTR filename, DWORD flags, WIN_BOOL builtin )
|
||||
{
|
||||
DWORD load_addr = (DWORD)hModule;
|
||||
IMAGE_NT_HEADERS *nt = PE_HEADER(hModule);
|
||||
IMAGE_DATA_DIRECTORY *dir;
|
||||
IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL;
|
||||
IMAGE_EXPORT_DIRECTORY *pe_export = NULL;
|
||||
IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL;
|
||||
WINE_MODREF *wm;
|
||||
int result;
|
||||
|
||||
|
||||
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
|
||||
if (dir->Size)
|
||||
pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress);
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT;
|
||||
if (dir->Size)
|
||||
pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress);
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE;
|
||||
if (dir->Size)
|
||||
pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress);
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION;
|
||||
if (dir->Size) FIXME("Exception directory ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY;
|
||||
if (dir->Size) FIXME("Security directory ignored\n" );
|
||||
|
||||
|
||||
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG;
|
||||
if (dir->Size) TRACE("Debug directory ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT;
|
||||
if (dir->Size) FIXME("Copyright string ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR;
|
||||
if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" );
|
||||
|
||||
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG;
|
||||
if (dir->Size) FIXME("Load Configuration directory ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT;
|
||||
if (dir->Size) TRACE("Bound Import directory ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT;
|
||||
if (dir->Size) TRACE("Import Address Table directory ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
|
||||
if (dir->Size)
|
||||
{
|
||||
TRACE("Delayed import, stub calls LoadLibrary\n" );
|
||||
/*
|
||||
* Nothing to do here.
|
||||
*/
|
||||
|
||||
#ifdef ImgDelayDescr
|
||||
/*
|
||||
* This code is useful to observe what the heck is going on.
|
||||
*/
|
||||
{
|
||||
ImgDelayDescr *pe_delay = NULL;
|
||||
pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress);
|
||||
TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs);
|
||||
TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName);
|
||||
TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod);
|
||||
TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT);
|
||||
TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT);
|
||||
TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT);
|
||||
TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT);
|
||||
TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR;
|
||||
if (dir->Size) FIXME("Unknown directory 14 ignored\n" );
|
||||
|
||||
dir = nt->OptionalHeader.DataDirectory+15;
|
||||
if (dir->Size) FIXME("Unknown directory 15 ignored\n" );
|
||||
|
||||
|
||||
|
||||
|
||||
wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, sizeof(*wm) );
|
||||
wm->module = hModule;
|
||||
|
||||
if ( builtin )
|
||||
wm->flags |= WINE_MODREF_INTERNAL;
|
||||
if ( flags & DONT_RESOLVE_DLL_REFERENCES )
|
||||
wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS;
|
||||
if ( flags & LOAD_LIBRARY_AS_DATAFILE )
|
||||
wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE;
|
||||
|
||||
wm->type = MODULE32_PE;
|
||||
wm->binfmt.pe.pe_export = pe_export;
|
||||
wm->binfmt.pe.pe_import = pe_import;
|
||||
wm->binfmt.pe.pe_resource = pe_resource;
|
||||
wm->binfmt.pe.tlsindex = -1;
|
||||
|
||||
wm->filename = malloc(strlen(filename)+1);
|
||||
strcpy(wm->filename, filename );
|
||||
wm->modname = strrchr( wm->filename, '\\' );
|
||||
if (!wm->modname) wm->modname = wm->filename;
|
||||
else wm->modname++;
|
||||
|
||||
if ( pe_export )
|
||||
dump_exports( hModule );
|
||||
|
||||
/* Fixup Imports */
|
||||
|
||||
if ( pe_import
|
||||
&& !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE )
|
||||
&& !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
|
||||
&& fixup_imports( wm ) )
|
||||
{
|
||||
/* remove entry from modref chain */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wm;
|
||||
|
||||
return wm;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* The PE Library Loader frontend.
|
||||
* FIXME: handle the flags.
|
||||
*/
|
||||
WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
|
||||
{
|
||||
HMODULE hModule32;
|
||||
WINE_MODREF *wm;
|
||||
char filename[256];
|
||||
int hFile;
|
||||
WORD version = 0;
|
||||
|
||||
|
||||
strncpy(filename, name, sizeof(filename));
|
||||
hFile=open(filename, O_RDONLY);
|
||||
if(hFile==-1)
|
||||
return NULL;
|
||||
|
||||
|
||||
hModule32 = PE_LoadImage( hFile, filename, &version );
|
||||
if (!hModule32)
|
||||
{
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !(wm = PE_CreateModule( hModule32, filename, flags, FALSE )) )
|
||||
{
|
||||
ERR( "can't load %s\n", filename );
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
close(hFile);
|
||||
return wm;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* PE_UnloadLibrary
|
||||
*
|
||||
* Unload the library unmapping the image and freeing the modref structure.
|
||||
*/
|
||||
void PE_UnloadLibrary(WINE_MODREF *wm)
|
||||
{
|
||||
TRACE(" unloading %s\n", wm->filename);
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, wm->filename );
|
||||
HeapFree( GetProcessHeap(), 0, wm->short_filename );
|
||||
HeapFree( GetProcessHeap(), 0, wm );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA
|
||||
* FIXME: this function should use PE_LoadLibraryExA, but currently can't
|
||||
* due to the PROCESS_Create stuff.
|
||||
*/
|
||||
|
||||
/* Called if the library is loaded or freed.
|
||||
* NOTE: if a thread attaches a DLL, the current thread will only do
|
||||
* DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
|
||||
* (SDK)
|
||||
*/
|
||||
WIN_BOOL PE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
|
||||
{
|
||||
WIN_BOOL retv = TRUE;
|
||||
assert( wm->type == MODULE32_PE );
|
||||
|
||||
|
||||
if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
|
||||
(PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint)
|
||||
) {
|
||||
DLLENTRYPROC entry ;
|
||||
entry = (void*)PE_FindExportedFunction(wm, "DllMain", 0);
|
||||
if(entry==NULL)
|
||||
entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint );
|
||||
|
||||
TRACE_(relay)("CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
|
||||
entry, wm->module, type, lpReserved );
|
||||
printf("Entering DllMain()\n");
|
||||
retv = entry( wm->module, type, lpReserved );
|
||||
}
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
static LPVOID
|
||||
_fixup_address(PIMAGE_OPTIONAL_HEADER opt,int delta,LPVOID addr) {
|
||||
if ( ((DWORD)addr>opt->ImageBase) &&
|
||||
((DWORD)addr<opt->ImageBase+opt->SizeOfImage)
|
||||
)
|
||||
|
||||
return (LPVOID)(((DWORD)addr)+delta);
|
||||
else
|
||||
|
||||
return addr;
|
||||
}
|
|
@ -1,390 +0,0 @@
|
|||
/*
|
||||
* PE (Portable Execute) File Resources
|
||||
*
|
||||
* Copyright 1995 Thomas Sandford
|
||||
* Copyright 1996 Martin von Loewis
|
||||
*
|
||||
* Based on the Win16 resource handling code in loader/resource.c
|
||||
* Copyright 1993 Robert J. Amstadt
|
||||
* Copyright 1995 Alexandre Julliard
|
||||
* Copyright 1997 Marcus Meissner
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <wine/winestring.h>
|
||||
#include <wine/windef.h>
|
||||
#include <wine/pe_image.h>
|
||||
#include <wine/module.h>
|
||||
#include <wine/heap.h>
|
||||
//#include "task.h"
|
||||
//#include "process.h"
|
||||
//#include "stackframe.h"
|
||||
#include <wine/debugtools.h>
|
||||
|
||||
/**********************************************************************
|
||||
* HMODULE32toPE_MODREF
|
||||
*
|
||||
* small helper function to get a PE_MODREF from a passed HMODULE32
|
||||
*/
|
||||
static PE_MODREF*
|
||||
HMODULE32toPE_MODREF(HMODULE hmod) {
|
||||
WINE_MODREF *wm;
|
||||
|
||||
wm = MODULE32_LookupHMODULE( hmod );
|
||||
if (!wm || wm->type!=MODULE32_PE)
|
||||
return NULL;
|
||||
return &(wm->binfmt.pe);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GetResDirEntryW
|
||||
*
|
||||
* Helper function - goes down one level of PE resource tree
|
||||
*
|
||||
*/
|
||||
PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY resdirptr,
|
||||
LPCWSTR name,DWORD root,
|
||||
WIN_BOOL allowdefault)
|
||||
{
|
||||
int entrynum;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
|
||||
int namelen;
|
||||
|
||||
if (HIWORD(name)) {
|
||||
if (name[0]=='#') {
|
||||
char buf[10];
|
||||
|
||||
lstrcpynWtoA(buf,name+1,10);
|
||||
return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault);
|
||||
}
|
||||
entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
|
||||
(BYTE *) resdirptr +
|
||||
sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
namelen = lstrlenW(name);
|
||||
for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
|
||||
{
|
||||
PIMAGE_RESOURCE_DIR_STRING_U str =
|
||||
(PIMAGE_RESOURCE_DIR_STRING_U) (root +
|
||||
entryTable[entrynum].u1.s.NameOffset);
|
||||
if(namelen != str->Length)
|
||||
continue;
|
||||
if(wcsnicmp(name,str->NameString,str->Length)==0)
|
||||
return (PIMAGE_RESOURCE_DIRECTORY) (
|
||||
root +
|
||||
entryTable[entrynum].u2.s.OffsetToDirectory);
|
||||
}
|
||||
return NULL;
|
||||
} else {
|
||||
entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
|
||||
(BYTE *) resdirptr +
|
||||
sizeof(IMAGE_RESOURCE_DIRECTORY) +
|
||||
resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
|
||||
for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
|
||||
if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
|
||||
return (PIMAGE_RESOURCE_DIRECTORY) (
|
||||
root +
|
||||
entryTable[entrynum].u2.s.OffsetToDirectory);
|
||||
/* just use first entry if no default can be found */
|
||||
if (allowdefault && !name && resdirptr->NumberOfIdEntries)
|
||||
return (PIMAGE_RESOURCE_DIRECTORY) (
|
||||
root +
|
||||
entryTable[0].u2.s.OffsetToDirectory);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* GetResDirEntryA
|
||||
*/
|
||||
PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA( PIMAGE_RESOURCE_DIRECTORY resdirptr,
|
||||
LPCSTR name, DWORD root,
|
||||
WIN_BOOL allowdefault )
|
||||
{
|
||||
PIMAGE_RESOURCE_DIRECTORY retv;
|
||||
LPWSTR nameW = HIWORD(name)? HEAP_strdupAtoW( GetProcessHeap(), 0, name )
|
||||
: (LPWSTR)name;
|
||||
|
||||
retv = GetResDirEntryW( resdirptr, nameW, root, allowdefault );
|
||||
|
||||
if ( HIWORD(name) ) HeapFree( GetProcessHeap(), 0, nameW );
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_FindResourceEx32W
|
||||
*/
|
||||
HANDLE PE_FindResourceExW(
|
||||
WINE_MODREF *wm,LPCWSTR name,LPCWSTR type,WORD lang
|
||||
) {
|
||||
PIMAGE_RESOURCE_DIRECTORY resdirptr;
|
||||
DWORD root;
|
||||
HANDLE result;
|
||||
PE_MODREF *pem = &(wm->binfmt.pe);
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return 0;
|
||||
|
||||
resdirptr = pem->pe_resource;
|
||||
root = (DWORD) resdirptr;
|
||||
if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
|
||||
return 0;
|
||||
if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
|
||||
return 0;
|
||||
result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE);
|
||||
/* Try LANG_NEUTRAL, too */
|
||||
if(!result)
|
||||
return (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)0, root, TRUE);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* PE_LoadResource32
|
||||
*/
|
||||
HANDLE PE_LoadResource( WINE_MODREF *wm, HANDLE hRsrc )
|
||||
{
|
||||
if (!hRsrc || !wm || wm->type!=MODULE32_PE)
|
||||
return 0;
|
||||
return (HANDLE) (wm->module + ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* PE_SizeofResource32
|
||||
*/
|
||||
DWORD PE_SizeofResource( HINSTANCE hModule, HANDLE hRsrc )
|
||||
{
|
||||
/* we don't need hModule */
|
||||
if (!hRsrc)
|
||||
return 0;
|
||||
return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_EnumResourceTypes32A
|
||||
*/
|
||||
WIN_BOOL
|
||||
PE_EnumResourceTypesA(HMODULE hmod,ENUMRESTYPEPROCA lpfun,LONG lparam) {
|
||||
PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
|
||||
int i;
|
||||
PIMAGE_RESOURCE_DIRECTORY resdir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
|
||||
WIN_BOOL ret;
|
||||
HANDLE heap = GetProcessHeap();
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return FALSE;
|
||||
|
||||
resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
|
||||
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
ret = FALSE;
|
||||
for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
|
||||
LPSTR name;
|
||||
|
||||
if (et[i].u1.s.NameIsString)
|
||||
name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset));
|
||||
else
|
||||
name = (LPSTR)(int)et[i].u1.Id;
|
||||
ret = lpfun(hmod,name,lparam);
|
||||
if (HIWORD(name))
|
||||
HeapFree(heap,0,name);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_EnumResourceTypes32W
|
||||
*/
|
||||
WIN_BOOL
|
||||
PE_EnumResourceTypesW(HMODULE hmod,ENUMRESTYPEPROCW lpfun,LONG lparam) {
|
||||
PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
|
||||
int i;
|
||||
PIMAGE_RESOURCE_DIRECTORY resdir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
|
||||
WIN_BOOL ret;
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return FALSE;
|
||||
|
||||
resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
|
||||
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
ret = FALSE;
|
||||
for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
|
||||
LPWSTR type;
|
||||
if (et[i].u1.s.NameIsString)
|
||||
type = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset);
|
||||
else
|
||||
type = (LPWSTR)(int)et[i].u1.Id;
|
||||
|
||||
ret = lpfun(hmod,type,lparam);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_EnumResourceNames32A
|
||||
*/
|
||||
WIN_BOOL
|
||||
PE_EnumResourceNamesA(
|
||||
HMODULE hmod,LPCSTR type,ENUMRESNAMEPROCA lpfun,LONG lparam
|
||||
) {
|
||||
PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
|
||||
int i;
|
||||
PIMAGE_RESOURCE_DIRECTORY resdir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
|
||||
WIN_BOOL ret;
|
||||
HANDLE heap = GetProcessHeap();
|
||||
LPWSTR typeW;
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return FALSE;
|
||||
resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
|
||||
if (HIWORD(type))
|
||||
typeW = HEAP_strdupAtoW(heap,0,type);
|
||||
else
|
||||
typeW = (LPWSTR)type;
|
||||
resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
|
||||
if (HIWORD(typeW))
|
||||
HeapFree(heap,0,typeW);
|
||||
if (!resdir)
|
||||
return FALSE;
|
||||
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
ret = FALSE;
|
||||
for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
|
||||
LPSTR name;
|
||||
|
||||
if (et[i].u1.s.NameIsString)
|
||||
name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset));
|
||||
else
|
||||
name = (LPSTR)(int)et[i].u1.Id;
|
||||
ret = lpfun(hmod,type,name,lparam);
|
||||
if (HIWORD(name)) HeapFree(heap,0,name);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_EnumResourceNames32W
|
||||
*/
|
||||
WIN_BOOL
|
||||
PE_EnumResourceNamesW(
|
||||
HMODULE hmod,LPCWSTR type,ENUMRESNAMEPROCW lpfun,LONG lparam
|
||||
) {
|
||||
PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
|
||||
int i;
|
||||
PIMAGE_RESOURCE_DIRECTORY resdir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
|
||||
WIN_BOOL ret;
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return FALSE;
|
||||
|
||||
resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
|
||||
resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
|
||||
if (!resdir)
|
||||
return FALSE;
|
||||
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
ret = FALSE;
|
||||
for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
|
||||
LPWSTR name;
|
||||
if (et[i].u1.s.NameIsString)
|
||||
name = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset);
|
||||
else
|
||||
name = (LPWSTR)(int)et[i].u1.Id;
|
||||
ret = lpfun(hmod,type,name,lparam);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_EnumResourceNames32A
|
||||
*/
|
||||
WIN_BOOL
|
||||
PE_EnumResourceLanguagesA(
|
||||
HMODULE hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROCA lpfun,
|
||||
LONG lparam
|
||||
) {
|
||||
PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
|
||||
int i;
|
||||
PIMAGE_RESOURCE_DIRECTORY resdir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
|
||||
WIN_BOOL ret;
|
||||
HANDLE heap = GetProcessHeap();
|
||||
LPWSTR nameW,typeW;
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return FALSE;
|
||||
|
||||
resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
|
||||
if (HIWORD(name))
|
||||
nameW = HEAP_strdupAtoW(heap,0,name);
|
||||
else
|
||||
nameW = (LPWSTR)name;
|
||||
resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource,FALSE);
|
||||
if (HIWORD(nameW))
|
||||
HeapFree(heap,0,nameW);
|
||||
if (!resdir)
|
||||
return FALSE;
|
||||
if (HIWORD(type))
|
||||
typeW = HEAP_strdupAtoW(heap,0,type);
|
||||
else
|
||||
typeW = (LPWSTR)type;
|
||||
resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
|
||||
if (HIWORD(typeW))
|
||||
HeapFree(heap,0,typeW);
|
||||
if (!resdir)
|
||||
return FALSE;
|
||||
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
ret = FALSE;
|
||||
for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
|
||||
/* languages are just ids... I hopem */
|
||||
ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PE_EnumResourceLanguages32W
|
||||
*/
|
||||
WIN_BOOL
|
||||
PE_EnumResourceLanguagesW(
|
||||
HMODULE hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROCW lpfun,
|
||||
LONG lparam
|
||||
) {
|
||||
PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
|
||||
int i;
|
||||
PIMAGE_RESOURCE_DIRECTORY resdir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
|
||||
WIN_BOOL ret;
|
||||
|
||||
if (!pem || !pem->pe_resource)
|
||||
return FALSE;
|
||||
|
||||
resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
|
||||
resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource,FALSE);
|
||||
if (!resdir)
|
||||
return FALSE;
|
||||
resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
|
||||
if (!resdir)
|
||||
return FALSE;
|
||||
et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
|
||||
ret = FALSE;
|
||||
for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
|
||||
ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
|
@ -1,410 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <wine/winbase.h>
|
||||
#include <wine/winreg.h>
|
||||
#include <wine/winnt.h>
|
||||
#include <wine/winerror.h>
|
||||
|
||||
#include <registry.h>
|
||||
|
||||
struct reg_value
|
||||
{
|
||||
int type;
|
||||
char* name;
|
||||
int len;
|
||||
char* value;
|
||||
};
|
||||
|
||||
static int reg_size=0;
|
||||
|
||||
static struct reg_value* regs=0;
|
||||
|
||||
struct reg_handle_s;
|
||||
typedef struct reg_handle_s
|
||||
{
|
||||
int handle;
|
||||
char* name;
|
||||
struct reg_handle_s* next;
|
||||
struct reg_handle_s* prev;
|
||||
} reg_handle_t;
|
||||
|
||||
static reg_handle_t* head=0;
|
||||
|
||||
#define DIR -25
|
||||
|
||||
static void create_registry();
|
||||
static void open_registry();
|
||||
static void save_registry();
|
||||
|
||||
|
||||
|
||||
|
||||
static void create_registry(){
|
||||
if(regs)
|
||||
{
|
||||
printf("Logic error: create_registry() called with existing registry\n");
|
||||
save_registry();
|
||||
return;
|
||||
}
|
||||
regs=(struct reg_value*)malloc(3*sizeof(struct reg_value));
|
||||
regs[0].type=regs[1].type=DIR;
|
||||
regs[0].name=(char*)malloc(5);
|
||||
strcpy(regs[0].name, "HKLM");
|
||||
regs[1].name=(char*)malloc(5);
|
||||
strcpy(regs[1].name, "HKCU");
|
||||
regs[0].value=regs[1].value=NULL;
|
||||
regs[0].len=regs[1].len=0;
|
||||
reg_size=2;
|
||||
save_registry();
|
||||
}
|
||||
static void open_registry()
|
||||
{
|
||||
int fd;
|
||||
int i;
|
||||
int len;
|
||||
struct passwd* pwent;
|
||||
char* pathname;
|
||||
if(regs)
|
||||
{
|
||||
printf("Multiple open_registry(>\n");
|
||||
return;
|
||||
}
|
||||
pwent=getpwuid(getuid());
|
||||
pathname=(char*)malloc(strlen(pwent->pw_dir)+20);
|
||||
strcpy(pathname, pwent->pw_dir);
|
||||
strcat(pathname, "/.registry");
|
||||
fd=open(pathname, O_RDONLY);
|
||||
free(pathname);
|
||||
if(fd==-1)
|
||||
{
|
||||
printf("Creating new registry\n");
|
||||
create_registry();
|
||||
return;
|
||||
}
|
||||
read(fd, ®_size, 4);
|
||||
regs=(struct reg_value*)malloc(reg_size*sizeof(struct reg_value));
|
||||
for(i=0; i<reg_size; i++)
|
||||
{
|
||||
read(fd,®s[i].type,4);
|
||||
read(fd,&len,4);
|
||||
regs[i].name=(char*)malloc(len+1);
|
||||
if(regs[i].name==0)
|
||||
{
|
||||
reg_size=i+1;
|
||||
goto error;
|
||||
}
|
||||
read(fd, regs[i].name, len);
|
||||
regs[i].name[len]=0;
|
||||
read(fd,®s[i].len,4);
|
||||
regs[i].value=(char*)malloc(len);
|
||||
if(regs[i].value==0)
|
||||
{
|
||||
free(regs[i].name);
|
||||
reg_size=i+1;
|
||||
goto error;
|
||||
}
|
||||
read(fd, regs[i].value, regs[i].len);
|
||||
}
|
||||
error:
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
static void save_registry()
|
||||
{
|
||||
int fd, i, len;
|
||||
struct passwd* pwent;
|
||||
char* pathname;
|
||||
pwent=getpwuid(getuid());
|
||||
pathname=(char*)malloc(strlen(pwent->pw_dir)+20);
|
||||
strcpy(pathname, pwent->pw_dir);
|
||||
strcat(pathname, "/.registry");
|
||||
fd=open(pathname, O_WRONLY | O_CREAT, 00777);
|
||||
free(pathname);
|
||||
if(fd==-1)
|
||||
{
|
||||
printf("Failed to open registry file for writing.\n");
|
||||
return;
|
||||
}
|
||||
write(fd, ®_size, 4);
|
||||
for(i=0; i<reg_size; i++)
|
||||
{
|
||||
write(fd, ®s[i].type, 4);
|
||||
len=strlen(regs[i].name);
|
||||
write(fd, &len, 4);
|
||||
write(fd, regs[i].name, len);
|
||||
write(fd, ®s[i].len, 4);
|
||||
write(fd, regs[i].value, regs[i].len);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
static reg_handle_t* find_handle_by_name(const char* name)
|
||||
{
|
||||
reg_handle_t* t;
|
||||
for(t=head; t; t=t->prev)
|
||||
{
|
||||
if(!strcmp(t->name, name))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static struct reg_value* find_value_by_name(const char* name)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<reg_size; i++)
|
||||
if(!strcmp(regs[i].name, name))
|
||||
return regs+i;
|
||||
return 0;
|
||||
}
|
||||
static reg_handle_t* find_handle(int handle)
|
||||
{
|
||||
reg_handle_t* t;
|
||||
for(t=head; t; t=t->prev)
|
||||
{
|
||||
if(t->handle==handle)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int generate_handle()
|
||||
{
|
||||
static int zz=249;
|
||||
zz++;
|
||||
while((zz==HKEY_LOCAL_MACHINE) || (zz==HKEY_CURRENT_USER))
|
||||
zz++;
|
||||
return zz;
|
||||
}
|
||||
|
||||
static reg_handle_t* insert_handle(long handle, const char* name)
|
||||
{
|
||||
reg_handle_t* t;
|
||||
t=(reg_handle_t*)malloc(sizeof(reg_handle_t));
|
||||
if(head==0)
|
||||
{
|
||||
t->prev=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
head->next=t;
|
||||
t->prev=head;
|
||||
}
|
||||
t->next=0;
|
||||
t->name=(char*)malloc(strlen(name)+1);
|
||||
strcpy(t->name, name);
|
||||
t->handle=handle;
|
||||
head=t;
|
||||
return t;
|
||||
}
|
||||
static char* build_keyname(long key, const char* subkey)
|
||||
{
|
||||
char* full_name;
|
||||
reg_handle_t* t;
|
||||
if((t=find_handle(key))==0)
|
||||
{
|
||||
TRACE("Invalid key\n");
|
||||
return NULL;
|
||||
}
|
||||
if(subkey==NULL)
|
||||
subkey="<default>";
|
||||
full_name=(char*)malloc(strlen(t->name)+strlen(subkey)+10);
|
||||
strcpy(full_name, t->name);
|
||||
strcat(full_name, "\\");
|
||||
strcat(full_name, subkey);
|
||||
return full_name;
|
||||
}
|
||||
struct reg_value* insert_reg_value(int handle, const char* name, int type, void* value, int len)
|
||||
{
|
||||
reg_handle_t* t;
|
||||
struct reg_value* v;
|
||||
char* fullname;
|
||||
if((fullname=build_keyname(handle, name))==NULL)
|
||||
{
|
||||
TRACE("Invalid handle\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((v=find_value_by_name(fullname))==0)
|
||||
//creating new value in registry
|
||||
{
|
||||
if(regs==0)
|
||||
create_registry();
|
||||
regs=(struct reg_value*)realloc(regs, sizeof(struct reg_value)*(reg_size+1));
|
||||
v=regs+reg_size;
|
||||
reg_size++;
|
||||
}
|
||||
else
|
||||
//replacing old one
|
||||
{
|
||||
free(v->value);
|
||||
free(v->name);
|
||||
}
|
||||
v->type=type;
|
||||
v->len=len;
|
||||
v->value=(char*)malloc(len);
|
||||
memcpy(v->value, value, len);
|
||||
v->name=(char*)malloc(strlen(fullname)+1);
|
||||
strcpy(v->name, fullname);
|
||||
save_registry();
|
||||
return v;
|
||||
}
|
||||
|
||||
static void init_registry()
|
||||
{
|
||||
printf("Initializing registry\n");
|
||||
open_registry();
|
||||
insert_handle(HKEY_LOCAL_MACHINE, "HKLM");
|
||||
insert_handle(HKEY_CURRENT_USER, "HKCU");
|
||||
}
|
||||
static reg_handle_t* find_handle_2(long key, const char* subkey)
|
||||
{
|
||||
char* full_name;
|
||||
reg_handle_t* t;
|
||||
if((t=find_handle(key))==0)
|
||||
{
|
||||
TRACE("Invalid key\n");
|
||||
return (reg_handle_t*)-1;
|
||||
}
|
||||
if(subkey==NULL)
|
||||
return t;
|
||||
full_name=(char*)malloc(strlen(t->name)+strlen(subkey)+10);
|
||||
strcpy(full_name, t->name);
|
||||
strcat(full_name, "\\");
|
||||
strcat(full_name, subkey);
|
||||
t=find_handle_by_name(full_name);
|
||||
free(full_name);
|
||||
return t;
|
||||
}
|
||||
|
||||
long RegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
|
||||
{
|
||||
char* full_name;
|
||||
reg_handle_t* t;
|
||||
struct reg_value* v;
|
||||
TRACE("Opening key %s\n", subkey);
|
||||
|
||||
if(!regs)
|
||||
init_registry()
|
||||
;
|
||||
/* t=find_handle_2(key, subkey);
|
||||
|
||||
if(t==0)
|
||||
return -1;
|
||||
|
||||
if(t==(reg_handle_t*)-1)
|
||||
return -1;
|
||||
|
||||
*/ full_name=build_keyname(key, subkey);
|
||||
if(!full_name)
|
||||
return -1;
|
||||
v=find_value_by_name(full_name);
|
||||
|
||||
t=insert_handle(generate_handle(), full_name);
|
||||
*newkey=t->handle;
|
||||
free(full_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
long RegCloseKey(long key)
|
||||
{
|
||||
reg_handle_t *handle;
|
||||
if(key==HKEY_LOCAL_MACHINE)
|
||||
return 0;
|
||||
if(key==HKEY_CURRENT_USER)
|
||||
return 0;
|
||||
handle=find_handle(key);
|
||||
if(handle==0)
|
||||
return 0;
|
||||
if(handle->prev)
|
||||
handle->prev->next=handle->next;
|
||||
if(handle->next)
|
||||
handle->next->prev=handle->prev;
|
||||
if(handle->name)
|
||||
free(handle->name);
|
||||
if(handle==head)
|
||||
head=head->prev;
|
||||
free(handle);
|
||||
return 1;
|
||||
}
|
||||
long RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
|
||||
{
|
||||
struct reg_value* t;
|
||||
char* c;
|
||||
TRACE("Querying value %s\n", value);
|
||||
if(!regs)
|
||||
init_registry()
|
||||
;
|
||||
c=build_keyname(key, value);
|
||||
if(c==NULL)
|
||||
return 1;
|
||||
if((t=find_value_by_name(c))==0)
|
||||
{
|
||||
free(c);
|
||||
return 2;
|
||||
}
|
||||
free(c);
|
||||
if(type)
|
||||
*type=t->type;
|
||||
if(data)
|
||||
memcpy(data, t->value, (t->len<*count)?t->len:*count);
|
||||
if(count)
|
||||
{
|
||||
if(*count<t->len)
|
||||
{
|
||||
*count=t->len;
|
||||
return ERROR_MORE_DATA;
|
||||
}else return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
long RegCreateKeyExA(long key, const char* name, long reserved,
|
||||
void* classs, long options, long security,
|
||||
void* sec_attr, int* newkey, int* status)
|
||||
{
|
||||
reg_handle_t* t;
|
||||
char* fullname;
|
||||
struct reg_value* v;
|
||||
TRACE("Creating/Opening key %s\n", name);
|
||||
if(!regs)
|
||||
init_registry()
|
||||
;
|
||||
fullname=build_keyname(key, name);
|
||||
if(fullname==NULL)
|
||||
return 1;
|
||||
v=find_value_by_name(fullname);
|
||||
if(v==0)
|
||||
{
|
||||
int qw=45708;
|
||||
v=insert_reg_value(key, name, DIR, &qw, 4);
|
||||
*status=REG_CREATED_NEW_KEY;
|
||||
// return 0;
|
||||
}
|
||||
else
|
||||
*status=REG_OPENED_EXISTING_KEY;
|
||||
|
||||
t=insert_handle(generate_handle(), fullname);
|
||||
*newkey=t->handle;
|
||||
free(fullname);
|
||||
return 0;
|
||||
}
|
||||
long RegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
|
||||
{
|
||||
struct reg_value* t;
|
||||
char* c;
|
||||
TRACE("Request to set value %s\n", name);
|
||||
if(!regs)
|
||||
init_registry()
|
||||
;
|
||||
c=build_keyname(key, name);
|
||||
if(c==NULL)
|
||||
return 1;
|
||||
insert_reg_value(key, name, v2, data, size);
|
||||
free(c);
|
||||
return 0;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/********************************************************
|
||||
|
||||
Declaration of registry access functions
|
||||
Copyright 2000 Eugene Smith (divx@euro.ru)
|
||||
Last modified: 18.06.2000
|
||||
|
||||
*********************************************************/
|
||||
|
||||
|
||||
#ifndef REGISTRY_H
|
||||
#define REGISTRY_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
long RegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey);
|
||||
long RegCloseKey(long key);
|
||||
long RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count);
|
||||
long RegCreateKeyExA(long key, const char* name, long reserved,
|
||||
void* classs, long options, long security,
|
||||
void* sec_attr, int* newkey, int* status) ;
|
||||
long RegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size);
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
#endif
|
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* Resources
|
||||
*
|
||||
* Copyright 1993 Robert J. Amstadt
|
||||
* Copyright 1995 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <wine/winbase.h>
|
||||
#include <wine/windef.h>
|
||||
#include <wine/winuser.h>
|
||||
#include <wine/heap.h>
|
||||
#include <wine/module.h>
|
||||
#include <wine/debugtools.h>
|
||||
#include <wine/winerror.h>
|
||||
#define CP_ACP 0
|
||||
|
||||
WORD WINE_LanguageId=0x409;//english
|
||||
|
||||
#define HRSRC_MAP_BLOCKSIZE 16
|
||||
|
||||
typedef struct _HRSRC_ELEM
|
||||
{
|
||||
HANDLE hRsrc;
|
||||
WORD type;
|
||||
} HRSRC_ELEM;
|
||||
|
||||
typedef struct _HRSRC_MAP
|
||||
{
|
||||
int nAlloc;
|
||||
int nUsed;
|
||||
HRSRC_ELEM *elem;
|
||||
} HRSRC_MAP;
|
||||
|
||||
static HRSRC RES_FindResource2( HMODULE hModule, LPCSTR type,
|
||||
LPCSTR name, WORD lang, int unicode)
|
||||
{
|
||||
HRSRC hRsrc = 0;
|
||||
LPWSTR typeStr, nameStr;
|
||||
WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
|
||||
|
||||
if(!wm)
|
||||
return 0;
|
||||
/* 32-bit PE module */
|
||||
|
||||
|
||||
if ( HIWORD( type ) && (!unicode))
|
||||
typeStr = HEAP_strdupAtoW( GetProcessHeap(), 0, type );
|
||||
else
|
||||
typeStr = (LPWSTR)type;
|
||||
if ( HIWORD( name ) && (!unicode))
|
||||
nameStr = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
|
||||
else
|
||||
nameStr = (LPWSTR)name;
|
||||
|
||||
hRsrc = PE_FindResourceExW( wm, nameStr, typeStr, lang );
|
||||
|
||||
if ( HIWORD( type ) && (!unicode))
|
||||
HeapFree( GetProcessHeap(), 0, typeStr );
|
||||
if ( HIWORD( name ) && (!unicode))
|
||||
HeapFree( GetProcessHeap(), 0, nameStr );
|
||||
|
||||
return hRsrc;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RES_FindResource
|
||||
*/
|
||||
|
||||
static HRSRC RES_FindResource( HMODULE hModule, LPCSTR type,
|
||||
LPCSTR name, WORD lang, int unicode )
|
||||
{
|
||||
HRSRC hRsrc;
|
||||
// __TRY
|
||||
// {
|
||||
hRsrc = RES_FindResource2(hModule, type, name, lang, unicode);
|
||||
// }
|
||||
// __EXCEPT(page_fault)
|
||||
// {
|
||||
// WARN("page fault\n");
|
||||
// SetLastError(ERROR_INVALID_PARAMETER);
|
||||
// return 0;
|
||||
// }
|
||||
// __ENDTRY
|
||||
return hRsrc;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RES_SizeofResource
|
||||
*/
|
||||
static DWORD RES_SizeofResource( HMODULE hModule, HRSRC hRsrc)
|
||||
{
|
||||
DWORD size = 0;
|
||||
HRSRC hRsrc32;
|
||||
|
||||
// HMODULE16 hMod16 = MapHModuleLS( hModule );
|
||||
// NE_MODULE *pModule = NE_GetPtr( hMod16 );
|
||||
// WINE_MODREF *wm = pModule && pModule->module32?
|
||||
// MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
|
||||
WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
|
||||
|
||||
if ( !hModule || !hRsrc ) return 0;
|
||||
|
||||
/* 32-bit PE module */
|
||||
/* If we got a 16-bit hRsrc, convert it */
|
||||
// hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
|
||||
if(!HIWORD(hRsrc))
|
||||
{
|
||||
printf("16-bit hRsrcs not supported\n");
|
||||
return 0;
|
||||
}
|
||||
size = PE_SizeofResource( hModule, hRsrc );
|
||||
return size;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RES_AccessResource
|
||||
*/
|
||||
static HFILE RES_AccessResource( HMODULE hModule, HRSRC hRsrc )
|
||||
{
|
||||
HFILE hFile = HFILE_ERROR;
|
||||
|
||||
WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
|
||||
|
||||
if ( !hModule || !hRsrc ) return HFILE_ERROR;
|
||||
|
||||
/* 32-bit PE module */
|
||||
FIXME("32-bit modules not yet supported.\n" );
|
||||
hFile = HFILE_ERROR;
|
||||
|
||||
return hFile;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RES_LoadResource
|
||||
*/
|
||||
static HGLOBAL RES_LoadResource( HMODULE hModule, HRSRC hRsrc)
|
||||
{
|
||||
HGLOBAL hMem = 0;
|
||||
HRSRC hRsrc32;
|
||||
WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
|
||||
|
||||
|
||||
if ( !hModule || !hRsrc ) return 0;
|
||||
|
||||
/* 32-bit PE module */
|
||||
|
||||
/* If we got a 16-bit hRsrc, convert it */
|
||||
// hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
|
||||
if(!HIWORD(hRsrc))
|
||||
{
|
||||
printf("16-bit hRsrcs not supported\n");
|
||||
return 0;
|
||||
}
|
||||
hMem = PE_LoadResource( wm, hRsrc );
|
||||
|
||||
return hMem;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RES_LockResource
|
||||
*/
|
||||
static LPVOID RES_LockResource( HGLOBAL handle )
|
||||
{
|
||||
LPVOID bits = NULL;
|
||||
|
||||
TRACE("(%08x, %s)\n", handle, "PE" );
|
||||
|
||||
bits = (LPVOID)handle;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RES_FreeResource
|
||||
*/
|
||||
static WIN_BOOL RES_FreeResource( HGLOBAL handle )
|
||||
{
|
||||
HGLOBAL retv = handle;
|
||||
return (WIN_BOOL)retv;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* FindResourceA (KERNEL32.128)
|
||||
*/
|
||||
HANDLE WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
|
||||
{
|
||||
return RES_FindResource( hModule, type, name,
|
||||
WINE_LanguageId, 0);
|
||||
}
|
||||
HANDLE WINAPI FindResourceW( HMODULE hModule, LPCWSTR name, LPCWSTR type )
|
||||
{
|
||||
return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name,
|
||||
WINE_LanguageId, 1);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* FindResourceExA (KERNEL32.129)
|
||||
*/
|
||||
HANDLE WINAPI FindResourceExA( HMODULE hModule,
|
||||
LPCSTR type, LPCSTR name, WORD lang )
|
||||
{
|
||||
return RES_FindResource( hModule, type, name,
|
||||
lang, 0 );
|
||||
}
|
||||
|
||||
HANDLE WINAPI FindResourceExW( HMODULE hModule,
|
||||
LPCWSTR type, LPCWSTR name, WORD lang )
|
||||
{
|
||||
return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name,
|
||||
lang, 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* LockResource (KERNEL32.384)
|
||||
*/
|
||||
LPVOID WINAPI LockResource( HGLOBAL handle )
|
||||
{
|
||||
return RES_LockResource( handle );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* FreeResource (KERNEL32.145)
|
||||
*/
|
||||
WIN_BOOL WINAPI FreeResource( HGLOBAL handle )
|
||||
{
|
||||
return RES_FreeResource( handle );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* AccessResource (KERNEL32.64)
|
||||
*/
|
||||
INT WINAPI AccessResource( HMODULE hModule, HRSRC hRsrc )
|
||||
{
|
||||
return RES_AccessResource( hModule, hRsrc );
|
||||
}
|
||||
/**********************************************************************
|
||||
* SizeofResource (KERNEL32.522)
|
||||
*/
|
||||
DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
|
||||
{
|
||||
return RES_SizeofResource( hModule, hRsrc );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* LoadStringA (USER32.375)
|
||||
*/
|
||||
INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id,
|
||||
LPSTR buffer, INT buflen )
|
||||
{
|
||||
INT retval;
|
||||
INT wbuflen;
|
||||
INT abuflen;
|
||||
LPWSTR wbuf = NULL;
|
||||
LPSTR abuf = NULL;
|
||||
|
||||
if ( buffer != NULL && buflen > 0 )
|
||||
*buffer = 0;
|
||||
|
||||
wbuflen = LoadStringW(instance,resource_id,NULL,0);
|
||||
if ( !wbuflen )
|
||||
return 0;
|
||||
wbuflen ++;
|
||||
|
||||
retval = 0;
|
||||
wbuf = HeapAlloc( GetProcessHeap(), 0, wbuflen * sizeof(WCHAR) );
|
||||
wbuflen = LoadStringW(instance,resource_id,wbuf,wbuflen);
|
||||
if ( wbuflen > 0 )
|
||||
{
|
||||
abuflen = WideCharToMultiByte(CP_ACP,0,wbuf,wbuflen,NULL,0,NULL,NULL);
|
||||
if ( abuflen > 0 )
|
||||
{
|
||||
if ( buffer == NULL || buflen == 0 )
|
||||
retval = abuflen;
|
||||
else
|
||||
{
|
||||
abuf = HeapAlloc( GetProcessHeap(), 0, abuflen * sizeof(CHAR) );
|
||||
abuflen = WideCharToMultiByte(CP_ACP,0,wbuf,wbuflen,abuf,abuflen,NULL,NULL);
|
||||
if ( abuflen > 0 )
|
||||
{
|
||||
abuflen = min(abuflen,buflen - 1);
|
||||
memcpy( buffer, abuf, abuflen );
|
||||
buffer[abuflen] = 0;
|
||||
retval = abuflen;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, abuf );
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, wbuf );
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* LoadStringW (USER32.376)
|
||||
*/
|
||||
INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
|
||||
LPWSTR buffer, INT buflen )
|
||||
{
|
||||
HGLOBAL hmem;
|
||||
HRSRC hrsrc;
|
||||
WCHAR *p;
|
||||
int string_num;
|
||||
int i;
|
||||
|
||||
if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
|
||||
resource_id = (UINT)(-((INT)resource_id));
|
||||
TRACE("instance = %04x, id = %04x, buffer = %08x, "
|
||||
"length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
|
||||
|
||||
/* Use bits 4 - 19 (incremented by 1) as resourceid, mask out
|
||||
* 20 - 31. */
|
||||
hrsrc = FindResourceW( instance, (LPCWSTR)(((resource_id>>4)&0xffff)+1),
|
||||
RT_STRINGW );
|
||||
if (!hrsrc) return 0;
|
||||
hmem = LoadResource( instance, hrsrc );
|
||||
if (!hmem) return 0;
|
||||
|
||||
p = LockResource(hmem);
|
||||
string_num = resource_id & 0x000f;
|
||||
for (i = 0; i < string_num; i++)
|
||||
p += *p + 1;
|
||||
|
||||
TRACE("strlen = %d\n", (int)*p );
|
||||
|
||||
if (buffer == NULL) return *p;
|
||||
i = min(buflen - 1, *p);
|
||||
if (i > 0) {
|
||||
memcpy(buffer, p + 1, i * sizeof (WCHAR));
|
||||
buffer[i] = (WCHAR) 0;
|
||||
} else {
|
||||
if (buflen > 1) {
|
||||
buffer[0] = (WCHAR) 0;
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
TRACE("String loaded !\n");
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Messages...used by FormatMessage32* (KERNEL32.something)
|
||||
*
|
||||
* They can be specified either directly or using a message ID and
|
||||
* loading them from the resource.
|
||||
*
|
||||
* The resourcedata has following format:
|
||||
* start:
|
||||
* 0: DWORD nrofentries
|
||||
* nrofentries * subentry:
|
||||
* 0: DWORD firstentry
|
||||
* 4: DWORD lastentry
|
||||
* 8: DWORD offset from start to the stringentries
|
||||
*
|
||||
* (lastentry-firstentry) * stringentry:
|
||||
* 0: WORD len (0 marks end)
|
||||
* 2: WORD flags
|
||||
* 4: CHAR[len-4]
|
||||
* (stringentry i of a subentry refers to the ID 'firstentry+i')
|
||||
*
|
||||
* Yes, ANSI strings in win32 resources. Go figure.
|
||||
*/
|
||||
|
||||
/**********************************************************************
|
||||
* LoadMessageA (internal)
|
||||
*/
|
||||
INT WINAPI LoadMessageA( HMODULE instance, UINT id, WORD lang,
|
||||
LPSTR buffer, INT buflen )
|
||||
{
|
||||
HGLOBAL hmem;
|
||||
HRSRC hrsrc;
|
||||
PMESSAGE_RESOURCE_DATA mrd;
|
||||
PMESSAGE_RESOURCE_BLOCK mrb;
|
||||
PMESSAGE_RESOURCE_ENTRY mre;
|
||||
int i,slen;
|
||||
|
||||
TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
|
||||
|
||||
/*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
|
||||
hrsrc = FindResourceExW(instance,RT_MESSAGELISTW,(LPWSTR)1,lang);
|
||||
if (!hrsrc) return 0;
|
||||
hmem = LoadResource( instance, hrsrc );
|
||||
if (!hmem) return 0;
|
||||
|
||||
mrd = (PMESSAGE_RESOURCE_DATA)LockResource(hmem);
|
||||
mre = NULL;
|
||||
mrb = &(mrd->Blocks[0]);
|
||||
for (i=mrd->NumberOfBlocks;i--;) {
|
||||
if ((id>=mrb->LowId) && (id<=mrb->HighId)) {
|
||||
mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mrd)+mrb->OffsetToEntries);
|
||||
id -= mrb->LowId;
|
||||
break;
|
||||
}
|
||||
mrb++;
|
||||
}
|
||||
if (!mre)
|
||||
return 0;
|
||||
for (i=id;i--;) {
|
||||
if (!mre->Length)
|
||||
return 0;
|
||||
mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mre)+(mre->Length));
|
||||
}
|
||||
slen=mre->Length;
|
||||
TRACE(" - strlen=%d\n",slen);
|
||||
i = min(buflen - 1, slen);
|
||||
if (buffer == NULL)
|
||||
return slen;
|
||||
if (i>0) {
|
||||
lstrcpynA(buffer,(char*)mre->Text,i);
|
||||
buffer[i]=0;
|
||||
} else {
|
||||
if (buflen>1) {
|
||||
buffer[0]=0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (buffer)
|
||||
TRACE("'%s' copied !\n", buffer);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* EnumResourceTypesA (KERNEL32.90)
|
||||
*/
|
||||
WIN_BOOL WINAPI EnumResourceTypesA( HMODULE hmodule,ENUMRESTYPEPROCA lpfun,
|
||||
LONG lParam)
|
||||
{
|
||||
/* FIXME: move WINE_MODREF stuff here */
|
||||
return PE_EnumResourceTypesA(hmodule,lpfun,lParam);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* EnumResourceNamesA (KERNEL32.88)
|
||||
*/
|
||||
WIN_BOOL WINAPI EnumResourceNamesA( HMODULE hmodule, LPCSTR type,
|
||||
ENUMRESNAMEPROCA lpfun, LONG lParam )
|
||||
{
|
||||
/* FIXME: move WINE_MODREF stuff here */
|
||||
return PE_EnumResourceNamesA(hmodule,type,lpfun,lParam);
|
||||
}
|
||||
/**********************************************************************
|
||||
* EnumResourceLanguagesA (KERNEL32.86)
|
||||
*/
|
||||
WIN_BOOL WINAPI EnumResourceLanguagesA( HMODULE hmodule, LPCSTR type,
|
||||
LPCSTR name, ENUMRESLANGPROCA lpfun,
|
||||
LONG lParam)
|
||||
{
|
||||
/* FIXME: move WINE_MODREF stuff here */
|
||||
return PE_EnumResourceLanguagesA(hmodule,type,name,lpfun,lParam);
|
||||
}
|
||||
/**********************************************************************
|
||||
* LoadResource (KERNEL32.370)
|
||||
*/
|
||||
HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
|
||||
{
|
||||
return RES_LoadResource( hModule, hRsrc);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
.file "stubs.c"
|
||||
.version "01.01"
|
||||
gcc2_compiled.:
|
||||
.section .rodata
|
||||
.LC0:
|
||||
.string "Called unk_%s\n"
|
||||
.text
|
||||
.align 4
|
||||
.globl unk_exp1
|
||||
.type unk_exp1,@function
|
||||
unk_exp1:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
subl $4,%esp
|
||||
movl $1,-4(%ebp)
|
||||
movl -4(%ebp),%eax
|
||||
movl %eax,%ecx
|
||||
movl %ecx,%edx
|
||||
sall $4,%edx
|
||||
subl %eax,%edx
|
||||
leal 0(,%edx,2),%eax
|
||||
movl %eax,%edx
|
||||
addl $export_names,%edx
|
||||
pushl %edx
|
||||
pushl $.LC0
|
||||
call printf
|
||||
addl $8,%esp
|
||||
xorl %eax,%eax
|
||||
jmp .L1
|
||||
.align 4
|
||||
.L1:
|
||||
leave
|
||||
ret
|
||||
.Lfe1:
|
||||
.size unk_exp1,.Lfe1-unk_exp1
|
||||
.ident "GCC: (GNU) egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)"
|
|
@ -1,375 +0,0 @@
|
|||
/*
|
||||
* Copyright 1998 Marcus Meissner
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wine/winbase.h>
|
||||
#include <wine/windef.h>
|
||||
#include <wine/winuser.h>
|
||||
#include <wine/vfw.h>
|
||||
#include <wine/winestring.h>
|
||||
#include <wine/driver.h>
|
||||
#include <avifmt.h>
|
||||
|
||||
#define FIXME_(X) printf
|
||||
#define FIXME printf
|
||||
|
||||
long VFWAPI VideoForWindowsVersion(void);
|
||||
|
||||
|
||||
long VFWAPIV ICDecompress(HIC hic,long dwFlags,LPBITMAPINFOHEADER lpbiFormat,void* lpData,LPBITMAPINFOHEADER lpbi,void* lpBits);
|
||||
|
||||
WIN_BOOL VFWAPI ICInfo(long fccType, long fccHandler, ICINFO * lpicinfo);
|
||||
LRESULT VFWAPI ICGetInfo(HIC hic,ICINFO *picinfo, long cb);
|
||||
HIC VFWAPI ICOpen(long fccType, long fccHandler, UINT wMode);
|
||||
HIC VFWAPI ICOpenFunction(long fccType, long fccHandler, unsigned int wMode, void* lpfnHandler);
|
||||
|
||||
LRESULT VFWAPI ICClose(HIC hic);
|
||||
LRESULT VFWAPI ICSendMessage(HIC hic, unsigned int msg, long dw1, long dw2);
|
||||
HIC VFWAPI ICLocate(long fccType, long fccHandler, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, short wFlags);
|
||||
|
||||
#define OpenDriverA DrvOpen
|
||||
extern HDRVR VFWAPI DrvOpen(long);
|
||||
#define STORE_ALL \
|
||||
__asm__ ( \
|
||||
"push %%ebx\n\t" \
|
||||
"push %%ecx\n\t" \
|
||||
"push %%edx\n\t" \
|
||||
"push %%esi\n\t" \
|
||||
"push %%edi\n\t"::)
|
||||
|
||||
#define REST_ALL \
|
||||
__asm__ ( \
|
||||
"pop %%edi\n\t" \
|
||||
"pop %%esi\n\t" \
|
||||
"pop %%edx\n\t" \
|
||||
"pop %%ecx\n\t" \
|
||||
"pop %%ebx\n\t"::)
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned int uDriverSignature;
|
||||
void* hDriverModule;
|
||||
void* DriverProc;
|
||||
long dwDriverID;
|
||||
} DRVR;
|
||||
|
||||
/***********************************************************************
|
||||
* VideoForWindowsVersion [MSVFW.2][MSVIDEO.2]
|
||||
* Returns the version in major.minor form.
|
||||
* In Windows95 this returns 0x040003b6 (4.950)
|
||||
*/
|
||||
long VideoForWindowsVersion(void) {
|
||||
return 0x040003B6; /* 4.950 */
|
||||
}
|
||||
|
||||
/* system.ini: [drivers] */
|
||||
|
||||
/***********************************************************************
|
||||
* ICInfo [MSVFW.33]
|
||||
* Get information about an installable compressor. Return TRUE if there
|
||||
* is one.
|
||||
*/
|
||||
int VFWAPI
|
||||
ICInfo(
|
||||
long fccType, /* [in] type of compressor ('vidc') */
|
||||
long fccHandler, /* [in] <n>th compressor */
|
||||
ICINFO *lpicinfo /* [out] information about compressor */
|
||||
) {
|
||||
char type[5],buf[2000];
|
||||
|
||||
memcpy(type,&fccType,4);type[4]=0;
|
||||
TRACE("(%s,%ld,%p).\n",type,fccHandler,lpicinfo);
|
||||
/* does OpenDriver/CloseDriver */
|
||||
lpicinfo->dwSize = sizeof(ICINFO);
|
||||
lpicinfo->fccType = fccType;
|
||||
lpicinfo->dwFlags = 0;
|
||||
/*
|
||||
if (GetPrivateProfileStringA("drivers32",NULL,NULL,buf,2000,"system.ini")) {
|
||||
char *s = buf;
|
||||
while (*s) {
|
||||
if (!lstrncmpiA(type,s,4)) {
|
||||
if(!fccHandler--) {
|
||||
lpicinfo->fccHandler = mmioStringToFOURCCA(s+5,0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
s=s+lstrlenA(s)+1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ICOpen [MSVFW.37]
|
||||
* Opens an installable compressor. Return special handle.
|
||||
*/
|
||||
HIC VFWAPI
|
||||
ICOpen(long fccType,long fccHandler,unsigned int wMode) {
|
||||
char type[5],handler[5],codecname[20];
|
||||
ICOPEN icopen;
|
||||
HDRVR hdrv;
|
||||
WINE_HIC *whic;
|
||||
|
||||
memcpy(type,&fccType,4);type[4]=0;
|
||||
memcpy(handler,&fccHandler,4);handler[4]=0;
|
||||
TRACE("(%s,%s,0x%08lx)\n",type,handler,(long)wMode);
|
||||
sprintf(codecname,"%s.%s",type,handler);
|
||||
|
||||
/* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
|
||||
* same layout as ICOPEN
|
||||
*/
|
||||
icopen.fccType = fccType;
|
||||
icopen.fccHandler = fccHandler;
|
||||
icopen.dwSize = sizeof(ICOPEN);
|
||||
icopen.dwFlags = wMode;
|
||||
/* FIXME: do we need to fill out the rest too? */
|
||||
// hdrv=OpenDriverA(codecname,"drivers32",(long)&icopen);
|
||||
hdrv=OpenDriverA((long)&icopen);
|
||||
/*
|
||||
if (!hdrv) {
|
||||
if (!strcasecmp(type,"vids")) {
|
||||
sprintf(codecname,"vidc.%s",handler);
|
||||
fccType = mmioFOURCC('v','i','d','c');
|
||||
}
|
||||
// hdrv=OpenDriverA(codecname,"drivers32",(long)&icopen);
|
||||
hdrv=OpenDriverA((long)&icopen);
|
||||
*/
|
||||
if (!hdrv)
|
||||
return 0;
|
||||
// }
|
||||
whic = (WINE_HIC*)my_mreq(sizeof(WINE_HIC), 0);
|
||||
whic->hdrv = hdrv;
|
||||
whic->driverproc= ((DRVR*)hdrv)->DriverProc;
|
||||
// whic->private = ICSendMessage((HIC)whic,DRV_OPEN,0,(long)&icopen);
|
||||
whic->private = ((DRVR*)hdrv)->dwDriverID;
|
||||
return (HIC)whic;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ICOpenFunction [MSVFW.38]
|
||||
*/
|
||||
HIC VFWAPI ICOpenFunction(long fccType, long fccHandler, unsigned int wMode,
|
||||
void* lpfnHandler) {
|
||||
char type[5],handler[5];
|
||||
HIC hic;
|
||||
WINE_HIC *whic;
|
||||
|
||||
memcpy(type,&fccType,4);type[4]=0;
|
||||
memcpy(handler,&fccHandler,4);handler[4]=0;
|
||||
FIXME("(%s,%s,%d,%p), stub!\n",type,handler,wMode,lpfnHandler);
|
||||
hic = ICOpen(fccType,fccHandler,wMode);
|
||||
if (!hic)
|
||||
return hic;
|
||||
whic = (WINE_HIC*)hic;
|
||||
whic->driverproc = lpfnHandler;
|
||||
return hic;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ICGetInfo [MSVFW.30]
|
||||
*/
|
||||
LRESULT VFWAPI
|
||||
ICGetInfo(HIC hic,ICINFO *picinfo,long cb) {
|
||||
LRESULT ret;
|
||||
|
||||
TRACE("(0x%08lx,%p,%ld)\n",(long)hic,picinfo,cb);
|
||||
ret = ICSendMessage(hic,ICM_GETINFO,(long)picinfo,cb);
|
||||
TRACE(" -> 0x%08lx\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ICLocate [MSVFW.35]
|
||||
*/
|
||||
HIC VFWAPI
|
||||
ICLocate(
|
||||
long fccType, long fccHandler, LPBITMAPINFOHEADER lpbiIn,
|
||||
LPBITMAPINFOHEADER lpbiOut, short wMode
|
||||
) {
|
||||
char type[5],handler[5];
|
||||
HIC hic;
|
||||
long querymsg;
|
||||
|
||||
switch (wMode) {
|
||||
case ICMODE_FASTCOMPRESS:
|
||||
case ICMODE_COMPRESS:
|
||||
querymsg = ICM_COMPRESS_QUERY;
|
||||
break;
|
||||
case ICMODE_DECOMPRESS:
|
||||
case ICMODE_FASTDECOMPRESS:
|
||||
querymsg = ICM_DECOMPRESS_QUERY;
|
||||
break;
|
||||
case ICMODE_DRAW:
|
||||
querymsg = ICM_DRAW_QUERY;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown mode (%d)\n",wMode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Easy case: handler/type match, we just fire a query and return */
|
||||
hic = ICOpen(fccType,fccHandler,wMode);
|
||||
if (hic) {
|
||||
if (!ICSendMessage(hic,querymsg,(long)lpbiIn,(long)lpbiOut))
|
||||
return hic;
|
||||
ICClose(hic);
|
||||
}
|
||||
type[4]='\0';memcpy(type,&fccType,4);
|
||||
handler[4]='\0';memcpy(handler,&fccHandler,4);
|
||||
if (fccType==streamtypeVIDEO) {
|
||||
hic = ICLocate(ICTYPE_VIDEO,fccHandler,lpbiIn,lpbiOut,wMode);
|
||||
if (hic)
|
||||
return hic;
|
||||
}
|
||||
FIXME("(%s,%s,%p,%p,0x%04x),unhandled!\n",type,handler,lpbiIn,lpbiOut,wMode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ICCompress [MSVFW.23]
|
||||
*/
|
||||
long VFWAPIV
|
||||
ICCompress(
|
||||
HIC hic,long dwFlags,LPBITMAPINFOHEADER lpbiOutput,void* lpData,
|
||||
LPBITMAPINFOHEADER lpbiInput,void* lpBits,long* lpckid,
|
||||
long* lpdwFlags,long lFrameNum,long dwFrameSize,long dwQuality,
|
||||
LPBITMAPINFOHEADER lpbiPrev,void* lpPrev
|
||||
) {
|
||||
ICCOMPRESS iccmp;
|
||||
|
||||
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,(long)&iccmp,sizeof(iccmp));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ICDecompress [MSVFW.26]
|
||||
*/
|
||||
long VFWAPIV
|
||||
ICDecompress(HIC hic,long dwFlags,LPBITMAPINFOHEADER lpbiFormat,void* lpData,LPBITMAPINFOHEADER lpbi,void* lpBits) {
|
||||
ICDECOMPRESS icd;
|
||||
int result;
|
||||
icd.dwFlags = dwFlags;
|
||||
icd.lpbiInput = lpbiFormat;
|
||||
icd.lpInput = lpData;
|
||||
|
||||
icd.lpbiOutput = lpbi;
|
||||
icd.lpOutput = lpBits;
|
||||
icd.ckid = 0;
|
||||
STORE_ALL;
|
||||
result=ICSendMessage(hic,ICM_DECOMPRESS,(long)&icd,sizeof(icd));
|
||||
REST_ALL;
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ICSendMessage [MSVFW.40]
|
||||
*/
|
||||
LRESULT VFWAPI
|
||||
ICSendMessage(HIC hic,unsigned int msg,long lParam1,long lParam2) {
|
||||
LRESULT ret;
|
||||
WINE_HIC *whic = (WINE_HIC*)hic;
|
||||
char qw[200];
|
||||
#define XX(x) case x: TRACE("(0x%08lx,"#x",0x%08lx,0x%08lx)\n",(long)hic,lParam1,lParam2);break;
|
||||
/*
|
||||
switch (msg) {
|
||||
XX(ICM_ABOUT)
|
||||
XX(ICM_GETINFO)
|
||||
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("(0x%08lx,0x%08lx,0x%08lx,0x%08lx)\n",(long)hic,(long)msg,lParam1,lParam2);
|
||||
}
|
||||
*/
|
||||
// if (whic->driverproc) {
|
||||
// FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx), calling %p\n",(long)hic,(long)msg,lParam1,lParam2,whic->driverproc);
|
||||
// printf("private=%x\n", whic->private);
|
||||
__asm__ __volatile__ ("fsave (%0)\n\t": :"r"(&qw));
|
||||
STORE_ALL;
|
||||
/*__asm__
|
||||
(
|
||||
"pushl %eax\n\t"
|
||||
"movl $0xf,%eax\n\t"
|
||||
"movw %ax, %fs\n\t"
|
||||
"popl %eax\n\t"
|
||||
);*/
|
||||
ret = whic->driverproc(whic->private,1,msg,lParam1,lParam2);
|
||||
REST_ALL;
|
||||
__asm__ __volatile__ ("frstor (%0)\n\t": :"r"(&qw));
|
||||
// } else
|
||||
|
||||
// ret = SendDriverMessage(whic->hdrv,msg,lParam1,lParam2);
|
||||
// TRACE(" -> 0x%08lx\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ICClose [MSVFW.22]
|
||||
*/
|
||||
LRESULT VFWAPI ICClose(HIC hic) {
|
||||
WINE_HIC *whic = (WINE_HIC*)hic;
|
||||
TRACE("(%d).\n",hic);
|
||||
/* FIXME: correct? */
|
||||
// CloseDriver(whic->hdrv,0,0);
|
||||
DrvClose(whic->hdrv);
|
||||
//#warning FIXME: DrvClose
|
||||
my_release(whic);
|
||||
return 0;
|
||||
}
|
||||
int VFWAPI ICDoSomething()
|
||||
{
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1 +0,0 @@
|
|||
int ext_unknown();
|
|
@ -1,55 +0,0 @@
|
|||
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
|
||||
|
||||
/***********************************************************************
|
||||
* Wine specific - Win32
|
||||
*/
|
||||
typedef struct _WINE_ACMDRIVERID *PWINE_ACMDRIVERID;
|
||||
typedef struct _WINE_ACMDRIVER *PWINE_ACMDRIVER;
|
||||
|
||||
typedef struct _WINE_ACMOBJ
|
||||
{
|
||||
PWINE_ACMDRIVERID pACMDriverID;
|
||||
} WINE_ACMOBJ, *PWINE_ACMOBJ;
|
||||
|
||||
typedef struct _WINE_ACMDRIVER
|
||||
{
|
||||
WINE_ACMOBJ obj;
|
||||
HDRVR hDrvr;
|
||||
DRIVERPROC pfnDriverProc;
|
||||
PWINE_ACMDRIVER pNextACMDriver;
|
||||
} WINE_ACMDRIVER;
|
||||
|
||||
typedef struct _WINE_ACMSTREAM
|
||||
{
|
||||
WINE_ACMOBJ obj;
|
||||
PWINE_ACMDRIVER pDrv;
|
||||
ACMDRVSTREAMINSTANCE drvInst;
|
||||
HACMDRIVER hAcmDriver;
|
||||
} WINE_ACMSTREAM, *PWINE_ACMSTREAM;
|
||||
|
||||
typedef struct _WINE_ACMDRIVERID
|
||||
{
|
||||
LPSTR pszDriverAlias;
|
||||
LPSTR pszFileName;
|
||||
HINSTANCE hInstModule; /* NULL if global */
|
||||
DWORD dwProcessID; /* ID of process which installed a local driver */
|
||||
WIN_BOOL bEnabled;
|
||||
PWINE_ACMDRIVER pACMDriverList;
|
||||
PWINE_ACMDRIVERID pNextACMDriverID;
|
||||
PWINE_ACMDRIVERID pPrevACMDriverID;
|
||||
} WINE_ACMDRIVERID;
|
||||
|
||||
/* From internal.c */
|
||||
extern HANDLE MSACM_hHeap;
|
||||
extern PWINE_ACMDRIVERID MSACM_pFirstACMDriverID;
|
||||
extern PWINE_ACMDRIVERID MSACM_pLastACMDriverID;
|
||||
PWINE_ACMDRIVERID MSACM_RegisterDriver(
|
||||
LPSTR pszDriverAlias, LPSTR pszFileName,
|
||||
HINSTANCE hinstModule);
|
||||
void MSACM_RegisterAllDrivers(void);
|
||||
PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p);
|
||||
void MSACM_UnregisterAllDrivers(void);
|
||||
PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID);
|
||||
PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver);
|
||||
PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj);
|
||||
|
Loading…
Reference in a new issue