Merge svn changes up to r30815
[mplayer/glamo.git] / loader / win32.c
blobf560ffdfb45ce98d9441cd8f20f52a62b2bd85d9
1 /***********************************************************
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.
9 Basic principle of implementation: it's not good
10 for DLL to know too much about its environment.
12 ************************************************************/
15 * Modified for use with MPlayer, detailed changelog at
16 * http://svn.mplayerhq.hu/mplayer/trunk/
19 #include "config.h"
20 #include "mangle.h"
22 #define REALPLAYER
23 //#define LOADLIB_TRY_NATIVE
25 /* Hack to make sure the correct function declaration in com.h is used when
26 * this file is built for the test applications with WIN32_LOADER disabled. */
27 #ifndef WIN32_LOADER
28 #define WIN32_LOADER
29 #endif
31 #ifdef CONFIG_QTX_CODECS
32 #define PSEUDO_SCREEN_WIDTH /*640*/800
33 #define PSEUDO_SCREEN_HEIGHT /*480*/600
34 #endif
36 #include "wine/winbase.h"
37 #include "wine/winreg.h"
38 #include "wine/winnt.h"
39 #include "wine/winerror.h"
40 #include "wine/debugtools.h"
41 #include "wine/module.h"
42 #include "wine/winuser.h"
43 #include "wine/objbase.h"
45 #include <stdio.h>
46 #include "win32.h"
48 #include "registry.h"
49 #include "loader.h"
50 #include "com.h"
51 #include "ext.h"
53 #include <stdlib.h>
54 #include <assert.h>
55 #include <stdarg.h>
56 #include <ctype.h>
57 #include <pthread.h>
58 #include <errno.h>
59 #include <time.h>
60 #include <math.h>
61 #include <unistd.h>
62 #include <fcntl.h>
63 #include <sys/types.h>
64 #include <dirent.h>
65 #include <sys/time.h>
66 #include <sys/stat.h>
67 #include <sys/timeb.h>
68 #ifdef HAVE_KSTAT
69 #include <kstat.h>
70 #endif
72 #ifdef HAVE_SYS_MMAN_H
73 #include <sys/mman.h>
74 #else
75 #include "osdep/mmap.h"
76 #endif
77 #include "osdep/mmap_anon.h"
78 #include "libavutil/avstring.h"
80 char* def_path = WIN32_PATH;
82 static void do_cpuid(unsigned int ax, unsigned int *regs)
84 __asm__ volatile
86 "pushl %%ebx; pushl %%ecx; pushl %%edx;"
87 ".byte 0x0f, 0xa2;"
88 "movl %%eax, (%2);"
89 "movl %%ebx, 4(%2);"
90 "movl %%ecx, 8(%2);"
91 "movl %%edx, 12(%2);"
92 "popl %%edx; popl %%ecx; popl %%ebx;"
93 : "=a" (ax)
94 : "0" (ax), "S" (regs)
97 static unsigned int c_localcount_tsc(void)
99 int a;
100 __asm__ volatile
102 "rdtsc\n\t"
103 :"=a"(a)
105 :"edx"
107 return a;
109 static void c_longcount_tsc(long long* z)
111 __asm__ volatile
113 "pushl %%ebx\n\t"
114 "movl %%eax, %%ebx\n\t"
115 "rdtsc\n\t"
116 "movl %%eax, 0(%%ebx)\n\t"
117 "movl %%edx, 4(%%ebx)\n\t"
118 "popl %%ebx\n\t"
119 ::"a"(z)
120 :"edx"
123 static unsigned int c_localcount_notsc(void)
125 struct timeval tv;
126 unsigned limit=~0;
127 limit/=1000000;
128 gettimeofday(&tv, 0);
129 return limit*tv.tv_usec;
131 static void c_longcount_notsc(long long* z)
133 struct timeval tv;
134 unsigned long long result;
135 unsigned limit=~0;
136 if(!z)return;
137 limit/=1000000;
138 gettimeofday(&tv, 0);
139 result=tv.tv_sec;
140 result<<=32;
141 result+=limit*tv.tv_usec;
142 *z=result;
144 static unsigned int localcount_stub(void);
145 static void longcount_stub(long long*);
146 static unsigned int (*localcount)()=localcount_stub;
147 static void (*longcount)(long long*)=longcount_stub;
149 static pthread_mutex_t memmut;
151 static unsigned int localcount_stub(void)
153 unsigned int regs[4];
154 do_cpuid(1, regs);
155 if ((regs[3] & 0x00000010) != 0)
157 localcount=c_localcount_tsc;
158 longcount=c_longcount_tsc;
160 else
162 localcount=c_localcount_notsc;
163 longcount=c_longcount_notsc;
165 return localcount();
167 static void longcount_stub(long long* z)
169 unsigned int regs[4];
170 do_cpuid(1, regs);
171 if ((regs[3] & 0x00000010) != 0)
173 localcount=c_localcount_tsc;
174 longcount=c_longcount_tsc;
176 else
178 localcount=c_localcount_notsc;
179 longcount=c_longcount_notsc;
181 longcount(z);
184 #include "mp_msg.h"
185 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
186 //#define DETAILED_OUT
187 static inline void dbgprintf(char* fmt, ...)
189 #ifdef DETAILED_OUT
190 if(LOADER_DEBUG)
192 FILE* f;
193 va_list va;
194 va_start(va, fmt);
195 f=fopen("./log", "a");
196 vprintf(fmt, va);
197 fflush(stdout);
198 if(f)
200 vfprintf(f, fmt, va);
201 fsync(fileno(f));
202 fclose(f);
204 va_end(va);
206 #endif
207 if ( mp_msg_test(MSGT_WIN32,MSGL_DBG3) )
209 va_list va;
211 va_start(va, fmt);
212 vprintf(fmt, va);
213 // mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
214 va_end(va);
215 fflush(stdout);
220 char export_names[300][32]={
221 "name1",
222 //"name2",
223 //"name3"
225 //#define min(x,y) ((x)<(y)?(x):(y))
227 void destroy_event(void* event);
229 struct th_list_t;
230 typedef struct th_list_t{
231 int id;
232 void* thread;
233 struct th_list_t* next;
234 struct th_list_t* prev;
235 } th_list;
238 // have to be cleared by GARBAGE COLLECTOR
239 //static unsigned char* heap=NULL;
240 //static int heap_counter=0;
241 static tls_t* g_tls=NULL;
242 static th_list* list=NULL;
244 #if 0
245 static void test_heap(void)
247 int offset=0;
248 if(heap==0)
249 return;
250 while(offset<heap_counter)
252 if(*(int*)(heap+offset)!=0x433476)
254 printf("Heap corruption at address %d\n", offset);
255 return;
257 offset+=8+*(int*)(heap+offset+4);
259 for(;offset<min(offset+1000, 20000000); offset++)
260 if(heap[offset]!=0xCC)
262 printf("Free heap corruption at address %d\n", offset);
265 #endif
266 #undef MEMORY_DEBUG
268 #ifdef MEMORY_DEBUG
270 static void* my_mreq(int size, int to_zero)
272 static int test=0;
273 test++;
274 if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
275 // test_heap();
276 if(heap==NULL)
278 heap=malloc(20000000);
279 memset(heap, 0xCC,20000000);
281 if(heap==0)
283 printf("No enough memory\n");
284 return 0;
286 if(heap_counter+size>20000000)
288 printf("No enough memory\n");
289 return 0;
291 *(int*)(heap+heap_counter)=0x433476;
292 heap_counter+=4;
293 *(int*)(heap+heap_counter)=size;
294 heap_counter+=4;
295 printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
296 if(to_zero)
297 memset(heap+heap_counter, 0, size);
298 else
299 memset(heap+heap_counter, 0xcc, size); // make crash reproducable
300 heap_counter+=size;
301 return heap+heap_counter-size;
303 static int my_release(char* memory)
305 // test_heap();
306 if(memory==NULL)
308 printf("ERROR: free(0)\n");
309 return 0;
311 if(*(int*)(memory-8)!=0x433476)
313 printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
314 return 0;
316 printf("Freed %d bytes of memory\n", *(int*)(memory-4));
317 // memset(memory-8, *(int*)(memory-4), 0xCC);
318 return 0;
321 #else
322 #define GARBAGE
323 typedef struct alloc_header_t alloc_header;
324 struct alloc_header_t
326 // let's keep allocated data 16 byte aligned
327 alloc_header* prev;
328 alloc_header* next;
329 long deadbeef;
330 long size;
331 long type;
332 long reserved1;
333 long reserved2;
334 long reserved3;
337 #ifdef GARBAGE
338 static alloc_header* last_alloc = NULL;
339 static int alccnt = 0;
340 #endif
342 #define AREATYPE_CLIENT 0
343 #define AREATYPE_EVENT 1
344 #define AREATYPE_MUTEX 2
345 #define AREATYPE_COND 3
346 #define AREATYPE_CRITSECT 4
348 /* -- critical sections -- */
349 struct CRITSECT
351 pthread_t id;
352 pthread_mutex_t mutex;
353 int locked;
354 long deadbeef;
357 void* mreq_private(int size, int to_zero, int type);
358 void* mreq_private(int size, int to_zero, int type)
360 int nsize = size + sizeof(alloc_header);
361 alloc_header* header = malloc(nsize);
362 if (!header)
363 return 0;
364 if (to_zero)
365 memset(header, 0, nsize);
366 #ifdef GARBAGE
367 if (!last_alloc)
369 pthread_mutex_init(&memmut, NULL);
370 pthread_mutex_lock(&memmut);
372 else
374 pthread_mutex_lock(&memmut);
375 last_alloc->next = header; /* set next */
378 header->prev = last_alloc;
379 header->next = 0;
380 last_alloc = header;
381 alccnt++;
382 pthread_mutex_unlock(&memmut);
383 #endif
384 header->deadbeef = 0xdeadbeef;
385 header->size = size;
386 header->type = type;
388 //if (alccnt < 40000) printf("MY_REQ: %p\t%d t:%d (cnt:%d)\n", header, size, type, alccnt);
389 return header + 1;
392 static int my_release(void* memory)
394 alloc_header* header = (alloc_header*) memory - 1;
395 #ifdef GARBAGE
396 alloc_header* prevmem;
397 alloc_header* nextmem;
399 if (memory == 0)
400 return 0;
402 if (header->deadbeef != (long) 0xdeadbeef)
404 dbgprintf("FATAL releasing corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
405 return 0;
408 pthread_mutex_lock(&memmut);
410 switch(header->type)
412 case AREATYPE_EVENT:
413 destroy_event(memory);
414 break;
415 case AREATYPE_COND:
416 pthread_cond_destroy((pthread_cond_t*)memory);
417 break;
418 case AREATYPE_MUTEX:
419 pthread_mutex_destroy((pthread_mutex_t*)memory);
420 break;
421 case AREATYPE_CRITSECT:
422 pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
423 break;
424 default:
425 //memset(memory, 0xcc, header->size);
429 header->deadbeef = 0;
430 prevmem = header->prev;
431 nextmem = header->next;
433 if (prevmem)
434 prevmem->next = nextmem;
435 if (nextmem)
436 nextmem->prev = prevmem;
438 if (header == last_alloc)
439 last_alloc = prevmem;
441 alccnt--;
443 if (last_alloc)
444 pthread_mutex_unlock(&memmut);
445 else
446 pthread_mutex_destroy(&memmut);
448 //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld (%d)\n", header, header->size, alccnt);
449 #else
450 if (memory == 0)
451 return 0;
452 #endif
453 //memset(header + 1, 0xcc, header->size);
454 free(header);
455 return 0;
457 #endif
459 static inline void* my_mreq(int size, int to_zero)
461 return mreq_private(size, to_zero, AREATYPE_CLIENT);
464 static int my_size(void* memory)
466 if(!memory) return 0;
467 return ((alloc_header*)memory)[-1].size;
470 static void* my_realloc(void* memory, int size)
472 void *ans = memory;
473 int osize;
474 if (memory == NULL)
475 return my_mreq(size, 0);
476 osize = my_size(memory);
477 if (osize < size)
479 ans = my_mreq(size, 0);
480 memcpy(ans, memory, osize);
481 my_release(memory);
483 return ans;
488 * WINE API - native implementation for several win32 libraries
492 static int WINAPI ext_unknown(void)
494 printf("Unknown func called\n");
495 return 0;
498 static int WINAPI expGetVolumeInformationA( const char *root, char *label,
499 unsigned int label_len, unsigned int *serial,
500 unsigned int *filename_len,unsigned int *flags,
501 char *fsname, unsigned int fsname_len )
503 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
504 root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
505 //hack Do not return any real data - do nothing
506 return 1;
509 static unsigned int WINAPI expGetDriveTypeA( const char *root )
511 dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
512 // hack return as Fixed Drive Type
513 return DRIVE_FIXED;
516 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
518 dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
519 // hack only have one drive c:\ in this hack
520 *buffer++='c';
521 *buffer++=':';
522 *buffer++='\\';
523 *buffer++='\0';
524 *buffer= '\0';
525 return 4; // 1 drive * 4 bytes (includes null)
529 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
531 int result = (count == 0 || ptr != 0) ? 0 : 1;
532 dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
533 return result;
535 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
537 int result = (count == 0 || ptr != 0) ? 0 : 1;
538 dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
539 return result;
541 static int WINAPI expDisableThreadLibraryCalls(int module)
543 dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
544 return 0;
547 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
549 HMODULE result;
550 if (pdrv==NULL)
551 result=0;
552 else
553 result=pdrv->hDriverModule;
554 dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
555 return result;
558 #define MODULE_HANDLE_kernel32 ((HMODULE)0x120)
559 #define MODULE_HANDLE_user32 ((HMODULE)0x121)
560 #ifdef CONFIG_QTX_CODECS
561 #define MODULE_HANDLE_wininet ((HMODULE)0x122)
562 #define MODULE_HANDLE_ddraw ((HMODULE)0x123)
563 #define MODULE_HANDLE_advapi32 ((HMODULE)0x124)
564 #endif
565 #define MODULE_HANDLE_comdlg32 ((HMODULE)0x125)
566 #define MODULE_HANDLE_msvcrt ((HMODULE)0x126)
567 #define MODULE_HANDLE_ole32 ((HMODULE)0x127)
568 #define MODULE_HANDLE_winmm ((HMODULE)0x128)
569 #define MODULE_HANDLE_psapi ((HMODULE)0x129)
571 static HMODULE WINAPI expGetModuleHandleA(const char* name)
573 WINE_MODREF* wm;
574 HMODULE result;
575 if(!name)
576 #ifdef CONFIG_QTX_CODECS
577 result=1;
578 #else
579 result=0;
580 #endif
581 else
583 wm=MODULE_FindModule(name);
584 if(wm==0)result=0;
585 else
586 result=(HMODULE)(wm->module);
588 if(!result)
590 if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
591 result=MODULE_HANDLE_kernel32;
592 #ifdef CONFIG_QTX_CODECS
593 if(name && strcasecmp(name, "user32")==0)
594 result=MODULE_HANDLE_user32;
595 #endif
597 dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
598 return result;
601 static HMODULE WINAPI expGetModuleHandleW(const uint16_t* name)
603 char aname[256];
604 int pos = 0;
605 while (*name) {
606 if (*name > 256 || pos >= sizeof(aname) - 1)
607 return NULL;
608 aname[pos++] = *name++;
610 aname[pos] = 0;
611 return expGetModuleHandleA(aname);
614 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
615 void* lpStartAddress, void* lpParameter,
616 long dwFlags, long* dwThreadId)
618 pthread_t *pth;
619 // printf("CreateThread:");
620 pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
621 pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
622 if(dwFlags)
623 printf( "WARNING: CreateThread flags not supported\n");
624 if(dwThreadId)
625 *dwThreadId=(long)pth;
626 if(list==NULL)
628 list=my_mreq(sizeof(th_list), 1);
629 list->next=list->prev=NULL;
631 else
633 list->next=my_mreq(sizeof(th_list), 0);
634 list->next->prev=list;
635 list->next->next=NULL;
636 list=list->next;
638 list->thread=pth;
639 dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
640 pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
641 return pth;
644 struct mutex_list_t;
646 struct mutex_list_t
648 char type;
649 pthread_mutex_t *pm;
650 pthread_cond_t *pc;
651 char state;
652 char reset;
653 char name[128];
654 int semaphore;
655 struct mutex_list_t* next;
656 struct mutex_list_t* prev;
658 typedef struct mutex_list_t mutex_list;
659 static mutex_list* mlist=NULL;
661 void destroy_event(void* event)
663 mutex_list* pp=mlist;
664 // printf("garbage collector: destroy_event(%x)\n", event);
665 while(pp)
667 if(pp==(mutex_list*)event)
669 if(pp->next)
670 pp->next->prev=pp->prev;
671 if(pp->prev)
672 pp->prev->next=pp->next;
673 if(mlist==(mutex_list*)event)
674 mlist=mlist->prev;
676 pp=mlist;
677 while(pp)
679 printf("%x => ", pp);
680 pp=pp->prev;
682 printf("0\n");
684 return;
686 pp=pp->prev;
690 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
691 char bInitialState, const char* name)
693 pthread_mutex_t *pm;
694 pthread_cond_t *pc;
696 mutex_list* pp;
697 pp=mlist;
698 while(pp)
700 printf("%x => ", pp);
701 pp=pp->prev;
703 printf("0\n");
705 if(mlist!=NULL)
707 mutex_list* pp=mlist;
708 if(name!=NULL)
711 if((strcmp(pp->name, name)==0) && (pp->type==0))
713 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
714 pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
715 return pp->pm;
717 }while((pp=pp->prev) != NULL);
719 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
720 pthread_mutex_init(pm, NULL);
721 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
722 pthread_cond_init(pc, NULL);
723 if(mlist==NULL)
725 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
726 mlist->next=mlist->prev=NULL;
728 else
730 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
731 mlist->next->prev=mlist;
732 mlist->next->next=NULL;
733 mlist=mlist->next;
735 mlist->type=0; /* Type Event */
736 mlist->pm=pm;
737 mlist->pc=pc;
738 mlist->state=bInitialState;
739 mlist->reset=bManualReset;
740 if(name)
741 strncpy(mlist->name, name, 127);
742 else
743 mlist->name[0]=0;
744 if(pm==NULL)
745 dbgprintf("ERROR::: CreateEventA failure\n");
747 if(bInitialState)
748 pthread_mutex_lock(pm);
750 if(name)
751 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
752 pSecAttr, bManualReset, bInitialState, name, name, mlist);
753 else
754 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
755 pSecAttr, bManualReset, bInitialState, mlist);
756 return mlist;
759 static void* WINAPI expSetEvent(void* event)
761 mutex_list *ml = (mutex_list *)event;
762 dbgprintf("SetEvent(%x) => 0x1\n", event);
763 pthread_mutex_lock(ml->pm);
764 if (ml->state == 0) {
765 ml->state = 1;
766 pthread_cond_signal(ml->pc);
768 pthread_mutex_unlock(ml->pm);
770 return (void *)1;
772 static void* WINAPI expResetEvent(void* event)
774 mutex_list *ml = (mutex_list *)event;
775 dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
776 pthread_mutex_lock(ml->pm);
777 ml->state = 0;
778 pthread_mutex_unlock(ml->pm);
780 return (void *)1;
783 static void* WINAPI expWaitForSingleObject(void* object, int duration)
785 mutex_list *ml = (mutex_list *)object;
786 // FIXME FIXME FIXME - this value is sometime unititialize !!!
787 int ret = WAIT_FAILED;
788 mutex_list* pp=mlist;
789 if(object == (void*)0xcfcf9898)
792 From GetCurrentThread() documentation:
793 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.
795 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.
797 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.
799 dbgprintf("WaitForSingleObject(thread_handle) called\n");
800 return (void*)WAIT_FAILED;
802 dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
804 // loop below was slightly fixed - its used just for checking if
805 // this object really exists in our list
806 if (!ml)
807 return (void*) ret;
808 while (pp && (pp->pm != ml->pm))
809 pp = pp->prev;
810 if (!pp) {
811 dbgprintf("WaitForSingleObject: NotFound\n");
812 return (void*)ret;
815 pthread_mutex_lock(ml->pm);
817 switch(ml->type) {
818 case 0: /* Event */
819 if (duration == 0) { /* Check Only */
820 if (ml->state == 1) ret = WAIT_FAILED;
821 else ret = WAIT_OBJECT_0;
823 if (duration == -1) { /* INFINITE */
824 if (ml->state == 0)
825 pthread_cond_wait(ml->pc,ml->pm);
826 if (ml->reset)
827 ml->state = 0;
828 ret = WAIT_OBJECT_0;
830 if (duration > 0) { /* Timed Wait */
831 struct timespec abstime;
832 struct timeval now;
833 gettimeofday(&now, 0);
834 abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
835 abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
836 if (ml->state == 0)
837 ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
838 if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
839 else ret = WAIT_OBJECT_0;
840 if (ml->reset)
841 ml->state = 0;
843 break;
844 case 1: /* Semaphore */
845 if (duration == 0) {
846 if(ml->semaphore==0) ret = WAIT_FAILED;
847 else {
848 ml->semaphore++;
849 ret = WAIT_OBJECT_0;
852 if (duration == -1) {
853 if (ml->semaphore==0)
854 pthread_cond_wait(ml->pc,ml->pm);
855 ml->semaphore--;
857 break;
859 pthread_mutex_unlock(ml->pm);
861 dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
862 return (void *)ret;
865 #ifdef CONFIG_QTX_CODECS
866 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
867 int WaitAll, int duration)
869 int i;
870 void *object;
871 void *ret;
873 dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
874 count, objects, WaitAll, duration);
876 for (i = 0; i < count; i++)
878 object = (void *)objects[i];
879 ret = expWaitForSingleObject(object, duration);
880 if (WaitAll)
881 dbgprintf("WaitAll flag not yet supported...\n");
882 else
883 return ret;
885 return NULL;
888 static void WINAPI expExitThread(int retcode)
890 dbgprintf("ExitThread(%d)\n", retcode);
891 pthread_exit(&retcode);
894 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
895 char bInitialOwner, const char *name)
897 HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
899 if (name)
900 dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
901 pSecAttr, bInitialOwner, name, mlist);
902 else
903 dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
904 pSecAttr, bInitialOwner, mlist);
905 #ifndef CONFIG_QTX_CODECS
906 /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
907 waits for ever, else it works ;) */
908 return mlist;
909 #endif
912 static int WINAPI expReleaseMutex(HANDLE hMutex)
914 dbgprintf("ReleaseMutex(%x) => 1\n", hMutex);
915 /* FIXME:XXX !! not yet implemented */
916 return 1;
918 #endif
920 static int pf_set = 0;
921 static BYTE PF[64] = {0,};
923 static void DumpSystemInfo(const SYSTEM_INFO* si)
925 dbgprintf(" Processor architecture %d\n", si->u.s.wProcessorArchitecture);
926 dbgprintf(" Page size: %d\n", si->dwPageSize);
927 dbgprintf(" Minimum app address: %d\n", si->lpMinimumApplicationAddress);
928 dbgprintf(" Maximum app address: %d\n", si->lpMaximumApplicationAddress);
929 dbgprintf(" Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
930 dbgprintf(" Number of processors: %d\n", si->dwNumberOfProcessors);
931 dbgprintf(" Processor type: 0x%x\n", si->dwProcessorType);
932 dbgprintf(" Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
933 dbgprintf(" Processor level: 0x%x\n", si->wProcessorLevel);
934 dbgprintf(" Processor revision: 0x%x\n", si->wProcessorRevision);
937 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
939 /* FIXME: better values for the two entries below... */
940 static int cache = 0;
941 static SYSTEM_INFO cachedsi;
942 dbgprintf("GetSystemInfo(%p) =>\n", si);
944 if (cache) {
945 goto exit;
947 memset(PF,0,sizeof(PF));
948 pf_set = 1;
950 cachedsi.u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
951 cachedsi.dwPageSize = getpagesize();
953 /* FIXME: better values for the two entries below... */
954 cachedsi.lpMinimumApplicationAddress = (void *)0x00000000;
955 cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
956 cachedsi.dwActiveProcessorMask = 1;
957 cachedsi.dwNumberOfProcessors = 1;
958 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
959 cachedsi.dwAllocationGranularity = 0x10000;
960 cachedsi.wProcessorLevel = 5; /* pentium */
961 cachedsi.wProcessorRevision = 0x0101;
963 /* mplayer's way to detect PF's */
965 #include "cpudetect.h"
967 if (gCpuCaps.hasMMX)
968 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
969 if (gCpuCaps.hasSSE)
970 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
971 if (gCpuCaps.hasSSE2)
972 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
973 if (gCpuCaps.has3DNow)
974 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
976 if (gCpuCaps.cpuType == 4)
978 cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
979 cachedsi.wProcessorLevel = 4;
981 else if (gCpuCaps.cpuType >= 5)
983 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
984 cachedsi.wProcessorLevel = 5;
986 else
988 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
989 cachedsi.wProcessorLevel = 3;
991 cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
992 cachedsi.dwNumberOfProcessors = 1; /* hardcoded */
995 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
996 fdiv_bug and fpu emulation flags -- alex/MPlayer */
997 #ifdef __linux__
999 char buf[20];
1000 char line[200];
1001 FILE *f = fopen ("/proc/cpuinfo", "r");
1003 if (!f)
1005 mp_msg(MSGT_WIN32, MSGL_WARN, "expGetSystemInfo: "
1006 "/proc/cpuinfo not readable! "
1007 "Expect bad performance and/or weird behaviour\n");
1008 goto exit;
1010 while (fgets(line,200,f)!=NULL) {
1011 char *s,*value;
1013 /* NOTE: the ':' is the only character we can rely on */
1014 if (!(value = strchr(line,':')))
1015 continue;
1016 /* terminate the valuename */
1017 *value++ = '\0';
1018 /* skip any leading spaces */
1019 while (*value==' ') value++;
1020 if ((s=strchr(value,'\n')))
1021 *s='\0';
1023 /* 2.1 method */
1024 if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
1025 if (isdigit (value[0])) {
1026 switch (value[0] - '0') {
1027 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1028 cachedsi.wProcessorLevel= 3;
1029 break;
1030 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1031 cachedsi.wProcessorLevel= 4;
1032 break;
1033 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1034 cachedsi.wProcessorLevel= 5;
1035 break;
1036 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1037 cachedsi.wProcessorLevel= 5;
1038 break;
1039 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1040 cachedsi.wProcessorLevel= 5;
1041 break;
1044 /* set the CPU type of the current processor */
1045 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1046 continue;
1048 /* old 2.0 method */
1049 if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
1050 if ( isdigit (value[0]) && value[1] == '8' &&
1051 value[2] == '6' && value[3] == 0
1053 switch (value[0] - '0') {
1054 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1055 cachedsi.wProcessorLevel= 3;
1056 break;
1057 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1058 cachedsi.wProcessorLevel= 4;
1059 break;
1060 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1061 cachedsi.wProcessorLevel= 5;
1062 break;
1063 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1064 cachedsi.wProcessorLevel= 5;
1065 break;
1066 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1067 cachedsi.wProcessorLevel= 5;
1068 break;
1071 /* set the CPU type of the current processor */
1072 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1073 continue;
1075 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
1076 if (!lstrncmpiA(value,"yes",3))
1077 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
1079 continue;
1081 if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
1082 if (!lstrncmpiA(value,"no",2))
1083 PF[PF_FLOATING_POINT_EMULATED] = TRUE;
1085 continue;
1087 if (!lstrncmpiA(line,"processor",strlen("processor"))) {
1088 /* processor number counts up...*/
1089 unsigned int x;
1091 if (sscanf(value,"%d",&x))
1092 if (x+1>cachedsi.dwNumberOfProcessors)
1093 cachedsi.dwNumberOfProcessors=x+1;
1095 /* Create a new processor subkey on a multiprocessor
1096 * system
1098 sprintf(buf,"%d",x);
1100 if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
1101 int x;
1103 if (sscanf(value,"%d",&x))
1104 cachedsi.wProcessorRevision = x;
1107 ( (!lstrncmpiA(line,"flags",strlen("flags")))
1108 || (!lstrncmpiA(line,"features",strlen("features"))) )
1110 if (strstr(value,"cx8"))
1111 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1112 if (strstr(value,"mmx"))
1113 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1114 if (strstr(value,"tsc"))
1115 PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
1116 if (strstr(value,"xmm") || strstr(value,"sse"))
1117 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1118 if (strstr(value,"sse2"))
1119 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
1120 if (strstr(value,"3dnow"))
1121 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1124 fclose (f);
1126 * ad hoc fix for smp machines.
1127 * some problems on WaitForSingleObject,CreateEvent,SetEvent
1128 * CreateThread ...etc..
1131 cachedsi.dwNumberOfProcessors=1;
1133 #endif /* __linux__ */
1134 cache = 1;
1135 exit:
1136 memcpy(si,&cachedsi,sizeof(*si));
1137 DumpSystemInfo(si);
1140 // avoid undefined expGetSystemInfo
1141 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
1143 WIN_BOOL result = 0;
1144 if (!pf_set)
1146 SYSTEM_INFO si;
1147 expGetSystemInfo(&si);
1149 if(v<64) result=PF[v];
1150 dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
1151 return result;
1154 static WIN_BOOL WINAPI expIsDebuggerPresent(void)
1156 return 0;
1159 static long WINAPI expGetVersion(void)
1161 dbgprintf("GetVersion() => 0xC0000004\n");
1162 return 0xC0000004;//Windows 95
1165 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
1167 // printf("HeapCreate:");
1168 HANDLE result;
1169 if(init_size==0)
1170 result=(HANDLE)my_mreq(0x110000, 0);
1171 else
1172 result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
1173 dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
1174 return result;
1177 // this is another dirty hack
1178 // VP31 is releasing one allocated Heap chunk twice
1179 // we will silently ignore this second call...
1180 static void* heapfreehack = 0;
1181 static int heapfreehackshown = 0;
1182 //void trapbug(void);
1183 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
1185 void* z;
1187 Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
1188 HeapAlloc returns area larger than size argument :-/
1190 actually according to M$ Doc HeapCreate size should be rounded
1191 to page boundaries thus we should simulate this
1193 //if (size == 22276) trapbug();
1194 z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
1195 if(z==0)
1196 printf("HeapAlloc failure\n");
1197 dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
1198 heapfreehack = 0; // reset
1199 return z;
1201 static long WINAPI expHeapDestroy(void* heap)
1203 dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
1204 my_release(heap);
1205 return 1;
1208 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
1210 dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
1211 if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
1212 && lpMem != (void*)0xbdbdbdbd)
1213 // 0xbdbdbdbd is for i263_drv.drv && libefence
1214 // it seems to be reading from relased memory
1215 // EF_PROTECT_FREE doens't show any probleme
1216 my_release(lpMem);
1217 else
1219 if (!heapfreehackshown++)
1220 printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
1222 heapfreehack = lpMem;
1223 return 1;
1225 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
1227 long result=my_size(pointer);
1228 dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
1229 return result;
1231 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
1233 long orgsize = my_size(lpMem);
1234 dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
1235 return my_realloc(lpMem, size);
1237 static long WINAPI expGetProcessHeap(void)
1239 dbgprintf("GetProcessHeap() => 1\n");
1240 return 1;
1242 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
1244 void* z = VirtualAlloc(v1, v2, v3, v4);
1245 if(z==0)
1246 printf("VirtualAlloc failure\n");
1247 dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
1248 return z;
1250 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
1252 int result = VirtualFree(v1,v2,v3);
1253 dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
1254 return result;
1257 /* we're building a table of critical sections. cs_win pointer uses the DLL
1258 cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
1259 struct critsecs_list_t
1261 CRITICAL_SECTION *cs_win;
1262 struct CRITSECT *cs_unix;
1265 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
1266 #undef CRITSECS_NEWTYPE
1267 //#define CRITSECS_NEWTYPE 1
1269 #ifdef CRITSECS_NEWTYPE
1270 /* increased due to ucod needs more than 32 entries */
1271 /* and 64 should be enough for everything */
1272 #define CRITSECS_LIST_MAX 64
1273 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
1275 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
1277 int i;
1279 for (i=0; i < CRITSECS_LIST_MAX; i++)
1280 if (critsecs_list[i].cs_win == cs_win)
1281 return i;
1282 return -1;
1285 static int critsecs_get_unused(void)
1287 int i;
1289 for (i=0; i < CRITSECS_LIST_MAX; i++)
1290 if (critsecs_list[i].cs_win == NULL)
1291 return i;
1292 return -1;
1295 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
1297 int i;
1299 for (i=0; i < CRITSECS_LIST_MAX; i++)
1300 if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
1301 return critsecs_list[i].cs_unix;
1302 return NULL;
1304 #endif
1306 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
1308 dbgprintf("InitializeCriticalSection(0x%x)\n", c);
1309 /* if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
1311 printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
1312 sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
1313 return;
1315 /* pthread_mutex_init((pthread_mutex_t*)c, NULL); */
1316 #ifdef CRITSECS_NEWTYPE
1318 struct CRITSECT *cs;
1319 int i = critsecs_get_unused();
1321 if (i < 0)
1323 printf("InitializeCriticalSection(%p) - no more space in list\n", c);
1324 return;
1326 dbgprintf("got unused space at %d\n", i);
1327 cs = malloc(sizeof(struct CRITSECT));
1328 if (!cs)
1330 printf("InitializeCriticalSection(%p) - out of memory\n", c);
1331 return;
1333 pthread_mutex_init(&cs->mutex, NULL);
1334 cs->locked = 0;
1335 critsecs_list[i].cs_win = c;
1336 critsecs_list[i].cs_unix = cs;
1337 dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
1338 i, c, cs);
1340 #else
1342 struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
1343 0, AREATYPE_CRITSECT);
1344 pthread_mutex_init(&cs->mutex, NULL);
1345 cs->locked=0;
1346 cs->deadbeef = 0xdeadbeef;
1347 *(void**)c = cs;
1349 #endif
1350 return;
1353 static void WINAPI expInitializeCriticalSectionAndSpinCount(CRITICAL_SECTION* c, DWORD spin)
1355 expInitializeCriticalSection(c);
1358 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
1360 #ifdef CRITSECS_NEWTYPE
1361 struct CRITSECT* cs = critsecs_get_unix(c);
1362 #else
1363 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1364 #endif
1365 dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
1366 if (!cs)
1368 dbgprintf("entered uninitialized critisec!\n");
1369 expInitializeCriticalSection(c);
1370 #ifdef CRITSECS_NEWTYPE
1371 cs=critsecs_get_unix(c);
1372 #else
1373 cs = (*(struct CRITSECT**)c);
1374 #endif
1375 dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
1377 if(cs->locked)
1378 if(cs->id==pthread_self())
1379 return;
1380 pthread_mutex_lock(&(cs->mutex));
1381 cs->locked=1;
1382 cs->id=pthread_self();
1383 return;
1385 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
1387 #ifdef CRITSECS_NEWTYPE
1388 struct CRITSECT* cs = critsecs_get_unix(c);
1389 #else
1390 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1391 #endif
1392 // struct CRITSECT* cs=(struct CRITSECT*)c;
1393 dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
1394 if (!cs)
1396 dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
1397 return;
1399 if (cs->locked)
1401 cs->locked=0;
1402 pthread_mutex_unlock(&(cs->mutex));
1404 else
1405 dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
1406 return;
1409 static void expfree(void* mem); /* forward declaration */
1411 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
1413 #ifdef CRITSECS_NEWTYPE
1414 struct CRITSECT* cs = critsecs_get_unix(c);
1415 #else
1416 struct CRITSECT* cs= (*(struct CRITSECT**)c);
1417 #endif
1418 // struct CRITSECT* cs=(struct CRITSECT*)c;
1419 dbgprintf("DeleteCriticalSection(0x%x)\n",c);
1421 if (!cs)
1423 dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
1424 return;
1427 if (cs->locked)
1429 dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
1430 pthread_mutex_unlock(&(cs->mutex));
1433 #ifndef GARBAGE
1434 pthread_mutex_destroy(&(cs->mutex));
1435 // released by GarbageCollector in my_relase otherwise
1436 #endif
1437 my_release(cs);
1438 #ifdef CRITSECS_NEWTYPE
1440 int i = critsecs_get_pos(c);
1442 if (i < 0)
1444 printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
1445 return;
1448 critsecs_list[i].cs_win = NULL;
1449 expfree(critsecs_list[i].cs_unix);
1450 critsecs_list[i].cs_unix = NULL;
1451 dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
1453 #endif
1454 return;
1456 static int WINAPI expGetCurrentThreadId(void)
1458 dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
1459 return pthread_self();
1461 static int WINAPI expGetCurrentProcess(void)
1463 dbgprintf("GetCurrentProcess() => %d\n", getpid());
1464 return getpid();
1467 #ifdef CONFIG_QTX_CODECS
1468 // this version is required for Quicktime codecs (.qtx/.qts) to work.
1469 // (they assume some pointers at FS: segment)
1471 extern void* fs_seg;
1473 //static int tls_count;
1474 static int tls_use_map[64];
1475 static int WINAPI expTlsAlloc(void)
1477 int i;
1478 for(i=0; i<64; i++)
1479 if(tls_use_map[i]==0)
1481 tls_use_map[i]=1;
1482 dbgprintf("TlsAlloc() => %d\n",i);
1483 return i;
1485 dbgprintf("TlsAlloc() => -1 (ERROR)\n");
1486 return -1;
1489 //static int WINAPI expTlsSetValue(DWORD index, void* value)
1490 static int WINAPI expTlsSetValue(int index, void* value)
1492 dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
1493 // if((index<0) || (index>64))
1494 if((index>=64))
1495 return 0;
1496 *(void**)((char*)fs_seg+0x88+4*index) = value;
1497 return 1;
1500 static void* WINAPI expTlsGetValue(DWORD index)
1502 dbgprintf("TlsGetValue(%d)\n",index);
1503 // if((index<0) || (index>64))
1504 if((index>=64)) return NULL;
1505 return *(void**)((char*)fs_seg+0x88+4*index);
1508 static int WINAPI expTlsFree(int idx)
1510 int index = (int) idx;
1511 dbgprintf("TlsFree(%d)\n",index);
1512 if((index<0) || (index>64))
1513 return 0;
1514 tls_use_map[index]=0;
1515 return 1;
1518 #else
1519 struct tls_s {
1520 void* value;
1521 int used;
1522 struct tls_s* prev;
1523 struct tls_s* next;
1526 static void* WINAPI expTlsAlloc(void)
1528 if (g_tls == NULL)
1530 g_tls=my_mreq(sizeof(tls_t), 0);
1531 g_tls->next=g_tls->prev=NULL;
1533 else
1535 g_tls->next=my_mreq(sizeof(tls_t), 0);
1536 g_tls->next->prev=g_tls;
1537 g_tls->next->next=NULL;
1538 g_tls=g_tls->next;
1540 dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
1541 if (g_tls)
1542 g_tls->value=0; /* XXX For Divx.dll */
1543 return g_tls;
1546 static int WINAPI expTlsSetValue(void* idx, void* value)
1548 tls_t* index = (tls_t*) idx;
1549 int result;
1550 if(index==0)
1551 result=0;
1552 else
1554 index->value=value;
1555 result=1;
1557 dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
1558 return result;
1560 static void* WINAPI expTlsGetValue(void* idx)
1562 tls_t* index = (tls_t*) idx;
1563 void* result;
1564 if(index==0)
1565 result=0;
1566 else
1567 result=index->value;
1568 dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
1569 return result;
1571 static int WINAPI expTlsFree(void* idx)
1573 tls_t* index = (tls_t*) idx;
1574 int result;
1575 if(index==0)
1576 result=0;
1577 else
1579 if(index->next)
1580 index->next->prev=index->prev;
1581 if(index->prev)
1582 index->prev->next=index->next;
1583 if (g_tls == index)
1584 g_tls = index->prev;
1585 my_release((void*)index);
1586 result=1;
1588 dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
1589 return result;
1591 #endif
1593 static void* WINAPI expLocalAlloc(int flags, int size)
1595 void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
1596 if (z == 0)
1597 printf("LocalAlloc() failed\n");
1598 dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1599 return z;
1602 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
1604 void *newpointer;
1605 int oldsize;
1607 newpointer=NULL;
1608 if (flags & LMEM_MODIFY) {
1609 dbgprintf("LocalReAlloc MODIFY\n");
1610 return (void *)handle;
1612 oldsize = my_size((void *)handle);
1613 newpointer = my_realloc((void *)handle,size);
1614 dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
1616 return newpointer;
1619 static void* WINAPI expLocalLock(void* z)
1621 dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
1622 return z;
1625 static void* WINAPI expGlobalAlloc(int flags, int size)
1627 void* z;
1628 dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
1630 z=my_mreq(size, (flags & GMEM_ZEROINIT));
1631 //z=calloc(size, 1);
1632 //z=malloc(size);
1633 if(z==0)
1634 printf("GlobalAlloc() failed\n");
1635 dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1636 return z;
1638 static void* WINAPI expGlobalLock(void* z)
1640 dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
1641 return z;
1643 // pvmjpg20 - but doesn't work anyway
1644 static int WINAPI expGlobalSize(void* amem)
1646 int size = 100000;
1647 #ifdef GARBAGE
1648 alloc_header* header = last_alloc;
1649 alloc_header* mem = (alloc_header*) amem - 1;
1650 if (amem == 0)
1651 return 0;
1652 pthread_mutex_lock(&memmut);
1653 while (header)
1655 if (header->deadbeef != 0xdeadbeef)
1657 dbgprintf("FATAL found corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
1658 break;
1661 if (header == mem)
1663 size = header->size;
1664 break;
1667 header = header->prev;
1669 pthread_mutex_unlock(&memmut);
1670 #endif
1672 dbgprintf("GlobalSize(0x%x)\n", amem);
1673 return size;
1676 static int WINAPI expLoadIconA( long hinstance, char *name )
1678 dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
1679 return 1;
1682 static int WINAPI expLoadStringA(long instance, long id, void* buf, long size)
1684 int result=LoadStringA(instance, id, buf, size);
1685 // if(buf)
1686 dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
1687 instance, id, buf, size, result, buf);
1688 // else
1689 // dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
1690 // instance, id, buf, size, result);
1691 return result;
1694 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
1696 #warning FIXME
1697 int i;
1698 int result;
1699 if(s2==0)
1700 result=1;
1701 else
1703 if(siz1>siz2/2)siz1=siz2/2;
1704 for(i=1; i<=siz1; i++)
1706 *s2=*s1;
1707 if(!*s1)break;
1708 s2++;
1709 s1++;
1711 result=i;
1713 if(s1)
1714 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
1715 "size %d, dest buffer 0x%x, dest size %d) => %d\n",
1716 v1, v2, s1, s1, siz1, s2, siz2, result);
1717 else
1718 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
1719 "size %d, dest buffer 0x%x, dest size %d) =>\n",
1720 v1, v2, siz1, s2, siz2, result);
1721 return result;
1723 static void wch_print(const short* str)
1725 dbgprintf(" src: ");
1726 while(*str)dbgprintf("%c", *str++);
1727 dbgprintf("\n");
1729 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
1730 char* s2, int siz2, char* c3, int* siz3)
1732 int result;
1733 dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
1734 "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
1735 result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
1736 dbgprintf("=> %d\n", result);
1737 //if(s1)wch_print(s1);
1738 if(s2)dbgprintf(" dest: %s\n", s2);
1739 return result;
1741 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
1743 dbgprintf("GetVersionExA(0x%x) => 1\n");
1744 c->dwOSVersionInfoSize=sizeof(*c);
1745 c->dwMajorVersion=4;
1746 c->dwMinorVersion=0;
1747 c->dwBuildNumber=0x4000457;
1748 #if 1
1749 // leave it here for testing win9x-only codecs
1750 c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
1751 strcpy(c->szCSDVersion, " B");
1752 #else
1753 c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
1754 strcpy(c->szCSDVersion, "Service Pack 3");
1755 #endif
1756 dbgprintf(" Major version: 4\n Minor version: 0\n Build number: 0x4000457\n"
1757 " Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 3'\n");
1758 return 1;
1760 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
1761 long max_count, char* name)
1763 pthread_mutex_t *pm;
1764 pthread_cond_t *pc;
1766 mutex_list* pp;
1767 printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
1768 pp=mlist;
1769 while(pp)
1771 printf("%p => ", pp);
1772 pp=pp->prev;
1774 printf("0\n");
1776 if(mlist!=NULL)
1778 mutex_list* pp=mlist;
1779 if(name!=NULL)
1782 if((strcmp(pp->name, name)==0) && (pp->type==1))
1784 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1785 v1, init_count, max_count, name, name, mlist);
1786 return (HANDLE)mlist;
1788 }while((pp=pp->prev) != NULL);
1790 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1791 pthread_mutex_init(pm, NULL);
1792 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1793 pthread_cond_init(pc, NULL);
1794 if(mlist==NULL)
1796 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1797 mlist->next=mlist->prev=NULL;
1799 else
1801 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1802 mlist->next->prev=mlist;
1803 mlist->next->next=NULL;
1804 mlist=mlist->next;
1805 // printf("new semaphore %p\n", mlist);
1807 mlist->type=1; /* Type Semaphore */
1808 mlist->pm=pm;
1809 mlist->pc=pc;
1810 mlist->state=0;
1811 mlist->reset=0;
1812 mlist->semaphore=init_count;
1813 if(name!=NULL)
1814 strncpy(mlist->name, name, 64);
1815 else
1816 mlist->name[0]=0;
1817 if(pm==NULL)
1818 dbgprintf("ERROR::: CreateSemaphoreA failure\n");
1819 if(name)
1820 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1821 v1, init_count, max_count, name, name, mlist);
1822 else
1823 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
1824 v1, init_count, max_count, mlist);
1825 return (HANDLE)mlist;
1828 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
1830 // The state of a semaphore object is signaled when its count
1831 // is greater than zero and nonsignaled when its count is equal to zero
1832 // Each time a waiting thread is released because of the semaphore's signaled
1833 // state, the count of the semaphore is decreased by one.
1834 mutex_list *ml = (mutex_list *)hsem;
1836 pthread_mutex_lock(ml->pm);
1837 if (prev_count != 0) *prev_count = ml->semaphore;
1838 if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
1839 ml->semaphore += increment;
1840 pthread_mutex_unlock(ml->pm);
1841 dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
1842 hsem, increment, prev_count);
1843 return 1;
1847 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
1849 long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
1850 dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
1851 key, subkey, reserved, access, newkey, result);
1852 if(newkey)dbgprintf(" New key: 0x%x\n", *newkey);
1853 return result;
1855 static long WINAPI expRegCloseKey(long key)
1857 long result=RegCloseKey(key);
1858 dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
1859 return result;
1861 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
1863 long result=RegQueryValueExA(key, value, reserved, type, data, count);
1864 dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
1865 " => 0x%x\n", key, value, reserved, data, count, result);
1866 if(data && count)dbgprintf(" read %d bytes: '%s'\n", *count, data);
1867 return result;
1870 //from wine source dlls/advapi32/registry.c
1871 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
1873 dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
1874 return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
1875 KEY_ALL_ACCESS , NULL, retkey, NULL );
1878 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
1879 void* classs, long options, long security,
1880 void* sec_attr, int* newkey, int* status)
1882 long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
1883 dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
1884 " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
1885 key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
1886 if(!result && newkey) dbgprintf(" New key: 0x%x\n", *newkey);
1887 if(!result && status) dbgprintf(" New key status: 0x%x\n", *status);
1888 return result;
1890 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
1892 long result=RegSetValueExA(key, name, v1, v2, data, size);
1893 dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
1894 key, name, v1, v2, data, *(int*)data, data, size, result);
1895 return result;
1898 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
1900 long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
1901 dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
1902 hKey, lpSubKey, phkResult, result);
1903 if(!result && phkResult) dbgprintf(" New key: 0x%x\n", *phkResult);
1904 return result;
1907 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1908 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
1910 return RegEnumValueA(hkey, index, value, val_count,
1911 reserved, type, data, count);
1914 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
1915 LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
1916 LPFILETIME lpftLastWriteTime)
1918 return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
1919 lpcbClass, lpftLastWriteTime);
1922 static long WINAPI expQueryPerformanceCounter(long long* z)
1924 longcount(z);
1925 dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
1926 return 1;
1930 * dummy function RegQueryInfoKeyA(), required by vss codecs
1932 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
1933 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
1934 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
1935 LPDWORD security, FILETIME *modif )
1937 return ERROR_SUCCESS;
1941 * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
1943 static double linux_cpuinfo_freq(void)
1945 double freq=-1;
1946 FILE *f;
1947 char line[200];
1948 char *s,*value;
1950 f = fopen ("/proc/cpuinfo", "r");
1951 if (f != NULL) {
1952 while (fgets(line,sizeof(line),f)!=NULL) {
1953 /* NOTE: the ':' is the only character we can rely on */
1954 if (!(value = strchr(line,':')))
1955 continue;
1956 /* terminate the valuename */
1957 *value++ = '\0';
1958 /* skip any leading spaces */
1959 while (*value==' ') value++;
1960 if ((s=strchr(value,'\n')))
1961 *s='\0';
1963 if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
1964 && sscanf(value, "%lf", &freq) == 1) {
1965 freq*=1000;
1966 break;
1969 fclose(f);
1971 return freq;
1975 static double solaris_kstat_freq(void)
1977 #if defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
1979 * try to extract the CPU speed from the solaris kernel's kstat data
1981 kstat_ctl_t *kc;
1982 kstat_t *ksp;
1983 kstat_named_t *kdata;
1984 int mhz = 0;
1986 kc = kstat_open();
1987 if (kc != NULL)
1989 ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
1991 /* kstat found and name/value pairs? */
1992 if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
1994 /* read the kstat data from the kernel */
1995 if (kstat_read(kc, ksp, NULL) != -1)
1998 * lookup desired "clock_MHz" entry, check the expected
1999 * data type
2001 kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
2002 if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
2003 mhz = kdata->value.i32;
2006 kstat_close(kc);
2009 if (mhz > 0)
2010 return mhz * 1000.;
2011 #endif /* HAVE_LIBKSTAT */
2012 return -1; // kstat stuff is not available, CPU freq is unknown
2016 * Measure CPU freq using the pentium's time stamp counter register (TSC)
2018 static double tsc_freq(void)
2020 static double ofreq=0.0;
2021 int i;
2022 int x,y;
2023 i=time(NULL);
2024 if (ofreq != 0.0) return ofreq;
2025 while(i==time(NULL));
2026 x=localcount();
2027 i++;
2028 while(i==time(NULL));
2029 y=localcount();
2030 ofreq = (double)(y-x)/1000.;
2031 return ofreq;
2034 static double CPU_Freq(void)
2036 double freq;
2038 if ((freq = linux_cpuinfo_freq()) > 0)
2039 return freq;
2041 if ((freq = solaris_kstat_freq()) > 0)
2042 return freq;
2044 return tsc_freq();
2047 static long WINAPI expQueryPerformanceFrequency(long long* z)
2049 *z=(long long)CPU_Freq();
2050 dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
2051 return 1;
2053 static long WINAPI exptimeGetTime(void)
2055 struct timeval t;
2056 long result;
2057 gettimeofday(&t, 0);
2058 result=1000*t.tv_sec+t.tv_usec/1000;
2059 dbgprintf("timeGetTime() => %d\n", result);
2060 return result;
2062 static void* WINAPI expLocalHandle(void* v)
2064 dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
2065 return v;
2068 static void* WINAPI expGlobalHandle(void* v)
2070 dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
2071 return v;
2073 static int WINAPI expGlobalUnlock(void* v)
2075 dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
2076 return 1;
2078 static void* WINAPI expGlobalFree(void* v)
2080 dbgprintf("GlobalFree(0x%x) => 0\n", v);
2081 my_release(v);
2082 //free(v);
2083 return 0;
2086 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
2088 void* result=my_realloc(v, size);
2089 //void* result=realloc(v, size);
2090 dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
2091 return result;
2094 static int WINAPI expLocalUnlock(void* v)
2096 dbgprintf("LocalUnlock(0x%x) => 1\n", v);
2097 return 1;
2100 static void* WINAPI expLocalFree(void* v)
2102 dbgprintf("LocalFree(0x%x) => 0\n", v);
2103 my_release(v);
2104 return 0;
2106 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
2108 HRSRC result;
2110 result=FindResourceA(module, name, type);
2111 dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
2112 module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
2113 return result;
2116 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
2118 HGLOBAL result=LoadResource(module, res);
2119 dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
2120 return result;
2122 static void* WINAPI expLockResource(long res)
2124 void* result=LockResource(res);
2125 dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
2126 return result;
2128 static int WINAPI expFreeResource(long res)
2130 int result=FreeResource(res);
2131 dbgprintf("FreeResource(0x%x) => %d\n", res, result);
2132 return result;
2134 //bool fun(HANDLE)
2135 //!0 on success
2136 static int WINAPI expCloseHandle(long v1)
2138 dbgprintf("CloseHandle(0x%x) => 1\n", v1);
2139 /* do not close stdin,stdout and stderr */
2140 if (v1 > 2)
2141 if (!close(v1))
2142 return 0;
2143 return 1;
2146 static const char* WINAPI expGetCommandLineA(void)
2148 dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
2149 return "c:\\aviplay.exe";
2151 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
2152 static LPWSTR WINAPI expGetEnvironmentStringsW(void)
2154 dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
2155 return 0;
2157 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
2159 void* result=memset(p,0,len);
2160 dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
2161 return result;
2163 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
2165 void* result=memmove(dst,src,len);
2166 dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
2167 return result;
2170 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
2172 void* result=memset(p,ch,len);
2173 dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
2174 return result;
2176 static int WINAPI expFreeEnvironmentStringsW(short* strings)
2178 dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
2179 return 1;
2181 static int WINAPI expFreeEnvironmentStringsA(char* strings)
2183 dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
2184 return 1;
2187 static const char ch_envs[]=
2188 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
2189 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
2190 static LPCSTR WINAPI expGetEnvironmentStrings(void)
2192 dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
2193 return (LPCSTR)ch_envs;
2194 // dbgprintf("GetEnvironmentStrings() => 0\n");
2195 // return 0;
2198 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
2200 dbgprintf("GetStartupInfoA(0x%x) => 1\n");
2201 memset(s, 0, sizeof(*s));
2202 s->cb=sizeof(*s);
2203 // s->lpReserved="Reserved";
2204 // s->lpDesktop="Desktop";
2205 // s->lpTitle="Title";
2206 // s->dwX=s->dwY=0;
2207 // s->dwXSize=s->dwYSize=200;
2208 s->dwFlags=s->wShowWindow=1;
2209 // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
2210 dbgprintf(" cb=%d\n", s->cb);
2211 dbgprintf(" lpReserved='%s'\n", s->lpReserved);
2212 dbgprintf(" lpDesktop='%s'\n", s->lpDesktop);
2213 dbgprintf(" lpTitle='%s'\n", s->lpTitle);
2214 dbgprintf(" dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
2215 s->dwX, s->dwY, s->dwXSize, s->dwYSize);
2216 dbgprintf(" dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
2217 s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
2218 dbgprintf(" dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
2219 s->dwFlags, s->wShowWindow, s->cbReserved2);
2220 dbgprintf(" lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
2221 s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
2222 return 1;
2225 static int WINAPI expGetStdHandle(int z)
2227 dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
2228 return z+0x1234;
2231 #ifdef CONFIG_QTX_CODECS
2232 #define FILE_HANDLE_quicktimeqts ((HANDLE)0x444)
2233 #define FILE_HANDLE_quicktimeqtx ((HANDLE)0x445)
2234 #endif
2236 static int WINAPI expGetFileType(int handle)
2238 dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
2239 return 0x3;
2241 #ifdef CONFIG_QTX_CODECS
2242 static int WINAPI expGetFileAttributesA(char *filename)
2244 dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
2245 if (strstr(filename, "QuickTime.qts"))
2246 return FILE_ATTRIBUTE_SYSTEM;
2247 return FILE_ATTRIBUTE_NORMAL;
2249 #endif
2250 static int WINAPI expSetHandleCount(int count)
2252 dbgprintf("SetHandleCount(0x%x) => 1\n", count);
2253 return 1;
2255 static int WINAPI expGetACP(void)
2257 dbgprintf("GetACP() => 0\n");
2258 return 0;
2260 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
2262 WINE_MODREF *mr;
2263 int result;
2264 //printf("File name of module %X (%s) requested\n", module, s);
2266 if (module == 0 && len >= 12)
2268 /* return caller program name */
2269 strcpy(s, "aviplay.dll");
2270 result=1;
2272 else if(s==0)
2273 result=0;
2274 else
2275 if(len<35)
2276 result=0;
2277 else
2279 result=1;
2280 strcpy(s, "c:\\windows\\system\\");
2281 mr=MODULE32_LookupHMODULE(module);
2282 if(mr==0)//oops
2283 strcat(s, "aviplay.dll");
2284 else
2285 if(strrchr(mr->filename, '/')==NULL)
2286 strcat(s, mr->filename);
2287 else
2288 strcat(s, strrchr(mr->filename, '/')+1);
2290 if(!s)
2291 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
2292 module, s, len, result);
2293 else
2294 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
2295 module, s, len, result, s);
2296 return result;
2299 static int WINAPI expGetModuleBaseNameA(int process, int module, char* s, int len)
2301 int result = 0;
2303 if (s && len) {
2304 av_strlcpy(s, "aviplay.dll", len);
2305 result = strlen(s);
2308 dbgprintf("GetModuleBaseNameA(0x%x, 0x%x, 0x%x, %d) => %d\n",
2309 process, module, s, len, result);
2311 return result;
2314 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
2316 dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
2317 return 1;//unsupported and probably won't ever be supported
2320 static int WINAPI expLoadLibraryA(char* name)
2322 int result = 0;
2323 char* lastbc;
2324 if (!name)
2325 return -1;
2326 // we skip to the last backslash
2327 // this is effectively eliminating weird characters in
2328 // the text output windows
2330 lastbc = strrchr(name, '\\');
2331 if (lastbc)
2333 int i;
2334 lastbc++;
2335 for (i = 0; 1 ;i++)
2337 name[i] = *lastbc++;
2338 if (!name[i])
2339 break;
2342 if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
2343 if(strncmp(name, ".\\", 2)==0) name += 2;
2345 dbgprintf("Entering LoadLibraryA(%s)\n", name);
2347 // PIMJ and VIVO audio are loading kernel32.dll
2348 if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
2349 return MODULE_HANDLE_kernel32;
2350 // return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
2351 /* exported -> do not return failed! */
2353 if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
2354 // return MODULE_HANDLE_kernel32;
2355 return MODULE_HANDLE_user32;
2357 #ifdef CONFIG_QTX_CODECS
2358 if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
2359 return MODULE_HANDLE_wininet;
2360 if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
2361 return MODULE_HANDLE_ddraw;
2362 if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
2363 return MODULE_HANDLE_advapi32;
2364 #endif
2366 if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
2367 return MODULE_HANDLE_comdlg32;
2368 if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
2369 return MODULE_HANDLE_msvcrt;
2370 if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
2371 return MODULE_HANDLE_ole32;
2372 if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
2373 return MODULE_HANDLE_winmm;
2374 if (strcasecmp(name, "psapi.dll") == 0 || strcasecmp(name, "psapi") == 0)
2375 return MODULE_HANDLE_psapi;
2377 result=LoadLibraryA(name);
2378 dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
2380 return result;
2383 static int WINAPI expFreeLibrary(int module)
2385 #ifdef CONFIG_QTX_CODECS
2386 int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
2387 #else
2388 int result=FreeLibrary(module);
2389 #endif
2390 dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
2391 return result;
2394 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
2396 void* result;
2397 switch(mod){
2398 case MODULE_HANDLE_kernel32:
2399 result=LookupExternalByName("kernel32.dll", name); break;
2400 case MODULE_HANDLE_user32:
2401 result=LookupExternalByName("user32.dll", name); break;
2402 #ifdef CONFIG_QTX_CODECS
2403 case MODULE_HANDLE_wininet:
2404 result=LookupExternalByName("wininet.dll", name); break;
2405 case MODULE_HANDLE_ddraw:
2406 result=LookupExternalByName("ddraw.dll", name); break;
2407 case MODULE_HANDLE_advapi32:
2408 result=LookupExternalByName("advapi32.dll", name); break;
2409 #endif
2410 case MODULE_HANDLE_comdlg32:
2411 result=LookupExternalByName("comdlg32.dll", name); break;
2412 case MODULE_HANDLE_msvcrt:
2413 result=LookupExternalByName("msvcrt.dll", name); break;
2414 case MODULE_HANDLE_ole32:
2415 result=LookupExternalByName("ole32.dll", name); break;
2416 case MODULE_HANDLE_winmm:
2417 result=LookupExternalByName("winmm.dll", name); break;
2418 case MODULE_HANDLE_psapi:
2419 result=LookupExternalByName("psapi.dll", name); break;
2420 default:
2421 result=GetProcAddress(mod, name);
2423 if((unsigned int)name > 0xffff)
2424 dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
2425 else
2426 dbgprintf("GetProcAddress(0x%x, '%d') => 0x%x\n", mod, (int)name, result);
2427 return result;
2430 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
2431 long flProtect, long dwMaxHigh,
2432 long dwMaxLow, const char* name)
2434 long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
2435 if(!name)
2436 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2437 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
2438 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
2439 else
2440 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2441 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
2442 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
2443 return result;
2446 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
2448 long result=OpenFileMappingA(hFile, hz, name);
2449 if(!name)
2450 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
2451 hFile, hz, result);
2452 else
2453 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
2454 hFile, hz, name, name, result);
2455 return result;
2458 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
2459 DWORD offLow, DWORD size)
2461 dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
2462 file,mode,offHigh,offLow,size,(char*)file+offLow);
2463 return (char*)file+offLow;
2466 static void* WINAPI expUnmapViewOfFile(void* view)
2468 dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
2469 return 0;
2472 static void* WINAPI expSleep(int time)
2474 #if HAVE_NANOSLEEP
2475 /* solaris doesn't have thread safe usleep */
2476 struct timespec tsp;
2477 tsp.tv_sec = time / 1000000;
2478 tsp.tv_nsec = (time % 1000000) * 1000;
2479 nanosleep(&tsp, NULL);
2480 #else
2481 usleep(time);
2482 #endif
2483 dbgprintf("Sleep(%d) => 0\n", time);
2484 return 0;
2487 // why does IV32 codec want to call this? I don't know ...
2488 static int WINAPI expCreateCompatibleDC(int hdc)
2490 int dc = 0;//0x81;
2491 //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
2492 dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
2493 return dc;
2496 static int WINAPI expGetDeviceCaps(int hdc, int unk)
2498 dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
2499 #ifdef CONFIG_QTX_CODECS
2500 #define BITSPIXEL 12
2501 #define PLANES 14
2502 if (unk == BITSPIXEL)
2503 return 24;
2504 if (unk == PLANES)
2505 return 1;
2506 #endif
2507 return 1;
2510 static WIN_BOOL WINAPI expDeleteDC(int hdc)
2512 dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
2513 if (hdc == 0x81)
2514 return 1;
2515 return 0;
2518 static WIN_BOOL WINAPI expDeleteObject(int hdc)
2520 dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
2521 /* FIXME - implement code here */
2522 return 1;
2525 /* btvvc32.drv wants this one */
2526 static void* WINAPI expGetWindowDC(int hdc)
2528 dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
2529 return 0;
2532 #ifdef CONFIG_QTX_CODECS
2533 static int WINAPI expGetWindowRect(HWND win, RECT *r)
2535 dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
2536 /* (win == 0) => desktop */
2537 r->right = PSEUDO_SCREEN_WIDTH;
2538 r->left = 0;
2539 r->bottom = PSEUDO_SCREEN_HEIGHT;
2540 r->top = 0;
2541 return 1;
2544 static int WINAPI expMonitorFromWindow(HWND win, int flags)
2546 dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
2547 return 0;
2550 static int WINAPI expMonitorFromRect(RECT *r, int flags)
2552 dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
2553 return 0;
2556 static int WINAPI expMonitorFromPoint(void *p, int flags)
2558 dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
2559 return 0;
2562 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r,
2563 int WINAPI (*callback_proc)(), void *callback_param)
2565 dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
2566 dc, r, callback_proc, callback_param);
2567 return callback_proc(0, dc, r, callback_param);
2570 #if 0
2571 typedef struct tagMONITORINFO {
2572 DWORD cbSize;
2573 RECT rcMonitor;
2574 RECT rcWork;
2575 DWORD dwFlags;
2576 } MONITORINFO, *LPMONITORINFO;
2577 #endif
2579 #define CCHDEVICENAME 8
2580 typedef struct tagMONITORINFOEX {
2581 DWORD cbSize;
2582 RECT rcMonitor;
2583 RECT rcWork;
2584 DWORD dwFlags;
2585 TCHAR szDevice[CCHDEVICENAME];
2586 } MONITORINFOEX, *LPMONITORINFOEX;
2588 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
2590 dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
2592 lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
2593 lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
2594 lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
2595 lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
2597 lpmi->dwFlags = 1; /* primary monitor */
2599 if (lpmi->cbSize == sizeof(MONITORINFOEX))
2601 LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
2602 dbgprintf("MONITORINFOEX!\n");
2603 strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
2606 return 1;
2609 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
2610 void *dispdev, int flags)
2612 dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
2613 device, device, devnum, dispdev, flags);
2614 return 1;
2617 static int WINAPI expIsWindowVisible(HWND win)
2619 dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
2620 return 1;
2623 static HWND WINAPI expGetActiveWindow(void)
2625 dbgprintf("GetActiveWindow() => 0\n");
2626 return (HWND)0;
2629 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
2631 strncat(classname, "QuickTime", maxcount);
2632 dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
2633 win, classname, maxcount, strlen(classname));
2634 return strlen(classname);
2637 #define LPWNDCLASS void *
2638 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
2640 dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
2641 classname, classname, wndclass);
2642 return 1;
2645 static int WINAPI expGetWindowLongA(HWND win, int index)
2647 dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
2648 return 1;
2651 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
2653 dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
2654 return objsize;
2657 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
2659 dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
2660 return 0;
2663 static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
2665 int i, i2;
2666 dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
2667 i = callback_func(0, callback_param);
2668 i2 = callback_func(1, callback_param);
2669 return i && i2;
2672 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
2674 int tid = pthread_self();
2675 dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
2676 win, pid_data, tid);
2677 if (pid_data)
2678 *(int*)pid_data = tid;
2679 return tid;
2682 //HWND WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
2683 // INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
2685 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
2686 const char *winname, int style, int x, int y, int w, int h,
2687 HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
2689 printf("CreateWindowEx() called\n");
2690 dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
2691 exstyle, classname, classname, winname, winname, style, x, y, w, h,
2692 parent, menu, inst, param);
2693 printf("CreateWindowEx() called okey\n");
2694 return 1;
2697 static int WINAPI expwaveOutGetNumDevs(void)
2699 dbgprintf("waveOutGetNumDevs() => 0\n");
2700 return 0;
2702 #endif
2705 * Returns the number of milliseconds, modulo 2^32, since the start
2706 * of the wineserver.
2708 static int WINAPI expGetTickCount(void)
2710 static int tcstart = 0;
2711 struct timeval t;
2712 int tc;
2713 gettimeofday( &t, NULL );
2714 tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
2715 if (tcstart == 0)
2717 tcstart = 0;
2718 tc = 0;
2720 dbgprintf("GetTickCount() => %d\n", tc);
2721 return tc;
2724 static int WINAPI expCreateFontA(void)
2726 dbgprintf("CreateFontA() => 0x0\n");
2727 return 1;
2730 /* tried to get pvmjpg work in a different way - no success */
2731 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
2732 LPRECT lpRect, unsigned int uFormat)
2734 dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
2735 return 8;
2738 static int WINAPI expGetPrivateProfileIntA(const char* appname,
2739 const char* keyname,
2740 int default_value,
2741 const char* filename)
2743 int size=255;
2744 char buffer[256];
2745 char* fullname;
2746 int result;
2748 buffer[255]=0;
2749 if(!(appname && keyname && filename) )
2751 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
2752 return default_value;
2754 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2755 strcpy(fullname, "Software\\IniFileMapping\\");
2756 strcat(fullname, appname);
2757 strcat(fullname, "\\");
2758 strcat(fullname, keyname);
2759 strcat(fullname, "\\");
2760 strcat(fullname, filename);
2761 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
2762 if((size>=0)&&(size<256))
2763 buffer[size]=0;
2764 // printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
2765 free(fullname);
2766 if(result)
2767 result=default_value;
2768 else
2769 result=atoi(buffer);
2770 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
2771 return result;
2773 static int WINAPI expGetProfileIntA(const char* appname,
2774 const char* keyname,
2775 int default_value)
2777 dbgprintf("GetProfileIntA -> ");
2778 return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
2781 static int WINAPI expGetPrivateProfileStringA(const char* appname,
2782 const char* keyname,
2783 const char* def_val,
2784 char* dest, unsigned int len,
2785 const char* filename)
2787 int result;
2788 int size;
2789 char* fullname;
2790 dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
2791 if(!(appname && keyname && filename) ) return 0;
2792 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2793 strcpy(fullname, "Software\\IniFileMapping\\");
2794 strcat(fullname, appname);
2795 strcat(fullname, "\\");
2796 strcat(fullname, keyname);
2797 strcat(fullname, "\\");
2798 strcat(fullname, filename);
2799 size=len;
2800 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
2801 free(fullname);
2802 if(result)
2804 strncpy(dest, def_val, size);
2805 if (strlen(def_val)< size) size = strlen(def_val);
2807 dbgprintf(" => %d ( '%s' )\n", size, dest);
2808 return size;
2810 static int WINAPI expWritePrivateProfileStringA(const char* appname,
2811 const char* keyname,
2812 const char* string,
2813 const char* filename)
2815 char* fullname;
2816 dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
2817 if(!(appname && keyname && filename) )
2819 dbgprintf(" => -1\n");
2820 return -1;
2822 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2823 strcpy(fullname, "Software\\IniFileMapping\\");
2824 strcat(fullname, appname);
2825 strcat(fullname, "\\");
2826 strcat(fullname, keyname);
2827 strcat(fullname, "\\");
2828 strcat(fullname, filename);
2829 RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
2830 // printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
2831 // printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
2832 free(fullname);
2833 dbgprintf(" => 0\n");
2834 return 0;
2837 unsigned int GetPrivateProfileIntA_(const char* appname, const char* keyname, INT default_value, const char* filename)
2839 return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
2841 int GetPrivateProfileStringA_(const char* appname, const char* keyname,
2842 const char* def_val, char* dest, unsigned int len, const char* filename)
2844 return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
2846 int WritePrivateProfileStringA_(const char* appname, const char* keyname,
2847 const char* string, const char* filename)
2849 return expWritePrivateProfileStringA(appname, keyname, string, filename);
2854 static int WINAPI expDefDriverProc(int private, int id, int msg, int arg1, int arg2)
2856 dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", private, id, msg, arg1, arg2);
2857 return 0;
2860 static int WINAPI expSizeofResource(int v1, int v2)
2862 int result=SizeofResource(v1, v2);
2863 dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
2864 return result;
2867 static int WINAPI expGetLastError(void)
2869 int result=GetLastError();
2870 dbgprintf("GetLastError() => 0x%x\n", result);
2871 return result;
2874 static void WINAPI expSetLastError(int error)
2876 dbgprintf("SetLastError(0x%x)\n", error);
2877 SetLastError(error);
2880 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
2882 int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
2883 guid->f1, guid->f2, guid->f3,
2884 (unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
2885 (unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
2886 (unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
2887 (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
2888 dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
2889 return result;
2893 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
2895 dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
2896 return 0;
2899 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
2901 int result;
2902 if(string==0)result=1; else result=0;
2903 dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
2904 if(string)wch_print(string);
2905 return result;
2907 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
2909 return expIsBadStringPtrW((const short*)string, nchars);
2911 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
2913 long ret;
2914 __asm__ volatile
2916 "lock; xaddl %0,(%1)"
2917 : "=r" (ret)
2918 : "r" (dest), "0" (incr)
2919 : "memory"
2921 return ret;
2924 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
2926 unsigned long retval = *dest;
2927 if(*dest == comperand)
2928 *dest = exchange;
2929 return retval;
2932 static long WINAPI expInterlockedIncrement( long* dest )
2934 long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
2935 dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
2936 return result;
2938 static long WINAPI expInterlockedDecrement( long* dest )
2940 long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
2941 dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
2942 return result;
2945 static void WINAPI expOutputDebugStringA( const char* string )
2947 dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
2948 fprintf(stderr, "DEBUG: %s\n", string);
2951 static int WINAPI expGetDC(int hwnd)
2953 dbgprintf("GetDC(0x%x) => 1\n", hwnd);
2954 return 1;
2957 static int WINAPI expReleaseDC(int hwnd, int hdc)
2959 dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
2960 return 1;
2963 static int WINAPI expGetDesktopWindow(void)
2965 dbgprintf("GetDesktopWindow() => 0\n");
2966 return 0;
2969 static int cursor[100];
2971 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
2973 dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
2974 return (int)&cursor[0];
2976 static int WINAPI expSetCursor(void *cursor)
2978 dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
2979 return (int)cursor;
2981 static int WINAPI expGetCursorPos(void *cursor)
2983 dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
2984 return 1;
2986 #ifdef CONFIG_QTX_CODECS
2987 static int show_cursor = 0;
2988 static int WINAPI expShowCursor(int show)
2990 dbgprintf("ShowCursor(%d) => %d\n", show, show);
2991 if (show)
2992 show_cursor++;
2993 else
2994 show_cursor--;
2995 return show_cursor;
2997 #endif
2998 static int WINAPI expRegisterWindowMessageA(char *message)
3000 dbgprintf("RegisterWindowMessageA(%s)\n", message);
3001 return 1;
3003 static int WINAPI expGetProcessVersion(int pid)
3005 dbgprintf("GetProcessVersion(%d)\n", pid);
3006 return 1;
3008 static int WINAPI expGetCurrentThread(void)
3010 #warning FIXME!
3011 dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
3012 return 0xcfcf9898;
3014 static int WINAPI expGetOEMCP(void)
3016 dbgprintf("GetOEMCP()\n");
3017 return 1;
3019 static int WINAPI expGetCPInfo(int cp,void *info)
3021 dbgprintf("GetCPInfo()\n");
3022 return 0;
3024 #ifdef CONFIG_QTX_CODECS
3025 #define SM_CXSCREEN 0
3026 #define SM_CYSCREEN 1
3027 #define SM_XVIRTUALSCREEN 76
3028 #define SM_YVIRTUALSCREEN 77
3029 #define SM_CXVIRTUALSCREEN 78
3030 #define SM_CYVIRTUALSCREEN 79
3031 #define SM_CMONITORS 80
3032 #endif
3033 static int WINAPI expGetSystemMetrics(int index)
3035 dbgprintf("GetSystemMetrics(%d)\n", index);
3036 #ifdef CONFIG_QTX_CODECS
3037 switch(index)
3039 case SM_XVIRTUALSCREEN:
3040 case SM_YVIRTUALSCREEN:
3041 return 0;
3042 case SM_CXSCREEN:
3043 case SM_CXVIRTUALSCREEN:
3044 return PSEUDO_SCREEN_WIDTH;
3045 case SM_CYSCREEN:
3046 case SM_CYVIRTUALSCREEN:
3047 return PSEUDO_SCREEN_HEIGHT;
3048 case SM_CMONITORS:
3049 return 1;
3051 #endif
3052 return 1;
3054 static int WINAPI expGetSysColor(int index)
3056 dbgprintf("GetSysColor(%d) => 1\n", index);
3057 return 1;
3059 static int WINAPI expGetSysColorBrush(int index)
3061 dbgprintf("GetSysColorBrush(%d)\n", index);
3062 return 1;
3067 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
3069 dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
3070 hdc, iStartIndex, nEntries, lppe);
3071 return 0;
3075 typedef struct TIME_ZONE_INFORMATION {
3076 long Bias;
3077 char StandardName[32];
3078 SYSTEMTIME StandardDate;
3079 long StandardBias;
3080 char DaylightName[32];
3081 SYSTEMTIME DaylightDate;
3082 long DaylightBias;
3083 } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
3086 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
3088 const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
3089 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
3090 const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
3091 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
3092 dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
3093 memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
3094 lpTimeZoneInformation->Bias=360;//GMT-6
3095 memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
3096 lpTimeZoneInformation->StandardDate.wMonth=10;
3097 lpTimeZoneInformation->StandardDate.wDay=5;
3098 lpTimeZoneInformation->StandardDate.wHour=2;
3099 lpTimeZoneInformation->StandardBias=0;
3100 memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
3101 lpTimeZoneInformation->DaylightDate.wMonth=4;
3102 lpTimeZoneInformation->DaylightDate.wDay=1;
3103 lpTimeZoneInformation->DaylightDate.wHour=2;
3104 lpTimeZoneInformation->DaylightBias=-60;
3105 return TIME_ZONE_ID_STANDARD;
3108 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
3110 time_t local_time;
3111 struct tm *local_tm;
3112 struct timeval tv;
3114 dbgprintf("GetLocalTime(0x%x)\n");
3115 gettimeofday(&tv, NULL);
3116 local_time=tv.tv_sec;
3117 local_tm=localtime(&local_time);
3119 systime->wYear = local_tm->tm_year + 1900;
3120 systime->wMonth = local_tm->tm_mon + 1;
3121 systime->wDayOfWeek = local_tm->tm_wday;
3122 systime->wDay = local_tm->tm_mday;
3123 systime->wHour = local_tm->tm_hour;
3124 systime->wMinute = local_tm->tm_min;
3125 systime->wSecond = local_tm->tm_sec;
3126 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3127 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3128 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3129 " Milliseconds: %d\n",
3130 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3131 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3134 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
3136 time_t local_time;
3137 struct tm *local_tm;
3138 struct timeval tv;
3140 dbgprintf("GetSystemTime(0x%x)\n", systime);
3141 gettimeofday(&tv, NULL);
3142 local_time=tv.tv_sec;
3143 local_tm=gmtime(&local_time);
3145 systime->wYear = local_tm->tm_year + 1900;
3146 systime->wMonth = local_tm->tm_mon + 1;
3147 systime->wDayOfWeek = local_tm->tm_wday;
3148 systime->wDay = local_tm->tm_mday;
3149 systime->wHour = local_tm->tm_hour;
3150 systime->wMinute = local_tm->tm_min;
3151 systime->wSecond = local_tm->tm_sec;
3152 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3153 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3154 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3155 " Milliseconds: %d\n",
3156 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3157 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3158 return 0;
3161 #define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ULL)
3162 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
3164 struct timeval tv;
3165 unsigned long long secs;
3167 dbgprintf("GetSystemTime(0x%x)\n", systime);
3168 gettimeofday(&tv, NULL);
3169 secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
3170 secs += tv.tv_usec * 10;
3171 systime->dwLowDateTime = secs & 0xffffffff;
3172 systime->dwHighDateTime = (secs >> 32);
3175 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
3177 //char *p;
3178 // printf("%s %x %x\n", name, field, size);
3179 if(field)field[0]=0;
3181 p = getenv(name);
3182 if (p) strncpy(field,p,size);
3184 if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
3185 strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
3186 dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
3187 return strlen(field);
3190 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
3192 dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
3193 return 0;
3196 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
3198 return my_mreq(cb, 0);
3200 static void WINAPI expCoTaskMemFree(void* cb)
3202 my_release(cb);
3208 void* CoTaskMemAlloc(unsigned long cb)
3210 return expCoTaskMemAlloc(cb);
3212 void CoTaskMemFree(void* cb)
3214 expCoTaskMemFree(cb);
3217 struct COM_OBJECT_INFO
3219 GUID clsid;
3220 long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
3223 static struct COM_OBJECT_INFO* com_object_table=0;
3224 static int com_object_size=0;
3225 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3227 if(!clsid || !gcs)
3228 return -1;
3229 com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
3230 com_object_table[com_object_size-1].clsid=*clsid;
3231 com_object_table[com_object_size-1].GetClassObject=gcs;
3232 return 0;
3235 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3237 int found = 0;
3238 int i = 0;
3239 if(!clsid || !gcs)
3240 return -1;
3242 if (com_object_table == 0)
3243 printf("Warning: UnregisterComClass() called without any registered class\n");
3244 while (i < com_object_size)
3246 if (found && i > 0)
3248 memcpy(&com_object_table[i - 1].clsid,
3249 &com_object_table[i].clsid, sizeof(GUID));
3250 com_object_table[i - 1].GetClassObject =
3251 com_object_table[i].GetClassObject;
3253 else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
3254 && com_object_table[i].GetClassObject == gcs)
3256 found++;
3258 i++;
3260 if (found)
3262 if (--com_object_size == 0)
3264 free(com_object_table);
3265 com_object_table = 0;
3268 return 0;
3272 const GUID IID_IUnknown =
3274 0x00000000, 0x0000, 0x0000,
3275 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3277 const GUID IID_IClassFactory =
3279 0x00000001, 0x0000, 0x0000,
3280 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3283 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3284 long dwClsContext, const GUID* riid, void** ppv)
3286 int i;
3287 struct COM_OBJECT_INFO* ci=0;
3288 for(i=0; i<com_object_size; i++)
3289 if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
3290 ci=&com_object_table[i];
3291 if(!ci)return REGDB_E_CLASSNOTREG;
3292 // in 'real' world we should mess with IClassFactory here
3293 i=ci->GetClassObject(rclsid, riid, ppv);
3294 return i;
3297 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3298 long dwClsContext, const GUID* riid, void** ppv)
3300 return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
3303 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
3305 int r = 0;
3306 int w,h;
3307 //trapbug();
3308 if (lprc)
3310 w = lprc->right - lprc->left;
3311 h = lprc->bottom - lprc->top;
3312 if (w <= 0 || h <= 0)
3313 r = 1;
3315 else
3316 r = 1;
3318 dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
3319 //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
3320 // return 0; // wmv9?
3321 return r; // TM20
3324 static int _adjust_fdiv=0; //what's this? - used to adjust division
3325 static int _winver = 0x510; // windows version
3330 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
3332 dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
3333 if(len<5)
3335 dbgprintf(" => 0\n");
3336 return 0;
3338 strcpy(path, "/tmp");
3339 dbgprintf(" => 5 ( '/tmp' )\n");
3340 return 5;
3343 FYI:
3344 typedef struct
3346 DWORD dwFileAttributes;
3347 FILETIME ftCreationTime;
3348 FILETIME ftLastAccessTime;
3349 FILETIME ftLastWriteTime;
3350 DWORD nFileSizeHigh;
3351 DWORD nFileSizeLow;
3352 DWORD dwReserved0;
3353 DWORD dwReserved1;
3354 CHAR cFileName[260];
3355 CHAR cAlternateFileName[14];
3356 } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
3359 static DIR* qtx_dir=NULL;
3361 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
3363 #ifdef CONFIG_QTX_CODECS
3364 dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
3365 if(h==FILE_HANDLE_quicktimeqtx){
3366 struct dirent* d;
3367 if(!qtx_dir) return 0;
3368 while((d=readdir(qtx_dir))){
3369 char* x=strrchr(d->d_name,'.');
3370 if(!x) continue;
3371 if(strcmp(x,".qtx")) continue;
3372 strcpy(lpfd->cFileName,d->d_name);
3373 // sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
3374 strcpy(lpfd->cAlternateFileName,"foobar.qtx");
3375 dbgprintf("### FindNext: %s\n",lpfd->cFileName);
3376 return 1;
3378 closedir(qtx_dir); qtx_dir=NULL;
3379 return 0;
3381 #endif
3382 return 0;
3385 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
3387 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
3388 // printf("\n### FindFirstFileA('%s')...\n",s);
3389 #ifdef CONFIG_QTX_CODECS
3390 if(strstr(s, "quicktime\\*.QTX")){
3391 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
3392 dbgprintf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",def_path);
3393 qtx_dir=opendir(def_path);
3394 if(!qtx_dir) return (HANDLE)-1;
3395 memset(lpfd,0,sizeof(*lpfd));
3396 if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
3397 return FILE_HANDLE_quicktimeqtx;
3398 printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",def_path);
3399 return (HANDLE)-1;
3401 #if 0
3402 if(strstr(s, "QuickTime.qts")){
3403 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
3404 // if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
3405 // return (HANDLE)-1;
3406 strcpy(lpfd->cFileName, "QuickTime.qts");
3407 strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
3408 return FILE_HANDLE_quicktimeqts;
3410 #endif
3411 #endif
3412 if(strstr(s, "*.vwp")){
3413 // hack for VoxWare codec plugins:
3414 strcpy(lpfd->cFileName, "msms001.vwp");
3415 strcpy(lpfd->cAlternateFileName, "msms001.vwp");
3416 return (HANDLE)0;
3418 // return 'file not found'
3419 return (HANDLE)-1;
3422 static WIN_BOOL WINAPI expFindClose(HANDLE h)
3424 dbgprintf("FindClose(0x%x) => 0\n", h);
3425 #ifdef CONFIG_QTX_CODECS
3426 // if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
3427 // closedir(qtx_dir);
3428 // qtx_dir=NULL;
3429 // }
3430 #endif
3431 return 0;
3433 static UINT WINAPI expSetErrorMode(UINT i)
3435 dbgprintf("SetErrorMode(%d) => 0\n", i);
3436 return 0;
3438 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
3440 char windir[]="c:\\windows";
3441 int result;
3442 strncpy(s, windir, c);
3443 result=1+((c<strlen(windir))?c:strlen(windir));
3444 dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
3445 return result;
3447 #ifdef CONFIG_QTX_CODECS
3448 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
3450 char curdir[]="c:\\";
3451 int result;
3452 strncpy(s, curdir, c);
3453 result=1+((c<strlen(curdir))?c:strlen(curdir));
3454 dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
3455 return result;
3458 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
3460 dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
3461 #if 0
3462 if (strrchr(pathname, '\\'))
3463 chdir(strcat(strrchr(pathname, '\\')+1, '/'));
3464 else
3465 chdir(pathname);
3466 #endif
3467 return 1;
3470 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
3472 dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
3473 pathname, pathname, sa);
3474 #if 0
3475 p = strrchr(pathname, '\\')+1;
3476 strcpy(&buf[0], p); /* should be strncpy */
3477 if (!strlen(p))
3479 buf[0] = '.';
3480 buf[1] = 0;
3482 #if 0
3483 if (strrchr(pathname, '\\'))
3484 mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
3485 else
3486 mkdir(pathname, 666);
3487 #endif
3488 mkdir(&buf);
3489 #endif
3490 return 1;
3492 #endif
3493 static WIN_BOOL WINAPI expDeleteFileA(LPCSTR s)
3495 dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
3496 return 0;
3498 static WIN_BOOL WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
3500 dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
3501 return 0;
3504 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
3506 char mask[16]="/tmp/AP_XXXXXX";
3507 int result;
3508 dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
3509 if(i && i<10)
3511 dbgprintf(" => -1\n");
3512 return -1;
3514 result=mkstemp(mask);
3515 sprintf(ps, "AP%d", result);
3516 dbgprintf(" => %d\n", strlen(ps));
3517 return strlen(ps);
3520 // This func might need proper implementation if we want AngelPotion codec.
3521 // They try to open APmpeg4v1.apl with it.
3522 // DLL will close opened file with CloseHandle().
3524 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
3525 LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
3527 dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
3528 i2, p1, i3, i4, i5);
3529 if((!cs1) || (strlen(cs1)<2))return -1;
3531 #ifdef CONFIG_QTX_CODECS
3532 if(strstr(cs1, "QuickTime.qts"))
3534 int result;
3535 char* tmp=malloc(strlen(def_path)+50);
3536 strcpy(tmp, def_path);
3537 strcat(tmp, "/");
3538 strcat(tmp, "QuickTime.qts");
3539 result=open(tmp, O_RDONLY);
3540 free(tmp);
3541 return result;
3543 if(strstr(cs1, ".qtx"))
3545 int result;
3546 char* tmp=malloc(strlen(def_path)+250);
3547 char* x=strrchr(cs1,'\\');
3548 sprintf(tmp,"%s/%s",def_path,x?(x+1):cs1);
3549 // printf("### Open: %s -> %s\n",cs1,tmp);
3550 result=open(tmp, O_RDONLY);
3551 free(tmp);
3552 return result;
3554 #endif
3556 if(strncmp(cs1, "AP", 2) == 0)
3558 int result;
3559 char* tmp=malloc(strlen(def_path)+50);
3560 strcpy(tmp, def_path);
3561 strcat(tmp, "/");
3562 strcat(tmp, "APmpg4v1.apl");
3563 result=open(tmp, O_RDONLY);
3564 free(tmp);
3565 return result;
3567 if (strstr(cs1, "vp3") || strstr(cs1, ".fpf"))
3569 int r;
3570 int flg = 0;
3571 char* tmp=malloc(20 + strlen(cs1));
3572 strcpy(tmp, "/tmp/");
3573 strcat(tmp, cs1);
3574 r = 4;
3575 while (tmp[r])
3577 if (tmp[r] == ':' || tmp[r] == '\\')
3578 tmp[r] = '_';
3579 r++;
3581 if (GENERIC_READ & i1)
3582 flg |= O_RDONLY;
3583 else if (GENERIC_WRITE & i1)
3585 flg |= O_WRONLY | O_CREAT;
3586 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", tmp, r, flg);
3588 r=open(tmp, flg, S_IRWXU);
3589 free(tmp);
3590 return r;
3593 // Needed by wnvplay1.dll
3594 if (strstr(cs1, "WINNOV.bmp"))
3596 int r;
3597 r=open("/dev/null", O_RDONLY);
3598 return r;
3601 #if 0
3602 /* we need this for some virtualdub filters */
3604 int r;
3605 int flg = 0;
3606 if (GENERIC_READ & i1)
3607 flg |= O_RDONLY;
3608 else if (GENERIC_WRITE & i1)
3610 flg |= O_WRONLY;
3611 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", cs1, r, flg);
3613 r=open(cs1, flg);
3614 return r;
3616 #endif
3618 return atoi(cs1+2);
3620 static UINT WINAPI expGetSystemDirectoryA(
3621 char* lpBuffer, // address of buffer for system directory
3622 UINT uSize // size of directory buffer
3624 dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
3625 if(!lpBuffer) strcpy(lpBuffer,".");
3626 return 1;
3629 static char sysdir[]=".";
3630 static LPCSTR WINAPI expGetSystemDirectoryA(void)
3632 dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
3633 return sysdir;
3636 static DWORD WINAPI expGetFullPathNameA
3638 LPCTSTR lpFileName,
3639 DWORD nBufferLength,
3640 LPTSTR lpBuffer,
3641 LPTSTR lpFilePart
3643 if(!lpFileName) return 0;
3644 dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
3645 lpBuffer, lpFilePart);
3646 #if 0
3647 #ifdef CONFIG_QTX_CODECS
3648 strcpy(lpFilePart, "Quick123.qts");
3649 #else
3650 strcpy(lpFilePart, lpFileName);
3651 #endif
3652 #else
3653 if (strrchr(lpFileName, '\\'))
3654 lpFilePart = strrchr(lpFileName, '\\');
3655 else
3656 lpFilePart = (LPTSTR)lpFileName;
3657 #endif
3658 strcpy(lpBuffer, lpFileName);
3659 // strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
3660 return strlen(lpBuffer);
3663 static DWORD WINAPI expGetShortPathNameA
3665 LPCSTR longpath,
3666 LPSTR shortpath,
3667 DWORD shortlen
3669 if(!longpath) return 0;
3670 dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
3671 strcpy(shortpath,longpath);
3672 return strlen(shortpath);
3675 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
3677 int result;
3678 dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
3679 result=read(h, pv, size);
3680 if(rd)*rd=result;
3681 if(!result)return 0;
3682 return 1;
3685 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
3687 int result;
3688 dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
3689 if(h==1234)h=1;
3690 result=write(h, pv, size);
3691 if(wr)*wr=result;
3692 if(!result)return 0;
3693 return 1;
3695 static DWORD WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
3697 int wh;
3698 dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, ext ? *ext : NULL, whence);
3699 //why would DLL want temporary file with >2Gb size?
3700 switch(whence)
3702 case FILE_BEGIN:
3703 wh=SEEK_SET;break;
3704 case FILE_END:
3705 wh=SEEK_END;break;
3706 case FILE_CURRENT:
3707 wh=SEEK_CUR;break;
3708 default:
3709 return -1;
3711 #ifdef CONFIG_QTX_CODECS
3712 if (val == 0 && ext != 0)
3713 val = val&(*ext);
3714 #endif
3715 return lseek(h, val, wh);
3718 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
3719 LPARAM lParam2)
3721 dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3722 return -1;
3724 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
3725 LPARAM lParam2)
3727 dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3728 return -1;
3732 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
3733 LPDWORD lpProcessAffinityMask,
3734 LPDWORD lpSystemAffinityMask)
3736 dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
3737 hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
3738 if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
3739 if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
3740 return 1;
3743 // Fake implementation: does nothing, but does it right :)
3744 static WIN_BOOL WINAPI expSetProcessAffinityMask(HANDLE hProcess,
3745 LPDWORD dwProcessAffinityMask)
3747 dbgprintf("SetProcessAffinityMask(0x%x, 0x%x) => 1\n",
3748 hProcess, dwProcessAffinityMask);
3750 return 1;
3753 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
3755 static const long long max_int=0x7FFFFFFFLL;
3756 static const long long min_int=-0x80000000LL;
3757 long long tmp=(long long)nNumber*(long long)nNumerator;
3758 dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
3759 if(!nDenominator)return 1;
3760 tmp/=nDenominator;
3761 if(tmp<min_int) return 1;
3762 if(tmp>max_int) return 1;
3763 return (int)tmp;
3766 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
3768 LONG result=strcasecmp(str1, str2);
3769 dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
3770 return result;
3773 static LONG WINAPI explstrlenA(const char* str1)
3775 LONG result=strlen(str1);
3776 dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
3777 return result;
3780 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
3782 int result= (int) strcpy(str1, str2);
3783 dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
3784 return result;
3786 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
3788 int result;
3789 if (strlen(str2)>len)
3790 result = (int) strncpy(str1, str2,len);
3791 else
3792 result = (int) strcpy(str1,str2);
3793 dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
3794 return result;
3796 static LONG WINAPI explstrcatA(char* str1, const char* str2)
3798 int result= (int) strcat(str1, str2);
3799 dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
3800 return result;
3804 static LONG WINAPI expInterlockedExchange(long *dest, long l)
3806 long retval = *dest;
3807 *dest = l;
3808 return retval;
3811 static void WINAPI expInitCommonControls(void)
3813 dbgprintf("InitCommonControls called!\n");
3814 return;
3817 #ifdef CONFIG_QTX_CODECS
3818 /* needed by QuickTime.qts */
3819 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
3820 HWND parent, INT id, HINSTANCE inst,
3821 HWND buddy, INT maxVal, INT minVal, INT curVal)
3823 dbgprintf("CreateUpDownControl(...)\n");
3824 return 0;
3826 #endif
3828 /* alex: implement this call! needed for 3ivx */
3829 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
3831 dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
3832 pUnkOuter, ppUnkInner);
3833 // return 0;
3834 return ERROR_CALL_NOT_IMPLEMENTED;
3838 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
3839 HANDLE hSourceHandle, // handle to duplicate
3840 HANDLE hTargetProcessHandle, // handle to target process
3841 HANDLE* lpTargetHandle, // duplicate handle
3842 DWORD dwDesiredAccess, // requested access
3843 int bInheritHandle, // handle inheritance option
3844 DWORD dwOptions // optional actions
3847 dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
3848 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
3849 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
3850 *lpTargetHandle = hSourceHandle;
3851 return 1;
3854 static HRESULT WINAPI expCoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3856 dbgprintf("CoInitializeEx(%p, %d) called\n", lpReserved, dwCoInit);
3857 return S_OK;
3860 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
3861 static HRESULT WINAPI expCoInitialize(
3862 LPVOID lpReserved /* [in] pointer to win32 malloc interface
3863 (obsolete, should be NULL) */
3867 * Just delegate to the newer method.
3869 return expCoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
3872 static void WINAPI expCoUninitialize(void)
3874 dbgprintf("CoUninitialize() called\n");
3877 /* allow static linking */
3878 HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3880 return expCoInitializeEx(lpReserved, dwCoInit);
3882 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
3884 return expCoInitialize(lpReserved);
3886 void WINAPI CoUninitialize(void)
3888 expCoUninitialize();
3891 static DWORD WINAPI expSetThreadAffinityMask
3893 HANDLE hThread,
3894 DWORD dwThreadAffinityMask
3896 return 0;
3900 * no WINAPI functions - CDECL
3902 static void* expmalloc(int size)
3904 //printf("malloc");
3905 // return malloc(size);
3906 void* result=my_mreq(size,0);
3907 dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
3908 if(result==0)
3909 printf("WARNING: malloc() failed\n");
3910 return result;
3912 static void expfree(void* mem)
3914 // return free(mem);
3915 dbgprintf("free(%p)\n", mem);
3916 my_release(mem);
3918 /* needed by atrac3.acm */
3919 static void *expcalloc(int num, int size)
3921 void* result=my_mreq(num*size,1);
3922 dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
3923 if(result==0)
3924 printf("WARNING: calloc() failed\n");
3925 return result;
3927 static void* expnew(int size)
3929 // printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
3930 // printf("%08x %08x %08x %08x\n",
3931 // size, *(1+(int*)&size),
3932 // *(2+(int*)&size),*(3+(int*)&size));
3933 void* result;
3934 assert(size >= 0);
3936 result=my_mreq(size,0);
3937 dbgprintf("new(%d) => %p\n", size, result);
3938 if (result==0)
3939 printf("WARNING: new() failed\n");
3940 return result;
3943 static int expdelete(void* memory)
3945 dbgprintf("delete(%p)\n", memory);
3946 my_release(memory);
3947 return 0;
3951 * local definition - we need only the last two members at this point
3952 * otherwice we would have to introduce here GUIDs and some more types..
3954 typedef struct __attribute__((__packed__))
3956 char hay[0x40];
3957 unsigned long cbFormat; //0x40
3958 char* pbFormat; //0x44
3959 } MY_MEDIA_TYPE;
3960 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
3962 if (!dest || !src)
3963 return E_POINTER;
3964 memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
3965 if (dest->cbFormat)
3967 dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
3968 if (!dest->pbFormat)
3969 return E_OUTOFMEMORY;
3970 memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
3972 return S_OK;
3974 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
3976 if (!dest)
3977 return E_POINTER;
3978 memset(dest, 0, sizeof(MY_MEDIA_TYPE));
3979 if (cbFormat)
3981 dest->pbFormat = (char*) my_mreq(cbFormat, 0);
3982 if (!dest->pbFormat)
3983 return E_OUTOFMEMORY;
3985 return S_OK;
3987 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
3989 if (!dest)
3990 return E_POINTER;
3991 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3992 return expMoInitMediaType(*dest, cbFormat);
3994 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
3996 if (!dest)
3997 return E_POINTER;
3998 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3999 return expMoCopyMediaType(*dest, src);
4001 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
4003 if (!dest)
4004 return E_POINTER;
4005 if (dest->pbFormat)
4007 my_release(dest->pbFormat);
4008 dest->pbFormat = 0;
4009 dest->cbFormat = 0;
4011 return S_OK;
4013 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
4015 if (!dest)
4016 return E_POINTER;
4017 expMoFreeMediaType(dest);
4018 my_release(dest);
4019 return S_OK;
4022 static int exp_snprintf( char *str, int size, const char *format, ... )
4024 int x;
4025 va_list va;
4026 va_start(va, format);
4027 x=snprintf(str,size,format,va);
4028 dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
4029 va_end(va);
4030 return x;
4033 #if 0
4034 static int exp_initterm(int v1, int v2)
4036 dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
4037 return 0;
4039 #else
4040 /* merged from wine - 2002.04.21 */
4041 typedef void (*INITTERMFUNC)();
4042 static int exp_initterm(INITTERMFUNC *start, INITTERMFUNC *end)
4044 dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
4045 while (start < end)
4047 if (*start)
4049 //printf("call _initfunc: from: %p %d\n", *start);
4050 // ok this trick with push/pop is necessary as otherwice
4051 // edi/esi registers are being trashed
4052 void* p = *start;
4053 __asm__ volatile
4055 "pushl %%ebx \n\t"
4056 "pushl %%ecx \n\t"
4057 "pushl %%edx \n\t"
4058 "pushl %%edi \n\t"
4059 "pushl %%esi \n\t"
4060 "call *%%eax \n\t"
4061 "popl %%esi \n\t"
4062 "popl %%edi \n\t"
4063 "popl %%edx \n\t"
4064 "popl %%ecx \n\t"
4065 "popl %%ebx \n\t"
4067 : "a"(p)
4068 : "memory"
4070 //printf("done %p %d:%d\n", end);
4072 start++;
4074 return 0;
4076 #endif
4078 /* Fake _initterm_e from msvcr80.dll, needed by sirenacm.dll
4079 * NOTE: If I make this an alias for _initterm, then sirenacm.dll tries to call
4080 other uninmplemented functions; keep this in mind if some future codec needs
4081 a real implementation of this function */
4082 static int exp_initterm_e(INITTERMFUNC *start, INITTERMFUNC *end)
4084 dbgprintf("_initterm_e(0x%x, 0x%x)\n", start, end);
4085 return 0;
4088 static void* exp__dllonexit(void)
4090 // FIXME extract from WINE
4091 return NULL;
4094 static int expwsprintfA(char* string, const char* format, ...)
4096 va_list va;
4097 int result;
4098 va_start(va, format);
4099 result = vsprintf(string, format, va);
4100 dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4101 va_end(va);
4102 return result;
4105 static int expsprintf(char* str, const char* format, ...)
4107 va_list args;
4108 int r;
4109 dbgprintf("sprintf(0x%x, %s)\n", str, format);
4110 va_start(args, format);
4111 r = vsprintf(str, format, args);
4112 va_end(args);
4113 return r;
4115 static int expsscanf(const char* str, const char* format, ...)
4117 va_list args;
4118 int r;
4119 dbgprintf("sscanf(%s, %s)\n", str, format);
4120 va_start(args, format);
4121 r = vsscanf(str, format, args);
4122 va_end(args);
4123 return r;
4125 static void* expfopen(const char* path, const char* mode)
4127 printf("fopen: \"%s\" mode:%s\n", path, mode);
4128 //return fopen(path, mode);
4129 return fdopen(0, mode); // everything on screen
4131 static int expfprintf(void* stream, const char* format, ...)
4133 va_list args;
4134 int r = 0;
4135 dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4136 va_start(args, format);
4137 r = vfprintf((FILE*) stream, format, args);
4138 va_end(args);
4139 return r;
4142 static int expprintf(const char* format, ...)
4144 va_list args;
4145 int r;
4146 dbgprintf("printf(%s, ...)\n", format);
4147 va_start(args, format);
4148 r = vprintf(format, args);
4149 va_end(args);
4150 return r;
4153 static char* expgetenv(const char* varname)
4155 char* v = getenv(varname);
4156 dbgprintf("getenv(%s) => %s\n", varname, v);
4157 return v;
4160 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4162 WCHAR* p = dst;
4163 while ((*p++ = *src++))
4165 return dst;
4168 static char* expstrrchr(char* string, int value)
4170 char* result=strrchr(string, value);
4171 if(result)
4172 dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4173 else
4174 dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4175 return result;
4178 static char* expstrchr(char* string, int value)
4180 char* result=strchr(string, value);
4181 if(result)
4182 dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4183 else
4184 dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4185 return result;
4187 static int expstrlen(char* str)
4189 int result=strlen(str);
4190 dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4191 return result;
4193 static char* expstrcpy(char* str1, const char* str2)
4195 char* result= strcpy(str1, str2);
4196 dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4197 return result;
4199 static char* expstrncpy(char* str1, const char* str2, size_t count)
4201 char* result= strncpy(str1, str2, count);
4202 dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4203 return result;
4205 static int expstrcmp(const char* str1, const char* str2)
4207 int result=strcmp(str1, str2);
4208 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4209 return result;
4211 static int expstrncmp(const char* str1, const char* str2,int x)
4213 int result=strncmp(str1, str2,x);
4214 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4215 return result;
4217 static char* expstrcat(char* str1, const char* str2)
4219 char* result = strcat(str1, str2);
4220 dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4221 return result;
4223 static char* exp_strdup(const char* str1)
4225 int l = strlen(str1);
4226 char* result = (char*) my_mreq(l + 1,0);
4227 if (result)
4228 strcpy(result, str1);
4229 dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4230 return result;
4232 static int expisalnum(int c)
4234 int result= (int) isalnum(c);
4235 dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4236 return result;
4238 static int expisspace(int c)
4240 int result= (int) isspace(c);
4241 dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4242 return result;
4244 static int expisalpha(int c)
4246 int result= (int) isalpha(c);
4247 dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4248 return result;
4250 static int expisdigit(int c)
4252 int result= (int) isdigit(c);
4253 dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4254 return result;
4256 static void* expmemmove(void* dest, void* src, int n)
4258 void* result = memmove(dest, src, n);
4259 dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4260 return result;
4262 static int expmemcmp(void* dest, void* src, int n)
4264 int result = memcmp(dest, src, n);
4265 dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4266 return result;
4268 static void* expmemcpy(void* dest, void* src, int n)
4270 void *result = memcpy(dest, src, n);
4271 dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4272 return result;
4274 static void* expmemset(void* dest, int c, size_t n)
4276 void *result = memset(dest, c, n);
4277 dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4278 return result;
4280 static time_t exptime(time_t* t)
4282 time_t result = time(t);
4283 dbgprintf("time(0x%x) => %d\n", t, result);
4284 return result;
4287 static int exprand(void)
4289 return rand();
4292 static void expsrand(int seed)
4294 srand(seed);
4297 #if 1
4299 // preferred compilation with -O2 -ffast-math !
4301 static double explog10(double x)
4303 /*printf("Log10 %f => %f 0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4304 return log10(x);
4307 static double expcos(double x)
4309 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4310 return cos(x);
4313 #else
4315 static void explog10(void)
4317 __asm__ volatile
4319 "fldl 8(%esp) \n\t"
4320 "fldln2 \n\t"
4321 "fxch %st(1) \n\t"
4322 "fyl2x \n\t"
4326 static void expcos(void)
4328 __asm__ volatile
4330 "fldl 8(%esp) \n\t"
4331 "fcos \n\t"
4335 #endif
4337 // this seem to be the only how to make this function working properly
4338 // ok - I've spent tremendous amount of time (many many many hours
4339 // of debuging fixing & testing - it's almost unimaginable - kabi
4341 // _ftol - operated on the float value which is already on the FPU stack
4343 static void exp_ftol(void)
4345 __asm__ volatile
4347 "sub $12, %esp \n\t"
4348 "fstcw -2(%ebp) \n\t"
4349 "wait \n\t"
4350 "movw -2(%ebp), %ax \n\t"
4351 "orb $0x0C, %ah \n\t"
4352 "movw %ax, -4(%ebp) \n\t"
4353 "fldcw -4(%ebp) \n\t"
4354 "fistpl -12(%ebp) \n\t"
4355 "fldcw -2(%ebp) \n\t"
4356 "movl -12(%ebp), %eax \n\t"
4357 //Note: gcc 3.03 does not do the following op if it
4358 // knows that ebp=esp
4359 "movl %ebp, %esp \n\t"
4363 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4364 __asm__ volatile( "fstpl %0;fwait" : "=m" (var2) : ); \
4365 __asm__ volatile( "fstpl %0;fwait" : "=m" (var1) : )
4367 static double exp_CIpow(void)
4369 FPU_DOUBLES(x,y);
4371 dbgprintf("_CIpow(%lf, %lf)\n", x, y);
4372 return pow(x, y);
4375 static double exppow(double x, double y)
4377 /*printf("Pow %f %f 0x%Lx 0x%Lx => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4378 return pow(x, y);
4381 static double expldexp(double x, int expo)
4383 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4384 return ldexp(x, expo);
4387 static double expfrexp(double x, int* expo)
4389 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4390 return frexp(x, expo);
4395 static int exp_stricmp(const char* s1, const char* s2)
4397 return strcasecmp(s1, s2);
4400 /* from declaration taken from Wine sources - this fountion seems to be
4401 * undocumented in any M$ doc */
4402 static int exp_setjmp3(void* jmpbuf, int x)
4404 //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4405 //return 0;
4406 __asm__ volatile
4408 //"mov 4(%%esp), %%edx \n\t"
4409 "mov (%%esp), %%eax \n\t"
4410 "mov %%eax, (%%edx) \n\t" // store ebp
4412 //"mov %%ebp, (%%edx) \n\t"
4413 "mov %%ebx, 4(%%edx) \n\t"
4414 "mov %%edi, 8(%%edx) \n\t"
4415 "mov %%esi, 12(%%edx) \n\t"
4416 "mov %%esp, 16(%%edx) \n\t"
4418 "mov 4(%%esp), %%eax \n\t"
4419 "mov %%eax, 20(%%edx) \n\t"
4421 "movl $0x56433230, 32(%%edx) \n\t" // VC20 ??
4422 "movl $0, 36(%%edx) \n\t"
4423 : // output
4424 : "d"(jmpbuf) // input
4425 : "eax"
4427 __asm__ volatile
4429 "mov %%fs:0, %%eax \n\t" // unsure
4430 "mov %%eax, 24(%%edx) \n\t"
4431 "cmp $0xffffffff, %%eax \n\t"
4432 "jnz l1 \n\t"
4433 "mov %%eax, 28(%%edx) \n\t"
4434 "l1: \n\t"
4437 : "eax"
4440 return 0;
4443 static DWORD WINAPI expGetCurrentProcessId(void)
4445 dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4446 return getpid(); //(DWORD)NtCurrentTeb()->pid;
4450 typedef struct {
4451 UINT wPeriodMin;
4452 UINT wPeriodMax;
4453 } TIMECAPS, *LPTIMECAPS;
4455 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4457 dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4459 lpCaps->wPeriodMin = 1;
4460 lpCaps->wPeriodMax = 65535;
4461 return 0;
4464 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4466 dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4468 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4469 return 0;
4472 #ifdef CONFIG_QTX_CODECS
4473 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4475 dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4477 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4478 return 0;
4480 #endif
4482 static void WINAPI expGlobalMemoryStatus(
4483 LPMEMORYSTATUS lpmem
4485 static MEMORYSTATUS cached_memstatus;
4486 static int cache_lastchecked = 0;
4487 SYSTEM_INFO si;
4488 FILE *f;
4490 if (time(NULL)==cache_lastchecked) {
4491 memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4492 return;
4495 f = fopen( "/proc/meminfo", "r" );
4496 if (f)
4498 char buffer[256];
4499 int total, used, free, shared, buffers, cached;
4501 lpmem->dwLength = sizeof(MEMORYSTATUS);
4502 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4503 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4504 while (fgets( buffer, sizeof(buffer), f ))
4506 /* old style /proc/meminfo ... */
4507 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4509 lpmem->dwTotalPhys += total;
4510 lpmem->dwAvailPhys += free + buffers + cached;
4512 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4514 lpmem->dwTotalPageFile += total;
4515 lpmem->dwAvailPageFile += free;
4518 /* new style /proc/meminfo ... */
4519 if (sscanf(buffer, "MemTotal: %d", &total))
4520 lpmem->dwTotalPhys = total*1024;
4521 if (sscanf(buffer, "MemFree: %d", &free))
4522 lpmem->dwAvailPhys = free*1024;
4523 if (sscanf(buffer, "SwapTotal: %d", &total))
4524 lpmem->dwTotalPageFile = total*1024;
4525 if (sscanf(buffer, "SwapFree: %d", &free))
4526 lpmem->dwAvailPageFile = free*1024;
4527 if (sscanf(buffer, "Buffers: %d", &buffers))
4528 lpmem->dwAvailPhys += buffers*1024;
4529 if (sscanf(buffer, "Cached: %d", &cached))
4530 lpmem->dwAvailPhys += cached*1024;
4532 fclose( f );
4534 if (lpmem->dwTotalPhys)
4536 DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4537 DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4538 lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4539 / (TotalPhysical / 100);
4541 } else
4543 /* FIXME: should do something for other systems */
4544 lpmem->dwMemoryLoad = 0;
4545 lpmem->dwTotalPhys = 16*1024*1024;
4546 lpmem->dwAvailPhys = 16*1024*1024;
4547 lpmem->dwTotalPageFile = 16*1024*1024;
4548 lpmem->dwAvailPageFile = 16*1024*1024;
4550 expGetSystemInfo(&si);
4551 lpmem->dwTotalVirtual = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
4552 /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4553 lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
4554 memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4555 cache_lastchecked = time(NULL);
4557 /* it appears some memory display programs want to divide by these values */
4558 if(lpmem->dwTotalPageFile==0)
4559 lpmem->dwTotalPageFile++;
4561 if(lpmem->dwAvailPageFile==0)
4562 lpmem->dwAvailPageFile++;
4565 static INT WINAPI expGetThreadPriority(HANDLE hthread)
4567 dbgprintf("GetThreadPriority(%p)\n",hthread);
4568 return 0;
4571 /**********************************************************************
4572 * SetThreadPriority [KERNEL32.@] Sets priority for thread.
4574 * RETURNS
4575 * Success: TRUE
4576 * Failure: FALSE
4578 static WIN_BOOL WINAPI expSetThreadPriority(
4579 HANDLE hthread, /* [in] Handle to thread */
4580 INT priority) /* [in] Thread priority level */
4582 dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4583 return TRUE;
4586 static void WINAPI expTerminateProcess( DWORD process, DWORD status )
4588 printf("EXIT - process %ld code %ld\n", process, status);
4589 exit(status);
4592 static void WINAPI expExitProcess( DWORD status )
4594 printf("EXIT - code %ld\n",status);
4595 exit(status);
4598 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4599 printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4600 #ifdef CONFIG_QTX_CODECS
4601 if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4602 return IDIGNORE;
4603 #endif
4604 return IDOK;
4607 /* these are needed for mss1 */
4610 * \brief this symbol is defined within exp_EH_prolog_dummy
4611 * \param dest jump target
4613 void exp_EH_prolog(void *dest);
4614 void exp_EH_prolog_dummy(void);
4615 //! just a dummy function that acts a container for the asm section
4616 void exp_EH_prolog_dummy(void) {
4617 __asm__ volatile (
4618 // take care, this "function" may not change flags or
4619 // registers besides eax (which is also why we can't use
4620 // exp_EH_prolog_dummy directly)
4621 MANGLE(exp_EH_prolog)": \n\t"
4622 "pop %eax \n\t"
4623 "push %ebp \n\t"
4624 "mov %esp, %ebp \n\t"
4625 "lea -12(%esp), %esp \n\t"
4626 "jmp *%eax \n\t"
4630 #include <netinet/in.h>
4631 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4633 // dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4634 return htonl(hostlong);
4637 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4639 // dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4640 return ntohl(netlong);
4643 static char* WINAPI expSysAllocStringLen(char *pch, unsigned cch)
4645 char *str;
4646 dbgprintf("SysAllocStringLen('%s', %d)\n", pch, cch);
4647 str = malloc(cch * 2 + sizeof(unsigned) + 2);
4648 *(unsigned *)str = cch;
4649 str += sizeof(unsigned);
4650 if (pch)
4651 memcpy(str, pch, cch * 2);
4652 str[cch * 2] = 0;
4653 str[cch * 2 + 1] = 0;
4654 return str;
4657 static void WINAPI expSysFreeString(char *str)
4659 if (str) {
4660 free(str - sizeof(unsigned));
4664 static void WINAPI expVariantInit(void* p)
4666 printf("InitCommonControls called!\n");
4667 return;
4670 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4672 dbgprintf("RegisterClassA(%p) => random id\n", wc);
4673 return time(NULL); /* be precise ! */
4676 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4678 dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4679 return 0;
4682 #ifdef CONFIG_QTX_CODECS
4683 /* should be fixed bcs it's not fully strlen equivalent */
4684 static int expSysStringByteLen(void *str)
4686 dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4687 return strlen(str);
4690 static int expDirectDrawCreate(void)
4692 dbgprintf("DirectDrawCreate(...) => NULL\n");
4693 return 0;
4696 #if 1
4697 typedef struct tagPALETTEENTRY {
4698 BYTE peRed;
4699 BYTE peGreen;
4700 BYTE peBlue;
4701 BYTE peFlags;
4702 } PALETTEENTRY;
4704 /* reversed the first 2 entries */
4705 typedef struct tagLOGPALETTE {
4706 WORD palNumEntries;
4707 WORD palVersion;
4708 PALETTEENTRY palPalEntry[1];
4709 } LOGPALETTE;
4711 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4713 HPALETTE test;
4714 int i;
4716 dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4718 i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4719 test = malloc(i);
4720 memcpy((void *)test, lpgpl, i);
4722 return test;
4724 #else
4725 static int expCreatePalette(void)
4727 dbgprintf("CreatePalette(...) => NULL\n");
4728 return NULL;
4730 #endif
4732 static int WINAPI expGetClientRect(HWND win, RECT *r)
4734 dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4735 r->right = PSEUDO_SCREEN_WIDTH;
4736 r->left = 0;
4737 r->bottom = PSEUDO_SCREEN_HEIGHT;
4738 r->top = 0;
4739 return 1;
4742 #if 0
4743 typedef struct tagPOINT {
4744 LONG x;
4745 LONG y;
4746 } POINT, *PPOINT;
4747 #endif
4749 static int WINAPI expClientToScreen(HWND win, POINT *p)
4751 dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4752 p->x = 0;
4753 p->y = 0;
4754 return 1;
4756 #endif
4758 /* for m3jpeg */
4759 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4761 dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4762 return 0;
4765 static int WINAPI expMessageBeep(int type)
4767 dbgprintf("MessageBeep(%d) => 1\n", type);
4768 return 1;
4771 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4772 HWND parent, void *dialog_func, void *init_param)
4774 dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4775 inst, name, name, parent, dialog_func, init_param);
4776 return 0x42424242;
4779 static void WINAPI expRegisterClipboardFormatA(const char *name) {
4780 dbgprintf("RegisterClipboardFormatA(0x%x = %s)\n", name, name);
4783 /* needed by imagepower mjpeg2k */
4784 static void *exprealloc(void *ptr, size_t size)
4786 dbgprintf("realloc(0x%x, %x)\n", ptr, size);
4787 if (!ptr)
4788 return my_mreq(size,0);
4789 else
4790 return my_realloc(ptr, size);
4793 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
4794 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
4796 return 1;
4799 static char * WINAPI expPathFindExtensionA(const char *path) {
4800 char *ext;
4801 if (!path)
4802 ext = NULL;
4803 else {
4804 ext = strrchr(path, '.');
4805 if (!ext)
4806 ext = &path[strlen(path)];
4808 dbgprintf("PathFindExtensionA(0x%x = %s) => 0x%x, %s\n", path, path, ext, ext);
4809 return ext;
4812 static char * WINAPI expPathFindFileNameA(const char *path) {
4813 char *name;
4814 if (!path || strlen(path) < 2)
4815 name = path;
4816 else {
4817 name = strrchr(path - 1, '\\');
4818 if (!name)
4819 name = path;
4821 dbgprintf("PathFindFileNameA(0x%x = %s) => 0x%x, %s\n", path, path, name, name);
4822 return name;
4825 static double expfloor(double x)
4827 dbgprintf("floor(%lf)\n", x);
4828 return floor(x);
4831 #define FPU_DOUBLE(var) double var; \
4832 __asm__ volatile( "fstpl %0;fwait" : "=m" (var) : )
4834 static double exp_CIcos(void)
4836 FPU_DOUBLE(x);
4838 dbgprintf("_CIcos(%lf)\n", x);
4839 return cos(x);
4842 static double exp_CIsin(void)
4844 FPU_DOUBLE(x);
4846 dbgprintf("_CIsin(%lf)\n", x);
4847 return sin(x);
4850 static double exp_CIsqrt(void)
4852 FPU_DOUBLE(x);
4854 dbgprintf("_CIsqrt(%lf)\n", x);
4855 return sqrt(x);
4858 /* Needed by rp8 sipr decoder */
4859 static LPSTR WINAPI expCharNextA(LPCSTR ptr)
4861 if (!*ptr) return (LPSTR)ptr;
4862 // dbgprintf("CharNextA(0x%08x), %s\n", ptr, ptr);
4863 return (LPSTR)(ptr + 1);
4866 // Fake implementation, needed by wvc1dmod.dll
4867 static int WINAPI expPropVariantClear(void *pvar)
4869 // dbgprintf("PropVariantclear (0x%08x), %s\n", ptr, ptr);
4870 return 1;
4873 // This define is fake, the real thing is a struct
4874 #define LPDEVMODEA void*
4875 // Dummy implementation, always return 1
4876 // Required for frapsvid.dll 2.8.1, return value does not matter
4877 static WIN_BOOL WINAPI expEnumDisplaySettingsA(LPCSTR name ,DWORD n,
4878 LPDEVMODEA devmode)
4880 dbgprintf("EnumDisplaySettingsA (dummy) => 1\n");
4881 return 1;
4884 // Fake implementation of _decode_pointer from msvcr80.dll, needed by sirenacm.dll
4885 // NOTE: undocumented function, probably the declaration is not right
4886 static int exp_decode_pointer(void *ptr)
4888 dbgprintf("_decode_pointer (0x%08x)\n", ptr);
4889 return 0;
4892 /* Fake implementation of sdt::_Lockit::_Lockit(void) from msvcp60.dll
4893 Needed by SCLS.DLL */
4894 static int exp_0Lockit_dummy(void)
4896 dbgprintf("0Lockit_dummy (??0_Lockit@std@@QAE@XZ)\n");
4897 return 0;
4900 /* Fake implementation of sdt::_Lockit::~_Lockit(void) from msvcp60.dll
4901 Needed by SCLS.DLL */
4902 static int exp_1Lockit_dummy(void)
4904 dbgprintf("1Lockit_dummy (??1_Lockit@std@@QAE@XZ)\n");
4905 return 0;
4908 static void * WINAPI expEncodePointer(void *p)
4910 return p;
4913 static void * WINAPI expDecodePointer(void *p)
4915 return p;
4918 static DWORD WINAPI expGetThreadLocale(void)
4920 return 0;
4924 * Very incomplete implementation, return an error for almost all cases.
4926 static DWORD WINAPI expGetLocaleInfoA(DWORD locale, DWORD lctype, char* lpLCData, int cchData)
4928 if (lctype == 0x1004) { // LOCALE_IDEFAULTANSICODEPAGE
4929 if (cchData < 4)
4930 return cchData == 0 ? 4 : 0;
4931 strcpy(lpLCData, "437");
4932 return 4;
4934 return 0;
4937 struct exports
4939 char name[64];
4940 int id;
4941 void* func;
4943 struct libs
4945 char name[64];
4946 int length;
4947 struct exports* exps;
4950 #define FF(X,Y) \
4951 {#X, Y, (void*)exp##X},
4953 #define UNDEFF(X, Y) \
4954 {#X, Y, (void*)-1},
4956 struct exports exp_kernel32[]=
4958 FF(GetVolumeInformationA,-1)
4959 FF(GetDriveTypeA,-1)
4960 FF(GetLogicalDriveStringsA,-1)
4961 FF(IsBadWritePtr, 357)
4962 FF(IsBadReadPtr, 354)
4963 FF(IsBadStringPtrW, -1)
4964 FF(IsBadStringPtrA, -1)
4965 FF(DisableThreadLibraryCalls, -1)
4966 FF(CreateThread, -1)
4967 FF(CreateEventA, -1)
4968 FF(SetEvent, -1)
4969 FF(ResetEvent, -1)
4970 FF(WaitForSingleObject, -1)
4971 #ifdef CONFIG_QTX_CODECS
4972 FF(WaitForMultipleObjects, -1)
4973 FF(ExitThread, -1)
4974 FF(CreateMutexA,-1)
4975 FF(ReleaseMutex,-1)
4976 #endif
4977 FF(GetSystemInfo, -1)
4978 FF(GetVersion, 332)
4979 FF(HeapCreate, 461)
4980 FF(HeapAlloc, -1)
4981 FF(HeapDestroy, -1)
4982 FF(HeapFree, -1)
4983 FF(HeapSize, -1)
4984 FF(HeapReAlloc,-1)
4985 FF(GetProcessHeap, -1)
4986 FF(VirtualAlloc, -1)
4987 FF(VirtualFree, -1)
4988 FF(InitializeCriticalSection, -1)
4989 FF(InitializeCriticalSectionAndSpinCount, -1)
4990 FF(EnterCriticalSection, -1)
4991 FF(LeaveCriticalSection, -1)
4992 FF(DeleteCriticalSection, -1)
4993 FF(TlsAlloc, -1)
4994 FF(TlsFree, -1)
4995 FF(TlsGetValue, -1)
4996 FF(TlsSetValue, -1)
4997 FF(GetCurrentThreadId, -1)
4998 FF(GetCurrentProcess, -1)
4999 FF(LocalAlloc, -1)
5000 FF(LocalReAlloc,-1)
5001 FF(LocalLock, -1)
5002 FF(GlobalAlloc, -1)
5003 FF(GlobalReAlloc, -1)
5004 FF(GlobalLock, -1)
5005 FF(GlobalSize, -1)
5006 FF(MultiByteToWideChar, 427)
5007 FF(WideCharToMultiByte, -1)
5008 FF(GetVersionExA, -1)
5009 FF(CreateSemaphoreA, -1)
5010 FF(QueryPerformanceCounter, -1)
5011 FF(QueryPerformanceFrequency, -1)
5012 FF(LocalHandle, -1)
5013 FF(LocalUnlock, -1)
5014 FF(LocalFree, -1)
5015 FF(GlobalHandle, -1)
5016 FF(GlobalUnlock, -1)
5017 FF(GlobalFree, -1)
5018 FF(LoadResource, -1)
5019 FF(ReleaseSemaphore, -1)
5020 FF(FindResourceA, -1)
5021 FF(LockResource, -1)
5022 FF(FreeResource, -1)
5023 FF(SizeofResource, -1)
5024 FF(CloseHandle, -1)
5025 FF(GetCommandLineA, -1)
5026 FF(GetEnvironmentStringsW, -1)
5027 FF(FreeEnvironmentStringsW, -1)
5028 FF(FreeEnvironmentStringsA, -1)
5029 FF(GetEnvironmentStrings, -1)
5030 FF(GetStartupInfoA, -1)
5031 FF(GetStdHandle, -1)
5032 FF(GetFileType, -1)
5033 #ifdef CONFIG_QTX_CODECS
5034 FF(GetFileAttributesA, -1)
5035 #endif
5036 FF(SetHandleCount, -1)
5037 FF(GetACP, -1)
5038 FF(GetModuleFileNameA, -1)
5039 FF(SetUnhandledExceptionFilter, -1)
5040 FF(LoadLibraryA, -1)
5041 FF(GetProcAddress, -1)
5042 FF(FreeLibrary, -1)
5043 FF(CreateFileMappingA, -1)
5044 FF(OpenFileMappingA, -1)
5045 FF(MapViewOfFile, -1)
5046 FF(UnmapViewOfFile, -1)
5047 FF(Sleep, -1)
5048 FF(GetModuleHandleA, -1)
5049 FF(GetModuleHandleW, -1)
5050 FF(GetProfileIntA, -1)
5051 FF(GetPrivateProfileIntA, -1)
5052 FF(GetPrivateProfileStringA, -1)
5053 FF(WritePrivateProfileStringA, -1)
5054 FF(GetLastError, -1)
5055 FF(SetLastError, -1)
5056 FF(InterlockedIncrement, -1)
5057 FF(InterlockedDecrement, -1)
5058 FF(GetTimeZoneInformation, -1)
5059 FF(OutputDebugStringA, -1)
5060 FF(GetLocalTime, -1)
5061 FF(GetSystemTime, -1)
5062 FF(GetSystemTimeAsFileTime, -1)
5063 FF(GetEnvironmentVariableA, -1)
5064 FF(SetEnvironmentVariableA, -1)
5065 FF(RtlZeroMemory,-1)
5066 FF(RtlMoveMemory,-1)
5067 FF(RtlFillMemory,-1)
5068 FF(GetTempPathA,-1)
5069 FF(FindFirstFileA,-1)
5070 FF(FindNextFileA,-1)
5071 FF(FindClose,-1)
5072 FF(FileTimeToLocalFileTime,-1)
5073 FF(DeleteFileA,-1)
5074 FF(ReadFile,-1)
5075 FF(WriteFile,-1)
5076 FF(SetFilePointer,-1)
5077 FF(GetTempFileNameA,-1)
5078 FF(CreateFileA,-1)
5079 FF(GetSystemDirectoryA,-1)
5080 FF(GetWindowsDirectoryA,-1)
5081 #ifdef CONFIG_QTX_CODECS
5082 FF(GetCurrentDirectoryA,-1)
5083 FF(SetCurrentDirectoryA,-1)
5084 FF(CreateDirectoryA,-1)
5085 #endif
5086 FF(GetShortPathNameA,-1)
5087 FF(GetFullPathNameA,-1)
5088 FF(SetErrorMode, -1)
5089 FF(IsProcessorFeaturePresent, -1)
5090 FF(IsDebuggerPresent, -1)
5091 FF(GetProcessAffinityMask, -1)
5092 FF(InterlockedExchange, -1)
5093 FF(InterlockedCompareExchange, -1)
5094 FF(MulDiv, -1)
5095 FF(lstrcmpiA, -1)
5096 FF(lstrlenA, -1)
5097 FF(lstrcpyA, -1)
5098 FF(lstrcatA, -1)
5099 FF(lstrcpynA,-1)
5100 FF(GetProcessVersion,-1)
5101 FF(GetCurrentThread,-1)
5102 FF(GetOEMCP,-1)
5103 FF(GetCPInfo,-1)
5104 FF(DuplicateHandle,-1)
5105 FF(GetTickCount, -1)
5106 FF(SetThreadAffinityMask,-1)
5107 FF(GetCurrentProcessId,-1)
5108 FF(GlobalMemoryStatus,-1)
5109 FF(GetThreadPriority,-1)
5110 FF(SetThreadPriority,-1)
5111 FF(TerminateProcess,-1)
5112 FF(ExitProcess,-1)
5113 {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
5114 FF(SetThreadIdealProcessor,-1)
5115 FF(SetProcessAffinityMask, -1)
5116 FF(EncodePointer, -1)
5117 FF(DecodePointer, -1)
5118 FF(GetThreadLocale, -1)
5119 FF(GetLocaleInfoA, -1)
5120 UNDEFF(FlsAlloc, -1)
5121 UNDEFF(FlsGetValue, -1)
5122 UNDEFF(FlsSetValue, -1)
5123 UNDEFF(FlsFree, -1)
5126 struct exports exp_msvcrt[]={
5127 FF(malloc, -1)
5128 FF(_initterm, -1)
5129 FF(__dllonexit, -1)
5130 FF(_snprintf,-1)
5131 FF(free, -1)
5132 {"??3@YAXPAX@Z", -1, expdelete},
5133 {"??2@YAPAXI@Z", -1, expnew},
5134 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5135 {"_winver",-1,(void*)&_winver},
5136 FF(strrchr, -1)
5137 FF(strchr, -1)
5138 FF(strlen, -1)
5139 FF(strcpy, -1)
5140 FF(strncpy, -1)
5141 FF(wcscpy, -1)
5142 FF(strcmp, -1)
5143 FF(strncmp, -1)
5144 FF(strcat, -1)
5145 FF(_stricmp,-1)
5146 FF(_strdup,-1)
5147 FF(_setjmp3,-1)
5148 FF(isalnum, -1)
5149 FF(isspace, -1)
5150 FF(isalpha, -1)
5151 FF(isdigit, -1)
5152 FF(memmove, -1)
5153 FF(memcmp, -1)
5154 FF(memset, -1)
5155 FF(memcpy, -1)
5156 FF(time, -1)
5157 FF(rand, -1)
5158 FF(srand, -1)
5159 FF(log10, -1)
5160 FF(pow, -1)
5161 FF(cos, -1)
5162 FF(_ftol,-1)
5163 FF(_CIpow,-1)
5164 FF(_CIcos,-1)
5165 FF(_CIsin,-1)
5166 FF(_CIsqrt,-1)
5167 FF(ldexp,-1)
5168 FF(frexp,-1)
5169 FF(sprintf,-1)
5170 FF(sscanf,-1)
5171 FF(fopen,-1)
5172 FF(fprintf,-1)
5173 FF(printf,-1)
5174 FF(getenv,-1)
5175 FF(floor,-1)
5176 /* needed by frapsvid.dll */
5177 {"strstr",-1,(char *)&strstr},
5178 {"qsort",-1,(void *)&qsort},
5179 FF(_EH_prolog,-1)
5180 FF(calloc,-1)
5181 {"ceil",-1,(void*)&ceil},
5182 /* needed by imagepower mjpeg2k */
5183 {"clock",-1,(void*)&clock},
5184 {"memchr",-1,(void*)&memchr},
5185 {"vfprintf",-1,(void*)&vfprintf},
5186 // {"realloc",-1,(void*)&realloc},
5187 FF(realloc,-1)
5188 {"puts",-1,(void*)&puts}
5190 struct exports exp_winmm[]={
5191 FF(GetDriverModuleHandle, -1)
5192 FF(timeGetTime, -1)
5193 FF(DefDriverProc, -1)
5194 FF(OpenDriverA, -1)
5195 FF(OpenDriver, -1)
5196 FF(timeGetDevCaps, -1)
5197 FF(timeBeginPeriod, -1)
5198 #ifdef CONFIG_QTX_CODECS
5199 FF(timeEndPeriod, -1)
5200 FF(waveOutGetNumDevs, -1)
5201 #endif
5203 struct exports exp_psapi[]={
5204 FF(GetModuleBaseNameA, -1)
5206 struct exports exp_user32[]={
5207 FF(LoadIconA,-1)
5208 FF(LoadStringA, -1)
5209 FF(wsprintfA, -1)
5210 FF(GetDC, -1)
5211 FF(GetDesktopWindow, -1)
5212 FF(ReleaseDC, -1)
5213 FF(IsRectEmpty, -1)
5214 FF(LoadCursorA,-1)
5215 FF(SetCursor,-1)
5216 FF(GetCursorPos,-1)
5217 #ifdef CONFIG_QTX_CODECS
5218 FF(ShowCursor,-1)
5219 #endif
5220 FF(RegisterWindowMessageA,-1)
5221 FF(GetSystemMetrics,-1)
5222 FF(GetSysColor,-1)
5223 FF(GetSysColorBrush,-1)
5224 FF(GetWindowDC, -1)
5225 FF(DrawTextA, -1)
5226 FF(MessageBoxA, -1)
5227 FF(RegisterClassA, -1)
5228 FF(UnregisterClassA, -1)
5229 #ifdef CONFIG_QTX_CODECS
5230 FF(GetWindowRect, -1)
5231 FF(MonitorFromWindow, -1)
5232 FF(MonitorFromRect, -1)
5233 FF(MonitorFromPoint, -1)
5234 FF(EnumDisplayMonitors, -1)
5235 FF(GetMonitorInfoA, -1)
5236 FF(EnumDisplayDevicesA, -1)
5237 FF(GetClientRect, -1)
5238 FF(ClientToScreen, -1)
5239 FF(IsWindowVisible, -1)
5240 FF(GetActiveWindow, -1)
5241 FF(GetClassNameA, -1)
5242 FF(GetClassInfoA, -1)
5243 FF(GetWindowLongA, -1)
5244 FF(EnumWindows, -1)
5245 FF(GetWindowThreadProcessId, -1)
5246 FF(CreateWindowExA, -1)
5247 #endif
5248 FF(MessageBeep, -1)
5249 FF(DialogBoxParamA, -1)
5250 FF(RegisterClipboardFormatA, -1)
5251 FF(CharNextA, -1)
5252 FF(EnumDisplaySettingsA, -1)
5254 struct exports exp_advapi32[]={
5255 FF(RegCloseKey, -1)
5256 FF(RegCreateKeyA, -1)
5257 FF(RegCreateKeyExA, -1)
5258 FF(RegEnumKeyExA, -1)
5259 FF(RegEnumValueA, -1)
5260 FF(RegOpenKeyA, -1)
5261 FF(RegOpenKeyExA, -1)
5262 FF(RegQueryValueExA, -1)
5263 FF(RegSetValueExA, -1)
5264 FF(RegQueryInfoKeyA, -1)
5266 struct exports exp_gdi32[]={
5267 FF(CreateCompatibleDC, -1)
5268 FF(CreateFontA, -1)
5269 FF(DeleteDC, -1)
5270 FF(DeleteObject, -1)
5271 FF(GetDeviceCaps, -1)
5272 FF(GetSystemPaletteEntries, -1)
5273 #ifdef CONFIG_QTX_CODECS
5274 FF(CreatePalette, -1)
5275 FF(GetObjectA, -1)
5276 FF(CreateRectRgn, -1)
5277 #endif
5279 struct exports exp_version[]={
5280 FF(GetFileVersionInfoSizeA, -1)
5282 struct exports exp_ole32[]={
5283 FF(CoCreateFreeThreadedMarshaler,-1)
5284 FF(CoCreateInstance, -1)
5285 FF(CoInitialize, -1)
5286 FF(CoInitializeEx, -1)
5287 FF(CoUninitialize, -1)
5288 FF(CoTaskMemAlloc, -1)
5289 FF(CoTaskMemFree, -1)
5290 FF(StringFromGUID2, -1)
5291 FF(PropVariantClear, -1)
5293 // do we really need crtdll ???
5294 // msvcrt is the correct place probably...
5295 struct exports exp_crtdll[]={
5296 FF(memcpy, -1)
5297 FF(wcscpy, -1)
5299 struct exports exp_comctl32[]={
5300 FF(StringFromGUID2, -1)
5301 FF(InitCommonControls, 17)
5302 #ifdef CONFIG_QTX_CODECS
5303 FF(CreateUpDownControl, 16)
5304 #endif
5306 struct exports exp_wsock32[]={
5307 FF(htonl,8)
5308 FF(ntohl,14)
5310 struct exports exp_msdmo[]={
5311 FF(memcpy, -1) // just test
5312 FF(MoCopyMediaType, -1)
5313 FF(MoCreateMediaType, -1)
5314 FF(MoDeleteMediaType, -1)
5315 FF(MoDuplicateMediaType, -1)
5316 FF(MoFreeMediaType, -1)
5317 FF(MoInitMediaType, -1)
5319 struct exports exp_oleaut32[]={
5320 FF(SysAllocStringLen, 4)
5321 FF(SysFreeString, 6)
5322 FF(VariantInit, 8)
5323 #ifdef CONFIG_QTX_CODECS
5324 FF(SysStringByteLen, 149)
5325 #endif
5328 /* realplayer8:
5329 DLL Name: PNCRT.dll
5330 vma: Hint/Ord Member-Name
5331 22ff4 615 free
5332 2302e 250 _ftol
5333 22fea 666 malloc
5334 2303e 609 fprintf
5335 2305e 167 _adjust_fdiv
5336 23052 280 _initterm
5338 22ffc 176 _beginthreadex
5339 23036 284 _iob
5340 2300e 85 __CxxFrameHandler
5341 23022 411 _purecall
5343 #ifdef REALPLAYER
5344 struct exports exp_pncrt[]={
5345 FF(malloc, -1) // just test
5346 FF(free, -1) // just test
5347 FF(fprintf, -1) // just test
5348 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5349 FF(_ftol,-1)
5350 FF(_initterm, -1)
5351 {"??3@YAXPAX@Z", -1, expdelete},
5352 {"??2@YAPAXI@Z", -1, expnew},
5353 FF(__dllonexit, -1)
5354 FF(strncpy, -1)
5355 FF(_CIpow,-1)
5356 FF(calloc,-1)
5357 FF(memmove, -1)
5358 FF(ldexp, -1)
5359 FF(frexp, -1)
5361 #endif
5363 #ifdef CONFIG_QTX_CODECS
5364 struct exports exp_ddraw[]={
5365 FF(DirectDrawCreate, -1)
5367 #endif
5369 struct exports exp_comdlg32[]={
5370 FF(GetOpenFileNameA, -1)
5373 struct exports exp_shlwapi[]={
5374 FF(PathFindExtensionA, -1)
5375 FF(PathFindFileNameA, -1)
5378 struct exports exp_msvcr80[]={
5379 FF(_CIpow,-1)
5380 FF(_CIsin,-1)
5381 FF(_CIcos,-1)
5382 FF(_CIsqrt,-1)
5383 FF(memset,-1)
5384 FF(_initterm_e, -1)
5385 FF(_initterm, -1)
5386 FF(_decode_pointer, -1)
5387 /* needed by KGV1-VFW.dll */
5388 {"??2@YAPAXI@Z", -1, expnew},
5389 {"??3@YAXPAX@Z", -1, expdelete}
5392 struct exports exp_msvcp60[]={
5393 {"??0_Lockit@std@@QAE@XZ", -1, exp_0Lockit_dummy},
5394 {"??1_Lockit@std@@QAE@XZ", -1, exp_1Lockit_dummy}
5397 #define LL(X) \
5398 {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5400 struct libs libraries[]={
5401 LL(kernel32)
5402 LL(msvcrt)
5403 LL(winmm)
5404 LL(psapi)
5405 LL(user32)
5406 LL(advapi32)
5407 LL(gdi32)
5408 LL(version)
5409 LL(ole32)
5410 LL(oleaut32)
5411 LL(crtdll)
5412 LL(comctl32)
5413 LL(wsock32)
5414 LL(msdmo)
5415 #ifdef REALPLAYER
5416 LL(pncrt)
5417 #endif
5418 #ifdef CONFIG_QTX_CODECS
5419 LL(ddraw)
5420 #endif
5421 LL(comdlg32)
5422 LL(shlwapi)
5423 LL(msvcr80)
5424 LL(msvcp60)
5427 static WIN_BOOL WINAPI ext_stubs(void)
5429 // NOTE! these magic values will be replaced at runtime, make sure
5430 // add_stub can still find them if you change them.
5431 volatile int idx = 0x0deadabc;
5432 // make sure gcc does not do eip-relative call or something like that
5433 void (* volatile my_printf)(char *, char *) = (void *)0xdeadfbcd;
5434 my_printf("Called unk_%s\n", export_names[idx]);
5435 return 0;
5438 #define MAX_STUB_SIZE 0x60
5439 #define MAX_NUM_STUBS 200
5440 static int pos=0;
5441 static char *extcode = NULL;
5443 static void* add_stub(void)
5445 int i;
5446 int found = 0;
5447 // generated code in runtime!
5448 char* answ;
5449 if (!extcode)
5450 extcode = mmap_anon(NULL, MAX_NUM_STUBS * MAX_STUB_SIZE,
5451 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0);
5452 answ = extcode + pos * MAX_STUB_SIZE;
5453 if (pos >= MAX_NUM_STUBS) {
5454 printf("too many stubs, expect crash\n");
5455 return NULL;
5457 memcpy(answ, ext_stubs, MAX_STUB_SIZE);
5458 for (i = 0; i < MAX_STUB_SIZE - 3; i++) {
5459 int *magic = (int *)(answ + i);
5460 if (*magic == 0x0deadabc) {
5461 *magic = pos;
5462 found |= 1;
5464 if (*magic == 0xdeadfbcd) {
5465 *magic = (intptr_t)printf;
5466 found |= 2;
5469 if (found != 3) {
5470 printf("magic code not found in ext_subs, expect crash\n");
5471 return NULL;
5473 pos++;
5474 return (void*)answ;
5477 void* LookupExternal(const char* library, int ordinal)
5479 int i,j;
5480 if(library==0)
5482 printf("ERROR: library=0\n");
5483 return (void*)ext_unknown;
5485 // printf("%x %x\n", &unk_exp1, &unk_exp2);
5487 dbgprintf("External func %s:%d\n", library, ordinal);
5489 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5491 if(strcasecmp(library, libraries[i].name))
5492 continue;
5493 for(j=0; j<libraries[i].length; j++)
5495 if(ordinal!=libraries[i].exps[j].id)
5496 continue;
5497 //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5498 return libraries[i].exps[j].func;
5502 #ifndef LOADLIB_TRY_NATIVE
5503 /* hack for truespeech and vssh264*/
5504 if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5505 #endif
5506 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5508 int hand;
5509 WINE_MODREF *wm;
5510 void *func;
5512 hand = LoadLibraryA(library);
5513 if (!hand)
5514 goto no_dll;
5515 wm = MODULE32_LookupHMODULE(hand);
5516 if (!wm)
5518 FreeLibrary(hand);
5519 goto no_dll;
5521 func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5522 if (!func)
5524 printf("No such ordinal in external dll\n");
5525 FreeLibrary((int)hand);
5526 goto no_dll;
5529 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5530 hand, func);
5531 return func;
5534 no_dll:
5535 if(pos>150)return 0;
5536 snprintf(export_names[pos], sizeof(export_names[pos]), "%s:%d", library, ordinal);
5537 return add_stub();
5540 void* LookupExternalByName(const char* library, const char* name)
5542 int i,j;
5543 // return (void*)ext_unknown;
5544 if(library==0)
5546 printf("ERROR: library=0\n");
5547 return (void*)ext_unknown;
5549 if((unsigned long)name<=0xffff)
5551 return LookupExternal(library, (int)name);
5553 dbgprintf("External func %s:%s\n", library, name);
5554 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5556 if(strcasecmp(library, libraries[i].name))
5557 continue;
5558 for(j=0; j<libraries[i].length; j++)
5560 if(strcmp(name, libraries[i].exps[j].name))
5561 continue;
5562 if((unsigned int)(libraries[i].exps[j].func) == -1)
5563 return NULL; //undefined func
5564 // printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5565 return libraries[i].exps[j].func;
5569 #ifndef LOADLIB_TRY_NATIVE
5570 /* hack for vss h264 */
5571 if (!strcmp(library,"vssh264core.dll") || !strcmp(library,"3ivx.dll"))
5572 #endif
5573 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5575 int hand;
5576 WINE_MODREF *wm;
5577 void *func;
5579 hand = LoadLibraryA(library);
5580 if (!hand)
5581 goto no_dll_byname;
5582 wm = MODULE32_LookupHMODULE(hand);
5583 if (!wm)
5585 FreeLibrary(hand);
5586 goto no_dll_byname;
5588 func = PE_FindExportedFunction(wm, name, 0);
5589 if (!func)
5591 printf("No such name in external dll\n");
5592 FreeLibrary((int)hand);
5593 goto no_dll_byname;
5596 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5597 hand, func);
5598 return func;
5601 no_dll_byname:
5602 if(pos>150)return 0;// to many symbols
5603 snprintf(export_names[pos], sizeof(export_names[pos]), "%s", name);
5604 return add_stub();
5607 void my_garbagecollection(void)
5609 #ifdef GARBAGE
5610 int unfree = 0, unfreecnt = 0;
5612 int max_fatal = 8;
5613 free_registry();
5614 while (last_alloc)
5616 alloc_header* mem = last_alloc + 1;
5617 unfree += my_size(mem);
5618 unfreecnt++;
5619 if (my_release(mem) != 0)
5620 // avoid endless loop when memory is trashed
5621 if (--max_fatal < 0)
5622 break;
5624 dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5625 #endif
5626 g_tls = NULL;
5627 list = NULL;