diff loader/win32.c @ 128:28091b3caff9

DLL loader updated from avifile-0.60beta4
author arpi_esp
date Sun, 18 Mar 2001 01:01:03 +0000
parents 94a1a9f52050
children 39ceb7a5a9e2
line wrap: on
line diff
--- a/loader/win32.c	Sun Mar 18 00:31:18 2001 +0000
+++ b/loader/win32.c	Sun Mar 18 01:01:03 2001 +0000
@@ -5,6 +5,9 @@
          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.
+      
+      Basic principle of implementation: it's not good
+      for DLL to know too much about its environment.
 
 ************************************************************/
 
@@ -13,12 +16,15 @@
 #include "win32.h"
 #include <stdio.h>
 #include <pthread.h>
+#include <errno.h>
 #ifdef HAVE_MALLOC_H
 #include <malloc.h>
 #else
 #include <stdlib.h>
 #endif
 #include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/timeb.h>
@@ -32,8 +38,26 @@
 
 #include <registry.h>
 #include <loader.h>
-#ifdef USE_TSC
-static unsigned int localcount()
+#include <com.h>
+
+char* def_path=WIN32_PATH;
+
+static void do_cpuid(unsigned int *regs)
+{
+  unsigned int ax;
+  ax=1;
+    __asm__ __volatile__(
+	"pushl %%ebx; pushl %%ecx; pushl %%edx; "
+        ".byte  0x0f, 0xa2;"
+        "movl   %%eax, (%2);"
+        "movl   %%ebx, 4(%2);"
+        "movl   %%ecx, 8(%2);"
+        "movl   %%edx, 12(%2);"
+	"popl %%edx; popl %%ecx; popl %%ebx; "
+        : "=a" (ax)
+    :  "0" (ax), "S" (&regs));
+}
+static unsigned int c_localcount_tsc()
 {
     int a;
     __asm__ __volatile__("rdtsc\n\t"
@@ -42,7 +66,7 @@
     :"edx");
     return a;
 }
-static void longcount(long long* z)
+static void c_longcount_tsc(long long* z)
 {
     __asm__ __volatile__(
     "pushl %%ebx\n\t"
@@ -53,10 +77,9 @@
     "popl %%ebx\n\t"
     ::"a"(z));
 }    
-#else
 #include <sys/time.h>
 #include <unistd.h>
-static unsigned int localcount()
+static unsigned int c_localcount_notsc()
 {
     struct timeval tv;
     unsigned limit=~0;
@@ -64,7 +87,7 @@
     gettimeofday(&tv, 0);
     return limit*tv.tv_usec;
 }
-static void longcount(long long* z)
+static void c_longcount_notsc(long long* z)
 {
     struct timeval tv;
     unsigned long long result;
@@ -77,27 +100,62 @@
     result+=limit*tv.tv_usec;
     *z=result;
 }
-#endif
+static unsigned int localcount_stub();
+static void longcount_stub(long long*);
+static unsigned int (*localcount)()=localcount_stub;
+static void (*longcount)(long long*)=longcount_stub;
 
-void dbgprintf(char* fmt, ...)
+static unsigned int localcount_stub()
+{
+    unsigned int regs[4];
+    do_cpuid(regs);
+    if ((regs[3] & 0x00000010) == 0) 
+    {
+	localcount=c_localcount_tsc;
+	longcount=c_longcount_tsc;
+    }	
+    else 
+    {
+    	localcount=c_localcount_notsc;
+	longcount=c_longcount_notsc;
+    }
+    return localcount();
+}
+static void longcount_stub(long long* z)
 {
-#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
+    unsigned int regs[4];
+    do_cpuid(regs);
+    if ((regs[3] & 0x00000010) == 0) 
+    {
+	localcount=c_localcount_tsc;
+	longcount=c_longcount_tsc;
+    }	
+    else 
+    {
+    	localcount=c_localcount_notsc;
+	longcount=c_longcount_notsc;
+    }
+    longcount(z);
+}
+
+int LOADER_DEBUG=0;
+inline void dbgprintf(char* fmt, ...)
+{
+    if(LOADER_DEBUG)
+    {
+	FILE* f;
+	va_list va;
+        va_start(va, fmt);
+	f=fopen("./log", "a");
+        vprintf(fmt, va);
+    	if(f)
+	{
+	    vfprintf(f, fmt, va);
+	    fsync(fileno(f));
+    	    fclose(f);
+	}
+	va_end(va);
+    }
 }    
 char export_names[500][30]={
 "name1",
@@ -182,6 +240,19 @@
 }    	     
 
 #else
+#define GARBAGE
+#ifdef GARBAGE
+struct alc_list_t;
+typedef struct alc_list_t {
+  int size;
+  int addr;
+  struct alc_list_t *prev;
+  struct alc_list_t *next;
+}alc_list;
+static alc_list *alclist=NULL;
+static alccnt=0;
+#endif
+
 void* my_mreq(int size, int to_zero)
 {
     void* answer; 
@@ -190,11 +261,56 @@
     else
 	answer=malloc(size+4);
     *(int*)answer=size;
-    return (int*)answer+1;
+#ifdef GARBAGE
+    if (alclist==NULL) {
+      alclist=malloc(sizeof(alc_list));
+      alclist->prev=alclist->next=NULL;
+    }
+    else {
+      alclist->next=malloc(sizeof(alc_list));
+      alclist->next->prev=alclist;
+      alclist->next->next=NULL;
+      alclist=alclist->next;
+    }
+    alclist->size=size;
+    alclist->addr=answer;
+    alccnt++;
+#endif
+    return (int*)((int)answer+sizeof(int));
 }	
 int my_release(char* memory)
 {
+#ifdef GARBAGE
+    alc_list* pp;
     if(memory==0)return 0;
+    if(alclist!=NULL)
+    {
+	pp=alclist;
+	if ((pp->prev==NULL) && (pp->next == NULL)){
+	   free(pp);
+           alclist=NULL;
+	}
+	else {
+		for(;pp;pp=pp->prev) {
+			if (pp->addr == memory-4) {
+				if (pp->prev)
+					pp->prev->next=pp->next;
+				if (pp->next)
+					pp->next->prev=pp->prev;
+				if (pp == alclist)
+					alclist=pp->prev;
+				free(pp);
+				alccnt--;
+				break;
+			}
+		}
+        	if (pp == NULL) {
+			printf("Not Found %x %d\n",memory-4,alccnt);
+			return 0;
+		}
+	}
+    }
+#endif
     free(memory-4);
     return 0;
 }
@@ -215,39 +331,44 @@
 }    
 int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
 {
-    dbgprintf("IsBadWritePtr(%x, %x)\n", ptr, count);
+    int result;
     if(count==0)
-	return 0;
+	result=0;
+    else
     if(ptr==0)
-        return 1;
-    return 0;
+        result=1;
+    else
+	result=0;
+    dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
+    return result;
 }
 int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
 {
-    dbgprintf("IsBadReadPtr(%x, %x)\n", ptr, count);
+    int result;
     if(count==0)
-	return 0;
+	result=0;
+    else
     if(ptr==0)
-        return 1;
-    return 0;
+        result=1;
+    else
+	result=0;
+    dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
+    return result;
 }
 void* CDECL expmalloc(int size)
 {
 //printf("malloc");
 //    return malloc(size);
     void* result=my_mreq(size,0);
-    dbgprintf("malloc(%x)\n", size);
+    dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
     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);
+    dbgprintf("free(0x%x)\n", mem);
     my_release(mem);
 }
 void* CDECL expnew(int size)
@@ -256,29 +377,27 @@
 //    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);
+    void* result=my_mreq(size,0);
+    dbgprintf("new(0x%x) => 0x%x\n", size, result);
     if(result==0)
-    {
-	dbgprintf("returns 0\n");
-	printf("WARNING: malloc() failed\n");
-    }	
+	printf("WARNING: new() failed\n");
     return result;
 
 }    
 int CDECL expdelete(void* memory)
 {
-    dbgprintf("delete(%x)\n", memory);
-    expfree(memory);
+    dbgprintf("delete(0x%x)\n", memory);
+    my_release(memory);
     return 0;
 }
 int WINAPI expDisableThreadLibraryCalls(int module)
 {
-    dbgprintf("DisableThreadLibraryCalls(%x)\n", module);
+    dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
     return 0;
 }    
 int CDECL exp_initterm(int v1, int v2)
 {
+    dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
     return 0;
 }    
 
@@ -291,19 +410,35 @@
 
 void* WINAPI expGetDriverModuleHandle(DRVR* pdrv)
 {
-    dbgprintf("GetDriverModuleHandle(%x)\n", pdrv);
-    return pdrv->hDriverModule;
+    void* result;
+    if (pdrv==NULL) result=NULL;
+    result=pdrv->hDriverModule;
+    dbgprintf("GetDriverModuleHandle(0x%x) => 0x%x\n", pdrv, result);
+    return result;
 }
 
 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);
+	void* result;
+	if(!name)
+	    result=0;
+	else
+	{
+    	    wm=MODULE_FindModule(name);
+		if(wm==0)result=0;
+	    else
+    		result=(void*)(wm->module);
+	}
+	if(!result)
+	{
+	    if(strcasecmp(name, "kernel32")==0)
+		result=0x120;
+	}	
+         dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
+	return result;
 }
+
 struct th_list_t;
 typedef struct th_list_t{
 int id;
@@ -322,13 +457,11 @@
     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");
+	printf( "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);
@@ -342,6 +475,8 @@
 	list=list->next;
     }		
     list->thread=pth;
+    dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
+	pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
     return pth;
 }
 
@@ -349,8 +484,13 @@
 
 struct mutex_list_t
 {
+    char type;
     pthread_mutex_t *pm;
+    pthread_cond_t  *pc;
+    char state;
+    char reset;
     char name[64];
+    int  semaphore;
     struct mutex_list_t* next;
     struct mutex_list_t* prev;
 };
@@ -359,21 +499,26 @@
 void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, 
     char bInitialState, const char* name)
 {
-#warning ManualReset
     pthread_mutex_t *pm;
-    dbgprintf("CreateEvent\n");
+    pthread_cond_t  *pc;
     if(mlist!=NULL)
     {
 	mutex_list* pp=mlist;
 	if(name!=NULL)
 	do
 	{
-	    if(strcmp(pp->name, name)==0)
+	    if((strcmp(pp->name, name)==0) && (pp->type==0))
+	    {
+		dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
+		    pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
 		return pp->pm;
+	    }
 	}while(pp=pp->prev);
     }	
     pm=my_mreq(sizeof(pthread_mutex_t), 0);
     pthread_mutex_init(pm, NULL);
+    pc=my_mreq(sizeof(pthread_cond_t), 0);
+    pthread_cond_init(pc, NULL);
     if(mlist==NULL)
     {
 	mlist=my_mreq(sizeof(mutex_list), 00);
@@ -382,53 +527,158 @@
     else
     {
 	mlist->next=my_mreq(sizeof(mutex_list), 00);
-	mlist->next->prev=mlist->next;
+	mlist->next->prev=mlist;
 	mlist->next->next=NULL;
 	mlist=mlist->next;
     }
+    mlist->type=0; /* Type Event */
     mlist->pm=pm;
+    mlist->pc=pc;
+    mlist->state=bInitialState;
+    mlist->reset=bManualReset;
     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;
+*/
+    if(name)
+    dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
+        pSecAttr, bManualReset, bInitialState, name, name, mlist);
+    else
+    dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
+        pSecAttr, bManualReset, bInitialState, mlist);
+    return mlist;
 }    
 
 void* WINAPI expSetEvent(void* event)
 {
-    dbgprintf("Trying to lock %X\n", event);
-    pthread_mutex_lock(event);
+    mutex_list *ml = (mutex_list *)event;
+    dbgprintf("SetEvent(%x) => 0x1\n", event);
+    pthread_mutex_lock(ml->pm);
+    if (ml->state == 0) {
+	ml->state = 1;
+	pthread_cond_signal(ml->pc);
+    }
+    pthread_mutex_unlock(ml->pm);
+
+    return (void *)1;
 }
 void* WINAPI expResetEvent(void* event)
 {
-    dbgprintf("Unlocking %X\n", event);
-    pthread_mutex_unlock(event);    
+    mutex_list *ml = (mutex_list *)event;
+    dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
+    pthread_mutex_lock(ml->pm);
+    ml->state = 0;
+    pthread_mutex_unlock(ml->pm);    
+
+    return (void *)1;
 }
 
 void* WINAPI expWaitForSingleObject(void* object, int duration)
 {
-#warning not sure
-    dbgprintf("WaitForSingleObject: duration %d\n", duration);
-    pthread_mutex_lock(object);
-    pthread_mutex_unlock(object);
+    mutex_list *ml = (mutex_list *)object;
+    int ret;
+    mutex_list* pp=mlist;
+//    dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
+    do {
+	if (pp == NULL) dbgprintf("WaitForSingleObject: NotFound\n");
+	if((pp->pm, mlist->pm)==0)
+		break;;
+     }while(pp=pp->prev);
+    
+
+    pthread_mutex_lock(ml->pm);
+
+    switch(ml->type) {
+      case 0: /* Event */
+	if (duration == 0) { /* Check Only */
+		if (ml->state == 1) ret = WAIT_FAILED;
+		else                   ret = WAIT_OBJECT_0;
+	}
+	if (duration == -1) { /* INFINITE */
+		if (ml->state == 0)
+			pthread_cond_wait(ml->pc,ml->pm);
+		if (ml->reset)
+			ml->state = 0;
+		ret = WAIT_OBJECT_0;
+	}
+	if (duration > 0) {  /* Timed Wait */
+		struct timespec abstime;
+		struct timeval now;
+		gettimeofday(&now, 0);
+		abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
+		abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
+		if (ml->state == 0)
+			ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
+		if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
+		else                  ret = WAIT_OBJECT_0;
+		if (ml->reset)
+			ml->state = 0;	
+	}
+        break;
+      case 1:  /* Semaphore */
+        if (duration == 0) {
+		if(ml->semaphore==0) ret = WAIT_FAILED;
+		else {
+			ml->semaphore++;
+			ret = WAIT_OBJECT_0;
+		}
+        }
+	if (duration == -1) {
+		if (ml->semaphore==0)
+			pthread_cond_wait(ml->pc,ml->pm);
+		ml->semaphore--;
+	}
+        break;
+    }
+    pthread_mutex_unlock(ml->pm);
+
+    dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
+    return (void *)ret;
 }    
 
 static BYTE PF[64] = {0,};
 
+WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
+{
+    WIN_BOOL result;
+    if(v>63)result=0;
+    else result=PF[v];
+    dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
+    return result;
+}
+
+static void DumpSystemInfo(const SYSTEM_INFO* si)
+{
+    dbgprintf("  Processor architecture %d\n", si->u.s.wProcessorArchitecture);
+    dbgprintf("  Page size: %d\n", si->dwPageSize);
+    dbgprintf("  Minimum app address: %d\n", si->lpMinimumApplicationAddress);
+    dbgprintf("  Maximum app address: %d\n", si->lpMaximumApplicationAddress);
+    dbgprintf("  Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
+    dbgprintf("  Number of processors: %d\n", si->dwNumberOfProcessors);
+    dbgprintf("  Processor type: 0x%x\n", si->dwProcessorType);
+    dbgprintf("  Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
+    dbgprintf("  Processor level: 0x%x\n", si->wProcessorLevel);
+    dbgprintf("  Processor revision: 0x%x\n", si->wProcessorRevision);
+}
+
 void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
 {
     	/* FIXME: better values for the two entries below... */
 	static int cache = 0;
 	static SYSTEM_INFO cachedsi;
+	unsigned int regs[4];
 	HKEY	xhkey=0,hkey;
-        dbgprintf("GetSystemInfo()\n");
+        dbgprintf("GetSystemInfo(0x%d) =>\n");
 
 	if (cache) {
 		memcpy(si,&cachedsi,sizeof(*si));
+		DumpSystemInfo(si);
 		return;
 	}
 	memset(PF,0,sizeof(PF));
@@ -437,22 +687,22 @@
 	cachedsi.dwPageSize 			= getpagesize();
 
 	/* FIXME: better values for the two entries below... */
-	cachedsi.lpMinimumApplicationAddress	= (void *)0x40000000;
+	cachedsi.lpMinimumApplicationAddress	= (void *)0x00000000;
 	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;
+	cachedsi.wProcessorLevel		= 5; /* pentium */
+	cachedsi.wProcessorRevision		= 0x0101;
 	
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__)
         cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
         cachedsi.wProcessorLevel= 5;
 	PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
-#ifdef MMX
-        PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
-#endif
+	do_cpuid(regs);
+	if (regs[3] & 0x00800000)
+          PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
         cachedsi.dwNumberOfProcessors=1;
 #else
 	{
@@ -559,8 +809,10 @@
 			if (sscanf(value,"%d",&x))
 				cachedsi.wProcessorRevision = x;
 		}
-		if ( (!lstrncmpiA(line,"flags",strlen("flags"))) ||
-                     (!lstrncmpiA(line,"features",strlen("features"))) ) {
+		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"))
@@ -569,70 +821,89 @@
 		}
 	}
 	fclose (f);
+/*
+ *	ad hoc fix for smp machines.
+ *	some problems on WaitForSingleObject,CreateEvent,SetEvent
+ *			CreateThread ...etc..
+ *
+ */
+        cachedsi.dwNumberOfProcessors=1;
 	}
 #endif /* __FreeBSD__ */
 	memcpy(si,&cachedsi,sizeof(*si));
+	DumpSystemInfo(si);
 }
 
 long WINAPI expGetVersion()
 {
-    return 0xC0000A04;//Windows 98
+    dbgprintf("GetVersion() => 0xC0000004\n");
+    return 0xC0000004;//Windows 95
 }    
 
 HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
 {
 //    printf("HeapCreate:");
-    dbgprintf("HeapCreate(%X, %X, %X)\n", flags, init_size, max_size); 
+    HANDLE result;
     if(init_size==0)
-    	return (HANDLE)my_mreq(0x110000, 0);
+    	result=(HANDLE)my_mreq(0x110000, 0);
     else
-	return (HANDLE)my_mreq(init_size, 0);
+	result=(HANDLE)my_mreq(init_size, 0);
+    dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result); 
+    return result;
 }		
 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);    
+/**
+ Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
+ HeapAlloc returns area larger than size argument :-/
+**/
+    z=my_mreq(((size+4095)/4096)*4096, flags&8);    
 //    z=HeapAlloc(heap,flags,size);
     if(z==0)
 	printf("HeapAlloc failure\n");
+    dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size 0x%x) => 0x%x\n", heap, flags, size, z); 
     return z;
 }
 long WINAPI expHeapDestroy(void* heap)
 {
-    dbgprintf("HeapDestroy(%X)\n", heap); 
+    dbgprintf("HeapDestroy(heap 0x%x) => 1\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);
+    dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", arg1, arg2, ptr);
     my_release(ptr);
     return 1;
 }    	
 long WINAPI expHeapSize(int heap, int flags, void* pointer)
 {
-    return my_size(pointer);
+    long result=my_size(pointer);
+    dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
+    return result;
 } 
 long WINAPI expGetProcessHeap(void)
 {
+    dbgprintf("GetProcessHeap() => 1\n");
     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");
+    dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
     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);
+    int result=VirtualFree(v1,v2,v3);
+    dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
+    return result;
 }    
 struct CRITSECT 
 {
@@ -643,7 +914,7 @@
 void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
 {
     struct CRITSECT cs;
-    dbgprintf("InitCriticalSection(%X) \n", c);
+    dbgprintf("InitializeCriticalSection(0x%x)\n", c);
 /*    if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
     {
 	printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
@@ -659,8 +930,8 @@
 }          
 void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
 {
-    struct CRITSECT* cs=(struct CRITSECT*)c;
-    dbgprintf("EnterCriticalSection(%X) \n",c);
+    struct CRITSECT* cs=*(struct CRITSECT**)c;
+    dbgprintf("EnterCriticalSection(0x%x)\n",c);
 //    cs.id=pthread_self();
     if(cs->locked)
 	if(cs->id==pthread_self())
@@ -672,21 +943,30 @@
 }          
 void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
 {
-    struct CRITSECT* cs=(struct CRITSECT*)c;
-    dbgprintf("LeaveCriticalSection(%X) \n",c);
+    struct CRITSECT* cs=*(struct CRITSECT**)c;
+//    struct CRITSECT* cs=(struct CRITSECT*)c;
+    dbgprintf("LeaveCriticalSection(0x%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);
+    struct CRITSECT* cs=*(struct CRITSECT**)c;
+//    struct CRITSECT* cs=(struct CRITSECT*)c;
+    dbgprintf("DeleteCriticalSection(0x%x)\n",c);
+    pthread_mutex_destroy(&(cs->mutex));
+    free(cs);
     return;
 }
 int WINAPI expGetCurrentThreadId()
 {
-    dbgprintf("GetCurrentThreadId() \n");
+    dbgprintf("GetCurrentThreadId() => %d\n", getpid());
+    return getpid();
+}                  
+int WINAPI expGetCurrentProcess()
+{
+    dbgprintf("GetCurrentProcess() => %d\n", getpid());
     return getpid();
 }                  
 struct tls_s;
@@ -702,7 +982,6 @@
     
 void* WINAPI expTlsAlloc()
 {
-    dbgprintf("TlsAlloc \n");
     if(g_tls==NULL)
     {
 	g_tls=my_mreq(sizeof(tls_t), 0);
@@ -715,135 +994,212 @@
 	g_tls->next->next=NULL;
 	g_tls=g_tls->next;
     }
-    return g_tls;
+    dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
+    return g_tls;    
 }
 
 int WINAPI expTlsSetValue(tls_t* index, void* value)
 {
-    dbgprintf("TlsSetVal(%X %X) \n", index, value );
+    int result;
     if(index==0)
-	return 0;
-    index->value=value;
-    return 1;
+	result=0;
+    else
+    {
+	index->value=value;
+	result=1;
+    }
+    dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
+    return result;
 }
 void* WINAPI expTlsGetValue(tls_t* index)
 {
-    dbgprintf("TlsGetVal(%X) \n", index );
+    void* result;
     if(index==0)
-	return 0;
-    return index->value;	
+	result=0;
+    else
+	result=index->value;	
+    dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
+    return result;
 }
 int WINAPI expTlsFree(tls_t* index)
 {
-    dbgprintf("TlsFree(%X) \n", index);
+    int result;
     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;
+	result=0;
+    else
+    {
+	if(index->next)
+	    index->next->prev=index->prev;
+	if(index->prev)
+    	    index->prev->next=index->next;
+	my_release((void*)index);
+	result=1;
+    }
+    dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
+    return result;
 }     
-
 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");
+    dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
     return z;
 }	
 void* WINAPI expLocalLock(void* z)
 {
-   dbgprintf("LocalLock\n");
+    dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
     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);
+	z=calloc(size, 1);	
+//	z=my_mreq(size, 1);
 	else
-	z=my_mreq(size, 0);
+	z=malloc(size);
+//	z=my_mreq(size, 0);
     if(z==0)
-	printf("LocalAlloc() failed\n");
+	printf("GlobalAlloc() failed\n");
+    dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
     return z;
 }	
 void* WINAPI expGlobalLock(void* z)
 {
-     dbgprintf("GlobalLock\n");
+    dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
     return z;
 }    
-
 int WINAPI expLoadStringA(long instance, long  id, void* buf, long size)
 {
-    dbgprintf("LoadStringA\n");
-    return LoadStringA(instance, id, buf, size);
+    int result=LoadStringA(instance, id, buf, size);
+//    if(buf)
+    dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
+	instance, id, buf, size, result, buf);
+//    else
+//    dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
+//	instance, id, buf, size, result);    
+    return result;
 }    	    	
 
-long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, char* s2, int siz2)
+long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
 {
 #warning FIXME
-    dbgprintf("MB2WCh\n");
-    dbgprintf("WARNING: Unsupported call: MBToWCh %s\n", s1);       
+    int i;
+    int result;
     if(s2==0)
-	return 1;
-    s2[0]=s2[1]=0;
-    return 1;
+    	result=1;
+    else
+    {
+    if(siz1>siz2/2)siz1=siz2/2;    
+    for(i=1; i<=siz1; i++)
+    {
+    	*s2=*s1;
+	if(!*s1)break;
+	s2++;
+	s1++;
+    }
+    result=i;
+    }
+    if(s1)
+    dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',
+	size %d, dest buffer 0x%x, dest size %d) => %d\n",
+	    v1, v2, s1, s1, siz1, s2, siz2, result);
+    else
+    dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,
+	size %d, dest buffer 0x%x, dest size %d) =>\n",
+	    v1, v2, siz1, s2, siz2, result);
+    return result;
+}
+static void wch_print(const short* str)
+{
+    dbgprintf("  src: ");
+    while(*str)dbgprintf("%c", *str++);
+    dbgprintf("\n");
 }
 long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1, char* s2, int siz2, char* c3, int* siz3)
 {
     int result;
-    dbgprintf("WCh2MB\n");
+    dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
+	"dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
     result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
     dbgprintf("=> %d\n", result);
+    if(s1)wch_print(s1);
+    if(s2)dbgprintf("  dest: %s\n", s2);
     return result;
 }
 long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
 {
-    dbgprintf("GetVersionExA\n");
+    dbgprintf("GetVersionExA(0x%x) => 1\n");
+    c->dwOSVersionInfoSize=sizeof(*c);
     c->dwMajorVersion=4;
-    c->dwMinorVersion=10;
-    c->dwBuildNumber=0x40a07ce;
+    c->dwMinorVersion=0;
+    c->dwBuildNumber=0x4000457;
     c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
-    strcpy(c->szCSDVersion, "Win98");
+    strcpy(c->szCSDVersion, " B");
+    dbgprintf("  Major version: 4\n  Minor version: 0\n  Build number: 0x4000457\n"
+    "  Platform Id: VER_PLATFORM_WIN32_WINDOWS\n Version string: ' B'\n");
     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)
+    pthread_mutex_t *pm;
+    pthread_cond_t  *pc;
+    if(mlist!=NULL)
     {
-	printf("semget() failed\n");
-	return (HANDLE)-1;
+	mutex_list* pp=mlist;
+	if(name!=NULL)
+	do
+	{
+	    if((strcmp(pp->name, name)==0) && (pp->type==1))
+	    {
+	        dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x",
+		    v1, init_count, max_count, name, name, mlist);
+		return (HANDLE)mlist;
+	    }
+	}while(pp=pp->prev);
     }	
-    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)
+    pm=my_mreq(sizeof(pthread_mutex_t), 0);
+    pthread_mutex_init(pm, NULL);
+    pc=my_mreq(sizeof(pthread_cond_t), 0);
+    pthread_cond_init(pc, NULL);
+    if(mlist==NULL)
+    {
+	mlist=my_mreq(sizeof(mutex_list), 00);
+	mlist->next=mlist->prev=NULL;
+    }
+    else
     {
-	printf("semop() failed\n");
+	mlist->next=my_mreq(sizeof(mutex_list), 00);
+	mlist->next->prev=mlist;
+	mlist->next->next=NULL;
+	mlist=mlist->next;
     }
-    return sem;	
-*/    
-    void* z;
-    dbgprintf("CreateSemaphoreA\n");
-    z=my_mreq(24, 0);
-    pthread_mutex_init(z, NULL);
-    return (HANDLE)z;
+    mlist->type=1; /* Type Semaphore */
+    mlist->pm=pm;
+    mlist->pc=pc;
+    mlist->state=0;
+    mlist->reset=0;
+    mlist->semaphore=init_count;
+    if(name!=NULL)
+        strncpy(mlist->name, name, 64);
+    else
+	mlist->name[0]=0;
+    if(pm==NULL)
+	dbgprintf("ERROR::: CreateSemaphoreA failure\n");
+    if(name)
+	dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x",
+	v1, init_count, max_count, name, name, mlist);
+    else
+	dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x",
+	v1, init_count, max_count, mlist);
+    return (HANDLE)mlist;
 }
         
 long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
@@ -852,48 +1208,59 @@
 // 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");
-    }*/
+    mutex_list *ml = (mutex_list *)hsem;
 
-    return 1;//zero on error
+    pthread_mutex_lock(ml->pm);
+    if (prev_count != 0) *prev_count = ml->semaphore;
+    if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
+    ml->semaphore += increment;
+    pthread_mutex_unlock(ml->pm);
+    dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
+	hsem, increment, prev_count);
+    return 1;
 }
 
 
 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 result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
+    dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
+	key, subkey, reserved, access, newkey, result);
+    if(newkey)dbgprintf("  New key: 0x%x\n", *newkey);
+    return result;
 }    
 long WINAPI expRegCloseKey(long key)
 {
-    dbgprintf("RegCloseKey()\n");
-    return RegCloseKey(key);
+    long result=RegCloseKey(key);
+    dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
+    return result;
 }         
 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 result=RegQueryValueExA(key, value, reserved, type, data, count);
+    dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
+	" => 0x%x\n", key, value, reserved, data, count, result);
+    if(data && count)dbgprintf("  read %d bytes: '%s'\n", *count, data);
+    return result;
 }  
 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 result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
+    dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
+	" 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
+	    key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
+    if(!result && newkey) dbgprintf("  New key: 0x%x\n", *newkey);
+    if(!result && status) dbgprintf("  New key status: 0x%x\n", *status);
+    return result;
 }
 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 result=RegSetValueExA(key, name, v1, v2, data, size);
+    dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d", 
+	key, name, v1, v2, data, *(int*)data, data, size, result);
+    return result;
 }        
 
 long WINAPI expRegOpenKeyA (
@@ -901,30 +1268,38 @@
  LPCSTR lpSubKey,
  int* phkResult
 ){
-    return  RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
+    long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
+    dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
+	hKey, lpSubKey, phkResult, result);
+    if(!result && phkResult) dbgprintf("  New key: 0x%x\n", *phkResult);
+    return result;
 }
 
 long WINAPI expQueryPerformanceCounter(long long* z)
 {
-    dbgprintf("QueryPerformanceCounter()\n");
     longcount(z);
+    dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
     return 1; 
 }
 
 static double old_freq()
 {
-    int i=time(NULL);
+    static double ofreq=0.0;
+    int i;
     int x,y;
+    i=time(NULL);
+    if (ofreq != 0.0) return ofreq;
     while(i==time(NULL));
     x=localcount();
     i++;
     while(i==time(NULL));
     y=localcount();
-    return (double)(y-x)/1000.;
+    ofreq = (double)(y-x)/1000.;
+    return ofreq;
 }
 static double CPU_Freq()
 {
-#ifdef USE_TSC
+//#ifdef USE_TSC
 	FILE *f = fopen ("/proc/cpuinfo", "r");
 	char line[200];
 	char model[200]="unknown";
@@ -934,7 +1309,7 @@
 	
 	if (!f)
 	{
-	    printf("Can't open /proc/cpuinfo for reading\n");
+	    //printf("Can't open /proc/cpuinfo for reading\n");
 	    return old_freq();
 	}    
 	while (fgets(line,200,f)!=NULL) 
@@ -961,100 +1336,114 @@
 	fclose(f);
 	if(freq<0)return old_freq();
 	return freq;
-#else
-	return old_freq();
-#endif    	
+//#else
+//	return old_freq();
+//#endif    	
 }
 
 long WINAPI expQueryPerformanceFrequency(long long* z)
 {
-    dbgprintf("QueryPerformanceFrequency()\n");
     *z=(long long)CPU_Freq();
+    dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
     return 1; 
 }
 long WINAPI exptimeGetTime()
 {
     struct timeval t;
-    dbgprintf("timeGetTime()\n");
+    long result;
     gettimeofday(&t, 0);
-    return 1000*t.tv_sec+t.tv_usec/1000;
+    result=1000*t.tv_sec+t.tv_usec/1000;
+    dbgprintf("timeGetTime() => %d\n", result);
+    return result;
 }
 void* WINAPI expLocalHandle(void* v)
 {
-    dbgprintf("LocalHandle\n");
+    dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
     return v;
 }        
 void* WINAPI expGlobalHandle(void* v)
 {
-    dbgprintf("GlobalHandle\n");
+    dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
     return v;
 }        
 int WINAPI expGlobalUnlock(void* v)
 {
-    dbgprintf("GlobalUnlock\n");
+    dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
     return 1;
 }
 //
 void* WINAPI expGlobalFree(void* v)
 {
-    dbgprintf("GlobalFree(%X)\n", v);
-    my_release(v);
+    dbgprintf("GlobalFree(0x%x) => 0\n", v);
+    //my_release(v);
+    free(v);
     return 0;
-}        
+}
+        
+          
+void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
+{
+    void* result=realloc(v, size);
+    dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
+    return result;
+}
 
 int WINAPI expLocalUnlock(void* v)
 {
-    dbgprintf("LocalUnlock\n");
+    dbgprintf("LocalUnlock(0x%x) => 1\n", v);
     return 1;
 }
-//
+  //
 void* WINAPI expLocalFree(void* v)
 {
-    dbgprintf("LocalFree(%X)\n", v);
+    dbgprintf("LocalFree(0x%x) => 0\n", v);
     my_release(v);
     return 0;
 }        
-
 HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
 {
-    dbgprintf("FindResourceA\n");
-    return FindResourceA(module, name, type);
+    HRSRC result=FindResourceA(module, name, type);
+    dbgprintf("FindResourceA(module 0x%x, name 0x%x, type 0x%x) => 0x%x\n", module, name, type, result);
+    return result;
 }
+extern HRSRC WINAPI LoadResource(HMODULE, HRSRC);
 HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
 {
-    dbgprintf("LoadResource\n");
-    return LoadResource(module, res);;    
+    HGLOBAL result=LoadResource(module, res);
+    dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
+    return result;
 }
 void* WINAPI expLockResource(long res)
 {
-    dbgprintf("LockResource\n");
-    return LockResource(res);
+    void* result=LockResource(res);
+    dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
+    return result;
 }    
 int WINAPI expFreeResource(long res)
 {
-    dbgprintf("FreeResource\n");
-    return FreeResource(res);
+    int result=FreeResource(res);
+    dbgprintf("FreeResource(0x%x) => %d\n", res, result);
+    return result;
 }    
 //bool fun(HANDLE)
 //!0 on success
 int WINAPI expCloseHandle(long v1)
 {
-    dbgprintf("CloseHandle\n");
+    dbgprintf("CloseHandle(0x%x) => 1\n", v1);
     return 1;
 }    
 
 const char* WINAPI expGetCommandLineA()
 {
-    dbgprintf("GetCommandLine\n");
+    dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
     return "c:\\aviplay.exe";
 }
+static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
 LPWSTR WINAPI expGetEnvironmentStringsW()
 {
-    static wchar_t envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
-    dbgprintf("GetEnvStringsW\n");
-    return (LPWSTR)envs;
+ dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
+ return 0;
 }
-
 void * WINAPI expRtlZeroMemory(void *p, size_t len)
 {
     void* result=memset(p,0,len);
@@ -1074,170 +1463,225 @@
     dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
     return result;
 }
-
-
 int WINAPI expFreeEnvironmentStringsW(short* strings)
 {
-    dbgprintf("FreeEnvStringsW\n");
+    dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
     return 1;
 }
+int WINAPI expFreeEnvironmentStringsA(char* strings)
+{
+ dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
+ return 1;
+}
+static const char ch_envs[]=
+    "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
+    "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
 LPCSTR WINAPI expGetEnvironmentStrings()
 {
-    dbgprintf("GetEnvStrings\n");
-    return "\0\0";
+    dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
+    return (LPCSTR)ch_envs;
+// dbgprintf("GetEnvironmentStrings() => 0\n");
+// return 0;
 }
 
 int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
 {
     int i;    
-    dbgprintf("GetStartupInfoA\n");
-/*    
-    for(i=0; i<sizeof(STARTUPINFOA)/4; i++)
-     ((int*)s)[i]=i+0x200;
-*/
+    dbgprintf("GetStartupInfoA(0x%x) => 1\n");
     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;
+// s->lpReserved="Reserved";
+// s->lpDesktop="Desktop";
+// s->lpTitle="Title";
+// s->dwX=s->dwY=0;
+// s->dwXSize=s->dwYSize=200;
+ s->dwFlags=s->wShowWindow=1;
+// s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
+    dbgprintf("  cb=%d\n", s->cb);
+    dbgprintf("  lpReserved='%s'\n", s->lpReserved);
+    dbgprintf("  lpDesktop='%s'\n", s->lpDesktop);
+    dbgprintf("  lpTitle='%s'\n", s->lpTitle);
+    dbgprintf("  dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
+	s->dwX, s->dwY, s->dwXSize, s->dwYSize);
+    dbgprintf("  dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
+	s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
+    dbgprintf("  dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
+	s->dwFlags, s->wShowWindow, s->cbReserved2);
+    dbgprintf("  lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
+	s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
     return 1;
 }    
 
 int WINAPI expGetStdHandle(int z)
 {
-    dbgprintf("GetStdHandle\n");
-    dbgprintf("WARNING: Unsupported call: GetStdHandle\n");       
-    return 1234;
+ dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
+ return z+0x1234;
 }
 int WINAPI expGetFileType(int handle)
 {
-    dbgprintf("GetFileType\n");
-    dbgprintf("WARNING: Unsupported call: GetFileType\n");       
-    return 5678;
+ dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
+ return 0x3;
 }
 int WINAPI expSetHandleCount(int count)
 {
-    dbgprintf("SetHandleCount\n");
+    dbgprintf("SetHandleCount(0x%x) => 1\n", count);
     return 1;        
 }
 int WINAPI expGetACP()
 {
-    dbgprintf("GetACP\n");
-    dbgprintf("WARNING: Unsupported call: GetACP\n");       
+    dbgprintf("GetACP() => 0\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");
+    int result;
 //    printf("File name of module %X requested\n", module);
     if(s==0)
-    return 0;
+	result=0;
+    else
     if(len<35)
-    return 0;
-    strcpy(s, "c:\\windows\\system\\");
-    mr=MODULE32_LookupHMODULE(module);
-    if(mr==0)//oops
+    result=0;
+    else
     {
-        strcat(s, "aviplay.dll");
-	return 1;
-    }	
-    if(strrchr(mr->filename, '/')==NULL)
-	strcat(s, mr->filename);
+	result=1;
+	strcpy(s, "c:\\windows\\system\\");
+	mr=MODULE32_LookupHMODULE(module);
+	if(mr==0)//oops
+    	    strcat(s, "aviplay.dll");
+	else
+	if(strrchr(mr->filename, '/')==NULL)
+	    strcat(s, mr->filename);
+	else
+	    strcat(s, strrchr(mr->filename, '/')+1);
+    }
+    if(!s)
+    dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
+	module, s, len, result);
     else
-	strcat(s, strrchr(mr->filename, '/')+1);
-    return 1;
+    dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )",
+	module, s, len, result, s);    
+    return result;
 }    
     
 int WINAPI expSetUnhandledExceptionFilter(void* filter)
 {
-    dbgprintf("SetUnhandledExcFilter\n");
+    dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
     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 result;
+    printf("They want library %s\n", def_path, name);
+    if(strncmp(name, "c:\\windows\\", 11)==0)name+=11;
+    if(name[0]!='/')
+    {
+	strcpy(qq, def_path);
+	strcat(qq, "/");
+	if(strncmp(name, ".\\", 2)==0)
+	    strcat(qq, name+2);
+	else
+	    strcat(qq, name);
+    }
+    dbgprintf("Entering LoadLibraryA(%s)\n", name);
+    result=LoadLibraryA(qq);
+    dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
+    return result;
 }      
 int WINAPI expFreeLibrary(int module)
 {
-    dbgprintf("FreeLibrary\n");
-    return FreeLibrary(module);
+    int result=FreeLibrary(module);
+    dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
+    return result;
 }   
 void* WINAPI expGetProcAddress(HMODULE mod, char* name)
 {
-    dbgprintf("GetProcAddress\n");
-    return GetProcAddress(mod, name);
+    int result;
+    if(mod!=0x120)
+	result=GetProcAddress(mod, name);
+    else
+	result=LookupExternalByName("kernel32.dll", name);
+    dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
+    return result;
 }    
 
 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 result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
+    if(!name)
+    dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x, 
+	flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
+	    hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
+    else
+    dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x, 
+	flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
+	    hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);    
+    return result;
 }    
 
 long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
 {
-    dbgprintf("OpenFileMappingA\n");
-    return OpenFileMappingA(hFile, hz, name);
+    long result=OpenFileMappingA(hFile, hz, name);
+    if(!name)
+	dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
+	    hFile, hz, result);
+    else
+	dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
+	    hFile, hz, name, name, result);
+    return result;
 }
 
 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);
+    dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
+	file,mode,offHigh,offLow,size,(char*)file+offLow);
     return (char*)file+offLow;
 }
 
 void* WINAPI expUnmapViewOfFile(void* view)
 {
-    dbgprintf("UnmapViewOfFile()\n");
+    dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
     return 0;
 }
 
 void* WINAPI expSleep(int time)
 {
-    dbgprintf("Sleep(%d)\n", time);
+    dbgprintf("Sleep(%d) => 0\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;
+        dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
+        return (void*)0x81;
 }
 
 int WINAPI expGetDeviceCaps(int hdc, int unk)
 {
-        dbgprintf("GetDeviceCaps(%d, %d)\n", hdc, unk);
+        dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
         return 0;
 }
 
 WIN_BOOL WINAPI expDeleteDC(int hdc)
 {
-        dbgprintf("DeleteDC(%d)\n", hdc);
+        dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
         return 0;
 }
 
 int expwsprintfA(char* string, char* format, ...)
 {
     va_list va;
+    int result;
     va_start(va, format);
-    dbgprintf("wsprintfA\n");
-    return vsprintf(string, format, va);
+    result=vsprintf(string, format, va);
+    dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
+    va_end(va);
+    return result;
 }
 
 int WINAPI expGetPrivateProfileIntA(const char* appname, const char* keyname, int default_value, const char* filename)
@@ -1248,8 +1692,11 @@
     int result;
     
     buffer[255]=0;
-    dbgprintf("GetPrivateProfileIntA(%s, %s, %s)\n", appname, keyname, filename );
-    if(!(appname && keyname && filename) ) return default_value;
+    if(!(appname && keyname && filename) )
+    {
+        dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
+	return default_value;
+    }
     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
     strcpy(fullname, "Software\\IniFileMapping\\");
     strcat(fullname, appname);
@@ -1263,17 +1710,26 @@
 //    printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
     free(fullname); 
     if(result)
-    return default_value;
+	result=default_value;
     else
-	return atoi(buffer);    	
+	result=atoi(buffer);
+    dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
+    return result;
 }
+int WINAPI expGetProfileIntA(const char* appname, const char* keyname, int default_value)
+{
+    dbgprintf("GetProfileIntA -> ");
+//    dbgprintf("GetProfileIntA(%s, %s, %d)\n", appname, keyname, default_value);
+    return expGetPrivateProfileIntA(appname, keyname, default_value, "default");    
+}
+
 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 );
+    dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", 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\\");
@@ -1286,9 +1742,12 @@
     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);
+    if(result)
+    {
+	strncpy(dest, def_val, size);
+	if (strlen(def_val)< size) size = strlen(def_val);
+    }
+    dbgprintf(" => %d ( '%s' )\n", size, dest);
     return size;
 }
 int WINAPI expWritePrivateProfileStringA(const char* appname, const char* keyname,
@@ -1296,8 +1755,12 @@
 {
     int size=256;
     char* fullname;
-    dbgprintf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
-    if(!(appname && keyname && filename) ) return -1;
+    dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
+    if(!(appname && keyname && filename) ) 
+    {
+	dbgprintf(" => -1\n");
+	return -1;	
+    }
     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
     strcpy(fullname, "Software\\IniFileMapping\\");
     strcat(fullname, appname);
@@ -1309,6 +1772,7 @@
 //    printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
 //    printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
     free(fullname); 
+    dbgprintf(" => 0\n");
     return 0;
 }
 
@@ -1328,50 +1792,119 @@
 }
 
 
+  
 int WINAPI expDefDriverProc(int _private, int id, int msg, int arg1, int arg2)
 {
-    printf("Called DefDriverProc(%X)\n", msg);
+    dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", _private, id, msg, arg1, arg2);
     return 0;
 }    
 
 int WINAPI expSizeofResource(int v1, int v2)
 {
-    dbgprintf("SizeofResource()\n");
-    return SizeofResource(v1, v2);
+    int result=SizeofResource(v1, v2);
+    dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
+    return result;
 }    
 
 int WINAPI expGetLastError()
 {
-    dbgprintf("GetLastError()\n");
-    return GetLastError();
+    int result=GetLastError();
+    dbgprintf("GetLastError() => 0x%x\n", result);
+    return result;
 }
 
 void WINAPI expSetLastError(int error)
 {
-    dbgprintf("SetLastError()\n");
+    dbgprintf("SetLastError(0x%x)\n", error);
     SetLastError(error);
 }        
 
 char* expstrrchr(char* string, int value)
 {
-    return strrchr(string, value);
+    char* result=strrchr(string, value);
+    if(result)
+	dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
+    else	
+	dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);    
+    return result;
 }    
 
 char* expstrchr(char* string, int value)
 {
-    return strchr(string, value);
+    char* result=strchr(string, value);
+    if(result)
+	dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
+    else	
+	dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);    
+    return result;
 }    
+int expstrlen(char* str)
+{
+    int result=strlen(str);
+    dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
+    return result; 
+}
+int expstrcpy(char* str1, const char* str2) 
+{
+    int result=strcpy(str1, str2);
+    dbgprintf("strcpy(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
+    return result;
+}
+int expstrcmp(const char* str1, const char* str2)
+{
+    int result=strcmp(str1, str2);
+    dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
+    return result;
+}
+int expstrcat(char* str1, const char* str2) 
+{
+    int result=strcat(str1, str2);
+    dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
+    return result;    
+}
+int expmemmove(void* dest, void* src, int n) 
+{
+    int result=memmove(dest, src, n);
+    dbgprintf("memmove(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
+    return memmove;
+}
+int expmemcmp(void* dest, void* src, int n) 
+{
+    int result=memcmp(dest, src, n);
+    dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
+    return result;
+}
+time_t exptime(time_t* t)
+{
+    time_t result=time(t);
+    dbgprintf("time(0x%x) => %d\n", t, result);
+    return result;
+}
+
+int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
+{
+    int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
+     guid->f1, guid->f2, guid->f3,
+     (unsigned char)guid->f4[0], (unsigned char)guid->f4[1], (unsigned char)guid->f4[2], (unsigned char)guid->f4[3], 
+     (unsigned char)guid->f4[4], (unsigned char)guid->f4[5], (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
+    dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
+    return result;
+}
+
 
 int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
 {
-    printf("GetFileVersionInfoSizeA(%s,0x%X)\n", name, lpHandle);
+    dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
     return 0;
 }    
 
 int WINAPI expIsBadStringPtrW(const short* string, int nchars)
 {
-    if(string==0)return 1;
-    return 0;
+    int result;
+    if(string==0)result=1; else result=0;
+    dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
+    if(string)wch_print(string);
+    return result;
 }    
 extern long WINAPI InterlockedExchangeAdd( long* dest, long incr )
 {
@@ -1383,37 +1916,59 @@
 
 extern long WINAPI expInterlockedIncrement( long* dest )
 {
-    return InterlockedExchangeAdd( dest, 1 ) + 1;
+    long result=InterlockedExchangeAdd( dest, 1 ) + 1;
+    dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
+    return result;
 }
 extern long WINAPI expInterlockedDecrement( long* dest )
 {
-    return InterlockedExchangeAdd( dest, -1 ) - 1;
+    long result=InterlockedExchangeAdd( dest, -1 ) - 1;
+    dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
+    return result;
 }
 
 extern void WINAPI expOutputDebugStringA( const char* string )
 {
+    dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
     fprintf(stderr, "DEBUG: %s\n", string);
 }    
 
 int WINAPI expGetDC(int hwnd)
 {
+    dbgprintf("GetDC(0x%x) => 0\n", hwnd);
     return 0;
 }
 
 int WINAPI expGetDesktopWindow()
 {
+    dbgprintf("GetDesktopWindow() => 0\n");
     return 0;
 }
      
 int WINAPI expReleaseDC(int hwnd, int hdc)
 {
+    dbgprintf("ReleaseDC(0x%x, 0x%x) => 0\n", hwnd, hdc);
+    return 0;
+}    
+static int cursor[100];
+
+int WINAPI expLoadCursorA(int handle,LPCSTR name)
+{
+  dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
+  return (int)&cursor[0];
+}
+int WINAPI expSetCursor(void *cursor)
+{
+    dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
+    return (int)cursor;
+}
+int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
+{
+    dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
+	hdc, iStartIndex, nEntries, lppe);
     return 0;
 }    
 
-int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
-{
-    return 0;
-}    
 /*
 typedef struct _TIME_ZONE_INFORMATION {
     long Bias;
@@ -1428,8 +1983,24 @@
 
 int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
 {
+    const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
+    'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
+    const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
+    'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
+    dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
     memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
-    return 0;
+    lpTimeZoneInformation->Bias=360;//GMT-6
+    memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
+    lpTimeZoneInformation->StandardDate.wMonth=10;
+    lpTimeZoneInformation->StandardDate.wDay=5;
+    lpTimeZoneInformation->StandardDate.wHour=2;
+    lpTimeZoneInformation->StandardBias=0;
+    memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
+    lpTimeZoneInformation->DaylightDate.wMonth=4;
+    lpTimeZoneInformation->DaylightDate.wDay=1;
+    lpTimeZoneInformation->DaylightDate.wHour=2;
+    lpTimeZoneInformation->DaylightBias=-60;
+    return TIME_ZONE_ID_STANDARD;
 }    
 
 void WINAPI expGetLocalTime(SYSTEMTIME* systime)
@@ -1438,6 +2009,7 @@
     struct tm *local_tm;
     struct timeval tv;
     
+    dbgprintf("GetLocalTime(0x%x)\n");
     gettimeofday(&tv, NULL);
     local_time=tv.tv_sec;
     local_tm=localtime(&local_time);
@@ -1450,6 +2022,11 @@
     systime->wMinute = local_tm->tm_min;
     systime->wSecond = local_tm->tm_sec;
     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
+    dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
+    "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
+    "  Milliseconds: %d\n",
+    systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
+    systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
 }
 
 int WINAPI expGetSystemTime(SYSTEMTIME* systime)
@@ -1458,6 +2035,7 @@
     struct tm *local_tm;
     struct timeval tv;
     
+    dbgprintf("GetSystemTime(0x%x)\n", systime);
     gettimeofday(&tv, NULL);
     local_time=tv.tv_sec;
     local_tm=gmtime(&local_time);
@@ -1470,26 +2048,298 @@
     systime->wMinute = local_tm->tm_min;
     systime->wSecond = local_tm->tm_sec;
     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
-    
+    dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
+    "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
+    "  Milliseconds: %d\n",
+    systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
+    systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
 }
 
 int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
 {
-    dbgprintf("GetEnvironmentVariableA\n");
-    printf("%s %x %x\n", name, field, size);
+    char *p;
+//    printf("%s %x %x\n", name, field, size);
     if(field)field[0]=0;
+/*
+    p = getenv(name);
+    if (p) strncpy(field,p,size);
+*/
+    if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
+       strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
+    dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
+    return strlen(field);
+}
+
+void* WINAPI expCoTaskMemAlloc(ULONG cb)
+{
+    return my_mreq(cb, 0);
+}
+void WINAPI expCoTaskMemFree(void* cb)
+{
+    my_release(cb);
+}
+
+void* CoTaskMemAlloc(ULONG cb){return expCoTaskMemAlloc(cb);}
+void CoTaskMemFree(void* cb){expCoTaskMemFree(cb);}
+
+struct COM_OBJECT_INFO
+{
+    GUID clsid;
+    long (*GetClassObject) (GUID* clsid, GUID* iid, void** ppv);
+};
+
+static struct COM_OBJECT_INFO* com_object_table=0;
+static int com_object_size=0;
+int RegisterComClass(GUID* clsid, GETCLASSOBJECT gcs)
+{
+    if(!clsid)return -1;
+    if(!gcs)return -1;
+    com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
+    com_object_table[com_object_size-1].clsid=*clsid;        
+    com_object_table[com_object_size-1].GetClassObject=gcs;
+    return 0;        
+}
+
+GUID IID_IUnknown={0x00000000, 0x0000, 0x0000,
+    {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
+GUID IID_IClassFactory={0x00000001, 0x0000, 0x0000,
+    {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};	
+
+long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
+                    long dwClsContext, GUID* riid, void** ppv)
+{
+    int i;
+    struct COM_OBJECT_INFO* ci=0;
+    for(i=0; i<com_object_size; i++)
+	if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
+	    ci=&com_object_table[i];
+    if(!ci)return 0x80040154;
+    // in 'real' world we should mess with IClassFactory here
+    i=ci->GetClassObject(rclsid, riid, ppv);
+    return i;
+}		    
+		    
+long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
+                    long dwClsContext, GUID* riid, void** ppv)
+{
+    return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
+}
+
+int WINAPI
+ expIsRectEmpty(
+CONST RECT *lprc)
+{
+    dbgprintf("IsRectEmpty(0x%x)");
+    if((!lprc) || (lprc->right==lprc->left) || (lprc->top==lprc->bottom))
+    {
+	dbgprintf(" => TRUE\n");
+	return TRUE;
+    }
+    dbgprintf(" => FALSE\n");
+    return FALSE;
+}
+
+int _adjust_fdiv=0; //what's this?
+
+
+
+
+unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
+{
+    dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
+    if(len<5)
+    {
+	dbgprintf(" => 0\n");
+	return 0;
+    }
+    strcpy(path, "/tmp");
+    dbgprintf(" => 5 ( '/tmp' )\n");
+    return 5;
+}
+/*
+FYI:
+typedef struct
+{
+    DWORD     dwFileAttributes;
+    FILETIME  ftCreationTime;
+    FILETIME  ftLastAccessTime;
+    FILETIME  ftLastWriteTime;
+    DWORD     nFileSizeHigh;
+    DWORD     nFileSizeLow;
+    DWORD     dwReserved0;
+    DWORD     dwReserved1;
+    CHAR      cFileName[260];
+    CHAR      cAlternateFileName[14];
+} WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
+*/
+
+HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
+{
+    dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
+    strcpy(lpfd->cFileName, "msms001.vwp");
+    strcpy(lpfd->cAlternateFileName, "msms001.vwp");
+    return (HANDLE)0;
+}
+WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA p)
+{
+    dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, p);
     return 0;
 }
+WIN_BOOL WINAPI expFindClose(HANDLE h)
+{
+    dbgprintf("FindClose(0x%x) => 0\n", h);
+    return 0;
+}
+UINT WINAPI expSetErrorMode(UINT i)
+{
+    dbgprintf("SetErrorMode(%d) => 0\n", i);
+    return 0;
+}
+UINT      WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
+{
+    char windir[]="c:\\windows";
+    int result;
+    strncpy(s, windir, c);
+    result=1+((c<strlen(windir))?c:strlen(windir));
+    dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
+    return result;
+}
+
+WIN_BOOL  WINAPI expDeleteFileA(LPCSTR s)
+{
+    dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
+    return 0;
+}
+WIN_BOOL  WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
+{
+    dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
+    return 0;
+}
+
+UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
+{
+    char mask[16]="/tmp/AP_XXXXXX";
+    int result;
+    dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
+    if(i && i<10)
+    {	
+	dbgprintf(" => -1\n");
+	return -1;
+    }
+    result=mkstemp(mask);
+    sprintf(ps, "AP%d", result);
+    dbgprintf(" => %d\n", strlen(ps));
+    return strlen(ps);
+}
+//
+// This func might need proper implementation if we want AngelPotion codec.
+// They try to open APmpeg4v1.apl with it.
+// DLL will close opened file with CloseHandle().
+//
+HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
+    LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
+{
+    dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
+	     i2, p1, i3, i4, i5);
+    if((!cs1) || (strlen(cs1)<2))return -1;
+    if(strncmp(cs1, "AP", 2))
+    {
+	int result;
+	char* tmp=(char*)malloc(strlen(def_path)+50);
+	strcpy(tmp, def_path);
+	strcat(tmp, "/");
+	strcat(tmp, "APmpg4v1.apl");
+	result=open(tmp, O_RDONLY);
+	free(tmp);
+	return result;
+    };
+    return atoi(cs1+2); 
+}
+static char sysdir[]=".";
+LPCSTR WINAPI expGetSystemDirectoryA() 
+{
+    dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
+    return sysdir;
+}
+WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
+{
+    int result;
+    dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
+    result=read(h, pv, size);
+    if(rd)*rd=result;
+    if(!result)return 0;
+    return 1;
+}
+
+WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
+{
+    int result;
+    dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
+    if(h==1234)h=1;
+    result=write(h, pv, size);
+    if(wr)*wr=result;
+    if(!result)return 0;
+    return 1;
+}
+DWORD  WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
+{
+    int wh;
+    dbgprintf("SetFilePointer(%d, %d, 0x%x, %d)\n", h, val, ext, whence);
+//why would DLL want temporary file with >2Gb size?
+    switch(whence)
+    {
+    case FILE_BEGIN:
+	wh=SEEK_SET;break;
+    case FILE_END:
+	wh=SEEK_END;break;
+    case FILE_CURRENT:
+	wh=SEEK_CUR;break;
+    default:
+	return -1;
+    }
+    return lseek(h, val, wh);
+}
+
+HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
+                             LPARAM lParam2)
+{
+    dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName,  szDriverName, szSectionName, szSectionName, lParam2);
+    return -1;    
+}
+HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
+                             LPARAM lParam2)
+{
+    dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
+    return -1;    
+}
 
 
-//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;
+WIN_BOOL
+ WINAPI
+ expGetProcessAffinityMask(
+    HANDLE hProcess,
+    LPDWORD lpProcessAffinityMask,
+    LPDWORD lpSystemAffinityMask
+    )
+{
+    dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
+	hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
+    if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
+    if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
+    return 1;
 }
 
 
+
+
+
+
+
+
+
+
+
+
 struct exports
 {
     char name[64];
@@ -1535,9 +2385,11 @@
 FF(TlsGetValue, -1)
 FF(TlsSetValue, -1)
 FF(GetCurrentThreadId, -1)
+FF(GetCurrentProcess, -1)
 FF(LocalAlloc, -1) 
 FF(LocalLock, -1)
 FF(GlobalAlloc, -1)
+FF(GlobalReAlloc, -1)
 FF(GlobalLock, -1)
 FF(MultiByteToWideChar, 427)
 FF(WideCharToMultiByte, -1)
@@ -1561,6 +2413,7 @@
 FF(GetCommandLineA, -1)
 FF(GetEnvironmentStringsW, -1)
 FF(FreeEnvironmentStringsW, -1)
+FF(FreeEnvironmentStringsA, -1)
 FF(GetEnvironmentStrings, -1)  
 FF(GetStartupInfoA, -1)
 FF(GetStdHandle, -1)
@@ -1578,6 +2431,7 @@
 FF(UnmapViewOfFile, -1)
 FF(Sleep, -1)
 FF(GetModuleHandleA, -1)
+FF(GetProfileIntA, -1)
 FF(GetPrivateProfileIntA, -1)
 FF(GetPrivateProfileStringA, -1)
 FF(WritePrivateProfileStringA, -1)
@@ -1593,6 +2447,22 @@
 FF(RtlZeroMemory,-1)
 FF(RtlMoveMemory,-1)
 FF(RtlFillMemory,-1)
+FF(GetTempPathA,-1)
+FF(FindFirstFileA,-1)
+FF(FindNextFileA,-1)
+FF(FindClose,-1)
+FF(FileTimeToLocalFileTime,-1)
+FF(DeleteFileA,-1)
+FF(ReadFile,-1)
+FF(WriteFile,-1)
+FF(SetFilePointer,-1)
+FF(GetTempFileNameA,-1)
+FF(CreateFileA,-1)
+FF(GetSystemDirectoryA,-1)
+FF(GetWindowsDirectoryA,-1)
+FF(SetErrorMode, -1)
+FF(IsProcessorFeaturePresent, -1)
+FF(GetProcessAffinityMask, -1)
 };
 
 struct exports exp_msvcrt[]={
@@ -1601,13 +2471,22 @@
 FF(free, -1)
 {"??3@YAXPAX@Z", -1, expdelete},
 {"??2@YAPAXI@Z", -1, expnew},
+{"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
 FF(strrchr, -1)
 FF(strchr, -1)
+FF(strlen, -1)
+FF(strcpy, -1)
+FF(strcmp, -1)
+FF(strcat, -1)
+FF(memmove, -1)
+FF(memcmp, -1)
+FF(time, -1)
 };
 struct exports exp_winmm[]={
 FF(GetDriverModuleHandle, -1)
 FF(timeGetTime, -1)
 FF(DefDriverProc, -1)
+FF(OpenDriverA, -1)
 FF(OpenDriver, -1)
 };
 struct exports exp_user32[]={
@@ -1616,6 +2495,9 @@
 FF(GetDC, -1)
 FF(GetDesktopWindow, -1)
 FF(ReleaseDC, -1)
+FF(IsRectEmpty, -1)
+FF(LoadCursorA,-1)
+FF(SetCursor,-1)
 };
 struct exports exp_advapi32[]={
 FF(RegOpenKeyA, -1)
@@ -1634,6 +2516,12 @@
 struct exports exp_version[]={
 FF(GetFileVersionInfoSizeA, -1)
 };
+struct exports exp_ole32[]={
+FF(CoTaskMemAlloc, -1)
+FF(CoTaskMemFree, -1)
+FF(CoCreateInstance, -1)
+FF(StringFromGUID2, -1)
+};
 #define LL(X) \
 {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
 
@@ -1645,6 +2533,7 @@
 LL(advapi32)
 LL(gdi32)
 LL(version)
+LL(ole32)
 };
 
 void* LookupExternal(const char* library, int ordinal)
@@ -1708,12 +2597,9 @@
 //	    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;
     }
+//    printf("%s %s\n", library, name);
+    if(pos>150)return 0;
     strcpy(export_names[pos], name);
     answ=(char*)extcode+pos*0x64;
     memcpy(answ, &unk_exp1, 0x64);
@@ -1728,3 +2614,51 @@
 //    return (void*)ext_unknown;
 }
 
+int my_garbagecollection()
+{
+#ifdef GARBAGE
+    alc_list* pp,*ppsv;
+    mutex_list* pm,*pmsv;
+    int unfree,unfreecnt;
+    if (mlist != NULL) {
+      pm=mlist;
+      for(;pm;) {
+        if (pm->prev) pm->prev->next=pm->next;
+        if (pm->next) pm->next->prev=pm->prev;
+        if (pm == mlist) mlist=pm->prev;
+        if (pm->pm) {
+		pthread_mutex_destroy(pm->pm);
+		my_release(pm->pm);
+	}
+	if (pm->pc) {
+		pthread_cond_destroy(pm->pc);
+		my_release(pm->pc);
+	}
+	pmsv = pm;
+	pm=pm->prev;
+        my_release(pmsv);
+      }
+    }
+ 
+    if (alclist==NULL) return 0;
+
+    pp=alclist;
+    unfree=unfreecnt=0;
+	for(;pp;) {
+		unfree+=pp->size;
+		unfreecnt++;
+		if (pp->prev)
+			pp->prev->next=pp->next;
+		if (pp->next)
+			pp->next->prev=pp->prev;
+		if (pp == alclist)
+			alclist=pp->prev;
+		free(pp->addr);
+		ppsv = pp;
+		pp=pp->prev;
+		free(ppsv);
+		alccnt--;
+	} 
+   printf("Total Unfree %d bytes cnt %d [%x,%d]\n",unfree,unfreecnt,alclist,alccnt);
+#endif
+}