changeset 3128:392316004607

avifile sync... maybe broken, tell me if so.
author arpi
date Mon, 26 Nov 2001 00:47:58 +0000
parents 59ac428ae68d
children 6d965759dd01
files loader/com.h loader/registry.c loader/win32.c loader/win32.h
diffstat 4 files changed, 241 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- a/loader/com.h	Mon Nov 26 00:46:44 2001 +0000
+++ b/loader/com.h	Mon Nov 26 00:47:58 2001 +0000
@@ -46,10 +46,11 @@
     long STDCALL (*AddRef)(struct IUnknown* _this) ;
     long STDCALL (*Release)(struct IUnknown* _this) ;
 } ;
-struct IUnknown
+
+typedef struct IUnknown
 {
     struct IUnknown_vt* vt;
-};
+} IUnknown;
 
 struct IClassFactory_vt
 {
--- a/loader/registry.c	Mon Nov 26 00:46:44 2001 +0000
+++ b/loader/registry.c	Mon Nov 26 00:47:58 2001 +0000
@@ -12,11 +12,12 @@
 #include <wine/winnt.h>
 #include <wine/winerror.h>
 
+#include <ext.h>
 #include <registry.h>
-#include <ext.h>
 
 //#undef TRACE
 //#define TRACE printf
+
 struct reg_value
 {
 	int type;
@@ -25,9 +26,11 @@
 	char* value;
 };
 
-static int reg_size=0;
+// ...can be set before init_registry() call
+char* regpathname = 0;
 
-static struct reg_value* regs=0;
+static int reg_size=0;
+static struct reg_value* regs = 0;
 
 struct reg_handle_s;
 typedef struct reg_handle_s
@@ -37,16 +40,15 @@
 	struct reg_handle_s* next;
 	struct reg_handle_s* prev;
 } reg_handle_t;
-		
+
 static reg_handle_t* head=0;
 
 #define DIR -25
 
-extern char *get_path(char *);
-
 static void create_registry(void);
 static void open_registry(void);
 static void save_registry(void);
+static void init_registry(void);
 
 
 
@@ -57,7 +59,7 @@
 	printf("Logic error: create_registry() called with existing registry\n");
 	save_registry();
 	return;
-    }	
+    }
     regs=(struct reg_value*)malloc(3*sizeof(struct reg_value));
     regs[0].type=regs[1].type=DIR;
     regs[0].name=(char*)malloc(5);
@@ -73,27 +75,19 @@
 {
 	int fd;
 	int i;
-	int len;
-//         struct passwd* pwent;
-         char* pathname;
+	unsigned int len;
 	if(regs)
 	{
 		printf("Multiple open_registry(>\n");
 		return;
 	}
-//        pwent=getpwuid(getuid());
-//        pathname=(char*)malloc(strlen(pwent->pw_dir)+20);
-//	strcpy(pathname, pwent->pw_dir);
-//        strcat(pathname, "/.mplayer/registry");
-	pathname = get_path("registry");
-	fd=open(pathname, O_RDONLY);
-        free(pathname);
-	if(fd==-1)
+	fd = open(regpathname, O_RDONLY);
+	if (fd == -1)
 	{
 	    printf("Creating new registry\n");
 	    create_registry();
 	    return;
-	}    
+	}
 	read(fd, &reg_size, 4);
 	regs=(struct reg_value*)malloc(reg_size*sizeof(struct reg_value));
 	for(i=0; i<reg_size; i++)
@@ -126,26 +120,21 @@
 
 static void save_registry(void)
 {
-	int fd, i, len;
-//         struct passwd* pwent;
-         char* pathname;
-//        pwent=getpwuid(getuid());
-//        pathname=(char*)malloc(strlen(pwent->pw_dir)+20);
-//	strcpy(pathname, pwent->pw_dir);
-//        strcat(pathname, "/.mplayer/registry");
-	pathname = get_path("registry");
-	fd=open(pathname, O_WRONLY | O_CREAT, 00777);
-        free(pathname);
-	if(fd==-1)
+	int fd, i;
+	if (!regs)
+		init_registry();
+	fd = open(regpathname, O_WRONLY | O_CREAT, 00666);
+	if (fd == -1)
 	{
-		printf("Failed to open registry file for writing.\n");
-		return;
+	    printf("Failed to open registry file '%s' for writing.\n",
+		   regpathname);
+	    return;
 	}
 	write(fd, &reg_size, 4);
 	for(i=0; i<reg_size; i++)
 	{
+	        unsigned len=strlen(regs[i].name);
 		write(fd, &regs[i].type, 4);
-		len=strlen(regs[i].name);
 		write(fd, &len, 4);
 		write(fd, regs[i].name, len);
 		write(fd, &regs[i].len, 4);
@@ -184,7 +173,7 @@
 		}
 	}
 	return 0;
-}	
+}
 static int generate_handle()
 {
 	static int zz=249;
@@ -269,13 +258,28 @@
 
 static void init_registry(void)
 {
-#ifdef DETAILED_OUT
-	printf("Initializing registry\n");
+	struct passwd* pwent;
+	TRACE("Initializing registry\n");
+	pwent = getpwuid(geteuid());
+	// can't be free-ed - it's static and probably thread
+	// unsafe structure which is stored in glibc
+
+#if 1
+	regpathname = get_path("registry");
+#else
+	if (regpathname == 0)
+	{
+	    regpathname = (char*)malloc(strlen(pwent->pw_dir)+20);
+	    strcpy(regpathname, pwent->pw_dir);
+	    strcat(regpathname, "/.registry");
+	}
 #endif
+
 	open_registry();
 	insert_handle(HKEY_LOCAL_MACHINE, "HKLM");
 	insert_handle(HKEY_CURRENT_USER, "HKCU");
 }
+
 static reg_handle_t* find_handle_2(long key, const char* subkey)
 {
 	char* full_name;
@@ -302,29 +306,30 @@
     reg_handle_t* t;
     struct reg_value* v;
     TRACE("Opening key %s\n", subkey);
-    
+
     if(!regs)
         init_registry()
-;	
+;
 /*	t=find_handle_2(key, subkey);
-	
+
 	if(t==0)
 		return -1;
 
 	if(t==(reg_handle_t*)-1)
 		return -1;
-
-*/    full_name=build_keyname(key, subkey);
+*/
+    full_name=build_keyname(key, subkey);
     if(!full_name)
         return -1;
-    v=find_value_by_name(full_name);    
+    TRACE("Opening key Fullname %s\n", full_name);
+    v=find_value_by_name(full_name);
 
     t=insert_handle(generate_handle(), full_name);
     *newkey=t->handle;
     free(full_name);
-    
+
     return 0;
-}    
+}
 long RegCloseKey(long key)
 {
         reg_handle_t *handle;
@@ -345,7 +350,9 @@
 	head=head->prev;
     free(handle);
     return 1;
-}         
+}
+
+extern void trapbug(void);
 long RegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
 {
 	struct reg_value* t;
@@ -353,8 +360,16 @@
 	TRACE("Querying value %s\n", value);
 	if(!regs)
 	    init_registry()
-;	
-    	c=build_keyname(key, value);
+;
+	c=build_keyname(key, value);
+	if (strcmp(value, "AudioReserved001")==0)
+	{
+	    printf("Query for AudioReserved001  %p  %p  count: %d\n", type, data, *count);
+	    *(int*)type = REG_DWORD;
+	    *(int*)data = 256;
+	    //trapbug();
+	    return 0;
+	}
 	if(c==NULL)
 		return 1;
 	if((t=find_value_by_name(c))==0)
@@ -369,7 +384,7 @@
 	{
 		memcpy(data, t->value, (t->len<*count)?t->len:*count);
 		TRACE("returning %d bytes: %d\n", t->len, *(int*)data);
-	}	
+	}
 		if(*count<t->len)
 		{
 			*count=t->len;
@@ -380,10 +395,10 @@
         *count=t->len;
 	}
     return 0;
-}  
+}
 long RegCreateKeyExA(long key, const char* name, long reserved,
-							   void* classs, long options, long security,
-							   void* sec_attr, int* newkey, int* status) 
+		     void* classs, long options, long security,
+		     void* sec_attr, int* newkey, int* status)
 {
 	reg_handle_t* t;
 	char* fullname;
@@ -392,7 +407,7 @@
         TRACE("Creating/Opening key %s\n", name);
 	if(!regs)
 	    init_registry()
-;	
+;
 	fullname=build_keyname(key, name);
 	if(fullname==NULL)
 		return 1;
@@ -404,13 +419,6 @@
 		if (status) *status=REG_CREATED_NEW_KEY;
 //		return 0;
 	}
-	else
-	{
-            // this is a hack as I don't know how RegEnumValueA works
-	    if (strstr(fullname, "zlib") || strstr(fullname, "mszh"))
-                return 1;
-	    if (status) *status=REG_OPENED_EXISTING_KEY;
-	}
 
 	t=insert_handle(generate_handle(), fullname);
 	*newkey=t->handle;
@@ -418,28 +426,41 @@
 	return 0;
 }
 
+/*
+LONG RegEnumValue(
+  HKEY hKey,              // handle to key to query
+  DWORD dwIndex,          // index of value to query
+  LPTSTR lpValueName,     // address of buffer for value string
+  LPDWORD lpcbValueName,  // address for size of value buffer
+  LPDWORD lpReserved,     // reserved
+  LPDWORD lpType,         // address of buffer for type code
+  LPBYTE lpData,          // address of buffer for value data
+  LPDWORD lpcbData        // address for size of data buffer
+);
+*/
+
 long RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
 		   LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
 {
-    // have no idea how this should work
-    //printf("Reg Enum 0x%x %d  %p %d   data: %p %d  %d >%s<\n", hkey, index, value, *val_count, data, *count, reg_size, data);
+    // currenly just made to support MSZH & ZLIB
+    //printf("Reg Enum 0x%x %d  %s %d   data: %p %d  %d >%s<\n", hkey, index,
+    //       value, *val_count, data, *count, reg_size, data);
+    reg_handle_t* t = find_handle(hkey);
+    if (t && index < 10)
     {
-	reg_handle_t* t = find_handle(hkey);
-	if (t)
+	struct reg_value* v=find_value_by_name(t->name);
+	if (v)
 	{
-	    struct reg_value* v=find_value_by_name(t->name);
-            *count = v->len;
-	    memcpy(data, v->value, *count);
-            *val_count = v->len;
-	    memcpy(value, v->value, *val_count);
-            if (type)
+	    memcpy(data, v->value, (v->len < *count) ? v->len : *count);
+	    if(*count < v->len)
+		*count = v->len;
+	    if (type)
 		*type = v->type;
 	    //printf("Found handle  %s\n", v->name);
-            return 0;
+	    return 0;
 	}
     }
-
-    return -1;
+    return ERROR_NO_MORE_ITEMS;
 }
 
 long RegSetValueExA(long key, const char* name, long v1, long v2, const void* data, long size)
@@ -449,11 +470,11 @@
     TRACE("Request to set value %s\n", name);
     if(!regs)
         init_registry()
-;	
+;
     c=build_keyname(key, name);
     if(c==NULL)
 	return 1;
     insert_reg_value(key, name, v2, data, size);
     free(c);
     return 0;
-}        
+}
--- a/loader/win32.c	Mon Nov 26 00:46:44 2001 +0000
+++ b/loader/win32.c	Mon Nov 26 00:47:58 2001 +0000
@@ -160,6 +160,7 @@
 }
 
 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
+//#define DETAILED_OUT
 static inline void dbgprintf(char* fmt, ...)
 {
 #ifdef DETAILED_OUT
@@ -180,6 +181,8 @@
     }
 #endif
 }
+
+
 char export_names[500][30]={
 "name1",
 //"name2",
@@ -322,7 +325,7 @@
     header->size = size;
     header->type = type;
 
-    //if (alccnt < 400) printf("MY_REQ: %p\t%d     (%d)\n",  answer, size, alccnt);
+    //if (alccnt < 40000) printf("MY_REQ: %p\t%d   t:%d  (cnt:%d)\n",  header, size, type, alccnt);
     return header + 1;
 }
 
@@ -341,14 +344,14 @@
     if (memory == 0)
 	return 0;
 
-    pthread_mutex_lock(&memmut);
-
     if (header->deadbeef != 0xdeadbeef)
     {
-	printf("FATAL releasing corrupted memory!\n");
+	printf("FATAL releasing corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
 	return 0;
     }
 
+    pthread_mutex_lock(&memmut);
+
     switch(header->type)
     {
     case AREATYPE_EVENT:
@@ -361,7 +364,7 @@
 	pthread_mutex_destroy((pthread_mutex_t*)memory);
 	break;
     }
-    	
+
     prevmem = header->prev;
     nextmem = header->next;
 
@@ -380,7 +383,7 @@
     else
 	pthread_mutex_destroy(&memmut);
 
-    //if (alccnt < 400) printf("MY_RELEASE: %p\t%ld    (%d)\n", mem, mem[3], alccnt);
+    //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld    (%d)\n", header, header->size, alccnt);
 #else
     if (memory == 0)
 	return 0;
@@ -608,7 +611,7 @@
 		printf("%x => ", pp);
 		pp=pp->prev;
 	    }
-	    printf("0\n");    
+	    printf("0\n");
 */
 	    return;
 	}
@@ -719,14 +722,14 @@
     {
 /**
 From GetCurrentThread() documentation:
-A pseudo handle is a special constant that is interpreted as the current thread handle. The calling thread can use this handle to specify itself whenever a thread handle is required. Pseudo handles are not inherited by child processes. 
+A pseudo handle is a special constant that is interpreted as the current thread handle. The calling thread can use this handle to specify itself whenever a thread handle is required. Pseudo handles are not inherited by child processes.
 
-This handle has the maximum possible access to the thread object. For systems that support security descriptors, this is the maximum access allowed by the security descriptor for the calling process. For systems that do not support security descriptors, this is THREAD_ALL_ACCESS. 
+This handle has the maximum possible access to the thread object. For systems that support security descriptors, this is the maximum access allowed by the security descriptor for the calling process. For systems that do not support security descriptors, this is THREAD_ALL_ACCESS.
 
-The function cannot be used by one thread to create a handle that can be used by other threads to refer to the first thread. The handle is always interpreted as referring to the thread that is using it. A thread can create a "real" handle to itself that can be used by other threads, or inherited by other processes, by specifying the pseudo handle as the source handle in a call to the DuplicateHandle function. 
+The function cannot be used by one thread to create a handle that can be used by other threads to refer to the first thread. The handle is always interpreted as referring to the thread that is using it. A thread can create a "real" handle to itself that can be used by other threads, or inherited by other processes, by specifying the pseudo handle as the source handle in a call to the DuplicateHandle function.
 **/
 	dbgprintf("WaitForSingleObject(thread_handle) called\n");
-	return WAIT_FAILED;
+	return (void*)WAIT_FAILED;
     }
     dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
 
@@ -843,14 +846,13 @@
 	cachedsi.dwAllocationGranularity	= 0x10000;
 	cachedsi.wProcessorLevel		= 5; /* pentium */
 	cachedsi.wProcessorRevision		= 0x0101;
-        cachedsi.dwNumberOfProcessors		= 1;
 
 #if 1
 	/* mplayer's way to detect PF's */
 	{
 	    #include "../cpudetect.h"
 	    extern CpuCaps gCpuCaps;
-	    
+
 	    if (gCpuCaps.hasMMX)
 		PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
 	    if (gCpuCaps.hasSSE)
@@ -859,7 +861,7 @@
 		PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
 	}
 #endif
-	
+
 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__svr4__)
 	do_cpuid(1, regs);
 	switch ((regs[0] >> 8) & 0xf) {			// cpu family
@@ -1041,6 +1043,12 @@
     dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
     return result;
 }
+
+// this is another dirty hack
+// VP31 is releasing one allocated Heap twice
+// we will silently ignore this second call...
+static void* heapfreehack = 0;
+static int heapfreehackshown = 0;
 void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
 {
     void* z;
@@ -1054,6 +1062,7 @@
     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);
+    heapfreehack = 0; // reset
     return z;
 }
 long WINAPI expHeapDestroy(void* heap)
@@ -1066,7 +1075,14 @@
 long WINAPI expHeapFree(int arg1, int arg2, void* ptr)
 {
     dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", arg1, arg2, ptr);
-    my_release(ptr);
+    if (heapfreehack != ptr)
+	my_release(ptr);
+    else
+    {
+        if (!heapfreehackshown++)
+	    printf("Info: HeapFree deallocating same memory twice! (%p)\n", ptr);
+    }
+    heapfreehack = ptr;
     return 1;
 }
 long WINAPI expHeapSize(int heap, int flags, void* pointer)
@@ -1102,10 +1118,10 @@
     int result=VirtualFree(v1,v2,v3);
     dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
     return result;
-}    
+}
 
 /* -- critical sections -- */
-struct CRITSECT 
+struct CRITSECT
 {
     pthread_t id;
     pthread_mutex_t mutex;
@@ -1120,13 +1136,17 @@
     struct CRITSECT *cs_unix;
 };
 
+#undef CRITSECS_NEWTYPE
+//#define CRITSECS_NEWTYPE 1
+
+#ifdef CRITSECS_NEWTYPE
 #define CRITSECS_LIST_MAX 20
 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
 
 int critsecs_get_pos(CRITICAL_SECTION *cs_win)
 {
     int i;
-    
+
     for (i=0; i < CRITSECS_LIST_MAX; i++)
 	if (critsecs_list[i].cs_win == cs_win)
 	    return(i);
@@ -1136,7 +1156,7 @@
 int critsecs_get_unused(void)
 {
     int i;
-    
+
     for (i=0; i < CRITSECS_LIST_MAX; i++)
 	if (critsecs_list[i].cs_win == NULL)
 	    return(i);
@@ -1149,16 +1169,14 @@
 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
 {
     int i;
-    
+
     for (i=0; i < CRITSECS_LIST_MAX; i++)
 	if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
 	    return(critsecs_list[i].cs_unix);
     return(NULL);
 }
 #endif
-
-#undef CRITSECS_NEWTYPE
-//#define CRITSECS_NEWTYPE 1
+#endif
 
 void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
 {
@@ -1266,13 +1284,13 @@
 #ifdef CRITSECS_NEWTYPE
 {
     int i = critsecs_get_pos(c);
-     
+
     if (i < 0)
     {
         printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
         return;
     }
-     
+
     critsecs_list[i].cs_win = NULL;
     expfree(critsecs_list[i].cs_unix);
     critsecs_list[i].cs_unix = NULL;
@@ -1294,7 +1312,10 @@
 
 extern void* fs_seg;
 
-#if 1
+#if 0
+// this version is required for Quicktime codecs (.qtx/.qts) to work.
+// (they assume some pointers at FS: segment)
+
 //static int tls_count;
 static int tls_use_map[64];
 int WINAPI expTlsAlloc()
@@ -1459,6 +1480,38 @@
     dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
     return z;
 }
+// pvmjpg20 - but doesn't work anyway
+int WINAPI expGlobalSize(void* amem)
+{
+    int size = 100000;
+#ifdef GARBAGE
+    alloc_header* header = last_alloc;
+    alloc_header* mem = (alloc_header*) amem - 1;
+    if (amem == 0)
+        return 0;
+    pthread_mutex_lock(&memmut);
+    while (header)
+    {
+	    if (header->deadbeef != 0xdeadbeef)
+	    {
+		printf("FATAL found corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
+		break;
+	    }
+
+	    if (header == mem)
+	    {
+                size = header->size;
+		break;
+	    }
+
+	    header = header->prev;
+    }
+    pthread_mutex_unlock(&memmut);
+#endif
+
+    dbgprintf("GlobalSize(0x%x)\n", amem);
+    return size;
+}
 int WINAPI expLoadStringA(long instance, long  id, void* buf, long size)
 {
     int result=LoadStringA(instance, id, buf, size);
@@ -2038,11 +2091,6 @@
     // we skip to the last backslash
     // this is effectively eliminating weird characters in
     // the text output windows
-    
-    if (strcmp(name, "KERNEL32") == 0){
-	printf("expLoadLibraryA('%s')\n",name);
-	return (int) LookupExternal(name, 0);
-    }
 
     lastbc = strrchr(name, '\\');
     if (lastbc)
@@ -2061,8 +2109,8 @@
 
     dbgprintf("Entering LoadLibraryA(%s)\n", name);
     // PIMJ is loading  kernel32.dll
-    if (strcasecmp(name, "kernel32.dll") == 1)
-	return (int) LookupExternal(name, 0);
+    if (strcasecmp(name, "kernel32.dll") == 0)
+	return MODULE_HANDLE_kernel32;
 
     result=LoadLibraryA(name);
     dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
@@ -2153,6 +2201,18 @@
         return 0;
 }
 
+// btvvc32.drv wants this one
+void* WINAPI expGetWindowDC(int hdc)
+{
+        dbgprintf("GetWindowDC(%d) => 0x81\n", hdc);
+        return (void*)0x81;
+}
+
+void* WINAPI expCreateFontA(void)
+{
+    return 0;
+}
+
 int expwsprintfA(char* string, char* format, ...)
 {
     va_list va;
@@ -2465,6 +2525,11 @@
     return (int)(f+.5);
 }
 
+int exp_stricmp(const char* s1, const char* s2)
+{
+    return strcasecmp(s1, s2);
+}
+
 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",
@@ -2492,6 +2557,10 @@
     if(string)wch_print(string);
     return result;
 }
+int WINAPI expIsBadStringPtrA(const char* string, int nchars)
+{
+    return expIsBadStringPtrW((const short*)string, nchars);
+}
 extern long WINAPI InterlockedExchangeAdd( long* dest, long incr )
 {
     long ret;
@@ -2914,7 +2983,8 @@
     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))
+
+    if(strncmp(cs1, "AP", 2) == 0)
     {
 	int result;
 	char* tmp=(char*)malloc(strlen(def_path)+50);
@@ -2924,7 +2994,33 @@
 	result=open(tmp, O_RDONLY);
 	free(tmp);
 	return result;
-    };
+    }
+    if (strstr(cs1, "vp3"))
+    {
+	int r;
+	int flg = 0;
+	char* tmp=(char*)malloc(20 + strlen(cs1));
+	strcpy(tmp, "/tmp/");
+	strcat(tmp, cs1);
+	r = 4;
+	while (tmp[r])
+	{
+	    if (tmp[r] == ':' || tmp[r] == '\\')
+		tmp[r] = '_';
+	    r++;
+	}
+	if (GENERIC_READ & i1)
+	    flg |= O_RDONLY;
+	else if (GENERIC_WRITE & i1)
+	{
+	    flg |= O_WRONLY;
+	    printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", tmp, r, flg);
+	}
+	r=open(tmp, flg);
+	free(tmp);
+	return r;
+    }
+
     return atoi(cs1+2);
 }
 static char sysdir[]=".";
@@ -3091,6 +3187,7 @@
     return 1;
 }
 
+// required by PIM1 codec (used by win98 PCTV Studio capture sw)
 HRESULT WINAPI expCoInitialize(
 	LPVOID lpReserved	/* [in] pointer to win32 malloc interface
                                    (obsolete, should be NULL) */
@@ -3124,6 +3221,7 @@
 FF(IsBadWritePtr, 357)
 FF(IsBadReadPtr, 354)
 FF(IsBadStringPtrW, -1)
+FF(IsBadStringPtrA, -1)
 FF(DisableThreadLibraryCalls, -1)
 FF(CreateThread, -1)
 FF(CreateEventA, -1)
@@ -3157,6 +3255,7 @@
 FF(GlobalAlloc, -1)
 FF(GlobalReAlloc, -1)
 FF(GlobalLock, -1)
+FF(GlobalSize, -1)
 FF(MultiByteToWideChar, 427)
 FF(WideCharToMultiByte, -1)
 FF(GetVersionExA, -1)
@@ -3257,6 +3356,7 @@
 FF(strcmp, -1)
 FF(strncmp, -1)
 FF(strcat, -1)
+FF(_stricmp,-1)
 FF(isalnum, -1)
 FF(memmove, -1)
 FF(memcmp, -1)
@@ -3295,6 +3395,7 @@
 FF(GetSystemMetrics,-1)
 FF(GetSysColor,-1)
 FF(GetSysColorBrush,-1)
+FF(GetWindowDC, -1)
 };
 struct exports exp_advapi32[]={
 FF(RegOpenKeyA, -1)
@@ -3310,6 +3411,7 @@
 FF(GetDeviceCaps, -1)
 FF(DeleteDC, -1)
 FF(GetSystemPaletteEntries, -1)
+FF(CreateFontA, -1)
 };
 struct exports exp_version[]={
 FF(GetFileVersionInfoSizeA, -1)
--- a/loader/win32.h	Mon Nov 26 00:46:44 2001 +0000
+++ b/loader/win32.h	Mon Nov 26 00:47:58 2001 +0000
@@ -59,10 +59,10 @@
 extern void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c);
 extern int WINAPI expGetCurrentThreadId(void);
 extern int WINAPI expGetCurrentProcess(void);
-//extern void* WINAPI expTlsAlloc(void);
-//extern int WINAPI expTlsSetValue(tls_t* index, void* value);
-//extern void* WINAPI expTlsGetValue(tls_t* index);
-//extern int WINAPI expTlsFree(tls_t* index);
+extern void* WINAPI expTlsAlloc(void);
+extern int WINAPI expTlsSetValue(tls_t* index, void* value);
+extern void* WINAPI expTlsGetValue(tls_t* index);
+extern int WINAPI expTlsFree(tls_t* index);
 extern void* WINAPI expLocalAlloc(int flags, int size);
 extern void* WINAPI expLocalReAlloc(int handle,int size,int flags);
 extern void* WINAPI expLocalLock(void* z);
@@ -214,6 +214,7 @@
 extern int expstrlen(char* str);
 extern int expstrcpy(char* str1, const char* str2);
 extern int expstrcmp(const char* str1, const char* str2);
+extern int expstrncmp(const char* str1, const char* str2, int);
 extern int expstrcat(char* str1, const char* str2);
 extern int expisalnum(int c);
 extern int expmemmove(void* dest, void* src, int n);
@@ -232,6 +233,7 @@
 extern int expfprintf(void* stream, const char* format, ...);
 extern int expprintf(const char* format, ...);
 extern void* expwcscpy(WCHAR* dst, const WCHAR* src);
+extern int exp_stricmp(const char*, const char*);
 
 extern void* LookupExternal(const char* library, int ordinal);
 extern void* LookupExternalByName(const char* library, const char* name);