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