summaryrefslogtreecommitdiffstats
path: root/loader/win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'loader/win32.c')
-rw-r--r--loader/win32.c1706
1 files changed, 1706 insertions, 0 deletions
diff --git a/loader/win32.c b/loader/win32.c
new file mode 100644
index 0000000000..e0b76798ef
--- /dev/null
+++ b/loader/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 <wine/winbase.h>
+#include <wine/winreg.h>
+#include <wine/winnt.h>
+#include <wine/winerror.h>
+#include <wine/debugtools.h>
+#include <wine/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);