Merge svn changes up to r30448
[mplayer/kovensky.git] / loader / win32.c
blob3b0dd5bb3ea1175a33fd600a3723453da0cf9fb0
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 #ifdef CONFIG_QTX_CODECS
23 #define QTX
24 #endif
25 #define REALPLAYER
26 //#define LOADLIB_TRY_NATIVE
28 #ifdef QTX
29 #define PSEUDO_SCREEN_WIDTH /*640*/800
30 #define PSEUDO_SCREEN_HEIGHT /*480*/600
31 #endif
33 #include "wine/winbase.h"
34 #include "wine/winreg.h"
35 #include "wine/winnt.h"
36 #include "wine/winerror.h"
37 #include "wine/debugtools.h"
38 #include "wine/module.h"
39 #include "wine/winuser.h"
40 #include "wine/objbase.h"
42 #include <stdio.h>
43 #include "win32.h"
45 #include "registry.h"
46 #include "loader.h"
47 #include "com.h"
48 #include "ext.h"
50 #include <stdlib.h>
51 #include <assert.h>
52 #include <stdarg.h>
53 #include <ctype.h>
54 #include <pthread.h>
55 #include <errno.h>
56 #include <time.h>
57 #include <math.h>
58 #include <unistd.h>
59 #include <fcntl.h>
60 #include <sys/types.h>
61 #include <dirent.h>
62 #include <sys/time.h>
63 #include <sys/stat.h>
64 #include <sys/timeb.h>
65 #ifdef HAVE_KSTAT
66 #include <kstat.h>
67 #endif
69 #ifdef HAVE_SYS_MMAN_H
70 #include <sys/mman.h>
71 #else
72 #include "osdep/mmap.h"
73 #endif
74 #include "osdep/mmap_anon.h"
76 char* def_path = WIN32_PATH;
78 static void do_cpuid(unsigned int ax, unsigned int *regs)
80 __asm__ volatile
82 "pushl %%ebx; pushl %%ecx; pushl %%edx;"
83 ".byte 0x0f, 0xa2;"
84 "movl %%eax, (%2);"
85 "movl %%ebx, 4(%2);"
86 "movl %%ecx, 8(%2);"
87 "movl %%edx, 12(%2);"
88 "popl %%edx; popl %%ecx; popl %%ebx;"
89 : "=a" (ax)
90 : "0" (ax), "S" (regs)
93 static unsigned int c_localcount_tsc(void)
95 int a;
96 __asm__ volatile
98 "rdtsc\n\t"
99 :"=a"(a)
101 :"edx"
103 return a;
105 static void c_longcount_tsc(long long* z)
107 __asm__ volatile
109 "pushl %%ebx\n\t"
110 "movl %%eax, %%ebx\n\t"
111 "rdtsc\n\t"
112 "movl %%eax, 0(%%ebx)\n\t"
113 "movl %%edx, 4(%%ebx)\n\t"
114 "popl %%ebx\n\t"
115 ::"a"(z)
116 :"edx"
119 static unsigned int c_localcount_notsc(void)
121 struct timeval tv;
122 unsigned limit=~0;
123 limit/=1000000;
124 gettimeofday(&tv, 0);
125 return limit*tv.tv_usec;
127 static void c_longcount_notsc(long long* z)
129 struct timeval tv;
130 unsigned long long result;
131 unsigned limit=~0;
132 if(!z)return;
133 limit/=1000000;
134 gettimeofday(&tv, 0);
135 result=tv.tv_sec;
136 result<<=32;
137 result+=limit*tv.tv_usec;
138 *z=result;
140 static unsigned int localcount_stub(void);
141 static void longcount_stub(long long*);
142 static unsigned int (*localcount)()=localcount_stub;
143 static void (*longcount)(long long*)=longcount_stub;
145 static pthread_mutex_t memmut;
147 static unsigned int localcount_stub(void)
149 unsigned int regs[4];
150 do_cpuid(1, regs);
151 if ((regs[3] & 0x00000010) != 0)
153 localcount=c_localcount_tsc;
154 longcount=c_longcount_tsc;
156 else
158 localcount=c_localcount_notsc;
159 longcount=c_longcount_notsc;
161 return localcount();
163 static void longcount_stub(long long* z)
165 unsigned int regs[4];
166 do_cpuid(1, regs);
167 if ((regs[3] & 0x00000010) != 0)
169 localcount=c_localcount_tsc;
170 longcount=c_longcount_tsc;
172 else
174 localcount=c_localcount_notsc;
175 longcount=c_longcount_notsc;
177 longcount(z);
180 #include "mp_msg.h"
181 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
182 //#define DETAILED_OUT
183 static inline void dbgprintf(char* fmt, ...)
185 #ifdef DETAILED_OUT
186 if(LOADER_DEBUG)
188 FILE* f;
189 va_list va;
190 va_start(va, fmt);
191 f=fopen("./log", "a");
192 vprintf(fmt, va);
193 fflush(stdout);
194 if(f)
196 vfprintf(f, fmt, va);
197 fsync(fileno(f));
198 fclose(f);
200 va_end(va);
202 #endif
203 if ( mp_msg_test(MSGT_WIN32,MSGL_DBG3) )
205 va_list va;
207 va_start(va, fmt);
208 vprintf(fmt, va);
209 // mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
210 va_end(va);
211 fflush(stdout);
216 char export_names[300][32]={
217 "name1",
218 //"name2",
219 //"name3"
221 //#define min(x,y) ((x)<(y)?(x):(y))
223 void destroy_event(void* event);
225 struct th_list_t;
226 typedef struct th_list_t{
227 int id;
228 void* thread;
229 struct th_list_t* next;
230 struct th_list_t* prev;
231 } th_list;
234 // have to be cleared by GARBAGE COLLECTOR
235 //static unsigned char* heap=NULL;
236 //static int heap_counter=0;
237 static tls_t* g_tls=NULL;
238 static th_list* list=NULL;
240 #if 0
241 static void test_heap(void)
243 int offset=0;
244 if(heap==0)
245 return;
246 while(offset<heap_counter)
248 if(*(int*)(heap+offset)!=0x433476)
250 printf("Heap corruption at address %d\n", offset);
251 return;
253 offset+=8+*(int*)(heap+offset+4);
255 for(;offset<min(offset+1000, 20000000); offset++)
256 if(heap[offset]!=0xCC)
258 printf("Free heap corruption at address %d\n", offset);
261 #endif
262 #undef MEMORY_DEBUG
264 #ifdef MEMORY_DEBUG
266 static void* my_mreq(int size, int to_zero)
268 static int test=0;
269 test++;
270 if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
271 // test_heap();
272 if(heap==NULL)
274 heap=malloc(20000000);
275 memset(heap, 0xCC,20000000);
277 if(heap==0)
279 printf("No enough memory\n");
280 return 0;
282 if(heap_counter+size>20000000)
284 printf("No enough memory\n");
285 return 0;
287 *(int*)(heap+heap_counter)=0x433476;
288 heap_counter+=4;
289 *(int*)(heap+heap_counter)=size;
290 heap_counter+=4;
291 printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
292 if(to_zero)
293 memset(heap+heap_counter, 0, size);
294 else
295 memset(heap+heap_counter, 0xcc, size); // make crash reproducable
296 heap_counter+=size;
297 return heap+heap_counter-size;
299 static int my_release(char* memory)
301 // test_heap();
302 if(memory==NULL)
304 printf("ERROR: free(0)\n");
305 return 0;
307 if(*(int*)(memory-8)!=0x433476)
309 printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
310 return 0;
312 printf("Freed %d bytes of memory\n", *(int*)(memory-4));
313 // memset(memory-8, *(int*)(memory-4), 0xCC);
314 return 0;
317 #else
318 #define GARBAGE
319 typedef struct alloc_header_t alloc_header;
320 struct alloc_header_t
322 // let's keep allocated data 16 byte aligned
323 alloc_header* prev;
324 alloc_header* next;
325 long deadbeef;
326 long size;
327 long type;
328 long reserved1;
329 long reserved2;
330 long reserved3;
333 #ifdef GARBAGE
334 static alloc_header* last_alloc = NULL;
335 static int alccnt = 0;
336 #endif
338 #define AREATYPE_CLIENT 0
339 #define AREATYPE_EVENT 1
340 #define AREATYPE_MUTEX 2
341 #define AREATYPE_COND 3
342 #define AREATYPE_CRITSECT 4
344 /* -- critical sections -- */
345 struct CRITSECT
347 pthread_t id;
348 pthread_mutex_t mutex;
349 int locked;
350 long deadbeef;
353 void* mreq_private(int size, int to_zero, int type);
354 void* mreq_private(int size, int to_zero, int type)
356 int nsize = size + sizeof(alloc_header);
357 alloc_header* header = (alloc_header* ) malloc(nsize);
358 if (!header)
359 return 0;
360 if (to_zero)
361 memset(header, 0, nsize);
362 #ifdef GARBAGE
363 if (!last_alloc)
365 pthread_mutex_init(&memmut, NULL);
366 pthread_mutex_lock(&memmut);
368 else
370 pthread_mutex_lock(&memmut);
371 last_alloc->next = header; /* set next */
374 header->prev = last_alloc;
375 header->next = 0;
376 last_alloc = header;
377 alccnt++;
378 pthread_mutex_unlock(&memmut);
379 #endif
380 header->deadbeef = 0xdeadbeef;
381 header->size = size;
382 header->type = type;
384 //if (alccnt < 40000) printf("MY_REQ: %p\t%d t:%d (cnt:%d)\n", header, size, type, alccnt);
385 return header + 1;
388 static int my_release(void* memory)
390 alloc_header* header = (alloc_header*) memory - 1;
391 #ifdef GARBAGE
392 alloc_header* prevmem;
393 alloc_header* nextmem;
395 if (memory == 0)
396 return 0;
398 if (header->deadbeef != (long) 0xdeadbeef)
400 dbgprintf("FATAL releasing corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
401 return 0;
404 pthread_mutex_lock(&memmut);
406 switch(header->type)
408 case AREATYPE_EVENT:
409 destroy_event(memory);
410 break;
411 case AREATYPE_COND:
412 pthread_cond_destroy((pthread_cond_t*)memory);
413 break;
414 case AREATYPE_MUTEX:
415 pthread_mutex_destroy((pthread_mutex_t*)memory);
416 break;
417 case AREATYPE_CRITSECT:
418 pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
419 break;
420 default:
421 //memset(memory, 0xcc, header->size);
425 header->deadbeef = 0;
426 prevmem = header->prev;
427 nextmem = header->next;
429 if (prevmem)
430 prevmem->next = nextmem;
431 if (nextmem)
432 nextmem->prev = prevmem;
434 if (header == last_alloc)
435 last_alloc = prevmem;
437 alccnt--;
439 if (last_alloc)
440 pthread_mutex_unlock(&memmut);
441 else
442 pthread_mutex_destroy(&memmut);
444 //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld (%d)\n", header, header->size, alccnt);
445 #else
446 if (memory == 0)
447 return 0;
448 #endif
449 //memset(header + 1, 0xcc, header->size);
450 free(header);
451 return 0;
453 #endif
455 static inline void* my_mreq(int size, int to_zero)
457 return mreq_private(size, to_zero, AREATYPE_CLIENT);
460 static int my_size(void* memory)
462 if(!memory) return 0;
463 return ((alloc_header*)memory)[-1].size;
466 static void* my_realloc(void* memory, int size)
468 void *ans = memory;
469 int osize;
470 if (memory == NULL)
471 return my_mreq(size, 0);
472 osize = my_size(memory);
473 if (osize < size)
475 ans = my_mreq(size, 0);
476 memcpy(ans, memory, osize);
477 my_release(memory);
479 return ans;
484 * WINE API - native implementation for several win32 libraries
488 static int WINAPI ext_unknown(void)
490 printf("Unknown func called\n");
491 return 0;
494 static int WINAPI expGetVolumeInformationA( const char *root, char *label,
495 unsigned int label_len, unsigned int *serial,
496 unsigned int *filename_len,unsigned int *flags,
497 char *fsname, unsigned int fsname_len )
499 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
500 root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
501 //hack Do not return any real data - do nothing
502 return 1;
505 static unsigned int WINAPI expGetDriveTypeA( const char *root )
507 dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
508 // hack return as Fixed Drive Type
509 return DRIVE_FIXED;
512 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
514 dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
515 // hack only have one drive c:\ in this hack
516 *buffer++='c';
517 *buffer++=':';
518 *buffer++='\\';
519 *buffer++='\0';
520 *buffer= '\0';
521 return 4; // 1 drive * 4 bytes (includes null)
525 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
527 int result = (count == 0 || ptr != 0) ? 0 : 1;
528 dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
529 return result;
531 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
533 int result = (count == 0 || ptr != 0) ? 0 : 1;
534 dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
535 return result;
537 static int WINAPI expDisableThreadLibraryCalls(int module)
539 dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
540 return 0;
543 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
545 HMODULE result;
546 if (pdrv==NULL)
547 result=0;
548 else
549 result=pdrv->hDriverModule;
550 dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
551 return result;
554 #define MODULE_HANDLE_kernel32 ((HMODULE)0x120)
555 #define MODULE_HANDLE_user32 ((HMODULE)0x121)
556 #ifdef QTX
557 #define MODULE_HANDLE_wininet ((HMODULE)0x122)
558 #define MODULE_HANDLE_ddraw ((HMODULE)0x123)
559 #define MODULE_HANDLE_advapi32 ((HMODULE)0x124)
560 #endif
561 #define MODULE_HANDLE_comdlg32 ((HMODULE)0x125)
562 #define MODULE_HANDLE_msvcrt ((HMODULE)0x126)
563 #define MODULE_HANDLE_ole32 ((HMODULE)0x127)
564 #define MODULE_HANDLE_winmm ((HMODULE)0x128)
566 static HMODULE WINAPI expGetModuleHandleA(const char* name)
568 WINE_MODREF* wm;
569 HMODULE result;
570 if(!name)
571 #ifdef QTX
572 result=1;
573 #else
574 result=0;
575 #endif
576 else
578 wm=MODULE_FindModule(name);
579 if(wm==0)result=0;
580 else
581 result=(HMODULE)(wm->module);
583 if(!result)
585 if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
586 result=MODULE_HANDLE_kernel32;
587 #ifdef QTX
588 if(name && strcasecmp(name, "user32")==0)
589 result=MODULE_HANDLE_user32;
590 #endif
592 dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
593 return result;
596 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
597 void* lpStartAddress, void* lpParameter,
598 long dwFlags, long* dwThreadId)
600 pthread_t *pth;
601 // printf("CreateThread:");
602 pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
603 pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
604 if(dwFlags)
605 printf( "WARNING: CreateThread flags not supported\n");
606 if(dwThreadId)
607 *dwThreadId=(long)pth;
608 if(list==NULL)
610 list=my_mreq(sizeof(th_list), 1);
611 list->next=list->prev=NULL;
613 else
615 list->next=my_mreq(sizeof(th_list), 0);
616 list->next->prev=list;
617 list->next->next=NULL;
618 list=list->next;
620 list->thread=pth;
621 dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
622 pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
623 return pth;
626 struct mutex_list_t;
628 struct mutex_list_t
630 char type;
631 pthread_mutex_t *pm;
632 pthread_cond_t *pc;
633 char state;
634 char reset;
635 char name[128];
636 int semaphore;
637 struct mutex_list_t* next;
638 struct mutex_list_t* prev;
640 typedef struct mutex_list_t mutex_list;
641 static mutex_list* mlist=NULL;
643 void destroy_event(void* event)
645 mutex_list* pp=mlist;
646 // printf("garbage collector: destroy_event(%x)\n", event);
647 while(pp)
649 if(pp==(mutex_list*)event)
651 if(pp->next)
652 pp->next->prev=pp->prev;
653 if(pp->prev)
654 pp->prev->next=pp->next;
655 if(mlist==(mutex_list*)event)
656 mlist=mlist->prev;
658 pp=mlist;
659 while(pp)
661 printf("%x => ", pp);
662 pp=pp->prev;
664 printf("0\n");
666 return;
668 pp=pp->prev;
672 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
673 char bInitialState, const char* name)
675 pthread_mutex_t *pm;
676 pthread_cond_t *pc;
678 mutex_list* pp;
679 pp=mlist;
680 while(pp)
682 printf("%x => ", pp);
683 pp=pp->prev;
685 printf("0\n");
687 if(mlist!=NULL)
689 mutex_list* pp=mlist;
690 if(name!=NULL)
693 if((strcmp(pp->name, name)==0) && (pp->type==0))
695 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
696 pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
697 return pp->pm;
699 }while((pp=pp->prev) != NULL);
701 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
702 pthread_mutex_init(pm, NULL);
703 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
704 pthread_cond_init(pc, NULL);
705 if(mlist==NULL)
707 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
708 mlist->next=mlist->prev=NULL;
710 else
712 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
713 mlist->next->prev=mlist;
714 mlist->next->next=NULL;
715 mlist=mlist->next;
717 mlist->type=0; /* Type Event */
718 mlist->pm=pm;
719 mlist->pc=pc;
720 mlist->state=bInitialState;
721 mlist->reset=bManualReset;
722 if(name)
723 strncpy(mlist->name, name, 127);
724 else
725 mlist->name[0]=0;
726 if(pm==NULL)
727 dbgprintf("ERROR::: CreateEventA failure\n");
729 if(bInitialState)
730 pthread_mutex_lock(pm);
732 if(name)
733 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
734 pSecAttr, bManualReset, bInitialState, name, name, mlist);
735 else
736 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
737 pSecAttr, bManualReset, bInitialState, mlist);
738 return mlist;
741 static void* WINAPI expSetEvent(void* event)
743 mutex_list *ml = (mutex_list *)event;
744 dbgprintf("SetEvent(%x) => 0x1\n", event);
745 pthread_mutex_lock(ml->pm);
746 if (ml->state == 0) {
747 ml->state = 1;
748 pthread_cond_signal(ml->pc);
750 pthread_mutex_unlock(ml->pm);
752 return (void *)1;
754 static void* WINAPI expResetEvent(void* event)
756 mutex_list *ml = (mutex_list *)event;
757 dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
758 pthread_mutex_lock(ml->pm);
759 ml->state = 0;
760 pthread_mutex_unlock(ml->pm);
762 return (void *)1;
765 static void* WINAPI expWaitForSingleObject(void* object, int duration)
767 mutex_list *ml = (mutex_list *)object;
768 // FIXME FIXME FIXME - this value is sometime unititialize !!!
769 int ret = WAIT_FAILED;
770 mutex_list* pp=mlist;
771 if(object == (void*)0xcfcf9898)
774 From GetCurrentThread() documentation:
775 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.
777 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.
779 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.
781 dbgprintf("WaitForSingleObject(thread_handle) called\n");
782 return (void*)WAIT_FAILED;
784 dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
786 // loop below was slightly fixed - its used just for checking if
787 // this object really exists in our list
788 if (!ml)
789 return (void*) ret;
790 while (pp && (pp->pm != ml->pm))
791 pp = pp->prev;
792 if (!pp) {
793 dbgprintf("WaitForSingleObject: NotFound\n");
794 return (void*)ret;
797 pthread_mutex_lock(ml->pm);
799 switch(ml->type) {
800 case 0: /* Event */
801 if (duration == 0) { /* Check Only */
802 if (ml->state == 1) ret = WAIT_FAILED;
803 else ret = WAIT_OBJECT_0;
805 if (duration == -1) { /* INFINITE */
806 if (ml->state == 0)
807 pthread_cond_wait(ml->pc,ml->pm);
808 if (ml->reset)
809 ml->state = 0;
810 ret = WAIT_OBJECT_0;
812 if (duration > 0) { /* Timed Wait */
813 struct timespec abstime;
814 struct timeval now;
815 gettimeofday(&now, 0);
816 abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
817 abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
818 if (ml->state == 0)
819 ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
820 if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
821 else ret = WAIT_OBJECT_0;
822 if (ml->reset)
823 ml->state = 0;
825 break;
826 case 1: /* Semaphore */
827 if (duration == 0) {
828 if(ml->semaphore==0) ret = WAIT_FAILED;
829 else {
830 ml->semaphore++;
831 ret = WAIT_OBJECT_0;
834 if (duration == -1) {
835 if (ml->semaphore==0)
836 pthread_cond_wait(ml->pc,ml->pm);
837 ml->semaphore--;
839 break;
841 pthread_mutex_unlock(ml->pm);
843 dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
844 return (void *)ret;
847 #ifdef QTX
848 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
849 int WaitAll, int duration)
851 int i;
852 void *object;
853 void *ret;
855 dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
856 count, objects, WaitAll, duration);
858 for (i = 0; i < count; i++)
860 object = (void *)objects[i];
861 ret = expWaitForSingleObject(object, duration);
862 if (WaitAll)
863 dbgprintf("WaitAll flag not yet supported...\n");
864 else
865 return ret;
867 return NULL;
870 static void WINAPI expExitThread(int retcode)
872 dbgprintf("ExitThread(%d)\n", retcode);
873 pthread_exit(&retcode);
876 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
877 char bInitialOwner, const char *name)
879 HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
881 if (name)
882 dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
883 pSecAttr, bInitialOwner, name, mlist);
884 else
885 dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
886 pSecAttr, bInitialOwner, mlist);
887 #ifndef QTX
888 /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
889 waits for ever, else it works ;) */
890 return mlist;
891 #endif
894 static int WINAPI expReleaseMutex(HANDLE hMutex)
896 dbgprintf("ReleaseMutex(%x) => 1\n", hMutex);
897 /* FIXME:XXX !! not yet implemented */
898 return 1;
900 #endif
902 static int pf_set = 0;
903 static BYTE PF[64] = {0,};
905 static void DumpSystemInfo(const SYSTEM_INFO* si)
907 dbgprintf(" Processor architecture %d\n", si->u.s.wProcessorArchitecture);
908 dbgprintf(" Page size: %d\n", si->dwPageSize);
909 dbgprintf(" Minimum app address: %d\n", si->lpMinimumApplicationAddress);
910 dbgprintf(" Maximum app address: %d\n", si->lpMaximumApplicationAddress);
911 dbgprintf(" Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
912 dbgprintf(" Number of processors: %d\n", si->dwNumberOfProcessors);
913 dbgprintf(" Processor type: 0x%x\n", si->dwProcessorType);
914 dbgprintf(" Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
915 dbgprintf(" Processor level: 0x%x\n", si->wProcessorLevel);
916 dbgprintf(" Processor revision: 0x%x\n", si->wProcessorRevision);
919 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
921 /* FIXME: better values for the two entries below... */
922 static int cache = 0;
923 static SYSTEM_INFO cachedsi;
924 dbgprintf("GetSystemInfo(%p) =>\n", si);
926 if (cache) {
927 goto exit;
929 memset(PF,0,sizeof(PF));
930 pf_set = 1;
932 cachedsi.u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
933 cachedsi.dwPageSize = getpagesize();
935 /* FIXME: better values for the two entries below... */
936 cachedsi.lpMinimumApplicationAddress = (void *)0x00000000;
937 cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
938 cachedsi.dwActiveProcessorMask = 1;
939 cachedsi.dwNumberOfProcessors = 1;
940 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
941 cachedsi.dwAllocationGranularity = 0x10000;
942 cachedsi.wProcessorLevel = 5; /* pentium */
943 cachedsi.wProcessorRevision = 0x0101;
945 /* mplayer's way to detect PF's */
947 #include "cpudetect.h"
949 if (gCpuCaps.hasMMX)
950 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
951 if (gCpuCaps.hasSSE)
952 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
953 if (gCpuCaps.hasSSE2)
954 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
955 if (gCpuCaps.has3DNow)
956 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
958 if (gCpuCaps.cpuType == 4)
960 cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
961 cachedsi.wProcessorLevel = 4;
963 else if (gCpuCaps.cpuType >= 5)
965 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
966 cachedsi.wProcessorLevel = 5;
968 else
970 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
971 cachedsi.wProcessorLevel = 3;
973 cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
974 cachedsi.dwNumberOfProcessors = 1; /* hardcoded */
977 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
978 fdiv_bug and fpu emulation flags -- alex/MPlayer */
979 #ifdef __linux__
981 char buf[20];
982 char line[200];
983 FILE *f = fopen ("/proc/cpuinfo", "r");
985 if (!f)
987 mp_msg(MSGT_WIN32, MSGL_WARN, "expGetSystemInfo: "
988 "/proc/cpuinfo not readable! "
989 "Expect bad performance and/or weird behaviour\n");
990 goto exit;
992 while (fgets(line,200,f)!=NULL) {
993 char *s,*value;
995 /* NOTE: the ':' is the only character we can rely on */
996 if (!(value = strchr(line,':')))
997 continue;
998 /* terminate the valuename */
999 *value++ = '\0';
1000 /* skip any leading spaces */
1001 while (*value==' ') value++;
1002 if ((s=strchr(value,'\n')))
1003 *s='\0';
1005 /* 2.1 method */
1006 if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
1007 if (isdigit (value[0])) {
1008 switch (value[0] - '0') {
1009 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1010 cachedsi.wProcessorLevel= 3;
1011 break;
1012 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1013 cachedsi.wProcessorLevel= 4;
1014 break;
1015 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1016 cachedsi.wProcessorLevel= 5;
1017 break;
1018 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1019 cachedsi.wProcessorLevel= 5;
1020 break;
1021 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1022 cachedsi.wProcessorLevel= 5;
1023 break;
1026 /* set the CPU type of the current processor */
1027 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1028 continue;
1030 /* old 2.0 method */
1031 if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
1032 if ( isdigit (value[0]) && value[1] == '8' &&
1033 value[2] == '6' && value[3] == 0
1035 switch (value[0] - '0') {
1036 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1037 cachedsi.wProcessorLevel= 3;
1038 break;
1039 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1040 cachedsi.wProcessorLevel= 4;
1041 break;
1042 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1043 cachedsi.wProcessorLevel= 5;
1044 break;
1045 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1046 cachedsi.wProcessorLevel= 5;
1047 break;
1048 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1049 cachedsi.wProcessorLevel= 5;
1050 break;
1053 /* set the CPU type of the current processor */
1054 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1055 continue;
1057 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
1058 if (!lstrncmpiA(value,"yes",3))
1059 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
1061 continue;
1063 if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
1064 if (!lstrncmpiA(value,"no",2))
1065 PF[PF_FLOATING_POINT_EMULATED] = TRUE;
1067 continue;
1069 if (!lstrncmpiA(line,"processor",strlen("processor"))) {
1070 /* processor number counts up...*/
1071 unsigned int x;
1073 if (sscanf(value,"%d",&x))
1074 if (x+1>cachedsi.dwNumberOfProcessors)
1075 cachedsi.dwNumberOfProcessors=x+1;
1077 /* Create a new processor subkey on a multiprocessor
1078 * system
1080 sprintf(buf,"%d",x);
1082 if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
1083 int x;
1085 if (sscanf(value,"%d",&x))
1086 cachedsi.wProcessorRevision = x;
1089 ( (!lstrncmpiA(line,"flags",strlen("flags")))
1090 || (!lstrncmpiA(line,"features",strlen("features"))) )
1092 if (strstr(value,"cx8"))
1093 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1094 if (strstr(value,"mmx"))
1095 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1096 if (strstr(value,"tsc"))
1097 PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
1098 if (strstr(value,"xmm") || strstr(value,"sse"))
1099 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1100 if (strstr(value,"sse2"))
1101 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
1102 if (strstr(value,"3dnow"))
1103 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1106 fclose (f);
1108 * ad hoc fix for smp machines.
1109 * some problems on WaitForSingleObject,CreateEvent,SetEvent
1110 * CreateThread ...etc..
1113 cachedsi.dwNumberOfProcessors=1;
1115 #endif /* __linux__ */
1116 cache = 1;
1117 exit:
1118 memcpy(si,&cachedsi,sizeof(*si));
1119 DumpSystemInfo(si);
1122 // avoid undefined expGetSystemInfo
1123 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
1125 WIN_BOOL result = 0;
1126 if (!pf_set)
1128 SYSTEM_INFO si;
1129 expGetSystemInfo(&si);
1131 if(v<64) result=PF[v];
1132 dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
1133 return result;
1137 static long WINAPI expGetVersion(void)
1139 dbgprintf("GetVersion() => 0xC0000004\n");
1140 return 0xC0000004;//Windows 95
1143 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
1145 // printf("HeapCreate:");
1146 HANDLE result;
1147 if(init_size==0)
1148 result=(HANDLE)my_mreq(0x110000, 0);
1149 else
1150 result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
1151 dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
1152 return result;
1155 // this is another dirty hack
1156 // VP31 is releasing one allocated Heap chunk twice
1157 // we will silently ignore this second call...
1158 static void* heapfreehack = 0;
1159 static int heapfreehackshown = 0;
1160 //void trapbug(void);
1161 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
1163 void* z;
1165 Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
1166 HeapAlloc returns area larger than size argument :-/
1168 actually according to M$ Doc HeapCreate size should be rounded
1169 to page boundaries thus we should simulate this
1171 //if (size == 22276) trapbug();
1172 z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
1173 if(z==0)
1174 printf("HeapAlloc failure\n");
1175 dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
1176 heapfreehack = 0; // reset
1177 return z;
1179 static long WINAPI expHeapDestroy(void* heap)
1181 dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
1182 my_release(heap);
1183 return 1;
1186 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
1188 dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
1189 if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
1190 && lpMem != (void*)0xbdbdbdbd)
1191 // 0xbdbdbdbd is for i263_drv.drv && libefence
1192 // it seems to be reading from relased memory
1193 // EF_PROTECT_FREE doens't show any probleme
1194 my_release(lpMem);
1195 else
1197 if (!heapfreehackshown++)
1198 printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
1200 heapfreehack = lpMem;
1201 return 1;
1203 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
1205 long result=my_size(pointer);
1206 dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
1207 return result;
1209 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
1211 long orgsize = my_size(lpMem);
1212 dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
1213 return my_realloc(lpMem, size);
1215 static long WINAPI expGetProcessHeap(void)
1217 dbgprintf("GetProcessHeap() => 1\n");
1218 return 1;
1220 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
1222 void* z = VirtualAlloc(v1, v2, v3, v4);
1223 if(z==0)
1224 printf("VirtualAlloc failure\n");
1225 dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
1226 return z;
1228 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
1230 int result = VirtualFree(v1,v2,v3);
1231 dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
1232 return result;
1235 /* we're building a table of critical sections. cs_win pointer uses the DLL
1236 cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
1237 struct critsecs_list_t
1239 CRITICAL_SECTION *cs_win;
1240 struct CRITSECT *cs_unix;
1243 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
1244 #undef CRITSECS_NEWTYPE
1245 //#define CRITSECS_NEWTYPE 1
1247 #ifdef CRITSECS_NEWTYPE
1248 /* increased due to ucod needs more than 32 entries */
1249 /* and 64 should be enough for everything */
1250 #define CRITSECS_LIST_MAX 64
1251 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
1253 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
1255 int i;
1257 for (i=0; i < CRITSECS_LIST_MAX; i++)
1258 if (critsecs_list[i].cs_win == cs_win)
1259 return i;
1260 return -1;
1263 static int critsecs_get_unused(void)
1265 int i;
1267 for (i=0; i < CRITSECS_LIST_MAX; i++)
1268 if (critsecs_list[i].cs_win == NULL)
1269 return i;
1270 return -1;
1273 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
1275 int i;
1277 for (i=0; i < CRITSECS_LIST_MAX; i++)
1278 if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
1279 return critsecs_list[i].cs_unix;
1280 return NULL;
1282 #endif
1284 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
1286 dbgprintf("InitializeCriticalSection(0x%x)\n", c);
1287 /* if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
1289 printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
1290 sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
1291 return;
1293 /* pthread_mutex_init((pthread_mutex_t*)c, NULL); */
1294 #ifdef CRITSECS_NEWTYPE
1296 struct CRITSECT *cs;
1297 int i = critsecs_get_unused();
1299 if (i < 0)
1301 printf("InitializeCriticalSection(%p) - no more space in list\n", c);
1302 return;
1304 dbgprintf("got unused space at %d\n", i);
1305 cs = malloc(sizeof(struct CRITSECT));
1306 if (!cs)
1308 printf("InitializeCriticalSection(%p) - out of memory\n", c);
1309 return;
1311 pthread_mutex_init(&cs->mutex, NULL);
1312 cs->locked = 0;
1313 critsecs_list[i].cs_win = c;
1314 critsecs_list[i].cs_unix = cs;
1315 dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
1316 i, c, cs);
1318 #else
1320 struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
1321 0, AREATYPE_CRITSECT);
1322 pthread_mutex_init(&cs->mutex, NULL);
1323 cs->locked=0;
1324 cs->deadbeef = 0xdeadbeef;
1325 *(void**)c = cs;
1327 #endif
1328 return;
1331 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
1333 #ifdef CRITSECS_NEWTYPE
1334 struct CRITSECT* cs = critsecs_get_unix(c);
1335 #else
1336 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1337 #endif
1338 dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
1339 if (!cs)
1341 dbgprintf("entered uninitialized critisec!\n");
1342 expInitializeCriticalSection(c);
1343 #ifdef CRITSECS_NEWTYPE
1344 cs=critsecs_get_unix(c);
1345 #else
1346 cs = (*(struct CRITSECT**)c);
1347 #endif
1348 dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
1350 if(cs->locked)
1351 if(cs->id==pthread_self())
1352 return;
1353 pthread_mutex_lock(&(cs->mutex));
1354 cs->locked=1;
1355 cs->id=pthread_self();
1356 return;
1358 static void WINAPI expLeaveCriticalSection(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 // struct CRITSECT* cs=(struct CRITSECT*)c;
1366 dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
1367 if (!cs)
1369 dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
1370 return;
1372 if (cs->locked)
1374 cs->locked=0;
1375 pthread_mutex_unlock(&(cs->mutex));
1377 else
1378 dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
1379 return;
1382 static void expfree(void* mem); /* forward declaration */
1384 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
1386 #ifdef CRITSECS_NEWTYPE
1387 struct CRITSECT* cs = critsecs_get_unix(c);
1388 #else
1389 struct CRITSECT* cs= (*(struct CRITSECT**)c);
1390 #endif
1391 // struct CRITSECT* cs=(struct CRITSECT*)c;
1392 dbgprintf("DeleteCriticalSection(0x%x)\n",c);
1394 if (!cs)
1396 dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
1397 return;
1400 if (cs->locked)
1402 dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
1403 pthread_mutex_unlock(&(cs->mutex));
1406 #ifndef GARBAGE
1407 pthread_mutex_destroy(&(cs->mutex));
1408 // released by GarbageCollector in my_relase otherwise
1409 #endif
1410 my_release(cs);
1411 #ifdef CRITSECS_NEWTYPE
1413 int i = critsecs_get_pos(c);
1415 if (i < 0)
1417 printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
1418 return;
1421 critsecs_list[i].cs_win = NULL;
1422 expfree(critsecs_list[i].cs_unix);
1423 critsecs_list[i].cs_unix = NULL;
1424 dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
1426 #endif
1427 return;
1429 static int WINAPI expGetCurrentThreadId(void)
1431 dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
1432 return pthread_self();
1434 static int WINAPI expGetCurrentProcess(void)
1436 dbgprintf("GetCurrentProcess() => %d\n", getpid());
1437 return getpid();
1440 #ifdef QTX
1441 // this version is required for Quicktime codecs (.qtx/.qts) to work.
1442 // (they assume some pointers at FS: segment)
1444 extern void* fs_seg;
1446 //static int tls_count;
1447 static int tls_use_map[64];
1448 static int WINAPI expTlsAlloc(void)
1450 int i;
1451 for(i=0; i<64; i++)
1452 if(tls_use_map[i]==0)
1454 tls_use_map[i]=1;
1455 dbgprintf("TlsAlloc() => %d\n",i);
1456 return i;
1458 dbgprintf("TlsAlloc() => -1 (ERROR)\n");
1459 return -1;
1462 //static int WINAPI expTlsSetValue(DWORD index, void* value)
1463 static int WINAPI expTlsSetValue(int index, void* value)
1465 dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
1466 // if((index<0) || (index>64))
1467 if((index>=64))
1468 return 0;
1469 *(void**)((char*)fs_seg+0x88+4*index) = value;
1470 return 1;
1473 static void* WINAPI expTlsGetValue(DWORD index)
1475 dbgprintf("TlsGetValue(%d)\n",index);
1476 // if((index<0) || (index>64))
1477 if((index>=64)) return NULL;
1478 return *(void**)((char*)fs_seg+0x88+4*index);
1481 static int WINAPI expTlsFree(int idx)
1483 int index = (int) idx;
1484 dbgprintf("TlsFree(%d)\n",index);
1485 if((index<0) || (index>64))
1486 return 0;
1487 tls_use_map[index]=0;
1488 return 1;
1491 #else
1492 struct tls_s {
1493 void* value;
1494 int used;
1495 struct tls_s* prev;
1496 struct tls_s* next;
1499 static void* WINAPI expTlsAlloc(void)
1501 if (g_tls == NULL)
1503 g_tls=my_mreq(sizeof(tls_t), 0);
1504 g_tls->next=g_tls->prev=NULL;
1506 else
1508 g_tls->next=my_mreq(sizeof(tls_t), 0);
1509 g_tls->next->prev=g_tls;
1510 g_tls->next->next=NULL;
1511 g_tls=g_tls->next;
1513 dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
1514 if (g_tls)
1515 g_tls->value=0; /* XXX For Divx.dll */
1516 return g_tls;
1519 static int WINAPI expTlsSetValue(void* idx, void* value)
1521 tls_t* index = (tls_t*) idx;
1522 int result;
1523 if(index==0)
1524 result=0;
1525 else
1527 index->value=value;
1528 result=1;
1530 dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
1531 return result;
1533 static void* WINAPI expTlsGetValue(void* idx)
1535 tls_t* index = (tls_t*) idx;
1536 void* result;
1537 if(index==0)
1538 result=0;
1539 else
1540 result=index->value;
1541 dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
1542 return result;
1544 static int WINAPI expTlsFree(void* idx)
1546 tls_t* index = (tls_t*) idx;
1547 int result;
1548 if(index==0)
1549 result=0;
1550 else
1552 if(index->next)
1553 index->next->prev=index->prev;
1554 if(index->prev)
1555 index->prev->next=index->next;
1556 if (g_tls == index)
1557 g_tls = index->prev;
1558 my_release((void*)index);
1559 result=1;
1561 dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
1562 return result;
1564 #endif
1566 static void* WINAPI expLocalAlloc(int flags, int size)
1568 void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
1569 if (z == 0)
1570 printf("LocalAlloc() failed\n");
1571 dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1572 return z;
1575 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
1577 void *newpointer;
1578 int oldsize;
1580 newpointer=NULL;
1581 if (flags & LMEM_MODIFY) {
1582 dbgprintf("LocalReAlloc MODIFY\n");
1583 return (void *)handle;
1585 oldsize = my_size((void *)handle);
1586 newpointer = my_realloc((void *)handle,size);
1587 dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
1589 return newpointer;
1592 static void* WINAPI expLocalLock(void* z)
1594 dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
1595 return z;
1598 static void* WINAPI expGlobalAlloc(int flags, int size)
1600 void* z;
1601 dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
1603 z=my_mreq(size, (flags & GMEM_ZEROINIT));
1604 //z=calloc(size, 1);
1605 //z=malloc(size);
1606 if(z==0)
1607 printf("GlobalAlloc() failed\n");
1608 dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1609 return z;
1611 static void* WINAPI expGlobalLock(void* z)
1613 dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
1614 return z;
1616 // pvmjpg20 - but doesn't work anyway
1617 static int WINAPI expGlobalSize(void* amem)
1619 int size = 100000;
1620 #ifdef GARBAGE
1621 alloc_header* header = last_alloc;
1622 alloc_header* mem = (alloc_header*) amem - 1;
1623 if (amem == 0)
1624 return 0;
1625 pthread_mutex_lock(&memmut);
1626 while (header)
1628 if (header->deadbeef != 0xdeadbeef)
1630 dbgprintf("FATAL found corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
1631 break;
1634 if (header == mem)
1636 size = header->size;
1637 break;
1640 header = header->prev;
1642 pthread_mutex_unlock(&memmut);
1643 #endif
1645 dbgprintf("GlobalSize(0x%x)\n", amem);
1646 return size;
1649 static int WINAPI expLoadIconA( long hinstance, char *name )
1651 dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
1652 return 1;
1655 static int WINAPI expLoadStringA(long instance, long id, void* buf, long size)
1657 int result=LoadStringA(instance, id, buf, size);
1658 // if(buf)
1659 dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
1660 instance, id, buf, size, result, buf);
1661 // else
1662 // dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
1663 // instance, id, buf, size, result);
1664 return result;
1667 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
1669 #warning FIXME
1670 int i;
1671 int result;
1672 if(s2==0)
1673 result=1;
1674 else
1676 if(siz1>siz2/2)siz1=siz2/2;
1677 for(i=1; i<=siz1; i++)
1679 *s2=*s1;
1680 if(!*s1)break;
1681 s2++;
1682 s1++;
1684 result=i;
1686 if(s1)
1687 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
1688 "size %d, dest buffer 0x%x, dest size %d) => %d\n",
1689 v1, v2, s1, s1, siz1, s2, siz2, result);
1690 else
1691 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
1692 "size %d, dest buffer 0x%x, dest size %d) =>\n",
1693 v1, v2, siz1, s2, siz2, result);
1694 return result;
1696 static void wch_print(const short* str)
1698 dbgprintf(" src: ");
1699 while(*str)dbgprintf("%c", *str++);
1700 dbgprintf("\n");
1702 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
1703 char* s2, int siz2, char* c3, int* siz3)
1705 int result;
1706 dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
1707 "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
1708 result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
1709 dbgprintf("=> %d\n", result);
1710 //if(s1)wch_print(s1);
1711 if(s2)dbgprintf(" dest: %s\n", s2);
1712 return result;
1714 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
1716 dbgprintf("GetVersionExA(0x%x) => 1\n");
1717 c->dwOSVersionInfoSize=sizeof(*c);
1718 c->dwMajorVersion=4;
1719 c->dwMinorVersion=0;
1720 c->dwBuildNumber=0x4000457;
1721 #if 1
1722 // leave it here for testing win9x-only codecs
1723 c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
1724 strcpy(c->szCSDVersion, " B");
1725 #else
1726 c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
1727 strcpy(c->szCSDVersion, "Service Pack 3");
1728 #endif
1729 dbgprintf(" Major version: 4\n Minor version: 0\n Build number: 0x4000457\n"
1730 " Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 3'\n");
1731 return 1;
1733 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
1734 long max_count, char* name)
1736 pthread_mutex_t *pm;
1737 pthread_cond_t *pc;
1739 mutex_list* pp;
1740 printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
1741 pp=mlist;
1742 while(pp)
1744 printf("%p => ", pp);
1745 pp=pp->prev;
1747 printf("0\n");
1749 if(mlist!=NULL)
1751 mutex_list* pp=mlist;
1752 if(name!=NULL)
1755 if((strcmp(pp->name, name)==0) && (pp->type==1))
1757 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1758 v1, init_count, max_count, name, name, mlist);
1759 return (HANDLE)mlist;
1761 }while((pp=pp->prev) != NULL);
1763 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1764 pthread_mutex_init(pm, NULL);
1765 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1766 pthread_cond_init(pc, NULL);
1767 if(mlist==NULL)
1769 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1770 mlist->next=mlist->prev=NULL;
1772 else
1774 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1775 mlist->next->prev=mlist;
1776 mlist->next->next=NULL;
1777 mlist=mlist->next;
1778 // printf("new semaphore %p\n", mlist);
1780 mlist->type=1; /* Type Semaphore */
1781 mlist->pm=pm;
1782 mlist->pc=pc;
1783 mlist->state=0;
1784 mlist->reset=0;
1785 mlist->semaphore=init_count;
1786 if(name!=NULL)
1787 strncpy(mlist->name, name, 64);
1788 else
1789 mlist->name[0]=0;
1790 if(pm==NULL)
1791 dbgprintf("ERROR::: CreateSemaphoreA failure\n");
1792 if(name)
1793 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1794 v1, init_count, max_count, name, name, mlist);
1795 else
1796 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
1797 v1, init_count, max_count, mlist);
1798 return (HANDLE)mlist;
1801 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
1803 // The state of a semaphore object is signaled when its count
1804 // is greater than zero and nonsignaled when its count is equal to zero
1805 // Each time a waiting thread is released because of the semaphore's signaled
1806 // state, the count of the semaphore is decreased by one.
1807 mutex_list *ml = (mutex_list *)hsem;
1809 pthread_mutex_lock(ml->pm);
1810 if (prev_count != 0) *prev_count = ml->semaphore;
1811 if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
1812 ml->semaphore += increment;
1813 pthread_mutex_unlock(ml->pm);
1814 dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
1815 hsem, increment, prev_count);
1816 return 1;
1820 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
1822 long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
1823 dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
1824 key, subkey, reserved, access, newkey, result);
1825 if(newkey)dbgprintf(" New key: 0x%x\n", *newkey);
1826 return result;
1828 static long WINAPI expRegCloseKey(long key)
1830 long result=RegCloseKey(key);
1831 dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
1832 return result;
1834 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
1836 long result=RegQueryValueExA(key, value, reserved, type, data, count);
1837 dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
1838 " => 0x%x\n", key, value, reserved, data, count, result);
1839 if(data && count)dbgprintf(" read %d bytes: '%s'\n", *count, data);
1840 return result;
1843 //from wine source dlls/advapi32/registry.c
1844 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
1846 dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
1847 return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
1848 KEY_ALL_ACCESS , NULL, retkey, NULL );
1851 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
1852 void* classs, long options, long security,
1853 void* sec_attr, int* newkey, int* status)
1855 long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
1856 dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
1857 " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
1858 key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
1859 if(!result && newkey) dbgprintf(" New key: 0x%x\n", *newkey);
1860 if(!result && status) dbgprintf(" New key status: 0x%x\n", *status);
1861 return result;
1863 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
1865 long result=RegSetValueExA(key, name, v1, v2, data, size);
1866 dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
1867 key, name, v1, v2, data, *(int*)data, data, size, result);
1868 return result;
1871 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
1873 long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
1874 dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
1875 hKey, lpSubKey, phkResult, result);
1876 if(!result && phkResult) dbgprintf(" New key: 0x%x\n", *phkResult);
1877 return result;
1880 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1881 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
1883 return RegEnumValueA(hkey, index, value, val_count,
1884 reserved, type, data, count);
1887 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
1888 LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
1889 LPFILETIME lpftLastWriteTime)
1891 return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
1892 lpcbClass, lpftLastWriteTime);
1895 static long WINAPI expQueryPerformanceCounter(long long* z)
1897 longcount(z);
1898 dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
1899 return 1;
1903 * dummy function RegQueryInfoKeyA(), required by vss codecs
1905 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
1906 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
1907 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
1908 LPDWORD security, FILETIME *modif )
1910 return ERROR_SUCCESS;
1914 * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
1916 static double linux_cpuinfo_freq(void)
1918 double freq=-1;
1919 FILE *f;
1920 char line[200];
1921 char *s,*value;
1923 f = fopen ("/proc/cpuinfo", "r");
1924 if (f != NULL) {
1925 while (fgets(line,sizeof(line),f)!=NULL) {
1926 /* NOTE: the ':' is the only character we can rely on */
1927 if (!(value = strchr(line,':')))
1928 continue;
1929 /* terminate the valuename */
1930 *value++ = '\0';
1931 /* skip any leading spaces */
1932 while (*value==' ') value++;
1933 if ((s=strchr(value,'\n')))
1934 *s='\0';
1936 if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
1937 && sscanf(value, "%lf", &freq) == 1) {
1938 freq*=1000;
1939 break;
1942 fclose(f);
1944 return freq;
1948 static double solaris_kstat_freq(void)
1950 #if defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
1952 * try to extract the CPU speed from the solaris kernel's kstat data
1954 kstat_ctl_t *kc;
1955 kstat_t *ksp;
1956 kstat_named_t *kdata;
1957 int mhz = 0;
1959 kc = kstat_open();
1960 if (kc != NULL)
1962 ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
1964 /* kstat found and name/value pairs? */
1965 if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
1967 /* read the kstat data from the kernel */
1968 if (kstat_read(kc, ksp, NULL) != -1)
1971 * lookup desired "clock_MHz" entry, check the expected
1972 * data type
1974 kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
1975 if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
1976 mhz = kdata->value.i32;
1979 kstat_close(kc);
1982 if (mhz > 0)
1983 return mhz * 1000.;
1984 #endif /* HAVE_LIBKSTAT */
1985 return -1; // kstat stuff is not available, CPU freq is unknown
1989 * Measure CPU freq using the pentium's time stamp counter register (TSC)
1991 static double tsc_freq(void)
1993 static double ofreq=0.0;
1994 int i;
1995 int x,y;
1996 i=time(NULL);
1997 if (ofreq != 0.0) return ofreq;
1998 while(i==time(NULL));
1999 x=localcount();
2000 i++;
2001 while(i==time(NULL));
2002 y=localcount();
2003 ofreq = (double)(y-x)/1000.;
2004 return ofreq;
2007 static double CPU_Freq(void)
2009 double freq;
2011 if ((freq = linux_cpuinfo_freq()) > 0)
2012 return freq;
2014 if ((freq = solaris_kstat_freq()) > 0)
2015 return freq;
2017 return tsc_freq();
2020 static long WINAPI expQueryPerformanceFrequency(long long* z)
2022 *z=(long long)CPU_Freq();
2023 dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
2024 return 1;
2026 static long WINAPI exptimeGetTime(void)
2028 struct timeval t;
2029 long result;
2030 gettimeofday(&t, 0);
2031 result=1000*t.tv_sec+t.tv_usec/1000;
2032 dbgprintf("timeGetTime() => %d\n", result);
2033 return result;
2035 static void* WINAPI expLocalHandle(void* v)
2037 dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
2038 return v;
2041 static void* WINAPI expGlobalHandle(void* v)
2043 dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
2044 return v;
2046 static int WINAPI expGlobalUnlock(void* v)
2048 dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
2049 return 1;
2051 static void* WINAPI expGlobalFree(void* v)
2053 dbgprintf("GlobalFree(0x%x) => 0\n", v);
2054 my_release(v);
2055 //free(v);
2056 return 0;
2059 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
2061 void* result=my_realloc(v, size);
2062 //void* result=realloc(v, size);
2063 dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
2064 return result;
2067 static int WINAPI expLocalUnlock(void* v)
2069 dbgprintf("LocalUnlock(0x%x) => 1\n", v);
2070 return 1;
2073 static void* WINAPI expLocalFree(void* v)
2075 dbgprintf("LocalFree(0x%x) => 0\n", v);
2076 my_release(v);
2077 return 0;
2079 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
2081 HRSRC result;
2083 result=FindResourceA(module, name, type);
2084 dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
2085 module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
2086 return result;
2089 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
2091 HGLOBAL result=LoadResource(module, res);
2092 dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
2093 return result;
2095 static void* WINAPI expLockResource(long res)
2097 void* result=LockResource(res);
2098 dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
2099 return result;
2101 static int WINAPI expFreeResource(long res)
2103 int result=FreeResource(res);
2104 dbgprintf("FreeResource(0x%x) => %d\n", res, result);
2105 return result;
2107 //bool fun(HANDLE)
2108 //!0 on success
2109 static int WINAPI expCloseHandle(long v1)
2111 dbgprintf("CloseHandle(0x%x) => 1\n", v1);
2112 /* do not close stdin,stdout and stderr */
2113 if (v1 > 2)
2114 if (!close(v1))
2115 return 0;
2116 return 1;
2119 static const char* WINAPI expGetCommandLineA(void)
2121 dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
2122 return "c:\\aviplay.exe";
2124 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
2125 static LPWSTR WINAPI expGetEnvironmentStringsW(void)
2127 dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
2128 return 0;
2130 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
2132 void* result=memset(p,0,len);
2133 dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
2134 return result;
2136 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
2138 void* result=memmove(dst,src,len);
2139 dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
2140 return result;
2143 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
2145 void* result=memset(p,ch,len);
2146 dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
2147 return result;
2149 static int WINAPI expFreeEnvironmentStringsW(short* strings)
2151 dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
2152 return 1;
2154 static int WINAPI expFreeEnvironmentStringsA(char* strings)
2156 dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
2157 return 1;
2160 static const char ch_envs[]=
2161 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
2162 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
2163 static LPCSTR WINAPI expGetEnvironmentStrings(void)
2165 dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
2166 return (LPCSTR)ch_envs;
2167 // dbgprintf("GetEnvironmentStrings() => 0\n");
2168 // return 0;
2171 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
2173 dbgprintf("GetStartupInfoA(0x%x) => 1\n");
2174 memset(s, 0, sizeof(*s));
2175 s->cb=sizeof(*s);
2176 // s->lpReserved="Reserved";
2177 // s->lpDesktop="Desktop";
2178 // s->lpTitle="Title";
2179 // s->dwX=s->dwY=0;
2180 // s->dwXSize=s->dwYSize=200;
2181 s->dwFlags=s->wShowWindow=1;
2182 // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
2183 dbgprintf(" cb=%d\n", s->cb);
2184 dbgprintf(" lpReserved='%s'\n", s->lpReserved);
2185 dbgprintf(" lpDesktop='%s'\n", s->lpDesktop);
2186 dbgprintf(" lpTitle='%s'\n", s->lpTitle);
2187 dbgprintf(" dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
2188 s->dwX, s->dwY, s->dwXSize, s->dwYSize);
2189 dbgprintf(" dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
2190 s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
2191 dbgprintf(" dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
2192 s->dwFlags, s->wShowWindow, s->cbReserved2);
2193 dbgprintf(" lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
2194 s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
2195 return 1;
2198 static int WINAPI expGetStdHandle(int z)
2200 dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
2201 return z+0x1234;
2204 #ifdef QTX
2205 #define FILE_HANDLE_quicktimeqts ((HANDLE)0x444)
2206 #define FILE_HANDLE_quicktimeqtx ((HANDLE)0x445)
2207 #endif
2209 static int WINAPI expGetFileType(int handle)
2211 dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
2212 return 0x3;
2214 #ifdef QTX
2215 static int WINAPI expGetFileAttributesA(char *filename)
2217 dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
2218 if (strstr(filename, "QuickTime.qts"))
2219 return FILE_ATTRIBUTE_SYSTEM;
2220 return FILE_ATTRIBUTE_NORMAL;
2222 #endif
2223 static int WINAPI expSetHandleCount(int count)
2225 dbgprintf("SetHandleCount(0x%x) => 1\n", count);
2226 return 1;
2228 static int WINAPI expGetACP(void)
2230 dbgprintf("GetACP() => 0\n");
2231 return 0;
2233 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
2235 WINE_MODREF *mr;
2236 int result;
2237 //printf("File name of module %X (%s) requested\n", module, s);
2239 if (module == 0 && len >= 12)
2241 /* return caller program name */
2242 strcpy(s, "aviplay.dll");
2243 result=1;
2245 else if(s==0)
2246 result=0;
2247 else
2248 if(len<35)
2249 result=0;
2250 else
2252 result=1;
2253 strcpy(s, "c:\\windows\\system\\");
2254 mr=MODULE32_LookupHMODULE(module);
2255 if(mr==0)//oops
2256 strcat(s, "aviplay.dll");
2257 else
2258 if(strrchr(mr->filename, '/')==NULL)
2259 strcat(s, mr->filename);
2260 else
2261 strcat(s, strrchr(mr->filename, '/')+1);
2263 if(!s)
2264 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
2265 module, s, len, result);
2266 else
2267 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
2268 module, s, len, result, s);
2269 return result;
2272 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
2274 dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
2275 return 1;//unsupported and probably won't ever be supported
2278 static int WINAPI expLoadLibraryA(char* name)
2280 int result = 0;
2281 char* lastbc;
2282 if (!name)
2283 return -1;
2284 // we skip to the last backslash
2285 // this is effectively eliminating weird characters in
2286 // the text output windows
2288 lastbc = strrchr(name, '\\');
2289 if (lastbc)
2291 int i;
2292 lastbc++;
2293 for (i = 0; 1 ;i++)
2295 name[i] = *lastbc++;
2296 if (!name[i])
2297 break;
2300 if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
2301 if(strncmp(name, ".\\", 2)==0) name += 2;
2303 dbgprintf("Entering LoadLibraryA(%s)\n", name);
2305 // PIMJ and VIVO audio are loading kernel32.dll
2306 if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
2307 return MODULE_HANDLE_kernel32;
2308 // return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
2309 /* exported -> do not return failed! */
2311 if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
2312 // return MODULE_HANDLE_kernel32;
2313 return MODULE_HANDLE_user32;
2315 #ifdef QTX
2316 if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
2317 return MODULE_HANDLE_wininet;
2318 if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
2319 return MODULE_HANDLE_ddraw;
2320 if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
2321 return MODULE_HANDLE_advapi32;
2322 #endif
2324 if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
2325 return MODULE_HANDLE_comdlg32;
2326 if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
2327 return MODULE_HANDLE_msvcrt;
2328 if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
2329 return MODULE_HANDLE_ole32;
2330 if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
2331 return MODULE_HANDLE_winmm;
2333 result=LoadLibraryA(name);
2334 dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
2336 return result;
2339 static int WINAPI expFreeLibrary(int module)
2341 #ifdef QTX
2342 int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
2343 #else
2344 int result=FreeLibrary(module);
2345 #endif
2346 dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
2347 return result;
2350 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
2352 void* result;
2353 switch(mod){
2354 case MODULE_HANDLE_kernel32:
2355 result=LookupExternalByName("kernel32.dll", name); break;
2356 case MODULE_HANDLE_user32:
2357 result=LookupExternalByName("user32.dll", name); break;
2358 #ifdef QTX
2359 case MODULE_HANDLE_wininet:
2360 result=LookupExternalByName("wininet.dll", name); break;
2361 case MODULE_HANDLE_ddraw:
2362 result=LookupExternalByName("ddraw.dll", name); break;
2363 case MODULE_HANDLE_advapi32:
2364 result=LookupExternalByName("advapi32.dll", name); break;
2365 #endif
2366 case MODULE_HANDLE_comdlg32:
2367 result=LookupExternalByName("comdlg32.dll", name); break;
2368 case MODULE_HANDLE_msvcrt:
2369 result=LookupExternalByName("msvcrt.dll", name); break;
2370 case MODULE_HANDLE_ole32:
2371 result=LookupExternalByName("ole32.dll", name); break;
2372 case MODULE_HANDLE_winmm:
2373 result=LookupExternalByName("winmm.dll", name); break;
2374 default:
2375 result=GetProcAddress(mod, name);
2377 if((unsigned int)name > 0xffff)
2378 dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
2379 else
2380 dbgprintf("GetProcAddress(0x%x, '%d') => 0x%x\n", mod, (int)name, result);
2381 return result;
2384 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
2385 long flProtect, long dwMaxHigh,
2386 long dwMaxLow, const char* name)
2388 long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
2389 if(!name)
2390 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2391 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
2392 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
2393 else
2394 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2395 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
2396 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
2397 return result;
2400 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
2402 long result=OpenFileMappingA(hFile, hz, name);
2403 if(!name)
2404 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
2405 hFile, hz, result);
2406 else
2407 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
2408 hFile, hz, name, name, result);
2409 return result;
2412 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
2413 DWORD offLow, DWORD size)
2415 dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
2416 file,mode,offHigh,offLow,size,(char*)file+offLow);
2417 return (char*)file+offLow;
2420 static void* WINAPI expUnmapViewOfFile(void* view)
2422 dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
2423 return 0;
2426 static void* WINAPI expSleep(int time)
2428 #if HAVE_NANOSLEEP
2429 /* solaris doesn't have thread safe usleep */
2430 struct timespec tsp;
2431 tsp.tv_sec = time / 1000000;
2432 tsp.tv_nsec = (time % 1000000) * 1000;
2433 nanosleep(&tsp, NULL);
2434 #else
2435 usleep(time);
2436 #endif
2437 dbgprintf("Sleep(%d) => 0\n", time);
2438 return 0;
2441 // why does IV32 codec want to call this? I don't know ...
2442 static int WINAPI expCreateCompatibleDC(int hdc)
2444 int dc = 0;//0x81;
2445 //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
2446 dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
2447 return dc;
2450 static int WINAPI expGetDeviceCaps(int hdc, int unk)
2452 dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
2453 #ifdef QTX
2454 #define BITSPIXEL 12
2455 #define PLANES 14
2456 if (unk == BITSPIXEL)
2457 return 24;
2458 if (unk == PLANES)
2459 return 1;
2460 #endif
2461 return 1;
2464 static WIN_BOOL WINAPI expDeleteDC(int hdc)
2466 dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
2467 if (hdc == 0x81)
2468 return 1;
2469 return 0;
2472 static WIN_BOOL WINAPI expDeleteObject(int hdc)
2474 dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
2475 /* FIXME - implement code here */
2476 return 1;
2479 /* btvvc32.drv wants this one */
2480 static void* WINAPI expGetWindowDC(int hdc)
2482 dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
2483 return 0;
2486 #ifdef QTX
2487 static int WINAPI expGetWindowRect(HWND win, RECT *r)
2489 dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
2490 /* (win == 0) => desktop */
2491 r->right = PSEUDO_SCREEN_WIDTH;
2492 r->left = 0;
2493 r->bottom = PSEUDO_SCREEN_HEIGHT;
2494 r->top = 0;
2495 return 1;
2498 static int WINAPI expMonitorFromWindow(HWND win, int flags)
2500 dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
2501 return 0;
2504 static int WINAPI expMonitorFromRect(RECT *r, int flags)
2506 dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
2507 return 0;
2510 static int WINAPI expMonitorFromPoint(void *p, int flags)
2512 dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
2513 return 0;
2516 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r,
2517 int WINAPI (*callback_proc)(), void *callback_param)
2519 dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
2520 dc, r, callback_proc, callback_param);
2521 return callback_proc(0, dc, r, callback_param);
2524 #if 0
2525 typedef struct tagMONITORINFO {
2526 DWORD cbSize;
2527 RECT rcMonitor;
2528 RECT rcWork;
2529 DWORD dwFlags;
2530 } MONITORINFO, *LPMONITORINFO;
2531 #endif
2533 #define CCHDEVICENAME 8
2534 typedef struct tagMONITORINFOEX {
2535 DWORD cbSize;
2536 RECT rcMonitor;
2537 RECT rcWork;
2538 DWORD dwFlags;
2539 TCHAR szDevice[CCHDEVICENAME];
2540 } MONITORINFOEX, *LPMONITORINFOEX;
2542 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
2544 dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
2546 lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
2547 lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
2548 lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
2549 lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
2551 lpmi->dwFlags = 1; /* primary monitor */
2553 if (lpmi->cbSize == sizeof(MONITORINFOEX))
2555 LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
2556 dbgprintf("MONITORINFOEX!\n");
2557 strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
2560 return 1;
2563 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
2564 void *dispdev, int flags)
2566 dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
2567 device, device, devnum, dispdev, flags);
2568 return 1;
2571 static int WINAPI expIsWindowVisible(HWND win)
2573 dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
2574 return 1;
2577 static HWND WINAPI expGetActiveWindow(void)
2579 dbgprintf("GetActiveWindow() => 0\n");
2580 return (HWND)0;
2583 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
2585 strncat(classname, "QuickTime", maxcount);
2586 dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
2587 win, classname, maxcount, strlen(classname));
2588 return strlen(classname);
2591 #define LPWNDCLASS void *
2592 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
2594 dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
2595 classname, classname, wndclass);
2596 return 1;
2599 static int WINAPI expGetWindowLongA(HWND win, int index)
2601 dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
2602 return 1;
2605 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
2607 dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
2608 return objsize;
2611 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
2613 dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
2614 return 0;
2617 static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
2619 int i, i2;
2620 dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
2621 i = callback_func(0, callback_param);
2622 i2 = callback_func(1, callback_param);
2623 return i && i2;
2626 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
2628 int tid = pthread_self();
2629 dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
2630 win, pid_data, tid);
2631 if (pid_data)
2632 *(int*)pid_data = tid;
2633 return tid;
2636 //HWND WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
2637 // INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
2639 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
2640 const char *winname, int style, int x, int y, int w, int h,
2641 HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
2643 printf("CreateWindowEx() called\n");
2644 dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
2645 exstyle, classname, classname, winname, winname, style, x, y, w, h,
2646 parent, menu, inst, param);
2647 printf("CreateWindowEx() called okey\n");
2648 return 1;
2651 static int WINAPI expwaveOutGetNumDevs(void)
2653 dbgprintf("waveOutGetNumDevs() => 0\n");
2654 return 0;
2656 #endif
2659 * Returns the number of milliseconds, modulo 2^32, since the start
2660 * of the wineserver.
2662 static int WINAPI expGetTickCount(void)
2664 static int tcstart = 0;
2665 struct timeval t;
2666 int tc;
2667 gettimeofday( &t, NULL );
2668 tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
2669 if (tcstart == 0)
2671 tcstart = 0;
2672 tc = 0;
2674 dbgprintf("GetTickCount() => %d\n", tc);
2675 return tc;
2678 static int WINAPI expCreateFontA(void)
2680 dbgprintf("CreateFontA() => 0x0\n");
2681 return 1;
2684 /* tried to get pvmjpg work in a different way - no success */
2685 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
2686 LPRECT lpRect, unsigned int uFormat)
2688 dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
2689 return 8;
2692 static int WINAPI expGetPrivateProfileIntA(const char* appname,
2693 const char* keyname,
2694 int default_value,
2695 const char* filename)
2697 int size=255;
2698 char buffer[256];
2699 char* fullname;
2700 int result;
2702 buffer[255]=0;
2703 if(!(appname && keyname && filename) )
2705 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
2706 return default_value;
2708 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2709 strcpy(fullname, "Software\\IniFileMapping\\");
2710 strcat(fullname, appname);
2711 strcat(fullname, "\\");
2712 strcat(fullname, keyname);
2713 strcat(fullname, "\\");
2714 strcat(fullname, filename);
2715 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
2716 if((size>=0)&&(size<256))
2717 buffer[size]=0;
2718 // printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
2719 free(fullname);
2720 if(result)
2721 result=default_value;
2722 else
2723 result=atoi(buffer);
2724 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
2725 return result;
2727 static int WINAPI expGetProfileIntA(const char* appname,
2728 const char* keyname,
2729 int default_value)
2731 dbgprintf("GetProfileIntA -> ");
2732 return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
2735 static int WINAPI expGetPrivateProfileStringA(const char* appname,
2736 const char* keyname,
2737 const char* def_val,
2738 char* dest, unsigned int len,
2739 const char* filename)
2741 int result;
2742 int size;
2743 char* fullname;
2744 dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
2745 if(!(appname && keyname && filename) ) return 0;
2746 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2747 strcpy(fullname, "Software\\IniFileMapping\\");
2748 strcat(fullname, appname);
2749 strcat(fullname, "\\");
2750 strcat(fullname, keyname);
2751 strcat(fullname, "\\");
2752 strcat(fullname, filename);
2753 size=len;
2754 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
2755 free(fullname);
2756 if(result)
2758 strncpy(dest, def_val, size);
2759 if (strlen(def_val)< size) size = strlen(def_val);
2761 dbgprintf(" => %d ( '%s' )\n", size, dest);
2762 return size;
2764 static int WINAPI expWritePrivateProfileStringA(const char* appname,
2765 const char* keyname,
2766 const char* string,
2767 const char* filename)
2769 char* fullname;
2770 dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
2771 if(!(appname && keyname && filename) )
2773 dbgprintf(" => -1\n");
2774 return -1;
2776 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2777 strcpy(fullname, "Software\\IniFileMapping\\");
2778 strcat(fullname, appname);
2779 strcat(fullname, "\\");
2780 strcat(fullname, keyname);
2781 strcat(fullname, "\\");
2782 strcat(fullname, filename);
2783 RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
2784 // printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
2785 // printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
2786 free(fullname);
2787 dbgprintf(" => 0\n");
2788 return 0;
2791 unsigned int GetPrivateProfileIntA_(const char* appname, const char* keyname, INT default_value, const char* filename)
2793 return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
2795 int GetPrivateProfileStringA_(const char* appname, const char* keyname,
2796 const char* def_val, char* dest, unsigned int len, const char* filename)
2798 return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
2800 int WritePrivateProfileStringA_(const char* appname, const char* keyname,
2801 const char* string, const char* filename)
2803 return expWritePrivateProfileStringA(appname, keyname, string, filename);
2808 static int WINAPI expDefDriverProc(int private, int id, int msg, int arg1, int arg2)
2810 dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", private, id, msg, arg1, arg2);
2811 return 0;
2814 static int WINAPI expSizeofResource(int v1, int v2)
2816 int result=SizeofResource(v1, v2);
2817 dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
2818 return result;
2821 static int WINAPI expGetLastError(void)
2823 int result=GetLastError();
2824 dbgprintf("GetLastError() => 0x%x\n", result);
2825 return result;
2828 static void WINAPI expSetLastError(int error)
2830 dbgprintf("SetLastError(0x%x)\n", error);
2831 SetLastError(error);
2834 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
2836 int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
2837 guid->f1, guid->f2, guid->f3,
2838 (unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
2839 (unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
2840 (unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
2841 (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
2842 dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
2843 return result;
2847 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
2849 dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
2850 return 0;
2853 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
2855 int result;
2856 if(string==0)result=1; else result=0;
2857 dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
2858 if(string)wch_print(string);
2859 return result;
2861 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
2863 return expIsBadStringPtrW((const short*)string, nchars);
2865 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
2867 long ret;
2868 __asm__ volatile
2870 "lock; xaddl %0,(%1)"
2871 : "=r" (ret)
2872 : "r" (dest), "0" (incr)
2873 : "memory"
2875 return ret;
2878 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
2880 unsigned long retval = *dest;
2881 if(*dest == comperand)
2882 *dest = exchange;
2883 return retval;
2886 static long WINAPI expInterlockedIncrement( long* dest )
2888 long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
2889 dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
2890 return result;
2892 static long WINAPI expInterlockedDecrement( long* dest )
2894 long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
2895 dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
2896 return result;
2899 static void WINAPI expOutputDebugStringA( const char* string )
2901 dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
2902 fprintf(stderr, "DEBUG: %s\n", string);
2905 static int WINAPI expGetDC(int hwnd)
2907 dbgprintf("GetDC(0x%x) => 1\n", hwnd);
2908 return 1;
2911 static int WINAPI expReleaseDC(int hwnd, int hdc)
2913 dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
2914 return 1;
2917 static int WINAPI expGetDesktopWindow(void)
2919 dbgprintf("GetDesktopWindow() => 0\n");
2920 return 0;
2923 static int cursor[100];
2925 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
2927 dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
2928 return (int)&cursor[0];
2930 static int WINAPI expSetCursor(void *cursor)
2932 dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
2933 return (int)cursor;
2935 static int WINAPI expGetCursorPos(void *cursor)
2937 dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
2938 return 1;
2940 #ifdef QTX
2941 static int show_cursor = 0;
2942 static int WINAPI expShowCursor(int show)
2944 dbgprintf("ShowCursor(%d) => %d\n", show, show);
2945 if (show)
2946 show_cursor++;
2947 else
2948 show_cursor--;
2949 return show_cursor;
2951 #endif
2952 static int WINAPI expRegisterWindowMessageA(char *message)
2954 dbgprintf("RegisterWindowMessageA(%s)\n", message);
2955 return 1;
2957 static int WINAPI expGetProcessVersion(int pid)
2959 dbgprintf("GetProcessVersion(%d)\n", pid);
2960 return 1;
2962 static int WINAPI expGetCurrentThread(void)
2964 #warning FIXME!
2965 dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
2966 return 0xcfcf9898;
2968 static int WINAPI expGetOEMCP(void)
2970 dbgprintf("GetOEMCP()\n");
2971 return 1;
2973 static int WINAPI expGetCPInfo(int cp,void *info)
2975 dbgprintf("GetCPInfo()\n");
2976 return 0;
2978 #ifdef QTX
2979 #define SM_CXSCREEN 0
2980 #define SM_CYSCREEN 1
2981 #define SM_XVIRTUALSCREEN 76
2982 #define SM_YVIRTUALSCREEN 77
2983 #define SM_CXVIRTUALSCREEN 78
2984 #define SM_CYVIRTUALSCREEN 79
2985 #define SM_CMONITORS 80
2986 #endif
2987 static int WINAPI expGetSystemMetrics(int index)
2989 dbgprintf("GetSystemMetrics(%d)\n", index);
2990 #ifdef QTX
2991 switch(index)
2993 case SM_XVIRTUALSCREEN:
2994 case SM_YVIRTUALSCREEN:
2995 return 0;
2996 case SM_CXSCREEN:
2997 case SM_CXVIRTUALSCREEN:
2998 return PSEUDO_SCREEN_WIDTH;
2999 case SM_CYSCREEN:
3000 case SM_CYVIRTUALSCREEN:
3001 return PSEUDO_SCREEN_HEIGHT;
3002 case SM_CMONITORS:
3003 return 1;
3005 #endif
3006 return 1;
3008 static int WINAPI expGetSysColor(int index)
3010 dbgprintf("GetSysColor(%d) => 1\n", index);
3011 return 1;
3013 static int WINAPI expGetSysColorBrush(int index)
3015 dbgprintf("GetSysColorBrush(%d)\n", index);
3016 return 1;
3021 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
3023 dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
3024 hdc, iStartIndex, nEntries, lppe);
3025 return 0;
3029 typedef struct TIME_ZONE_INFORMATION {
3030 long Bias;
3031 char StandardName[32];
3032 SYSTEMTIME StandardDate;
3033 long StandardBias;
3034 char DaylightName[32];
3035 SYSTEMTIME DaylightDate;
3036 long DaylightBias;
3037 } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
3040 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
3042 const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
3043 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
3044 const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
3045 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
3046 dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
3047 memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
3048 lpTimeZoneInformation->Bias=360;//GMT-6
3049 memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
3050 lpTimeZoneInformation->StandardDate.wMonth=10;
3051 lpTimeZoneInformation->StandardDate.wDay=5;
3052 lpTimeZoneInformation->StandardDate.wHour=2;
3053 lpTimeZoneInformation->StandardBias=0;
3054 memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
3055 lpTimeZoneInformation->DaylightDate.wMonth=4;
3056 lpTimeZoneInformation->DaylightDate.wDay=1;
3057 lpTimeZoneInformation->DaylightDate.wHour=2;
3058 lpTimeZoneInformation->DaylightBias=-60;
3059 return TIME_ZONE_ID_STANDARD;
3062 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
3064 time_t local_time;
3065 struct tm *local_tm;
3066 struct timeval tv;
3068 dbgprintf("GetLocalTime(0x%x)\n");
3069 gettimeofday(&tv, NULL);
3070 local_time=tv.tv_sec;
3071 local_tm=localtime(&local_time);
3073 systime->wYear = local_tm->tm_year + 1900;
3074 systime->wMonth = local_tm->tm_mon + 1;
3075 systime->wDayOfWeek = local_tm->tm_wday;
3076 systime->wDay = local_tm->tm_mday;
3077 systime->wHour = local_tm->tm_hour;
3078 systime->wMinute = local_tm->tm_min;
3079 systime->wSecond = local_tm->tm_sec;
3080 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3081 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3082 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3083 " Milliseconds: %d\n",
3084 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3085 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3088 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
3090 time_t local_time;
3091 struct tm *local_tm;
3092 struct timeval tv;
3094 dbgprintf("GetSystemTime(0x%x)\n", systime);
3095 gettimeofday(&tv, NULL);
3096 local_time=tv.tv_sec;
3097 local_tm=gmtime(&local_time);
3099 systime->wYear = local_tm->tm_year + 1900;
3100 systime->wMonth = local_tm->tm_mon + 1;
3101 systime->wDayOfWeek = local_tm->tm_wday;
3102 systime->wDay = local_tm->tm_mday;
3103 systime->wHour = local_tm->tm_hour;
3104 systime->wMinute = local_tm->tm_min;
3105 systime->wSecond = local_tm->tm_sec;
3106 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3107 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3108 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3109 " Milliseconds: %d\n",
3110 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3111 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3112 return 0;
3115 #define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ULL)
3116 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
3118 struct timeval tv;
3119 unsigned long long secs;
3121 dbgprintf("GetSystemTime(0x%x)\n", systime);
3122 gettimeofday(&tv, NULL);
3123 secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
3124 secs += tv.tv_usec * 10;
3125 systime->dwLowDateTime = secs & 0xffffffff;
3126 systime->dwHighDateTime = (secs >> 32);
3129 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
3131 //char *p;
3132 // printf("%s %x %x\n", name, field, size);
3133 if(field)field[0]=0;
3135 p = getenv(name);
3136 if (p) strncpy(field,p,size);
3138 if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
3139 strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
3140 dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
3141 return strlen(field);
3144 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
3146 dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
3147 return 0;
3150 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
3152 return my_mreq(cb, 0);
3154 static void WINAPI expCoTaskMemFree(void* cb)
3156 my_release(cb);
3162 void* CoTaskMemAlloc(unsigned long cb)
3164 return expCoTaskMemAlloc(cb);
3166 void CoTaskMemFree(void* cb)
3168 expCoTaskMemFree(cb);
3171 struct COM_OBJECT_INFO
3173 GUID clsid;
3174 long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
3177 static struct COM_OBJECT_INFO* com_object_table=0;
3178 static int com_object_size=0;
3179 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3181 if(!clsid || !gcs)
3182 return -1;
3183 com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
3184 com_object_table[com_object_size-1].clsid=*clsid;
3185 com_object_table[com_object_size-1].GetClassObject=gcs;
3186 return 0;
3189 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3191 int found = 0;
3192 int i = 0;
3193 if(!clsid || !gcs)
3194 return -1;
3196 if (com_object_table == 0)
3197 printf("Warning: UnregisterComClass() called without any registered class\n");
3198 while (i < com_object_size)
3200 if (found && i > 0)
3202 memcpy(&com_object_table[i - 1].clsid,
3203 &com_object_table[i].clsid, sizeof(GUID));
3204 com_object_table[i - 1].GetClassObject =
3205 com_object_table[i].GetClassObject;
3207 else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
3208 && com_object_table[i].GetClassObject == gcs)
3210 found++;
3212 i++;
3214 if (found)
3216 if (--com_object_size == 0)
3218 free(com_object_table);
3219 com_object_table = 0;
3222 return 0;
3226 const GUID IID_IUnknown =
3228 0x00000000, 0x0000, 0x0000,
3229 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3231 const GUID IID_IClassFactory =
3233 0x00000001, 0x0000, 0x0000,
3234 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3237 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3238 long dwClsContext, const GUID* riid, void** ppv)
3240 int i;
3241 struct COM_OBJECT_INFO* ci=0;
3242 for(i=0; i<com_object_size; i++)
3243 if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
3244 ci=&com_object_table[i];
3245 if(!ci)return REGDB_E_CLASSNOTREG;
3246 // in 'real' world we should mess with IClassFactory here
3247 i=ci->GetClassObject(rclsid, riid, ppv);
3248 return i;
3251 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3252 long dwClsContext, const GUID* riid, void** ppv)
3254 return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
3257 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
3259 int r = 0;
3260 int w,h;
3261 //trapbug();
3262 if (lprc)
3264 w = lprc->right - lprc->left;
3265 h = lprc->bottom - lprc->top;
3266 if (w <= 0 || h <= 0)
3267 r = 1;
3269 else
3270 r = 1;
3272 dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
3273 //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
3274 // return 0; // wmv9?
3275 return r; // TM20
3278 static int _adjust_fdiv=0; //what's this? - used to adjust division
3279 static int _winver = 0x510; // windows version
3284 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
3286 dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
3287 if(len<5)
3289 dbgprintf(" => 0\n");
3290 return 0;
3292 strcpy(path, "/tmp");
3293 dbgprintf(" => 5 ( '/tmp' )\n");
3294 return 5;
3297 FYI:
3298 typedef struct
3300 DWORD dwFileAttributes;
3301 FILETIME ftCreationTime;
3302 FILETIME ftLastAccessTime;
3303 FILETIME ftLastWriteTime;
3304 DWORD nFileSizeHigh;
3305 DWORD nFileSizeLow;
3306 DWORD dwReserved0;
3307 DWORD dwReserved1;
3308 CHAR cFileName[260];
3309 CHAR cAlternateFileName[14];
3310 } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
3313 static DIR* qtx_dir=NULL;
3315 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
3317 #ifdef QTX
3318 dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
3319 if(h==FILE_HANDLE_quicktimeqtx){
3320 struct dirent* d;
3321 if(!qtx_dir) return 0;
3322 while((d=readdir(qtx_dir))){
3323 char* x=strrchr(d->d_name,'.');
3324 if(!x) continue;
3325 if(strcmp(x,".qtx")) continue;
3326 strcpy(lpfd->cFileName,d->d_name);
3327 // sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
3328 strcpy(lpfd->cAlternateFileName,"foobar.qtx");
3329 dbgprintf("### FindNext: %s\n",lpfd->cFileName);
3330 return 1;
3332 closedir(qtx_dir); qtx_dir=NULL;
3333 return 0;
3335 #endif
3336 return 0;
3339 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
3341 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
3342 // printf("\n### FindFirstFileA('%s')...\n",s);
3343 #ifdef QTX
3344 if(strstr(s, "quicktime\\*.QTX")){
3345 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
3346 dbgprintf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",def_path);
3347 qtx_dir=opendir(def_path);
3348 if(!qtx_dir) return (HANDLE)-1;
3349 memset(lpfd,0,sizeof(*lpfd));
3350 if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
3351 return FILE_HANDLE_quicktimeqtx;
3352 printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",def_path);
3353 return (HANDLE)-1;
3355 #if 0
3356 if(strstr(s, "QuickTime.qts")){
3357 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
3358 // if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
3359 // return (HANDLE)-1;
3360 strcpy(lpfd->cFileName, "QuickTime.qts");
3361 strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
3362 return FILE_HANDLE_quicktimeqts;
3364 #endif
3365 #endif
3366 if(strstr(s, "*.vwp")){
3367 // hack for VoxWare codec plugins:
3368 strcpy(lpfd->cFileName, "msms001.vwp");
3369 strcpy(lpfd->cAlternateFileName, "msms001.vwp");
3370 return (HANDLE)0;
3372 // return 'file not found'
3373 return (HANDLE)-1;
3376 static WIN_BOOL WINAPI expFindClose(HANDLE h)
3378 dbgprintf("FindClose(0x%x) => 0\n", h);
3379 #ifdef QTX
3380 // if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
3381 // closedir(qtx_dir);
3382 // qtx_dir=NULL;
3383 // }
3384 #endif
3385 return 0;
3387 static UINT WINAPI expSetErrorMode(UINT i)
3389 dbgprintf("SetErrorMode(%d) => 0\n", i);
3390 return 0;
3392 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
3394 char windir[]="c:\\windows";
3395 int result;
3396 strncpy(s, windir, c);
3397 result=1+((c<strlen(windir))?c:strlen(windir));
3398 dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
3399 return result;
3401 #ifdef QTX
3402 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
3404 char curdir[]="c:\\";
3405 int result;
3406 strncpy(s, curdir, c);
3407 result=1+((c<strlen(curdir))?c:strlen(curdir));
3408 dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
3409 return result;
3412 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
3414 dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
3415 #if 0
3416 if (strrchr(pathname, '\\'))
3417 chdir(strcat(strrchr(pathname, '\\')+1, '/'));
3418 else
3419 chdir(pathname);
3420 #endif
3421 return 1;
3424 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
3426 dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
3427 pathname, pathname, sa);
3428 #if 0
3429 p = strrchr(pathname, '\\')+1;
3430 strcpy(&buf[0], p); /* should be strncpy */
3431 if (!strlen(p))
3433 buf[0] = '.';
3434 buf[1] = 0;
3436 #if 0
3437 if (strrchr(pathname, '\\'))
3438 mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
3439 else
3440 mkdir(pathname, 666);
3441 #endif
3442 mkdir(&buf);
3443 #endif
3444 return 1;
3446 #endif
3447 static WIN_BOOL WINAPI expDeleteFileA(LPCSTR s)
3449 dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
3450 return 0;
3452 static WIN_BOOL WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
3454 dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
3455 return 0;
3458 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
3460 char mask[16]="/tmp/AP_XXXXXX";
3461 int result;
3462 dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
3463 if(i && i<10)
3465 dbgprintf(" => -1\n");
3466 return -1;
3468 result=mkstemp(mask);
3469 sprintf(ps, "AP%d", result);
3470 dbgprintf(" => %d\n", strlen(ps));
3471 return strlen(ps);
3474 // This func might need proper implementation if we want AngelPotion codec.
3475 // They try to open APmpeg4v1.apl with it.
3476 // DLL will close opened file with CloseHandle().
3478 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
3479 LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
3481 dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
3482 i2, p1, i3, i4, i5);
3483 if((!cs1) || (strlen(cs1)<2))return -1;
3485 #ifdef QTX
3486 if(strstr(cs1, "QuickTime.qts"))
3488 int result;
3489 char* tmp=malloc(strlen(def_path)+50);
3490 strcpy(tmp, def_path);
3491 strcat(tmp, "/");
3492 strcat(tmp, "QuickTime.qts");
3493 result=open(tmp, O_RDONLY);
3494 free(tmp);
3495 return result;
3497 if(strstr(cs1, ".qtx"))
3499 int result;
3500 char* tmp=malloc(strlen(def_path)+250);
3501 char* x=strrchr(cs1,'\\');
3502 sprintf(tmp,"%s/%s",def_path,x?(x+1):cs1);
3503 // printf("### Open: %s -> %s\n",cs1,tmp);
3504 result=open(tmp, O_RDONLY);
3505 free(tmp);
3506 return result;
3508 #endif
3510 if(strncmp(cs1, "AP", 2) == 0)
3512 int result;
3513 char* tmp=malloc(strlen(def_path)+50);
3514 strcpy(tmp, def_path);
3515 strcat(tmp, "/");
3516 strcat(tmp, "APmpg4v1.apl");
3517 result=open(tmp, O_RDONLY);
3518 free(tmp);
3519 return result;
3521 if (strstr(cs1, "vp3") || strstr(cs1, ".fpf"))
3523 int r;
3524 int flg = 0;
3525 char* tmp=malloc(20 + strlen(cs1));
3526 strcpy(tmp, "/tmp/");
3527 strcat(tmp, cs1);
3528 r = 4;
3529 while (tmp[r])
3531 if (tmp[r] == ':' || tmp[r] == '\\')
3532 tmp[r] = '_';
3533 r++;
3535 if (GENERIC_READ & i1)
3536 flg |= O_RDONLY;
3537 else if (GENERIC_WRITE & i1)
3539 flg |= O_WRONLY | O_CREAT;
3540 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", tmp, r, flg);
3542 r=open(tmp, flg, S_IRWXU);
3543 free(tmp);
3544 return r;
3547 // Needed by wnvplay1.dll
3548 if (strstr(cs1, "WINNOV.bmp"))
3550 int r;
3551 r=open("/dev/null", O_RDONLY);
3552 return r;
3555 #if 0
3556 /* we need this for some virtualdub filters */
3558 int r;
3559 int flg = 0;
3560 if (GENERIC_READ & i1)
3561 flg |= O_RDONLY;
3562 else if (GENERIC_WRITE & i1)
3564 flg |= O_WRONLY;
3565 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", cs1, r, flg);
3567 r=open(cs1, flg);
3568 return r;
3570 #endif
3572 return atoi(cs1+2);
3574 static UINT WINAPI expGetSystemDirectoryA(
3575 char* lpBuffer, // address of buffer for system directory
3576 UINT uSize // size of directory buffer
3578 dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
3579 if(!lpBuffer) strcpy(lpBuffer,".");
3580 return 1;
3583 static char sysdir[]=".";
3584 static LPCSTR WINAPI expGetSystemDirectoryA(void)
3586 dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
3587 return sysdir;
3590 static DWORD WINAPI expGetFullPathNameA
3592 LPCTSTR lpFileName,
3593 DWORD nBufferLength,
3594 LPTSTR lpBuffer,
3595 LPTSTR lpFilePart
3597 if(!lpFileName) return 0;
3598 dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
3599 lpBuffer, lpFilePart);
3600 #if 0
3601 #ifdef QTX
3602 strcpy(lpFilePart, "Quick123.qts");
3603 #else
3604 strcpy(lpFilePart, lpFileName);
3605 #endif
3606 #else
3607 if (strrchr(lpFileName, '\\'))
3608 lpFilePart = strrchr(lpFileName, '\\');
3609 else
3610 lpFilePart = (LPTSTR)lpFileName;
3611 #endif
3612 strcpy(lpBuffer, lpFileName);
3613 // strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
3614 return strlen(lpBuffer);
3617 static DWORD WINAPI expGetShortPathNameA
3619 LPCSTR longpath,
3620 LPSTR shortpath,
3621 DWORD shortlen
3623 if(!longpath) return 0;
3624 dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
3625 strcpy(shortpath,longpath);
3626 return strlen(shortpath);
3629 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
3631 int result;
3632 dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
3633 result=read(h, pv, size);
3634 if(rd)*rd=result;
3635 if(!result)return 0;
3636 return 1;
3639 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
3641 int result;
3642 dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
3643 if(h==1234)h=1;
3644 result=write(h, pv, size);
3645 if(wr)*wr=result;
3646 if(!result)return 0;
3647 return 1;
3649 static DWORD WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
3651 int wh;
3652 dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, ext ? *ext : NULL, whence);
3653 //why would DLL want temporary file with >2Gb size?
3654 switch(whence)
3656 case FILE_BEGIN:
3657 wh=SEEK_SET;break;
3658 case FILE_END:
3659 wh=SEEK_END;break;
3660 case FILE_CURRENT:
3661 wh=SEEK_CUR;break;
3662 default:
3663 return -1;
3665 #ifdef QTX
3666 if (val == 0 && ext != 0)
3667 val = val&(*ext);
3668 #endif
3669 return lseek(h, val, wh);
3672 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
3673 LPARAM lParam2)
3675 dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3676 return -1;
3678 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
3679 LPARAM lParam2)
3681 dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3682 return -1;
3686 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
3687 LPDWORD lpProcessAffinityMask,
3688 LPDWORD lpSystemAffinityMask)
3690 dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
3691 hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
3692 if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
3693 if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
3694 return 1;
3697 // Fake implementation: does nothing, but does it right :)
3698 static WIN_BOOL WINAPI expSetProcessAffinityMask(HANDLE hProcess,
3699 LPDWORD dwProcessAffinityMask)
3701 dbgprintf("SetProcessAffinityMask(0x%x, 0x%x) => 1\n",
3702 hProcess, dwProcessAffinityMask);
3704 return 1;
3707 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
3709 static const long long max_int=0x7FFFFFFFLL;
3710 static const long long min_int=-0x80000000LL;
3711 long long tmp=(long long)nNumber*(long long)nNumerator;
3712 dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
3713 if(!nDenominator)return 1;
3714 tmp/=nDenominator;
3715 if(tmp<min_int) return 1;
3716 if(tmp>max_int) return 1;
3717 return (int)tmp;
3720 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
3722 LONG result=strcasecmp(str1, str2);
3723 dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
3724 return result;
3727 static LONG WINAPI explstrlenA(const char* str1)
3729 LONG result=strlen(str1);
3730 dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
3731 return result;
3734 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
3736 int result= (int) strcpy(str1, str2);
3737 dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
3738 return result;
3740 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
3742 int result;
3743 if (strlen(str2)>len)
3744 result = (int) strncpy(str1, str2,len);
3745 else
3746 result = (int) strcpy(str1,str2);
3747 dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
3748 return result;
3750 static LONG WINAPI explstrcatA(char* str1, const char* str2)
3752 int result= (int) strcat(str1, str2);
3753 dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
3754 return result;
3758 static LONG WINAPI expInterlockedExchange(long *dest, long l)
3760 long retval = *dest;
3761 *dest = l;
3762 return retval;
3765 static void WINAPI expInitCommonControls(void)
3767 dbgprintf("InitCommonControls called!\n");
3768 return;
3771 #ifdef QTX
3772 /* needed by QuickTime.qts */
3773 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
3774 HWND parent, INT id, HINSTANCE inst,
3775 HWND buddy, INT maxVal, INT minVal, INT curVal)
3777 dbgprintf("CreateUpDownControl(...)\n");
3778 return 0;
3780 #endif
3782 /* alex: implement this call! needed for 3ivx */
3783 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
3785 dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
3786 pUnkOuter, ppUnkInner);
3787 // return 0;
3788 return ERROR_CALL_NOT_IMPLEMENTED;
3792 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
3793 HANDLE hSourceHandle, // handle to duplicate
3794 HANDLE hTargetProcessHandle, // handle to target process
3795 HANDLE* lpTargetHandle, // duplicate handle
3796 DWORD dwDesiredAccess, // requested access
3797 int bInheritHandle, // handle inheritance option
3798 DWORD dwOptions // optional actions
3801 dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
3802 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
3803 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
3804 *lpTargetHandle = hSourceHandle;
3805 return 1;
3808 static HRESULT WINAPI expCoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3810 dbgprintf("CoInitializeEx(%p, %d) called\n", lpReserved, dwCoInit);
3811 return S_OK;
3814 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
3815 static HRESULT WINAPI expCoInitialize(
3816 LPVOID lpReserved /* [in] pointer to win32 malloc interface
3817 (obsolete, should be NULL) */
3821 * Just delegate to the newer method.
3823 return expCoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
3826 static void WINAPI expCoUninitialize(void)
3828 dbgprintf("CoUninitialize() called\n");
3831 /* allow static linking */
3832 HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3834 return expCoInitializeEx(lpReserved, dwCoInit);
3836 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
3838 return expCoInitialize(lpReserved);
3840 void WINAPI CoUninitialize(void)
3842 expCoUninitialize();
3845 static DWORD WINAPI expSetThreadAffinityMask
3847 HANDLE hThread,
3848 DWORD dwThreadAffinityMask
3850 return 0;
3854 * no WINAPI functions - CDECL
3856 static void* expmalloc(int size)
3858 //printf("malloc");
3859 // return malloc(size);
3860 void* result=my_mreq(size,0);
3861 dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
3862 if(result==0)
3863 printf("WARNING: malloc() failed\n");
3864 return result;
3866 static void expfree(void* mem)
3868 // return free(mem);
3869 dbgprintf("free(%p)\n", mem);
3870 my_release(mem);
3872 /* needed by atrac3.acm */
3873 static void *expcalloc(int num, int size)
3875 void* result=my_mreq(num*size,1);
3876 dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
3877 if(result==0)
3878 printf("WARNING: calloc() failed\n");
3879 return result;
3881 static void* expnew(int size)
3883 // printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
3884 // printf("%08x %08x %08x %08x\n",
3885 // size, *(1+(int*)&size),
3886 // *(2+(int*)&size),*(3+(int*)&size));
3887 void* result;
3888 assert(size >= 0);
3890 result=my_mreq(size,0);
3891 dbgprintf("new(%d) => %p\n", size, result);
3892 if (result==0)
3893 printf("WARNING: new() failed\n");
3894 return result;
3897 static int expdelete(void* memory)
3899 dbgprintf("delete(%p)\n", memory);
3900 my_release(memory);
3901 return 0;
3905 * local definition - we need only the last two members at this point
3906 * otherwice we would have to introduce here GUIDs and some more types..
3908 typedef struct __attribute__((__packed__))
3910 char hay[0x40];
3911 unsigned long cbFormat; //0x40
3912 char* pbFormat; //0x44
3913 } MY_MEDIA_TYPE;
3914 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
3916 if (!dest || !src)
3917 return E_POINTER;
3918 memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
3919 if (dest->cbFormat)
3921 dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
3922 if (!dest->pbFormat)
3923 return E_OUTOFMEMORY;
3924 memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
3926 return S_OK;
3928 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
3930 if (!dest)
3931 return E_POINTER;
3932 memset(dest, 0, sizeof(MY_MEDIA_TYPE));
3933 if (cbFormat)
3935 dest->pbFormat = (char*) my_mreq(cbFormat, 0);
3936 if (!dest->pbFormat)
3937 return E_OUTOFMEMORY;
3939 return S_OK;
3941 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
3943 if (!dest)
3944 return E_POINTER;
3945 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3946 return expMoInitMediaType(*dest, cbFormat);
3948 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
3950 if (!dest)
3951 return E_POINTER;
3952 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3953 return expMoCopyMediaType(*dest, src);
3955 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
3957 if (!dest)
3958 return E_POINTER;
3959 if (dest->pbFormat)
3961 my_release(dest->pbFormat);
3962 dest->pbFormat = 0;
3963 dest->cbFormat = 0;
3965 return S_OK;
3967 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
3969 if (!dest)
3970 return E_POINTER;
3971 expMoFreeMediaType(dest);
3972 my_release(dest);
3973 return S_OK;
3976 static int exp_snprintf( char *str, int size, const char *format, ... )
3978 int x;
3979 va_list va;
3980 va_start(va, format);
3981 x=snprintf(str,size,format,va);
3982 dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
3983 va_end(va);
3984 return x;
3987 #if 0
3988 static int exp_initterm(int v1, int v2)
3990 dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
3991 return 0;
3993 #else
3994 /* merged from wine - 2002.04.21 */
3995 typedef void (*INITTERMFUNC)();
3996 static int exp_initterm(INITTERMFUNC *start, INITTERMFUNC *end)
3998 dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
3999 while (start < end)
4001 if (*start)
4003 //printf("call _initfunc: from: %p %d\n", *start);
4004 // ok this trick with push/pop is necessary as otherwice
4005 // edi/esi registers are being trashed
4006 void* p = *start;
4007 __asm__ volatile
4009 "pushl %%ebx \n\t"
4010 "pushl %%ecx \n\t"
4011 "pushl %%edx \n\t"
4012 "pushl %%edi \n\t"
4013 "pushl %%esi \n\t"
4014 "call *%%eax \n\t"
4015 "popl %%esi \n\t"
4016 "popl %%edi \n\t"
4017 "popl %%edx \n\t"
4018 "popl %%ecx \n\t"
4019 "popl %%ebx \n\t"
4021 : "a"(p)
4022 : "memory"
4024 //printf("done %p %d:%d\n", end);
4026 start++;
4028 return 0;
4030 #endif
4032 /* Fake _initterm_e from msvcr80.dll, needed by sirenacm.dll
4033 * NOTE: If I make this an alias for _initterm, then sirenacm.dll tries to call
4034 other uninmplemented functions; keep this in mind if some future codec needs
4035 a real implementation of this function */
4036 static int exp_initterm_e(INITTERMFUNC *start, INITTERMFUNC *end)
4038 dbgprintf("_initterm_e(0x%x, 0x%x)\n", start, end);
4039 return 0;
4042 static void* exp__dllonexit(void)
4044 // FIXME extract from WINE
4045 return NULL;
4048 static int expwsprintfA(char* string, const char* format, ...)
4050 va_list va;
4051 int result;
4052 va_start(va, format);
4053 result = vsprintf(string, format, va);
4054 dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4055 va_end(va);
4056 return result;
4059 static int expsprintf(char* str, const char* format, ...)
4061 va_list args;
4062 int r;
4063 dbgprintf("sprintf(0x%x, %s)\n", str, format);
4064 va_start(args, format);
4065 r = vsprintf(str, format, args);
4066 va_end(args);
4067 return r;
4069 static int expsscanf(const char* str, const char* format, ...)
4071 va_list args;
4072 int r;
4073 dbgprintf("sscanf(%s, %s)\n", str, format);
4074 va_start(args, format);
4075 r = vsscanf(str, format, args);
4076 va_end(args);
4077 return r;
4079 static void* expfopen(const char* path, const char* mode)
4081 printf("fopen: \"%s\" mode:%s\n", path, mode);
4082 //return fopen(path, mode);
4083 return fdopen(0, mode); // everything on screen
4085 static int expfprintf(void* stream, const char* format, ...)
4087 va_list args;
4088 int r = 0;
4089 dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4090 #if 1
4091 va_start(args, format);
4092 r = vfprintf((FILE*) stream, format, args);
4093 va_end(args);
4094 #endif
4095 return r;
4098 static int expprintf(const char* format, ...)
4100 va_list args;
4101 int r;
4102 dbgprintf("printf(%s, ...)\n", format);
4103 va_start(args, format);
4104 r = vprintf(format, args);
4105 va_end(args);
4106 return r;
4109 static char* expgetenv(const char* varname)
4111 char* v = getenv(varname);
4112 dbgprintf("getenv(%s) => %s\n", varname, v);
4113 return v;
4116 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4118 WCHAR* p = dst;
4119 while ((*p++ = *src++))
4121 return dst;
4124 static char* expstrrchr(char* string, int value)
4126 char* result=strrchr(string, value);
4127 if(result)
4128 dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4129 else
4130 dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4131 return result;
4134 static char* expstrchr(char* string, int value)
4136 char* result=strchr(string, value);
4137 if(result)
4138 dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4139 else
4140 dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4141 return result;
4143 static int expstrlen(char* str)
4145 int result=strlen(str);
4146 dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4147 return result;
4149 static char* expstrcpy(char* str1, const char* str2)
4151 char* result= strcpy(str1, str2);
4152 dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4153 return result;
4155 static char* expstrncpy(char* str1, const char* str2, size_t count)
4157 char* result= strncpy(str1, str2, count);
4158 dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4159 return result;
4161 static int expstrcmp(const char* str1, const char* str2)
4163 int result=strcmp(str1, str2);
4164 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4165 return result;
4167 static int expstrncmp(const char* str1, const char* str2,int x)
4169 int result=strncmp(str1, str2,x);
4170 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4171 return result;
4173 static char* expstrcat(char* str1, const char* str2)
4175 char* result = strcat(str1, str2);
4176 dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4177 return result;
4179 static char* exp_strdup(const char* str1)
4181 int l = strlen(str1);
4182 char* result = (char*) my_mreq(l + 1,0);
4183 if (result)
4184 strcpy(result, str1);
4185 dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4186 return result;
4188 static int expisalnum(int c)
4190 int result= (int) isalnum(c);
4191 dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4192 return result;
4194 static int expisspace(int c)
4196 int result= (int) isspace(c);
4197 dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4198 return result;
4200 static int expisalpha(int c)
4202 int result= (int) isalpha(c);
4203 dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4204 return result;
4206 static int expisdigit(int c)
4208 int result= (int) isdigit(c);
4209 dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4210 return result;
4212 static void* expmemmove(void* dest, void* src, int n)
4214 void* result = memmove(dest, src, n);
4215 dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4216 return result;
4218 static int expmemcmp(void* dest, void* src, int n)
4220 int result = memcmp(dest, src, n);
4221 dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4222 return result;
4224 static void* expmemcpy(void* dest, void* src, int n)
4226 void *result = memcpy(dest, src, n);
4227 dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4228 return result;
4230 static void* expmemset(void* dest, int c, size_t n)
4232 void *result = memset(dest, c, n);
4233 dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4234 return result;
4236 static time_t exptime(time_t* t)
4238 time_t result = time(t);
4239 dbgprintf("time(0x%x) => %d\n", t, result);
4240 return result;
4243 static int exprand(void)
4245 return rand();
4248 static void expsrand(int seed)
4250 srand(seed);
4253 #if 1
4255 // preferred compilation with -O2 -ffast-math !
4257 static double explog10(double x)
4259 /*printf("Log10 %f => %f 0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4260 return log10(x);
4263 static double expcos(double x)
4265 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4266 return cos(x);
4269 #else
4271 static void explog10(void)
4273 __asm__ volatile
4275 "fldl 8(%esp) \n\t"
4276 "fldln2 \n\t"
4277 "fxch %st(1) \n\t"
4278 "fyl2x \n\t"
4282 static void expcos(void)
4284 __asm__ volatile
4286 "fldl 8(%esp) \n\t"
4287 "fcos \n\t"
4291 #endif
4293 // this seem to be the only how to make this function working properly
4294 // ok - I've spent tremendous amount of time (many many many hours
4295 // of debuging fixing & testing - it's almost unimaginable - kabi
4297 // _ftol - operated on the float value which is already on the FPU stack
4299 static void exp_ftol(void)
4301 __asm__ volatile
4303 "sub $12, %esp \n\t"
4304 "fstcw -2(%ebp) \n\t"
4305 "wait \n\t"
4306 "movw -2(%ebp), %ax \n\t"
4307 "orb $0x0C, %ah \n\t"
4308 "movw %ax, -4(%ebp) \n\t"
4309 "fldcw -4(%ebp) \n\t"
4310 "fistpl -12(%ebp) \n\t"
4311 "fldcw -2(%ebp) \n\t"
4312 "movl -12(%ebp), %eax \n\t"
4313 //Note: gcc 3.03 does not do the following op if it
4314 // knows that ebp=esp
4315 "movl %ebp, %esp \n\t"
4319 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4320 __asm__ volatile( "fstpl %0;fwait" : "=m" (var2) : ); \
4321 __asm__ volatile( "fstpl %0;fwait" : "=m" (var1) : )
4323 static double exp_CIpow(void)
4325 FPU_DOUBLES(x,y);
4327 dbgprintf("_CIpow(%lf, %lf)\n", x, y);
4328 return pow(x, y);
4331 static double exppow(double x, double y)
4333 /*printf("Pow %f %f 0x%Lx 0x%Lx => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4334 return pow(x, y);
4337 static double expldexp(double x, int expo)
4339 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4340 return ldexp(x, expo);
4343 static double expfrexp(double x, int* expo)
4345 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4346 return frexp(x, expo);
4351 static int exp_stricmp(const char* s1, const char* s2)
4353 return strcasecmp(s1, s2);
4356 /* from declaration taken from Wine sources - this fountion seems to be
4357 * undocumented in any M$ doc */
4358 static int exp_setjmp3(void* jmpbuf, int x)
4360 //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4361 //return 0;
4362 __asm__ volatile
4364 //"mov 4(%%esp), %%edx \n\t"
4365 "mov (%%esp), %%eax \n\t"
4366 "mov %%eax, (%%edx) \n\t" // store ebp
4368 //"mov %%ebp, (%%edx) \n\t"
4369 "mov %%ebx, 4(%%edx) \n\t"
4370 "mov %%edi, 8(%%edx) \n\t"
4371 "mov %%esi, 12(%%edx) \n\t"
4372 "mov %%esp, 16(%%edx) \n\t"
4374 "mov 4(%%esp), %%eax \n\t"
4375 "mov %%eax, 20(%%edx) \n\t"
4377 "movl $0x56433230, 32(%%edx) \n\t" // VC20 ??
4378 "movl $0, 36(%%edx) \n\t"
4379 : // output
4380 : "d"(jmpbuf) // input
4381 : "eax"
4383 #if 1
4384 __asm__ volatile
4386 "mov %%fs:0, %%eax \n\t" // unsure
4387 "mov %%eax, 24(%%edx) \n\t"
4388 "cmp $0xffffffff, %%eax \n\t"
4389 "jnz l1 \n\t"
4390 "mov %%eax, 28(%%edx) \n\t"
4391 "l1: \n\t"
4394 : "eax"
4396 #endif
4398 return 0;
4401 static DWORD WINAPI expGetCurrentProcessId(void)
4403 dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4404 return getpid(); //(DWORD)NtCurrentTeb()->pid;
4408 typedef struct {
4409 UINT wPeriodMin;
4410 UINT wPeriodMax;
4411 } TIMECAPS, *LPTIMECAPS;
4413 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4415 dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4417 lpCaps->wPeriodMin = 1;
4418 lpCaps->wPeriodMax = 65535;
4419 return 0;
4422 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4424 dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4426 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4427 return 0;
4430 #ifdef QTX
4431 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4433 dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4435 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4436 return 0;
4438 #endif
4440 static void WINAPI expGlobalMemoryStatus(
4441 LPMEMORYSTATUS lpmem
4443 static MEMORYSTATUS cached_memstatus;
4444 static int cache_lastchecked = 0;
4445 SYSTEM_INFO si;
4446 FILE *f;
4448 if (time(NULL)==cache_lastchecked) {
4449 memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4450 return;
4453 #if 1
4454 f = fopen( "/proc/meminfo", "r" );
4455 if (f)
4457 char buffer[256];
4458 int total, used, free, shared, buffers, cached;
4460 lpmem->dwLength = sizeof(MEMORYSTATUS);
4461 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4462 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4463 while (fgets( buffer, sizeof(buffer), f ))
4465 /* old style /proc/meminfo ... */
4466 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4468 lpmem->dwTotalPhys += total;
4469 lpmem->dwAvailPhys += free + buffers + cached;
4471 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4473 lpmem->dwTotalPageFile += total;
4474 lpmem->dwAvailPageFile += free;
4477 /* new style /proc/meminfo ... */
4478 if (sscanf(buffer, "MemTotal: %d", &total))
4479 lpmem->dwTotalPhys = total*1024;
4480 if (sscanf(buffer, "MemFree: %d", &free))
4481 lpmem->dwAvailPhys = free*1024;
4482 if (sscanf(buffer, "SwapTotal: %d", &total))
4483 lpmem->dwTotalPageFile = total*1024;
4484 if (sscanf(buffer, "SwapFree: %d", &free))
4485 lpmem->dwAvailPageFile = free*1024;
4486 if (sscanf(buffer, "Buffers: %d", &buffers))
4487 lpmem->dwAvailPhys += buffers*1024;
4488 if (sscanf(buffer, "Cached: %d", &cached))
4489 lpmem->dwAvailPhys += cached*1024;
4491 fclose( f );
4493 if (lpmem->dwTotalPhys)
4495 DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4496 DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4497 lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4498 / (TotalPhysical / 100);
4500 } else
4501 #endif
4503 /* FIXME: should do something for other systems */
4504 lpmem->dwMemoryLoad = 0;
4505 lpmem->dwTotalPhys = 16*1024*1024;
4506 lpmem->dwAvailPhys = 16*1024*1024;
4507 lpmem->dwTotalPageFile = 16*1024*1024;
4508 lpmem->dwAvailPageFile = 16*1024*1024;
4510 expGetSystemInfo(&si);
4511 lpmem->dwTotalVirtual = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
4512 /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4513 lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
4514 memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4515 cache_lastchecked = time(NULL);
4517 /* it appears some memory display programs want to divide by these values */
4518 if(lpmem->dwTotalPageFile==0)
4519 lpmem->dwTotalPageFile++;
4521 if(lpmem->dwAvailPageFile==0)
4522 lpmem->dwAvailPageFile++;
4525 static INT WINAPI expGetThreadPriority(HANDLE hthread)
4527 dbgprintf("GetThreadPriority(%p)\n",hthread);
4528 return 0;
4531 /**********************************************************************
4532 * SetThreadPriority [KERNEL32.@] Sets priority for thread.
4534 * RETURNS
4535 * Success: TRUE
4536 * Failure: FALSE
4538 static WIN_BOOL WINAPI expSetThreadPriority(
4539 HANDLE hthread, /* [in] Handle to thread */
4540 INT priority) /* [in] Thread priority level */
4542 dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4543 return TRUE;
4546 static void WINAPI expExitProcess( DWORD status )
4548 printf("EXIT - code %ld\n",status);
4549 exit(status);
4552 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4553 printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4554 #ifdef QTX
4555 if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4556 return IDIGNORE;
4557 #endif
4558 return IDOK;
4561 /* these are needed for mss1 */
4564 * \brief this symbol is defined within exp_EH_prolog_dummy
4565 * \param dest jump target
4567 void exp_EH_prolog(void *dest);
4568 //! just a dummy function that acts a container for the asm section
4569 void exp_EH_prolog_dummy(void) {
4570 __asm__ volatile (
4571 // take care, this "function" may not change flags or
4572 // registers besides eax (which is also why we can't use
4573 // exp_EH_prolog_dummy directly)
4574 MANGLE(exp_EH_prolog)": \n\t"
4575 "pop %eax \n\t"
4576 "push %ebp \n\t"
4577 "mov %esp, %ebp \n\t"
4578 "lea -12(%esp), %esp \n\t"
4579 "jmp *%eax \n\t"
4583 #include <netinet/in.h>
4584 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4586 // dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4587 return htonl(hostlong);
4590 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4592 // dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4593 return ntohl(netlong);
4595 static void WINAPI expVariantInit(void* p)
4597 printf("InitCommonControls called!\n");
4598 return;
4601 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4603 dbgprintf("RegisterClassA(%p) => random id\n", wc);
4604 return time(NULL); /* be precise ! */
4607 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4609 dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4610 return 0;
4613 #ifdef QTX
4614 /* should be fixed bcs it's not fully strlen equivalent */
4615 static int expSysStringByteLen(void *str)
4617 dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4618 return strlen(str);
4621 static int expDirectDrawCreate(void)
4623 dbgprintf("DirectDrawCreate(...) => NULL\n");
4624 return 0;
4627 #if 1
4628 typedef struct tagPALETTEENTRY {
4629 BYTE peRed;
4630 BYTE peGreen;
4631 BYTE peBlue;
4632 BYTE peFlags;
4633 } PALETTEENTRY;
4635 /* reversed the first 2 entries */
4636 typedef struct tagLOGPALETTE {
4637 WORD palNumEntries;
4638 WORD palVersion;
4639 PALETTEENTRY palPalEntry[1];
4640 } LOGPALETTE;
4642 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4644 HPALETTE test;
4645 int i;
4647 dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4649 i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4650 test = (HPALETTE)malloc(i);
4651 memcpy((void *)test, lpgpl, i);
4653 return test;
4655 #else
4656 static int expCreatePalette(void)
4658 dbgprintf("CreatePalette(...) => NULL\n");
4659 return NULL;
4661 #endif
4663 static int WINAPI expGetClientRect(HWND win, RECT *r)
4665 dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4666 r->right = PSEUDO_SCREEN_WIDTH;
4667 r->left = 0;
4668 r->bottom = PSEUDO_SCREEN_HEIGHT;
4669 r->top = 0;
4670 return 1;
4673 #if 0
4674 typedef struct tagPOINT {
4675 LONG x;
4676 LONG y;
4677 } POINT, *PPOINT;
4678 #endif
4680 static int WINAPI expClientToScreen(HWND win, POINT *p)
4682 dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4683 p->x = 0;
4684 p->y = 0;
4685 return 1;
4687 #endif
4689 /* for m3jpeg */
4690 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4692 dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4693 return 0;
4696 static int WINAPI expMessageBeep(int type)
4698 dbgprintf("MessageBeep(%d) => 1\n", type);
4699 return 1;
4702 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4703 HWND parent, void *dialog_func, void *init_param)
4705 dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4706 inst, name, name, parent, dialog_func, init_param);
4707 return 0x42424242;
4710 static void WINAPI expRegisterClipboardFormatA(const char *name) {
4711 dbgprintf("RegisterClipboardFormatA(0x%x = %s)\n", name, name);
4714 /* needed by imagepower mjpeg2k */
4715 static void *exprealloc(void *ptr, size_t size)
4717 dbgprintf("realloc(0x%x, %x)\n", ptr, size);
4718 if (!ptr)
4719 return my_mreq(size,0);
4720 else
4721 return my_realloc(ptr, size);
4724 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
4725 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
4727 return 1;
4730 static char * WINAPI expPathFindExtensionA(const char *path) {
4731 char *ext;
4732 if (!path)
4733 ext = NULL;
4734 else {
4735 ext = strrchr(path, '.');
4736 if (!ext)
4737 ext = &path[strlen(path)];
4739 dbgprintf("PathFindExtensionA(0x%x = %s) => 0x%x, %s\n", path, path, ext, ext);
4740 return ext;
4743 static char * WINAPI expPathFindFileNameA(const char *path) {
4744 char *name;
4745 if (!path || strlen(path) < 2)
4746 name = path;
4747 else {
4748 name = strrchr(path - 1, '\\');
4749 if (!name)
4750 name = path;
4752 dbgprintf("PathFindFileNameA(0x%x = %s) => 0x%x, %s\n", path, path, name, name);
4753 return name;
4756 static double expfloor(double x)
4758 dbgprintf("floor(%lf)\n", x);
4759 return floor(x);
4762 #define FPU_DOUBLE(var) double var; \
4763 __asm__ volatile( "fstpl %0;fwait" : "=m" (var) : )
4765 static double exp_CIcos(void)
4767 FPU_DOUBLE(x);
4769 dbgprintf("_CIcos(%lf)\n", x);
4770 return cos(x);
4773 static double exp_CIsin(void)
4775 FPU_DOUBLE(x);
4777 dbgprintf("_CIsin(%lf)\n", x);
4778 return sin(x);
4781 static double exp_CIsqrt(void)
4783 FPU_DOUBLE(x);
4785 dbgprintf("_CIsqrt(%lf)\n", x);
4786 return sqrt(x);
4789 /* Needed by rp8 sipr decoder */
4790 static LPSTR WINAPI expCharNextA(LPCSTR ptr)
4792 if (!*ptr) return (LPSTR)ptr;
4793 // dbgprintf("CharNextA(0x%08x), %s\n", ptr, ptr);
4794 return (LPSTR)(ptr + 1);
4797 // Fake implementation, needed by wvc1dmod.dll
4798 static int WINAPI expPropVariantClear(void *pvar)
4800 // dbgprintf("PropVariantclear (0x%08x), %s\n", ptr, ptr);
4801 return 1;
4804 // This define is fake, the real thing is a struct
4805 #define LPDEVMODEA void*
4806 // Dummy implementation, always return 1
4807 // Required for frapsvid.dll 2.8.1, return value does not matter
4808 static WIN_BOOL WINAPI expEnumDisplaySettingsA(LPCSTR name ,DWORD n,
4809 LPDEVMODEA devmode)
4811 dbgprintf("EnumDisplaySettingsA (dummy) => 1\n");
4812 return 1;
4815 // Fake implementation of _decode_pointer from msvcr80.dll, needed by sirenacm.dll
4816 // NOTE: undocumented function, probably the declaration is not right
4817 static int exp_decode_pointer(void *ptr)
4819 dbgprintf("_decode_pointer (0x%08x)\n", ptr);
4820 return 0;
4823 /* Fake implementation of sdt::_Lockit::_Lockit(void) from msvcp60.dll
4824 Needed by SCLS.DLL */
4825 static int exp_0Lockit_dummy(void)
4827 dbgprintf("0Lockit_dummy (??0_Lockit@std@@QAE@XZ)\n");
4828 return 0;
4831 /* Fake implementation of sdt::_Lockit::~_Lockit(void) from msvcp60.dll
4832 Needed by SCLS.DLL */
4833 static int exp_1Lockit_dummy(void)
4835 dbgprintf("1Lockit_dummy (??1_Lockit@std@@QAE@XZ)\n");
4836 return 0;
4839 static void * WINAPI expEncodePointer(void *p)
4841 return p;
4844 static void * WINAPI expDecodePointer(void *p)
4846 return p;
4849 struct exports
4851 char name[64];
4852 int id;
4853 void* func;
4855 struct libs
4857 char name[64];
4858 int length;
4859 struct exports* exps;
4862 #define FF(X,Y) \
4863 {#X, Y, (void*)exp##X},
4865 #define UNDEFF(X, Y) \
4866 {#X, Y, (void*)-1},
4868 struct exports exp_kernel32[]=
4870 FF(GetVolumeInformationA,-1)
4871 FF(GetDriveTypeA,-1)
4872 FF(GetLogicalDriveStringsA,-1)
4873 FF(IsBadWritePtr, 357)
4874 FF(IsBadReadPtr, 354)
4875 FF(IsBadStringPtrW, -1)
4876 FF(IsBadStringPtrA, -1)
4877 FF(DisableThreadLibraryCalls, -1)
4878 FF(CreateThread, -1)
4879 FF(CreateEventA, -1)
4880 FF(SetEvent, -1)
4881 FF(ResetEvent, -1)
4882 FF(WaitForSingleObject, -1)
4883 #ifdef QTX
4884 FF(WaitForMultipleObjects, -1)
4885 FF(ExitThread, -1)
4886 FF(CreateMutexA,-1)
4887 FF(ReleaseMutex,-1)
4888 #endif
4889 FF(GetSystemInfo, -1)
4890 FF(GetVersion, 332)
4891 FF(HeapCreate, 461)
4892 FF(HeapAlloc, -1)
4893 FF(HeapDestroy, -1)
4894 FF(HeapFree, -1)
4895 FF(HeapSize, -1)
4896 FF(HeapReAlloc,-1)
4897 FF(GetProcessHeap, -1)
4898 FF(VirtualAlloc, -1)
4899 FF(VirtualFree, -1)
4900 FF(InitializeCriticalSection, -1)
4901 FF(EnterCriticalSection, -1)
4902 FF(LeaveCriticalSection, -1)
4903 FF(DeleteCriticalSection, -1)
4904 FF(TlsAlloc, -1)
4905 FF(TlsFree, -1)
4906 FF(TlsGetValue, -1)
4907 FF(TlsSetValue, -1)
4908 FF(GetCurrentThreadId, -1)
4909 FF(GetCurrentProcess, -1)
4910 FF(LocalAlloc, -1)
4911 FF(LocalReAlloc,-1)
4912 FF(LocalLock, -1)
4913 FF(GlobalAlloc, -1)
4914 FF(GlobalReAlloc, -1)
4915 FF(GlobalLock, -1)
4916 FF(GlobalSize, -1)
4917 FF(MultiByteToWideChar, 427)
4918 FF(WideCharToMultiByte, -1)
4919 FF(GetVersionExA, -1)
4920 FF(CreateSemaphoreA, -1)
4921 FF(QueryPerformanceCounter, -1)
4922 FF(QueryPerformanceFrequency, -1)
4923 FF(LocalHandle, -1)
4924 FF(LocalUnlock, -1)
4925 FF(LocalFree, -1)
4926 FF(GlobalHandle, -1)
4927 FF(GlobalUnlock, -1)
4928 FF(GlobalFree, -1)
4929 FF(LoadResource, -1)
4930 FF(ReleaseSemaphore, -1)
4931 FF(FindResourceA, -1)
4932 FF(LockResource, -1)
4933 FF(FreeResource, -1)
4934 FF(SizeofResource, -1)
4935 FF(CloseHandle, -1)
4936 FF(GetCommandLineA, -1)
4937 FF(GetEnvironmentStringsW, -1)
4938 FF(FreeEnvironmentStringsW, -1)
4939 FF(FreeEnvironmentStringsA, -1)
4940 FF(GetEnvironmentStrings, -1)
4941 FF(GetStartupInfoA, -1)
4942 FF(GetStdHandle, -1)
4943 FF(GetFileType, -1)
4944 #ifdef QTX
4945 FF(GetFileAttributesA, -1)
4946 #endif
4947 FF(SetHandleCount, -1)
4948 FF(GetACP, -1)
4949 FF(GetModuleFileNameA, -1)
4950 FF(SetUnhandledExceptionFilter, -1)
4951 FF(LoadLibraryA, -1)
4952 FF(GetProcAddress, -1)
4953 FF(FreeLibrary, -1)
4954 FF(CreateFileMappingA, -1)
4955 FF(OpenFileMappingA, -1)
4956 FF(MapViewOfFile, -1)
4957 FF(UnmapViewOfFile, -1)
4958 FF(Sleep, -1)
4959 FF(GetModuleHandleA, -1)
4960 FF(GetProfileIntA, -1)
4961 FF(GetPrivateProfileIntA, -1)
4962 FF(GetPrivateProfileStringA, -1)
4963 FF(WritePrivateProfileStringA, -1)
4964 FF(GetLastError, -1)
4965 FF(SetLastError, -1)
4966 FF(InterlockedIncrement, -1)
4967 FF(InterlockedDecrement, -1)
4968 FF(GetTimeZoneInformation, -1)
4969 FF(OutputDebugStringA, -1)
4970 FF(GetLocalTime, -1)
4971 FF(GetSystemTime, -1)
4972 FF(GetSystemTimeAsFileTime, -1)
4973 FF(GetEnvironmentVariableA, -1)
4974 FF(SetEnvironmentVariableA, -1)
4975 FF(RtlZeroMemory,-1)
4976 FF(RtlMoveMemory,-1)
4977 FF(RtlFillMemory,-1)
4978 FF(GetTempPathA,-1)
4979 FF(FindFirstFileA,-1)
4980 FF(FindNextFileA,-1)
4981 FF(FindClose,-1)
4982 FF(FileTimeToLocalFileTime,-1)
4983 FF(DeleteFileA,-1)
4984 FF(ReadFile,-1)
4985 FF(WriteFile,-1)
4986 FF(SetFilePointer,-1)
4987 FF(GetTempFileNameA,-1)
4988 FF(CreateFileA,-1)
4989 FF(GetSystemDirectoryA,-1)
4990 FF(GetWindowsDirectoryA,-1)
4991 #ifdef QTX
4992 FF(GetCurrentDirectoryA,-1)
4993 FF(SetCurrentDirectoryA,-1)
4994 FF(CreateDirectoryA,-1)
4995 #endif
4996 FF(GetShortPathNameA,-1)
4997 FF(GetFullPathNameA,-1)
4998 FF(SetErrorMode, -1)
4999 FF(IsProcessorFeaturePresent, -1)
5000 FF(GetProcessAffinityMask, -1)
5001 FF(InterlockedExchange, -1)
5002 FF(InterlockedCompareExchange, -1)
5003 FF(MulDiv, -1)
5004 FF(lstrcmpiA, -1)
5005 FF(lstrlenA, -1)
5006 FF(lstrcpyA, -1)
5007 FF(lstrcatA, -1)
5008 FF(lstrcpynA,-1)
5009 FF(GetProcessVersion,-1)
5010 FF(GetCurrentThread,-1)
5011 FF(GetOEMCP,-1)
5012 FF(GetCPInfo,-1)
5013 FF(DuplicateHandle,-1)
5014 FF(GetTickCount, -1)
5015 FF(SetThreadAffinityMask,-1)
5016 FF(GetCurrentProcessId,-1)
5017 FF(GlobalMemoryStatus,-1)
5018 FF(GetThreadPriority,-1)
5019 FF(SetThreadPriority,-1)
5020 FF(ExitProcess,-1)
5021 {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
5022 FF(SetThreadIdealProcessor,-1)
5023 FF(SetProcessAffinityMask, -1)
5024 FF(EncodePointer, -1)
5025 FF(DecodePointer, -1)
5026 UNDEFF(FlsAlloc, -1)
5027 UNDEFF(FlsGetValue, -1)
5028 UNDEFF(FlsSetValue, -1)
5029 UNDEFF(FlsFree, -1)
5032 struct exports exp_msvcrt[]={
5033 FF(malloc, -1)
5034 FF(_initterm, -1)
5035 FF(__dllonexit, -1)
5036 FF(_snprintf,-1)
5037 FF(free, -1)
5038 {"??3@YAXPAX@Z", -1, expdelete},
5039 {"??2@YAPAXI@Z", -1, expnew},
5040 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5041 {"_winver",-1,(void*)&_winver},
5042 FF(strrchr, -1)
5043 FF(strchr, -1)
5044 FF(strlen, -1)
5045 FF(strcpy, -1)
5046 FF(strncpy, -1)
5047 FF(wcscpy, -1)
5048 FF(strcmp, -1)
5049 FF(strncmp, -1)
5050 FF(strcat, -1)
5051 FF(_stricmp,-1)
5052 FF(_strdup,-1)
5053 FF(_setjmp3,-1)
5054 FF(isalnum, -1)
5055 FF(isspace, -1)
5056 FF(isalpha, -1)
5057 FF(isdigit, -1)
5058 FF(memmove, -1)
5059 FF(memcmp, -1)
5060 FF(memset, -1)
5061 FF(memcpy, -1)
5062 FF(time, -1)
5063 FF(rand, -1)
5064 FF(srand, -1)
5065 FF(log10, -1)
5066 FF(pow, -1)
5067 FF(cos, -1)
5068 FF(_ftol,-1)
5069 FF(_CIpow,-1)
5070 FF(_CIcos,-1)
5071 FF(_CIsin,-1)
5072 FF(_CIsqrt,-1)
5073 FF(ldexp,-1)
5074 FF(frexp,-1)
5075 FF(sprintf,-1)
5076 FF(sscanf,-1)
5077 FF(fopen,-1)
5078 FF(fprintf,-1)
5079 FF(printf,-1)
5080 FF(getenv,-1)
5081 FF(floor,-1)
5082 /* needed by frapsvid.dll */
5083 {"strstr",-1,(char *)&strstr},
5084 {"qsort",-1,(void *)&qsort},
5085 FF(_EH_prolog,-1)
5086 FF(calloc,-1)
5087 {"ceil",-1,(void*)&ceil},
5088 /* needed by imagepower mjpeg2k */
5089 {"clock",-1,(void*)&clock},
5090 {"memchr",-1,(void*)&memchr},
5091 {"vfprintf",-1,(void*)&vfprintf},
5092 // {"realloc",-1,(void*)&realloc},
5093 FF(realloc,-1)
5094 {"puts",-1,(void*)&puts}
5096 struct exports exp_winmm[]={
5097 FF(GetDriverModuleHandle, -1)
5098 FF(timeGetTime, -1)
5099 FF(DefDriverProc, -1)
5100 FF(OpenDriverA, -1)
5101 FF(OpenDriver, -1)
5102 FF(timeGetDevCaps, -1)
5103 FF(timeBeginPeriod, -1)
5104 #ifdef QTX
5105 FF(timeEndPeriod, -1)
5106 FF(waveOutGetNumDevs, -1)
5107 #endif
5109 struct exports exp_user32[]={
5110 FF(LoadIconA,-1)
5111 FF(LoadStringA, -1)
5112 FF(wsprintfA, -1)
5113 FF(GetDC, -1)
5114 FF(GetDesktopWindow, -1)
5115 FF(ReleaseDC, -1)
5116 FF(IsRectEmpty, -1)
5117 FF(LoadCursorA,-1)
5118 FF(SetCursor,-1)
5119 FF(GetCursorPos,-1)
5120 #ifdef QTX
5121 FF(ShowCursor,-1)
5122 #endif
5123 FF(RegisterWindowMessageA,-1)
5124 FF(GetSystemMetrics,-1)
5125 FF(GetSysColor,-1)
5126 FF(GetSysColorBrush,-1)
5127 FF(GetWindowDC, -1)
5128 FF(DrawTextA, -1)
5129 FF(MessageBoxA, -1)
5130 FF(RegisterClassA, -1)
5131 FF(UnregisterClassA, -1)
5132 #ifdef QTX
5133 FF(GetWindowRect, -1)
5134 FF(MonitorFromWindow, -1)
5135 FF(MonitorFromRect, -1)
5136 FF(MonitorFromPoint, -1)
5137 FF(EnumDisplayMonitors, -1)
5138 FF(GetMonitorInfoA, -1)
5139 FF(EnumDisplayDevicesA, -1)
5140 FF(GetClientRect, -1)
5141 FF(ClientToScreen, -1)
5142 FF(IsWindowVisible, -1)
5143 FF(GetActiveWindow, -1)
5144 FF(GetClassNameA, -1)
5145 FF(GetClassInfoA, -1)
5146 FF(GetWindowLongA, -1)
5147 FF(EnumWindows, -1)
5148 FF(GetWindowThreadProcessId, -1)
5149 FF(CreateWindowExA, -1)
5150 #endif
5151 FF(MessageBeep, -1)
5152 FF(DialogBoxParamA, -1)
5153 FF(RegisterClipboardFormatA, -1)
5154 FF(CharNextA, -1)
5155 FF(EnumDisplaySettingsA, -1)
5157 struct exports exp_advapi32[]={
5158 FF(RegCloseKey, -1)
5159 FF(RegCreateKeyA, -1)
5160 FF(RegCreateKeyExA, -1)
5161 FF(RegEnumKeyExA, -1)
5162 FF(RegEnumValueA, -1)
5163 FF(RegOpenKeyA, -1)
5164 FF(RegOpenKeyExA, -1)
5165 FF(RegQueryValueExA, -1)
5166 FF(RegSetValueExA, -1)
5167 FF(RegQueryInfoKeyA, -1)
5169 struct exports exp_gdi32[]={
5170 FF(CreateCompatibleDC, -1)
5171 FF(CreateFontA, -1)
5172 FF(DeleteDC, -1)
5173 FF(DeleteObject, -1)
5174 FF(GetDeviceCaps, -1)
5175 FF(GetSystemPaletteEntries, -1)
5176 #ifdef QTX
5177 FF(CreatePalette, -1)
5178 FF(GetObjectA, -1)
5179 FF(CreateRectRgn, -1)
5180 #endif
5182 struct exports exp_version[]={
5183 FF(GetFileVersionInfoSizeA, -1)
5185 struct exports exp_ole32[]={
5186 FF(CoCreateFreeThreadedMarshaler,-1)
5187 FF(CoCreateInstance, -1)
5188 FF(CoInitialize, -1)
5189 FF(CoInitializeEx, -1)
5190 FF(CoUninitialize, -1)
5191 FF(CoTaskMemAlloc, -1)
5192 FF(CoTaskMemFree, -1)
5193 FF(StringFromGUID2, -1)
5194 FF(PropVariantClear, -1)
5196 // do we really need crtdll ???
5197 // msvcrt is the correct place probably...
5198 struct exports exp_crtdll[]={
5199 FF(memcpy, -1)
5200 FF(wcscpy, -1)
5202 struct exports exp_comctl32[]={
5203 FF(StringFromGUID2, -1)
5204 FF(InitCommonControls, 17)
5205 #ifdef QTX
5206 FF(CreateUpDownControl, 16)
5207 #endif
5209 struct exports exp_wsock32[]={
5210 FF(htonl,8)
5211 FF(ntohl,14)
5213 struct exports exp_msdmo[]={
5214 FF(memcpy, -1) // just test
5215 FF(MoCopyMediaType, -1)
5216 FF(MoCreateMediaType, -1)
5217 FF(MoDeleteMediaType, -1)
5218 FF(MoDuplicateMediaType, -1)
5219 FF(MoFreeMediaType, -1)
5220 FF(MoInitMediaType, -1)
5222 struct exports exp_oleaut32[]={
5223 FF(VariantInit, 8)
5224 #ifdef QTX
5225 FF(SysStringByteLen, 149)
5226 #endif
5229 /* realplayer8:
5230 DLL Name: PNCRT.dll
5231 vma: Hint/Ord Member-Name
5232 22ff4 615 free
5233 2302e 250 _ftol
5234 22fea 666 malloc
5235 2303e 609 fprintf
5236 2305e 167 _adjust_fdiv
5237 23052 280 _initterm
5239 22ffc 176 _beginthreadex
5240 23036 284 _iob
5241 2300e 85 __CxxFrameHandler
5242 23022 411 _purecall
5244 #ifdef REALPLAYER
5245 struct exports exp_pncrt[]={
5246 FF(malloc, -1) // just test
5247 FF(free, -1) // just test
5248 FF(fprintf, -1) // just test
5249 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5250 FF(_ftol,-1)
5251 FF(_initterm, -1)
5252 {"??3@YAXPAX@Z", -1, expdelete},
5253 {"??2@YAPAXI@Z", -1, expnew},
5254 FF(__dllonexit, -1)
5255 FF(strncpy, -1)
5256 FF(_CIpow,-1)
5257 FF(calloc,-1)
5258 FF(memmove, -1)
5259 FF(ldexp, -1)
5260 FF(frexp, -1)
5262 #endif
5264 #ifdef QTX
5265 struct exports exp_ddraw[]={
5266 FF(DirectDrawCreate, -1)
5268 #endif
5270 struct exports exp_comdlg32[]={
5271 FF(GetOpenFileNameA, -1)
5274 struct exports exp_shlwapi[]={
5275 FF(PathFindExtensionA, -1)
5276 FF(PathFindFileNameA, -1)
5279 struct exports exp_msvcr80[]={
5280 FF(_CIpow,-1)
5281 FF(_CIsin,-1)
5282 FF(_CIcos,-1)
5283 FF(_CIsqrt,-1)
5284 FF(memset,-1)
5285 FF(_initterm_e, -1)
5286 FF(_initterm, -1)
5287 FF(_decode_pointer, -1)
5288 /* needed by KGV1-VFW.dll */
5289 {"??2@YAPAXI@Z", -1, expnew},
5290 {"??3@YAXPAX@Z", -1, expdelete}
5293 struct exports exp_msvcp60[]={
5294 {"??0_Lockit@std@@QAE@XZ", -1, exp_0Lockit_dummy},
5295 {"??1_Lockit@std@@QAE@XZ", -1, exp_1Lockit_dummy}
5298 #define LL(X) \
5299 {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5301 struct libs libraries[]={
5302 LL(kernel32)
5303 LL(msvcrt)
5304 LL(winmm)
5305 LL(user32)
5306 LL(advapi32)
5307 LL(gdi32)
5308 LL(version)
5309 LL(ole32)
5310 LL(oleaut32)
5311 LL(crtdll)
5312 LL(comctl32)
5313 LL(wsock32)
5314 LL(msdmo)
5315 #ifdef REALPLAYER
5316 LL(pncrt)
5317 #endif
5318 #ifdef QTX
5319 LL(ddraw)
5320 #endif
5321 LL(comdlg32)
5322 LL(shlwapi)
5323 LL(msvcr80)
5324 LL(msvcp60)
5327 static WIN_BOOL WINAPI ext_stubs(void)
5329 // NOTE! these magic values will be replaced at runtime, make sure
5330 // add_stub can still find them if you change them.
5331 volatile int idx = 0x0deadabc;
5332 // make sure gcc does not do eip-relative call or something like that
5333 void (* volatile my_printf)(char *, char *) = (void *)0xdeadfbcd;
5334 my_printf("Called unk_%s\n", export_names[idx]);
5335 return 0;
5338 #define MAX_STUB_SIZE 0x60
5339 #define MAX_NUM_STUBS 200
5340 static int pos=0;
5341 static char *extcode = NULL;
5343 static void* add_stub(void)
5345 int i;
5346 int found = 0;
5347 // generated code in runtime!
5348 char* answ;
5349 if (!extcode)
5350 extcode = mmap_anon(NULL, MAX_NUM_STUBS * MAX_STUB_SIZE,
5351 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0);
5352 answ = extcode + pos * MAX_STUB_SIZE;
5353 if (pos >= MAX_NUM_STUBS) {
5354 printf("too many stubs, expect crash\n");
5355 return NULL;
5357 memcpy(answ, ext_stubs, MAX_STUB_SIZE);
5358 for (i = 0; i < MAX_STUB_SIZE - 3; i++) {
5359 int *magic = (int *)(answ + i);
5360 if (*magic == 0x0deadabc) {
5361 *magic = pos;
5362 found |= 1;
5364 if (*magic == 0xdeadfbcd) {
5365 *magic = (intptr_t)printf;
5366 found |= 2;
5369 if (found != 3) {
5370 printf("magic code not found in ext_subs, expect crash\n");
5371 return NULL;
5373 pos++;
5374 return (void*)answ;
5377 void* LookupExternal(const char* library, int ordinal)
5379 int i,j;
5380 if(library==0)
5382 printf("ERROR: library=0\n");
5383 return (void*)ext_unknown;
5385 // printf("%x %x\n", &unk_exp1, &unk_exp2);
5387 dbgprintf("External func %s:%d\n", library, ordinal);
5389 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5391 if(strcasecmp(library, libraries[i].name))
5392 continue;
5393 for(j=0; j<libraries[i].length; j++)
5395 if(ordinal!=libraries[i].exps[j].id)
5396 continue;
5397 //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5398 return libraries[i].exps[j].func;
5402 #ifndef LOADLIB_TRY_NATIVE
5403 /* hack for truespeech and vssh264*/
5404 if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5405 #endif
5406 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5408 int hand;
5409 WINE_MODREF *wm;
5410 void *func;
5412 hand = LoadLibraryA(library);
5413 if (!hand)
5414 goto no_dll;
5415 wm = MODULE32_LookupHMODULE(hand);
5416 if (!wm)
5418 FreeLibrary(hand);
5419 goto no_dll;
5421 func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5422 if (!func)
5424 printf("No such ordinal in external dll\n");
5425 FreeLibrary((int)hand);
5426 goto no_dll;
5429 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5430 hand, func);
5431 return func;
5434 no_dll:
5435 if(pos>150)return 0;
5436 sprintf(export_names[pos], "%s:%d", library, ordinal);
5437 return add_stub();
5440 void* LookupExternalByName(const char* library, const char* name)
5442 int i,j;
5443 // return (void*)ext_unknown;
5444 if(library==0)
5446 printf("ERROR: library=0\n");
5447 return (void*)ext_unknown;
5449 if((unsigned long)name<=0xffff)
5451 return LookupExternal(library, (int)name);
5453 dbgprintf("External func %s:%s\n", library, name);
5454 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5456 if(strcasecmp(library, libraries[i].name))
5457 continue;
5458 for(j=0; j<libraries[i].length; j++)
5460 if(strcmp(name, libraries[i].exps[j].name))
5461 continue;
5462 if((unsigned int)(libraries[i].exps[j].func) == -1)
5463 return NULL; //undefined func
5464 // printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5465 return libraries[i].exps[j].func;
5469 #ifndef LOADLIB_TRY_NATIVE
5470 /* hack for vss h264 */
5471 if (!strcmp(library,"vssh264core.dll") || !strcmp(library,"3ivx.dll"))
5472 #endif
5473 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5475 int hand;
5476 WINE_MODREF *wm;
5477 void *func;
5479 hand = LoadLibraryA(library);
5480 if (!hand)
5481 goto no_dll_byname;
5482 wm = MODULE32_LookupHMODULE(hand);
5483 if (!wm)
5485 FreeLibrary(hand);
5486 goto no_dll_byname;
5488 func = PE_FindExportedFunction(wm, name, 0);
5489 if (!func)
5491 printf("No such name in external dll\n");
5492 FreeLibrary((int)hand);
5493 goto no_dll_byname;
5496 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5497 hand, func);
5498 return func;
5501 no_dll_byname:
5502 if(pos>150)return 0;// to many symbols
5503 strcpy(export_names[pos], name);
5504 return add_stub();
5507 void my_garbagecollection(void)
5509 #ifdef GARBAGE
5510 int unfree = 0, unfreecnt = 0;
5512 int max_fatal = 8;
5513 free_registry();
5514 while (last_alloc)
5516 alloc_header* mem = last_alloc + 1;
5517 unfree += my_size(mem);
5518 unfreecnt++;
5519 if (my_release(mem) != 0)
5520 // avoid endless loop when memory is trashed
5521 if (--max_fatal < 0)
5522 break;
5524 dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5525 #endif
5526 g_tls = NULL;
5527 list = NULL;