summaryrefslogtreecommitdiff
path: root/src/libw32dll/wine
diff options
context:
space:
mode:
Diffstat (limited to 'src/libw32dll/wine')
-rw-r--r--src/libw32dll/wine/Makefile.am26
-rw-r--r--src/libw32dll/wine/afl.c765
-rw-r--r--src/libw32dll/wine/driver.c182
-rw-r--r--src/libw32dll/wine/elfdll.c305
-rw-r--r--src/libw32dll/wine/ext.c565
-rw-r--r--src/libw32dll/wine/loader.h286
-rw-r--r--src/libw32dll/wine/module.c618
-rw-r--r--src/libw32dll/wine/pe_image.c936
-rw-r--r--src/libw32dll/wine/pe_resource.c391
-rw-r--r--src/libw32dll/wine/registry.c421
-rw-r--r--src/libw32dll/wine/registry.h24
-rw-r--r--src/libw32dll/wine/resource.c479
-rw-r--r--src/libw32dll/wine/vfl.c330
-rw-r--r--src/libw32dll/wine/win32.c1706
-rw-r--r--src/libw32dll/wine/win32.h1
-rw-r--r--src/libw32dll/wine/wineacm.h55
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, &reg_size, 4);
+ regs=(struct reg_value*)malloc(reg_size*sizeof(struct reg_value));
+ for(i=0; i<reg_size; i++)
+ {
+ read(fd,&regs[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,&regs[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, &reg_size, 4);
+ for(i=0; i<reg_size; i++)
+ {
+ write(fd, &regs[i].type, 4);
+ len=strlen(regs[i].name);
+ write(fd, &len, 4);
+ write(fd, regs[i].name, len);
+ write(fd, &regs[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);
+