1 /***********************************************************
2 
3 Win32 emulation code. Functions that emulate
4 responses from corresponding Win32 API calls.
5 Since we are not going to be able to load
6 virtually any DLL, we can only implement this
7 much, adding needed functions with each new codec.
8 
9 Basic principle of implementation: it's not good
10 for DLL to know too much about its environment.
11 
12 ************************************************************/
13 
14 /*
15  * Modified for use with MPlayer, detailed changelog at
16  * http://svn.mplayerhq.hu/mplayer/trunk/
17  */
18 
19 #define _BSD_SOURCE
20 
21 #include "config.h"
22 #include "mangle.h"
23 
24 #define REALPLAYER
25 //#define LOADLIB_TRY_NATIVE
26 
27 /* Hack to make sure the correct function declaration in com.h is used when
28  * this file is built for the test applications with WIN32_LOADER disabled. */
29 #ifndef WIN32_LOADER
30 #define WIN32_LOADER
31 #endif
32 
33 #ifdef CONFIG_QTX_CODECS
34 #define PSEUDO_SCREEN_WIDTH	/*640*/800
35 #define PSEUDO_SCREEN_HEIGHT	/*480*/600
36 #endif
37 
38 #include "wine/winbase.h"
39 #include "wine/winreg.h"
40 #include "wine/winnt.h"
41 #include "wine/winerror.h"
42 #include "wine/debugtools.h"
43 #include "wine/module.h"
44 #include "wine/winuser.h"
45 #include "wine/objbase.h"
46 
47 #include <stdio.h>
48 #include "win32.h"
49 
50 #include "registry.h"
51 #include "loader.h"
52 #include "com.h"
53 #include "ext.h"
54 #include "ldt_keeper.h"
55 #include "path.h"
56 
57 #include <stdlib.h>
58 #include <assert.h>
59 #include <stdarg.h>
60 #include <ctype.h>
61 #include <pthread.h>
62 #include <errno.h>
63 #include <time.h>
64 #include <math.h>
65 #include <unistd.h>
66 #include <fcntl.h>
67 #include <sys/types.h>
68 #include <dirent.h>
69 #include <sys/time.h>
70 #include <sys/stat.h>
71 #ifdef	HAVE_KSTAT
72 #include <kstat.h>
73 #endif
74 #if HAVE_MALLOC_H
75 #include <malloc.h>
76 #endif
77 
78 #if HAVE_SYS_MMAN_H
79 #include <sys/mman.h>
80 #else
81 #include "osdep/mmap.h"
82 #endif
83 #include "osdep/mmap_anon.h"
84 #include "libavutil/mem.h"
85 #include "libavutil/avstring.h"
86 #include "cpudetect.h"
87 
c_localcount_tsc(void)88 static unsigned int c_localcount_tsc(void)
89 {
90     int a;
91     __asm__ volatile
92 	(
93 	 "rdtsc\n\t"
94 	 :"=a"(a)
95 	 :
96 	 :"edx"
97 	);
98     return a;
99 }
c_longcount_tsc(long long * z)100 static void c_longcount_tsc(long long* z)
101 {
102     __asm__ volatile
103 	(
104 	 "pushl %%ebx\n\t"
105 	 "movl %%eax, %%ebx\n\t"
106 	 "rdtsc\n\t"
107 	 "movl %%eax, 0(%%ebx)\n\t"
108 	 "movl %%edx, 4(%%ebx)\n\t"
109 	 "popl %%ebx\n\t"
110 	 ::"a"(z)
111 	 :"edx"
112 	);
113 }
c_localcount_notsc(void)114 static unsigned int c_localcount_notsc(void)
115 {
116     struct timeval tv;
117     unsigned limit=~0;
118     limit/=1000000;
119     gettimeofday(&tv, 0);
120     return limit*tv.tv_usec;
121 }
c_longcount_notsc(long long * z)122 static void c_longcount_notsc(long long* z)
123 {
124     struct timeval tv;
125     unsigned long long result;
126     unsigned limit=~0;
127     if(!z)return;
128     limit/=1000000;
129     gettimeofday(&tv, 0);
130     result=tv.tv_sec;
131     result<<=32;
132     result+=limit*tv.tv_usec;
133     *z=result;
134 }
135 static unsigned int localcount_stub(void);
136 static void longcount_stub(long long*);
137 static unsigned int (*localcount)(void)=localcount_stub;
138 static void (*longcount)(long long*)=longcount_stub;
139 
140 static pthread_mutex_t memmut = PTHREAD_MUTEX_INITIALIZER;
141 
localcount_stub(void)142 static unsigned int localcount_stub(void)
143 {
144     unsigned int regs[4];
145     do_cpuid(1, regs);
146     if ((regs[3] & 0x00000010) != 0)
147     {
148 	localcount=c_localcount_tsc;
149 	longcount=c_longcount_tsc;
150     }
151     else
152     {
153 	localcount=c_localcount_notsc;
154 	longcount=c_longcount_notsc;
155     }
156     return localcount();
157 }
longcount_stub(long long * z)158 static void longcount_stub(long long* z)
159 {
160     unsigned int regs[4];
161     do_cpuid(1, regs);
162     if ((regs[3] & 0x00000010) != 0)
163     {
164 	localcount=c_localcount_tsc;
165 	longcount=c_longcount_tsc;
166     }
167     else
168     {
169 	localcount=c_localcount_notsc;
170 	longcount=c_longcount_notsc;
171     }
172     longcount(z);
173 }
174 
175 #include "mp_msg.h"
176 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
177 //#define DETAILED_OUT
dbgprintf(char * fmt,...)178 static inline void dbgprintf(char* fmt, ...)
179 {
180 #ifdef DETAILED_OUT
181     if(LOADER_DEBUG)
182     {
183 	FILE* f;
184 	va_list va;
185 	va_start(va, fmt);
186 	f=fopen("./log", "a");
187 	vprintf(fmt, va);
188 	fflush(stdout);
189 	if(f)
190 	{
191 	    vfprintf(f, fmt, va);
192 	    fsync(fileno(f));
193 	    fclose(f);
194 	}
195 	va_end(va);
196     }
197 #endif
198     if ( mp_msg_test(MSGT_WIN32,MSGL_DBG3) )
199     {
200 	va_list va;
201 
202 	va_start(va, fmt);
203 	vprintf(fmt, va);
204 //	mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
205 	va_end(va);
206 	fflush(stdout);
207     }
208 }
209 
210 
211 char export_names[300][32]={
212     "name1",
213     //"name2",
214     //"name3"
215 };
216 //#define min(x,y) ((x)<(y)?(x):(y))
217 
218 void destroy_event(void* event);
219 
220 struct th_list_t;
221 typedef struct th_list_t{
222     int id;
223     void* thread;
224     struct th_list_t* next;
225     struct th_list_t* prev;
226 } th_list;
227 
228 
229 // have to be cleared by GARBAGE COLLECTOR
230 //static unsigned char* heap=NULL;
231 //static int heap_counter=0;
232 static tls_t* g_tls=NULL;
233 static th_list* list=NULL;
234 static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
235 
236 #if 0
237 static void test_heap(void)
238 {
239     int offset=0;
240     if(heap==0)
241 	return;
242     while(offset<heap_counter)
243     {
244 	if(*(int*)(heap+offset)!=0x433476)
245 	{
246 	    printf("Heap corruption at address %d\n", offset);
247 	    return;
248 	}
249 	offset+=8+*(int*)(heap+offset+4);
250     }
251     for(;offset<min(offset+1000, 20000000); offset++)
252 	if(heap[offset]!=0xCC)
253 	{
254 	    printf("Free heap corruption at address %d\n", offset);
255 	}
256 }
257 #endif
258 #undef MEMORY_DEBUG
259 
260 #ifdef MEMORY_DEBUG
261 
my_mreq(int size,int to_zero)262 static void* my_mreq(int size, int to_zero)
263 {
264     static int test=0;
265     test++;
266     if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
267     //    test_heap();
268     if(heap==NULL)
269     {
270 	heap=malloc(20000000);
271 	memset(heap, 0xCC,20000000);
272     }
273     if(heap==0)
274     {
275 	printf("No enough memory\n");
276 	return 0;
277     }
278     if(heap_counter+size>20000000)
279     {
280 	printf("No enough memory\n");
281 	return 0;
282     }
283     *(int*)(heap+heap_counter)=0x433476;
284     heap_counter+=4;
285     *(int*)(heap+heap_counter)=size;
286     heap_counter+=4;
287     printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
288     if(to_zero)
289 	memset(heap+heap_counter, 0, size);
290     else
291 	memset(heap+heap_counter, 0xcc, size);  // make crash reproducable
292     heap_counter+=size;
293     return heap+heap_counter-size;
294 }
my_release(char * memory)295 static int my_release(char* memory)
296 {
297     //    test_heap();
298     if(memory==NULL)
299     {
300 	printf("ERROR: free(0)\n");
301 	return 0;
302     }
303     if(*(int*)(memory-8)!=0x433476)
304     {
305 	printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
306 	return 0;
307     }
308     printf("Freed %d bytes of memory\n", *(int*)(memory-4));
309     //    memset(memory-8, *(int*)(memory-4), 0xCC);
310     return 0;
311 }
312 
313 #else
314 #define GARBAGE
315 typedef struct alloc_header_t alloc_header;
316 struct alloc_header_t
317 {
318     // let's keep allocated data 16 byte aligned
319     alloc_header* prev;
320     alloc_header* next;
321     long deadbeef;
322     long size;
323     long type;
324     long reserved1;
325     long reserved2;
326     long reserved3;
327 };
328 
329 #ifdef GARBAGE
330 static alloc_header* last_alloc = NULL;
331 static int alccnt = 0;
332 #endif
333 
334 #define AREATYPE_CLIENT 0
335 #define AREATYPE_EVENT 1
336 #define AREATYPE_MUTEX 2
337 #define AREATYPE_COND 3
338 #define AREATYPE_CRITSECT 4
339 
340 /* -- critical sections -- */
341 struct CRITSECT
342 {
343     pthread_t id;
344     pthread_mutex_t mutex;
345     pthread_cond_t unlocked;
346     int lock_count;
347     long deadbeef;
348 };
349 
350 void* mreq_private(int size, int to_zero, int type);
mreq_private(int size,int to_zero,int type)351 void* mreq_private(int size, int to_zero, int type)
352 {
353     int nsize = size + sizeof(alloc_header);
354     alloc_header* header = av_malloc(nsize);
355     if (!header)
356         return 0;
357     if (to_zero)
358 	memset(header, 0, nsize);
359 #ifdef GARBAGE
360     pthread_mutex_lock(&memmut);
361     if (last_alloc)
362     {
363 	last_alloc->next = header;  /* set next */
364     }
365 
366     header->prev = last_alloc;
367     header->next = 0;
368     last_alloc = header;
369     alccnt++;
370     pthread_mutex_unlock(&memmut);
371 #endif
372     header->deadbeef = 0xdeadbeef;
373     header->size = size;
374     header->type = type;
375 
376     //if (alccnt < 40000) printf("MY_REQ: %p\t%d   t:%d  (cnt:%d)\n",  header, size, type, alccnt);
377     return header + 1;
378 }
379 
my_release(void * memory)380 static int my_release(void* memory)
381 {
382     alloc_header* header = (alloc_header*) memory - 1;
383 #ifdef GARBAGE
384     alloc_header* prevmem;
385     alloc_header* nextmem;
386 
387     if (memory == 0)
388 	return 0;
389 
390     if (header->deadbeef != (long) 0xdeadbeef)
391     {
392 	dbgprintf("FATAL releasing corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
393 	return 0;
394     }
395 
396     pthread_mutex_lock(&memmut);
397 
398     switch(header->type)
399     {
400     case AREATYPE_EVENT:
401 	destroy_event(memory);
402 	break;
403     case AREATYPE_COND:
404 	pthread_cond_destroy((pthread_cond_t*)memory);
405 	break;
406     case AREATYPE_MUTEX:
407 	pthread_mutex_destroy((pthread_mutex_t*)memory);
408 	break;
409     case AREATYPE_CRITSECT:
410 	pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
411 	break;
412     default:
413 	//memset(memory, 0xcc, header->size);
414 	;
415     }
416 
417     header->deadbeef = 0;
418     prevmem = header->prev;
419     nextmem = header->next;
420 
421     if (prevmem)
422 	prevmem->next = nextmem;
423     if (nextmem)
424 	nextmem->prev = prevmem;
425 
426     if (header == last_alloc)
427 	last_alloc = prevmem;
428 
429     alccnt--;
430 
431     pthread_mutex_unlock(&memmut);
432 
433     //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld    (%d)\n", header, header->size, alccnt);
434 #else
435     if (memory == 0)
436 	return 0;
437 #endif
438     //memset(header + 1, 0xcc, header->size);
439     av_free(header);
440     return 0;
441 }
442 #endif
443 
my_mreq(int size,int to_zero)444 static inline void* my_mreq(int size, int to_zero)
445 {
446     return mreq_private(size, to_zero, AREATYPE_CLIENT);
447 }
448 
my_size(void * memory)449 static int my_size(void* memory)
450 {
451     if(!memory) return 0;
452     return ((alloc_header*)memory)[-1].size;
453 }
454 
my_realloc(void * memory,int size)455 static void* my_realloc(void* memory, int size)
456 {
457     void *ans = memory;
458     int osize;
459     if (memory == NULL)
460 	return my_mreq(size, 0);
461     osize = my_size(memory);
462     if (osize < size)
463     {
464 	ans = my_mreq(size, 0);
465 	memcpy(ans, memory, osize);
466 	my_release(memory);
467     }
468     return ans;
469 }
470 
471 /*
472  *
473  *  WINE  API  - native implementation for several win32 libraries
474  *
475  */
476 
ext_unknown(void)477 static int WINAPI ext_unknown(void)
478 {
479     printf("Unknown func called\n");
480     return 0;
481 }
482 
expGetVolumeInformationA(const char * root,char * label,unsigned int label_len,unsigned int * serial,unsigned int * filename_len,unsigned int * flags,char * fsname,unsigned int fsname_len)483 static int  WINAPI expGetVolumeInformationA( const char *root, char *label,
484                                        unsigned int label_len, unsigned int *serial,
485                                        unsigned int *filename_len,unsigned int *flags,
486                                        char *fsname, unsigned int fsname_len )
487 {
488 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
489 		      root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
490 //hack Do not return any real data - do nothing
491 return 1;
492 }
493 
expGetDriveTypeA(const char * root)494 static unsigned int WINAPI expGetDriveTypeA( const char *root )
495 {
496  dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
497  // hack return as Fixed Drive Type
498  return DRIVE_FIXED;
499 }
500 
expGetLogicalDriveStringsA(unsigned int len,char * buffer)501 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
502 {
503  dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
504  // hack only have one drive c:\ in this hack
505   *buffer++='c';
506   *buffer++=':';
507   *buffer++='\\';
508   *buffer++='\0';
509   *buffer= '\0';
510 return 4; // 1 drive * 4 bytes (includes null)
511 }
512 
513 
expIsBadWritePtr(void * ptr,unsigned int count)514 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
515 {
516     int result = (count == 0 || ptr != 0) ? 0 : 1;
517     dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
518     return result;
519 }
expIsBadReadPtr(void * ptr,unsigned int count)520 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
521 {
522     int result = (count == 0 || ptr != 0) ? 0 : 1;
523     dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
524     return result;
525 }
expDisableThreadLibraryCalls(int module)526 static int WINAPI expDisableThreadLibraryCalls(int module)
527 {
528     dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
529     return 0;
530 }
531 
expGetDriverModuleHandle(DRVR * pdrv)532 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
533 {
534     HMODULE result;
535     if (pdrv==NULL)
536 	result=0;
537     else
538 	result=pdrv->hDriverModule;
539     dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
540     return result;
541 }
542 
543 #define	MODULE_HANDLE_kernel32	((HMODULE)0x120)
544 #define	MODULE_HANDLE_user32	((HMODULE)0x121)
545 #ifdef CONFIG_QTX_CODECS
546 #define	MODULE_HANDLE_wininet	((HMODULE)0x122)
547 #define	MODULE_HANDLE_ddraw	((HMODULE)0x123)
548 #define	MODULE_HANDLE_advapi32	((HMODULE)0x124)
549 #endif
550 #define	MODULE_HANDLE_comdlg32	((HMODULE)0x125)
551 #define	MODULE_HANDLE_msvcrt	((HMODULE)0x126)
552 #define	MODULE_HANDLE_ole32	((HMODULE)0x127)
553 #define	MODULE_HANDLE_winmm	((HMODULE)0x128)
554 #define	MODULE_HANDLE_psapi	((HMODULE)0x129)
555 
556 // Fake PE header, since some software (and the Microsoft CRT v8 and newer)
557 // assume GetModuleHandle(NULL) returns a pointer to a PE header.
558 // We simulate a very simple header with only one section.
559 //
560 // NOTE: If you have a section called .mixcrt, the Microsoft CRT will assume
561 // it's running in a POSIX binary, and stop using EncodePointer/DecodePointer.
562 static const struct {
563     IMAGE_DOS_HEADER doshdr;
564     IMAGE_NT_HEADERS nthdr;
565     IMAGE_SECTION_HEADER opthdr;
566 } __attribute__((__packed__)) mp_exe = {
567     .doshdr.e_lfanew = sizeof(IMAGE_DOS_HEADER),
568     .nthdr.FileHeader.NumberOfSections = 1,
569     .nthdr.FileHeader.SizeOfOptionalHeader =
570         sizeof(IMAGE_NT_HEADERS) - FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader), /* 0xe0 */
571     .opthdr.Name = ".text"
572 };
573 
expGetModuleHandleA(const char * name)574 static HMODULE WINAPI expGetModuleHandleA(const char* name)
575 {
576     WINE_MODREF* wm;
577     HMODULE result;
578     if(!name)
579 	result=(HMODULE)&mp_exe.doshdr;
580     else
581     {
582 	wm=MODULE_FindModule(name);
583 	if(wm==0)result=0;
584 	else
585 	    result=(HMODULE)(wm->module);
586     }
587     if(!result)
588     {
589 	if(name && (av_strcasecmp(name, "kernel32")==0 || !av_strcasecmp(name, "kernel32.dll")))
590 	    result=MODULE_HANDLE_kernel32;
591 #ifdef CONFIG_QTX_CODECS
592 	if(name && av_strcasecmp(name, "user32")==0)
593 	    result=MODULE_HANDLE_user32;
594 #endif
595     }
596     dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
597     return result;
598 }
599 
expGetModuleHandleW(const uint16_t * name)600 static HMODULE WINAPI expGetModuleHandleW(const uint16_t* name)
601 {
602     char aname[256];
603     int pos = 0;
604     while (*name) {
605         if (*name > 256 || pos >= sizeof(aname) - 1)
606             return NULL;
607         aname[pos++] = *name++;
608     }
609     aname[pos] = 0;
610     return expGetModuleHandleA(aname);
611 }
612 
expCreateThread(void * pSecAttr,long dwStackSize,void * lpStartAddress,void * lpParameter,long dwFlags,long * dwThreadId)613 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
614 				    void* lpStartAddress, void* lpParameter,
615 				    long dwFlags, long* dwThreadId)
616 {
617     pthread_t *pth;
618     //    printf("CreateThread:");
619     pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
620     pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
621     if(dwFlags)
622 	printf( "WARNING: CreateThread flags not supported\n");
623     if(dwThreadId)
624 	*dwThreadId=(long)pth;
625     pthread_mutex_lock(&list_lock);
626     if(list==NULL)
627     {
628 	list=my_mreq(sizeof(th_list), 1);
629 	list->next=list->prev=NULL;
630     }
631     else
632     {
633 	list->next=my_mreq(sizeof(th_list), 0);
634 	list->next->prev=list;
635 	list->next->next=NULL;
636 	list=list->next;
637     }
638     list->thread=pth;
639     pthread_mutex_unlock(&list_lock);
640     dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
641 	      pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
642     return pth;
643 }
644 
expResumeThread(HANDLE hThread)645 static DWORD WINAPI expResumeThread(HANDLE hThread)
646 {
647     int ret = 1;
648     dbgprintf("ResumeThread(0x%x) => 0x%x\n", hThread, ret);
649     return ret;
650 }
651 
652 struct mutex_list_t;
653 
654 struct mutex_list_t
655 {
656     char type;
657     pthread_mutex_t *pm;
658     pthread_cond_t  *pc;
659     char state;
660     char reset;
661     char name[128];
662     int  semaphore;
663     int  lock_count;
664     pthread_t owner;
665     struct mutex_list_t* next;
666     struct mutex_list_t* prev;
667 };
668 typedef struct mutex_list_t mutex_list;
669 static mutex_list* mlist=NULL;
670 static pthread_mutex_t mlist_lock = PTHREAD_MUTEX_INITIALIZER;
671 
destroy_event(void * event)672 void destroy_event(void* event)
673 {
674     mutex_list *pp;
675     pthread_mutex_lock(&mlist_lock);
676     pp=mlist;
677     //    printf("garbage collector: destroy_event(%x)\n", event);
678     while(pp)
679     {
680 	if(pp==(mutex_list*)event)
681 	{
682 	    if(pp->next)
683 		pp->next->prev=pp->prev;
684 	    if(pp->prev)
685 		pp->prev->next=pp->next;
686 	    if(mlist==(mutex_list*)event)
687 		mlist=mlist->prev;
688 	    /*
689 	     pp=mlist;
690 	     while(pp)
691 	     {
692 	     printf("%x => ", pp);
693 	     pp=pp->prev;
694 	     }
695 	     printf("0\n");
696 	     */
697 	    pthread_mutex_unlock(&mlist_lock);
698 	    return;
699 	}
700 	pp=pp->prev;
701     }
702     pthread_mutex_unlock(&mlist_lock);
703 }
704 
expCreateEventA(void * pSecAttr,char bManualReset,char bInitialState,const char * name)705 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
706 				    char bInitialState, const char* name)
707 {
708     pthread_mutex_t *pm;
709     pthread_cond_t  *pc;
710     void *ret;
711     /*
712      mutex_list* pp;
713      pp=mlist;
714      while(pp)
715      {
716      printf("%x => ", pp);
717      pp=pp->prev;
718      }
719      printf("0\n");
720      */
721     pthread_mutex_lock(&mlist_lock);
722     if(mlist!=NULL)
723     {
724 	mutex_list* pp=mlist;
725 	if(name!=NULL)
726 	    do
727 	{
728 	    if((strcmp(pp->name, name)==0) && (pp->type==0))
729 	    {
730 		dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
731 			  pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
732 		pthread_mutex_unlock(&mlist_lock);
733 		return pp->pm;
734 	    }
735 	}while((pp=pp->prev) != NULL);
736     }
737     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
738     pthread_mutex_init(pm, NULL);
739     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
740     pthread_cond_init(pc, NULL);
741     if(mlist==NULL)
742     {
743 	mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
744 	mlist->next=mlist->prev=NULL;
745     }
746     else
747     {
748 	mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
749 	mlist->next->prev=mlist;
750 	mlist->next->next=NULL;
751 	mlist=mlist->next;
752     }
753     mlist->type=0; /* Type Event */
754     mlist->pm=pm;
755     mlist->pc=pc;
756     mlist->state=bInitialState;
757     mlist->reset=!bManualReset;
758     if(name)
759 	strncpy(mlist->name, name, 127);
760     else
761 	mlist->name[0]=0;
762     if(pm==NULL)
763 	dbgprintf("ERROR::: CreateEventA failure\n");
764     /*
765      if(bInitialState)
766      pthread_mutex_lock(pm);
767      */
768     if(name)
769 	dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
770 		  pSecAttr, bManualReset, bInitialState, name, name, mlist);
771     else
772 	dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
773 		  pSecAttr, bManualReset, bInitialState, mlist);
774     ret = mlist;
775     pthread_mutex_unlock(&mlist_lock);
776     return ret;
777 }
778 
expCreateEventW(void * pSecAttr,char bManualReset,char bInitialState,const WCHAR * name)779 static void* WINAPI expCreateEventW(void* pSecAttr, char bManualReset,
780                                     char bInitialState, const WCHAR* name)
781 {
782     char ascii_name[256];
783     char *aname = NULL;
784     if (name) {
785         WideCharToMultiByte(65001, 0x0, name, -1, ascii_name, 256, NULL, NULL);
786         aname = ascii_name;
787     }
788     return expCreateEventA(pSecAttr, bManualReset, bInitialState, aname);
789 }
790 
expSetEvent(void * event)791 static void* WINAPI expSetEvent(void* event)
792 {
793     mutex_list *ml = (mutex_list *)event;
794     dbgprintf("SetEvent(%x) => 0x1\n", event);
795     pthread_mutex_lock(ml->pm);
796     if (ml->state == 0) {
797 	ml->state = 1;
798 	pthread_cond_signal(ml->pc);
799     }
800     pthread_mutex_unlock(ml->pm);
801 
802     return (void *)1;
803 }
expResetEvent(void * event)804 static void* WINAPI expResetEvent(void* event)
805 {
806     mutex_list *ml = (mutex_list *)event;
807     dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
808     pthread_mutex_lock(ml->pm);
809     ml->state = 0;
810     pthread_mutex_unlock(ml->pm);
811 
812     return (void *)1;
813 }
814 
expWaitForSingleObject(void * object,int duration)815 static void* WINAPI expWaitForSingleObject(void* object, int duration)
816 {
817     mutex_list *ml = (mutex_list *)object;
818     // FIXME FIXME FIXME - this value is sometime unititialize !!!
819     int ret = WAIT_FAILED;
820     mutex_list* pp;
821     th_list* tp;
822     if(object == (void*)0xcfcf9898)
823     {
824 	/**
825 	 From GetCurrentThread() documentation:
826 	 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.
827 
828 	 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.
829 
830 	 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.
831 	 **/
832 	dbgprintf("WaitForSingleObject(thread_handle) called\n");
833 	return (void*)WAIT_FAILED;
834     }
835     dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
836 
837     // See if this is a thread.
838     pthread_mutex_lock(&list_lock);
839     tp=list;
840     while (tp && (tp->thread != object))
841         tp = tp->prev;
842     pthread_mutex_unlock(&list_lock);
843     if (tp) {
844         if (pthread_join(*(pthread_t*)object, NULL) == 0) {
845             return (void*)WAIT_OBJECT_0;
846         } else {
847             return (void*)WAIT_FAILED;
848         }
849     }
850 
851     // loop below was slightly fixed - its used just for checking if
852     // this object really exists in our list
853     if (!ml)
854 	return (void*) ret;
855     pthread_mutex_lock(&mlist_lock);
856     pp=mlist;
857     while (pp && (pp->pm != ml->pm))
858 	pp = pp->prev;
859     pthread_mutex_unlock(&mlist_lock);
860     if (!pp) {
861 	dbgprintf("WaitForSingleObject: NotFound\n");
862 	return (void*)ret;
863     }
864 
865     pthread_mutex_lock(ml->pm);
866 
867     switch(ml->type) {
868     case 0: /* Event */
869 	if (duration == 0) { /* Check Only */
870 	    if (ml->state == 1) ret = WAIT_OBJECT_0;
871 	    else                   ret = WAIT_FAILED;
872 	}
873 	if (duration == -1) { /* INFINITE */
874 	    if (ml->state == 0)
875 		pthread_cond_wait(ml->pc,ml->pm);
876 	    if (ml->reset)
877 		ml->state = 0;
878 	    ret = WAIT_OBJECT_0;
879 	}
880 	if (duration > 0) {  /* Timed Wait */
881 	    struct timespec abstime;
882 	    struct timeval now;
883 	    gettimeofday(&now, 0);
884 	    abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
885 	    abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
886 	    if (ml->state == 0)
887 		ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
888 	    if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
889 	    else                  ret = WAIT_OBJECT_0;
890 	    if (ml->reset)
891 		ml->state = 0;
892 	}
893 	break;
894     case 1:  /* Semaphore */
895 	if (duration == 0) {
896 	    if(ml->semaphore==0) ret = WAIT_FAILED;
897 	    else {
898 		ml->semaphore--;
899 		ret = WAIT_OBJECT_0;
900 	    }
901 	}
902 	if (duration == -1) {
903 	    if (ml->semaphore==0)
904 		pthread_cond_wait(ml->pc,ml->pm);
905 	    ml->semaphore--;
906 	    ret = WAIT_OBJECT_0;
907 	}
908 	break;
909     case 2:  /* Mutex */
910 	if (duration == 0) {
911 	   if(ml->lock_count > 0 && ml->owner != pthread_self()) ret = WAIT_FAILED;
912 	   else {
913 		ml->lock_count++;
914 		ml->owner = pthread_self();
915 		ret = WAIT_OBJECT_0;
916 	   }
917 	}
918 	if (duration == -1) {
919 	    if (ml->lock_count > 0 && ml->owner != pthread_self()) {
920 		pthread_cond_wait(ml->pc,ml->pm);
921 	    }
922 	    ml->lock_count++;
923 	    ml->owner = pthread_self();
924 	    ret = WAIT_OBJECT_0;
925 	}
926 	break;
927     }
928     pthread_mutex_unlock(ml->pm);
929 
930     dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
931     return (void *)ret;
932 }
933 
934 #ifdef CONFIG_QTX_CODECS
expWaitForMultipleObjects(int count,const void ** objects,int WaitAll,int duration)935 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
936 		    int WaitAll, int duration)
937 {
938     int i;
939     void *object;
940     void *ret;
941 
942     dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
943 	count, objects, WaitAll, duration);
944 
945     for (i = 0; i < count; i++)
946     {
947 	object = (void *)objects[i];
948 	ret = expWaitForSingleObject(object, duration);
949 	if (WaitAll)
950 	    dbgprintf("WaitAll flag not yet supported...\n");
951 	else
952 	    return ret;
953     }
954     return NULL;
955 }
956 
expExitThread(int retcode)957 static void WINAPI expExitThread(int retcode)
958 {
959     dbgprintf("ExitThread(%d)\n", retcode);
960     pthread_exit(&retcode);
961 }
962 #endif
963 
964 static int pf_set = 0;
965 static BYTE PF[64] = {0,};
966 
DumpSystemInfo(const SYSTEM_INFO * si)967 static void DumpSystemInfo(const SYSTEM_INFO* si)
968 {
969     dbgprintf("  Processor architecture %d\n", si->u.s.wProcessorArchitecture);
970     dbgprintf("  Page size: %d\n", si->dwPageSize);
971     dbgprintf("  Minimum app address: %d\n", si->lpMinimumApplicationAddress);
972     dbgprintf("  Maximum app address: %d\n", si->lpMaximumApplicationAddress);
973     dbgprintf("  Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
974     dbgprintf("  Number of processors: %d\n", si->dwNumberOfProcessors);
975     dbgprintf("  Processor type: 0x%x\n", si->dwProcessorType);
976     dbgprintf("  Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
977     dbgprintf("  Processor level: 0x%x\n", si->wProcessorLevel);
978     dbgprintf("  Processor revision: 0x%x\n", si->wProcessorRevision);
979 }
980 
expGetSystemInfo(SYSTEM_INFO * si)981 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
982 {
983     /* FIXME: better values for the two entries below... */
984     static int cache = 0;
985     static SYSTEM_INFO cachedsi;
986     dbgprintf("GetSystemInfo(%p) =>\n", si);
987 
988     if (cache) {
989 	goto exit;
990     }
991     memset(PF,0,sizeof(PF));
992     pf_set = 1;
993 
994     cachedsi.u.s.wProcessorArchitecture     = PROCESSOR_ARCHITECTURE_INTEL;
995     cachedsi.dwPageSize 			= getpagesize();
996 
997     /* FIXME: better values for the two entries below... */
998     cachedsi.lpMinimumApplicationAddress	= (void *)0x00000000;
999     cachedsi.lpMaximumApplicationAddress	= (void *)0x7FFFFFFF;
1000     cachedsi.dwActiveProcessorMask		= 1;
1001     cachedsi.dwNumberOfProcessors		= 1;
1002     cachedsi.dwProcessorType		= PROCESSOR_INTEL_386;
1003     cachedsi.dwAllocationGranularity	= 0x10000;
1004     cachedsi.wProcessorLevel		= 5; /* pentium */
1005     cachedsi.wProcessorRevision		= 0x0101;
1006 
1007     /* mplayer's way to detect PF's */
1008     {
1009 	if (gCpuCaps.hasMMX)
1010 	    PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1011 	if (gCpuCaps.hasSSE)
1012 	    PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1013 	if (gCpuCaps.hasSSE2)
1014 	    PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
1015 	if (gCpuCaps.has3DNow)
1016 	    PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1017 
1018 	    if (gCpuCaps.cpuType == 4)
1019 	    {
1020 	        cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1021 		cachedsi.wProcessorLevel = 4;
1022 	    }
1023 	    else if (gCpuCaps.cpuType >= 5)
1024 	    {
1025 		cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1026 		cachedsi.wProcessorLevel = 5;
1027 	    }
1028 	    else
1029 	    {
1030 	        cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1031 		cachedsi.wProcessorLevel = 3;
1032 	    }
1033 	    cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
1034     	    cachedsi.dwNumberOfProcessors = 1;	/* hardcoded */
1035     }
1036 
1037 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
1038    fdiv_bug and fpu emulation flags -- alex/MPlayer */
1039 #ifdef __linux__
1040     {
1041 	char buf[20];
1042 	char line[200];
1043 	FILE *f = fopen ("/proc/cpuinfo", "r");
1044 
1045 	if (!f)
1046 	{
1047 	  mp_msg(MSGT_WIN32, MSGL_WARN, "expGetSystemInfo: "
1048 	                     "/proc/cpuinfo not readable! "
1049 	                     "Expect bad performance and/or weird behaviour\n");
1050 	  goto exit;
1051 	}
1052 	while (fgets(line,200,f)!=NULL) {
1053 	    char	*s,*value;
1054 
1055 	    /* NOTE: the ':' is the only character we can rely on */
1056 	    if (!(value = strchr(line,':')))
1057 		continue;
1058 	    /* terminate the valuename */
1059 	    *value++ = '\0';
1060 	    /* skip any leading spaces */
1061 	    while (*value==' ') value++;
1062 	    if ((s=strchr(value,'\n')))
1063 		*s='\0';
1064 
1065 	    /* 2.1 method */
1066 	    if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
1067 		if (isdigit (value[0])) {
1068 		    switch (value[0] - '0') {
1069 		    case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1070 		    cachedsi.wProcessorLevel= 3;
1071 		    break;
1072 		    case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1073 		    cachedsi.wProcessorLevel= 4;
1074 		    break;
1075 		    case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1076 		    cachedsi.wProcessorLevel= 5;
1077 		    break;
1078 		    case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1079 		    cachedsi.wProcessorLevel= 5;
1080 		    break;
1081 		    default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1082 		    cachedsi.wProcessorLevel= 5;
1083 		    break;
1084 		    }
1085 		}
1086 		/* set the CPU type of the current processor */
1087 		sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1088 		continue;
1089 	    }
1090 	    /* old 2.0 method */
1091 	    if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
1092 		if (	isdigit (value[0]) && value[1] == '8' &&
1093 			value[2] == '6' && value[3] == 0
1094 		   ) {
1095 		    switch (value[0] - '0') {
1096 		    case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1097 		    cachedsi.wProcessorLevel= 3;
1098 		    break;
1099 		    case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1100 		    cachedsi.wProcessorLevel= 4;
1101 		    break;
1102 		    case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1103 		    cachedsi.wProcessorLevel= 5;
1104 		    break;
1105 		    case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1106 		    cachedsi.wProcessorLevel= 5;
1107 		    break;
1108 		    default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1109 		    cachedsi.wProcessorLevel= 5;
1110 		    break;
1111 		    }
1112 		}
1113 		/* set the CPU type of the current processor */
1114 		sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1115 		continue;
1116 	    }
1117 	    if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
1118 		if (!lstrncmpiA(value,"yes",3))
1119 		    PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
1120 
1121 		continue;
1122 	    }
1123 	    if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
1124 		if (!lstrncmpiA(value,"no",2))
1125 		    PF[PF_FLOATING_POINT_EMULATED] = TRUE;
1126 
1127 		continue;
1128 	    }
1129 	    if (!lstrncmpiA(line,"processor",strlen("processor"))) {
1130 		/* processor number counts up...*/
1131 		unsigned int x;
1132 
1133 		if (sscanf(value,"%d",&x))
1134 		    if (x+1>cachedsi.dwNumberOfProcessors)
1135 			cachedsi.dwNumberOfProcessors=x+1;
1136 
1137 		/* Create a new processor subkey on a multiprocessor
1138 		 * system
1139 		 */
1140 		sprintf(buf,"%d",x);
1141 	    }
1142 	    if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
1143 		int	x;
1144 
1145 		if (sscanf(value,"%d",&x))
1146 		    cachedsi.wProcessorRevision = x;
1147 	    }
1148 	    if
1149 		( (!lstrncmpiA(line,"flags",strlen("flags")))
1150 		  || (!lstrncmpiA(line,"features",strlen("features"))) )
1151 	    {
1152 		if (strstr(value,"cx8"))
1153 		    PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1154 		if (strstr(value,"mmx"))
1155 		    PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1156 		if (strstr(value,"tsc"))
1157 		    PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
1158 		if (strstr(value,"xmm") || strstr(value,"sse"))
1159 		    PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1160 		if (strstr(value,"sse2"))
1161 		    PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
1162 		if (strstr(value,"3dnow"))
1163 		    PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1164 	    }
1165 	}
1166 	fclose (f);
1167     }
1168 #endif /* __linux__ */
1169     cache = 1;
1170 exit:
1171     memcpy(si,&cachedsi,sizeof(*si));
1172     DumpSystemInfo(si);
1173 }
1174 
1175 // avoid undefined expGetSystemInfo
expIsProcessorFeaturePresent(DWORD v)1176 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
1177 {
1178     WIN_BOOL result = 0;
1179     if (!pf_set)
1180     {
1181 	SYSTEM_INFO si;
1182 	expGetSystemInfo(&si);
1183     }
1184     if(v<64) result=PF[v];
1185     dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
1186     return result;
1187 }
1188 
expIsDebuggerPresent(void)1189 static WIN_BOOL WINAPI expIsDebuggerPresent(void)
1190 {
1191     return 0;
1192 }
1193 
expGetVersion(void)1194 static long WINAPI expGetVersion(void)
1195 {
1196     dbgprintf("GetVersion() => 0xC0000004\n");
1197     return 0xC0000004;//Windows 95
1198 }
1199 
expHeapCreate(long flags,long init_size,long max_size)1200 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
1201 {
1202     //    printf("HeapCreate:");
1203     HANDLE result;
1204     if(init_size==0)
1205 	result=(HANDLE)my_mreq(0x110000, 0);
1206     else
1207 	result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
1208     dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
1209     return result;
1210 }
1211 
1212 // this is another dirty hack
1213 // VP31 is releasing one allocated Heap chunk twice
1214 // we will silently ignore this second call...
1215 static void* heapfreehack = 0;
1216 static int heapfreehackshown = 0;
1217 //void trapbug(void);
expHeapAlloc(HANDLE heap,int flags,int size)1218 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
1219 {
1220     void* z;
1221     /**
1222      Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
1223      HeapAlloc returns area larger than size argument :-/
1224 
1225      actually according to M$ Doc  HeapCreate size should be rounded
1226      to page boundaries thus we should simulate this
1227      **/
1228     //if (size == 22276) trapbug();
1229     z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
1230     if(z==0)
1231 	printf("HeapAlloc failure\n");
1232     dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
1233     heapfreehack = 0; // reset
1234     return z;
1235 }
expHeapDestroy(void * heap)1236 static long WINAPI expHeapDestroy(void* heap)
1237 {
1238     dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
1239     my_release(heap);
1240     return 1;
1241 }
1242 
expHeapFree(HANDLE heap,DWORD dwFlags,LPVOID lpMem)1243 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
1244 {
1245     dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
1246     if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
1247 	&& lpMem != (void*)0xbdbdbdbd)
1248 	// 0xbdbdbdbd is for i263_drv.drv && libefence
1249 	// it seems to be reading from relased memory
1250         // EF_PROTECT_FREE doens't show any probleme
1251 	my_release(lpMem);
1252     else
1253     {
1254 	if (!heapfreehackshown++)
1255 	    printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
1256     }
1257     heapfreehack = lpMem;
1258     return 1;
1259 }
expHeapSize(int heap,int flags,void * pointer)1260 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
1261 {
1262     long result=my_size(pointer);
1263     dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
1264     return result;
1265 }
expHeapReAlloc(HANDLE heap,int flags,void * lpMem,int size)1266 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
1267 {
1268     long orgsize = my_size(lpMem);
1269     dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
1270     return my_realloc(lpMem, size);
1271 }
expGetProcessHeap(void)1272 static long WINAPI expGetProcessHeap(void)
1273 {
1274     dbgprintf("GetProcessHeap() => 1\n");
1275     return 1;
1276 }
expVirtualAlloc(void * v1,long v2,long v3,long v4)1277 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
1278 {
1279     void* z = VirtualAlloc(v1, v2, v3, v4);
1280     if(z==0)
1281 	printf("VirtualAlloc failure\n");
1282     dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
1283     return z;
1284 }
expVirtualFree(void * v1,int v2,int v3)1285 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
1286 {
1287     int result = VirtualFree(v1,v2,v3);
1288     dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
1289     return result;
1290 }
1291 
1292 /* we're building a table of critical sections. cs_win pointer uses the DLL
1293  cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
1294 struct critsecs_list_t
1295 {
1296     CRITICAL_SECTION *cs_win;
1297     struct CRITSECT *cs_unix;
1298 };
1299 
1300 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
1301 #undef CRITSECS_NEWTYPE
1302 //#define CRITSECS_NEWTYPE 1
1303 
1304 #ifdef CRITSECS_NEWTYPE
1305 /* increased due to ucod needs more than 32 entries */
1306 /* and 64 should be enough for everything */
1307 #define CRITSECS_LIST_MAX 64
1308 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
1309 
critsecs_get_pos(CRITICAL_SECTION * cs_win)1310 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
1311 {
1312     int i;
1313 
1314     for (i=0; i < CRITSECS_LIST_MAX; i++)
1315 	if (critsecs_list[i].cs_win == cs_win)
1316 	    return i;
1317     return -1;
1318 }
1319 
critsecs_get_unused(void)1320 static int critsecs_get_unused(void)
1321 {
1322     int i;
1323 
1324     for (i=0; i < CRITSECS_LIST_MAX; i++)
1325 	if (critsecs_list[i].cs_win == NULL)
1326 	    return i;
1327     return -1;
1328 }
1329 
critsecs_get_unix(CRITICAL_SECTION * cs_win)1330 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
1331 {
1332     int i;
1333 
1334     for (i=0; i < CRITSECS_LIST_MAX; i++)
1335 	if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
1336 	    return critsecs_list[i].cs_unix;
1337     return NULL;
1338 }
1339 #endif
1340 
expInitializeCriticalSection(CRITICAL_SECTION * c)1341 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
1342 {
1343     dbgprintf("InitializeCriticalSection(0x%x)\n", c);
1344     /*    if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
1345      {
1346      printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
1347      sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
1348      return;
1349      }*/
1350     /*    pthread_mutex_init((pthread_mutex_t*)c, NULL);   */
1351 #ifdef CRITSECS_NEWTYPE
1352     {
1353 	struct CRITSECT *cs;
1354 	int i = critsecs_get_unused();
1355 
1356 	if (i < 0)
1357 	{
1358 	    printf("InitializeCriticalSection(%p) - no more space in list\n", c);
1359 	    return;
1360 	}
1361 	dbgprintf("got unused space at %d\n", i);
1362 	cs = malloc(sizeof(struct CRITSECT));
1363 	if (!cs)
1364 	{
1365 	    printf("InitializeCriticalSection(%p) - out of memory\n", c);
1366 	    return;
1367 	}
1368 	pthread_mutex_init(&cs->mutex, NULL);
1369 	pthread_cond_init(&cs->unlocked, NULL);
1370 	cs->lock_count = 0;
1371 	critsecs_list[i].cs_win = c;
1372 	critsecs_list[i].cs_unix = cs;
1373 	dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
1374 		  i, c, cs);
1375     }
1376 #else
1377     {
1378 	struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
1379 					   0, AREATYPE_CRITSECT);
1380 	pthread_mutex_init(&cs->mutex, NULL);
1381 	pthread_cond_init(&cs->unlocked, NULL);
1382 	cs->lock_count = 0;
1383         cs->deadbeef = 0xdeadbeef;
1384 	*(void**)c = cs;
1385     }
1386 #endif
1387     return;
1388 }
1389 
expInitializeCriticalSectionAndSpinCount(CRITICAL_SECTION * c,DWORD spin)1390 static WIN_BOOL WINAPI expInitializeCriticalSectionAndSpinCount(CRITICAL_SECTION* c, DWORD spin)
1391 {
1392     expInitializeCriticalSection(c);
1393     return 1;
1394 }
1395 
expEnterCriticalSection(CRITICAL_SECTION * c)1396 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
1397 {
1398 #ifdef CRITSECS_NEWTYPE
1399     struct CRITSECT* cs = critsecs_get_unix(c);
1400 #else
1401     struct CRITSECT* cs = (*(struct CRITSECT**)c);
1402 #endif
1403     dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
1404     if (!cs)
1405     {
1406 	dbgprintf("entered uninitialized critisec!\n");
1407 	expInitializeCriticalSection(c);
1408 #ifdef CRITSECS_NEWTYPE
1409 	cs=critsecs_get_unix(c);
1410 #else
1411 	cs = (*(struct CRITSECT**)c);
1412 #endif
1413 	dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
1414     }
1415     pthread_mutex_lock(&(cs->mutex));
1416     if (cs->lock_count > 0 && cs->id == pthread_self()) {
1417         cs->lock_count++;
1418     } else {
1419         while (cs->lock_count != 0) {
1420             pthread_cond_wait(&(cs->unlocked), &(cs->mutex));
1421         }
1422         cs->lock_count = 1;
1423         cs->id = pthread_self();
1424     }
1425     pthread_mutex_unlock(&(cs->mutex));
1426     return;
1427 }
expLeaveCriticalSection(CRITICAL_SECTION * c)1428 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
1429 {
1430 #ifdef CRITSECS_NEWTYPE
1431     struct CRITSECT* cs = critsecs_get_unix(c);
1432 #else
1433     struct CRITSECT* cs = (*(struct CRITSECT**)c);
1434 #endif
1435     //    struct CRITSECT* cs=(struct CRITSECT*)c;
1436     dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
1437     if (!cs)
1438     {
1439 	dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
1440 	return;
1441     }
1442     pthread_mutex_lock(&(cs->mutex));
1443     if (cs->lock_count == 0) {
1444         dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
1445     } else {
1446         cs->lock_count--;
1447     }
1448     if (cs->lock_count == 0) {
1449         pthread_cond_signal(&(cs->unlocked));
1450     }
1451     pthread_mutex_unlock(&(cs->mutex));
1452     return;
1453 }
1454 
1455 static void expfree(void* mem); /* forward declaration */
1456 
expDeleteCriticalSection(CRITICAL_SECTION * c)1457 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
1458 {
1459 #ifdef CRITSECS_NEWTYPE
1460     struct CRITSECT* cs = critsecs_get_unix(c);
1461 #else
1462     struct CRITSECT* cs= (*(struct CRITSECT**)c);
1463 #endif
1464     //    struct CRITSECT* cs=(struct CRITSECT*)c;
1465     dbgprintf("DeleteCriticalSection(0x%x)\n",c);
1466 
1467     if (!cs)
1468     {
1469 	dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
1470 	return;
1471     }
1472 
1473     pthread_mutex_lock(&(cs->mutex));
1474     if (cs->lock_count > 0)
1475     {
1476        dbgprintf("Win32 Warning: Deleting locked Critical Section %p!!\n", c);
1477     }
1478     pthread_mutex_unlock(&(cs->mutex));
1479 
1480 #ifndef GARBAGE
1481     pthread_mutex_destroy(&(cs->mutex));
1482     pthread_cond_destroy(&(cs->unlocked));
1483     // released by GarbageCollector in my_relase otherwise
1484 #endif
1485     my_release(cs);
1486 #ifdef CRITSECS_NEWTYPE
1487     {
1488 	int i = critsecs_get_pos(c);
1489 
1490 	if (i < 0)
1491 	{
1492 	    printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
1493 	    return;
1494 	}
1495 
1496 	critsecs_list[i].cs_win = NULL;
1497 	expfree(critsecs_list[i].cs_unix);
1498 	critsecs_list[i].cs_unix = NULL;
1499 	dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
1500     }
1501 #endif
1502     return;
1503 }
expGetCurrentThreadId(void)1504 static int WINAPI expGetCurrentThreadId(void)
1505 {
1506     dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
1507     return pthread_self();
1508 }
expGetCurrentProcess(void)1509 static int WINAPI expGetCurrentProcess(void)
1510 {
1511     dbgprintf("GetCurrentProcess() => %d\n", getpid());
1512     return getpid();
1513 }
1514 
1515 #ifdef CONFIG_QTX_CODECS
1516 // this version is required for Quicktime codecs (.qtx/.qts) to work.
1517 // (they assume some pointers at FS: segment)
1518 
1519 //static int tls_count;
1520 static int tls_use_map[64];
expTlsAlloc(void)1521 static int WINAPI expTlsAlloc(void)
1522 {
1523     int i;
1524     for(i=0; i<64; i++)
1525 	if(tls_use_map[i]==0)
1526 	{
1527 	    tls_use_map[i]=1;
1528 	    dbgprintf("TlsAlloc() => %d\n",i);
1529 	    return i;
1530 	}
1531     dbgprintf("TlsAlloc() => -1 (ERROR)\n");
1532     return -1;
1533 }
1534 
1535 //static int WINAPI expTlsSetValue(DWORD index, void* value)
expTlsSetValue(int index,void * value)1536 static int WINAPI expTlsSetValue(int index, void* value)
1537 {
1538     dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
1539 //    if((index<0) || (index>64))
1540     if((index>=64))
1541 	return 0;
1542     *(void**)((char*)fs_seg+0x88+4*index) = value;
1543     return 1;
1544 }
1545 
expTlsGetValue(DWORD index)1546 static void* WINAPI expTlsGetValue(DWORD index)
1547 {
1548     dbgprintf("TlsGetValue(%d)\n",index);
1549 //    if((index<0) || (index>64))
1550     if((index>=64)) return NULL;
1551     return *(void**)((char*)fs_seg+0x88+4*index);
1552 }
1553 
expTlsFree(int idx)1554 static int WINAPI expTlsFree(int idx)
1555 {
1556     int index = (int) idx;
1557     dbgprintf("TlsFree(%d)\n",index);
1558     if((index<0) || (index>64))
1559 	return 0;
1560     tls_use_map[index]=0;
1561     return 1;
1562 }
1563 
1564 #else
1565 struct tls_s {
1566     void* value;
1567     int used;
1568     struct tls_s* prev;
1569     struct tls_s* next;
1570 };
1571 
expTlsAlloc(void)1572 static void* WINAPI expTlsAlloc(void)
1573 {
1574     if (g_tls == NULL)
1575     {
1576 	g_tls=my_mreq(sizeof(tls_t), 0);
1577 	g_tls->next=g_tls->prev=NULL;
1578     }
1579     else
1580     {
1581 	g_tls->next=my_mreq(sizeof(tls_t), 0);
1582 	g_tls->next->prev=g_tls;
1583 	g_tls->next->next=NULL;
1584 	g_tls=g_tls->next;
1585     }
1586     dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
1587     if (g_tls)
1588 	g_tls->value=0; /* XXX For Divx.dll */
1589     return g_tls;
1590 }
1591 
expTlsSetValue(void * idx,void * value)1592 static int WINAPI expTlsSetValue(void* idx, void* value)
1593 {
1594     tls_t* index = (tls_t*) idx;
1595     int result;
1596     if(index==0)
1597 	result=0;
1598     else
1599     {
1600 	index->value=value;
1601 	result=1;
1602     }
1603     dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
1604     return result;
1605 }
expTlsGetValue(void * idx)1606 static void* WINAPI expTlsGetValue(void* idx)
1607 {
1608     tls_t* index = (tls_t*) idx;
1609     void* result;
1610     if(index==0)
1611 	result=0;
1612     else
1613 	result=index->value;
1614     dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
1615     return result;
1616 }
expTlsFree(void * idx)1617 static int WINAPI expTlsFree(void* idx)
1618 {
1619     tls_t* index = (tls_t*) idx;
1620     int result;
1621     if(index==0)
1622 	result=0;
1623     else
1624     {
1625 	if(index->next)
1626 	    index->next->prev=index->prev;
1627 	if(index->prev)
1628 	    index->prev->next=index->next;
1629 	if (g_tls == index)
1630             g_tls = index->prev;
1631 	my_release((void*)index);
1632 	result=1;
1633     }
1634     dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
1635     return result;
1636 }
1637 #endif
1638 
expLocalAlloc(int flags,int size)1639 static void* WINAPI expLocalAlloc(int flags, int size)
1640 {
1641     void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
1642     if (z == 0)
1643 	printf("LocalAlloc() failed\n");
1644     dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1645     return z;
1646 }
1647 
expLocalReAlloc(int handle,int size,int flags)1648 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
1649 {
1650     void *newpointer;
1651     int oldsize;
1652 
1653     newpointer=NULL;
1654     if (flags & LMEM_MODIFY) {
1655 	dbgprintf("LocalReAlloc MODIFY\n");
1656 	return (void *)handle;
1657     }
1658     oldsize = my_size((void *)handle);
1659     newpointer = my_realloc((void *)handle,size);
1660     dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
1661 
1662     return newpointer;
1663 }
1664 
expLocalLock(void * z)1665 static void* WINAPI expLocalLock(void* z)
1666 {
1667     dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
1668     return z;
1669 }
1670 
expGlobalAlloc(int flags,int size)1671 static void* WINAPI expGlobalAlloc(int flags, int size)
1672 {
1673     void* z;
1674     dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
1675 
1676     z=my_mreq(size, (flags & GMEM_ZEROINIT));
1677     //z=calloc(size, 1);
1678     //z=malloc(size);
1679     if(z==0)
1680 	printf("GlobalAlloc() failed\n");
1681     dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1682     return z;
1683 }
expGlobalLock(void * z)1684 static void* WINAPI expGlobalLock(void* z)
1685 {
1686     dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
1687     return z;
1688 }
1689 // pvmjpg20 - but doesn't work anyway
expGlobalSize(void * amem)1690 static int WINAPI expGlobalSize(void* amem)
1691 {
1692     int size = 100000;
1693 #ifdef GARBAGE
1694     alloc_header* header = last_alloc;
1695     alloc_header* mem = (alloc_header*) amem - 1;
1696     if (amem == 0)
1697 	return 0;
1698     pthread_mutex_lock(&memmut);
1699     while (header)
1700     {
1701 	if (header->deadbeef != 0xdeadbeef)
1702 	{
1703 	    dbgprintf("FATAL found corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
1704 	    break;
1705 	}
1706 
1707 	if (header == mem)
1708 	{
1709 	    size = header->size;
1710 	    break;
1711 	}
1712 
1713 	header = header->prev;
1714     }
1715     pthread_mutex_unlock(&memmut);
1716 #endif
1717 
1718     dbgprintf("GlobalSize(0x%x)\n", amem);
1719     return size;
1720 }
1721 
expLoadIconA(long hinstance,char * name)1722 static int WINAPI expLoadIconA( long hinstance, char *name )
1723 {
1724  dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
1725  return 1;
1726 }
1727 
expLoadStringA(long instance,long id,void * buf,long size)1728 static int WINAPI expLoadStringA(long instance, long  id, void* buf, long size)
1729 {
1730     int result=LoadStringA(instance, id, buf, size);
1731     //    if(buf)
1732     dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
1733 	      instance, id, buf, size, result, buf);
1734     //    else
1735     //    dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
1736     //	instance, id, buf, size, result);
1737     return result;
1738 }
1739 
expMultiByteToWideChar(long v1,long v2,char * s1,long siz1,short * s2,int siz2)1740 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
1741 {
1742     /* FIXME */
1743     int i;
1744     int result;
1745     if(s2==0)
1746 	result=1;
1747     else
1748     {
1749 	if(siz1>siz2/2)siz1=siz2/2;
1750 	for(i=1; i<=siz1; i++)
1751 	{
1752 	    *s2=*s1;
1753 	    if(!*s1)break;
1754 	    s2++;
1755 	    s1++;
1756 	}
1757 	result=i;
1758     }
1759     if(s1)
1760 	dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
1761 		  "size %d, dest buffer 0x%x, dest size %d) => %d\n",
1762 		  v1, v2, s1, s1, siz1, s2, siz2, result);
1763     else
1764 	dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
1765 		  "size %d, dest buffer 0x%x, dest size %d) =>\n",
1766 		  v1, v2, siz1, s2, siz2, result);
1767     return result;
1768 }
wch_print(const short * str)1769 static void wch_print(const short* str)
1770 {
1771     dbgprintf("  src: ");
1772     while(*str)dbgprintf("%c", *str++);
1773     dbgprintf("\n");
1774 }
expWideCharToMultiByte(long v1,long v2,short * s1,long siz1,char * s2,int siz2,char * c3,int * siz3)1775 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
1776 					  char* s2, int siz2, char* c3, int* siz3)
1777 {
1778     int result;
1779     dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
1780 	      "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
1781     result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
1782     dbgprintf("=> %d\n", result);
1783     //if(s1)wch_print(s1);
1784     if(s2)dbgprintf("  dest: %s\n", s2);
1785     return result;
1786 }
1787 
expGetVersionExA(OSVERSIONINFOA * c)1788 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
1789 {
1790     dbgprintf("GetVersionExA(0x%x) => 1\n", c);
1791     c->dwOSVersionInfoSize=sizeof(*c);
1792     c->dwMajorVersion=5;
1793     c->dwMinorVersion=1;
1794     c->dwBuildNumber=0x5010a28;
1795     c->dwPlatformId=VER_PLATFORM_WIN32_NT;
1796     strcpy(c->szCSDVersion, "Service Pack 2");
1797     dbgprintf("  Major version: 5\n  Minor version: 1\n  Build number: 0x5010a28\n"
1798 	      "  Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 2'\n");
1799     return 1;
1800 }
1801 
expGetVersionExW(OSVERSIONINFOW * c)1802 static long WINAPI expGetVersionExW(OSVERSIONINFOW* c)
1803 {
1804     char CSDVersion[128];
1805     dbgprintf("GetVersionExW(0x%x) => 1\n", c);
1806     c->dwOSVersionInfoSize=sizeof(*c);
1807     c->dwMajorVersion=5;
1808     c->dwMinorVersion=1;
1809     c->dwBuildNumber=0x5010a28;
1810     c->dwPlatformId=VER_PLATFORM_WIN32_NT;
1811     strcpy(CSDVersion, "Service Pack 2");
1812     MultiByteToWideChar(65001, 0x0, CSDVersion, -1, c->szCSDVersion, 128);
1813     dbgprintf("  Major version: 5\n  Minor version: 1\n  Build number: 0x5010a28\n"
1814 	      "  Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 2'\n");
1815     return 1;
1816 }
1817 
expCreateSemaphoreA(char * v1,long init_count,long max_count,char * name)1818 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
1819 					 long max_count, char* name)
1820 {
1821     pthread_mutex_t *pm;
1822     pthread_cond_t  *pc;
1823     HANDLE ret;
1824     /*
1825     mutex_list* pp;
1826      printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
1827      pp=mlist;
1828      while(pp)
1829      {
1830      printf("%p => ", pp);
1831      pp=pp->prev;
1832      }
1833      printf("0\n");
1834      */
1835     pthread_mutex_lock(&mlist_lock);
1836     if(mlist!=NULL)
1837     {
1838 	mutex_list* pp=mlist;
1839 	if(name!=NULL)
1840 	    do
1841 	{
1842 	    if((strcmp(pp->name, name)==0) && (pp->type==1))
1843 	    {
1844 		dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1845 			  v1, init_count, max_count, name, name, mlist);
1846 		ret = (HANDLE)mlist;
1847 		pthread_mutex_unlock(&mlist_lock);
1848 		return ret;
1849 	    }
1850 	}while((pp=pp->prev) != NULL);
1851     }
1852     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1853     pthread_mutex_init(pm, NULL);
1854     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1855     pthread_cond_init(pc, NULL);
1856     if(mlist==NULL)
1857     {
1858 	mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1859 	mlist->next=mlist->prev=NULL;
1860     }
1861     else
1862     {
1863 	mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1864 	mlist->next->prev=mlist;
1865 	mlist->next->next=NULL;
1866 	mlist=mlist->next;
1867 	//	printf("new semaphore %p\n", mlist);
1868     }
1869     mlist->type=1; /* Type Semaphore */
1870     mlist->pm=pm;
1871     mlist->pc=pc;
1872     mlist->state=0;
1873     mlist->reset=0;
1874     mlist->semaphore=init_count;
1875     if(name!=NULL)
1876 	strncpy(mlist->name, name, 64);
1877     else
1878 	mlist->name[0]=0;
1879     if(pm==NULL)
1880 	dbgprintf("ERROR::: CreateSemaphoreA failure\n");
1881     if(name)
1882 	dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1883 		  v1, init_count, max_count, name, name, mlist);
1884     else
1885 	dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
1886 		  v1, init_count, max_count, mlist);
1887     ret = (HANDLE)mlist;
1888     pthread_mutex_unlock(&mlist_lock);
1889     return ret;
1890 }
1891 
expCreateSemaphoreW(char * v1,long init_count,long max_count,const WCHAR * name)1892 static HANDLE WINAPI expCreateSemaphoreW(char* v1, long init_count,
1893                                          long max_count, const WCHAR* name)
1894 {
1895     char ascii_name[256];
1896     char *aname = NULL;
1897     if (name) {
1898         WideCharToMultiByte(65001, 0x0, name, -1, ascii_name, 256, NULL, NULL);
1899         aname = ascii_name;
1900     }
1901     return expCreateSemaphoreA(v1, init_count, max_count, aname);
1902 }
1903 
expReleaseSemaphore(long hsem,long increment,long * prev_count)1904 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
1905 {
1906     // The state of a semaphore object is signaled when its count
1907     // is greater than zero and nonsignaled when its count is equal to zero
1908     // Each time a waiting thread is released because of the semaphore's signaled
1909     // state, the count of the semaphore is decreased by one.
1910     mutex_list *ml = (mutex_list *)hsem;
1911 
1912     pthread_mutex_lock(ml->pm);
1913     if (prev_count != 0) *prev_count = ml->semaphore;
1914     if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
1915     ml->semaphore += increment;
1916     pthread_mutex_unlock(ml->pm);
1917     dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
1918 	      hsem, increment, prev_count);
1919     return 1;
1920 }
1921 
expCreateMutexA(void * pSecAttr,char bInitialOwner,const char * name)1922 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
1923                    char bInitialOwner, const char *name)
1924 {
1925     pthread_mutex_t *pm;
1926     pthread_cond_t  *pc;
1927     HANDLE ret;
1928     pthread_mutex_lock(&mlist_lock);
1929     if(mlist!=NULL)
1930     {
1931        mutex_list* pp=mlist;
1932        if(name!=NULL)
1933            do
1934        {
1935            if((strcmp(pp->name, name)==0) && (pp->type==2))
1936            {
1937                dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n", pSecAttr, bInitialOwner, name, mlist);
1938                ret = (HANDLE)mlist;
1939                pthread_mutex_unlock(&mlist_lock);
1940                return ret;
1941            }
1942        }while((pp=pp->prev) != NULL);
1943     }
1944     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1945     pthread_mutex_init(pm, NULL);
1946     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1947     pthread_cond_init(pc, NULL);
1948     if(mlist==NULL)
1949     {
1950        mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1951        mlist->next=mlist->prev=NULL;
1952     }
1953     else
1954     {
1955        mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1956        mlist->next->prev=mlist;
1957        mlist->next->next=NULL;
1958        mlist=mlist->next;
1959     }
1960     mlist->type=2; /* Type Mutex */
1961     mlist->pm=pm;
1962     mlist->pc=pc;
1963     mlist->state=0;
1964     mlist->reset=0;
1965     mlist->semaphore=0;
1966     if (bInitialOwner) {
1967       mlist->owner = pthread_self();
1968       mlist->lock_count = 1;
1969     } else {
1970       mlist->owner = (pthread_t)0;
1971       mlist->lock_count = 0;
1972     }
1973     if(name!=NULL)
1974        strncpy(mlist->name, name, 64);
1975     else
1976        mlist->name[0]=0;
1977     if(pm==NULL)
1978        dbgprintf("ERROR::: CreateMutexA failure\n");
1979     if(name)
1980        dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
1981            pSecAttr, bInitialOwner, name, mlist);
1982     else
1983        dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
1984            pSecAttr, bInitialOwner, mlist);
1985     ret = (HANDLE)mlist;
1986     pthread_mutex_unlock(&mlist_lock);
1987     return ret;
1988 }
1989 
expCreateMutexW(void * pSecAttr,char bInitialOwner,const WCHAR * name)1990 static HANDLE WINAPI expCreateMutexW(void *pSecAttr, char bInitialOwner, const WCHAR *name)
1991 {
1992     char ascii_name[256];
1993     char *aname = NULL;
1994     if (name) {
1995         WideCharToMultiByte(65001, 0x0, name, -1, ascii_name, 256, NULL, NULL);
1996         aname = ascii_name;
1997     }
1998     return expCreateMutexA(pSecAttr, bInitialOwner, aname);
1999 }
2000 
expReleaseMutex(HANDLE hMutex)2001 static int WINAPI expReleaseMutex(HANDLE hMutex)
2002 {
2003     mutex_list *ml = (mutex_list *)hMutex;
2004 
2005     pthread_mutex_lock(ml->pm);
2006     if (--ml->lock_count == 0) pthread_cond_signal(ml->pc);
2007     pthread_mutex_unlock(ml->pm);
2008     return 1;
2009 }
2010 
expSignalObjectAndWait(HANDLE hObjectToSignal,HANDLE hObjectToWaitOn,DWORD dwMilliseconds,WIN_BOOL bAlertable)2011 static DWORD WINAPI expSignalObjectAndWait(HANDLE hObjectToSignal,
2012                                            HANDLE hObjectToWaitOn,
2013                                            DWORD dwMilliseconds,
2014                                            WIN_BOOL bAlertable) {
2015     mutex_list* mlist = (mutex_list*)hObjectToSignal;
2016 
2017     switch (mlist->type) {
2018     case 0:  // Event
2019         expSetEvent(mlist);
2020         break;
2021     case 1:  // Semaphore
2022         expReleaseSemaphore(mlist, 1, NULL);
2023         break;
2024     case 2:  // Mutex
2025         expReleaseMutex(mlist);
2026         break;
2027     default:
2028         dbgprintf("Signalling unknown object type %d!\n", hObjectToSignal);
2029     }
2030     return expWaitForSingleObject(hObjectToWaitOn, dwMilliseconds);
2031 }
2032 
expRegOpenKeyExA(long key,const char * subkey,long reserved,long access,int * newkey)2033 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
2034 {
2035     long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
2036     dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
2037 	      key, subkey, reserved, access, newkey, result);
2038     if(newkey)dbgprintf("  New key: 0x%x\n", *newkey);
2039     return result;
2040 }
expRegCloseKey(long key)2041 static long WINAPI expRegCloseKey(long key)
2042 {
2043     long result=RegCloseKey(key);
2044     dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
2045     return result;
2046 }
expRegQueryValueExA(long key,const char * value,int * reserved,int * type,int * data,int * count)2047 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
2048 {
2049     long result=RegQueryValueExA(key, value, reserved, type, data, count);
2050     dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
2051 	      " => 0x%x\n", key, value, reserved, data, count, result);
2052     if(data && count)dbgprintf("  read %d bytes: '%s'\n", *count, data);
2053     return result;
2054 }
2055 
2056 //from wine source dlls/advapi32/registry.c
expRegCreateKeyA(long hkey,const char * name,int * retkey)2057 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
2058 {
2059     dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
2060     return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
2061                             KEY_ALL_ACCESS , NULL, retkey, NULL );
2062 }
2063 
expRegCreateKeyExA(long key,const char * name,long reserved,void * classs,long options,long security,void * sec_attr,int * newkey,int * status)2064 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
2065 				      void* classs, long options, long security,
2066 				      void* sec_attr, int* newkey, int* status)
2067 {
2068     long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
2069     dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
2070 	      " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
2071 	      key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
2072     if(!result && newkey) dbgprintf("  New key: 0x%x\n", *newkey);
2073     if(!result && status) dbgprintf("  New key status: 0x%x\n", *status);
2074     return result;
2075 }
expRegSetValueExA(long key,const char * name,long v1,long v2,void * data,long size)2076 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
2077 {
2078     long result=RegSetValueExA(key, name, v1, v2, data, size);
2079     dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
2080 	      key, name, v1, v2, data, *(int*)data, data, size, result);
2081     return result;
2082 }
2083 
expRegOpenKeyA(long hKey,LPCSTR lpSubKey,int * phkResult)2084 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
2085 {
2086     long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
2087     dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
2088 	      hKey, lpSubKey, phkResult, result);
2089     if(!result && phkResult) dbgprintf("  New key: 0x%x\n", *phkResult);
2090     return result;
2091 }
2092 
expRegEnumValueA(HKEY hkey,DWORD index,LPSTR value,LPDWORD val_count,LPDWORD reserved,LPDWORD type,LPBYTE data,LPDWORD count)2093 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
2094 				     LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
2095 {
2096     return RegEnumValueA(hkey, index, value, val_count,
2097 			 reserved, type, data, count);
2098 }
2099 
expRegEnumKeyExA(HKEY hKey,DWORD dwIndex,LPSTR lpName,LPDWORD lpcbName,LPDWORD lpReserved,LPSTR lpClass,LPDWORD lpcbClass,LPFILETIME lpftLastWriteTime)2100 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
2101 				     LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
2102 				     LPFILETIME lpftLastWriteTime)
2103 {
2104     return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
2105 			 lpcbClass, lpftLastWriteTime);
2106 }
2107 
expQueryPerformanceCounter(long long * z)2108 static long WINAPI expQueryPerformanceCounter(long long* z)
2109 {
2110     longcount(z);
2111     dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
2112     return 1;
2113 }
2114 
2115 /*
2116  * dummy function RegQueryInfoKeyA(), required by vss codecs
2117  */
expRegQueryInfoKeyA(HKEY hkey,LPSTR class,LPDWORD class_len,LPDWORD reserved,LPDWORD subkeys,LPDWORD max_subkey,LPDWORD max_class,LPDWORD values,LPDWORD max_value,LPDWORD max_data,LPDWORD security,FILETIME * modif)2118 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
2119                                          LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
2120                                          LPDWORD values, LPDWORD max_value, LPDWORD max_data,
2121                                          LPDWORD security, FILETIME *modif )
2122 {
2123     return ERROR_SUCCESS;
2124 }
2125 
2126 /*
2127  * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
2128  */
linux_cpuinfo_freq(void)2129 static double linux_cpuinfo_freq(void)
2130 {
2131     double freq=-1;
2132     FILE *f;
2133     char line[200];
2134     char *s,*value;
2135 
2136     f = fopen ("/proc/cpuinfo", "r");
2137     if (f != NULL) {
2138 	while (fgets(line,sizeof(line),f)!=NULL) {
2139 	    /* NOTE: the ':' is the only character we can rely on */
2140 	    if (!(value = strchr(line,':')))
2141 		continue;
2142 	    /* terminate the valuename */
2143 	    *value++ = '\0';
2144 	    /* skip any leading spaces */
2145 	    while (*value==' ') value++;
2146 	    if ((s=strchr(value,'\n')))
2147 		*s='\0';
2148 
2149 	    if (!av_strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
2150 		&& sscanf(value, "%lf", &freq) == 1) {
2151 		freq*=1000;
2152 		break;
2153 	    }
2154 	}
2155 	fclose(f);
2156     }
2157     return freq;
2158 }
2159 
2160 
solaris_kstat_freq(void)2161 static double solaris_kstat_freq(void)
2162 {
2163 #if	defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
2164     /*
2165      * try to extract the CPU speed from the solaris kernel's kstat data
2166      */
2167     kstat_ctl_t   *kc;
2168     kstat_t       *ksp;
2169     kstat_named_t *kdata;
2170     int            mhz = 0;
2171 
2172     kc = kstat_open();
2173     if (kc != NULL)
2174     {
2175 	ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
2176 
2177 	/* kstat found and name/value pairs? */
2178 	if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
2179 	{
2180 	    /* read the kstat data from the kernel */
2181 	    if (kstat_read(kc, ksp, NULL) != -1)
2182 	    {
2183 		/*
2184 		 * lookup desired "clock_MHz" entry, check the expected
2185 		 * data type
2186 		 */
2187 		kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
2188 		if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
2189 		    mhz = kdata->value.i32;
2190 	    }
2191 	}
2192 	kstat_close(kc);
2193     }
2194 
2195     if (mhz > 0)
2196 	return mhz * 1000.;
2197 #endif	/* HAVE_LIBKSTAT */
2198     return -1;		// kstat stuff is not available, CPU freq is unknown
2199 }
2200 
2201 /*
2202  * Measure CPU freq using the pentium's time stamp counter register (TSC)
2203  */
tsc_freq(void)2204 static double tsc_freq(void)
2205 {
2206     static double ofreq=0.0;
2207     int i;
2208     int x,y;
2209     i=time(NULL);
2210     if (ofreq != 0.0) return ofreq;
2211     while(i==time(NULL));
2212     x=localcount();
2213     i++;
2214     while(i==time(NULL));
2215     y=localcount();
2216     ofreq = (double)(y-x)/1000.;
2217     return ofreq;
2218 }
2219 
CPU_Freq(void)2220 static double CPU_Freq(void)
2221 {
2222     double freq;
2223 
2224     if ((freq = linux_cpuinfo_freq()) > 0)
2225 	return freq;
2226 
2227     if ((freq = solaris_kstat_freq()) > 0)
2228 	return freq;
2229 
2230     return tsc_freq();
2231 }
2232 
expQueryPerformanceFrequency(long long * z)2233 static long WINAPI expQueryPerformanceFrequency(long long* z)
2234 {
2235     *z=(long long)CPU_Freq();
2236     dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
2237     return 1;
2238 }
exptimeGetTime(void)2239 static long WINAPI exptimeGetTime(void)
2240 {
2241     struct timeval t;
2242     long result;
2243     gettimeofday(&t, 0);
2244     result=1000*t.tv_sec+t.tv_usec/1000;
2245     dbgprintf("timeGetTime() => %d\n", result);
2246     return result;
2247 }
expLocalHandle(void * v)2248 static void* WINAPI expLocalHandle(void* v)
2249 {
2250     dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
2251     return v;
2252 }
2253 
expGlobalHandle(void * v)2254 static void* WINAPI expGlobalHandle(void* v)
2255 {
2256     dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
2257     return v;
2258 }
expGlobalUnlock(void * v)2259 static int WINAPI expGlobalUnlock(void* v)
2260 {
2261     dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
2262     return 1;
2263 }
expGlobalFree(void * v)2264 static void* WINAPI expGlobalFree(void* v)
2265 {
2266     dbgprintf("GlobalFree(0x%x) => 0\n", v);
2267     my_release(v);
2268     //free(v);
2269     return 0;
2270 }
2271 
expGlobalReAlloc(void * v,int size,int flags)2272 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
2273 {
2274     void* result=my_realloc(v, size);
2275     //void* result=realloc(v, size);
2276     dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
2277     return result;
2278 }
2279 
expLocalUnlock(void * v)2280 static int WINAPI expLocalUnlock(void* v)
2281 {
2282     dbgprintf("LocalUnlock(0x%x) => 1\n", v);
2283     return 1;
2284 }
2285 //
expLocalFree(void * v)2286 static void* WINAPI expLocalFree(void* v)
2287 {
2288     dbgprintf("LocalFree(0x%x) => 0\n", v);
2289     my_release(v);
2290     return 0;
2291 }
expFindResourceA(HMODULE module,char * name,char * type)2292 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
2293 {
2294     HRSRC result;
2295 
2296     result=FindResourceA(module, name, type);
2297     dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
2298 	module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
2299     return result;
2300 }
2301 
expLoadResource(HMODULE module,HRSRC res)2302 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
2303 {
2304     HGLOBAL result=LoadResource(module, res);
2305     dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
2306     return result;
2307 }
expLockResource(long res)2308 static void* WINAPI expLockResource(long res)
2309 {
2310     void* result=LockResource(res);
2311     dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
2312     return result;
2313 }
expFreeResource(long res)2314 static int WINAPI expFreeResource(long res)
2315 {
2316     int result=FreeResource(res);
2317     dbgprintf("FreeResource(0x%x) => %d\n", res, result);
2318     return result;
2319 }
2320 //bool fun(HANDLE)
2321 //!0 on success
expCloseHandle(long v1)2322 static int WINAPI expCloseHandle(long v1)
2323 {
2324     dbgprintf("CloseHandle(0x%x) => 1\n", v1);
2325     /* do not close stdin,stdout and stderr */
2326     if (v1 > 2)
2327 	if (!close(v1))
2328 	    return 0;
2329     return 1;
2330 }
2331 
expGetCommandLineA(void)2332 static const char* WINAPI expGetCommandLineA(void)
2333 {
2334     dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
2335     return "c:\\aviplay.exe";
2336 }
2337 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
expGetEnvironmentStringsW(void)2338 static LPWSTR WINAPI expGetEnvironmentStringsW(void)
2339 {
2340     dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
2341     return 0;
2342 }
expRtlZeroMemory(void * p,size_t len)2343 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
2344 {
2345     void* result=memset(p,0,len);
2346     dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
2347     return result;
2348 }
expRtlMoveMemory(void * dst,void * src,size_t len)2349 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
2350 {
2351     void* result=memmove(dst,src,len);
2352     dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
2353     return result;
2354 }
2355 
expRtlFillMemory(void * p,int ch,size_t len)2356 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
2357 {
2358     void* result=memset(p,ch,len);
2359     dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
2360     return result;
2361 }
expFreeEnvironmentStringsW(short * strings)2362 static int WINAPI expFreeEnvironmentStringsW(short* strings)
2363 {
2364     dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
2365     return 1;
2366 }
expFreeEnvironmentStringsA(char * strings)2367 static int WINAPI expFreeEnvironmentStringsA(char* strings)
2368 {
2369     dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
2370     return 1;
2371 }
2372 
2373 static const char ch_envs[]=
2374 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
2375 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
expGetEnvironmentStrings(void)2376 static LPCSTR WINAPI expGetEnvironmentStrings(void)
2377 {
2378     dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
2379     return (LPCSTR)ch_envs;
2380     // dbgprintf("GetEnvironmentStrings() => 0\n");
2381     // return 0;
2382 }
2383 
expGetStartupInfoA(STARTUPINFOA * s)2384 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
2385 {
2386     dbgprintf("GetStartupInfoA(0x%x) => 1\n");
2387     memset(s, 0, sizeof(*s));
2388     s->cb=sizeof(*s);
2389     // s->lpReserved="Reserved";
2390     // s->lpDesktop="Desktop";
2391     // s->lpTitle="Title";
2392     // s->dwX=s->dwY=0;
2393     // s->dwXSize=s->dwYSize=200;
2394     s->dwFlags=s->wShowWindow=1;
2395     // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
2396     dbgprintf("  cb=%d\n", s->cb);
2397     dbgprintf("  lpReserved='%s'\n", s->lpReserved);
2398     dbgprintf("  lpDesktop='%s'\n", s->lpDesktop);
2399     dbgprintf("  lpTitle='%s'\n", s->lpTitle);
2400     dbgprintf("  dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
2401 	      s->dwX, s->dwY, s->dwXSize, s->dwYSize);
2402     dbgprintf("  dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
2403 	      s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
2404     dbgprintf("  dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
2405 	      s->dwFlags, s->wShowWindow, s->cbReserved2);
2406     dbgprintf("  lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
2407 	      s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
2408     return 1;
2409 }
2410 
expGetStdHandle(int z)2411 static int WINAPI expGetStdHandle(int z)
2412 {
2413     dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
2414     return z+0x1234;
2415 }
2416 
2417 #ifdef CONFIG_QTX_CODECS
2418 #define FILE_HANDLE_quicktimeqts	((HANDLE)0x444)
2419 #define FILE_HANDLE_quicktimeqtx	((HANDLE)0x445)
2420 #endif
2421 
expGetFileType(int handle)2422 static int WINAPI expGetFileType(int handle)
2423 {
2424     dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
2425     return 0x3;
2426 }
2427 #ifdef CONFIG_QTX_CODECS
expGetFileAttributesA(char * filename)2428 static int WINAPI expGetFileAttributesA(char *filename)
2429 {
2430     dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
2431     if (strstr(filename, "QuickTime.qts"))
2432 	return FILE_ATTRIBUTE_SYSTEM;
2433     return FILE_ATTRIBUTE_NORMAL;
2434 }
2435 #endif
expSetHandleCount(int count)2436 static int WINAPI expSetHandleCount(int count)
2437 {
2438     dbgprintf("SetHandleCount(0x%x) => 1\n", count);
2439     return 1;
2440 }
expGetACP(void)2441 static int WINAPI expGetACP(void)
2442 {
2443     dbgprintf("GetACP() => 0\n");
2444     return 0;
2445 }
expGetModuleFileNameA(int module,char * s,int len)2446 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
2447 {
2448     WINE_MODREF *mr;
2449     int result;
2450     //printf("File name of module %X (%s) requested\n", module, s);
2451 
2452     if (module == 0 && len >= 12)
2453     {
2454 	/* return caller program name */
2455 	strcpy(s, "aviplay.dll");
2456 	result=1;
2457     }
2458     else if(s==0)
2459 	result=0;
2460     else
2461 	if(len<35)
2462 	    result=0;
2463 	else
2464 	{
2465 	    result=1;
2466 	    strcpy(s, "c:\\windows\\system\\");
2467 	    mr=MODULE32_LookupHMODULE(module);
2468 	    if(mr==0)//oops
2469 		strcat(s, "aviplay.dll");
2470 	    else
2471 		if(strrchr(mr->filename, '/')==NULL)
2472 		    strcat(s, mr->filename);
2473 		else
2474 		    strcat(s, strrchr(mr->filename, '/')+1);
2475 	}
2476     if(!s)
2477 	dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
2478 		  module, s, len, result);
2479     else
2480 	dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
2481 		  module, s, len, result, s);
2482     return result;
2483 }
2484 
expGetModuleBaseNameA(int process,int module,char * s,int len)2485 static int WINAPI expGetModuleBaseNameA(int process, int module, char* s, int len)
2486 {
2487     int result = 0;
2488 
2489     if (s && len) {
2490         av_strlcpy(s, "aviplay.dll", len);
2491         result = strlen(s);
2492     }
2493 
2494     dbgprintf("GetModuleBaseNameA(0x%x, 0x%x, 0x%x, %d) => %d\n",
2495         process, module, s, len, result);
2496 
2497     return result;
2498 }
2499 
expSetUnhandledExceptionFilter(void * filter)2500 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
2501 {
2502     dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
2503     return 1;//unsupported and probably won't ever be supported
2504 }
2505 
expLoadLibraryA(char * name)2506 static int WINAPI expLoadLibraryA(char* name)
2507 {
2508     int result = 0;
2509     char* lastbc;
2510     if (!name)
2511 	return -1;
2512     // we skip to the last backslash
2513     // this is effectively eliminating weird characters in
2514     // the text output windows
2515 
2516     lastbc = strrchr(name, '\\');
2517     if (lastbc)
2518     {
2519 	int i;
2520 	lastbc++;
2521 	for (i = 0; 1 ;i++)
2522 	{
2523 	    name[i] = *lastbc++;
2524 	    if (!name[i])
2525 		break;
2526 	}
2527     }
2528     if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
2529     if(strncmp(name, ".\\", 2)==0) name += 2;
2530 
2531     dbgprintf("Entering LoadLibraryA(%s)\n", name);
2532 
2533     // PIMJ and VIVO audio are loading  kernel32.dll
2534     if (av_strcasecmp(name, "kernel32.dll") == 0 || av_strcasecmp(name, "kernel32") == 0)
2535 	return MODULE_HANDLE_kernel32;
2536 //	return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
2537 			      /* exported -> do not return failed! */
2538 
2539     if (av_strcasecmp(name, "user32.dll") == 0 || av_strcasecmp(name, "user32") == 0)
2540 //	return MODULE_HANDLE_kernel32;
2541 	return MODULE_HANDLE_user32;
2542 
2543 #ifdef CONFIG_QTX_CODECS
2544     if (av_strcasecmp(name, "wininet.dll") == 0 || av_strcasecmp(name, "wininet") == 0)
2545 	return MODULE_HANDLE_wininet;
2546     if (av_strcasecmp(name, "ddraw.dll") == 0 || av_strcasecmp(name, "ddraw") == 0)
2547 	return MODULE_HANDLE_ddraw;
2548     if (av_strcasecmp(name, "advapi32.dll") == 0 || av_strcasecmp(name, "advapi32") == 0)
2549 	return MODULE_HANDLE_advapi32;
2550 #endif
2551 
2552     if (av_strcasecmp(name, "comdlg32.dll") == 0 || av_strcasecmp(name, "comdlg32") == 0)
2553 	return MODULE_HANDLE_comdlg32;
2554     if (av_strcasecmp(name, "msvcrt.dll") == 0 || av_strcasecmp(name, "msvcrt") == 0)
2555 	return MODULE_HANDLE_msvcrt;
2556     if (av_strcasecmp(name, "ole32.dll") == 0 || av_strcasecmp(name, "ole32") == 0)
2557 	return MODULE_HANDLE_ole32;
2558     if (av_strcasecmp(name, "winmm.dll") == 0 || av_strcasecmp(name, "winmm") == 0)
2559 	return MODULE_HANDLE_winmm;
2560     if (av_strcasecmp(name, "psapi.dll") == 0 || av_strcasecmp(name, "psapi") == 0)
2561 	return MODULE_HANDLE_psapi;
2562 
2563     result=LoadLibraryA(name);
2564     dbgprintf("Returned LoadLibraryA(0x%x='%s'), codec_path=%s => 0x%x\n",
2565               name, name, codec_path, result);
2566 
2567     return result;
2568 }
2569 
expFreeLibrary(int module)2570 static int WINAPI expFreeLibrary(int module)
2571 {
2572 #ifdef CONFIG_QTX_CODECS
2573     int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
2574 #else
2575     int result=FreeLibrary(module);
2576 #endif
2577     dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
2578     return result;
2579 }
2580 
expGetProcAddress(HMODULE mod,char * name)2581 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
2582 {
2583     void* result;
2584     switch(mod){
2585     case MODULE_HANDLE_kernel32:
2586 	result=LookupExternalByName("kernel32.dll", name); break;
2587     case MODULE_HANDLE_user32:
2588 	result=LookupExternalByName("user32.dll", name); break;
2589 #ifdef CONFIG_QTX_CODECS
2590     case MODULE_HANDLE_wininet:
2591 	result=LookupExternalByName("wininet.dll", name); break;
2592     case MODULE_HANDLE_ddraw:
2593 	result=LookupExternalByName("ddraw.dll", name); break;
2594     case MODULE_HANDLE_advapi32:
2595 	result=LookupExternalByName("advapi32.dll", name); break;
2596 #endif
2597     case MODULE_HANDLE_comdlg32:
2598 	result=LookupExternalByName("comdlg32.dll", name); break;
2599     case MODULE_HANDLE_msvcrt:
2600 	result=LookupExternalByName("msvcrt.dll", name); break;
2601     case MODULE_HANDLE_ole32:
2602 	result=LookupExternalByName("ole32.dll", name); break;
2603     case MODULE_HANDLE_winmm:
2604 	result=LookupExternalByName("winmm.dll", name); break;
2605     case MODULE_HANDLE_psapi:
2606 	result=LookupExternalByName("psapi.dll", name); break;
2607     default:
2608 	result=GetProcAddress(mod, name);
2609     }
2610     if((unsigned int)name > 0xffff)
2611 	dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
2612     else
2613 	dbgprintf("GetProcAddress(0x%x, '%d') => 0x%x\n", mod, (int)name, result);
2614     return result;
2615 }
2616 
expCreateFileMappingA(int hFile,void * lpAttr,long flProtect,long dwMaxHigh,long dwMaxLow,const char * name)2617 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
2618 					 long flProtect, long dwMaxHigh,
2619 					 long dwMaxLow, const char* name)
2620 {
2621     long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
2622     if(!name)
2623 	dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2624 		  "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
2625 		  hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
2626     else
2627 	dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2628 		  "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
2629 		  hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
2630     return result;
2631 }
2632 
expOpenFileMappingA(long hFile,long hz,const char * name)2633 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
2634 {
2635     long result=OpenFileMappingA(hFile, hz, name);
2636     if(!name)
2637 	dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
2638 		  hFile, hz, result);
2639     else
2640 	dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
2641 		  hFile, hz, name, name, result);
2642     return result;
2643 }
2644 
expMapViewOfFile(HANDLE file,DWORD mode,DWORD offHigh,DWORD offLow,DWORD size)2645 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
2646 				     DWORD offLow, DWORD size)
2647 {
2648     dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
2649 	      file,mode,offHigh,offLow,size,(char*)file+offLow);
2650     return (char*)file+offLow;
2651 }
2652 
expUnmapViewOfFile(void * view)2653 static void* WINAPI expUnmapViewOfFile(void* view)
2654 {
2655     dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
2656     return 0;
2657 }
2658 
expSleep(int time)2659 static void* WINAPI expSleep(int time)
2660 {
2661 #if HAVE_NANOSLEEP
2662     /* solaris doesn't have thread safe usleep */
2663     struct timespec tsp;
2664     tsp.tv_sec  =  time / 1000000;
2665     tsp.tv_nsec = (time % 1000000) * 1000;
2666     nanosleep(&tsp, NULL);
2667 #else
2668     usleep(time);
2669 #endif
2670     dbgprintf("Sleep(%d) => 0\n", time);
2671     return 0;
2672 }
2673 
2674 // why does IV32 codec want to call this? I don't know ...
expCreateCompatibleDC(int hdc)2675 static int WINAPI expCreateCompatibleDC(int hdc)
2676 {
2677     int dc = 0;//0x81;
2678     //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
2679     dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
2680     return dc;
2681 }
2682 
expGetDeviceCaps(int hdc,int unk)2683 static int WINAPI expGetDeviceCaps(int hdc, int unk)
2684 {
2685     dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
2686 #ifdef CONFIG_QTX_CODECS
2687     #define BITSPIXEL 12
2688     #define PLANES    14
2689     if (unk == BITSPIXEL)
2690 	return 24;
2691     if (unk == PLANES)
2692 	return 1;
2693 #endif
2694     return 1;
2695 }
2696 
expDeleteDC(int hdc)2697 static WIN_BOOL WINAPI expDeleteDC(int hdc)
2698 {
2699     dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
2700     if (hdc == 0x81)
2701 	return 1;
2702     return 0;
2703 }
2704 
expDeleteObject(int hdc)2705 static WIN_BOOL WINAPI expDeleteObject(int hdc)
2706 {
2707     dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
2708     /* FIXME - implement code here */
2709     return 1;
2710 }
2711 
2712 /* btvvc32.drv wants this one */
expGetWindowDC(int hdc)2713 static void* WINAPI expGetWindowDC(int hdc)
2714 {
2715     dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
2716     return 0;
2717 }
2718 
2719 #ifdef CONFIG_QTX_CODECS
expGetWindowRect(HWND win,RECT * r)2720 static int WINAPI expGetWindowRect(HWND win, RECT *r)
2721 {
2722     dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
2723     /* (win == 0) => desktop */
2724     r->right = PSEUDO_SCREEN_WIDTH;
2725     r->left = 0;
2726     r->bottom = PSEUDO_SCREEN_HEIGHT;
2727     r->top = 0;
2728     return 1;
2729 }
2730 
expMonitorFromWindow(HWND win,int flags)2731 static int WINAPI expMonitorFromWindow(HWND win, int flags)
2732 {
2733     dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
2734     return 0;
2735 }
2736 
expMonitorFromRect(RECT * r,int flags)2737 static int WINAPI expMonitorFromRect(RECT *r, int flags)
2738 {
2739     dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
2740     return 0;
2741 }
2742 
expMonitorFromPoint(void * p,int flags)2743 static int WINAPI expMonitorFromPoint(void *p, int flags)
2744 {
2745     dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
2746     return 0;
2747 }
2748 
expEnumDisplayMonitors(void * dc,RECT * r,int WINAPI (* callback_proc)(HMONITOR,HDC,LPRECT,LPARAM),void * callback_param)2749 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r,
2750     int WINAPI (*callback_proc)(HMONITOR, HDC, LPRECT, LPARAM), void *callback_param)
2751 {
2752     dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
2753 	dc, r, callback_proc, callback_param);
2754     return callback_proc(0, dc, r, callback_param);
2755 }
2756 
2757 #if 0
2758 typedef struct tagMONITORINFO {
2759     DWORD  cbSize;
2760     RECT   rcMonitor;
2761     RECT   rcWork;
2762     DWORD  dwFlags;
2763 } MONITORINFO, *LPMONITORINFO;
2764 #endif
2765 
2766 #define CCHDEVICENAME 8
2767 typedef struct tagMONITORINFOEX {
2768     DWORD  cbSize;
2769     RECT   rcMonitor;
2770     RECT   rcWork;
2771     DWORD  dwFlags;
2772     TCHAR  szDevice[CCHDEVICENAME];
2773 } MONITORINFOEX, *LPMONITORINFOEX;
2774 
expGetMonitorInfoA(void * mon,LPMONITORINFO lpmi)2775 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
2776 {
2777     dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
2778 
2779     lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
2780     lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
2781     lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
2782     lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
2783 
2784     lpmi->dwFlags = 1; /* primary monitor */
2785 
2786     if (lpmi->cbSize == sizeof(MONITORINFOEX))
2787     {
2788 	LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
2789 	dbgprintf("MONITORINFOEX!\n");
2790 	strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
2791     }
2792 
2793     return 1;
2794 }
2795 
expEnumDisplayDevicesA(const char * device,int devnum,void * dispdev,int flags)2796 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
2797 	void *dispdev, int flags)
2798 {
2799     dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
2800 	device, device, devnum, dispdev, flags);
2801     return 1;
2802 }
2803 
expIsWindowVisible(HWND win)2804 static int WINAPI expIsWindowVisible(HWND win)
2805 {
2806     dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
2807     return 1;
2808 }
2809 
expGetActiveWindow(void)2810 static HWND WINAPI expGetActiveWindow(void)
2811 {
2812     dbgprintf("GetActiveWindow() => 0\n");
2813     return (HWND)0;
2814 }
2815 
expGetClassNameA(HWND win,LPTSTR classname,int maxcount)2816 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
2817 {
2818     strncat(classname, "QuickTime", maxcount);
2819     dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
2820 	win, classname, maxcount, strlen(classname));
2821     return strlen(classname);
2822 }
2823 
2824 #define LPWNDCLASS void *
expGetClassInfoA(HINSTANCE inst,LPCSTR classname,LPWNDCLASS wndclass)2825 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
2826 {
2827     dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
2828 	classname, classname, wndclass);
2829     return 1;
2830 }
2831 
expGetWindowLongA(HWND win,int index)2832 static int WINAPI expGetWindowLongA(HWND win, int index)
2833 {
2834     dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
2835     return 1;
2836 }
2837 
expGetObjectA(HGDIOBJ hobj,int objsize,LPVOID obj)2838 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
2839 {
2840     dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
2841     return objsize;
2842 }
2843 
expCreateRectRgn(int x,int y,int width,int height)2844 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
2845 {
2846     dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
2847     return 0;
2848 }
2849 
expEnumWindows(int (* callback_func)(HWND,LPARAM),void * callback_param)2850 static int WINAPI expEnumWindows(int (*callback_func)(HWND, LPARAM), void *callback_param)
2851 {
2852     int i, i2;
2853     dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
2854     i = callback_func(0, callback_param);
2855     i2 = callback_func(1, callback_param);
2856     return i && i2;
2857 }
2858 
expGetWindowThreadProcessId(HWND win,int * pid_data)2859 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
2860 {
2861     int tid = pthread_self();
2862     dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
2863 	win, pid_data, tid);
2864     if (pid_data)
2865 	*(int*)pid_data = tid;
2866     return tid;
2867 }
2868 
2869 //HWND      WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
2870 //                                INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
2871 
expCreateWindowExA(int exstyle,const char * classname,const char * winname,int style,int x,int y,int w,int h,HWND parent,HMENU menu,HINSTANCE inst,LPVOID param)2872 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
2873     const char *winname, int style, int x, int y, int w, int h,
2874     HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
2875 {
2876     printf("CreateWindowEx() called\n");
2877     dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
2878 	exstyle, classname, classname, winname, winname, style, x, y, w, h,
2879 	parent, menu, inst, param);
2880     printf("CreateWindowEx() called okey\n");
2881     return 1;
2882 }
2883 
expwaveOutGetNumDevs(void)2884 static int WINAPI expwaveOutGetNumDevs(void)
2885 {
2886     dbgprintf("waveOutGetNumDevs() => 0\n");
2887     return 0;
2888 }
2889 #endif
2890 
2891 /*
2892  * Returns the number of milliseconds, modulo 2^32, since the start
2893  * of the wineserver.
2894  */
expGetTickCount(void)2895 static int WINAPI expGetTickCount(void)
2896 {
2897     static int tcstart = 0;
2898     struct timeval t;
2899     int tc;
2900     gettimeofday( &t, NULL );
2901     tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
2902     if (tcstart == 0)
2903     {
2904 	tcstart = 0;
2905         tc = 0;
2906     }
2907     dbgprintf("GetTickCount() => %d\n", tc);
2908     return tc;
2909 }
2910 
expCreateFontA(void)2911 static int WINAPI expCreateFontA(void)
2912 {
2913     dbgprintf("CreateFontA() => 0x0\n");
2914     return 1;
2915 }
2916 
2917 /* tried to get pvmjpg work in a different way - no success */
expDrawTextA(int hDC,char * lpString,int nCount,LPRECT lpRect,unsigned int uFormat)2918 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
2919 			       LPRECT lpRect, unsigned int uFormat)
2920 {
2921     dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
2922     return 8;
2923 }
2924 
expGetPrivateProfileIntA(const char * appname,const char * keyname,int default_value,const char * filename)2925 static int WINAPI expGetPrivateProfileIntA(const char* appname,
2926 					   const char* keyname,
2927 					   int default_value,
2928 					   const char* filename)
2929 {
2930     int size=255;
2931     char buffer[256];
2932     char* fullname;
2933     int result;
2934 
2935     buffer[255]=0;
2936     if(!(appname && keyname && filename) )
2937     {
2938 	dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
2939 	return default_value;
2940     }
2941     fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2942     strcpy(fullname, "Software\\IniFileMapping\\");
2943     strcat(fullname, appname);
2944     strcat(fullname, "\\");
2945     strcat(fullname, keyname);
2946     strcat(fullname, "\\");
2947     strcat(fullname, filename);
2948     result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
2949     if((size>=0)&&(size<256))
2950 	buffer[size]=0;
2951     //    printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
2952     free(fullname);
2953     if(result)
2954 	result=default_value;
2955     else
2956 	result=atoi(buffer);
2957     dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
2958     return result;
2959 }
expGetProfileIntA(const char * appname,const char * keyname,int default_value)2960 static int WINAPI expGetProfileIntA(const char* appname,
2961 				    const char* keyname,
2962 				    int default_value)
2963 {
2964     dbgprintf("GetProfileIntA -> ");
2965     return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
2966 }
2967 
expGetPrivateProfileStringA(const char * appname,const char * keyname,const char * def_val,char * dest,unsigned int len,const char * filename)2968 static int WINAPI expGetPrivateProfileStringA(const char* appname,
2969 					      const char* keyname,
2970 					      const char* def_val,
2971 					      char* dest, unsigned int len,
2972 					      const char* filename)
2973 {
2974     int result;
2975     int size;
2976     char* fullname;
2977     dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
2978     if(!(appname && keyname && filename) ) return 0;
2979     fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2980     strcpy(fullname, "Software\\IniFileMapping\\");
2981     strcat(fullname, appname);
2982     strcat(fullname, "\\");
2983     strcat(fullname, keyname);
2984     strcat(fullname, "\\");
2985     strcat(fullname, filename);
2986     size=len;
2987     result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
2988     free(fullname);
2989     if(result)
2990     {
2991 	strncpy(dest, def_val, size);
2992 	if (strlen(def_val)< size) size = strlen(def_val);
2993     }
2994     dbgprintf(" => %d ( '%s' )\n", size, dest);
2995     return size;
2996 }
expWritePrivateProfileStringA(const char * appname,const char * keyname,const char * string,const char * filename)2997 static int WINAPI expWritePrivateProfileStringA(const char* appname,
2998 						const char* keyname,
2999 						const char* string,
3000 						const char* filename)
3001 {
3002     char* fullname;
3003     dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
3004     if(!(appname && keyname && filename) )
3005     {
3006 	dbgprintf(" => -1\n");
3007 	return -1;
3008     }
3009     fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
3010     strcpy(fullname, "Software\\IniFileMapping\\");
3011     strcat(fullname, appname);
3012     strcat(fullname, "\\");
3013     strcat(fullname, keyname);
3014     strcat(fullname, "\\");
3015     strcat(fullname, filename);
3016     RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
3017     //    printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
3018     //    printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
3019     free(fullname);
3020     dbgprintf(" => 0\n");
3021     return 0;
3022 }
3023 
GetPrivateProfileIntA_(const char * appname,const char * keyname,INT default_value,const char * filename)3024 unsigned int GetPrivateProfileIntA_(const char* appname, const char* keyname, INT default_value, const char* filename)
3025 {
3026     return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
3027 }
GetPrivateProfileStringA_(const char * appname,const char * keyname,const char * def_val,char * dest,unsigned int len,const char * filename)3028 int GetPrivateProfileStringA_(const char* appname, const char* keyname,
3029 			      const char* def_val, char* dest, unsigned int len, const char* filename)
3030 {
3031     return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
3032 }
WritePrivateProfileStringA_(const char * appname,const char * keyname,const char * string,const char * filename)3033 int WritePrivateProfileStringA_(const char* appname, const char* keyname,
3034 				const char* string, const char* filename)
3035 {
3036     return expWritePrivateProfileStringA(appname, keyname, string, filename);
3037 }
3038 
3039 
3040 
expDefDriverProc(int private,int id,int msg,int arg1,int arg2)3041 static int WINAPI expDefDriverProc(int private, int id, int msg, int arg1, int arg2)
3042 {
3043     dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", private, id, msg, arg1, arg2);
3044     return 0;
3045 }
3046 
expSizeofResource(int v1,int v2)3047 static int WINAPI expSizeofResource(int v1, int v2)
3048 {
3049     int result=SizeofResource(v1, v2);
3050     dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
3051     return result;
3052 }
3053 
expGetLastError(void)3054 static int WINAPI expGetLastError(void)
3055 {
3056     int result=GetLastError();
3057     dbgprintf("GetLastError() => 0x%x\n", result);
3058     return result;
3059 }
3060 
expSetLastError(int error)3061 static void WINAPI expSetLastError(int error)
3062 {
3063     dbgprintf("SetLastError(0x%x)\n", error);
3064     SetLastError(error);
3065 }
3066 
expStringFromGUID2(GUID * guid,char * str,int cbMax)3067 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
3068 {
3069     int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
3070 			guid->f1, guid->f2, guid->f3,
3071 			(unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
3072 			(unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
3073 			(unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
3074 			(unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
3075     dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
3076     return result;
3077 }
3078 
3079 
expGetFileVersionInfoSizeA(const char * name,int * lpHandle)3080 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
3081 {
3082     dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
3083     return 0;
3084 }
3085 
expIsBadStringPtrW(const short * string,int nchars)3086 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
3087 {
3088     int result;
3089     if(string==0)result=1; else result=0;
3090     dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
3091     if(string)wch_print(string);
3092     return result;
3093 }
expIsBadStringPtrA(const char * string,int nchars)3094 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
3095 {
3096     return expIsBadStringPtrW((const short*)string, nchars);
3097 }
expInterlockedExchangeAdd(long * dest,long incr)3098 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
3099 {
3100     long ret;
3101     __asm__ volatile
3102 	(
3103 	 "lock; xaddl %0,(%1)"
3104 	 : "=r" (ret)
3105 	 : "r" (dest), "0" (incr)
3106 	 : "memory"
3107 	);
3108     return ret;
3109 }
3110 
expInterlockedCompareExchange(unsigned long * dest,unsigned long exchange,unsigned long comperand)3111 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
3112 {
3113     unsigned long retval = *dest;
3114     if(*dest == comperand)
3115 	*dest = exchange;
3116     return retval;
3117 }
3118 
expInterlockedIncrement(long * dest)3119 static long WINAPI expInterlockedIncrement( long* dest )
3120 {
3121     long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
3122     dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
3123     return result;
3124 }
expInterlockedDecrement(long * dest)3125 static long WINAPI expInterlockedDecrement( long* dest )
3126 {
3127     long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
3128     dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
3129     return result;
3130 }
3131 
expOutputDebugStringA(const char * string)3132 static void WINAPI expOutputDebugStringA( const char* string )
3133 {
3134     dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
3135     fprintf(stderr, "DEBUG: %s\n", string);
3136 }
3137 
expGetDC(int hwnd)3138 static int WINAPI expGetDC(int hwnd)
3139 {
3140     dbgprintf("GetDC(0x%x) => 1\n", hwnd);
3141     return 1;
3142 }
3143 
expReleaseDC(int hwnd,int hdc)3144 static int WINAPI expReleaseDC(int hwnd, int hdc)
3145 {
3146     dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
3147     return 1;
3148 }
3149 
expGetDesktopWindow(void)3150 static int WINAPI expGetDesktopWindow(void)
3151 {
3152     dbgprintf("GetDesktopWindow() => 0\n");
3153     return 0;
3154 }
3155 
3156 static int cursor[100];
3157 
expLoadCursorA(int handle,LPCSTR name)3158 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
3159 {
3160     dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
3161     return (int)&cursor[0];
3162 }
expSetCursor(void * cursor)3163 static int WINAPI expSetCursor(void *cursor)
3164 {
3165     dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
3166     return (int)cursor;
3167 }
expGetCursorPos(void * cursor)3168 static int WINAPI expGetCursorPos(void *cursor)
3169 {
3170     dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
3171     return 1;
3172 }
3173 #ifdef CONFIG_QTX_CODECS
3174 static int show_cursor = 0;
expShowCursor(int show)3175 static int WINAPI expShowCursor(int show)
3176 {
3177     dbgprintf("ShowCursor(%d) => %d\n", show, show);
3178     if (show)
3179 	show_cursor++;
3180     else
3181 	show_cursor--;
3182     return show_cursor;
3183 }
3184 #endif
expRegisterWindowMessageA(char * message)3185 static int WINAPI expRegisterWindowMessageA(char *message)
3186 {
3187     dbgprintf("RegisterWindowMessageA(%s)\n", message);
3188     return 1;
3189 }
expGetProcessVersion(int pid)3190 static int WINAPI expGetProcessVersion(int pid)
3191 {
3192     dbgprintf("GetProcessVersion(%d)\n", pid);
3193     return 1;
3194 }
expGetCurrentThread(void)3195 static int WINAPI expGetCurrentThread(void)
3196 {
3197     /* FIXME! */
3198     dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
3199     return 0xcfcf9898;
3200 }
expGetOEMCP(void)3201 static int WINAPI expGetOEMCP(void)
3202 {
3203     dbgprintf("GetOEMCP()\n");
3204     return 1;
3205 }
expGetCPInfo(int cp,void * info)3206 static int WINAPI expGetCPInfo(int cp,void *info)
3207 {
3208     dbgprintf("GetCPInfo()\n");
3209     return 0;
3210 }
3211 #ifdef CONFIG_QTX_CODECS
3212 #define SM_CXSCREEN		0
3213 #define SM_CYSCREEN		1
3214 #define SM_XVIRTUALSCREEN	76
3215 #define SM_YVIRTUALSCREEN	77
3216 #define SM_CXVIRTUALSCREEN 	78
3217 #define SM_CYVIRTUALSCREEN	79
3218 #define SM_CMONITORS		80
3219 #endif
expGetSystemMetrics(int index)3220 static int WINAPI expGetSystemMetrics(int index)
3221 {
3222     dbgprintf("GetSystemMetrics(%d)\n", index);
3223 #ifdef CONFIG_QTX_CODECS
3224     switch(index)
3225     {
3226 	case SM_XVIRTUALSCREEN:
3227 	case SM_YVIRTUALSCREEN:
3228 	    return 0;
3229 	case SM_CXSCREEN:
3230 	case SM_CXVIRTUALSCREEN:
3231 	    return PSEUDO_SCREEN_WIDTH;
3232 	case SM_CYSCREEN:
3233 	case SM_CYVIRTUALSCREEN:
3234 	    return PSEUDO_SCREEN_HEIGHT;
3235 	case SM_CMONITORS:
3236 	    return 1;
3237     }
3238 #endif
3239     return 1;
3240 }
expGetSysColor(int index)3241 static int WINAPI expGetSysColor(int index)
3242 {
3243     dbgprintf("GetSysColor(%d) => 1\n", index);
3244     return 1;
3245 }
expGetSysColorBrush(int index)3246 static int WINAPI expGetSysColorBrush(int index)
3247 {
3248     dbgprintf("GetSysColorBrush(%d)\n", index);
3249     return 1;
3250 }
3251 
3252 
3253 
expGetSystemPaletteEntries(int hdc,int iStartIndex,int nEntries,void * lppe)3254 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
3255 {
3256     dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
3257 	      hdc, iStartIndex, nEntries, lppe);
3258     return 0;
3259 }
3260 
3261 /*
3262  typedef struct TIME_ZONE_INFORMATION {
3263  long Bias;
3264  char StandardName[32];
3265  SYSTEMTIME StandardDate;
3266  long StandardBias;
3267  char DaylightName[32];
3268  SYSTEMTIME DaylightDate;
3269  long DaylightBias;
3270  } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
3271  */
3272 
expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)3273 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
3274 {
3275     const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
3276     'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
3277     const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
3278     'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
3279     dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
3280     memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
3281     lpTimeZoneInformation->Bias=360;//GMT-6
3282     memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
3283     lpTimeZoneInformation->StandardDate.wMonth=10;
3284     lpTimeZoneInformation->StandardDate.wDay=5;
3285     lpTimeZoneInformation->StandardDate.wHour=2;
3286     lpTimeZoneInformation->StandardBias=0;
3287     memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
3288     lpTimeZoneInformation->DaylightDate.wMonth=4;
3289     lpTimeZoneInformation->DaylightDate.wDay=1;
3290     lpTimeZoneInformation->DaylightDate.wHour=2;
3291     lpTimeZoneInformation->DaylightBias=-60;
3292     return TIME_ZONE_ID_STANDARD;
3293 }
3294 
expGetLocalTime(SYSTEMTIME * systime)3295 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
3296 {
3297     time_t local_time;
3298     struct tm *local_tm;
3299     struct timeval tv;
3300 
3301     dbgprintf("GetLocalTime(0x%x)\n");
3302     gettimeofday(&tv, NULL);
3303     local_time=tv.tv_sec;
3304     local_tm=localtime(&local_time);
3305 
3306     systime->wYear = local_tm->tm_year + 1900;
3307     systime->wMonth = local_tm->tm_mon + 1;
3308     systime->wDayOfWeek = local_tm->tm_wday;
3309     systime->wDay = local_tm->tm_mday;
3310     systime->wHour = local_tm->tm_hour;
3311     systime->wMinute = local_tm->tm_min;
3312     systime->wSecond = local_tm->tm_sec;
3313     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3314     dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
3315 	      "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
3316 	      "  Milliseconds: %d\n",
3317 	      systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3318 	      systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3319 }
3320 
expGetSystemTime(SYSTEMTIME * systime)3321 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
3322 {
3323     time_t local_time;
3324     struct tm *local_tm;
3325     struct timeval tv;
3326 
3327     dbgprintf("GetSystemTime(0x%x)\n", systime);
3328     gettimeofday(&tv, NULL);
3329     local_time=tv.tv_sec;
3330     local_tm=gmtime(&local_time);
3331 
3332     systime->wYear = local_tm->tm_year + 1900;
3333     systime->wMonth = local_tm->tm_mon + 1;
3334     systime->wDayOfWeek = local_tm->tm_wday;
3335     systime->wDay = local_tm->tm_mday;
3336     systime->wHour = local_tm->tm_hour;
3337     systime->wMinute = local_tm->tm_min;
3338     systime->wSecond = local_tm->tm_sec;
3339     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3340     dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
3341 	      "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
3342 	      "  Milliseconds: %d\n",
3343 	      systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3344 	      systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3345     return 0;
3346 }
3347 
3348 #define SECS_1601_TO_1970  ((369 * 365 + 89) * 86400ULL)
expGetSystemTimeAsFileTime(FILETIME * systime)3349 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
3350 {
3351     struct timeval tv;
3352     unsigned long long secs;
3353 
3354     dbgprintf("GetSystemTime(0x%x)\n", systime);
3355     gettimeofday(&tv, NULL);
3356     secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
3357     secs += tv.tv_usec * 10;
3358     systime->dwLowDateTime = secs & 0xffffffff;
3359     systime->dwHighDateTime = (secs >> 32);
3360 }
3361 
expGetEnvironmentVariableA(const char * name,char * field,int size)3362 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
3363 {
3364     //char *p;
3365     //    printf("%s %x %x\n", name, field, size);
3366     if(field)field[0]=0;
3367     /*
3368      p = getenv(name);
3369      if (p) strncpy(field,p,size);
3370      */
3371     if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
3372 	strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
3373     dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
3374     return strlen(field);
3375 }
3376 
expSetEnvironmentVariableA(const char * name,const char * value)3377 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
3378 {
3379     dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
3380     return 0;
3381 }
3382 
expCoTaskMemAlloc(ULONG cb)3383 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
3384 {
3385     return my_mreq(cb, 0);
3386 }
expCoTaskMemFree(void * cb)3387 static void WINAPI expCoTaskMemFree(void* cb)
3388 {
3389     my_release(cb);
3390 }
3391 
3392 
3393 
3394 
CoTaskMemAlloc(unsigned long cb)3395 void* CoTaskMemAlloc(unsigned long cb)
3396 {
3397     return expCoTaskMemAlloc(cb);
3398 }
CoTaskMemFree(void * cb)3399 void CoTaskMemFree(void* cb)
3400 {
3401     expCoTaskMemFree(cb);
3402 }
3403 
3404 struct COM_OBJECT_INFO
3405 {
3406     GUID clsid;
3407     long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
3408 };
3409 
3410 static struct COM_OBJECT_INFO* com_object_table=0;
3411 static int com_object_size=0;
RegisterComClass(const GUID * clsid,GETCLASSOBJECT gcs)3412 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3413 {
3414     if(!clsid || !gcs)
3415 	return -1;
3416     com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
3417     com_object_table[com_object_size-1].clsid=*clsid;
3418     com_object_table[com_object_size-1].GetClassObject=gcs;
3419     return 0;
3420 }
3421 
UnregisterComClass(const GUID * clsid,GETCLASSOBJECT gcs)3422 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3423 {
3424     int found = 0;
3425     int i = 0;
3426     if(!clsid || !gcs)
3427 	return -1;
3428 
3429     if (com_object_table == 0)
3430 	printf("Warning: UnregisterComClass() called without any registered class\n");
3431     while (i < com_object_size)
3432     {
3433 	if (found && i > 0)
3434 	{
3435 	    memcpy(&com_object_table[i - 1].clsid,
3436 		   &com_object_table[i].clsid, sizeof(GUID));
3437 	    com_object_table[i - 1].GetClassObject =
3438 		com_object_table[i].GetClassObject;
3439 	}
3440 	else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
3441 		 && com_object_table[i].GetClassObject == gcs)
3442 	{
3443 	    found++;
3444 	}
3445 	i++;
3446     }
3447     if (found)
3448     {
3449 	if (--com_object_size == 0)
3450 	{
3451 	    free(com_object_table);
3452 	    com_object_table = 0;
3453 	}
3454     }
3455     return 0;
3456 }
3457 
3458 
3459 const GUID IID_IUnknown =
3460 {
3461     0x00000000, 0x0000, 0x0000,
3462     {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3463 };
3464 const GUID IID_IClassFactory =
3465 {
3466     0x00000001, 0x0000, 0x0000,
3467     {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3468 };
3469 
expCoCreateInstance(GUID * rclsid,struct IUnknown * pUnkOuter,long dwClsContext,const GUID * riid,void ** ppv)3470 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3471 				       long dwClsContext, const GUID* riid, void** ppv)
3472 {
3473     int i;
3474     struct COM_OBJECT_INFO* ci=0;
3475     for(i=0; i<com_object_size; i++)
3476 	if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
3477 	    ci=&com_object_table[i];
3478     if(!ci)return REGDB_E_CLASSNOTREG;
3479     // in 'real' world we should mess with IClassFactory here
3480     i=ci->GetClassObject(rclsid, riid, ppv);
3481     return i;
3482 }
3483 
CoCreateInstance(GUID * rclsid,struct IUnknown * pUnkOuter,long dwClsContext,const GUID * riid,void ** ppv)3484 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3485 		      long dwClsContext, const GUID* riid, void** ppv)
3486 {
3487     return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
3488 }
3489 
expIsRectEmpty(CONST RECT * lprc)3490 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
3491 {
3492     int r = 0;
3493     int w,h;
3494 //trapbug();
3495     if (lprc)
3496     {
3497 	w = lprc->right - lprc->left;
3498 	h = lprc->bottom - lprc->top;
3499 	if (w <= 0 || h <= 0)
3500 	    r = 1;
3501     }
3502     else
3503 	r = 1;
3504 
3505     dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
3506     //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
3507 //    return 0;	// wmv9?
3508     return r; // TM20
3509 }
3510 
3511 static int _adjust_fdiv=0; //what's this? - used to adjust division
3512 static int _winver = 0x510; // windows version
3513 
3514 
3515 
3516 
expGetTempPathA(unsigned int len,char * path)3517 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
3518 {
3519     dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
3520     if(len<5)
3521     {
3522 	dbgprintf(" => 0\n");
3523 	return 0;
3524     }
3525     strcpy(path, "/tmp");
3526     dbgprintf(" => 5 ( '/tmp' )\n");
3527     return 5;
3528 }
3529 /*
3530  FYI:
3531  typedef struct
3532  {
3533  DWORD     dwFileAttributes;
3534  FILETIME  ftCreationTime;
3535  FILETIME  ftLastAccessTime;
3536  FILETIME  ftLastWriteTime;
3537  DWORD     nFileSizeHigh;
3538  DWORD     nFileSizeLow;
3539  DWORD     dwReserved0;
3540  DWORD     dwReserved1;
3541  CHAR      cFileName[260];
3542  CHAR      cAlternateFileName[14];
3543  } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
3544  */
3545 
3546 static DIR* qtx_dir=NULL;
3547 
expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)3548 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
3549 {
3550 #ifdef CONFIG_QTX_CODECS
3551     dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
3552     if(h==FILE_HANDLE_quicktimeqtx){
3553 	struct dirent* d;
3554 	if(!qtx_dir) return 0;
3555 	while((d=readdir(qtx_dir))){
3556 	    char* x=strrchr(d->d_name,'.');
3557 	    if(!x) continue;
3558 	    if(strcmp(x,".qtx")) continue;
3559 	    strcpy(lpfd->cFileName,d->d_name);
3560 //	    sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
3561 	    strcpy(lpfd->cAlternateFileName,"foobar.qtx");
3562 	    dbgprintf("### FindNext: %s\n",lpfd->cFileName);
3563 	    return 1;
3564 	}
3565 	closedir(qtx_dir); qtx_dir=NULL;
3566 	return 0;
3567     }
3568 #endif
3569     return 0;
3570 }
3571 
expFindFirstFileA(LPCSTR s,LPWIN32_FIND_DATAA lpfd)3572 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
3573 {
3574     dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
3575 //    printf("\n### FindFirstFileA('%s')...\n",s);
3576 #ifdef CONFIG_QTX_CODECS
3577     if(strstr(s, "quicktime\\*.QTX")){
3578 	dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
3579 	dbgprintf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",
3580 	          codec_path);
3581 	qtx_dir = opendir(codec_path);
3582 	if(!qtx_dir) return (HANDLE)-1;
3583 	memset(lpfd,0,sizeof(*lpfd));
3584 	if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
3585 	    return FILE_HANDLE_quicktimeqtx;
3586 	printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",
3587 	       codec_path);
3588 	return (HANDLE)-1;
3589     }
3590 #if 0
3591     if(strstr(s, "QuickTime.qts")){
3592 	dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
3593 //	if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
3594 //	    return (HANDLE)-1;
3595 	strcpy(lpfd->cFileName, "QuickTime.qts");
3596 	strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
3597 	return FILE_HANDLE_quicktimeqts;
3598     }
3599 #endif
3600 #endif
3601     if(strstr(s, "*.vwp")){
3602 	// hack for VoxWare codec plugins:
3603 	strcpy(lpfd->cFileName, "msms001.vwp");
3604 	strcpy(lpfd->cAlternateFileName, "msms001.vwp");
3605 	return (HANDLE)0;
3606     }
3607     // return 'file not found'
3608     return (HANDLE)-1;
3609 }
3610 
expFindClose(HANDLE h)3611 static WIN_BOOL WINAPI expFindClose(HANDLE h)
3612 {
3613     dbgprintf("FindClose(0x%x) => 0\n", h);
3614 #ifdef CONFIG_QTX_CODECS
3615 //    if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
3616 //	closedir(qtx_dir);
3617 //	qtx_dir=NULL;
3618 //    }
3619 #endif
3620     return 0;
3621 }
expSetErrorMode(UINT i)3622 static UINT WINAPI expSetErrorMode(UINT i)
3623 {
3624     dbgprintf("SetErrorMode(%d) => 0\n", i);
3625     return 0;
3626 }
expGetWindowsDirectoryA(LPSTR s,UINT c)3627 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
3628 {
3629     char windir[]="c:\\windows";
3630     int result;
3631     strncpy(s, windir, c);
3632     result=1+((c<strlen(windir))?c:strlen(windir));
3633     dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
3634     return result;
3635 }
3636 #ifdef CONFIG_QTX_CODECS
expGetCurrentDirectoryA(UINT c,LPSTR s)3637 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
3638 {
3639     char curdir[]="c:\\";
3640     int result;
3641     strncpy(s, curdir, c);
3642     result=1+((c<strlen(curdir))?c:strlen(curdir));
3643     dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
3644     return result;
3645 }
3646 
expSetCurrentDirectoryA(const char * pathname)3647 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
3648 {
3649     dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
3650 #if 0
3651     if (strrchr(pathname, '\\'))
3652 	chdir(strcat(strrchr(pathname, '\\')+1, '/'));
3653     else
3654 	chdir(pathname);
3655 #endif
3656     return 1;
3657 }
3658 
expCreateDirectoryA(const char * pathname,void * sa)3659 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
3660 {
3661     dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
3662 	pathname, pathname, sa);
3663 #if 0
3664     p = strrchr(pathname, '\\')+1;
3665     strcpy(&buf[0], p); /* should be strncpy */
3666     if (!strlen(p))
3667     {
3668 	buf[0] = '.';
3669 	buf[1] = 0;
3670     }
3671 #if 0
3672     if (strrchr(pathname, '\\'))
3673 	mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
3674     else
3675 	mkdir(pathname, 666);
3676 #endif
3677     mkdir(&buf);
3678 #endif
3679     return 1;
3680 }
3681 #endif
expDeleteFileA(LPCSTR s)3682 static WIN_BOOL  WINAPI expDeleteFileA(LPCSTR s)
3683 {
3684     dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
3685     return 0;
3686 }
expFileTimeToLocalFileTime(const FILETIME * cpf,LPFILETIME pf)3687 static WIN_BOOL  WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
3688 {
3689     dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
3690     return 0;
3691 }
3692 
expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)3693 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
3694 {
3695     char mask[16]="/tmp/AP_XXXXXX";
3696     int result;
3697     dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
3698     if(i && i<10)
3699     {
3700 	dbgprintf(" => -1\n");
3701 	return -1;
3702     }
3703     result=mkstemp(mask);
3704     sprintf(ps, "AP%d", result);
3705     dbgprintf(" => %d\n", strlen(ps));
3706     return strlen(ps);
3707 }
3708 //
3709 // This func might need proper implementation if we want AngelPotion codec.
3710 // They try to open APmpeg4v1.apl with it.
3711 // DLL will close opened file with CloseHandle().
3712 //
expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,LPSECURITY_ATTRIBUTES p1,DWORD i3,DWORD i4,HANDLE i5)3713 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
3714 				    LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
3715 {
3716     dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
3717 	      i2, p1, i3, i4, i5);
3718     if((!cs1) || (strlen(cs1)<2))return -1;
3719 
3720 #ifdef CONFIG_QTX_CODECS
3721     if(strstr(cs1, "QuickTime.qts"))
3722     {
3723 	int result;
3724 	char* tmp = malloc(strlen(codec_path) + 50);
3725 	strcpy(tmp, codec_path);
3726 	strcat(tmp, "/");
3727 	strcat(tmp, "QuickTime.qts");
3728 	result=open(tmp, O_RDONLY);
3729 	free(tmp);
3730 	return result;
3731     }
3732     if(strstr(cs1, ".qtx"))
3733     {
3734 	int result;
3735 	char* tmp = malloc(strlen(codec_path) + 250);
3736 	char* x=strrchr(cs1,'\\');
3737 	sprintf(tmp, "%s/%s", codec_path, x ? (x + 1) : cs1);
3738 //	printf("### Open: %s -> %s\n",cs1,tmp);
3739 	result=open(tmp, O_RDONLY);
3740 	free(tmp);
3741 	return result;
3742     }
3743 #endif
3744 
3745     if(strncmp(cs1, "AP", 2) == 0)
3746     {
3747 	int result;
3748 	char* tmp = malloc(strlen(codec_path) + 50);
3749 	strcpy(tmp, codec_path);
3750 	strcat(tmp, "/");
3751 	strcat(tmp, "APmpg4v1.apl");
3752 	result=open(tmp, O_RDONLY);
3753 	free(tmp);
3754 	return result;
3755     }
3756     if (strstr(cs1, "vp3") || strstr(cs1, ".fpf") || strstr(cs1, ".col"))
3757     {
3758 	int r;
3759 	int flg = 0;
3760 	char* tmp=malloc(20 + strlen(cs1));
3761 	strcpy(tmp, "/tmp/");
3762 	strcat(tmp, cs1);
3763 	r = 4;
3764 	while (tmp[r])
3765 	{
3766 	    if (tmp[r] == ':' || tmp[r] == '\\')
3767 		tmp[r] = '_';
3768 	    r++;
3769 	}
3770 	if (GENERIC_READ & i1)
3771 	    flg |= O_RDONLY;
3772 	else if (GENERIC_WRITE & i1)
3773 	{
3774 	    flg |= O_WRONLY | O_CREAT;
3775 	    printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", tmp, r, flg);
3776 	}
3777 	r=open(tmp, flg, S_IRWXU);
3778 	free(tmp);
3779 	return r;
3780     }
3781 
3782     // Needed by wnvplay1.dll
3783     if (strstr(cs1, "WINNOV.bmp"))
3784     {
3785 	int r;
3786 	r=open("/dev/null", O_RDONLY);
3787 	return r;
3788     }
3789 
3790 #if 0
3791     /* we need this for some virtualdub filters */
3792     {
3793 	int r;
3794 	int flg = 0;
3795 	if (GENERIC_READ & i1)
3796 	    flg |= O_RDONLY;
3797 	else if (GENERIC_WRITE & i1)
3798 	{
3799 	    flg |= O_WRONLY;
3800 	    printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", cs1, r, flg);
3801 	}
3802 	r=open(cs1, flg);
3803 	return r;
3804     }
3805 #endif
3806 
3807     return atoi(cs1+2);
3808 }
expGetSystemDirectoryA(char * lpBuffer,UINT uSize)3809 static UINT WINAPI expGetSystemDirectoryA(
3810   char* lpBuffer,  // address of buffer for system directory
3811   UINT uSize        // size of directory buffer
3812 ){
3813     dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
3814     if(!lpBuffer) strcpy(lpBuffer,".");
3815     return 1;
3816 }
3817 /*
3818 static char sysdir[]=".";
3819 static LPCSTR WINAPI expGetSystemDirectoryA(void)
3820 {
3821     dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
3822     return sysdir;
3823 }
3824 */
expGetFullPathNameA(LPCTSTR lpFileName,DWORD nBufferLength,LPTSTR lpBuffer,LPTSTR lpFilePart)3825 static DWORD WINAPI expGetFullPathNameA
3826 (
3827 	LPCTSTR lpFileName,
3828 	DWORD nBufferLength,
3829 	LPTSTR lpBuffer,
3830 	LPTSTR lpFilePart
3831 ){
3832     if(!lpFileName) return 0;
3833     dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
3834 	lpBuffer, lpFilePart);
3835 #if 0
3836 #ifdef CONFIG_QTX_CODECS
3837     strcpy(lpFilePart, "Quick123.qts");
3838 #else
3839     strcpy(lpFilePart, lpFileName);
3840 #endif
3841 #else
3842     if (strrchr(lpFileName, '\\'))
3843 	lpFilePart = strrchr(lpFileName, '\\');
3844     else
3845 	lpFilePart = (LPTSTR)lpFileName;
3846 #endif
3847     strcpy(lpBuffer, lpFileName);
3848 //    strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
3849     return strlen(lpBuffer);
3850 }
3851 
expGetShortPathNameA(LPCSTR longpath,LPSTR shortpath,DWORD shortlen)3852 static DWORD WINAPI expGetShortPathNameA
3853 (
3854         LPCSTR longpath,
3855         LPSTR shortpath,
3856         DWORD shortlen
3857 ){
3858     if(!longpath) return 0;
3859     dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
3860     strcpy(shortpath,longpath);
3861     return strlen(shortpath);
3862 }
3863 
expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)3864 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
3865 {
3866     int result;
3867     dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
3868     result=read(h, pv, size);
3869     if(rd)*rd=result;
3870     if(!result)return 0;
3871     return 1;
3872 }
3873 
expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)3874 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
3875 {
3876     int result;
3877     dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
3878     if(h==1234)h=1;
3879     result=write(h, pv, size);
3880     if(wr)*wr=result;
3881     if(!result)return 0;
3882     return 1;
3883 }
expSetFilePointer(HANDLE h,LONG val,LPLONG ext,DWORD whence)3884 static DWORD  WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
3885 {
3886     int wh;
3887     dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, ext ? *ext : 0, whence);
3888     //why would DLL want temporary file with >2Gb size?
3889     switch(whence)
3890     {
3891     case FILE_BEGIN:
3892 	wh=SEEK_SET;break;
3893     case FILE_END:
3894 	wh=SEEK_END;break;
3895     case FILE_CURRENT:
3896 	wh=SEEK_CUR;break;
3897     default:
3898 	return -1;
3899     }
3900 #ifdef CONFIG_QTX_CODECS
3901     if (val == 0 && ext != 0)
3902 	val = val&(*ext);
3903 #endif
3904     return lseek(h, val, wh);
3905 }
3906 
expOpenDriverA(LPCSTR szDriverName,LPCSTR szSectionName,LPARAM lParam2)3907 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
3908 				   LPARAM lParam2)
3909 {
3910     dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName,  szDriverName, szSectionName, szSectionName, lParam2);
3911     return -1;
3912 }
expOpenDriver(LPCSTR szDriverName,LPCSTR szSectionName,LPARAM lParam2)3913 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
3914 				  LPARAM lParam2)
3915 {
3916     dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3917     return -1;
3918 }
3919 
3920 
expGetProcessAffinityMask(HANDLE hProcess,LPDWORD lpProcessAffinityMask,LPDWORD lpSystemAffinityMask)3921 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
3922 						 LPDWORD lpProcessAffinityMask,
3923 						 LPDWORD lpSystemAffinityMask)
3924 {
3925     dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
3926 	      hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
3927     if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
3928     if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
3929     return 1;
3930 }
3931 
3932 // Fake implementation: does nothing, but does it right :)
expSetProcessAffinityMask(HANDLE hProcess,LPDWORD dwProcessAffinityMask)3933 static WIN_BOOL WINAPI expSetProcessAffinityMask(HANDLE hProcess,
3934                                               LPDWORD dwProcessAffinityMask)
3935 {
3936     dbgprintf("SetProcessAffinityMask(0x%x, 0x%x) => 1\n",
3937 	      hProcess, dwProcessAffinityMask);
3938 
3939     return 1;
3940 };
3941 
expMulDiv(int nNumber,int nNumerator,int nDenominator)3942 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
3943 {
3944     static const long long max_int=0x7FFFFFFFLL;
3945     static const long long min_int=-0x80000000LL;
3946     long long tmp=(long long)nNumber*(long long)nNumerator;
3947     dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
3948     if(!nDenominator)return 1;
3949     tmp/=nDenominator;
3950     if(tmp<min_int) return 1;
3951     if(tmp>max_int) return 1;
3952     return (int)tmp;
3953 }
3954 
explstrcmpiA(const char * str1,const char * str2)3955 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
3956 {
3957     LONG result=av_strcasecmp(str1, str2);
3958     dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
3959     return result;
3960 }
3961 
explstrlenA(const char * str1)3962 static LONG WINAPI explstrlenA(const char* str1)
3963 {
3964     LONG result=strlen(str1);
3965     dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
3966     return result;
3967 }
3968 
explstrlenW(const uint16_t * s)3969 static LONG WINAPI explstrlenW(const uint16_t* s)
3970 {
3971     int result = 0;
3972     while (s && s[result]) result++;
3973     return result;
3974 }
3975 
explstrcpyA(char * str1,const char * str2)3976 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
3977 {
3978     int result= (int) strcpy(str1, str2);
3979     dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
3980     return result;
3981 }
explstrcpynA(char * str1,const char * str2,int len)3982 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
3983 {
3984     int result;
3985     if (strlen(str2)>len)
3986 	result = (int) strncpy(str1, str2,len);
3987     else
3988 	result = (int) strcpy(str1,str2);
3989     dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
3990     return result;
3991 }
explstrcatA(char * str1,const char * str2)3992 static LONG WINAPI explstrcatA(char* str1, const char* str2)
3993 {
3994     int result= (int) strcat(str1, str2);
3995     dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
3996     return result;
3997 }
3998 
3999 
expInterlockedExchange(long * dest,long l)4000 static LONG WINAPI expInterlockedExchange(long *dest, long l)
4001 {
4002     long retval = *dest;
4003     *dest = l;
4004     return retval;
4005 }
4006 
expInitCommonControls(void)4007 static void WINAPI expInitCommonControls(void)
4008 {
4009     dbgprintf("InitCommonControls called!\n");
4010     return;
4011 }
4012 
4013 #ifdef CONFIG_QTX_CODECS
4014 /* needed by QuickTime.qts */
expCreateUpDownControl(DWORD style,INT x,INT y,INT cx,INT cy,HWND parent,INT id,HINSTANCE inst,HWND buddy,INT maxVal,INT minVal,INT curVal)4015 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
4016 	      HWND parent, INT id, HINSTANCE inst,
4017               HWND buddy, INT maxVal, INT minVal, INT curVal)
4018 {
4019     dbgprintf("CreateUpDownControl(...)\n");
4020     return 0;
4021 }
4022 #endif
4023 
4024 /* alex: implement this call! needed for 3ivx */
expCoCreateFreeThreadedMarshaler(void * pUnkOuter,void ** ppUnkInner)4025 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
4026 {
4027     dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
4028 	   pUnkOuter, ppUnkInner);
4029 //    return 0;
4030     return ERROR_CALL_NOT_IMPLEMENTED;
4031 }
4032 
4033 
expDuplicateHandle(HANDLE hSourceProcessHandle,HANDLE hSourceHandle,HANDLE hTargetProcessHandle,HANDLE * lpTargetHandle,DWORD dwDesiredAccess,int bInheritHandle,DWORD dwOptions)4034 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle,  // handle to source process
4035 				     HANDLE hSourceHandle,         // handle to duplicate
4036 				     HANDLE hTargetProcessHandle,  // handle to target process
4037 				     HANDLE* lpTargetHandle,      // duplicate handle
4038 				     DWORD dwDesiredAccess,        // requested access
4039 				     int bInheritHandle,          // handle inheritance option
4040 				     DWORD dwOptions               // optional actions
4041 				    )
4042 {
4043     dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
4044 	      hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
4045 	      lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
4046     *lpTargetHandle = hSourceHandle;
4047     return 1;
4048 }
4049 
expCoInitializeEx(LPVOID lpReserved,DWORD dwCoInit)4050 static HRESULT WINAPI expCoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
4051 {
4052     dbgprintf("CoInitializeEx(%p, %d) called\n", lpReserved, dwCoInit);
4053     return S_OK;
4054 }
4055 
4056 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
expCoInitialize(LPVOID lpReserved)4057 static HRESULT WINAPI expCoInitialize(
4058 				      LPVOID lpReserved	/* [in] pointer to win32 malloc interface
4059 				      (obsolete, should be NULL) */
4060 				     )
4061 {
4062     /*
4063      * Just delegate to the newer method.
4064      */
4065     return expCoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
4066 }
4067 
expCoUninitialize(void)4068 static void WINAPI expCoUninitialize(void)
4069 {
4070     dbgprintf("CoUninitialize() called\n");
4071 }
4072 
4073 /* allow static linking */
CoInitializeEx(LPVOID lpReserved,DWORD dwCoInit)4074 HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
4075 {
4076     return expCoInitializeEx(lpReserved, dwCoInit);
4077 }
CoInitialize(LPVOID lpReserved)4078 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
4079 {
4080     return expCoInitialize(lpReserved);
4081 }
CoUninitialize(void)4082 void WINAPI CoUninitialize(void)
4083 {
4084     expCoUninitialize();
4085 }
4086 
expSetThreadAffinityMask(HANDLE hThread,DWORD dwThreadAffinityMask)4087 static DWORD WINAPI expSetThreadAffinityMask
4088 (
4089         HANDLE hThread,
4090         DWORD dwThreadAffinityMask
4091 ){
4092     return 0;
4093 };
4094 
4095 /*
4096  * no WINAPI functions - CDECL
4097  */
expmalloc(int size)4098 static void* expmalloc(int size)
4099 {
4100     //printf("malloc");
4101     //    return malloc(size);
4102     void* result=my_mreq(size,0);
4103     dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
4104     if(result==0)
4105 	printf("WARNING: malloc() failed\n");
4106     return result;
4107 }
expfree(void * mem)4108 static void expfree(void* mem)
4109 {
4110     //    return free(mem);
4111     dbgprintf("free(%p)\n", mem);
4112     my_release(mem);
4113 }
4114 /* needed by atrac3.acm */
expcalloc(int num,int size)4115 static void *expcalloc(int num, int size)
4116 {
4117     void* result=my_mreq(num*size,1);
4118     dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
4119     if(result==0)
4120 	printf("WARNING: calloc() failed\n");
4121     return result;
4122 }
expnew(int size)4123 static void* expnew(int size)
4124 {
4125     //    printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
4126     //    printf("%08x %08x %08x %08x\n",
4127     //    size, *(1+(int*)&size),
4128     //    *(2+(int*)&size),*(3+(int*)&size));
4129     void* result;
4130     assert(size >= 0);
4131 
4132     result=my_mreq(size,0);
4133     dbgprintf("new(%d) => %p\n", size, result);
4134     if (result==0)
4135 	printf("WARNING: new() failed\n");
4136     return result;
4137 
4138 }
expdelete(void * memory)4139 static int expdelete(void* memory)
4140 {
4141     dbgprintf("delete(%p)\n", memory);
4142     my_release(memory);
4143     return 0;
4144 }
4145 
4146 /*
4147  * local definition - we need only the last two members at this point
4148  * otherwice we would have to introduce here GUIDs and some more types..
4149  */
4150 typedef struct __attribute__((__packed__))
4151 {
4152     char hay[0x40];
4153     unsigned long cbFormat;		//0x40
4154     char*	pbFormat;		//0x44
4155 } MY_MEDIA_TYPE;
expMoCopyMediaType(MY_MEDIA_TYPE * dest,const MY_MEDIA_TYPE * src)4156 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
4157 {
4158     if (!dest || !src)
4159 	return E_POINTER;
4160     memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
4161     if (dest->cbFormat)
4162     {
4163 	dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
4164 	if (!dest->pbFormat)
4165             return E_OUTOFMEMORY;
4166 	memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
4167     }
4168     return S_OK;
4169 }
expMoInitMediaType(MY_MEDIA_TYPE * dest,DWORD cbFormat)4170 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
4171 {
4172     if (!dest)
4173         return E_POINTER;
4174     memset(dest, 0, sizeof(MY_MEDIA_TYPE));
4175     if (cbFormat)
4176     {
4177 	dest->pbFormat = (char*) my_mreq(cbFormat, 0);
4178 	if (!dest->pbFormat)
4179             return E_OUTOFMEMORY;
4180     }
4181     return S_OK;
4182 }
expMoCreateMediaType(MY_MEDIA_TYPE ** dest,DWORD cbFormat)4183 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
4184 {
4185     if (!dest)
4186 	return E_POINTER;
4187     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
4188     return expMoInitMediaType(*dest, cbFormat);
4189 }
expMoDuplicateMediaType(MY_MEDIA_TYPE ** dest,const void * src)4190 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
4191 {
4192     if (!dest)
4193 	return E_POINTER;
4194     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
4195     return expMoCopyMediaType(*dest, src);
4196 }
expMoFreeMediaType(MY_MEDIA_TYPE * dest)4197 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
4198 {
4199     if (!dest)
4200 	return E_POINTER;
4201     if (dest->pbFormat)
4202     {
4203 	my_release(dest->pbFormat);
4204 	dest->pbFormat = 0;
4205         dest->cbFormat = 0;
4206     }
4207     return S_OK;
4208 }
expMoDeleteMediaType(MY_MEDIA_TYPE * dest)4209 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
4210 {
4211     if (!dest)
4212 	return E_POINTER;
4213     expMoFreeMediaType(dest);
4214     my_release(dest);
4215     return S_OK;
4216 }
4217 
exp_snprintf(char * str,int size,const char * format,...)4218 static int exp_snprintf( char *str, int size, const char *format, ... )
4219 {
4220       int x;
4221       va_list va;
4222       va_start(va, format);
4223       x=snprintf(str,size,format,va);
4224       dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
4225       va_end(va);
4226       return x;
4227 }
4228 
4229 #if 0
4230 static int exp_initterm(int v1, int v2)
4231 {
4232     dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
4233     return 0;
4234 }
4235 #else
4236 /* merged from wine - 2002.04.21 */
4237 typedef void (*INITTERMFUNC)();
exp_initterm(INITTERMFUNC * start,INITTERMFUNC * end)4238 static int exp_initterm(INITTERMFUNC *start, INITTERMFUNC *end)
4239 {
4240     dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
4241     while (start < end)
4242     {
4243 	if (*start)
4244 	{
4245 	    //printf("call _initfunc: from: %p %d\n", *start);
4246 	    // ok this trick with push/pop is necessary as otherwice
4247 	    // edi/esi registers are being trashed
4248 	    void* p = *start;
4249 	    __asm__ volatile
4250 		(
4251 		 "pushl %%ebx		\n\t"
4252 		 "pushl %%ecx		\n\t"
4253 		 "pushl %%edx		\n\t"
4254 		 "pushl %%edi		\n\t"
4255 		 "pushl %%esi		\n\t"
4256 		 "call  *%%eax		\n\t"
4257 		 "popl  %%esi		\n\t"
4258 		 "popl  %%edi		\n\t"
4259 		 "popl  %%edx		\n\t"
4260 		 "popl  %%ecx		\n\t"
4261 		 "popl  %%ebx		\n\t"
4262 		 :
4263 		 : "a"(p)
4264 		 : "memory"
4265 		);
4266             //printf("done  %p  %d:%d\n", end);
4267 	}
4268 	start++;
4269     }
4270     return 0;
4271 }
4272 #endif
4273 
4274 /* Fake _initterm_e from msvcr80.dll, needed by sirenacm.dll
4275  * NOTE: If I make this an alias for _initterm, then sirenacm.dll tries to call
4276    other uninmplemented functions; keep this in mind if some future codec needs
4277    a real implementation of this function */
exp_initterm_e(INITTERMFUNC * start,INITTERMFUNC * end)4278 static int exp_initterm_e(INITTERMFUNC *start, INITTERMFUNC *end)
4279 {
4280     dbgprintf("_initterm_e(0x%x, 0x%x)\n", start, end);
4281     return 0;
4282 }
4283 
exp__dllonexit(void)4284 static void* exp__dllonexit(void)
4285 {
4286     // FIXME extract from WINE
4287     return NULL;
4288 }
4289 
expwsprintfA(char * string,const char * format,...)4290 static int expwsprintfA(char* string, const char* format, ...)
4291 {
4292     va_list va;
4293     int result;
4294     va_start(va, format);
4295     result = vsprintf(string, format, va);
4296     dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4297     va_end(va);
4298     return result;
4299 }
4300 
expsprintf(char * str,const char * format,...)4301 static int expsprintf(char* str, const char* format, ...)
4302 {
4303     va_list args;
4304     int r;
4305     dbgprintf("sprintf(0x%x, %s)\n", str, format);
4306     va_start(args, format);
4307     r = vsprintf(str, format, args);
4308     va_end(args);
4309     return r;
4310 }
expsscanf(const char * str,const char * format,...)4311 static int expsscanf(const char* str, const char* format, ...)
4312 {
4313     va_list args;
4314     int r;
4315     dbgprintf("sscanf(%s, %s)\n", str, format);
4316     va_start(args, format);
4317     r = vsscanf(str, format, args);
4318     va_end(args);
4319     return r;
4320 }
expfopen(const char * path,const char * mode)4321 static void* expfopen(const char* path, const char* mode)
4322 {
4323     printf("fopen: \"%s\"  mode:%s\n", path, mode);
4324     if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0)
4325         return NULL;
4326     //return fopen(path, mode);
4327     return fdopen(0, mode); // everything on screen
4328 }
expfprintf(void * stream,const char * format,...)4329 static int expfprintf(void* stream, const char* format, ...)
4330 {
4331     va_list args;
4332     int r = 0;
4333     dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4334     va_start(args, format);
4335     r = vfprintf((FILE*) stream, format, args);
4336     va_end(args);
4337     return r;
4338 }
4339 
expprintf(const char * format,...)4340 static int expprintf(const char* format, ...)
4341 {
4342     va_list args;
4343     int r;
4344     dbgprintf("printf(%s, ...)\n", format);
4345     va_start(args, format);
4346     r = vprintf(format, args);
4347     va_end(args);
4348     return r;
4349 }
4350 
expgetenv(const char * varname)4351 static char* expgetenv(const char* varname)
4352 {
4353     char* v = getenv(varname);
4354     dbgprintf("getenv(%s) => %s\n", varname, v);
4355     return v;
4356 }
4357 
expwcscpy(WCHAR * dst,const WCHAR * src)4358 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4359 {
4360     WCHAR* p = dst;
4361     while ((*p++ = *src++))
4362 	;
4363     return dst;
4364 }
4365 
expstrrchr(char * string,int value)4366 static char* expstrrchr(char* string, int value)
4367 {
4368     char* result=strrchr(string, value);
4369     if(result)
4370 	dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4371     else
4372 	dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4373     return result;
4374 }
4375 
expstrchr(char * string,int value)4376 static char* expstrchr(char* string, int value)
4377 {
4378     char* result=strchr(string, value);
4379     if(result)
4380 	dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4381     else
4382 	dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4383     return result;
4384 }
expstrlen(char * str)4385 static int expstrlen(char* str)
4386 {
4387     int result=strlen(str);
4388     dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4389     return result;
4390 }
expstrcpy(char * str1,const char * str2)4391 static char* expstrcpy(char* str1, const char* str2)
4392 {
4393     char* result= strcpy(str1, str2);
4394     dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4395     return result;
4396 }
expstrncpy(char * str1,const char * str2,size_t count)4397 static char* expstrncpy(char* str1, const char* str2, size_t count)
4398 {
4399     char* result= strncpy(str1, str2, count);
4400     dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4401     return result;
4402 }
expstrcmp(const char * str1,const char * str2)4403 static int expstrcmp(const char* str1, const char* str2)
4404 {
4405     int result=strcmp(str1, str2);
4406     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4407     return result;
4408 }
expstrncmp(const char * str1,const char * str2,int x)4409 static int expstrncmp(const char* str1, const char* str2,int x)
4410 {
4411     int result=strncmp(str1, str2,x);
4412     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4413     return result;
4414 }
expstrcat(char * str1,const char * str2)4415 static char* expstrcat(char* str1, const char* str2)
4416 {
4417     char* result = strcat(str1, str2);
4418     dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4419     return result;
4420 }
exp_strdup(const char * str1)4421 static char* exp_strdup(const char* str1)
4422 {
4423     int l = strlen(str1);
4424     char* result = (char*) my_mreq(l + 1,0);
4425     if (result)
4426 	strcpy(result, str1);
4427     dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4428     return result;
4429 }
expisalnum(int c)4430 static int expisalnum(int c)
4431 {
4432     int result= (int) isalnum(c);
4433     dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4434     return result;
4435 }
expisspace(int c)4436 static int expisspace(int c)
4437 {
4438     int result= (int) isspace(c);
4439     dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4440     return result;
4441 }
expisalpha(int c)4442 static int expisalpha(int c)
4443 {
4444     int result= (int) isalpha(c);
4445     dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4446     return result;
4447 }
expisdigit(int c)4448 static int expisdigit(int c)
4449 {
4450     int result= (int) isdigit(c);
4451     dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4452     return result;
4453 }
expmemmove(void * dest,void * src,int n)4454 static void* expmemmove(void* dest, void* src, int n)
4455 {
4456     void* result = memmove(dest, src, n);
4457     dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4458     return result;
4459 }
expmemcmp(void * dest,void * src,int n)4460 static int expmemcmp(void* dest, void* src, int n)
4461 {
4462     int result = memcmp(dest, src, n);
4463     dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4464     return result;
4465 }
expmemcpy(void * dest,void * src,int n)4466 static void* expmemcpy(void* dest, void* src, int n)
4467 {
4468     void *result = memcpy(dest, src, n);
4469     dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4470     return result;
4471 }
expmemset(void * dest,int c,size_t n)4472 static void* expmemset(void* dest, int c, size_t n)
4473 {
4474     void *result = memset(dest, c, n);
4475     dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4476     return result;
4477 }
exptime(time_t * t)4478 static time_t exptime(time_t* t)
4479 {
4480     time_t result = time(t);
4481     dbgprintf("time(0x%x) => %d\n", t, result);
4482     return result;
4483 }
4484 
exprand(void)4485 static int exprand(void)
4486 {
4487     return rand();
4488 }
4489 
expsrand(int seed)4490 static void expsrand(int seed)
4491 {
4492     srand(seed);
4493 }
4494 
4495 #if 1
4496 
4497 // preferred compilation with  -O2 -ffast-math !
4498 
explog10(double x)4499 static double explog10(double x)
4500 {
4501     /*printf("Log10 %f => %f    0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4502     return log10(x);
4503 }
4504 
expcos(double x)4505 static double expcos(double x)
4506 {
4507     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4508     return cos(x);
4509 }
4510 
4511 #else
4512 
explog10(void)4513 static void explog10(void)
4514 {
4515     __asm__ volatile
4516 	(
4517 	 "fldl 8(%esp)	\n\t"
4518 	 "fldln2	\n\t"
4519 	 "fxch %st(1)	\n\t"
4520 	 "fyl2x		\n\t"
4521 	);
4522 }
4523 
expcos(void)4524 static void expcos(void)
4525 {
4526     __asm__ volatile
4527 	(
4528 	 "fldl 8(%esp)	\n\t"
4529 	 "fcos		\n\t"
4530 	);
4531 }
4532 
4533 #endif
4534 
4535 // this seem to be the only how to make this function working properly
4536 // ok - I've spent tremendous amount of time (many many many hours
4537 // of debuging fixing & testing - it's almost unimaginable - kabi
4538 
4539 // _ftol - operated on the float value which is already on the FPU stack
4540 
exp_ftol(void)4541 static void exp_ftol(void)
4542 {
4543     __asm__ volatile
4544 	(
4545 	 "sub $12, %esp		\n\t"
4546 	 "fstcw   -2(%ebp)	\n\t"
4547 	 "wait			\n\t"
4548 	 "movw	  -2(%ebp), %ax	\n\t"
4549 	 "orb	 $0x0C, %ah	\n\t"
4550 	 "movw    %ax, -4(%ebp)	\n\t"
4551 	 "fldcw   -4(%ebp)	\n\t"
4552 	 "fistpl -12(%ebp)	\n\t"
4553 	 "fldcw   -2(%ebp)	\n\t"
4554 	 "movl	 -12(%ebp), %eax \n\t"
4555 	 //Note: gcc 3.03 does not do the following op if it
4556 	 //      knows that ebp=esp
4557 	 "movl %ebp, %esp       \n\t"
4558 	);
4559 }
4560 
4561 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4562   __asm__ volatile( "fstpl %0;fwait" : "=m" (var2) : ); \
4563   __asm__ volatile( "fstpl %0;fwait" : "=m" (var1) : )
4564 
exp_CIpow(void)4565 static double exp_CIpow(void)
4566 {
4567     FPU_DOUBLES(x,y);
4568 
4569     dbgprintf("_CIpow(%f, %f)\n", x, y);
4570     return pow(x, y);
4571 }
4572 
exppow(double x,double y)4573 static double exppow(double x, double y)
4574 {
4575     /*printf("Pow %f  %f    0x%Lx  0x%Lx  => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4576     return pow(x, y);
4577 }
4578 
expldexp(double x,int expo)4579 static double expldexp(double x, int expo)
4580 {
4581     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4582     return ldexp(x, expo);
4583 }
4584 
expfrexp(double x,int * expo)4585 static double expfrexp(double x, int* expo)
4586 {
4587     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4588     return frexp(x, expo);
4589 }
4590 
4591 
exp_splitpath(const char * path,char * drive,char * dir,char * name,char * ext)4592 static void exp_splitpath(const char *path, char *drive, char *dir, char *name, char *ext)
4593 {
4594     const char *ext_start = strrchr(path, '.');
4595     int name_len = ext_start ? ext_start - path : strlen(path);
4596     if (drive)
4597         strcpy(drive, "");
4598     if (dir)
4599         strcpy(dir, "");
4600     if (name) {
4601         strncpy(name, path, name_len);
4602         name[name_len] = 0;
4603     }
4604     if (ext)
4605         strcpy(ext, ext_start ? ext_start : "");
4606 }
4607 
exp_mbsupr(char * str)4608 static char *exp_mbsupr(char *str)
4609 {
4610     int i;
4611     for (i = 0; str[i]; i++) str[i] = toupper(str[i]);
4612     return str;
4613 }
4614 
exp_stricmp(const char * s1,const char * s2)4615 static int exp_stricmp(const char* s1, const char* s2)
4616 {
4617     return av_strcasecmp(s1, s2);
4618 }
4619 
exp_time64(void)4620 static uint64_t exp_time64(void)
4621 {
4622     return 0;
4623 }
4624 
4625 /* from declaration taken from Wine sources - this fountion seems to be
4626  * undocumented in any M$ doc */
exp_setjmp3(void * jmpbuf,int x)4627 static int exp_setjmp3(void* jmpbuf, int x)
4628 {
4629     //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4630     //return 0;
4631     __asm__ volatile
4632 	(
4633 	 //"mov 4(%%esp), %%edx	\n\t"
4634 	 "mov (%%esp), %%eax   \n\t"
4635 	 "mov %%eax, (%%edx)	\n\t" // store ebp
4636 
4637 	 //"mov %%ebp, (%%edx)	\n\t"
4638 	 "mov %%ebx, 4(%%edx)	\n\t"
4639 	 "mov %%edi, 8(%%edx)	\n\t"
4640 	 "mov %%esi, 12(%%edx)	\n\t"
4641 	 "mov %%esp, 16(%%edx)	\n\t"
4642 
4643 	 "mov 4(%%esp), %%eax	\n\t"
4644 	 "mov %%eax, 20(%%edx)	\n\t"
4645 
4646 	 "movl $0x56433230, 32(%%edx)	\n\t" // VC20 ??
4647 	 "movl $0, 36(%%edx)	\n\t"
4648 	 : // output
4649 	 : "d"(jmpbuf) // input
4650 	 : "eax"
4651 	);
4652     __asm__ volatile
4653 	(
4654 	 "mov %%fs:0, %%eax	\n\t" // unsure
4655 	 "mov %%eax, 24(%%edx)	\n\t"
4656 	 "cmp $0xffffffff, %%eax \n\t"
4657 	 "jnz l1                \n\t"
4658 	 "mov %%eax, 28(%%edx)	\n\t"
4659 	 "l1:                   \n\t"
4660 	 :
4661 	 :
4662 	 : "eax"
4663 	);
4664 
4665 	return 0;
4666 }
4667 
expGetCurrentProcessId(void)4668 static DWORD WINAPI expGetCurrentProcessId(void)
4669 {
4670     dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4671     return getpid(); //(DWORD)NtCurrentTeb()->pid;
4672 }
4673 
4674 
4675 typedef struct {
4676     UINT	wPeriodMin;
4677     UINT	wPeriodMax;
4678 } TIMECAPS, *LPTIMECAPS;
4679 
exptimeGetDevCaps(LPTIMECAPS lpCaps,UINT wSize)4680 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4681 {
4682     dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4683 
4684     lpCaps->wPeriodMin = 1;
4685     lpCaps->wPeriodMax = 65535;
4686     return 0;
4687 }
4688 
exptimeBeginPeriod(UINT wPeriod)4689 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4690 {
4691     dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4692 
4693     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4694     return 0;
4695 }
4696 
4697 #ifdef CONFIG_QTX_CODECS
exptimeEndPeriod(UINT wPeriod)4698 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4699 {
4700     dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4701 
4702     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4703     return 0;
4704 }
4705 #endif
4706 
expGlobalMemoryStatus(LPMEMORYSTATUS lpmem)4707 static void WINAPI expGlobalMemoryStatus(
4708             LPMEMORYSTATUS lpmem
4709 ) {
4710     static MEMORYSTATUS	cached_memstatus;
4711     static int cache_lastchecked = 0;
4712     SYSTEM_INFO si;
4713     FILE *f;
4714 
4715     if (time(NULL)==cache_lastchecked) {
4716 	memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4717 	return;
4718     }
4719 
4720     f = fopen( "/proc/meminfo", "r" );
4721     if (f)
4722     {
4723         char buffer[256];
4724         int total, used, free, shared, buffers, cached;
4725 
4726         lpmem->dwLength = sizeof(MEMORYSTATUS);
4727         lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4728         lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4729         while (fgets( buffer, sizeof(buffer), f ))
4730         {
4731 	    /* old style /proc/meminfo ... */
4732             if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4733             {
4734                 lpmem->dwTotalPhys += total;
4735                 lpmem->dwAvailPhys += free + buffers + cached;
4736             }
4737             if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4738             {
4739                 lpmem->dwTotalPageFile += total;
4740                 lpmem->dwAvailPageFile += free;
4741             }
4742 
4743 	    /* new style /proc/meminfo ... */
4744 	    if (sscanf(buffer, "MemTotal: %d", &total))
4745 	    	lpmem->dwTotalPhys = total*1024;
4746 	    if (sscanf(buffer, "MemFree: %d", &free))
4747 	    	lpmem->dwAvailPhys = free*1024;
4748 	    if (sscanf(buffer, "SwapTotal: %d", &total))
4749 	        lpmem->dwTotalPageFile = total*1024;
4750 	    if (sscanf(buffer, "SwapFree: %d", &free))
4751 	        lpmem->dwAvailPageFile = free*1024;
4752 	    if (sscanf(buffer, "Buffers: %d", &buffers))
4753 	        lpmem->dwAvailPhys += buffers*1024;
4754 	    if (sscanf(buffer, "Cached: %d", &cached))
4755 	        lpmem->dwAvailPhys += cached*1024;
4756         }
4757         fclose( f );
4758 
4759         if (lpmem->dwTotalPhys)
4760         {
4761             DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4762             DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4763             lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4764                                       / (TotalPhysical / 100);
4765         }
4766     } else
4767     {
4768 	/* FIXME: should do something for other systems */
4769 	lpmem->dwMemoryLoad    = 0;
4770 	lpmem->dwTotalPhys     = 16*1024*1024;
4771 	lpmem->dwAvailPhys     = 16*1024*1024;
4772 	lpmem->dwTotalPageFile = 16*1024*1024;
4773 	lpmem->dwAvailPageFile = 16*1024*1024;
4774     }
4775     expGetSystemInfo(&si);
4776     lpmem->dwTotalVirtual  = (uint8_t *)si.lpMaximumApplicationAddress-(uint8_t *)si.lpMinimumApplicationAddress;
4777     /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4778     lpmem->dwAvailVirtual  = lpmem->dwTotalVirtual-64*1024;
4779     memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4780     cache_lastchecked = time(NULL);
4781 
4782     /* it appears some memory display programs want to divide by these values */
4783     if(lpmem->dwTotalPageFile==0)
4784         lpmem->dwTotalPageFile++;
4785 
4786     if(lpmem->dwAvailPageFile==0)
4787         lpmem->dwAvailPageFile++;
4788 }
4789 
expGetThreadPriority(HANDLE hthread)4790 static INT WINAPI expGetThreadPriority(HANDLE hthread)
4791 {
4792     dbgprintf("GetThreadPriority(%p)\n",hthread);
4793     return 0;
4794 }
4795 
4796 /**********************************************************************
4797  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
4798  *
4799  * RETURNS
4800  *    Success: TRUE
4801  *    Failure: FALSE
4802  */
expSetThreadPriority(HANDLE hthread,INT priority)4803 static WIN_BOOL WINAPI expSetThreadPriority(
4804     HANDLE hthread, /* [in] Handle to thread */
4805     INT priority)   /* [in] Thread priority level */
4806 {
4807     dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4808     return TRUE;
4809 }
4810 
expTerminateProcess(DWORD process,DWORD status)4811 static void WINAPI expTerminateProcess( DWORD process, DWORD status )
4812 {
4813     printf("EXIT - process %ld code %ld\n", process, status);
4814     exit(status);
4815 }
4816 
expExitProcess(DWORD status)4817 static void WINAPI expExitProcess( DWORD status )
4818 {
4819     printf("EXIT - code %ld\n",status);
4820     exit(status);
4821 }
4822 
expMessageBoxA(HWND hWnd,LPCSTR text,LPCSTR title,UINT type)4823 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4824     printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4825 #ifdef CONFIG_QTX_CODECS
4826     if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4827 	return IDIGNORE;
4828 #endif
4829     return IDOK;
4830 }
4831 
4832 /* these are needed for mss1 */
4833 
4834 /**
4835  * \brief this symbol is defined within exp_EH_prolog_dummy
4836  * \param dest jump target
4837  */
4838 void exp_EH_prolog(void *dest);
4839 void exp_EH_prolog_dummy(void);
4840 //! just a dummy function that acts a container for the asm section
exp_EH_prolog_dummy(void)4841 void exp_EH_prolog_dummy(void) {
4842   __asm__ volatile (
4843 // take care, this "function" may not change flags or
4844 // registers besides eax (which is also why we can't use
4845 // exp_EH_prolog_dummy directly)
4846 MANGLE(exp_EH_prolog)":    \n\t"
4847     "pop   %eax            \n\t"
4848     "push  %ebp            \n\t"
4849     "mov   %esp, %ebp      \n\t"
4850     "lea   -12(%esp), %esp \n\t"
4851     "jmp   *%eax           \n\t"
4852   );
4853 }
4854 
4855 #include <netinet/in.h>
exphtonl(unsigned long int hostlong)4856 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4857 {
4858 //    dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4859     return htonl(hostlong);
4860 }
4861 
expntohl(unsigned long int netlong)4862 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4863 {
4864 //    dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4865     return ntohl(netlong);
4866 }
4867 
expSysAllocStringLen(char * pch,unsigned cch)4868 static char* WINAPI expSysAllocStringLen(char *pch, unsigned cch)
4869 {
4870     char *str;
4871     dbgprintf("SysAllocStringLen('%s', %d)\n", pch, cch);
4872     str = malloc(cch * 2 + sizeof(unsigned) + 2);
4873     *(unsigned *)str = cch;
4874     str += sizeof(unsigned);
4875     if (pch)
4876         memcpy(str, pch, cch * 2);
4877     str[cch * 2] = 0;
4878     str[cch * 2 + 1] = 0;
4879     return str;
4880 }
4881 
expSysFreeString(char * str)4882 static void WINAPI expSysFreeString(char *str)
4883 {
4884     if (str) {
4885         free(str - sizeof(unsigned));
4886     }
4887 }
4888 
expVariantInit(void * p)4889 static void WINAPI expVariantInit(void* p)
4890 {
4891     printf("InitCommonControls called!\n");
4892     return;
4893 }
4894 
expRegisterClassA(const void * wc)4895 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4896 {
4897     dbgprintf("RegisterClassA(%p) => random id\n", wc);
4898     return time(NULL); /* be precise ! */
4899 }
4900 
expUnregisterClassA(const char * className,HINSTANCE hInstance)4901 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4902 {
4903     dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4904     return 0;
4905 }
4906 
4907 #ifdef CONFIG_QTX_CODECS
4908 /* should be fixed bcs it's not fully strlen equivalent */
expSysStringByteLen(void * str)4909 static int expSysStringByteLen(void *str)
4910 {
4911     dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4912     return strlen(str);
4913 }
4914 
expDirectDrawCreate(void)4915 static int expDirectDrawCreate(void)
4916 {
4917     dbgprintf("DirectDrawCreate(...) => NULL\n");
4918     return 0;
4919 }
4920 
4921 #if 1
4922 typedef struct tagPALETTEENTRY {
4923     BYTE peRed;
4924     BYTE peGreen;
4925     BYTE peBlue;
4926     BYTE peFlags;
4927 } PALETTEENTRY;
4928 
4929 typedef struct tagLOGPALETTE {
4930     WORD         palVersion;
4931     WORD         palNumEntries;
4932     PALETTEENTRY palPalEntry[1];
4933 } LOGPALETTE;
4934 
expCreatePalette(CONST LOGPALETTE * lpgpl)4935 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4936 {
4937     HPALETTE test;
4938     int i;
4939 
4940     dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4941 
4942     i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4943     test = malloc(i);
4944     memcpy((void *)test, lpgpl, i);
4945 
4946     return test;
4947 }
4948 #else
expCreatePalette(void)4949 static int expCreatePalette(void)
4950 {
4951     dbgprintf("CreatePalette(...) => NULL\n");
4952     return NULL;
4953 }
4954 #endif
4955 
expGetClientRect(HWND win,RECT * r)4956 static int WINAPI expGetClientRect(HWND win, RECT *r)
4957 {
4958     dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4959     r->right = PSEUDO_SCREEN_WIDTH;
4960     r->left = 0;
4961     r->bottom = PSEUDO_SCREEN_HEIGHT;
4962     r->top = 0;
4963     return 1;
4964 }
4965 
4966 #if 0
4967 typedef struct tagPOINT {
4968     LONG x;
4969     LONG y;
4970 } POINT, *PPOINT;
4971 #endif
4972 
expClientToScreen(HWND win,POINT * p)4973 static int WINAPI expClientToScreen(HWND win, POINT *p)
4974 {
4975     dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4976     p->x = 0;
4977     p->y = 0;
4978     return 1;
4979 }
4980 #endif
4981 
4982 /* for m3jpeg */
expSetThreadIdealProcessor(HANDLE thread,int proc)4983 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4984 {
4985     dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4986     return 0;
4987 }
4988 
expMessageBeep(int type)4989 static int WINAPI expMessageBeep(int type)
4990 {
4991     dbgprintf("MessageBeep(%d) => 1\n", type);
4992     return 1;
4993 }
4994 
expDialogBoxParamA(void * inst,const char * name,HWND parent,void * dialog_func,void * init_param)4995 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4996     HWND parent, void *dialog_func, void *init_param)
4997 {
4998     dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4999 	inst, name, name, parent, dialog_func, init_param);
5000     return 0x42424242;
5001 }
5002 
expRegisterClipboardFormatA(const char * name)5003 static void WINAPI expRegisterClipboardFormatA(const char *name) {
5004     dbgprintf("RegisterClipboardFormatA(0x%x = %s)\n", name, name);
5005 }
5006 
5007 /* needed by imagepower mjpeg2k */
exprealloc(void * ptr,size_t size)5008 static void *exprealloc(void *ptr, size_t size)
5009 {
5010     dbgprintf("realloc(0x%x, %x)\n", ptr, size);
5011     if (!ptr)
5012 	return my_mreq(size,0);
5013     else
5014 	return my_realloc(ptr, size);
5015 }
5016 
5017 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
expGetOpenFileNameA(void * lpfn)5018 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
5019 {
5020     return 1;
5021 }
5022 
expPathFindExtensionA(const char * path)5023 static const char * WINAPI expPathFindExtensionA(const char *path) {
5024   const char *ext;
5025   if (!path)
5026     ext = NULL;
5027   else {
5028     ext = strrchr(path, '.');
5029     if (!ext)
5030       ext = &path[strlen(path)];
5031   }
5032   dbgprintf("PathFindExtensionA(0x%x = %s) => 0x%x, %s\n", path, path, ext, ext);
5033   return ext;
5034 }
5035 
expPathFindFileNameA(const char * path)5036 static const char * WINAPI expPathFindFileNameA(const char *path) {
5037   const char *name;
5038   if (!path || strlen(path) < 2)
5039     name = path;
5040   else {
5041     name = strrchr(path - 1, '\\');
5042     if (!name)
5043       name = path;
5044   }
5045   dbgprintf("PathFindFileNameA(0x%x = %s) => 0x%x, %s\n", path, path, name, name);
5046   return name;
5047 }
5048 
expfloor(double x)5049 static double expfloor(double x)
5050 {
5051     dbgprintf("floor(%f)\n", x);
5052     return floor(x);
5053 }
5054 
5055 #define FPU_DOUBLE(var) double var; \
5056   __asm__ volatile( "fstpl %0;fwait" : "=m" (var) : )
5057 
exp_CIcos(void)5058 static double exp_CIcos(void)
5059 {
5060     FPU_DOUBLE(x);
5061 
5062     dbgprintf("_CIcos(%f)\n", x);
5063     return cos(x);
5064 }
5065 
exp_CIsin(void)5066 static double exp_CIsin(void)
5067 {
5068     FPU_DOUBLE(x);
5069 
5070     dbgprintf("_CIsin(%f)\n", x);
5071     return sin(x);
5072 }
5073 
exp_CIsqrt(void)5074 static double exp_CIsqrt(void)
5075 {
5076     FPU_DOUBLE(x);
5077 
5078     dbgprintf("_CIsqrt(%f)\n", x);
5079     return sqrt(x);
5080 }
5081 
5082 /* Needed by rp8 sipr decoder */
expCharNextA(LPCSTR ptr)5083 static LPSTR WINAPI expCharNextA(LPCSTR ptr)
5084 {
5085     if (!*ptr) return (LPSTR)ptr;
5086 //    dbgprintf("CharNextA(0x%08x), %s\n", ptr, ptr);
5087     return (LPSTR)(ptr + 1);
5088 }
5089 
5090 // Fake implementation, needed by wvc1dmod.dll
expPropVariantClear(void * pvar)5091 static int WINAPI expPropVariantClear(void *pvar)
5092 {
5093 //    dbgprintf("PropVariantclear (0x%08x), %s\n", ptr, ptr);
5094     return 1;
5095 }
5096 
5097 // This define is fake, the real thing is a struct
5098 #define LPDEVMODEA void*
5099 // Dummy implementation, always return 1
5100 // Required for frapsvid.dll 2.8.1, return value does not matter
expEnumDisplaySettingsA(LPCSTR name,DWORD n,LPDEVMODEA devmode)5101 static WIN_BOOL WINAPI expEnumDisplaySettingsA(LPCSTR name ,DWORD n,
5102     LPDEVMODEA devmode)
5103 {
5104     dbgprintf("EnumDisplaySettingsA (dummy) => 1\n");
5105     return 1;
5106 }
5107 
5108 // Fake implementation of _decode_pointer from msvcr80.dll, needed by sirenacm.dll
5109 // NOTE: undocumented function, probably the declaration is not right
exp_decode_pointer(void * ptr)5110 static int exp_decode_pointer(void *ptr)
5111 {
5112     dbgprintf("_decode_pointer (0x%08x)\n", ptr);
5113     return 0;
5114 }
5115 
5116 /* Fake implementation of sdt::_Lockit::_Lockit(void) from msvcp60.dll
5117    Needed by SCLS.DLL */
exp_0Lockit_dummy(void)5118 static int exp_0Lockit_dummy(void)
5119 {
5120     dbgprintf("0Lockit_dummy (??0_Lockit@std@@QAE@XZ)\n");
5121     return 0;
5122 }
5123 
5124 /* Fake implementation of sdt::_Lockit::~_Lockit(void) from msvcp60.dll
5125    Needed by SCLS.DLL */
exp_1Lockit_dummy(void)5126 static int exp_1Lockit_dummy(void)
5127 {
5128     dbgprintf("1Lockit_dummy (??1_Lockit@std@@QAE@XZ)\n");
5129     return 0;
5130 }
5131 
expEncodePointer(void * p)5132 static void * WINAPI expEncodePointer(void *p)
5133 {
5134     return p;
5135 }
5136 
expDecodePointer(void * p)5137 static void * WINAPI expDecodePointer(void *p)
5138 {
5139     return p;
5140 }
5141 
expGetThreadLocale(void)5142 static DWORD WINAPI expGetThreadLocale(void)
5143 {
5144     return 0;
5145 }
5146 
5147 /**
5148  * Very incomplete implementation, return an error for almost all cases.
5149  */
expGetLocaleInfoA(DWORD locale,DWORD lctype,char * lpLCData,int cchData)5150 static DWORD WINAPI expGetLocaleInfoA(DWORD locale, DWORD lctype, char* lpLCData, int cchData)
5151 {
5152     if (lctype == 0x1004) {  // LOCALE_IDEFAULTANSICODEPAGE
5153        if (cchData < 4)
5154            return cchData == 0 ? 4 : 0;
5155        strcpy(lpLCData, "437");
5156        return 4;
5157     }
5158     return 0;
5159 }
5160 
5161 struct exports
5162 {
5163     char name[64];
5164     int id;
5165     void* func;
5166 };
5167 struct libs
5168 {
5169     char name[64];
5170     int length;
5171     const struct exports* exps;
5172 };
5173 
5174 #define FF(X,Y) \
5175     {#X, Y, (void*)exp##X},
5176 
5177 #define UNDEFF(X, Y) \
5178     {#X, Y, (void*)-1},
5179 
5180 #define UNDEFORD(Y) \
5181     {NULL, Y, (void*)-1},
5182 
5183 static const struct exports exp_kernel32[]=
5184 {
5185     FF(GetVolumeInformationA,-1)
5186     FF(GetDriveTypeA,-1)
5187     FF(GetLogicalDriveStringsA,-1)
5188     FF(IsBadWritePtr, 357)
5189     FF(IsBadReadPtr, 354)
5190     FF(IsBadStringPtrW, -1)
5191     FF(IsBadStringPtrA, -1)
5192     FF(DisableThreadLibraryCalls, -1)
5193     FF(CreateThread, -1)
5194     FF(ResumeThread, -1)
5195     FF(CreateEventA, -1)
5196     FF(CreateEventW, -1)
5197     FF(SetEvent, -1)
5198     FF(ResetEvent, -1)
5199     FF(WaitForSingleObject, -1)
5200 #ifdef CONFIG_QTX_CODECS
5201     FF(WaitForMultipleObjects, -1)
5202     FF(ExitThread, -1)
5203 #endif
5204     FF(GetSystemInfo, -1)
5205     FF(GetVersion, 332)
5206     FF(HeapCreate, 461)
5207     FF(HeapAlloc, -1)
5208     FF(HeapDestroy, -1)
5209     FF(HeapFree, -1)
5210     FF(HeapSize, -1)
5211     FF(HeapReAlloc,-1)
5212     FF(GetProcessHeap, -1)
5213     FF(VirtualAlloc, -1)
5214     FF(VirtualFree, -1)
5215     FF(InitializeCriticalSection, -1)
5216     FF(InitializeCriticalSectionAndSpinCount, -1)
5217     FF(EnterCriticalSection, -1)
5218     FF(LeaveCriticalSection, -1)
5219     FF(DeleteCriticalSection, -1)
5220     FF(TlsAlloc, -1)
5221     FF(TlsFree, -1)
5222     FF(TlsGetValue, -1)
5223     FF(TlsSetValue, -1)
5224     FF(GetCurrentThreadId, -1)
5225     FF(GetCurrentProcess, -1)
5226     FF(LocalAlloc, -1)
5227     FF(LocalReAlloc,-1)
5228     FF(LocalLock, -1)
5229     FF(GlobalAlloc, -1)
5230     FF(GlobalReAlloc, -1)
5231     FF(GlobalLock, -1)
5232     FF(GlobalSize, -1)
5233     FF(MultiByteToWideChar, 427)
5234     FF(WideCharToMultiByte, -1)
5235     FF(GetVersionExA, -1)
5236     FF(GetVersionExW, -1)
5237     FF(CreateSemaphoreA, -1)
5238     FF(CreateSemaphoreW, -1)
5239     FF(QueryPerformanceCounter, -1)
5240     FF(QueryPerformanceFrequency, -1)
5241     FF(LocalHandle, -1)
5242     FF(LocalUnlock, -1)
5243     FF(LocalFree, -1)
5244     FF(GlobalHandle, -1)
5245     FF(GlobalUnlock, -1)
5246     FF(GlobalFree, -1)
5247     FF(LoadResource, -1)
5248     FF(ReleaseSemaphore, -1)
5249     FF(CreateMutexA, -1)
5250     FF(CreateMutexW, -1)
5251     FF(ReleaseMutex, -1)
5252     FF(SignalObjectAndWait, -1)
5253     FF(FindResourceA, -1)
5254     FF(LockResource, -1)
5255     FF(FreeResource, -1)
5256     FF(SizeofResource, -1)
5257     FF(CloseHandle, -1)
5258     FF(GetCommandLineA, -1)
5259     FF(GetEnvironmentStringsW, -1)
5260     FF(FreeEnvironmentStringsW, -1)
5261     FF(FreeEnvironmentStringsA, -1)
5262     FF(GetEnvironmentStrings, -1)
5263     FF(GetStartupInfoA, -1)
5264     FF(GetStdHandle, -1)
5265     FF(GetFileType, -1)
5266 #ifdef CONFIG_QTX_CODECS
5267     FF(GetFileAttributesA, -1)
5268 #endif
5269     FF(SetHandleCount, -1)
5270     FF(GetACP, -1)
5271     FF(GetModuleFileNameA, -1)
5272     FF(SetUnhandledExceptionFilter, -1)
5273     FF(LoadLibraryA, -1)
5274     FF(GetProcAddress, -1)
5275     FF(FreeLibrary, -1)
5276     FF(CreateFileMappingA, -1)
5277     FF(OpenFileMappingA, -1)
5278     FF(MapViewOfFile, -1)
5279     FF(UnmapViewOfFile, -1)
5280     FF(Sleep, -1)
5281     FF(GetModuleHandleA, -1)
5282     FF(GetModuleHandleW, -1)
5283     FF(GetProfileIntA, -1)
5284     FF(GetPrivateProfileIntA, -1)
5285     FF(GetPrivateProfileStringA, -1)
5286     FF(WritePrivateProfileStringA, -1)
5287     FF(GetLastError, -1)
5288     FF(SetLastError, -1)
5289     FF(InterlockedIncrement, -1)
5290     FF(InterlockedDecrement, -1)
5291     FF(GetTimeZoneInformation, -1)
5292     FF(OutputDebugStringA, -1)
5293     FF(GetLocalTime, -1)
5294     FF(GetSystemTime, -1)
5295     FF(GetSystemTimeAsFileTime, -1)
5296     FF(GetEnvironmentVariableA, -1)
5297     FF(SetEnvironmentVariableA, -1)
5298     FF(RtlZeroMemory,-1)
5299     FF(RtlMoveMemory,-1)
5300     FF(RtlFillMemory,-1)
5301     FF(GetTempPathA,-1)
5302     FF(FindFirstFileA,-1)
5303     FF(FindNextFileA,-1)
5304     FF(FindClose,-1)
5305     FF(FileTimeToLocalFileTime,-1)
5306     FF(DeleteFileA,-1)
5307     FF(ReadFile,-1)
5308     FF(WriteFile,-1)
5309     FF(SetFilePointer,-1)
5310     FF(GetTempFileNameA,-1)
5311     FF(CreateFileA,-1)
5312     FF(GetSystemDirectoryA,-1)
5313     FF(GetWindowsDirectoryA,-1)
5314 #ifdef CONFIG_QTX_CODECS
5315     FF(GetCurrentDirectoryA,-1)
5316     FF(SetCurrentDirectoryA,-1)
5317     FF(CreateDirectoryA,-1)
5318 #endif
5319     FF(GetShortPathNameA,-1)
5320     FF(GetFullPathNameA,-1)
5321     FF(SetErrorMode, -1)
5322     FF(IsProcessorFeaturePresent, -1)
5323     FF(IsDebuggerPresent, -1)
5324     FF(GetProcessAffinityMask, -1)
5325     FF(InterlockedExchange, -1)
5326     FF(InterlockedCompareExchange, -1)
5327     FF(MulDiv, -1)
5328     FF(lstrcmpiA, -1)
5329     FF(lstrlenA, -1)
5330     FF(lstrlenW, -1)
5331     FF(lstrcpyA, -1)
5332     FF(lstrcatA, -1)
5333     FF(lstrcpynA,-1)
5334     FF(GetProcessVersion,-1)
5335     FF(GetCurrentThread,-1)
5336     FF(GetOEMCP,-1)
5337     FF(GetCPInfo,-1)
5338     FF(DuplicateHandle,-1)
5339     FF(GetTickCount, -1)
5340     FF(SetThreadAffinityMask,-1)
5341     FF(GetCurrentProcessId,-1)
5342     FF(GlobalMemoryStatus,-1)
5343     FF(GetThreadPriority,-1)
5344     FF(SetThreadPriority,-1)
5345     FF(TerminateProcess,-1)
5346     FF(ExitProcess,-1)
5347     {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
5348     FF(SetThreadIdealProcessor,-1)
5349     FF(SetProcessAffinityMask, -1)
5350     FF(EncodePointer, -1)
5351     FF(DecodePointer, -1)
5352     FF(GetThreadLocale, -1)
5353     FF(GetLocaleInfoA, -1)
5354     UNDEFF(FlsAlloc, -1)
5355     UNDEFF(FlsGetValue, -1)
5356     UNDEFF(FlsSetValue, -1)
5357     UNDEFF(FlsFree, -1)
5358 };
5359 
5360 static const struct exports exp_msvcrt[]={
5361     FF(malloc, -1)
5362     FF(_initterm, -1)
5363     FF(__dllonexit, -1)
5364     FF(_snprintf,-1)
5365     FF(free, -1)
5366     {"??3@YAXPAX@Z", -1, expdelete},
5367     {"??2@YAPAXI@Z", -1, expnew},
5368     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5369     {"_winver",-1,(void*)&_winver},
5370     FF(strrchr, -1)
5371     FF(strchr, -1)
5372     FF(strlen, -1)
5373     FF(strcpy, -1)
5374     FF(strncpy, -1)
5375     FF(wcscpy, -1)
5376     FF(strcmp, -1)
5377     FF(strncmp, -1)
5378     FF(strcat, -1)
5379     FF(_stricmp,-1)
5380     FF(_strdup,-1)
5381     FF(_setjmp3,-1)
5382     FF(isalnum, -1)
5383     FF(isspace, -1)
5384     FF(isalpha, -1)
5385     FF(isdigit, -1)
5386     FF(memmove, -1)
5387     FF(memcmp, -1)
5388     FF(memset, -1)
5389     FF(memcpy, -1)
5390     FF(time, -1)
5391     FF(rand, -1)
5392     FF(srand, -1)
5393     FF(log10, -1)
5394     FF(pow, -1)
5395     FF(cos, -1)
5396     FF(_ftol,-1)
5397     FF(_CIpow,-1)
5398     FF(_CIcos,-1)
5399     FF(_CIsin,-1)
5400     FF(_CIsqrt,-1)
5401     FF(ldexp,-1)
5402     FF(frexp,-1)
5403     FF(sprintf,-1)
5404     FF(sscanf,-1)
5405     FF(fopen,-1)
5406     FF(fprintf,-1)
5407     FF(printf,-1)
5408     FF(getenv,-1)
5409     FF(floor,-1)
5410 /* needed by frapsvid.dll */
5411     {"strstr",-1,(char *)&strstr},
5412     {"qsort",-1,(void *)&qsort},
5413     FF(_EH_prolog,-1)
5414     FF(calloc,-1)
5415     {"ceil",-1,(void*)&ceil},
5416 /* needed by imagepower mjpeg2k */
5417     {"clock",-1,(void*)&clock},
5418     {"memchr",-1,(void*)&memchr},
5419     {"vfprintf",-1,(void*)&vfprintf},
5420 //    {"realloc",-1,(void*)&realloc},
5421     FF(realloc,-1)
5422     {"puts",-1,(void*)&puts}
5423 };
5424 static const struct exports exp_winmm[]={
5425     FF(GetDriverModuleHandle, -1)
5426     FF(timeGetTime, -1)
5427     FF(DefDriverProc, -1)
5428     FF(OpenDriverA, -1)
5429     FF(OpenDriver, -1)
5430     FF(timeGetDevCaps, -1)
5431     FF(timeBeginPeriod, -1)
5432 #ifdef CONFIG_QTX_CODECS
5433     FF(timeEndPeriod, -1)
5434     FF(waveOutGetNumDevs, -1)
5435 #endif
5436 };
5437 static const struct exports exp_psapi[]={
5438     FF(GetModuleBaseNameA, -1)
5439 };
5440 static const struct exports exp_user32[]={
5441     FF(LoadIconA,-1)
5442     FF(LoadStringA, -1)
5443     FF(wsprintfA, -1)
5444     FF(GetDC, -1)
5445     FF(GetDesktopWindow, -1)
5446     FF(ReleaseDC, -1)
5447     FF(IsRectEmpty, -1)
5448     FF(LoadCursorA,-1)
5449     FF(SetCursor,-1)
5450     FF(GetCursorPos,-1)
5451 #ifdef CONFIG_QTX_CODECS
5452     FF(ShowCursor,-1)
5453 #endif
5454     FF(RegisterWindowMessageA,-1)
5455     FF(GetSystemMetrics,-1)
5456     FF(GetSysColor,-1)
5457     FF(GetSysColorBrush,-1)
5458     FF(GetWindowDC, -1)
5459     FF(DrawTextA, -1)
5460     FF(MessageBoxA, -1)
5461     FF(RegisterClassA, -1)
5462     FF(UnregisterClassA, -1)
5463 #ifdef CONFIG_QTX_CODECS
5464     FF(GetWindowRect, -1)
5465     FF(MonitorFromWindow, -1)
5466     FF(MonitorFromRect, -1)
5467     FF(MonitorFromPoint, -1)
5468     FF(EnumDisplayMonitors, -1)
5469     FF(GetMonitorInfoA, -1)
5470     FF(EnumDisplayDevicesA, -1)
5471     FF(GetClientRect, -1)
5472     FF(ClientToScreen, -1)
5473     FF(IsWindowVisible, -1)
5474     FF(GetActiveWindow, -1)
5475     FF(GetClassNameA, -1)
5476     FF(GetClassInfoA, -1)
5477     FF(GetWindowLongA, -1)
5478     FF(EnumWindows, -1)
5479     FF(GetWindowThreadProcessId, -1)
5480     FF(CreateWindowExA, -1)
5481 #endif
5482     FF(MessageBeep, -1)
5483     FF(DialogBoxParamA, -1)
5484     FF(RegisterClipboardFormatA, -1)
5485     FF(CharNextA, -1)
5486     FF(EnumDisplaySettingsA, -1)
5487 };
5488 static const struct exports exp_advapi32[]={
5489     FF(RegCloseKey, -1)
5490     FF(RegCreateKeyA, -1)
5491     FF(RegCreateKeyExA, -1)
5492     FF(RegEnumKeyExA, -1)
5493     FF(RegEnumValueA, -1)
5494     FF(RegOpenKeyA, -1)
5495     FF(RegOpenKeyExA, -1)
5496     FF(RegQueryValueExA, -1)
5497     FF(RegSetValueExA, -1)
5498     FF(RegQueryInfoKeyA, -1)
5499 };
5500 static const struct exports exp_gdi32[]={
5501     FF(CreateCompatibleDC, -1)
5502     FF(CreateFontA, -1)
5503     FF(DeleteDC, -1)
5504     FF(DeleteObject, -1)
5505     FF(GetDeviceCaps, -1)
5506     FF(GetSystemPaletteEntries, -1)
5507 #ifdef CONFIG_QTX_CODECS
5508     FF(CreatePalette, -1)
5509     FF(GetObjectA, -1)
5510     FF(CreateRectRgn, -1)
5511 #endif
5512 };
5513 static const struct exports exp_version[]={
5514     FF(GetFileVersionInfoSizeA, -1)
5515 };
5516 static const struct exports exp_ole32[]={
5517     FF(CoCreateFreeThreadedMarshaler,-1)
5518     FF(CoCreateInstance, -1)
5519     FF(CoInitialize, -1)
5520     FF(CoInitializeEx, -1)
5521     FF(CoUninitialize, -1)
5522     FF(CoTaskMemAlloc, -1)
5523     FF(CoTaskMemFree, -1)
5524     FF(StringFromGUID2, -1)
5525     FF(PropVariantClear, -1)
5526 };
5527 // do we really need crtdll ???
5528 // msvcrt is the correct place probably...
5529 static const struct exports exp_crtdll[]={
5530     FF(memcpy, -1)
5531     FF(wcscpy, -1)
5532 };
5533 static const struct exports exp_comctl32[]={
5534     FF(StringFromGUID2, -1)
5535     FF(InitCommonControls, 17)
5536 #ifdef CONFIG_QTX_CODECS
5537     FF(CreateUpDownControl, 16)
5538 #endif
5539 };
5540 static const struct exports exp_wsock32[]={
5541     FF(htonl,8)
5542     FF(ntohl,14)
5543 };
5544 static const struct exports exp_msdmo[]={
5545     FF(memcpy, -1) // just test
5546     FF(MoCopyMediaType, -1)
5547     FF(MoCreateMediaType, -1)
5548     FF(MoDeleteMediaType, -1)
5549     FF(MoDuplicateMediaType, -1)
5550     FF(MoFreeMediaType, -1)
5551     FF(MoInitMediaType, -1)
5552 };
5553 static const struct exports exp_oleaut32[]={
5554     FF(SysAllocStringLen, 4)
5555     FF(SysFreeString, 6)
5556     FF(VariantInit, 8)
5557 #ifdef CONFIG_QTX_CODECS
5558     FF(SysStringByteLen, 149)
5559 #endif
5560 };
5561 
5562 /*  realplayer8:
5563 	DLL Name: PNCRT.dll
5564 	vma:  Hint/Ord Member-Name
5565 	22ff4	  615  free
5566 	2302e	  250  _ftol
5567 	22fea	  666  malloc
5568 	2303e	  609  fprintf
5569 	2305e	  167  _adjust_fdiv
5570 	23052	  280  _initterm
5571 
5572 	22ffc	  176  _beginthreadex
5573 	23036	  284  _iob
5574 	2300e	   85  __CxxFrameHandler
5575 	23022	  411  _purecall
5576 */
5577 #ifdef REALPLAYER
5578 static const struct exports exp_pncrt[]={
5579     FF(malloc, -1) // just test
5580     FF(free, -1) // just test
5581     FF(fprintf, -1) // just test
5582     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5583     FF(_ftol,-1)
5584     FF(_initterm, -1)
5585     {"??3@YAXPAX@Z", -1, expdelete},
5586     {"??2@YAPAXI@Z", -1, expnew},
5587     FF(__dllonexit, -1)
5588     FF(strncpy, -1)
5589     FF(_CIpow,-1)
5590     FF(calloc,-1)
5591     FF(memmove, -1)
5592     FF(ldexp, -1)
5593     FF(frexp, -1)
5594 };
5595 #endif
5596 
5597 #ifdef CONFIG_QTX_CODECS
5598 static const struct exports exp_ddraw[]={
5599     FF(DirectDrawCreate, -1)
5600 };
5601 #endif
5602 
5603 static const struct exports exp_comdlg32[]={
5604     FF(GetOpenFileNameA, -1)
5605 };
5606 
5607 static const struct exports exp_shlwapi[]={
5608     FF(PathFindExtensionA, -1)
5609     FF(PathFindFileNameA, -1)
5610 };
5611 
5612 static const struct exports exp_msvcr80[]={
5613     FF(_CIpow,-1)
5614     FF(_CIsin,-1)
5615     FF(_CIcos,-1)
5616     FF(_CIsqrt,-1)
5617     FF(memcpy,-1)
5618     FF(memset,-1)
5619     FF(sprintf,-1)
5620     FF(strncpy,-1)
5621     FF(fopen,-1)
5622     FF(malloc,-1)
5623     FF(free,-1)
5624     FF(_initterm_e, -1)
5625     FF(_initterm, -1)
5626     FF(_decode_pointer, -1)
5627 
5628 // For CFDecode2.ax
5629     {"_aligned_free",-1,(void*)expfree},
5630     {"_aligned_malloc",-1,(void*)expmalloc},
5631     FF(_splitpath,-1)
5632     FF(_mbsupr,-1)
5633     {"_mbscmp", -1, (void*)strcmp},
5634     {"clock",-1,(void*)&clock},
5635     FF(_time64,-1)
5636 /* needed by KGV1-VFW.dll */
5637     {"??2@YAPAXI@Z", -1, expnew},
5638     {"??3@YAXPAX@Z", -1, expdelete}
5639 };
5640 
5641 static const struct exports exp_msvcp60[]={
5642     {"??0_Lockit@std@@QAE@XZ", -1, exp_0Lockit_dummy},
5643     {"??1_Lockit@std@@QAE@XZ", -1, exp_1Lockit_dummy}
5644 };
5645 
5646 static const struct exports exp_msvcr100[]={
5647     FF(memcpy, -1)
5648     FF(memset, -1)
5649     FF(_initterm_e, -1)
5650     FF(_initterm, -1)
5651     {"??2@YAPAXI@Z", -1, expnew},
5652     {"??3@YAXPAX@Z", -1, expdelete}
5653 };
5654 
5655 #define LL(X) \
5656     {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5657 
5658 static const struct libs libraries[]={
5659     LL(kernel32)
5660     LL(msvcrt)
5661     LL(winmm)
5662     LL(psapi)
5663     LL(user32)
5664     LL(advapi32)
5665     LL(gdi32)
5666     LL(version)
5667     LL(ole32)
5668     LL(oleaut32)
5669     LL(crtdll)
5670     LL(comctl32)
5671     LL(wsock32)
5672     LL(msdmo)
5673 #ifdef REALPLAYER
5674     LL(pncrt)
5675 #endif
5676 #ifdef CONFIG_QTX_CODECS
5677     LL(ddraw)
5678 #endif
5679     LL(comdlg32)
5680     LL(shlwapi)
5681     LL(msvcr80)
5682     LL(msvcp60)
5683     LL(msvcr100)
5684 };
5685 
ext_stubs(void)5686 static WIN_BOOL WINAPI ext_stubs(void)
5687 {
5688     // NOTE! these magic values will be replaced at runtime, make sure
5689     // add_stub can still find them if you change them.
5690     volatile int idx = 0x0deadabc;
5691     // make sure gcc does not do eip-relative call or something like that
5692     void (* volatile my_printf)(char *, char *) = (void *)0xdeadfbcd;
5693     my_printf("Called unk_%s\n", export_names[idx]);
5694     return 0;
5695 }
5696 
5697 #define MAX_STUB_SIZE 0x60
5698 #define MAX_NUM_STUBS 200
5699 static int pos=0;
5700 static char *extcode = NULL;
5701 
add_stub(void)5702 static void* add_stub(void)
5703 {
5704     int i;
5705     int found = 0;
5706     // generated code in runtime!
5707     char* answ;
5708     if (!extcode)
5709       extcode = mmap_anon(NULL, MAX_NUM_STUBS * MAX_STUB_SIZE,
5710                   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0);
5711     answ = extcode + pos * MAX_STUB_SIZE;
5712     if (pos >= MAX_NUM_STUBS) {
5713       printf("too many stubs, expect crash\n");
5714       return NULL;
5715     }
5716     memcpy(answ, ext_stubs, MAX_STUB_SIZE);
5717     for (i = 0; i < MAX_STUB_SIZE - 3; i++) {
5718       int *magic = (int *)(answ + i);
5719       if (*magic == 0x0deadabc) {
5720         *magic = pos;
5721         found |= 1;
5722       }
5723       if (*magic == 0xdeadfbcd) {
5724         *magic = (intptr_t)printf;
5725         found |= 2;
5726       }
5727     }
5728     if (found != 3) {
5729       printf("magic code not found in ext_subs, expect crash\n");
5730       return NULL;
5731     }
5732     pos++;
5733     return (void*)answ;
5734 }
5735 
LookupExternal(const char * library,int ordinal)5736 void* LookupExternal(const char* library, int ordinal)
5737 {
5738     int i,j;
5739     if(library==0)
5740     {
5741 	printf("ERROR: library=0\n");
5742 	return (void*)ext_unknown;
5743     }
5744     //    printf("%x %x\n", &unk_exp1, &unk_exp2);
5745 
5746     dbgprintf("External func %s:%d\n", library, ordinal);
5747 
5748     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5749     {
5750 	if(av_strcasecmp(library, libraries[i].name))
5751 	    continue;
5752 	for(j=0; j<libraries[i].length; j++)
5753 	{
5754 	    if(ordinal!=libraries[i].exps[j].id)
5755 		continue;
5756 	    //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5757 	    if((unsigned int)(libraries[i].exps[j].func) == -1)
5758 		return NULL; //undefined func
5759 	    return libraries[i].exps[j].func;
5760 	}
5761     }
5762 
5763 #ifndef LOADLIB_TRY_NATIVE
5764   /* hack for truespeech and vssh264*/
5765   if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5766 #endif
5767     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5768     {
5769 	int hand;
5770 	WINE_MODREF *wm;
5771 	void *func;
5772 
5773 	hand = LoadLibraryA(library);
5774 	if (!hand)
5775 	    goto no_dll;
5776 	wm = MODULE32_LookupHMODULE(hand);
5777 	if (!wm)
5778 	{
5779 	    FreeLibrary(hand);
5780 	    goto no_dll;
5781 	}
5782 	func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5783 	if (!func)
5784 	{
5785 	    printf("No such ordinal in external dll\n");
5786 	    FreeLibrary((int)hand);
5787 	    goto no_dll;
5788 	}
5789 
5790 	printf("External dll loaded (offset: 0x%x, func: %p)\n",
5791 	       hand, func);
5792 	return func;
5793     }
5794 
5795 no_dll:
5796     if(pos>150)return 0;
5797     snprintf(export_names[pos], sizeof(export_names[pos]), "%s:%d", library, ordinal);
5798     return add_stub();
5799 }
5800 
LookupExternalByName(const char * library,const char * name)5801 void* LookupExternalByName(const char* library, const char* name)
5802 {
5803     int i,j;
5804     //   return (void*)ext_unknown;
5805     if(library==0)
5806     {
5807 	printf("ERROR: library=0\n");
5808 	return (void*)ext_unknown;
5809     }
5810     if((unsigned long)name<=0xffff)
5811     {
5812 	return LookupExternal(library, (int)name);
5813     }
5814     dbgprintf("External func %s:%s\n", library, name);
5815     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5816     {
5817 	if(av_strcasecmp(library, libraries[i].name))
5818 	    continue;
5819 	for(j=0; j<libraries[i].length; j++)
5820 	{
5821 	    if(libraries[i].exps[j].name && strcmp(name, libraries[i].exps[j].name))
5822 		continue;
5823  	    if((unsigned int)(libraries[i].exps[j].func) == -1)
5824 		return NULL; //undefined func
5825 	    //	    printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5826 	    return libraries[i].exps[j].func;
5827 	}
5828     }
5829 
5830 #ifndef LOADLIB_TRY_NATIVE
5831   /* hack for vss h264 */
5832   if (!strcmp(library,"vssh264core.dll") || !strcmp(library,"3ivx.dll"))
5833 #endif
5834     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5835     {
5836 	int hand;
5837 	WINE_MODREF *wm;
5838 	void *func;
5839 
5840 	hand = LoadLibraryA(library);
5841 	if (!hand)
5842 	    goto no_dll_byname;
5843 	wm = MODULE32_LookupHMODULE(hand);
5844 	if (!wm)
5845 	{
5846 	    FreeLibrary(hand);
5847 	    goto no_dll_byname;
5848 	}
5849 	func = PE_FindExportedFunction(wm, name, 0);
5850 	if (!func)
5851 	{
5852 	    printf("No such name in external dll\n");
5853 	    FreeLibrary((int)hand);
5854 	    goto no_dll_byname;
5855 	}
5856 
5857 	printf("External dll loaded (offset: 0x%x, func: %p)\n",
5858 	       hand, func);
5859 	return func;
5860     }
5861 
5862 no_dll_byname:
5863     if(pos>150)return 0;// to many symbols
5864     snprintf(export_names[pos], sizeof(export_names[pos]), "%s", name);
5865     return add_stub();
5866 }
5867 
my_garbagecollection(void)5868 void my_garbagecollection(void)
5869 {
5870 #ifdef GARBAGE
5871     int unfree = 0, unfreecnt = 0;
5872 
5873     int max_fatal = 8;
5874     free_registry();
5875     while (last_alloc)
5876     {
5877 	alloc_header* mem = last_alloc + 1;
5878 	unfree += my_size(mem);
5879 	unfreecnt++;
5880 	if (my_release(mem) != 0)
5881 	    // avoid endless loop when memory is trashed
5882 	    if (--max_fatal < 0)
5883 		break;
5884     }
5885     dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5886 #endif
5887     g_tls = NULL;
5888     pthread_mutex_lock(&list_lock);
5889     list = NULL;
5890     pthread_mutex_unlock(&list_lock);
5891 }
5892