diff options
Diffstat (limited to 'src/libw32dll/wine')
-rw-r--r-- | src/libw32dll/wine/Makefile.am | 26 | ||||
-rw-r--r-- | src/libw32dll/wine/afl.c | 765 | ||||
-rw-r--r-- | src/libw32dll/wine/driver.c | 182 | ||||
-rw-r--r-- | src/libw32dll/wine/elfdll.c | 305 | ||||
-rw-r--r-- | src/libw32dll/wine/ext.c | 565 | ||||
-rw-r--r-- | src/libw32dll/wine/loader.h | 286 | ||||
-rw-r--r-- | src/libw32dll/wine/module.c | 618 | ||||
-rw-r--r-- | src/libw32dll/wine/pe_image.c | 936 | ||||
-rw-r--r-- | src/libw32dll/wine/pe_resource.c | 391 | ||||
-rw-r--r-- | src/libw32dll/wine/registry.c | 421 | ||||
-rw-r--r-- | src/libw32dll/wine/registry.h | 24 | ||||
-rw-r--r-- | src/libw32dll/wine/resource.c | 479 | ||||
-rw-r--r-- | src/libw32dll/wine/vfl.c | 330 | ||||
-rw-r--r-- | src/libw32dll/wine/win32.c | 1706 | ||||
-rw-r--r-- | src/libw32dll/wine/win32.h | 1 | ||||
-rw-r--r-- | src/libw32dll/wine/wineacm.h | 55 |
16 files changed, 7089 insertions, 1 deletions
diff --git a/src/libw32dll/wine/Makefile.am b/src/libw32dll/wine/Makefile.am index bbf9d835c..21835ddf2 100644 --- a/src/libw32dll/wine/Makefile.am +++ b/src/libw32dll/wine/Makefile.am @@ -1,9 +1,32 @@ +EXTRA_DIST = stubs.s + +CFLAGS = @BUILD_LIB_STATIC@ -fno-omit-frame-pointer @X_CFLAGS@ \ + -DWIN32_PATH=\"@w32_path@\" -pipe + + noinst_HEADERS = avifmt.h elfdll.h msacm.h pshpack1.h winbase.h \ winnt.h basetsd.h heap.h msacmdrv.h pshpack2.h\ windef.h winreg.h config.h ldt.h ntdef.h \ pshpack4.h windows.h winuser.h debugtools.h mmreg.h \ pe_image.h pshpack8.h winerror.h driver.h module.h \ - poppack.h vfw.h winestring.h + poppack.h vfw.h winestring.h \ + loader.h registry.h win32.h wineacm.h + + +if HAVE_W32DLL +wine_lib = libwine.la +endif + +noinst_LTLIBRARIES = $(wine_lib) + +libwine_la_SOURCES = afl.c elfdll.c module.c pe_resource.c \ + resource.c win32.c driver.c ext.c \ + pe_image.c registry.c vfl.c + +libwine_la_LIBADD = stubs.lo + +stubs.lo: stubs.s + $(CC) -c $(top_srcdir)/src/libw32dll/wine/stubs.s -o stubs.lo debug: @@ -14,3 +37,4 @@ maintainer-clean-generic: -@echo "This command is intended for maintainers to use;" -@echo "it deletes files that may require special tools to rebuild." -rm -f Makefile.in + diff --git a/src/libw32dll/wine/afl.c b/src/libw32dll/wine/afl.c new file mode 100644 index 000000000..2a6768db0 --- /dev/null +++ b/src/libw32dll/wine/afl.c @@ -0,0 +1,765 @@ +/************************************************************************** + + + 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 "config.h" + +#include <stdio.h> +#include <string.h> + +#include "winbase.h" +#include "windef.h" +#include "winuser.h" +#include "vfw.h" +#include "winestring.h" +#include "driver.h" +#include "winerror.h" +#include "msacm.h" +#include "msacmdrv.h" +#include "debugtools.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); // DivX/WMA [07] + MSACM_RegisterDriver("msadp32", (LPSTR)0x2, 0); // MS ADPCM [08] + MSACM_RegisterDriver("l3codeca", (LPSTR)0x55, 0); // MPEG Layer-3 [12] +// MSACM_RegisterDriver("imaadp32", (LPSTR)0x11, 0); // IMA ADPCM [13] +// MSACM_RegisterDriver("msgsm32", (LPSTR)0x32, 0); // MS GSM 6.10 [14] +} + +/*********************************************************************** + * 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; +} diff --git a/src/libw32dll/wine/driver.c b/src/libw32dll/wine/driver.c new file mode 100644 index 000000000..e0820d4c8 --- /dev/null +++ b/src/libw32dll/wine/driver.c @@ -0,0 +1,182 @@ +#include "config.h" +#include <stdio.h> + +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif + +#include "driver.h" +#include "pe_image.h" +#include "winreg.h" +#include "vfw.h" +#include "registry.h" + +#ifdef __FreeBSD__ +#include <sys/time.h> +#endif + +//#define WIN32_PATH "/usr/lib/win32" + +#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 { + 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); +} + + +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) { + if(((DRVR*)hDriver)->hDriverModule) + if(((DRVR*)hDriver)->DriverProc) + (((DRVR*)hDriver)->DriverProc)(0, hDriver, DRV_FREE, 0, 0); + FreeLibrary(((DRVR*)hDriver)->hDriverModule); + free((NPDRVR)hDriver); + return; + } +} + +void DrvClose(HDRVR hdrvr) +{ + DrvFree(hdrvr); +} + + +#ifndef STATIC_WIN32_PATH +char* def_path=WIN32_PATH; // path to codecs +#else +char* def_path="/usr/lib/win32"; // path to codecs +#endif +char* win32_codec_name=NULL; // must be set before calling DrvOpen() !!! + +HDRVR +DrvOpen(LPARAM lParam2) +{ + ICOPEN *icopen=lParam2; + UINT uDrvResult; + HDRVR hDriver; + NPDRVR npDriver; + char unknown[0x24]; +// char* codec_name=icopen->fccHandler; + + if (!(npDriver = DrvAlloc(&hDriver, &uDrvResult))) + return ((HDRVR) 0); + + if (!(npDriver->hDriverModule = expLoadLibraryA(win32_codec_name))) { + printf("Can't open library %s\n", win32_codec_name); + DrvFree(hDriver); + return ((HDRVR) 0); + } + + if (!(npDriver->DriverProc = (DRIVERPROC) + GetProcAddress(npDriver->hDriverModule, "DriverProc"))) { + printf("Library %s is not a valid codec\n", win32_codec_name); + FreeLibrary(npDriver->hDriverModule); + DrvFree(hDriver); + return ((HDRVR) 0); + } + + //TRACE("DriverProc == %X\n", npDriver->DriverProc); + npDriver->dwDriverID = ++dwDrvID; + + 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; + } + + printf("Successfully loaded codec %s\n",win32_codec_name); + + return (hDriver); +} + diff --git a/src/libw32dll/wine/elfdll.c b/src/libw32dll/wine/elfdll.c new file mode 100644 index 000000000..3b6923668 --- /dev/null +++ b/src/libw32dll/wine/elfdll.c @@ -0,0 +1,305 @@ +/* + * 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"; +extern char* def_path; + +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 = def_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*/ diff --git a/src/libw32dll/wine/ext.c b/src/libw32dll/wine/ext.c new file mode 100644 index 000000000..1847d6b34 --- /dev/null +++ b/src/libw32dll/wine/ext.c @@ -0,0 +1,565 @@ +/******************************************************** + * + * + * Stub functions for Wine module + * + * + ********************************************************/ +#include "config.h" +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdarg.h> +#include "windef.h" +//#include "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); + fflush(stdout); +#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; + for(i=0; i<srclen; i++) + printf("%c", src[i]); + printf("\n"); + if(dest==0) + { + for(i=0; i<srclen; i++) + { + src++; + if(*src==0) + return i+1; + } + return srclen+1; + } + if(used_defch) + *used_defch=0; + for(i=0; i<min(srclen, destlen); i++) + { + *dest=(char)*src; + dest++; + src++; + if(*src==0) + return i+1; + } + return min(srclen, destlen); +} +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; +} diff --git a/src/libw32dll/wine/loader.h b/src/libw32dll/wine/loader.h new file mode 100644 index 000000000..e2ee82c75 --- /dev/null +++ b/src/libw32dll/wine/loader.h @@ -0,0 +1,286 @@ +/******************************************************** + + Win32 binary loader interface + Copyright 2000 Eugene Smith (divx@euro.ru) + Shamelessly stolen from Wine project + +*********************************************************/ + +#ifndef _LOADER_H +#define _LOADER_H +#include <windef.h> +#include <driver.h> +#include <mmreg.h> +#include <vfw.h> +#include <msacm.h> +#ifdef __cplusplus +extern "C" { +#endif + +void SetCodecPath(const char* path); +unsigned int _GetPrivateProfileIntA(const char* appname, const char* keyname, int default_value, const char* filename); +int _GetPrivateProfileStringA(const char* appname, const char* keyname, + const char* def_val, char* dest, unsigned int len, const char* filename); +int _WritePrivateProfileStringA(const char* appname, const char* keyname, + const char* string, const char* filename); + + +/********************************************** + + MS VFW ( Video For Windows ) interface + +**********************************************/ + +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 +); + +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); + +int VFWAPI ICDoSomething(); + +#define ICCompressGetFormat(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic,ICM_COMPRESS_GET_FORMAT,(long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + ) + +#define ICCompressGetFormatSize(hic,lpbi) ICCompressGetFormat(hic,lpbi,NULL) + +#define ICGetDefaultKeyFrameRate(hic,lpint) \ + ICSendMessage( \ + hic, ICM_GETDEFAULTKEYFRAMERATE, \ + (long)(void*)(lpint), \ + 0 ) + +#define ICGetDefaultQuality(hic,lpint) \ + ICSendMessage( \ + hic, ICM_GETDEFAULTQUALITY, \ + (long)(void*)(lpint), \ + 0 ) + + +#define ICCompressBegin(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic, ICM_COMPRESS_BEGIN, (long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + ) + +#define ICCompressGetSize(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic, ICM_COMPRESS_GET_SIZE, (long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + ) + +#define ICCompressQuery(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic, ICM_COMPRESS_QUERY, (long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + ) + + +#define ICCompressEnd(hic) ICSendMessage(hic, ICM_COMPRESS_END, 0, 0) + + + +#define ICDecompressBegin(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic, ICM_DECOMPRESS_BEGIN, (long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + ) + +#define ICDecompressQuery(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic,ICM_DECOMPRESS_QUERY, (long)(void*)(lpbiInput), \ + (long) (void*)(lpbiOutput) \ + ) + +#define ICDecompressGetFormat(hic, lpbiInput, lpbiOutput) \ + ((long)ICSendMessage( \ + hic,ICM_DECOMPRESS_GET_FORMAT, (long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + )) + +#define ICDecompressGetFormatSize(hic, lpbi) \ + ICDecompressGetFormat(hic, lpbi, NULL) + +#define ICDecompressGetPalette(hic, lpbiInput, lpbiOutput) \ + ICSendMessage( \ + hic, ICM_DECOMPRESS_GET_PALETTE, (long)(void*)(lpbiInput), \ + (long)(void*)(lpbiOutput) \ + ) + +#define ICDecompressSetPalette(hic,lpbiPalette) \ + ICSendMessage( \ + hic,ICM_DECOMPRESS_SET_PALETTE, \ + (long)(void*)(lpbiPalette),0 \ + ) + +#define ICDecompressEnd(hic) ICSendMessage(hic, ICM_DECOMPRESS_END, 0, 0) + + +/***************************************************** + + MS ACM ( Audio Compression Manager ) interface + +******************************************************/ + + +MMRESULT WINAPI acmDriverAddA( + PHACMDRIVERID phadid, HINSTANCE hinstModule, + LPARAM lParam, DWORD dwPriority, DWORD fdwAdd +); +MMRESULT WINAPI acmDriverAddW( + PHACMDRIVERID phadid, HINSTANCE hinstModule, + LPARAM lParam, DWORD dwPriority, DWORD fdwAdd +); +MMRESULT WINAPI acmDriverClose( + HACMDRIVER had, DWORD fdwClose +); +MMRESULT WINAPI acmDriverDetailsA( + HACMDRIVERID hadid, PACMDRIVERDETAILSA padd, DWORD fdwDetails +); +MMRESULT WINAPI acmDriverDetailsW( + HACMDRIVERID hadid, PACMDRIVERDETAILSW padd, DWORD fdwDetails +); +MMRESULT WINAPI acmDriverEnum( + ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmDriverID( + HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID +); +LRESULT WINAPI acmDriverMessage( + HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2 +); +MMRESULT WINAPI acmDriverOpen( + PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen +); +MMRESULT WINAPI acmDriverPriority( + HACMDRIVERID hadid, DWORD dwPriority, DWORD fdwPriority +); +MMRESULT WINAPI acmDriverRemove( + HACMDRIVERID hadid, DWORD fdwRemove +); +MMRESULT WINAPI acmFilterChooseA( + PACMFILTERCHOOSEA pafltrc +); +MMRESULT WINAPI acmFilterChooseW( + PACMFILTERCHOOSEW pafltrc +); +MMRESULT WINAPI acmFilterDetailsA( + HACMDRIVER had, PACMFILTERDETAILSA pafd, DWORD fdwDetails +); +MMRESULT WINAPI acmFilterDetailsW( + HACMDRIVER had, PACMFILTERDETAILSW pafd, DWORD fdwDetails +); +MMRESULT WINAPI acmFilterEnumA( + HACMDRIVER had, PACMFILTERDETAILSA pafd, + ACMFILTERENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFilterEnumW( + HACMDRIVER had, PACMFILTERDETAILSW pafd, + ACMFILTERENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFilterTagDetailsA( + HACMDRIVER had, PACMFILTERTAGDETAILSA paftd, DWORD fdwDetails +); +MMRESULT WINAPI acmFilterTagDetailsW( + HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, DWORD fdwDetails +); +MMRESULT WINAPI acmFilterTagEnumA( + HACMDRIVER had, PACMFILTERTAGDETAILSA paftd, + ACMFILTERTAGENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFilterTagEnumW( + HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, + ACMFILTERTAGENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFormatChooseA( + PACMFORMATCHOOSEA pafmtc +); +MMRESULT WINAPI acmFormatChooseW( + PACMFORMATCHOOSEW pafmtc +); +MMRESULT WINAPI acmFormatDetailsA( + HACMDRIVER had, PACMFORMATDETAILSA pafd, DWORD fdwDetails +); +MMRESULT WINAPI acmFormatDetailsW( + HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails +); +MMRESULT WINAPI acmFormatEnumA( + HACMDRIVER had, PACMFORMATDETAILSA pafd, + ACMFORMATENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFormatEnumW( + HACMDRIVER had, PACMFORMATDETAILSW pafd, + ACMFORMATENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFormatSuggest( + HACMDRIVER had, PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst, + DWORD cbwfxDst, DWORD fdwSuggest +); +MMRESULT WINAPI acmFormatTagDetailsA( + HACMDRIVER had, PACMFORMATTAGDETAILSA paftd, DWORD fdwDetails +); +MMRESULT WINAPI acmFormatTagDetailsW( + HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, DWORD fdwDetails +); +MMRESULT WINAPI acmFormatTagEnumA( + HACMDRIVER had, PACMFORMATTAGDETAILSA paftd, + ACMFORMATTAGENUMCBA fnCallback, DWORD dwInstance, DWORD fdwEnum +); +MMRESULT WINAPI acmFormatTagEnumW( + HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, + ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance, DWORD fdwEnum +); +DWORD WINAPI acmGetVersion( +); +MMRESULT WINAPI acmMetrics( + HACMOBJ hao, UINT uMetric, LPVOID pMetric +); +MMRESULT WINAPI acmStreamClose( + HACMSTREAM has, DWORD fdwClose +); +MMRESULT WINAPI acmStreamConvert( + HACMSTREAM has, PACMSTREAMHEADER pash, DWORD fdwConvert +); +MMRESULT WINAPI acmStreamMessage( + HACMSTREAM has, UINT uMsg, LPARAM lParam1, LPARAM lParam2 +); +MMRESULT WINAPI acmStreamOpen( + PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc, + PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback, + DWORD dwInstance, DWORD fdwOpen +); +MMRESULT WINAPI acmStreamPrepareHeader( + HACMSTREAM has, PACMSTREAMHEADER pash, DWORD fdwPrepare +); +MMRESULT WINAPI acmStreamReset( + HACMSTREAM has, DWORD fdwReset +); +MMRESULT WINAPI acmStreamSize( + HACMSTREAM has, DWORD cbInput, + LPDWORD pdwOutputBytes, DWORD fdwSize +); +MMRESULT WINAPI acmStreamUnprepareHeader( + HACMSTREAM has, PACMSTREAMHEADER pash, DWORD fdwUnprepare +); +void MSACM_RegisterAllDrivers(void); + +#ifdef __cplusplus +} +#endif +#endif /* __LOADER_H */ + diff --git a/src/libw32dll/wine/module.c b/src/libw32dll/wine/module.c new file mode 100644 index 000000000..1d4415838 --- /dev/null +++ b/src/libw32dll/wine/module.c @@ -0,0 +1,618 @@ +/* + * Modules + * + * Copyright 1995 Alexandre Julliard + */ +#include "config.h" + +#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 "windef.h" +#include "winerror.h" +#include "heap.h" +#include "module.h" +#include "pe_image.h" +#include "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; + } +} + diff --git a/src/libw32dll/wine/pe_image.c b/src/libw32dll/wine/pe_image.c new file mode 100644 index 000000000..123f4ce7d --- /dev/null +++ b/src/libw32dll/wine/pe_image.c @@ -0,0 +1,936 @@ +/* + * 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 "config.h" +#include "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 "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "heap.h" +#include "pe_image.h" +#include "module.h" +#include "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("); + switch(type) + { + case DLL_PROCESS_DETACH: + printf("DLL_PROCESS_DETACH) "); + break; + case DLL_PROCESS_ATTACH: + printf("DLL_PROCESS_ATTACH) "); + break; + case DLL_THREAD_DETACH: + printf("DLL_THREAD_DETACH) "); + break; + case DLL_THREAD_ATTACH: + printf("DLL_THREAD_ATTACH) "); + break; + } + printf("for %s\n", wm->filename); + 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; +} diff --git a/src/libw32dll/wine/pe_resource.c b/src/libw32dll/wine/pe_resource.c new file mode 100644 index 000000000..1620b20c0 --- /dev/null +++ b/src/libw32dll/wine/pe_resource.c @@ -0,0 +1,391 @@ +/* + * 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 "config.h" + +#include <stdlib.h> +#include <sys/types.h> +#include "winestring.h" +#include "windef.h" +#include "pe_image.h" +#include "module.h" +#include "heap.h" +//#include "task.h" +//#include "process.h" +//#include "stackframe.h" +#include "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; +} diff --git a/src/libw32dll/wine/registry.c b/src/libw32dll/wine/registry.c new file mode 100644 index 000000000..23110ce59 --- /dev/null +++ b/src/libw32dll/wine/registry.c @@ -0,0 +1,421 @@ +#include "config.h" + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <pwd.h> +#include <sys/types.h> + +#include "winbase.h" +#include "winreg.h" +#include "winnt.h" +#include "winerror.h" +#include "debugtools.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(regs[i].len+1); + if(regs[i].value==0) + { + free(regs[i].name); + reg_size=i+1; + goto error; + } + read(fd, regs[i].value, regs[i].len); + regs[i].value[regs[i].len]=0; + } +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, const 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); + TRACE("returning %d bytes: %d\n", t->len, *(int*)data); + } + if(*count<t->len) + { + *count=t->len; + return ERROR_MORE_DATA; + } + else + { + *count=t->len; + } + 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); + 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, const 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; +} diff --git a/src/libw32dll/wine/registry.h b/src/libw32dll/wine/registry.h new file mode 100644 index 000000000..2e794799e --- /dev/null +++ b/src/libw32dll/wine/registry.h @@ -0,0 +1,24 @@ +/******************************************************** + + Declaration of registry access functions + Copyright 2000 Eugene Smith (divx@euro.ru) + +*********************************************************/ + + +#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, const void* data, long size); +#ifdef __cplusplus +}; +#endif +#endif diff --git a/src/libw32dll/wine/resource.c b/src/libw32dll/wine/resource.c new file mode 100644 index 000000000..ecb3cf90a --- /dev/null +++ b/src/libw32dll/wine/resource.c @@ -0,0 +1,479 @@ +/* + * Resources + * + * Copyright 1993 Robert J. Amstadt + * Copyright 1995 Alexandre Julliard + */ +#include "config.h" + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include "winbase.h" +#include "windef.h" +#include "winuser.h" +#include "heap.h" +#include "module.h" +#include "debugtools.h" +#include "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 ); +} + + +INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id, + LPWSTR buffer, INT buflen ); + +/********************************************************************** + * 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); +} diff --git a/src/libw32dll/wine/vfl.c b/src/libw32dll/wine/vfl.c new file mode 100644 index 000000000..02e6f5b6c --- /dev/null +++ b/src/libw32dll/wine/vfl.c @@ -0,0 +1,330 @@ +/* + * Copyright 1998 Marcus Meissner + */ +#include "config.h" + +#include <stdio.h> +#include <string.h> + +#include "winbase.h" +#include "windef.h" +#include "winuser.h" +#include "vfw.h" +#include "winestring.h" +#include "driver.h" +#include "avifmt.h" + +#define FIXME_(X) printf +#define FIXME printf + +long VFWAPI VideoForWindowsVersion(void); + +extern void* my_mreq(int size, int to_zero); +extern void DrvClose(HDRVR hdrvr); +extern int my_release(char* memory); + +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; + DRIVERPROC 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]; + + memcpy(type,&fccType,4);type[4]=0; + + /* 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; + + 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 = (DRIVERPROC)lpfnHandler; + return hic; +} + + +/*********************************************************************** + * ICGetInfo [MSVFW.30] + */ +LRESULT VFWAPI +ICGetInfo(HIC hic,ICINFO *picinfo,long cb) { + LRESULT ret; + + ret = ICSendMessage(hic,ICM_GETINFO,(long)picinfo,cb); + + 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]; + + __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; + /* FIXME: correct? */ +// CloseDriver(whic->hdrv,0,0); + DrvClose(whic->hdrv); +//#warning FIXME: DrvClose + my_release(whic); + return 0; +} +int VFWAPI ICDoSomething() +{ + return 0; +} + diff --git a/src/libw32dll/wine/win32.c b/src/libw32dll/wine/win32.c new file mode 100644 index 000000000..2ca3e3bbd --- /dev/null +++ b/src/libw32dll/wine/win32.c @@ -0,0 +1,1706 @@ +/*********************************************************** + + Win32 emulation code. Functions that emulate + responses from corresponding Win32 API calls. + Since we are not going to be able to load + virtually any DLL, we can only implement this + much, adding needed functions with each new codec. + +************************************************************/ + +#include "config.h" + +#include "win32.h" +#include <stdio.h> +#include <pthread.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif +#include <time.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/timeb.h> + +#include "winbase.h" +#include "winreg.h" +#include "winnt.h" +#include "winerror.h" +#include "debugtools.h" +#include "module.h" + +#include "registry.h" +#include "loader.h" +#ifdef USE_TSC +static unsigned int localcount() +{ + int a; + __asm__ __volatile__("rdtsc\n\t" + :"=a"(a) + : + :"edx"); + return a; +} +static void longcount(long long* z) +{ + __asm__ __volatile__( + "pushl %%ebx\n\t" + "movl %%eax, %%ebx\n\t" + "rdtsc\n\t" + "movl %%eax, 0(%%ebx)\n\t" + "movl %%edx, 4(%%ebx)\n\t" + "popl %%ebx\n\t" + ::"a"(z)); +} +#else +#include <sys/time.h> +#include <unistd.h> +static unsigned int localcount() +{ + struct timeval tv; + unsigned limit=~0; + limit/=1000000; + gettimeofday(&tv, 0); + return limit*tv.tv_usec; +} +static void longcount(long long* z) +{ + struct timeval tv; + unsigned long long result; + unsigned limit=~0; + if(!z)return; + limit/=1000000; + gettimeofday(&tv, 0); + result=tv.tv_sec; + result<<=32; + result+=limit*tv.tv_usec; + *z=result; +} +#endif + +void dbgprintf(char* fmt, ...) +{ +#ifdef DETAILED_OUT +#if 1 + va_list va; + va_start(va, fmt); + vprintf(fmt, va); + va_end(va); +#else + va_list va; + FILE* f; + va_start(va, fmt); + f=fopen("./log", "a"); + if(f==0)return; + vfprintf(f, fmt, va); + fsync(f); + fclose(f); +#endif +#endif +} +char export_names[500][30]={ +"name1", +//"name2", +//"name3" +}; +//#define min(x,y) ((x)<(y)?(x):(y)) + +static unsigned char* heap=NULL; +static int heap_counter=0; +void test_heap() +{ + int offset=0; + if(heap==0) + return; + while(offset<heap_counter) + { + if(*(int*)(heap+offset)!=0x433476) + { + printf("Heap corruption at address %d\n", offset); + return; + } + offset+=8+*(int*)(heap+offset+4); + } + for(;offset<min(offset+1000, 20000000); offset++) + if(heap[offset]!=0xCC) + { + printf("Free heap corruption at address %d\n", offset); + } +} +#undef MEMORY_DEBUG + +#ifdef MEMORY_DEBUG + +void* my_mreq(int size, int to_zero) +{ + static int test=0; + test++; + if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter); +// test_heap(); + if(heap==NULL) + { + heap=malloc(20000000); + memset(heap, 0xCC,20000000); + } + if(heap==0) + { + printf("No enough memory\n"); + return 0; + } + if(heap_counter+size>20000000) + { + printf("No enough memory\n"); + return 0; + } + *(int*)(heap+heap_counter)=0x433476; + heap_counter+=4; + *(int*)(heap+heap_counter)=size; + heap_counter+=4; + printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size); + if(to_zero) + memset(heap+heap_counter, 0, size); + heap_counter+=size; + return heap+heap_counter-size; +} +int my_release(char* memory) +{ +// test_heap(); + if(memory==NULL) + { + printf("ERROR: free(0)\n"); + return 0; + } + if(*(int*)(memory-8)!=0x433476) + { + printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n"); + return 0; + } + printf("Freed %d bytes of memory\n", *(int*)(memory-4)); +// memset(memory-8, *(int*)(memory-4), 0xCC); + return 0; +} + +#else +void* my_mreq(int size, int to_zero) +{ + void* answer; + if(to_zero) + answer=calloc(size+4, 1); + else + answer=malloc(size+4); + *(int*)answer=size; + return (int*)answer+1; +} +int my_release(char* memory) +{ + if(memory==0)return 0; + free(memory-4); + return 0; +} +#endif +int my_size(char* memory) +{ + return *(int*)(memory-4); +} + +extern int unk_exp1; +char extcode[20000];// place for 200 unresolved exports +int pos=0; + +int WINAPI ext_unknown() +{ + printf("Unknown func called\n"); + return 0; +} +int WINAPI expIsBadWritePtr(void* ptr, unsigned int count) +{ + dbgprintf("IsBadWritePtr(%x, %x)\n", ptr, count); + if(count==0) + return 0; + if(ptr==0) + return 1; + return 0; +} +int WINAPI expIsBadReadPtr(void* ptr, unsigned int count) +{ + dbgprintf("IsBadReadPtr(%x, %x)\n", ptr, count); + if(count==0) + return 0; + if(ptr==0) + return 1; + return 0; +} +void* CDECL expmalloc(int size) +{ +//printf("malloc"); +// return malloc(size); + void* result=my_mreq(size,0); + dbgprintf("malloc(%x)\n", size); + if(result==0) + { + dbgprintf("returns 0\n"); + printf("WARNING: malloc() failed\n"); + } + return result; +} +void CDECL expfree(void* mem) +{ +// return free(mem); + dbgprintf("free(%x)\n", mem); + my_release(mem); +} +void* CDECL expnew(int size) +{ +// printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size)); +// printf("%08x %08x %08x %08x\n", +// size, *(1+(int*)&size), +// *(2+(int*)&size),*(3+(int*)&size)); + void* result=expmalloc(size); + dbgprintf("new(%x)\n", size); + if(result==0) + { + dbgprintf("returns 0\n"); + printf("WARNING: malloc() failed\n"); + } + return result; + +} +int CDECL expdelete(void* memory) +{ + dbgprintf("delete(%x)\n", memory); + expfree(memory); + return 0; +} +int WINAPI expDisableThreadLibraryCalls(int module) +{ + dbgprintf("DisableThreadLibraryCalls(%x)\n", module); + return 0; +} +int CDECL exp_initterm(int v1, int v2) +{ + return 0; +} + +typedef struct { + unsigned int uDriverSignature; + void* hDriverModule; + void* DriverProc; + unsigned int dwDriverID; +} DRVR; + +void* WINAPI expGetDriverModuleHandle(DRVR* pdrv) +{ + dbgprintf("GetDriverModuleHandle(%x)\n", pdrv); + return pdrv->hDriverModule; +} + +void* WINAPI expGetModuleHandleA(const char* name) +{ + WINE_MODREF* wm; + dbgprintf("GetModuleHandleA(%s)\n", name); + if(!name)return 0; + wm=MODULE_FindModule(name); + if(wm==0)return 0; + return (void*)(wm->module); +} +struct th_list_t; +typedef struct th_list_t{ +int id; +void* thread; +struct th_list_t* next; +struct th_list_t* prev; +}th_list; + +static th_list* list=NULL; + + + +void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize, void* lpStartAddress, + void* lpParameter, long dwFlags, long* dwThreadId) +{ + pthread_t *pth; +// printf("CreateThread:"); + pth=my_mreq(sizeof(pthread_t), 0); + dbgprintf("pthread_create\n"); + pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter); + if(dwFlags) + dbgprintf( "WARNING: CreateThread flags not supported\n"); + if(dwThreadId) + *dwThreadId=(long)pth; + dbgprintf( "Created thread %08X\n", pth); + if(list==NULL) + { + list=my_mreq(sizeof(th_list), 1); + list->next=list->prev=NULL; + } + else + { + list->next=my_mreq(sizeof(th_list), 0); + list->next->prev=list; + list->next->next=NULL; + list=list->next; + } + list->thread=pth; + return pth; +} + +struct mutex_list_t; + +struct mutex_list_t +{ + pthread_mutex_t *pm; + char name[64]; + struct mutex_list_t* next; + struct mutex_list_t* prev; +}; +typedef struct mutex_list_t mutex_list; +static mutex_list* mlist=NULL; +void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, + char bInitialState, const char* name) +{ +#warning ManualReset + pthread_mutex_t *pm; + dbgprintf("CreateEvent\n"); + if(mlist!=NULL) + { + mutex_list* pp=mlist; + if(name!=NULL) + do + { + if(strcmp(pp->name, name)==0) + return pp->pm; + }while(pp=pp->prev); + } + pm=my_mreq(sizeof(pthread_mutex_t), 0); + pthread_mutex_init(pm, NULL); + if(mlist==NULL) + { + mlist=my_mreq(sizeof(mutex_list), 00); + mlist->next=mlist->prev=NULL; + } + else + { + mlist->next=my_mreq(sizeof(mutex_list), 00); + mlist->next->prev=mlist->next; + mlist->next->next=NULL; + mlist=mlist->next; + } + mlist->pm=pm; + if(name!=NULL) + strncpy(mlist->name, name, 64); + else + mlist->name[0]=0; + if(pm==NULL) + dbgprintf("ERROR::: CreateEventA failure\n"); + if(bInitialState) + pthread_mutex_lock(pm); + return pm; +} + +void* WINAPI expSetEvent(void* event) +{ + dbgprintf("Trying to lock %X\n", event); + pthread_mutex_lock(event); +} +void* WINAPI expResetEvent(void* event) +{ + dbgprintf("Unlocking %X\n", event); + pthread_mutex_unlock(event); +} + +void* WINAPI expWaitForSingleObject(void* object, int duration) +{ +#warning not sure + dbgprintf("WaitForSingleObject: duration %d\n", duration); + pthread_mutex_lock(object); + pthread_mutex_unlock(object); +} + +static BYTE PF[64] = {0,}; + +void WINAPI expGetSystemInfo(SYSTEM_INFO* si) +{ + /* FIXME: better values for the two entries below... */ + static int cache = 0; + static SYSTEM_INFO cachedsi; + HKEY xhkey=0,hkey; + dbgprintf("GetSystemInfo()\n"); + + if (cache) { + memcpy(si,&cachedsi,sizeof(*si)); + return; + } + memset(PF,0,sizeof(PF)); + + cachedsi.u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; + cachedsi.dwPageSize = getpagesize(); + + /* FIXME: better values for the two entries below... */ + cachedsi.lpMinimumApplicationAddress = (void *)0x40000000; + cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF; + cachedsi.dwActiveProcessorMask = 1; + cachedsi.dwNumberOfProcessors = 1; + cachedsi.dwProcessorType = PROCESSOR_INTEL_386; + cachedsi.dwAllocationGranularity = 0x10000; + cachedsi.wProcessorLevel = 3; /* pentium */ + cachedsi.wProcessorRevision = 0; + +#ifdef __FreeBSD__ + cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE; +#ifdef MMX + PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE; +#endif + cachedsi.dwNumberOfProcessors=1; +#else + { + char buf[20]; + char line[200]; + FILE *f = fopen ("/proc/cpuinfo", "r"); + + if (!f) + return; + xhkey = 0; + while (fgets(line,200,f)!=NULL) { + char *s,*value; + + /* NOTE: the ':' is the only character we can rely on */ + if (!(value = strchr(line,':'))) + continue; + /* terminate the valuename */ + *value++ = '\0'; + /* skip any leading spaces */ + while (*value==' ') value++; + if ((s=strchr(value,'\n'))) + *s='\0'; + + /* 2.1 method */ + if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) { + if (isdigit (value[0])) { + switch (value[0] - '0') { + case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386; + cachedsi.wProcessorLevel= 3; + break; + case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486; + cachedsi.wProcessorLevel= 4; + break; + case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + break; + case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + break; + default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + break; + } + } + /* set the CPU type of the current processor */ + sprintf(buf,"CPU %ld",cachedsi.dwProcessorType); + continue; + } + /* old 2.0 method */ + if (!lstrncmpiA(line, "cpu",strlen("cpu"))) { + if ( isdigit (value[0]) && value[1] == '8' && + value[2] == '6' && value[3] == 0 + ) { + switch (value[0] - '0') { + case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386; + cachedsi.wProcessorLevel= 3; + break; + case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486; + cachedsi.wProcessorLevel= 4; + break; + case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + break; + case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + break; + default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel= 5; + break; + } + } + /* set the CPU type of the current processor */ + sprintf(buf,"CPU %ld",cachedsi.dwProcessorType); + continue; + } + if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) { + if (!lstrncmpiA(value,"yes",3)) + PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE; + + continue; + } + if (!lstrncmpiA(line,"fpu",strlen("fpu"))) { + if (!lstrncmpiA(value,"no",2)) + PF[PF_FLOATING_POINT_EMULATED] = TRUE; + + continue; + } + if (!lstrncmpiA(line,"processor",strlen("processor"))) { + /* processor number counts up...*/ + int x; + + if (sscanf(value,"%d",&x)) + if (x+1>cachedsi.dwNumberOfProcessors) + cachedsi.dwNumberOfProcessors=x+1; + + /* Create a new processor subkey on a multiprocessor + * system + */ + sprintf(buf,"%d",x); + } + if (!lstrncmpiA(line,"stepping",strlen("stepping"))) { + int x; + + if (sscanf(value,"%d",&x)) + cachedsi.wProcessorRevision = x; + } + if ( (!lstrncmpiA(line,"flags",strlen("flags"))) || + (!lstrncmpiA(line,"features",strlen("features"))) ) { + if (strstr(value,"cx8")) + PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE; + if (strstr(value,"mmx")) + PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE; + + } + } + fclose (f); + } +#endif /* __FreeBSD__ */ + memcpy(si,&cachedsi,sizeof(*si)); +} + +long WINAPI expGetVersion() +{ + return 0xC0000A04;//Windows 98 +} + +HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size) +{ +// printf("HeapCreate:"); + dbgprintf("HeapCreate(%X, %X, %X)\n", flags, init_size, max_size); + if(init_size==0) + return (HANDLE)my_mreq(0x110000, 0); + else + return (HANDLE)my_mreq(init_size, 0); +} +void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size) +{ + void* z; + dbgprintf("HeapAlloc(%X, %X, %X)\n", heap, flags, size); +// printf("HeapAlloc:"); + z=my_mreq(size, flags&8); +// z=HeapAlloc(heap,flags,size); + if(z==0) + printf("HeapAlloc failure\n"); + return z; +} +long WINAPI expHeapDestroy(void* heap) +{ + dbgprintf("HeapDestroy(%X)\n", heap); + my_release(heap); + return 1; +} + +long WINAPI expHeapFree(int arg1, int arg2, void* ptr) +{ + dbgprintf("HeapFree(%X, %X, %X)\n", arg1, arg2, ptr); + my_release(ptr); + return 1; +} +long WINAPI expHeapSize(int heap, int flags, void* pointer) +{ + return my_size(pointer); +} +long WINAPI expGetProcessHeap(void) +{ + return 1; +} +void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4) +{ + void* z; + dbgprintf("VirtualAlloc(%d %d %d %d) \n",v1,v2,v3,v4); + z=VirtualAlloc(v1, v2, v3, v4); + if(z==0) + printf("VirtualAlloc failure\n"); + return z; +} +int WINAPI expVirtualFree(void* v1, int v2, int v3) +{ + dbgprintf("VirtualFree(%X %X %X) \n",v1,v2,v3); + return VirtualFree(v1,v2,v3); +} +struct CRITSECT +{ + pthread_t id; + pthread_mutex_t mutex; + int locked; +}; +void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c) +{ + struct CRITSECT cs; + dbgprintf("InitCriticalSection(%X) \n", c); +/* if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION)) + { + printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n", + sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION)); + return; + }*/ +/* pthread_mutex_init((pthread_mutex_t*)c, NULL); */ + pthread_mutex_init(&cs.mutex, NULL); + cs.locked=0; + *(void**)c=malloc(sizeof cs); + memcpy(*(void**)c, &cs, sizeof cs); + return; +} +void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c) +{ + struct CRITSECT* cs=(struct CRITSECT*)c; + dbgprintf("EnterCriticalSection(%X) \n",c); +// cs.id=pthread_self(); + if(cs->locked) + if(cs->id==pthread_self()) + return; + pthread_mutex_lock(&(cs->mutex)); + cs->locked=1; + cs->id=pthread_self(); + return; +} +void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c) +{ + struct CRITSECT* cs=(struct CRITSECT*)c; + dbgprintf("LeaveCriticalSection(%X) \n",c); + cs->locked=0; + pthread_mutex_unlock(&(cs->mutex)); + return; +} +void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c) +{ + dbgprintf("DeleteCriticalSection(%X) \n",c); + pthread_mutex_destroy((pthread_mutex_t*)c); + return; +} +int WINAPI expGetCurrentThreadId() +{ + dbgprintf("GetCurrentThreadId() \n"); + return getpid(); +} +struct tls_s; +typedef struct tls_s +{ + void* value; + int used; + struct tls_s* prev; + struct tls_s* next; +}tls_t; + +tls_t* g_tls=NULL; + +void* WINAPI expTlsAlloc() +{ + dbgprintf("TlsAlloc \n"); + if(g_tls==NULL) + { + g_tls=my_mreq(sizeof(tls_t), 0); + g_tls->next=g_tls->prev=NULL; + } + else + { + g_tls->next=my_mreq(sizeof(tls_t), 0); + g_tls->next->prev=g_tls; + g_tls->next->next=NULL; + g_tls=g_tls->next; + } + return g_tls; +} + +int WINAPI expTlsSetValue(tls_t* index, void* value) +{ + dbgprintf("TlsSetVal(%X %X) \n", index, value ); + if(index==0) + return 0; + index->value=value; + return 1; +} +void* WINAPI expTlsGetValue(tls_t* index) +{ + dbgprintf("TlsGetVal(%X) \n", index ); + if(index==0) + return 0; + return index->value; +} +int WINAPI expTlsFree(tls_t* index) +{ + dbgprintf("TlsFree(%X) \n", index); + if(index==0) + return 0; + if(index->next) + index->next->prev=index->prev; + if(index->prev) + index->prev->next=index->next; + my_release((void*)index); + return 1; +} + +void* WINAPI expLocalAlloc(int flags, int size) +{ + void* z; + dbgprintf("LocalAlloc(%d, flags %X)\n", size, flags); + if(flags&GMEM_ZEROINIT) + z=my_mreq(size, 1); + else + z=my_mreq(size, 0); + if(z==0) + printf("LocalAlloc() failed\n"); + return z; +} +void* WINAPI expLocalLock(void* z) +{ + dbgprintf("LocalLock\n"); + return z; +} +void* WINAPI expGlobalAlloc(int flags, int size) +{ + void* z; + dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags); + if(flags&GMEM_ZEROINIT) + z=my_mreq(size, 1); + else + z=my_mreq(size, 0); + if(z==0) + printf("LocalAlloc() failed\n"); + return z; +} +void* WINAPI expGlobalLock(void* z) +{ + dbgprintf("GlobalLock\n"); + return z; +} + +int WINAPI expLoadStringA(long instance, long id, void* buf, long size) +{ + dbgprintf("LoadStringA\n"); + return LoadStringA(instance, id, buf, size); +} + +long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, char* s2, int siz2) +{ +#warning FIXME + dbgprintf("MB2WCh\n"); + dbgprintf("WARNING: Unsupported call: MBToWCh %s\n", s1); + if(s2==0) + return 1; + s2[0]=s2[1]=0; + return 1; +} +long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1, char* s2, int siz2, char* c3, int* siz3) +{ + int result; + dbgprintf("WCh2MB\n"); + result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3); + dbgprintf("=> %d\n", result); + return result; +} +long WINAPI expGetVersionExA(OSVERSIONINFOA* c) +{ + dbgprintf("GetVersionExA\n"); + c->dwMajorVersion=4; + c->dwMinorVersion=10; + c->dwBuildNumber=0x40a07ce; + c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS; + strcpy(c->szCSDVersion, "Win98"); + return 1; +} +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> +HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count, long max_count, char* name) +{ +#warning FIXME +/* struct sembuf buf[1]; + int sem=semget(IPC_PRIVATE,1,IPC_CREAT); + if(sem==-1) + { + printf("semget() failed\n"); + return (HANDLE)-1; + } + buf[0].sem_num=0; + printf("%s\n", name); + printf("Init count %d, max count %d\n", init_count, max_count); + buf[0].sem_op=-max_count+init_count; + buf[0].sem_flg=0; + if(semop(sem, &buf, 1)<0) + { + printf("semop() failed\n"); + } + return sem; +*/ + void* z; + dbgprintf("CreateSemaphoreA\n"); + z=my_mreq(24, 0); + pthread_mutex_init(z, NULL); + return (HANDLE)z; +} + +long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count) +{ +// The state of a semaphore object is signaled when its count +// is greater than zero and nonsignaled when its count is equal to zero +// Each time a waiting thread is released because of the semaphore's signaled +// state, the count of the semaphore is decreased by one. + struct sembuf buf[1]; + dbgprintf("ReleaseSemaphore\n"); + dbgprintf("WARNING: Unsupported call: ReleaseSemaphoreA\n"); +/* if(hsem==-1)return 0; + buf[0].sem_num=0; + buf[0].sem_op=-1; + buf[0].sem_flg=0; + if(semop(hsem, &buf, 1)<0) + { + printf("ReleaseSemaphore: semop() failed\n"); + }*/ + + return 1;//zero on error +} + + +long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey) +{ + dbgprintf("RegOpenKeyExA(%d,%s)\n", key, subkey); + return RegOpenKeyExA(key, subkey, reserved, access, newkey); +} +long WINAPI expRegCloseKey(long key) +{ + dbgprintf("RegCloseKey()\n"); + return RegCloseKey(key); +} +long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count) +{ + dbgprintf("RegQueryValueExA()\n"); + return RegQueryValueExA(key, value, reserved, type, data, count); +} +long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved, + void* classs, long options, long security, + void* sec_attr, int* newkey, int* status) +{ + dbgprintf("RegCreateKeyExA()\n"); + return RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status); +} +long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size) +{ + dbgprintf("RegSetValueExA()\n"); + return RegSetValueExA(key, name, v1, v2, data, size); +} + +long WINAPI expRegOpenKeyA ( +long hKey, + LPCSTR lpSubKey, + int* phkResult +){ + return RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult); +} + +long WINAPI expQueryPerformanceCounter(long long* z) +{ + dbgprintf("QueryPerformanceCounter()\n"); + longcount(z); + return 1; +} + +static double old_freq() +{ + int i=time(NULL); + int x,y; + while(i==time(NULL)); + x=localcount(); + i++; + while(i==time(NULL)); + y=localcount(); + return (double)(y-x)/1000.; +} +static double CPU_Freq() +{ +#ifdef USE_TSC + FILE *f = fopen ("/proc/cpuinfo", "r"); + char line[200]; + char model[200]="unknown"; + char flags[500]=""; + char *s,*value; + double freq=-1; + + if (!f) + { + printf("Can't open /proc/cpuinfo for reading\n"); + return old_freq(); + } + while (fgets(line,200,f)!=NULL) + { + /* NOTE: the ':' is the only character we can rely on */ + if (!(value = strchr(line,':'))) + continue; + /* terminate the valuename */ + *value++ = '\0'; + /* skip any leading spaces */ + while (*value==' ') value++; + if ((s=strchr(value,'\n'))) + *s='\0'; + + if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))) + { + sscanf(value, "%lf", &freq); + freq*=1000; + break; + } + continue; + + } + fclose(f); + if(freq<0)return old_freq(); + return freq; +#else + return old_freq(); +#endif +} + +long WINAPI expQueryPerformanceFrequency(long long* z) +{ + dbgprintf("QueryPerformanceFrequency()\n"); + *z=(long long)CPU_Freq(); + return 1; +} +long WINAPI exptimeGetTime() +{ + struct timeval t; + dbgprintf("timeGetTime()\n"); + gettimeofday(&t, 0); + return 1000*t.tv_sec+t.tv_usec/1000; +} +void* WINAPI expLocalHandle(void* v) +{ + dbgprintf("LocalHandle\n"); + return v; +} +void* WINAPI expGlobalHandle(void* v) +{ + dbgprintf("GlobalHandle\n"); + return v; +} +int WINAPI expGlobalUnlock(void* v) +{ + dbgprintf("GlobalUnlock\n"); + return 1; +} +// +void* WINAPI expGlobalFree(void* v) +{ + dbgprintf("GlobalFree(%X)\n", v); + my_release(v); + return 0; +} + +int WINAPI expLocalUnlock(void* v) +{ + dbgprintf("LocalUnlock\n"); + return 1; +} +// +void* WINAPI expLocalFree(void* v) +{ + dbgprintf("LocalFree(%X)\n", v); + my_release(v); + return 0; +} + +HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type) +{ + dbgprintf("FindResourceA\n"); + return FindResourceA(module, name, type); +} +HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res) +{ + dbgprintf("LoadResource\n"); + return LoadResource(module, res);; +} +void* WINAPI expLockResource(long res) +{ + dbgprintf("LockResource\n"); + return LockResource(res); +} +int WINAPI expFreeResource(long res) +{ + dbgprintf("FreeResource\n"); + return FreeResource(res); +} +//bool fun(HANDLE) +//!0 on success +int WINAPI expCloseHandle(long v1) +{ + dbgprintf("CloseHandle\n"); + return 1; +} + +const char* WINAPI expGetCommandLineA() +{ + dbgprintf("GetCommandLine\n"); + return "c:\\aviplay.exe"; +} +LPWSTR WINAPI expGetEnvironmentStringsW() +{ + static wchar_t envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0}; + dbgprintf("GetEnvStringsW\n"); + return (LPWSTR)envs; +} + +int WINAPI expFreeEnvironmentStringsW(short* strings) +{ + dbgprintf("FreeEnvStringsW\n"); + return 1; +} +LPCSTR WINAPI expGetEnvironmentStrings() +{ + dbgprintf("GetEnvStrings\n"); + return "\0\0"; +} + +int WINAPI expGetStartupInfoA(STARTUPINFOA *s) +{ + int i; + dbgprintf("GetStartupInfoA\n"); +/* + for(i=0; i<sizeof(STARTUPINFOA)/4; i++) + ((int*)s)[i]=i+0x200; +*/ + memset(s, 0, sizeof(*s)); + s->cb=sizeof(*s); + s->lpReserved="qwe"; + s->lpDesktop="rty"; + s->lpTitle="uio"; + s->dwX=s->dwY=0; + s->dwXSize=s->dwYSize=200; + s->dwFlags=s->wShowWindow=0; + return 1; +} + +int WINAPI expGetStdHandle(int z) +{ + dbgprintf("GetStdHandle\n"); + dbgprintf("WARNING: Unsupported call: GetStdHandle\n"); + return 1234; +} +int WINAPI expGetFileType(int handle) +{ + dbgprintf("GetFileType\n"); + dbgprintf("WARNING: Unsupported call: GetFileType\n"); + return 5678; +} +int WINAPI expSetHandleCount(int count) +{ + dbgprintf("SetHandleCount\n"); + return 1; +} +int WINAPI expGetACP() +{ + dbgprintf("GetACP\n"); + dbgprintf("WARNING: Unsupported call: GetACP\n"); + return 0; +} +extern WINE_MODREF *MODULE32_LookupHMODULE(HMODULE m); +int WINAPI expGetModuleFileNameA(int module, char* s, int len) +{ + WINE_MODREF *mr; + dbgprintf("GetModuleFileNameA\n"); +// printf("File name of module %X requested\n", module); + if(s==0) + return 0; + if(len<35) + return 0; + strcpy(s, "c:\\windows\\system\\"); + mr=MODULE32_LookupHMODULE(module); + if(mr==0)//oops + { + strcat(s, "aviplay.dll"); + return 1; + } + if(strrchr(mr->filename, '/')==NULL) + strcat(s, mr->filename); + else + strcat(s, strrchr(mr->filename, '/')+1); + return 1; +} + +int WINAPI expSetUnhandledExceptionFilter(void* filter) +{ + dbgprintf("SetUnhandledExcFilter\n"); + return 1;//unsupported and probably won't ever be supported +} +extern char* def_path; + +int WINAPI expLoadLibraryA(char* name) +{ + char qq[256]; + dbgprintf("LoadLibraryA\n"); + printf("They want library %s\n", name); + strcpy(qq, def_path); + strcat(qq, "/"); + strcat(qq, name); + return LoadLibraryA(qq); +} +int WINAPI expFreeLibrary(int module) +{ + dbgprintf("FreeLibrary\n"); + return FreeLibrary(module); +} +void* WINAPI expGetProcAddress(HMODULE mod, char* name) +{ + dbgprintf("GetProcAddress\n"); + return GetProcAddress(mod, name); +} + +long WINAPI expCreateFileMappingA(int hFile, void* lpAttr, + long flProtect, long dwMaxHigh, long dwMaxLow, const char* name) +{ + dbgprintf("CreateFileMappingA\n"); + return CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name); +} + +long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name) +{ + dbgprintf("OpenFileMappingA\n"); + return OpenFileMappingA(hFile, hz, name); +} + +void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh, DWORD offLow, DWORD size) +{ + dbgprintf("MapViewOfFile(%d, %x, %x, %x, %x)\n", + file,mode,offHigh,offLow,size); + return (char*)file+offLow; +} + +void* WINAPI expUnmapViewOfFile(void* view) +{ + dbgprintf("UnmapViewOfFile()\n"); + return 0; +} + +void* WINAPI expSleep(int time) +{ + dbgprintf("Sleep(%d)\n", time); + usleep(time); + return 0; +} + // why does IV32 codec want to call this? I don't know ... +void* WINAPI expCreateCompatibleDC(int hdc) +{ + dbgprintf("CreateCompatibleDC(%d)\n", hdc); + return (void*)129; +} + +int WINAPI expGetDeviceCaps(int hdc, int unk) +{ + dbgprintf("GetDeviceCaps(%d, %d)\n", hdc, unk); + return 0; +} + +WIN_BOOL WINAPI expDeleteDC(int hdc) +{ + dbgprintf("DeleteDC(%d)\n", hdc); + return 0; +} + +int expwsprintfA(char* string, char* format, ...) +{ + va_list va; + va_start(va, format); + dbgprintf("wsprintfA\n"); + return vsprintf(string, format, va); +} + +int WINAPI expGetPrivateProfileIntA(const char* appname, const char* keyname, int default_value, const char* filename) +{ + int size=255; + char buffer[256]; + char* fullname; + int result; + + buffer[255]=0; + dbgprintf("GetPrivateProfileIntA(%s, %s, %s)\n", appname, keyname, filename ); + if(!(appname && keyname && filename) ) return default_value; + fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename)); + strcpy(fullname, "Software\\IniFileMapping\\"); + strcat(fullname, appname); + strcat(fullname, "\\"); + strcat(fullname, keyname); + strcat(fullname, "\\"); + strcat(fullname, filename); + result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size); + if((size>=0)&&(size<256)) + buffer[size]=0; +// printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer); + free(fullname); + if(result) + return default_value; + else + return atoi(buffer); +} +int WINAPI expGetPrivateProfileStringA(const char* appname, const char* keyname, + const char* def_val, char* dest, unsigned int len, const char* filename) +{ + int result; + int size; + char* fullname; + dbgprintf("GetPrivateProfileStringA(%s, %s, %s, %X, %X, %s)\n", appname, keyname, def_val, dest, len, filename ); + if(!(appname && keyname && filename) ) return 0; + fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename)); + strcpy(fullname, "Software\\IniFileMapping\\"); + strcat(fullname, appname); + strcat(fullname, "\\"); + strcat(fullname, keyname); + strcat(fullname, "\\"); + strcat(fullname, filename); + size=len; + result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size); +// printf("GetPrivateProfileStringA(%s, %s, %s, %X, %X, %s)\n", appname, keyname, def_val, dest, len, filename ); + free(fullname); + if(!result) + return size; + strncpy(dest, def_val, size); + return size; +} +int WINAPI expWritePrivateProfileStringA(const char* appname, const char* keyname, + const char* string, const char* filename) +{ + int size=256; + char* fullname; + dbgprintf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename ); + if(!(appname && keyname && filename) ) return -1; + fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename)); + strcpy(fullname, "Software\\IniFileMapping\\"); + strcat(fullname, appname); + strcat(fullname, "\\"); + strcat(fullname, keyname); + strcat(fullname, "\\"); + strcat(fullname, filename); + RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string)); +// printf("RegSetValueExA(%s,%d)\n", string, strlen(string)); +// printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename ); + free(fullname); + return 0; +} + +unsigned int _GetPrivateProfileIntA(const char* appname, const char* keyname, INT default_value, const char* filename) +{ + return expGetPrivateProfileIntA(appname, keyname, default_value, filename); +} +int _GetPrivateProfileStringA(const char* appname, const char* keyname, + const char* def_val, char* dest, unsigned int len, const char* filename) +{ + return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename); +} +int _WritePrivateProfileStringA(const char* appname, const char* keyname, + const char* string, const char* filename) +{ + return expWritePrivateProfileStringA(appname, keyname, string, filename); +} + + +int WINAPI expDefDriverProc(int _private, int id, int msg, int arg1, int arg2) +{ + printf("Called DefDriverProc(%X)\n", msg); + return 0; +} + +int WINAPI expSizeofResource(int v1, int v2) +{ + dbgprintf("SizeofResource()\n"); + return SizeofResource(v1, v2); +} + +int WINAPI expGetLastError() +{ + dbgprintf("GetLastError()\n"); + return GetLastError(); +} + +void WINAPI expSetLastError(int error) +{ + dbgprintf("SetLastError()\n"); + SetLastError(error); +} + +char* expstrrchr(char* string, int value) +{ + return strrchr(string, value); +} + +char* expstrchr(char* string, int value) +{ + return strchr(string, value); +} + +int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle) +{ + printf("GetFileVersionInfoSizeA(%s,0x%X)\n", name, lpHandle); + return 0; +} + +int WINAPI expIsBadStringPtrW(const short* string, int nchars) +{ + if(string==0)return 1; + return 0; +} +extern long WINAPI InterlockedExchangeAdd( long* dest, long incr ) +{ + long ret; + __asm__ __volatile__( "lock; xaddl %0,(%1)" + : "=r" (ret) : "r" (dest), "0" (incr) : "memory" ); + return ret; +} + +extern long WINAPI expInterlockedIncrement( long* dest ) +{ + return InterlockedExchangeAdd( dest, 1 ) + 1; +} +extern long WINAPI expInterlockedDecrement( long* dest ) +{ + return InterlockedExchangeAdd( dest, -1 ) - 1; +} + +extern void WINAPI expOutputDebugStringA( const char* string ) +{ + fprintf(stderr, "DEBUG: %s\n", string); +} + +int WINAPI expGetDC(int hwnd) +{ + return 0; +} + +int WINAPI expGetDesktopWindow() +{ + return 0; +} + +int WINAPI expReleaseDC(int hwnd, int hdc) +{ + return 0; +} + +int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe) +{ + return 0; +} +/* +typedef struct _TIME_ZONE_INFORMATION { + long Bias; + char StandardName[32]; + SYSTEMTIME StandardDate; + long StandardBias; + char DaylightName[32]; + SYSTEMTIME DaylightDate; + long DaylightBias; +} TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION; +*/ + +int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) +{ + memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION)); + return 0; +} + +void WINAPI expGetLocalTime(SYSTEMTIME* systime) +{ + time_t local_time; + struct tm *local_tm; + struct timeval tv; + + gettimeofday(&tv, NULL); + local_time=tv.tv_sec; + local_tm=localtime(&local_time); + + systime->wYear = local_tm->tm_year + 1900; + systime->wMonth = local_tm->tm_mon + 1; + systime->wDayOfWeek = local_tm->tm_wday; + systime->wDay = local_tm->tm_mday; + systime->wHour = local_tm->tm_hour; + systime->wMinute = local_tm->tm_min; + systime->wSecond = local_tm->tm_sec; + systime->wMilliseconds = (tv.tv_usec / 1000) % 1000; +} + +int WINAPI expGetSystemTime(SYSTEMTIME* systime) +{ + time_t local_time; + struct tm *local_tm; + struct timeval tv; + + gettimeofday(&tv, NULL); + local_time=tv.tv_sec; + local_tm=gmtime(&local_time); + + systime->wYear = local_tm->tm_year + 1900; + systime->wMonth = local_tm->tm_mon + 1; + systime->wDayOfWeek = local_tm->tm_wday; + systime->wDay = local_tm->tm_mday; + systime->wHour = local_tm->tm_hour; + systime->wMinute = local_tm->tm_min; + systime->wSecond = local_tm->tm_sec; + systime->wMilliseconds = (tv.tv_usec / 1000) % 1000; + +} + +int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size) +{ + dbgprintf("GetEnvironmentVariableA\n"); + printf("%s %x %x\n", name, field, size); + if(field)field[0]=0; + return 0; +} + + +//HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName, LPARAM lParam2); +//HDRVR WINAPI expOpenDriverW(LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2); +HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName, LPARAM lParam2){ + printf("winmm32::OpenDriver() called\n"); + return NULL; +} + + +struct exports +{ + char name[64]; + int id; + void* func; +}; +struct libs +{ + char name[64]; + int length; + struct exports* exps; +}; + +#define FF(X,Y) \ +{#X, Y, (void*)exp##X}, + +struct exports exp_kernel32[]={ +FF(IsBadWritePtr, 357) +FF(IsBadReadPtr, 354) +FF(IsBadStringPtrW, -1) +FF(DisableThreadLibraryCalls, -1) +FF(CreateThread, -1) +FF(CreateEventA, -1) +FF(SetEvent, -1) +FF(ResetEvent, -1) +FF(WaitForSingleObject, -1) +FF(GetSystemInfo, -1) +FF(GetVersion, 332) +FF(HeapCreate, 461) +FF(HeapAlloc, -1) +FF(HeapDestroy, -1) +FF(HeapFree, -1) +FF(HeapSize, -1) +FF(GetProcessHeap, -1) +FF(VirtualAlloc, -1) +FF(VirtualFree, -1) +FF(InitializeCriticalSection, -1) +FF(EnterCriticalSection, -1) +FF(LeaveCriticalSection, -1) +FF(DeleteCriticalSection, -1) +FF(TlsAlloc, -1) +FF(TlsFree, -1) +FF(TlsGetValue, -1) +FF(TlsSetValue, -1) +FF(GetCurrentThreadId, -1) +FF(LocalAlloc, -1) +FF(LocalLock, -1) +FF(GlobalAlloc, -1) +FF(GlobalLock, -1) +FF(MultiByteToWideChar, 427) +FF(WideCharToMultiByte, -1) +FF(GetVersionExA, -1) +FF(CreateSemaphoreA, -1) +FF(QueryPerformanceCounter, -1) +FF(QueryPerformanceFrequency, -1) +FF(LocalHandle, -1) +FF(LocalUnlock, -1) +FF(LocalFree, -1) +FF(GlobalHandle, -1) +FF(GlobalUnlock, -1) +FF(GlobalFree, -1) +FF(LoadResource, -1) +FF(ReleaseSemaphore, -1) +FF(FindResourceA, -1) +FF(LockResource, -1) +FF(FreeResource, -1) +FF(SizeofResource, -1) +FF(CloseHandle, -1) +FF(GetCommandLineA, -1) +FF(GetEnvironmentStringsW, -1) +FF(FreeEnvironmentStringsW, -1) +FF(GetEnvironmentStrings, -1) +FF(GetStartupInfoA, -1) +FF(GetStdHandle, -1) +FF(GetFileType, -1) +FF(SetHandleCount, -1) +FF(GetACP, -1) +FF(GetModuleFileNameA, -1) +FF(SetUnhandledExceptionFilter, -1) +FF(LoadLibraryA, -1) +FF(GetProcAddress, -1) +FF(FreeLibrary, -1) +FF(CreateFileMappingA, -1) +FF(OpenFileMappingA, -1) +FF(MapViewOfFile, -1) +FF(UnmapViewOfFile, -1) +FF(Sleep, -1) +FF(GetModuleHandleA, -1) +FF(GetPrivateProfileIntA, -1) +FF(GetPrivateProfileStringA, -1) +FF(WritePrivateProfileStringA, -1) +FF(GetLastError, -1) +FF(SetLastError, -1) +FF(InterlockedIncrement, -1) +FF(InterlockedDecrement, -1) +FF(GetTimeZoneInformation, -1) +FF(OutputDebugStringA, -1) +FF(GetLocalTime, -1) +FF(GetSystemTime, -1) +FF(GetEnvironmentVariableA, -1) +}; + +struct exports exp_msvcrt[]={ +FF(malloc, -1) +FF(_initterm, -1) +FF(free, -1) +{"??3@YAXPAX@Z", -1, expdelete}, +{"??2@YAPAXI@Z", -1, expnew}, +FF(strrchr, -1) +FF(strchr, -1) +}; +struct exports exp_winmm[]={ +FF(GetDriverModuleHandle, -1) +FF(timeGetTime, -1) +FF(DefDriverProc, -1) +FF(OpenDriver, -1) +}; +struct exports exp_user32[]={ +FF(LoadStringA, -1) +FF(wsprintfA, -1) +FF(GetDC, -1) +FF(GetDesktopWindow, -1) +FF(ReleaseDC, -1) +}; +struct exports exp_advapi32[]={ +FF(RegOpenKeyA, -1) +FF(RegOpenKeyExA, -1) +FF(RegCreateKeyExA, -1) +FF(RegQueryValueExA, -1) +FF(RegSetValueExA, -1) +FF(RegCloseKey, -1) +}; +struct exports exp_gdi32[]={ +FF(CreateCompatibleDC, -1) +FF(GetDeviceCaps, -1) +FF(DeleteDC, -1) +FF(GetSystemPaletteEntries, -1) +}; +struct exports exp_version[]={ +FF(GetFileVersionInfoSizeA, -1) +}; +#define LL(X) \ +{#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X}, + +struct libs libraries[]={ +LL(kernel32) +LL(msvcrt) +LL(winmm) +LL(user32) +LL(advapi32) +LL(gdi32) +LL(version) +}; + +void* LookupExternal(const char* library, int ordinal) +{ + char* answ; + int i,j; + if(library==0) + { + printf("ERROR: library=0\n"); + return (void*)ext_unknown; + } + printf("External func %s:%d\n", library, ordinal); +// printf("%x %x\n", &unk_exp1, &unk_exp2); + + for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++) + { + if(strcasecmp(library, libraries[i].name)) + continue; + for(j=0; j<libraries[i].length; j++) + { + if(ordinal!=libraries[i].exps[j].id) + continue; + printf("Hit: 0x%08X\n", libraries[i].exps[j].func); + return libraries[i].exps[j].func; + } + } + if(pos>150)return 0; + answ=(char*)extcode+pos*0x64; + memcpy(answ, &unk_exp1, 0x64); + *(int*)(answ+9)=pos; + *(int*)(answ+47)-=((int)answ-(int)&unk_exp1); + sprintf(export_names[pos], "%s:%d", library, ordinal); + pos++; + return (void*)answ; +} + +void* LookupExternalByName(const char* library, const char* name) +{ + char* answ; + int i,j; +// return (void*)ext_unknown; + if(library==0) + { + printf("ERROR: library=0\n"); + return (void*)ext_unknown; + } + if(name==0) + { + printf("ERROR: name=0\n"); + return (void*)ext_unknown; + } +// printf("External func %s:%s\n", library, name); + for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++) + { + if(strcasecmp(library, libraries[i].name)) + continue; + for(j=0; j<libraries[i].length; j++) + { + if(strcmp(name, libraries[i].exps[j].name)) + continue; +// printf("Hit: 0x%08X\n", libraries[i].exps[j].func); + return libraries[i].exps[j].func; + } + }// printf("%x %x\n", &unk_exp1, &unk_exp2); + //printf("Missing (%d) External func %s:%s\n", pos, library, name); + if(pos>150){ +// printf("Warning! Too many missing externals!\n"); + return 0; + } + strcpy(export_names[pos], name); + answ=(char*)extcode+pos*0x64; + memcpy(answ, &unk_exp1, 0x64); + *(int*)(answ+9)=pos; + *(int*)(answ+47)-=((int)answ-(int)&unk_exp1); + pos++; + return (void*)answ; +// memcpy(extcode, &unk_exp1, 0x64); +// *(int*)(extcode+52)-=((int)extcode-(int)&unk_exp1); +// return (void*)extcode; +// printf("Unknown func %s:%s\n", library, name); +// return (void*)ext_unknown; +} + diff --git a/src/libw32dll/wine/win32.h b/src/libw32dll/wine/win32.h new file mode 100644 index 000000000..327cfb298 --- /dev/null +++ b/src/libw32dll/wine/win32.h @@ -0,0 +1 @@ +int ext_unknown(); diff --git a/src/libw32dll/wine/wineacm.h b/src/libw32dll/wine/wineacm.h new file mode 100644 index 000000000..f215d754d --- /dev/null +++ b/src/libw32dll/wine/wineacm.h @@ -0,0 +1,55 @@ +/* -*- 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); + |