100l, reorder check for AC3 format to avoid a possible memleak
[mplayer/glamo.git] / loader / win32.c
blob96ab76f69106cc9cef0523d44b344b8d31ddf3b2
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 #ifdef HAVE_MALLOC_H
57 #include <malloc.h>
58 #endif
59 #include <time.h>
60 #include <math.h>
61 #include <unistd.h>
62 #include <fcntl.h>
63 #include <sys/types.h>
64 #include <dirent.h>
65 #include <sys/time.h>
66 #include <sys/timeb.h>
67 #ifdef HAVE_KSTAT
68 #include <kstat.h>
69 #endif
71 #ifdef HAVE_SYS_MMAN_H
72 #include <sys/mman.h>
73 #else
74 #include "osdep/mmap.h"
75 #endif
76 #include "osdep/mmap_anon.h"
78 char* def_path = WIN32_PATH;
80 static void do_cpuid(unsigned int ax, unsigned int *regs)
82 __asm__ volatile
84 "pushl %%ebx; pushl %%ecx; pushl %%edx;"
85 ".byte 0x0f, 0xa2;"
86 "movl %%eax, (%2);"
87 "movl %%ebx, 4(%2);"
88 "movl %%ecx, 8(%2);"
89 "movl %%edx, 12(%2);"
90 "popl %%edx; popl %%ecx; popl %%ebx;"
91 : "=a" (ax)
92 : "0" (ax), "S" (regs)
95 static unsigned int c_localcount_tsc()
97 int a;
98 __asm__ volatile
100 "rdtsc\n\t"
101 :"=a"(a)
103 :"edx"
105 return a;
107 static void c_longcount_tsc(long long* z)
109 __asm__ volatile
111 "pushl %%ebx\n\t"
112 "movl %%eax, %%ebx\n\t"
113 "rdtsc\n\t"
114 "movl %%eax, 0(%%ebx)\n\t"
115 "movl %%edx, 4(%%ebx)\n\t"
116 "popl %%ebx\n\t"
117 ::"a"(z)
118 :"edx"
121 static unsigned int c_localcount_notsc()
123 struct timeval tv;
124 unsigned limit=~0;
125 limit/=1000000;
126 gettimeofday(&tv, 0);
127 return limit*tv.tv_usec;
129 static void c_longcount_notsc(long long* z)
131 struct timeval tv;
132 unsigned long long result;
133 unsigned limit=~0;
134 if(!z)return;
135 limit/=1000000;
136 gettimeofday(&tv, 0);
137 result=tv.tv_sec;
138 result<<=32;
139 result+=limit*tv.tv_usec;
140 *z=result;
142 static unsigned int localcount_stub(void);
143 static void longcount_stub(long long*);
144 static unsigned int (*localcount)()=localcount_stub;
145 static void (*longcount)(long long*)=longcount_stub;
147 static pthread_mutex_t memmut;
149 static unsigned int localcount_stub(void)
151 unsigned int regs[4];
152 do_cpuid(1, regs);
153 if ((regs[3] & 0x00000010) != 0)
155 localcount=c_localcount_tsc;
156 longcount=c_longcount_tsc;
158 else
160 localcount=c_localcount_notsc;
161 longcount=c_longcount_notsc;
163 return localcount();
165 static void longcount_stub(long long* z)
167 unsigned int regs[4];
168 do_cpuid(1, regs);
169 if ((regs[3] & 0x00000010) != 0)
171 localcount=c_localcount_tsc;
172 longcount=c_longcount_tsc;
174 else
176 localcount=c_localcount_notsc;
177 longcount=c_longcount_notsc;
179 longcount(z);
182 #include "mp_msg.h"
183 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
184 //#define DETAILED_OUT
185 static inline void dbgprintf(char* fmt, ...)
187 #ifdef DETAILED_OUT
188 if(LOADER_DEBUG)
190 FILE* f;
191 va_list va;
192 va_start(va, fmt);
193 f=fopen("./log", "a");
194 vprintf(fmt, va);
195 fflush(stdout);
196 if(f)
198 vfprintf(f, fmt, va);
199 fsync(fileno(f));
200 fclose(f);
202 va_end(va);
204 #endif
205 if ( mp_msg_test(MSGT_WIN32,MSGL_DBG3) )
207 va_list va;
209 va_start(va, fmt);
210 vprintf(fmt, va);
211 // mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
212 va_end(va);
214 fflush(stdout);
218 char export_names[300][32]={
219 "name1",
220 //"name2",
221 //"name3"
223 //#define min(x,y) ((x)<(y)?(x):(y))
225 void destroy_event(void* event);
227 struct th_list_t;
228 typedef struct th_list_t{
229 int id;
230 void* thread;
231 struct th_list_t* next;
232 struct th_list_t* prev;
233 } th_list;
236 // have to be cleared by GARBAGE COLLECTOR
237 //static unsigned char* heap=NULL;
238 //static int heap_counter=0;
239 static tls_t* g_tls=NULL;
240 static th_list* list=NULL;
242 #if 0
243 static void test_heap(void)
245 int offset=0;
246 if(heap==0)
247 return;
248 while(offset<heap_counter)
250 if(*(int*)(heap+offset)!=0x433476)
252 printf("Heap corruption at address %d\n", offset);
253 return;
255 offset+=8+*(int*)(heap+offset+4);
257 for(;offset<min(offset+1000, 20000000); offset++)
258 if(heap[offset]!=0xCC)
260 printf("Free heap corruption at address %d\n", offset);
263 #endif
264 #undef MEMORY_DEBUG
266 #ifdef MEMORY_DEBUG
268 static void* my_mreq(int size, int to_zero)
270 static int test=0;
271 test++;
272 if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
273 // test_heap();
274 if(heap==NULL)
276 heap=malloc(20000000);
277 memset(heap, 0xCC,20000000);
279 if(heap==0)
281 printf("No enough memory\n");
282 return 0;
284 if(heap_counter+size>20000000)
286 printf("No enough memory\n");
287 return 0;
289 *(int*)(heap+heap_counter)=0x433476;
290 heap_counter+=4;
291 *(int*)(heap+heap_counter)=size;
292 heap_counter+=4;
293 printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
294 if(to_zero)
295 memset(heap+heap_counter, 0, size);
296 else
297 memset(heap+heap_counter, 0xcc, size); // make crash reproducable
298 heap_counter+=size;
299 return heap+heap_counter-size;
301 static int my_release(char* memory)
303 // test_heap();
304 if(memory==NULL)
306 printf("ERROR: free(0)\n");
307 return 0;
309 if(*(int*)(memory-8)!=0x433476)
311 printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
312 return 0;
314 printf("Freed %d bytes of memory\n", *(int*)(memory-4));
315 // memset(memory-8, *(int*)(memory-4), 0xCC);
316 return 0;
319 #else
320 #define GARBAGE
321 typedef struct alloc_header_t alloc_header;
322 struct alloc_header_t
324 // let's keep allocated data 16 byte aligned
325 alloc_header* prev;
326 alloc_header* next;
327 long deadbeef;
328 long size;
329 long type;
330 long reserved1;
331 long reserved2;
332 long reserved3;
335 #ifdef GARBAGE
336 static alloc_header* last_alloc = NULL;
337 static int alccnt = 0;
338 #endif
340 #define AREATYPE_CLIENT 0
341 #define AREATYPE_EVENT 1
342 #define AREATYPE_MUTEX 2
343 #define AREATYPE_COND 3
344 #define AREATYPE_CRITSECT 4
346 /* -- critical sections -- */
347 struct CRITSECT
349 pthread_t id;
350 pthread_mutex_t mutex;
351 int locked;
352 long deadbeef;
355 void* mreq_private(int size, int to_zero, int type);
356 void* mreq_private(int size, int to_zero, int type)
358 int nsize = size + sizeof(alloc_header);
359 alloc_header* header = (alloc_header* ) malloc(nsize);
360 if (!header)
361 return 0;
362 if (to_zero)
363 memset(header, 0, nsize);
364 #ifdef GARBAGE
365 if (!last_alloc)
367 pthread_mutex_init(&memmut, NULL);
368 pthread_mutex_lock(&memmut);
370 else
372 pthread_mutex_lock(&memmut);
373 last_alloc->next = header; /* set next */
376 header->prev = last_alloc;
377 header->next = 0;
378 last_alloc = header;
379 alccnt++;
380 pthread_mutex_unlock(&memmut);
381 #endif
382 header->deadbeef = 0xdeadbeef;
383 header->size = size;
384 header->type = type;
386 //if (alccnt < 40000) printf("MY_REQ: %p\t%d t:%d (cnt:%d)\n", header, size, type, alccnt);
387 return header + 1;
390 static int my_release(void* memory)
392 alloc_header* header = (alloc_header*) memory - 1;
393 #ifdef GARBAGE
394 alloc_header* prevmem;
395 alloc_header* nextmem;
397 if (memory == 0)
398 return 0;
400 if (header->deadbeef != (long) 0xdeadbeef)
402 dbgprintf("FATAL releasing corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
403 return 0;
406 pthread_mutex_lock(&memmut);
408 switch(header->type)
410 case AREATYPE_EVENT:
411 destroy_event(memory);
412 break;
413 case AREATYPE_COND:
414 pthread_cond_destroy((pthread_cond_t*)memory);
415 break;
416 case AREATYPE_MUTEX:
417 pthread_mutex_destroy((pthread_mutex_t*)memory);
418 break;
419 case AREATYPE_CRITSECT:
420 pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
421 break;
422 default:
423 //memset(memory, 0xcc, header->size);
427 header->deadbeef = 0;
428 prevmem = header->prev;
429 nextmem = header->next;
431 if (prevmem)
432 prevmem->next = nextmem;
433 if (nextmem)
434 nextmem->prev = prevmem;
436 if (header == last_alloc)
437 last_alloc = prevmem;
439 alccnt--;
441 if (last_alloc)
442 pthread_mutex_unlock(&memmut);
443 else
444 pthread_mutex_destroy(&memmut);
446 //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld (%d)\n", header, header->size, alccnt);
447 #else
448 if (memory == 0)
449 return 0;
450 #endif
451 //memset(header + 1, 0xcc, header->size);
452 free(header);
453 return 0;
455 #endif
457 static inline void* my_mreq(int size, int to_zero)
459 return mreq_private(size, to_zero, AREATYPE_CLIENT);
462 static int my_size(void* memory)
464 if(!memory) return 0;
465 return ((alloc_header*)memory)[-1].size;
468 static void* my_realloc(void* memory, int size)
470 void *ans = memory;
471 int osize;
472 if (memory == NULL)
473 return my_mreq(size, 0);
474 osize = my_size(memory);
475 if (osize < size)
477 ans = my_mreq(size, 0);
478 memcpy(ans, memory, osize);
479 my_release(memory);
481 return ans;
486 * WINE API - native implementation for several win32 libraries
490 static int WINAPI ext_unknown()
492 printf("Unknown func called\n");
493 return 0;
496 static int WINAPI expGetVolumeInformationA( const char *root, char *label,
497 unsigned int label_len, unsigned int *serial,
498 unsigned int *filename_len,unsigned int *flags,
499 char *fsname, unsigned int fsname_len )
501 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
502 root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
503 //hack Do not return any real data - do nothing
504 return 1;
507 static unsigned int WINAPI expGetDriveTypeA( const char *root )
509 dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
510 // hack return as Fixed Drive Type
511 return DRIVE_FIXED;
514 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
516 dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
517 // hack only have one drive c:\ in this hack
518 *buffer++='c';
519 *buffer++=':';
520 *buffer++='\\';
521 *buffer++='\0';
522 *buffer= '\0';
523 return 4; // 1 drive * 4 bytes (includes null)
527 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
529 int result = (count == 0 || ptr != 0) ? 0 : 1;
530 dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
531 return result;
533 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
535 int result = (count == 0 || ptr != 0) ? 0 : 1;
536 dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
537 return result;
539 static int WINAPI expDisableThreadLibraryCalls(int module)
541 dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
542 return 0;
545 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
547 HMODULE result;
548 if (pdrv==NULL)
549 result=0;
550 else
551 result=pdrv->hDriverModule;
552 dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
553 return result;
556 #define MODULE_HANDLE_kernel32 ((HMODULE)0x120)
557 #define MODULE_HANDLE_user32 ((HMODULE)0x121)
558 #ifdef QTX
559 #define MODULE_HANDLE_wininet ((HMODULE)0x122)
560 #define MODULE_HANDLE_ddraw ((HMODULE)0x123)
561 #define MODULE_HANDLE_advapi32 ((HMODULE)0x124)
562 #endif
563 #define MODULE_HANDLE_comdlg32 ((HMODULE)0x125)
564 #define MODULE_HANDLE_msvcrt ((HMODULE)0x126)
565 #define MODULE_HANDLE_ole32 ((HMODULE)0x127)
566 #define MODULE_HANDLE_winmm ((HMODULE)0x128)
568 static HMODULE WINAPI expGetModuleHandleA(const char* name)
570 WINE_MODREF* wm;
571 HMODULE result;
572 if(!name)
573 #ifdef QTX
574 result=1;
575 #else
576 result=0;
577 #endif
578 else
580 wm=MODULE_FindModule(name);
581 if(wm==0)result=0;
582 else
583 result=(HMODULE)(wm->module);
585 if(!result)
587 if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
588 result=MODULE_HANDLE_kernel32;
589 #ifdef QTX
590 if(name && strcasecmp(name, "user32")==0)
591 result=MODULE_HANDLE_user32;
592 #endif
594 dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
595 return result;
598 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
599 void* lpStartAddress, void* lpParameter,
600 long dwFlags, long* dwThreadId)
602 pthread_t *pth;
603 // printf("CreateThread:");
604 pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
605 pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
606 if(dwFlags)
607 printf( "WARNING: CreateThread flags not supported\n");
608 if(dwThreadId)
609 *dwThreadId=(long)pth;
610 if(list==NULL)
612 list=my_mreq(sizeof(th_list), 1);
613 list->next=list->prev=NULL;
615 else
617 list->next=my_mreq(sizeof(th_list), 0);
618 list->next->prev=list;
619 list->next->next=NULL;
620 list=list->next;
622 list->thread=pth;
623 dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
624 pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
625 return pth;
628 struct mutex_list_t;
630 struct mutex_list_t
632 char type;
633 pthread_mutex_t *pm;
634 pthread_cond_t *pc;
635 char state;
636 char reset;
637 char name[128];
638 int semaphore;
639 struct mutex_list_t* next;
640 struct mutex_list_t* prev;
642 typedef struct mutex_list_t mutex_list;
643 static mutex_list* mlist=NULL;
645 void destroy_event(void* event)
647 mutex_list* pp=mlist;
648 // printf("garbage collector: destroy_event(%x)\n", event);
649 while(pp)
651 if(pp==(mutex_list*)event)
653 if(pp->next)
654 pp->next->prev=pp->prev;
655 if(pp->prev)
656 pp->prev->next=pp->next;
657 if(mlist==(mutex_list*)event)
658 mlist=mlist->prev;
660 pp=mlist;
661 while(pp)
663 printf("%x => ", pp);
664 pp=pp->prev;
666 printf("0\n");
668 return;
670 pp=pp->prev;
674 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
675 char bInitialState, const char* name)
677 pthread_mutex_t *pm;
678 pthread_cond_t *pc;
680 mutex_list* pp;
681 pp=mlist;
682 while(pp)
684 printf("%x => ", pp);
685 pp=pp->prev;
687 printf("0\n");
689 if(mlist!=NULL)
691 mutex_list* pp=mlist;
692 if(name!=NULL)
695 if((strcmp(pp->name, name)==0) && (pp->type==0))
697 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
698 pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
699 return pp->pm;
701 }while((pp=pp->prev) != NULL);
703 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
704 pthread_mutex_init(pm, NULL);
705 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
706 pthread_cond_init(pc, NULL);
707 if(mlist==NULL)
709 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
710 mlist->next=mlist->prev=NULL;
712 else
714 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
715 mlist->next->prev=mlist;
716 mlist->next->next=NULL;
717 mlist=mlist->next;
719 mlist->type=0; /* Type Event */
720 mlist->pm=pm;
721 mlist->pc=pc;
722 mlist->state=bInitialState;
723 mlist->reset=bManualReset;
724 if(name)
725 strncpy(mlist->name, name, 127);
726 else
727 mlist->name[0]=0;
728 if(pm==NULL)
729 dbgprintf("ERROR::: CreateEventA failure\n");
731 if(bInitialState)
732 pthread_mutex_lock(pm);
734 if(name)
735 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
736 pSecAttr, bManualReset, bInitialState, name, name, mlist);
737 else
738 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
739 pSecAttr, bManualReset, bInitialState, mlist);
740 return mlist;
743 static void* WINAPI expSetEvent(void* event)
745 mutex_list *ml = (mutex_list *)event;
746 dbgprintf("SetEvent(%x) => 0x1\n", event);
747 pthread_mutex_lock(ml->pm);
748 if (ml->state == 0) {
749 ml->state = 1;
750 pthread_cond_signal(ml->pc);
752 pthread_mutex_unlock(ml->pm);
754 return (void *)1;
756 static void* WINAPI expResetEvent(void* event)
758 mutex_list *ml = (mutex_list *)event;
759 dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
760 pthread_mutex_lock(ml->pm);
761 ml->state = 0;
762 pthread_mutex_unlock(ml->pm);
764 return (void *)1;
767 static void* WINAPI expWaitForSingleObject(void* object, int duration)
769 mutex_list *ml = (mutex_list *)object;
770 // FIXME FIXME FIXME - this value is sometime unititialize !!!
771 int ret = WAIT_FAILED;
772 mutex_list* pp=mlist;
773 if(object == (void*)0xcfcf9898)
776 From GetCurrentThread() documentation:
777 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.
779 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.
781 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.
783 dbgprintf("WaitForSingleObject(thread_handle) called\n");
784 return (void*)WAIT_FAILED;
786 dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
788 // loop below was slightly fixed - its used just for checking if
789 // this object really exists in our list
790 if (!ml)
791 return (void*) ret;
792 while (pp && (pp->pm != ml->pm))
793 pp = pp->prev;
794 if (!pp) {
795 dbgprintf("WaitForSingleObject: NotFound\n");
796 return (void*)ret;
799 pthread_mutex_lock(ml->pm);
801 switch(ml->type) {
802 case 0: /* Event */
803 if (duration == 0) { /* Check Only */
804 if (ml->state == 1) ret = WAIT_FAILED;
805 else ret = WAIT_OBJECT_0;
807 if (duration == -1) { /* INFINITE */
808 if (ml->state == 0)
809 pthread_cond_wait(ml->pc,ml->pm);
810 if (ml->reset)
811 ml->state = 0;
812 ret = WAIT_OBJECT_0;
814 if (duration > 0) { /* Timed Wait */
815 struct timespec abstime;
816 struct timeval now;
817 gettimeofday(&now, 0);
818 abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
819 abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
820 if (ml->state == 0)
821 ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
822 if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
823 else ret = WAIT_OBJECT_0;
824 if (ml->reset)
825 ml->state = 0;
827 break;
828 case 1: /* Semaphore */
829 if (duration == 0) {
830 if(ml->semaphore==0) ret = WAIT_FAILED;
831 else {
832 ml->semaphore++;
833 ret = WAIT_OBJECT_0;
836 if (duration == -1) {
837 if (ml->semaphore==0)
838 pthread_cond_wait(ml->pc,ml->pm);
839 ml->semaphore--;
841 break;
843 pthread_mutex_unlock(ml->pm);
845 dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
846 return (void *)ret;
849 #ifdef QTX
850 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
851 int WaitAll, int duration)
853 int i;
854 void *object;
855 void *ret;
857 dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
858 count, objects, WaitAll, duration);
860 for (i = 0; i < count; i++)
862 object = (void *)objects[i];
863 ret = expWaitForSingleObject(object, duration);
864 if (WaitAll)
865 dbgprintf("WaitAll flag not yet supported...\n");
866 else
867 return ret;
869 return NULL;
872 static void WINAPI expExitThread(int retcode)
874 dbgprintf("ExitThread(%d)\n", retcode);
875 pthread_exit(&retcode);
878 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
879 char bInitialOwner, const char *name)
881 HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
883 if (name)
884 dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
885 pSecAttr, bInitialOwner, name, mlist);
886 else
887 dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
888 pSecAttr, bInitialOwner, mlist);
889 #ifndef QTX
890 /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
891 waits for ever, else it works ;) */
892 return mlist;
893 #endif
896 static int WINAPI expReleaseMutex(HANDLE hMutex)
898 dbgprintf("ReleaseMutex(%x) => 1\n", hMutex);
899 /* FIXME:XXX !! not yet implemented */
900 return 1;
902 #endif
904 static int pf_set = 0;
905 static BYTE PF[64] = {0,};
907 static void DumpSystemInfo(const SYSTEM_INFO* si)
909 dbgprintf(" Processor architecture %d\n", si->u.s.wProcessorArchitecture);
910 dbgprintf(" Page size: %d\n", si->dwPageSize);
911 dbgprintf(" Minimum app address: %d\n", si->lpMinimumApplicationAddress);
912 dbgprintf(" Maximum app address: %d\n", si->lpMaximumApplicationAddress);
913 dbgprintf(" Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
914 dbgprintf(" Number of processors: %d\n", si->dwNumberOfProcessors);
915 dbgprintf(" Processor type: 0x%x\n", si->dwProcessorType);
916 dbgprintf(" Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
917 dbgprintf(" Processor level: 0x%x\n", si->wProcessorLevel);
918 dbgprintf(" Processor revision: 0x%x\n", si->wProcessorRevision);
921 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
923 /* FIXME: better values for the two entries below... */
924 static int cache = 0;
925 static SYSTEM_INFO cachedsi;
926 dbgprintf("GetSystemInfo(%p) =>\n", si);
928 if (cache) {
929 goto exit;
931 memset(PF,0,sizeof(PF));
932 pf_set = 1;
934 cachedsi.u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
935 cachedsi.dwPageSize = getpagesize();
937 /* FIXME: better values for the two entries below... */
938 cachedsi.lpMinimumApplicationAddress = (void *)0x00000000;
939 cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
940 cachedsi.dwActiveProcessorMask = 1;
941 cachedsi.dwNumberOfProcessors = 1;
942 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
943 cachedsi.dwAllocationGranularity = 0x10000;
944 cachedsi.wProcessorLevel = 5; /* pentium */
945 cachedsi.wProcessorRevision = 0x0101;
947 /* mplayer's way to detect PF's */
949 #include "cpudetect.h"
951 if (gCpuCaps.hasMMX)
952 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
953 if (gCpuCaps.hasSSE)
954 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
955 if (gCpuCaps.hasSSE2)
956 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
957 if (gCpuCaps.has3DNow)
958 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
960 if (gCpuCaps.cpuType == 4)
962 cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
963 cachedsi.wProcessorLevel = 4;
965 else if (gCpuCaps.cpuType >= 5)
967 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
968 cachedsi.wProcessorLevel = 5;
970 else
972 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
973 cachedsi.wProcessorLevel = 3;
975 cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
976 cachedsi.dwNumberOfProcessors = 1; /* hardcoded */
979 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
980 fdiv_bug and fpu emulation flags -- alex/MPlayer */
981 #ifdef __linux__
983 char buf[20];
984 char line[200];
985 FILE *f = fopen ("/proc/cpuinfo", "r");
987 if (!f)
989 mp_msg(MSGT_WIN32, MSGL_WARN, "expGetSystemInfo: "
990 "/proc/cpuinfo not readable! "
991 "Expect bad performance and/or weird behaviour\n");
992 goto exit;
994 while (fgets(line,200,f)!=NULL) {
995 char *s,*value;
997 /* NOTE: the ':' is the only character we can rely on */
998 if (!(value = strchr(line,':')))
999 continue;
1000 /* terminate the valuename */
1001 *value++ = '\0';
1002 /* skip any leading spaces */
1003 while (*value==' ') value++;
1004 if ((s=strchr(value,'\n')))
1005 *s='\0';
1007 /* 2.1 method */
1008 if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
1009 if (isdigit (value[0])) {
1010 switch (value[0] - '0') {
1011 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1012 cachedsi.wProcessorLevel= 3;
1013 break;
1014 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1015 cachedsi.wProcessorLevel= 4;
1016 break;
1017 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1018 cachedsi.wProcessorLevel= 5;
1019 break;
1020 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1021 cachedsi.wProcessorLevel= 5;
1022 break;
1023 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1024 cachedsi.wProcessorLevel= 5;
1025 break;
1028 /* set the CPU type of the current processor */
1029 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1030 continue;
1032 /* old 2.0 method */
1033 if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
1034 if ( isdigit (value[0]) && value[1] == '8' &&
1035 value[2] == '6' && value[3] == 0
1037 switch (value[0] - '0') {
1038 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1039 cachedsi.wProcessorLevel= 3;
1040 break;
1041 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1042 cachedsi.wProcessorLevel= 4;
1043 break;
1044 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1045 cachedsi.wProcessorLevel= 5;
1046 break;
1047 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1048 cachedsi.wProcessorLevel= 5;
1049 break;
1050 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1051 cachedsi.wProcessorLevel= 5;
1052 break;
1055 /* set the CPU type of the current processor */
1056 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1057 continue;
1059 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
1060 if (!lstrncmpiA(value,"yes",3))
1061 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
1063 continue;
1065 if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
1066 if (!lstrncmpiA(value,"no",2))
1067 PF[PF_FLOATING_POINT_EMULATED] = TRUE;
1069 continue;
1071 if (!lstrncmpiA(line,"processor",strlen("processor"))) {
1072 /* processor number counts up...*/
1073 unsigned int x;
1075 if (sscanf(value,"%d",&x))
1076 if (x+1>cachedsi.dwNumberOfProcessors)
1077 cachedsi.dwNumberOfProcessors=x+1;
1079 /* Create a new processor subkey on a multiprocessor
1080 * system
1082 sprintf(buf,"%d",x);
1084 if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
1085 int x;
1087 if (sscanf(value,"%d",&x))
1088 cachedsi.wProcessorRevision = x;
1091 ( (!lstrncmpiA(line,"flags",strlen("flags")))
1092 || (!lstrncmpiA(line,"features",strlen("features"))) )
1094 if (strstr(value,"cx8"))
1095 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1096 if (strstr(value,"mmx"))
1097 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1098 if (strstr(value,"tsc"))
1099 PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
1100 if (strstr(value,"xmm") || strstr(value,"sse"))
1101 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1102 if (strstr(value,"sse2"))
1103 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
1104 if (strstr(value,"3dnow"))
1105 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1108 fclose (f);
1110 * ad hoc fix for smp machines.
1111 * some problems on WaitForSingleObject,CreateEvent,SetEvent
1112 * CreateThread ...etc..
1115 cachedsi.dwNumberOfProcessors=1;
1117 #endif /* __linux__ */
1118 cache = 1;
1119 exit:
1120 memcpy(si,&cachedsi,sizeof(*si));
1121 DumpSystemInfo(si);
1124 // avoid undefined expGetSystemInfo
1125 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
1127 WIN_BOOL result = 0;
1128 if (!pf_set)
1130 SYSTEM_INFO si;
1131 expGetSystemInfo(&si);
1133 if(v<64) result=PF[v];
1134 dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
1135 return result;
1139 static long WINAPI expGetVersion()
1141 dbgprintf("GetVersion() => 0xC0000004\n");
1142 return 0xC0000004;//Windows 95
1145 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
1147 // printf("HeapCreate:");
1148 HANDLE result;
1149 if(init_size==0)
1150 result=(HANDLE)my_mreq(0x110000, 0);
1151 else
1152 result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
1153 dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
1154 return result;
1157 // this is another dirty hack
1158 // VP31 is releasing one allocated Heap chunk twice
1159 // we will silently ignore this second call...
1160 static void* heapfreehack = 0;
1161 static int heapfreehackshown = 0;
1162 //void trapbug(void);
1163 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
1165 void* z;
1167 Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
1168 HeapAlloc returns area larger than size argument :-/
1170 actually according to M$ Doc HeapCreate size should be rounded
1171 to page boundaries thus we should simulate this
1173 //if (size == 22276) trapbug();
1174 z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
1175 if(z==0)
1176 printf("HeapAlloc failure\n");
1177 dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
1178 heapfreehack = 0; // reset
1179 return z;
1181 static long WINAPI expHeapDestroy(void* heap)
1183 dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
1184 my_release(heap);
1185 return 1;
1188 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
1190 dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
1191 if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
1192 && lpMem != (void*)0xbdbdbdbd)
1193 // 0xbdbdbdbd is for i263_drv.drv && libefence
1194 // it seems to be reading from relased memory
1195 // EF_PROTECT_FREE doens't show any probleme
1196 my_release(lpMem);
1197 else
1199 if (!heapfreehackshown++)
1200 printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
1202 heapfreehack = lpMem;
1203 return 1;
1205 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
1207 long result=my_size(pointer);
1208 dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
1209 return result;
1211 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
1213 long orgsize = my_size(lpMem);
1214 dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
1215 return my_realloc(lpMem, size);
1217 static long WINAPI expGetProcessHeap(void)
1219 dbgprintf("GetProcessHeap() => 1\n");
1220 return 1;
1222 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
1224 void* z = VirtualAlloc(v1, v2, v3, v4);
1225 if(z==0)
1226 printf("VirtualAlloc failure\n");
1227 dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
1228 return z;
1230 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
1232 int result = VirtualFree(v1,v2,v3);
1233 dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
1234 return result;
1237 /* we're building a table of critical sections. cs_win pointer uses the DLL
1238 cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
1239 struct critsecs_list_t
1241 CRITICAL_SECTION *cs_win;
1242 struct CRITSECT *cs_unix;
1245 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
1246 #undef CRITSECS_NEWTYPE
1247 //#define CRITSECS_NEWTYPE 1
1249 #ifdef CRITSECS_NEWTYPE
1250 /* increased due to ucod needs more than 32 entries */
1251 /* and 64 should be enough for everything */
1252 #define CRITSECS_LIST_MAX 64
1253 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
1255 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
1257 int i;
1259 for (i=0; i < CRITSECS_LIST_MAX; i++)
1260 if (critsecs_list[i].cs_win == cs_win)
1261 return i;
1262 return -1;
1265 static int critsecs_get_unused(void)
1267 int i;
1269 for (i=0; i < CRITSECS_LIST_MAX; i++)
1270 if (critsecs_list[i].cs_win == NULL)
1271 return i;
1272 return -1;
1275 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
1277 int i;
1279 for (i=0; i < CRITSECS_LIST_MAX; i++)
1280 if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
1281 return critsecs_list[i].cs_unix;
1282 return NULL;
1284 #endif
1286 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
1288 dbgprintf("InitializeCriticalSection(0x%x)\n", c);
1289 /* if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
1291 printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
1292 sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
1293 return;
1295 /* pthread_mutex_init((pthread_mutex_t*)c, NULL); */
1296 #ifdef CRITSECS_NEWTYPE
1298 struct CRITSECT *cs;
1299 int i = critsecs_get_unused();
1301 if (i < 0)
1303 printf("InitializeCriticalSection(%p) - no more space in list\n", c);
1304 return;
1306 dbgprintf("got unused space at %d\n", i);
1307 cs = malloc(sizeof(struct CRITSECT));
1308 if (!cs)
1310 printf("InitializeCriticalSection(%p) - out of memory\n", c);
1311 return;
1313 pthread_mutex_init(&cs->mutex, NULL);
1314 cs->locked = 0;
1315 critsecs_list[i].cs_win = c;
1316 critsecs_list[i].cs_unix = cs;
1317 dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
1318 i, c, cs);
1320 #else
1322 struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
1323 0, AREATYPE_CRITSECT);
1324 pthread_mutex_init(&cs->mutex, NULL);
1325 cs->locked=0;
1326 cs->deadbeef = 0xdeadbeef;
1327 *(void**)c = cs;
1329 #endif
1330 return;
1333 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
1335 #ifdef CRITSECS_NEWTYPE
1336 struct CRITSECT* cs = critsecs_get_unix(c);
1337 #else
1338 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1339 #endif
1340 dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
1341 if (!cs)
1343 dbgprintf("entered uninitialized critisec!\n");
1344 expInitializeCriticalSection(c);
1345 #ifdef CRITSECS_NEWTYPE
1346 cs=critsecs_get_unix(c);
1347 #else
1348 cs = (*(struct CRITSECT**)c);
1349 #endif
1350 dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
1352 if(cs->locked)
1353 if(cs->id==pthread_self())
1354 return;
1355 pthread_mutex_lock(&(cs->mutex));
1356 cs->locked=1;
1357 cs->id=pthread_self();
1358 return;
1360 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
1362 #ifdef CRITSECS_NEWTYPE
1363 struct CRITSECT* cs = critsecs_get_unix(c);
1364 #else
1365 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1366 #endif
1367 // struct CRITSECT* cs=(struct CRITSECT*)c;
1368 dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
1369 if (!cs)
1371 dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
1372 return;
1374 if (cs->locked)
1376 cs->locked=0;
1377 pthread_mutex_unlock(&(cs->mutex));
1379 else
1380 dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
1381 return;
1384 static void expfree(void* mem); /* forward declaration */
1386 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
1388 #ifdef CRITSECS_NEWTYPE
1389 struct CRITSECT* cs = critsecs_get_unix(c);
1390 #else
1391 struct CRITSECT* cs= (*(struct CRITSECT**)c);
1392 #endif
1393 // struct CRITSECT* cs=(struct CRITSECT*)c;
1394 dbgprintf("DeleteCriticalSection(0x%x)\n",c);
1396 if (!cs)
1398 dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
1399 return;
1402 if (cs->locked)
1404 dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
1405 pthread_mutex_unlock(&(cs->mutex));
1408 #ifndef GARBAGE
1409 pthread_mutex_destroy(&(cs->mutex));
1410 // released by GarbageCollector in my_relase otherwise
1411 #endif
1412 my_release(cs);
1413 #ifdef CRITSECS_NEWTYPE
1415 int i = critsecs_get_pos(c);
1417 if (i < 0)
1419 printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
1420 return;
1423 critsecs_list[i].cs_win = NULL;
1424 expfree(critsecs_list[i].cs_unix);
1425 critsecs_list[i].cs_unix = NULL;
1426 dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
1428 #endif
1429 return;
1431 static int WINAPI expGetCurrentThreadId()
1433 dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
1434 return pthread_self();
1436 static int WINAPI expGetCurrentProcess()
1438 dbgprintf("GetCurrentProcess() => %d\n", getpid());
1439 return getpid();
1442 #ifdef QTX
1443 // this version is required for Quicktime codecs (.qtx/.qts) to work.
1444 // (they assume some pointers at FS: segment)
1446 extern void* fs_seg;
1448 //static int tls_count;
1449 static int tls_use_map[64];
1450 static int WINAPI expTlsAlloc()
1452 int i;
1453 for(i=0; i<64; i++)
1454 if(tls_use_map[i]==0)
1456 tls_use_map[i]=1;
1457 dbgprintf("TlsAlloc() => %d\n",i);
1458 return i;
1460 dbgprintf("TlsAlloc() => -1 (ERROR)\n");
1461 return -1;
1464 //static int WINAPI expTlsSetValue(DWORD index, void* value)
1465 static int WINAPI expTlsSetValue(int index, void* value)
1467 dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
1468 // if((index<0) || (index>64))
1469 if((index>=64))
1470 return 0;
1471 *(void**)((char*)fs_seg+0x88+4*index) = value;
1472 return 1;
1475 static void* WINAPI expTlsGetValue(DWORD index)
1477 dbgprintf("TlsGetValue(%d)\n",index);
1478 // if((index<0) || (index>64))
1479 if((index>=64)) return NULL;
1480 return *(void**)((char*)fs_seg+0x88+4*index);
1483 static int WINAPI expTlsFree(int idx)
1485 int index = (int) idx;
1486 dbgprintf("TlsFree(%d)\n",index);
1487 if((index<0) || (index>64))
1488 return 0;
1489 tls_use_map[index]=0;
1490 return 1;
1493 #else
1494 struct tls_s {
1495 void* value;
1496 int used;
1497 struct tls_s* prev;
1498 struct tls_s* next;
1501 static void* WINAPI expTlsAlloc()
1503 if (g_tls == NULL)
1505 g_tls=my_mreq(sizeof(tls_t), 0);
1506 g_tls->next=g_tls->prev=NULL;
1508 else
1510 g_tls->next=my_mreq(sizeof(tls_t), 0);
1511 g_tls->next->prev=g_tls;
1512 g_tls->next->next=NULL;
1513 g_tls=g_tls->next;
1515 dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
1516 if (g_tls)
1517 g_tls->value=0; /* XXX For Divx.dll */
1518 return g_tls;
1521 static int WINAPI expTlsSetValue(void* idx, void* value)
1523 tls_t* index = (tls_t*) idx;
1524 int result;
1525 if(index==0)
1526 result=0;
1527 else
1529 index->value=value;
1530 result=1;
1532 dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
1533 return result;
1535 static void* WINAPI expTlsGetValue(void* idx)
1537 tls_t* index = (tls_t*) idx;
1538 void* result;
1539 if(index==0)
1540 result=0;
1541 else
1542 result=index->value;
1543 dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
1544 return result;
1546 static int WINAPI expTlsFree(void* idx)
1548 tls_t* index = (tls_t*) idx;
1549 int result;
1550 if(index==0)
1551 result=0;
1552 else
1554 if(index->next)
1555 index->next->prev=index->prev;
1556 if(index->prev)
1557 index->prev->next=index->next;
1558 if (g_tls == index)
1559 g_tls = index->prev;
1560 my_release((void*)index);
1561 result=1;
1563 dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
1564 return result;
1566 #endif
1568 static void* WINAPI expLocalAlloc(int flags, int size)
1570 void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
1571 if (z == 0)
1572 printf("LocalAlloc() failed\n");
1573 dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1574 return z;
1577 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
1579 void *newpointer;
1580 int oldsize;
1582 newpointer=NULL;
1583 if (flags & LMEM_MODIFY) {
1584 dbgprintf("LocalReAlloc MODIFY\n");
1585 return (void *)handle;
1587 oldsize = my_size((void *)handle);
1588 newpointer = my_realloc((void *)handle,size);
1589 dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
1591 return newpointer;
1594 static void* WINAPI expLocalLock(void* z)
1596 dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
1597 return z;
1600 static void* WINAPI expGlobalAlloc(int flags, int size)
1602 void* z;
1603 dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
1605 z=my_mreq(size, (flags & GMEM_ZEROINIT));
1606 //z=calloc(size, 1);
1607 //z=malloc(size);
1608 if(z==0)
1609 printf("GlobalAlloc() failed\n");
1610 dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1611 return z;
1613 static void* WINAPI expGlobalLock(void* z)
1615 dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
1616 return z;
1618 // pvmjpg20 - but doesn't work anyway
1619 static int WINAPI expGlobalSize(void* amem)
1621 int size = 100000;
1622 #ifdef GARBAGE
1623 alloc_header* header = last_alloc;
1624 alloc_header* mem = (alloc_header*) amem - 1;
1625 if (amem == 0)
1626 return 0;
1627 pthread_mutex_lock(&memmut);
1628 while (header)
1630 if (header->deadbeef != 0xdeadbeef)
1632 dbgprintf("FATAL found corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
1633 break;
1636 if (header == mem)
1638 size = header->size;
1639 break;
1642 header = header->prev;
1644 pthread_mutex_unlock(&memmut);
1645 #endif
1647 dbgprintf("GlobalSize(0x%x)\n", amem);
1648 return size;
1651 static int WINAPI expLoadIconA( long hinstance, char *name )
1653 dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
1654 return 1;
1657 static int WINAPI expLoadStringA(long instance, long id, void* buf, long size)
1659 int result=LoadStringA(instance, id, buf, size);
1660 // if(buf)
1661 dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
1662 instance, id, buf, size, result, buf);
1663 // else
1664 // dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
1665 // instance, id, buf, size, result);
1666 return result;
1669 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
1671 #warning FIXME
1672 int i;
1673 int result;
1674 if(s2==0)
1675 result=1;
1676 else
1678 if(siz1>siz2/2)siz1=siz2/2;
1679 for(i=1; i<=siz1; i++)
1681 *s2=*s1;
1682 if(!*s1)break;
1683 s2++;
1684 s1++;
1686 result=i;
1688 if(s1)
1689 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
1690 "size %d, dest buffer 0x%x, dest size %d) => %d\n",
1691 v1, v2, s1, s1, siz1, s2, siz2, result);
1692 else
1693 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
1694 "size %d, dest buffer 0x%x, dest size %d) =>\n",
1695 v1, v2, siz1, s2, siz2, result);
1696 return result;
1698 static void wch_print(const short* str)
1700 dbgprintf(" src: ");
1701 while(*str)dbgprintf("%c", *str++);
1702 dbgprintf("\n");
1704 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
1705 char* s2, int siz2, char* c3, int* siz3)
1707 int result;
1708 dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
1709 "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
1710 result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
1711 dbgprintf("=> %d\n", result);
1712 //if(s1)wch_print(s1);
1713 if(s2)dbgprintf(" dest: %s\n", s2);
1714 return result;
1716 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
1718 dbgprintf("GetVersionExA(0x%x) => 1\n");
1719 c->dwOSVersionInfoSize=sizeof(*c);
1720 c->dwMajorVersion=4;
1721 c->dwMinorVersion=0;
1722 c->dwBuildNumber=0x4000457;
1723 #if 1
1724 // leave it here for testing win9x-only codecs
1725 c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
1726 strcpy(c->szCSDVersion, " B");
1727 #else
1728 c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
1729 strcpy(c->szCSDVersion, "Service Pack 3");
1730 #endif
1731 dbgprintf(" Major version: 4\n Minor version: 0\n Build number: 0x4000457\n"
1732 " Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 3'\n");
1733 return 1;
1735 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
1736 long max_count, char* name)
1738 pthread_mutex_t *pm;
1739 pthread_cond_t *pc;
1741 mutex_list* pp;
1742 printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
1743 pp=mlist;
1744 while(pp)
1746 printf("%p => ", pp);
1747 pp=pp->prev;
1749 printf("0\n");
1751 if(mlist!=NULL)
1753 mutex_list* pp=mlist;
1754 if(name!=NULL)
1757 if((strcmp(pp->name, name)==0) && (pp->type==1))
1759 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1760 v1, init_count, max_count, name, name, mlist);
1761 return (HANDLE)mlist;
1763 }while((pp=pp->prev) != NULL);
1765 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1766 pthread_mutex_init(pm, NULL);
1767 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1768 pthread_cond_init(pc, NULL);
1769 if(mlist==NULL)
1771 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1772 mlist->next=mlist->prev=NULL;
1774 else
1776 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1777 mlist->next->prev=mlist;
1778 mlist->next->next=NULL;
1779 mlist=mlist->next;
1780 // printf("new semaphore %p\n", mlist);
1782 mlist->type=1; /* Type Semaphore */
1783 mlist->pm=pm;
1784 mlist->pc=pc;
1785 mlist->state=0;
1786 mlist->reset=0;
1787 mlist->semaphore=init_count;
1788 if(name!=NULL)
1789 strncpy(mlist->name, name, 64);
1790 else
1791 mlist->name[0]=0;
1792 if(pm==NULL)
1793 dbgprintf("ERROR::: CreateSemaphoreA failure\n");
1794 if(name)
1795 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1796 v1, init_count, max_count, name, name, mlist);
1797 else
1798 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
1799 v1, init_count, max_count, mlist);
1800 return (HANDLE)mlist;
1803 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
1805 // The state of a semaphore object is signaled when its count
1806 // is greater than zero and nonsignaled when its count is equal to zero
1807 // Each time a waiting thread is released because of the semaphore's signaled
1808 // state, the count of the semaphore is decreased by one.
1809 mutex_list *ml = (mutex_list *)hsem;
1811 pthread_mutex_lock(ml->pm);
1812 if (prev_count != 0) *prev_count = ml->semaphore;
1813 if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
1814 ml->semaphore += increment;
1815 pthread_mutex_unlock(ml->pm);
1816 dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
1817 hsem, increment, prev_count);
1818 return 1;
1822 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
1824 long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
1825 dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
1826 key, subkey, reserved, access, newkey, result);
1827 if(newkey)dbgprintf(" New key: 0x%x\n", *newkey);
1828 return result;
1830 static long WINAPI expRegCloseKey(long key)
1832 long result=RegCloseKey(key);
1833 dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
1834 return result;
1836 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
1838 long result=RegQueryValueExA(key, value, reserved, type, data, count);
1839 dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
1840 " => 0x%x\n", key, value, reserved, data, count, result);
1841 if(data && count)dbgprintf(" read %d bytes: '%s'\n", *count, data);
1842 return result;
1845 //from wine source dlls/advapi32/registry.c
1846 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
1848 dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
1849 return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
1850 KEY_ALL_ACCESS , NULL, retkey, NULL );
1853 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
1854 void* classs, long options, long security,
1855 void* sec_attr, int* newkey, int* status)
1857 long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
1858 dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
1859 " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
1860 key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
1861 if(!result && newkey) dbgprintf(" New key: 0x%x\n", *newkey);
1862 if(!result && status) dbgprintf(" New key status: 0x%x\n", *status);
1863 return result;
1865 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
1867 long result=RegSetValueExA(key, name, v1, v2, data, size);
1868 dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
1869 key, name, v1, v2, data, *(int*)data, data, size, result);
1870 return result;
1873 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
1875 long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
1876 dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
1877 hKey, lpSubKey, phkResult, result);
1878 if(!result && phkResult) dbgprintf(" New key: 0x%x\n", *phkResult);
1879 return result;
1882 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1883 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
1885 return RegEnumValueA(hkey, index, value, val_count,
1886 reserved, type, data, count);
1889 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
1890 LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
1891 LPFILETIME lpftLastWriteTime)
1893 return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
1894 lpcbClass, lpftLastWriteTime);
1897 static long WINAPI expQueryPerformanceCounter(long long* z)
1899 longcount(z);
1900 dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
1901 return 1;
1905 * dummy function RegQueryInfoKeyA(), required by vss codecs
1907 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
1908 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
1909 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
1910 LPDWORD security, FILETIME *modif )
1912 return ERROR_SUCCESS;
1916 * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
1918 static double linux_cpuinfo_freq()
1920 double freq=-1;
1921 FILE *f;
1922 char line[200];
1923 char *s,*value;
1925 f = fopen ("/proc/cpuinfo", "r");
1926 if (f != NULL) {
1927 while (fgets(line,sizeof(line),f)!=NULL) {
1928 /* NOTE: the ':' is the only character we can rely on */
1929 if (!(value = strchr(line,':')))
1930 continue;
1931 /* terminate the valuename */
1932 *value++ = '\0';
1933 /* skip any leading spaces */
1934 while (*value==' ') value++;
1935 if ((s=strchr(value,'\n')))
1936 *s='\0';
1938 if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
1939 && sscanf(value, "%lf", &freq) == 1) {
1940 freq*=1000;
1941 break;
1944 fclose(f);
1946 return freq;
1950 static double solaris_kstat_freq()
1952 #if defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
1954 * try to extract the CPU speed from the solaris kernel's kstat data
1956 kstat_ctl_t *kc;
1957 kstat_t *ksp;
1958 kstat_named_t *kdata;
1959 int mhz = 0;
1961 kc = kstat_open();
1962 if (kc != NULL)
1964 ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
1966 /* kstat found and name/value pairs? */
1967 if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
1969 /* read the kstat data from the kernel */
1970 if (kstat_read(kc, ksp, NULL) != -1)
1973 * lookup desired "clock_MHz" entry, check the expected
1974 * data type
1976 kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
1977 if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
1978 mhz = kdata->value.i32;
1981 kstat_close(kc);
1984 if (mhz > 0)
1985 return mhz * 1000.;
1986 #endif /* HAVE_LIBKSTAT */
1987 return -1; // kstat stuff is not available, CPU freq is unknown
1991 * Measure CPU freq using the pentium's time stamp counter register (TSC)
1993 static double tsc_freq()
1995 static double ofreq=0.0;
1996 int i;
1997 int x,y;
1998 i=time(NULL);
1999 if (ofreq != 0.0) return ofreq;
2000 while(i==time(NULL));
2001 x=localcount();
2002 i++;
2003 while(i==time(NULL));
2004 y=localcount();
2005 ofreq = (double)(y-x)/1000.;
2006 return ofreq;
2009 static double CPU_Freq()
2011 double freq;
2013 if ((freq = linux_cpuinfo_freq()) > 0)
2014 return freq;
2016 if ((freq = solaris_kstat_freq()) > 0)
2017 return freq;
2019 return tsc_freq();
2022 static long WINAPI expQueryPerformanceFrequency(long long* z)
2024 *z=(long long)CPU_Freq();
2025 dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
2026 return 1;
2028 static long WINAPI exptimeGetTime()
2030 struct timeval t;
2031 long result;
2032 gettimeofday(&t, 0);
2033 result=1000*t.tv_sec+t.tv_usec/1000;
2034 dbgprintf("timeGetTime() => %d\n", result);
2035 return result;
2037 static void* WINAPI expLocalHandle(void* v)
2039 dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
2040 return v;
2043 static void* WINAPI expGlobalHandle(void* v)
2045 dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
2046 return v;
2048 static int WINAPI expGlobalUnlock(void* v)
2050 dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
2051 return 1;
2053 static void* WINAPI expGlobalFree(void* v)
2055 dbgprintf("GlobalFree(0x%x) => 0\n", v);
2056 my_release(v);
2057 //free(v);
2058 return 0;
2061 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
2063 void* result=my_realloc(v, size);
2064 //void* result=realloc(v, size);
2065 dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
2066 return result;
2069 static int WINAPI expLocalUnlock(void* v)
2071 dbgprintf("LocalUnlock(0x%x) => 1\n", v);
2072 return 1;
2075 static void* WINAPI expLocalFree(void* v)
2077 dbgprintf("LocalFree(0x%x) => 0\n", v);
2078 my_release(v);
2079 return 0;
2081 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
2083 HRSRC result;
2085 result=FindResourceA(module, name, type);
2086 dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
2087 module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
2088 return result;
2091 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
2093 HGLOBAL result=LoadResource(module, res);
2094 dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
2095 return result;
2097 static void* WINAPI expLockResource(long res)
2099 void* result=LockResource(res);
2100 dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
2101 return result;
2103 static int WINAPI expFreeResource(long res)
2105 int result=FreeResource(res);
2106 dbgprintf("FreeResource(0x%x) => %d\n", res, result);
2107 return result;
2109 //bool fun(HANDLE)
2110 //!0 on success
2111 static int WINAPI expCloseHandle(long v1)
2113 dbgprintf("CloseHandle(0x%x) => 1\n", v1);
2114 /* do not close stdin,stdout and stderr */
2115 if (v1 > 2)
2116 if (!close(v1))
2117 return 0;
2118 return 1;
2121 static const char* WINAPI expGetCommandLineA()
2123 dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
2124 return "c:\\aviplay.exe";
2126 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
2127 static LPWSTR WINAPI expGetEnvironmentStringsW()
2129 dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
2130 return 0;
2132 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
2134 void* result=memset(p,0,len);
2135 dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
2136 return result;
2138 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
2140 void* result=memmove(dst,src,len);
2141 dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
2142 return result;
2145 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
2147 void* result=memset(p,ch,len);
2148 dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
2149 return result;
2151 static int WINAPI expFreeEnvironmentStringsW(short* strings)
2153 dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
2154 return 1;
2156 static int WINAPI expFreeEnvironmentStringsA(char* strings)
2158 dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
2159 return 1;
2162 static const char ch_envs[]=
2163 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
2164 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
2165 static LPCSTR WINAPI expGetEnvironmentStrings()
2167 dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
2168 return (LPCSTR)ch_envs;
2169 // dbgprintf("GetEnvironmentStrings() => 0\n");
2170 // return 0;
2173 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
2175 dbgprintf("GetStartupInfoA(0x%x) => 1\n");
2176 memset(s, 0, sizeof(*s));
2177 s->cb=sizeof(*s);
2178 // s->lpReserved="Reserved";
2179 // s->lpDesktop="Desktop";
2180 // s->lpTitle="Title";
2181 // s->dwX=s->dwY=0;
2182 // s->dwXSize=s->dwYSize=200;
2183 s->dwFlags=s->wShowWindow=1;
2184 // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
2185 dbgprintf(" cb=%d\n", s->cb);
2186 dbgprintf(" lpReserved='%s'\n", s->lpReserved);
2187 dbgprintf(" lpDesktop='%s'\n", s->lpDesktop);
2188 dbgprintf(" lpTitle='%s'\n", s->lpTitle);
2189 dbgprintf(" dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
2190 s->dwX, s->dwY, s->dwXSize, s->dwYSize);
2191 dbgprintf(" dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
2192 s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
2193 dbgprintf(" dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
2194 s->dwFlags, s->wShowWindow, s->cbReserved2);
2195 dbgprintf(" lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
2196 s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
2197 return 1;
2200 static int WINAPI expGetStdHandle(int z)
2202 dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
2203 return z+0x1234;
2206 #ifdef QTX
2207 #define FILE_HANDLE_quicktimeqts ((HANDLE)0x444)
2208 #define FILE_HANDLE_quicktimeqtx ((HANDLE)0x445)
2209 #endif
2211 static int WINAPI expGetFileType(int handle)
2213 dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
2214 return 0x3;
2216 #ifdef QTX
2217 static int WINAPI expGetFileAttributesA(char *filename)
2219 dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
2220 if (strstr(filename, "QuickTime.qts"))
2221 return FILE_ATTRIBUTE_SYSTEM;
2222 return FILE_ATTRIBUTE_NORMAL;
2224 #endif
2225 static int WINAPI expSetHandleCount(int count)
2227 dbgprintf("SetHandleCount(0x%x) => 1\n", count);
2228 return 1;
2230 static int WINAPI expGetACP(void)
2232 dbgprintf("GetACP() => 0\n");
2233 return 0;
2235 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
2237 WINE_MODREF *mr;
2238 int result;
2239 //printf("File name of module %X (%s) requested\n", module, s);
2241 if (module == 0 && len >= 12)
2243 /* return caller program name */
2244 strcpy(s, "aviplay.dll");
2245 result=1;
2247 else if(s==0)
2248 result=0;
2249 else
2250 if(len<35)
2251 result=0;
2252 else
2254 result=1;
2255 strcpy(s, "c:\\windows\\system\\");
2256 mr=MODULE32_LookupHMODULE(module);
2257 if(mr==0)//oops
2258 strcat(s, "aviplay.dll");
2259 else
2260 if(strrchr(mr->filename, '/')==NULL)
2261 strcat(s, mr->filename);
2262 else
2263 strcat(s, strrchr(mr->filename, '/')+1);
2265 if(!s)
2266 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
2267 module, s, len, result);
2268 else
2269 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
2270 module, s, len, result, s);
2271 return result;
2274 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
2276 dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
2277 return 1;//unsupported and probably won't ever be supported
2280 static int WINAPI expLoadLibraryA(char* name)
2282 int result = 0;
2283 char* lastbc;
2284 if (!name)
2285 return -1;
2286 // we skip to the last backslash
2287 // this is effectively eliminating weird characters in
2288 // the text output windows
2290 lastbc = strrchr(name, '\\');
2291 if (lastbc)
2293 int i;
2294 lastbc++;
2295 for (i = 0; 1 ;i++)
2297 name[i] = *lastbc++;
2298 if (!name[i])
2299 break;
2302 if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
2303 if(strncmp(name, ".\\", 2)==0) name += 2;
2305 dbgprintf("Entering LoadLibraryA(%s)\n", name);
2307 // PIMJ and VIVO audio are loading kernel32.dll
2308 if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
2309 return MODULE_HANDLE_kernel32;
2310 // return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
2311 /* exported -> do not return failed! */
2313 if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
2314 // return MODULE_HANDLE_kernel32;
2315 return MODULE_HANDLE_user32;
2317 #ifdef QTX
2318 if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
2319 return MODULE_HANDLE_wininet;
2320 if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
2321 return MODULE_HANDLE_ddraw;
2322 if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
2323 return MODULE_HANDLE_advapi32;
2324 #endif
2326 if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
2327 return MODULE_HANDLE_comdlg32;
2328 if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
2329 return MODULE_HANDLE_msvcrt;
2330 if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
2331 return MODULE_HANDLE_ole32;
2332 if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
2333 return MODULE_HANDLE_winmm;
2335 result=LoadLibraryA(name);
2336 dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
2338 return result;
2341 static int WINAPI expFreeLibrary(int module)
2343 #ifdef QTX
2344 int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
2345 #else
2346 int result=FreeLibrary(module);
2347 #endif
2348 dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
2349 return result;
2352 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
2354 void* result;
2355 switch(mod){
2356 case MODULE_HANDLE_kernel32:
2357 result=LookupExternalByName("kernel32.dll", name); break;
2358 case MODULE_HANDLE_user32:
2359 result=LookupExternalByName("user32.dll", name); break;
2360 #ifdef QTX
2361 case MODULE_HANDLE_wininet:
2362 result=LookupExternalByName("wininet.dll", name); break;
2363 case MODULE_HANDLE_ddraw:
2364 result=LookupExternalByName("ddraw.dll", name); break;
2365 case MODULE_HANDLE_advapi32:
2366 result=LookupExternalByName("advapi32.dll", name); break;
2367 #endif
2368 case MODULE_HANDLE_comdlg32:
2369 result=LookupExternalByName("comdlg32.dll", name); break;
2370 case MODULE_HANDLE_msvcrt:
2371 result=LookupExternalByName("msvcrt.dll", name); break;
2372 case MODULE_HANDLE_ole32:
2373 result=LookupExternalByName("ole32.dll", name); break;
2374 case MODULE_HANDLE_winmm:
2375 result=LookupExternalByName("winmm.dll", name); break;
2376 default:
2377 result=GetProcAddress(mod, name);
2379 if((unsigned int)name > 0xffff)
2380 dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
2381 else
2382 dbgprintf("GetProcAddress(0x%x, '%d') => 0x%x\n", mod, (int)name, result);
2383 return result;
2386 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
2387 long flProtect, long dwMaxHigh,
2388 long dwMaxLow, const char* name)
2390 long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
2391 if(!name)
2392 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2393 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
2394 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
2395 else
2396 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2397 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
2398 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
2399 return result;
2402 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
2404 long result=OpenFileMappingA(hFile, hz, name);
2405 if(!name)
2406 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
2407 hFile, hz, result);
2408 else
2409 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
2410 hFile, hz, name, name, result);
2411 return result;
2414 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
2415 DWORD offLow, DWORD size)
2417 dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
2418 file,mode,offHigh,offLow,size,(char*)file+offLow);
2419 return (char*)file+offLow;
2422 static void* WINAPI expUnmapViewOfFile(void* view)
2424 dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
2425 return 0;
2428 static void* WINAPI expSleep(int time)
2430 #if HAVE_NANOSLEEP
2431 /* solaris doesn't have thread safe usleep */
2432 struct timespec tsp;
2433 tsp.tv_sec = time / 1000000;
2434 tsp.tv_nsec = (time % 1000000) * 1000;
2435 nanosleep(&tsp, NULL);
2436 #else
2437 usleep(time);
2438 #endif
2439 dbgprintf("Sleep(%d) => 0\n", time);
2440 return 0;
2443 // why does IV32 codec want to call this? I don't know ...
2444 static int WINAPI expCreateCompatibleDC(int hdc)
2446 int dc = 0;//0x81;
2447 //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
2448 dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
2449 return dc;
2452 static int WINAPI expGetDeviceCaps(int hdc, int unk)
2454 dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
2455 #ifdef QTX
2456 #define BITSPIXEL 12
2457 #define PLANES 14
2458 if (unk == BITSPIXEL)
2459 return 24;
2460 if (unk == PLANES)
2461 return 1;
2462 #endif
2463 return 1;
2466 static WIN_BOOL WINAPI expDeleteDC(int hdc)
2468 dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
2469 if (hdc == 0x81)
2470 return 1;
2471 return 0;
2474 static WIN_BOOL WINAPI expDeleteObject(int hdc)
2476 dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
2477 /* FIXME - implement code here */
2478 return 1;
2481 /* btvvc32.drv wants this one */
2482 static void* WINAPI expGetWindowDC(int hdc)
2484 dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
2485 return 0;
2488 #ifdef QTX
2489 static int WINAPI expGetWindowRect(HWND win, RECT *r)
2491 dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
2492 /* (win == 0) => desktop */
2493 r->right = PSEUDO_SCREEN_WIDTH;
2494 r->left = 0;
2495 r->bottom = PSEUDO_SCREEN_HEIGHT;
2496 r->top = 0;
2497 return 1;
2500 static int WINAPI expMonitorFromWindow(HWND win, int flags)
2502 dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
2503 return 0;
2506 static int WINAPI expMonitorFromRect(RECT *r, int flags)
2508 dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
2509 return 0;
2512 static int WINAPI expMonitorFromPoint(void *p, int flags)
2514 dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
2515 return 0;
2518 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r,
2519 int WINAPI (*callback_proc)(), void *callback_param)
2521 dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
2522 dc, r, callback_proc, callback_param);
2523 return callback_proc(0, dc, r, callback_param);
2526 #if 0
2527 typedef struct tagMONITORINFO {
2528 DWORD cbSize;
2529 RECT rcMonitor;
2530 RECT rcWork;
2531 DWORD dwFlags;
2532 } MONITORINFO, *LPMONITORINFO;
2533 #endif
2535 #define CCHDEVICENAME 8
2536 typedef struct tagMONITORINFOEX {
2537 DWORD cbSize;
2538 RECT rcMonitor;
2539 RECT rcWork;
2540 DWORD dwFlags;
2541 TCHAR szDevice[CCHDEVICENAME];
2542 } MONITORINFOEX, *LPMONITORINFOEX;
2544 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
2546 dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
2548 lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
2549 lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
2550 lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
2551 lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
2553 lpmi->dwFlags = 1; /* primary monitor */
2555 if (lpmi->cbSize == sizeof(MONITORINFOEX))
2557 LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
2558 dbgprintf("MONITORINFOEX!\n");
2559 strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
2562 return 1;
2565 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
2566 void *dispdev, int flags)
2568 dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
2569 device, device, devnum, dispdev, flags);
2570 return 1;
2573 static int WINAPI expIsWindowVisible(HWND win)
2575 dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
2576 return 1;
2579 static HWND WINAPI expGetActiveWindow(void)
2581 dbgprintf("GetActiveWindow() => 0\n");
2582 return (HWND)0;
2585 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
2587 strncat(classname, "QuickTime", maxcount);
2588 dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
2589 win, classname, maxcount, strlen(classname));
2590 return strlen(classname);
2593 #define LPWNDCLASS void *
2594 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
2596 dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
2597 classname, classname, wndclass);
2598 return 1;
2601 static int WINAPI expGetWindowLongA(HWND win, int index)
2603 dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
2604 return 1;
2607 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
2609 dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
2610 return objsize;
2613 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
2615 dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
2616 return 0;
2619 static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
2621 int i, i2;
2622 dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
2623 i = callback_func(0, callback_param);
2624 i2 = callback_func(1, callback_param);
2625 return i && i2;
2628 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
2630 int tid = pthread_self();
2631 dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
2632 win, pid_data, tid);
2633 if (pid_data)
2634 *(int*)pid_data = tid;
2635 return tid;
2638 //HWND WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
2639 // INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
2641 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
2642 const char *winname, int style, int x, int y, int w, int h,
2643 HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
2645 printf("CreateWindowEx() called\n");
2646 dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
2647 exstyle, classname, classname, winname, winname, style, x, y, w, h,
2648 parent, menu, inst, param);
2649 printf("CreateWindowEx() called okey\n");
2650 return 1;
2653 static int WINAPI expwaveOutGetNumDevs(void)
2655 dbgprintf("waveOutGetNumDevs() => 0\n");
2656 return 0;
2658 #endif
2661 * Returns the number of milliseconds, modulo 2^32, since the start
2662 * of the wineserver.
2664 static int WINAPI expGetTickCount(void)
2666 static int tcstart = 0;
2667 struct timeval t;
2668 int tc;
2669 gettimeofday( &t, NULL );
2670 tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
2671 if (tcstart == 0)
2673 tcstart = 0;
2674 tc = 0;
2676 dbgprintf("GetTickCount() => %d\n", tc);
2677 return tc;
2680 static int WINAPI expCreateFontA(void)
2682 dbgprintf("CreateFontA() => 0x0\n");
2683 return 1;
2686 /* tried to get pvmjpg work in a different way - no success */
2687 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
2688 LPRECT lpRect, unsigned int uFormat)
2690 dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
2691 return 8;
2694 static int WINAPI expGetPrivateProfileIntA(const char* appname,
2695 const char* keyname,
2696 int default_value,
2697 const char* filename)
2699 int size=255;
2700 char buffer[256];
2701 char* fullname;
2702 int result;
2704 buffer[255]=0;
2705 if(!(appname && keyname && filename) )
2707 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
2708 return default_value;
2710 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2711 strcpy(fullname, "Software\\IniFileMapping\\");
2712 strcat(fullname, appname);
2713 strcat(fullname, "\\");
2714 strcat(fullname, keyname);
2715 strcat(fullname, "\\");
2716 strcat(fullname, filename);
2717 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
2718 if((size>=0)&&(size<256))
2719 buffer[size]=0;
2720 // printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
2721 free(fullname);
2722 if(result)
2723 result=default_value;
2724 else
2725 result=atoi(buffer);
2726 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
2727 return result;
2729 static int WINAPI expGetProfileIntA(const char* appname,
2730 const char* keyname,
2731 int default_value)
2733 dbgprintf("GetProfileIntA -> ");
2734 return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
2737 static int WINAPI expGetPrivateProfileStringA(const char* appname,
2738 const char* keyname,
2739 const char* def_val,
2740 char* dest, unsigned int len,
2741 const char* filename)
2743 int result;
2744 int size;
2745 char* fullname;
2746 dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
2747 if(!(appname && keyname && filename) ) return 0;
2748 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2749 strcpy(fullname, "Software\\IniFileMapping\\");
2750 strcat(fullname, appname);
2751 strcat(fullname, "\\");
2752 strcat(fullname, keyname);
2753 strcat(fullname, "\\");
2754 strcat(fullname, filename);
2755 size=len;
2756 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
2757 free(fullname);
2758 if(result)
2760 strncpy(dest, def_val, size);
2761 if (strlen(def_val)< size) size = strlen(def_val);
2763 dbgprintf(" => %d ( '%s' )\n", size, dest);
2764 return size;
2766 static int WINAPI expWritePrivateProfileStringA(const char* appname,
2767 const char* keyname,
2768 const char* string,
2769 const char* filename)
2771 char* fullname;
2772 dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
2773 if(!(appname && keyname && filename) )
2775 dbgprintf(" => -1\n");
2776 return -1;
2778 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2779 strcpy(fullname, "Software\\IniFileMapping\\");
2780 strcat(fullname, appname);
2781 strcat(fullname, "\\");
2782 strcat(fullname, keyname);
2783 strcat(fullname, "\\");
2784 strcat(fullname, filename);
2785 RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
2786 // printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
2787 // printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
2788 free(fullname);
2789 dbgprintf(" => 0\n");
2790 return 0;
2793 unsigned int GetPrivateProfileIntA_(const char* appname, const char* keyname, INT default_value, const char* filename)
2795 return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
2797 int GetPrivateProfileStringA_(const char* appname, const char* keyname,
2798 const char* def_val, char* dest, unsigned int len, const char* filename)
2800 return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
2802 int WritePrivateProfileStringA_(const char* appname, const char* keyname,
2803 const char* string, const char* filename)
2805 return expWritePrivateProfileStringA(appname, keyname, string, filename);
2810 static int WINAPI expDefDriverProc(int private, int id, int msg, int arg1, int arg2)
2812 dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", private, id, msg, arg1, arg2);
2813 return 0;
2816 static int WINAPI expSizeofResource(int v1, int v2)
2818 int result=SizeofResource(v1, v2);
2819 dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
2820 return result;
2823 static int WINAPI expGetLastError()
2825 int result=GetLastError();
2826 dbgprintf("GetLastError() => 0x%x\n", result);
2827 return result;
2830 static void WINAPI expSetLastError(int error)
2832 dbgprintf("SetLastError(0x%x)\n", error);
2833 SetLastError(error);
2836 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
2838 int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
2839 guid->f1, guid->f2, guid->f3,
2840 (unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
2841 (unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
2842 (unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
2843 (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
2844 dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
2845 return result;
2849 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
2851 dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
2852 return 0;
2855 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
2857 int result;
2858 if(string==0)result=1; else result=0;
2859 dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
2860 if(string)wch_print(string);
2861 return result;
2863 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
2865 return expIsBadStringPtrW((const short*)string, nchars);
2867 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
2869 long ret;
2870 __asm__ volatile
2872 "lock; xaddl %0,(%1)"
2873 : "=r" (ret)
2874 : "r" (dest), "0" (incr)
2875 : "memory"
2877 return ret;
2880 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
2882 unsigned long retval = *dest;
2883 if(*dest == comperand)
2884 *dest = exchange;
2885 return retval;
2888 static long WINAPI expInterlockedIncrement( long* dest )
2890 long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
2891 dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
2892 return result;
2894 static long WINAPI expInterlockedDecrement( long* dest )
2896 long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
2897 dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
2898 return result;
2901 static void WINAPI expOutputDebugStringA( const char* string )
2903 dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
2904 fprintf(stderr, "DEBUG: %s\n", string);
2907 static int WINAPI expGetDC(int hwnd)
2909 dbgprintf("GetDC(0x%x) => 1\n", hwnd);
2910 return 1;
2913 static int WINAPI expReleaseDC(int hwnd, int hdc)
2915 dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
2916 return 1;
2919 static int WINAPI expGetDesktopWindow()
2921 dbgprintf("GetDesktopWindow() => 0\n");
2922 return 0;
2925 static int cursor[100];
2927 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
2929 dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
2930 return (int)&cursor[0];
2932 static int WINAPI expSetCursor(void *cursor)
2934 dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
2935 return (int)cursor;
2937 static int WINAPI expGetCursorPos(void *cursor)
2939 dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
2940 return 1;
2942 #ifdef QTX
2943 static int show_cursor = 0;
2944 static int WINAPI expShowCursor(int show)
2946 dbgprintf("ShowCursor(%d) => %d\n", show, show);
2947 if (show)
2948 show_cursor++;
2949 else
2950 show_cursor--;
2951 return show_cursor;
2953 #endif
2954 static int WINAPI expRegisterWindowMessageA(char *message)
2956 dbgprintf("RegisterWindowMessageA(%s)\n", message);
2957 return 1;
2959 static int WINAPI expGetProcessVersion(int pid)
2961 dbgprintf("GetProcessVersion(%d)\n", pid);
2962 return 1;
2964 static int WINAPI expGetCurrentThread(void)
2966 #warning FIXME!
2967 dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
2968 return 0xcfcf9898;
2970 static int WINAPI expGetOEMCP(void)
2972 dbgprintf("GetOEMCP()\n");
2973 return 1;
2975 static int WINAPI expGetCPInfo(int cp,void *info)
2977 dbgprintf("GetCPInfo()\n");
2978 return 0;
2980 #ifdef QTX
2981 #define SM_CXSCREEN 0
2982 #define SM_CYSCREEN 1
2983 #define SM_XVIRTUALSCREEN 76
2984 #define SM_YVIRTUALSCREEN 77
2985 #define SM_CXVIRTUALSCREEN 78
2986 #define SM_CYVIRTUALSCREEN 79
2987 #define SM_CMONITORS 80
2988 #endif
2989 static int WINAPI expGetSystemMetrics(int index)
2991 dbgprintf("GetSystemMetrics(%d)\n", index);
2992 #ifdef QTX
2993 switch(index)
2995 case SM_XVIRTUALSCREEN:
2996 case SM_YVIRTUALSCREEN:
2997 return 0;
2998 case SM_CXSCREEN:
2999 case SM_CXVIRTUALSCREEN:
3000 return PSEUDO_SCREEN_WIDTH;
3001 case SM_CYSCREEN:
3002 case SM_CYVIRTUALSCREEN:
3003 return PSEUDO_SCREEN_HEIGHT;
3004 case SM_CMONITORS:
3005 return 1;
3007 #endif
3008 return 1;
3010 static int WINAPI expGetSysColor(int index)
3012 dbgprintf("GetSysColor(%d) => 1\n", index);
3013 return 1;
3015 static int WINAPI expGetSysColorBrush(int index)
3017 dbgprintf("GetSysColorBrush(%d)\n", index);
3018 return 1;
3023 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
3025 dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
3026 hdc, iStartIndex, nEntries, lppe);
3027 return 0;
3031 typedef struct TIME_ZONE_INFORMATION {
3032 long Bias;
3033 char StandardName[32];
3034 SYSTEMTIME StandardDate;
3035 long StandardBias;
3036 char DaylightName[32];
3037 SYSTEMTIME DaylightDate;
3038 long DaylightBias;
3039 } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
3042 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
3044 const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
3045 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
3046 const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
3047 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
3048 dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
3049 memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
3050 lpTimeZoneInformation->Bias=360;//GMT-6
3051 memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
3052 lpTimeZoneInformation->StandardDate.wMonth=10;
3053 lpTimeZoneInformation->StandardDate.wDay=5;
3054 lpTimeZoneInformation->StandardDate.wHour=2;
3055 lpTimeZoneInformation->StandardBias=0;
3056 memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
3057 lpTimeZoneInformation->DaylightDate.wMonth=4;
3058 lpTimeZoneInformation->DaylightDate.wDay=1;
3059 lpTimeZoneInformation->DaylightDate.wHour=2;
3060 lpTimeZoneInformation->DaylightBias=-60;
3061 return TIME_ZONE_ID_STANDARD;
3064 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
3066 time_t local_time;
3067 struct tm *local_tm;
3068 struct timeval tv;
3070 dbgprintf("GetLocalTime(0x%x)\n");
3071 gettimeofday(&tv, NULL);
3072 local_time=tv.tv_sec;
3073 local_tm=localtime(&local_time);
3075 systime->wYear = local_tm->tm_year + 1900;
3076 systime->wMonth = local_tm->tm_mon + 1;
3077 systime->wDayOfWeek = local_tm->tm_wday;
3078 systime->wDay = local_tm->tm_mday;
3079 systime->wHour = local_tm->tm_hour;
3080 systime->wMinute = local_tm->tm_min;
3081 systime->wSecond = local_tm->tm_sec;
3082 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3083 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3084 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3085 " Milliseconds: %d\n",
3086 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3087 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3090 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
3092 time_t local_time;
3093 struct tm *local_tm;
3094 struct timeval tv;
3096 dbgprintf("GetSystemTime(0x%x)\n", systime);
3097 gettimeofday(&tv, NULL);
3098 local_time=tv.tv_sec;
3099 local_tm=gmtime(&local_time);
3101 systime->wYear = local_tm->tm_year + 1900;
3102 systime->wMonth = local_tm->tm_mon + 1;
3103 systime->wDayOfWeek = local_tm->tm_wday;
3104 systime->wDay = local_tm->tm_mday;
3105 systime->wHour = local_tm->tm_hour;
3106 systime->wMinute = local_tm->tm_min;
3107 systime->wSecond = local_tm->tm_sec;
3108 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3109 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3110 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3111 " Milliseconds: %d\n",
3112 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3113 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3114 return 0;
3117 #define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ULL)
3118 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
3120 struct timeval tv;
3121 unsigned long long secs;
3123 dbgprintf("GetSystemTime(0x%x)\n", systime);
3124 gettimeofday(&tv, NULL);
3125 secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
3126 secs += tv.tv_usec * 10;
3127 systime->dwLowDateTime = secs & 0xffffffff;
3128 systime->dwHighDateTime = (secs >> 32);
3131 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
3133 //char *p;
3134 // printf("%s %x %x\n", name, field, size);
3135 if(field)field[0]=0;
3137 p = getenv(name);
3138 if (p) strncpy(field,p,size);
3140 if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
3141 strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
3142 dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
3143 return strlen(field);
3146 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
3148 dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
3149 return 0;
3152 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
3154 return my_mreq(cb, 0);
3156 static void WINAPI expCoTaskMemFree(void* cb)
3158 my_release(cb);
3164 void* CoTaskMemAlloc(unsigned long cb)
3166 return expCoTaskMemAlloc(cb);
3168 void CoTaskMemFree(void* cb)
3170 expCoTaskMemFree(cb);
3173 struct COM_OBJECT_INFO
3175 GUID clsid;
3176 long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
3179 static struct COM_OBJECT_INFO* com_object_table=0;
3180 static int com_object_size=0;
3181 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3183 if(!clsid || !gcs)
3184 return -1;
3185 com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
3186 com_object_table[com_object_size-1].clsid=*clsid;
3187 com_object_table[com_object_size-1].GetClassObject=gcs;
3188 return 0;
3191 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3193 int found = 0;
3194 int i = 0;
3195 if(!clsid || !gcs)
3196 return -1;
3198 if (com_object_table == 0)
3199 printf("Warning: UnregisterComClass() called without any registered class\n");
3200 while (i < com_object_size)
3202 if (found && i > 0)
3204 memcpy(&com_object_table[i - 1].clsid,
3205 &com_object_table[i].clsid, sizeof(GUID));
3206 com_object_table[i - 1].GetClassObject =
3207 com_object_table[i].GetClassObject;
3209 else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
3210 && com_object_table[i].GetClassObject == gcs)
3212 found++;
3214 i++;
3216 if (found)
3218 if (--com_object_size == 0)
3220 free(com_object_table);
3221 com_object_table = 0;
3224 return 0;
3228 const GUID IID_IUnknown =
3230 0x00000000, 0x0000, 0x0000,
3231 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3233 const GUID IID_IClassFactory =
3235 0x00000001, 0x0000, 0x0000,
3236 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3239 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3240 long dwClsContext, const GUID* riid, void** ppv)
3242 int i;
3243 struct COM_OBJECT_INFO* ci=0;
3244 for(i=0; i<com_object_size; i++)
3245 if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
3246 ci=&com_object_table[i];
3247 if(!ci)return REGDB_E_CLASSNOTREG;
3248 // in 'real' world we should mess with IClassFactory here
3249 i=ci->GetClassObject(rclsid, riid, ppv);
3250 return i;
3253 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3254 long dwClsContext, const GUID* riid, void** ppv)
3256 return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
3259 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
3261 int r = 0;
3262 int w,h;
3263 //trapbug();
3264 if (lprc)
3266 w = lprc->right - lprc->left;
3267 h = lprc->bottom - lprc->top;
3268 if (w <= 0 || h <= 0)
3269 r = 1;
3271 else
3272 r = 1;
3274 dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
3275 //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
3276 // return 0; // wmv9?
3277 return r; // TM20
3280 static int _adjust_fdiv=0; //what's this? - used to adjust division
3281 static int _winver = 0x510; // windows version
3286 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
3288 dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
3289 if(len<5)
3291 dbgprintf(" => 0\n");
3292 return 0;
3294 strcpy(path, "/tmp");
3295 dbgprintf(" => 5 ( '/tmp' )\n");
3296 return 5;
3299 FYI:
3300 typedef struct
3302 DWORD dwFileAttributes;
3303 FILETIME ftCreationTime;
3304 FILETIME ftLastAccessTime;
3305 FILETIME ftLastWriteTime;
3306 DWORD nFileSizeHigh;
3307 DWORD nFileSizeLow;
3308 DWORD dwReserved0;
3309 DWORD dwReserved1;
3310 CHAR cFileName[260];
3311 CHAR cAlternateFileName[14];
3312 } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
3315 static DIR* qtx_dir=NULL;
3317 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
3319 #ifdef QTX
3320 dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
3321 if(h==FILE_HANDLE_quicktimeqtx){
3322 struct dirent* d;
3323 if(!qtx_dir) return 0;
3324 while((d=readdir(qtx_dir))){
3325 char* x=strrchr(d->d_name,'.');
3326 if(!x) continue;
3327 if(strcmp(x,".qtx")) continue;
3328 strcpy(lpfd->cFileName,d->d_name);
3329 // sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
3330 strcpy(lpfd->cAlternateFileName,"foobar.qtx");
3331 printf("### FindNext: %s\n",lpfd->cFileName);
3332 return 1;
3334 closedir(qtx_dir); qtx_dir=NULL;
3335 return 0;
3337 #endif
3338 return 0;
3341 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
3343 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
3344 // printf("\n### FindFirstFileA('%s')...\n",s);
3345 #ifdef QTX
3346 if(strstr(s, "quicktime\\*.QTX")){
3347 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
3348 printf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",def_path);
3349 qtx_dir=opendir(def_path);
3350 if(!qtx_dir) return (HANDLE)-1;
3351 memset(lpfd,0,sizeof(*lpfd));
3352 if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
3353 return FILE_HANDLE_quicktimeqtx;
3354 printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",def_path);
3355 return (HANDLE)-1;
3357 #if 0
3358 if(strstr(s, "QuickTime.qts")){
3359 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
3360 // if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
3361 // return (HANDLE)-1;
3362 strcpy(lpfd->cFileName, "QuickTime.qts");
3363 strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
3364 return FILE_HANDLE_quicktimeqts;
3366 #endif
3367 #endif
3368 if(strstr(s, "*.vwp")){
3369 // hack for VoxWare codec plugins:
3370 strcpy(lpfd->cFileName, "msms001.vwp");
3371 strcpy(lpfd->cAlternateFileName, "msms001.vwp");
3372 return (HANDLE)0;
3374 // return 'file not found'
3375 return (HANDLE)-1;
3378 static WIN_BOOL WINAPI expFindClose(HANDLE h)
3380 dbgprintf("FindClose(0x%x) => 0\n", h);
3381 #ifdef QTX
3382 // if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
3383 // closedir(qtx_dir);
3384 // qtx_dir=NULL;
3385 // }
3386 #endif
3387 return 0;
3389 static UINT WINAPI expSetErrorMode(UINT i)
3391 dbgprintf("SetErrorMode(%d) => 0\n", i);
3392 return 0;
3394 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
3396 char windir[]="c:\\windows";
3397 int result;
3398 strncpy(s, windir, c);
3399 result=1+((c<strlen(windir))?c:strlen(windir));
3400 dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
3401 return result;
3403 #ifdef QTX
3404 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
3406 char curdir[]="c:\\";
3407 int result;
3408 strncpy(s, curdir, c);
3409 result=1+((c<strlen(curdir))?c:strlen(curdir));
3410 dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
3411 return result;
3414 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
3416 dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
3417 #if 0
3418 if (strrchr(pathname, '\\'))
3419 chdir(strcat(strrchr(pathname, '\\')+1, '/'));
3420 else
3421 chdir(pathname);
3422 #endif
3423 return 1;
3426 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
3428 dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
3429 pathname, pathname, sa);
3430 #if 0
3431 p = strrchr(pathname, '\\')+1;
3432 strcpy(&buf[0], p); /* should be strncpy */
3433 if (!strlen(p))
3435 buf[0] = '.';
3436 buf[1] = 0;
3438 #if 0
3439 if (strrchr(pathname, '\\'))
3440 mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
3441 else
3442 mkdir(pathname, 666);
3443 #endif
3444 mkdir(&buf);
3445 #endif
3446 return 1;
3448 #endif
3449 static WIN_BOOL WINAPI expDeleteFileA(LPCSTR s)
3451 dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
3452 return 0;
3454 static WIN_BOOL WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
3456 dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
3457 return 0;
3460 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
3462 char mask[16]="/tmp/AP_XXXXXX";
3463 int result;
3464 dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
3465 if(i && i<10)
3467 dbgprintf(" => -1\n");
3468 return -1;
3470 result=mkstemp(mask);
3471 sprintf(ps, "AP%d", result);
3472 dbgprintf(" => %d\n", strlen(ps));
3473 return strlen(ps);
3476 // This func might need proper implementation if we want AngelPotion codec.
3477 // They try to open APmpeg4v1.apl with it.
3478 // DLL will close opened file with CloseHandle().
3480 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
3481 LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
3483 dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
3484 i2, p1, i3, i4, i5);
3485 if((!cs1) || (strlen(cs1)<2))return -1;
3487 #ifdef QTX
3488 if(strstr(cs1, "QuickTime.qts"))
3490 int result;
3491 char* tmp=malloc(strlen(def_path)+50);
3492 strcpy(tmp, def_path);
3493 strcat(tmp, "/");
3494 strcat(tmp, "QuickTime.qts");
3495 result=open(tmp, O_RDONLY);
3496 free(tmp);
3497 return result;
3499 if(strstr(cs1, ".qtx"))
3501 int result;
3502 char* tmp=malloc(strlen(def_path)+250);
3503 char* x=strrchr(cs1,'\\');
3504 sprintf(tmp,"%s/%s",def_path,x?(x+1):cs1);
3505 // printf("### Open: %s -> %s\n",cs1,tmp);
3506 result=open(tmp, O_RDONLY);
3507 free(tmp);
3508 return result;
3510 #endif
3512 if(strncmp(cs1, "AP", 2) == 0)
3514 int result;
3515 char* tmp=malloc(strlen(def_path)+50);
3516 strcpy(tmp, def_path);
3517 strcat(tmp, "/");
3518 strcat(tmp, "APmpg4v1.apl");
3519 result=open(tmp, O_RDONLY);
3520 free(tmp);
3521 return result;
3523 if (strstr(cs1, "vp3"))
3525 int r;
3526 int flg = 0;
3527 char* tmp=malloc(20 + strlen(cs1));
3528 strcpy(tmp, "/tmp/");
3529 strcat(tmp, cs1);
3530 r = 4;
3531 while (tmp[r])
3533 if (tmp[r] == ':' || tmp[r] == '\\')
3534 tmp[r] = '_';
3535 r++;
3537 if (GENERIC_READ & i1)
3538 flg |= O_RDONLY;
3539 else if (GENERIC_WRITE & i1)
3541 flg |= O_WRONLY;
3542 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", tmp, r, flg);
3544 r=open(tmp, flg);
3545 free(tmp);
3546 return r;
3549 // Needed by wnvplay1.dll
3550 if (strstr(cs1, "WINNOV.bmp"))
3552 int r;
3553 r=open("/dev/null", O_RDONLY);
3554 return r;
3557 #if 0
3558 /* we need this for some virtualdub filters */
3560 int r;
3561 int flg = 0;
3562 if (GENERIC_READ & i1)
3563 flg |= O_RDONLY;
3564 else if (GENERIC_WRITE & i1)
3566 flg |= O_WRONLY;
3567 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", cs1, r, flg);
3569 r=open(cs1, flg);
3570 return r;
3572 #endif
3574 return atoi(cs1+2);
3576 static UINT WINAPI expGetSystemDirectoryA(
3577 char* lpBuffer, // address of buffer for system directory
3578 UINT uSize // size of directory buffer
3580 dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
3581 if(!lpBuffer) strcpy(lpBuffer,".");
3582 return 1;
3585 static char sysdir[]=".";
3586 static LPCSTR WINAPI expGetSystemDirectoryA()
3588 dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
3589 return sysdir;
3592 static DWORD WINAPI expGetFullPathNameA
3594 LPCTSTR lpFileName,
3595 DWORD nBufferLength,
3596 LPTSTR lpBuffer,
3597 LPTSTR lpFilePart
3599 if(!lpFileName) return 0;
3600 dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
3601 lpBuffer, lpFilePart);
3602 #if 0
3603 #ifdef QTX
3604 strcpy(lpFilePart, "Quick123.qts");
3605 #else
3606 strcpy(lpFilePart, lpFileName);
3607 #endif
3608 #else
3609 if (strrchr(lpFileName, '\\'))
3610 lpFilePart = strrchr(lpFileName, '\\');
3611 else
3612 lpFilePart = (LPTSTR)lpFileName;
3613 #endif
3614 strcpy(lpBuffer, lpFileName);
3615 // strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
3616 return strlen(lpBuffer);
3619 static DWORD WINAPI expGetShortPathNameA
3621 LPCSTR longpath,
3622 LPSTR shortpath,
3623 DWORD shortlen
3625 if(!longpath) return 0;
3626 dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
3627 strcpy(shortpath,longpath);
3628 return strlen(shortpath);
3631 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
3633 int result;
3634 dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
3635 result=read(h, pv, size);
3636 if(rd)*rd=result;
3637 if(!result)return 0;
3638 return 1;
3641 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
3643 int result;
3644 dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
3645 if(h==1234)h=1;
3646 result=write(h, pv, size);
3647 if(wr)*wr=result;
3648 if(!result)return 0;
3649 return 1;
3651 static DWORD WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
3653 int wh;
3654 dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, ext ? *ext : NULL, whence);
3655 //why would DLL want temporary file with >2Gb size?
3656 switch(whence)
3658 case FILE_BEGIN:
3659 wh=SEEK_SET;break;
3660 case FILE_END:
3661 wh=SEEK_END;break;
3662 case FILE_CURRENT:
3663 wh=SEEK_CUR;break;
3664 default:
3665 return -1;
3667 #ifdef QTX
3668 if (val == 0 && ext != 0)
3669 val = val&(*ext);
3670 #endif
3671 return lseek(h, val, wh);
3674 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
3675 LPARAM lParam2)
3677 dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3678 return -1;
3680 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
3681 LPARAM lParam2)
3683 dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3684 return -1;
3688 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
3689 LPDWORD lpProcessAffinityMask,
3690 LPDWORD lpSystemAffinityMask)
3692 dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
3693 hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
3694 if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
3695 if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
3696 return 1;
3699 // Fake implementation: does nothing, but does it right :)
3700 static WIN_BOOL WINAPI expSetProcessAffinityMask(HANDLE hProcess,
3701 LPDWORD dwProcessAffinityMask)
3703 dbgprintf("SetProcessAffinityMask(0x%x, 0x%x) => 1\n",
3704 hProcess, dwProcessAffinityMask);
3706 return 1;
3709 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
3711 static const long long max_int=0x7FFFFFFFLL;
3712 static const long long min_int=-0x80000000LL;
3713 long long tmp=(long long)nNumber*(long long)nNumerator;
3714 dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
3715 if(!nDenominator)return 1;
3716 tmp/=nDenominator;
3717 if(tmp<min_int) return 1;
3718 if(tmp>max_int) return 1;
3719 return (int)tmp;
3722 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
3724 LONG result=strcasecmp(str1, str2);
3725 dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
3726 return result;
3729 static LONG WINAPI explstrlenA(const char* str1)
3731 LONG result=strlen(str1);
3732 dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
3733 return result;
3736 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
3738 int result= (int) strcpy(str1, str2);
3739 dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
3740 return result;
3742 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
3744 int result;
3745 if (strlen(str2)>len)
3746 result = (int) strncpy(str1, str2,len);
3747 else
3748 result = (int) strcpy(str1,str2);
3749 dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
3750 return result;
3752 static LONG WINAPI explstrcatA(char* str1, const char* str2)
3754 int result= (int) strcat(str1, str2);
3755 dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
3756 return result;
3760 static LONG WINAPI expInterlockedExchange(long *dest, long l)
3762 long retval = *dest;
3763 *dest = l;
3764 return retval;
3767 static void WINAPI expInitCommonControls(void)
3769 dbgprintf("InitCommonControls called!\n");
3770 return;
3773 #ifdef QTX
3774 /* needed by QuickTime.qts */
3775 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
3776 HWND parent, INT id, HINSTANCE inst,
3777 HWND buddy, INT maxVal, INT minVal, INT curVal)
3779 dbgprintf("CreateUpDownControl(...)\n");
3780 return 0;
3782 #endif
3784 /* alex: implement this call! needed for 3ivx */
3785 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
3787 dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
3788 pUnkOuter, ppUnkInner);
3789 // return 0;
3790 return ERROR_CALL_NOT_IMPLEMENTED;
3794 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
3795 HANDLE hSourceHandle, // handle to duplicate
3796 HANDLE hTargetProcessHandle, // handle to target process
3797 HANDLE* lpTargetHandle, // duplicate handle
3798 DWORD dwDesiredAccess, // requested access
3799 int bInheritHandle, // handle inheritance option
3800 DWORD dwOptions // optional actions
3803 dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
3804 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
3805 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
3806 *lpTargetHandle = hSourceHandle;
3807 return 1;
3810 static HRESULT WINAPI expCoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3812 dbgprintf("CoInitializeEx(%p, %d) called\n", lpReserved, dwCoInit);
3813 return S_OK;
3816 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
3817 static HRESULT WINAPI expCoInitialize(
3818 LPVOID lpReserved /* [in] pointer to win32 malloc interface
3819 (obsolete, should be NULL) */
3823 * Just delegate to the newer method.
3825 return expCoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
3828 static void WINAPI expCoUninitialize(void)
3830 dbgprintf("CoUninitialize() called\n");
3833 /* allow static linking */
3834 HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3836 return expCoInitializeEx(lpReserved, dwCoInit);
3838 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
3840 return expCoInitialize(lpReserved);
3842 void WINAPI CoUninitialize(void)
3844 return expCoUninitialize();
3847 static DWORD WINAPI expSetThreadAffinityMask
3849 HANDLE hThread,
3850 DWORD dwThreadAffinityMask
3852 return 0;
3856 * no WINAPI functions - CDECL
3858 static void* expmalloc(int size)
3860 //printf("malloc");
3861 // return malloc(size);
3862 void* result=my_mreq(size,0);
3863 dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
3864 if(result==0)
3865 printf("WARNING: malloc() failed\n");
3866 return result;
3868 static void expfree(void* mem)
3870 // return free(mem);
3871 dbgprintf("free(%p)\n", mem);
3872 my_release(mem);
3874 /* needed by atrac3.acm */
3875 static void *expcalloc(int num, int size)
3877 void* result=my_mreq(num*size,1);
3878 dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
3879 if(result==0)
3880 printf("WARNING: calloc() failed\n");
3881 return result;
3883 static void* expnew(int size)
3885 // printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
3886 // printf("%08x %08x %08x %08x\n",
3887 // size, *(1+(int*)&size),
3888 // *(2+(int*)&size),*(3+(int*)&size));
3889 void* result;
3890 assert(size >= 0);
3892 result=my_mreq(size,0);
3893 dbgprintf("new(%d) => %p\n", size, result);
3894 if (result==0)
3895 printf("WARNING: new() failed\n");
3896 return result;
3899 static int expdelete(void* memory)
3901 dbgprintf("delete(%p)\n", memory);
3902 my_release(memory);
3903 return 0;
3907 * local definition - we need only the last two members at this point
3908 * otherwice we would have to introduce here GUIDs and some more types..
3910 typedef struct __attribute__((__packed__))
3912 char hay[0x40];
3913 unsigned long cbFormat; //0x40
3914 char* pbFormat; //0x44
3915 } MY_MEDIA_TYPE;
3916 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
3918 if (!dest || !src)
3919 return E_POINTER;
3920 memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
3921 if (dest->cbFormat)
3923 dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
3924 if (!dest->pbFormat)
3925 return E_OUTOFMEMORY;
3926 memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
3928 return S_OK;
3930 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
3932 if (!dest)
3933 return E_POINTER;
3934 memset(dest, 0, sizeof(MY_MEDIA_TYPE));
3935 if (cbFormat)
3937 dest->pbFormat = (char*) my_mreq(cbFormat, 0);
3938 if (!dest->pbFormat)
3939 return E_OUTOFMEMORY;
3941 return S_OK;
3943 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
3945 if (!dest)
3946 return E_POINTER;
3947 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3948 return expMoInitMediaType(*dest, cbFormat);
3950 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
3952 if (!dest)
3953 return E_POINTER;
3954 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3955 return expMoCopyMediaType(*dest, src);
3957 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
3959 if (!dest)
3960 return E_POINTER;
3961 if (dest->pbFormat)
3963 my_release(dest->pbFormat);
3964 dest->pbFormat = 0;
3965 dest->cbFormat = 0;
3967 return S_OK;
3969 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
3971 if (!dest)
3972 return E_POINTER;
3973 expMoFreeMediaType(dest);
3974 my_release(dest);
3975 return S_OK;
3978 static int exp_snprintf( char *str, int size, const char *format, ... )
3980 int x;
3981 va_list va;
3982 va_start(va, format);
3983 x=snprintf(str,size,format,va);
3984 dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
3985 va_end(va);
3986 return x;
3989 #if 0
3990 static int exp_initterm(int v1, int v2)
3992 dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
3993 return 0;
3995 #else
3996 /* merged from wine - 2002.04.21 */
3997 typedef void (*INITTERMFUNC)();
3998 static int exp_initterm(INITTERMFUNC *start, INITTERMFUNC *end)
4000 dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
4001 while (start < end)
4003 if (*start)
4005 //printf("call _initfunc: from: %p %d\n", *start);
4006 // ok this trick with push/pop is necessary as otherwice
4007 // edi/esi registers are being trashed
4008 void* p = *start;
4009 __asm__ volatile
4011 "pushl %%ebx \n\t"
4012 "pushl %%ecx \n\t"
4013 "pushl %%edx \n\t"
4014 "pushl %%edi \n\t"
4015 "pushl %%esi \n\t"
4016 "call *%%eax \n\t"
4017 "popl %%esi \n\t"
4018 "popl %%edi \n\t"
4019 "popl %%edx \n\t"
4020 "popl %%ecx \n\t"
4021 "popl %%ebx \n\t"
4023 : "a"(p)
4024 : "memory"
4026 //printf("done %p %d:%d\n", end);
4028 start++;
4030 return 0;
4032 #endif
4034 /* Fake _initterm_e from msvcr80.dll, needed by sirenacm.dll
4035 * NOTE: If I make this an alias for _initterm, then sirenacm.dll tries to call
4036 other uninmplemented functions; keep this in mind if some future codec needs
4037 a real implementation of this function */
4038 static int exp_initterm_e(INITTERMFUNC *start, INITTERMFUNC *end)
4040 dbgprintf("_initterm_e(0x%x, 0x%x)\n", start, end);
4041 return 0;
4044 static void* exp__dllonexit()
4046 // FIXME extract from WINE
4047 return NULL;
4050 static int expwsprintfA(char* string, const char* format, ...)
4052 va_list va;
4053 int result;
4054 va_start(va, format);
4055 result = vsprintf(string, format, va);
4056 dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4057 va_end(va);
4058 return result;
4061 static int expsprintf(char* str, const char* format, ...)
4063 va_list args;
4064 int r;
4065 dbgprintf("sprintf(0x%x, %s)\n", str, format);
4066 va_start(args, format);
4067 r = vsprintf(str, format, args);
4068 va_end(args);
4069 return r;
4071 static int expsscanf(const char* str, const char* format, ...)
4073 va_list args;
4074 int r;
4075 dbgprintf("sscanf(%s, %s)\n", str, format);
4076 va_start(args, format);
4077 r = vsscanf(str, format, args);
4078 va_end(args);
4079 return r;
4081 static void* expfopen(const char* path, const char* mode)
4083 printf("fopen: \"%s\" mode:%s\n", path, mode);
4084 //return fopen(path, mode);
4085 return fdopen(0, mode); // everything on screen
4087 static int expfprintf(void* stream, const char* format, ...)
4089 va_list args;
4090 int r = 0;
4091 dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4092 #if 1
4093 va_start(args, format);
4094 r = vfprintf((FILE*) stream, format, args);
4095 va_end(args);
4096 #endif
4097 return r;
4100 static int expprintf(const char* format, ...)
4102 va_list args;
4103 int r;
4104 dbgprintf("printf(%s, ...)\n", format);
4105 va_start(args, format);
4106 r = vprintf(format, args);
4107 va_end(args);
4108 return r;
4111 static char* expgetenv(const char* varname)
4113 char* v = getenv(varname);
4114 dbgprintf("getenv(%s) => %s\n", varname, v);
4115 return v;
4118 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4120 WCHAR* p = dst;
4121 while ((*p++ = *src++))
4123 return dst;
4126 static char* expstrrchr(char* string, int value)
4128 char* result=strrchr(string, value);
4129 if(result)
4130 dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4131 else
4132 dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4133 return result;
4136 static char* expstrchr(char* string, int value)
4138 char* result=strchr(string, value);
4139 if(result)
4140 dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4141 else
4142 dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4143 return result;
4145 static int expstrlen(char* str)
4147 int result=strlen(str);
4148 dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4149 return result;
4151 static char* expstrcpy(char* str1, const char* str2)
4153 char* result= strcpy(str1, str2);
4154 dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4155 return result;
4157 static char* expstrncpy(char* str1, const char* str2, size_t count)
4159 char* result= strncpy(str1, str2, count);
4160 dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4161 return result;
4163 static int expstrcmp(const char* str1, const char* str2)
4165 int result=strcmp(str1, str2);
4166 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4167 return result;
4169 static int expstrncmp(const char* str1, const char* str2,int x)
4171 int result=strncmp(str1, str2,x);
4172 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4173 return result;
4175 static char* expstrcat(char* str1, const char* str2)
4177 char* result = strcat(str1, str2);
4178 dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4179 return result;
4181 static char* exp_strdup(const char* str1)
4183 int l = strlen(str1);
4184 char* result = (char*) my_mreq(l + 1,0);
4185 if (result)
4186 strcpy(result, str1);
4187 dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4188 return result;
4190 static int expisalnum(int c)
4192 int result= (int) isalnum(c);
4193 dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4194 return result;
4196 static int expisspace(int c)
4198 int result= (int) isspace(c);
4199 dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4200 return result;
4202 static int expisalpha(int c)
4204 int result= (int) isalpha(c);
4205 dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4206 return result;
4208 static int expisdigit(int c)
4210 int result= (int) isdigit(c);
4211 dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4212 return result;
4214 static void* expmemmove(void* dest, void* src, int n)
4216 void* result = memmove(dest, src, n);
4217 dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4218 return result;
4220 static int expmemcmp(void* dest, void* src, int n)
4222 int result = memcmp(dest, src, n);
4223 dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4224 return result;
4226 static void* expmemcpy(void* dest, void* src, int n)
4228 void *result = memcpy(dest, src, n);
4229 dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4230 return result;
4232 static void* expmemset(void* dest, int c, size_t n)
4234 void *result = memset(dest, c, n);
4235 dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4236 return result;
4238 static time_t exptime(time_t* t)
4240 time_t result = time(t);
4241 dbgprintf("time(0x%x) => %d\n", t, result);
4242 return result;
4245 static int exprand(void)
4247 return rand();
4250 static void expsrand(int seed)
4252 srand(seed);
4255 #if 1
4257 // preferred compilation with -O2 -ffast-math !
4259 static double explog10(double x)
4261 /*printf("Log10 %f => %f 0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4262 return log10(x);
4265 static double expcos(double x)
4267 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4268 return cos(x);
4271 #else
4273 static void explog10(void)
4275 __asm__ volatile
4277 "fldl 8(%esp) \n\t"
4278 "fldln2 \n\t"
4279 "fxch %st(1) \n\t"
4280 "fyl2x \n\t"
4284 static void expcos(void)
4286 __asm__ volatile
4288 "fldl 8(%esp) \n\t"
4289 "fcos \n\t"
4293 #endif
4295 // this seem to be the only how to make this function working properly
4296 // ok - I've spent tremendous amount of time (many many many hours
4297 // of debuging fixing & testing - it's almost unimaginable - kabi
4299 // _ftol - operated on the float value which is already on the FPU stack
4301 static void exp_ftol(void)
4303 __asm__ volatile
4305 "sub $12, %esp \n\t"
4306 "fstcw -2(%ebp) \n\t"
4307 "wait \n\t"
4308 "movw -2(%ebp), %ax \n\t"
4309 "orb $0x0C, %ah \n\t"
4310 "movw %ax, -4(%ebp) \n\t"
4311 "fldcw -4(%ebp) \n\t"
4312 "fistpl -12(%ebp) \n\t"
4313 "fldcw -2(%ebp) \n\t"
4314 "movl -12(%ebp), %eax \n\t"
4315 //Note: gcc 3.03 does not do the following op if it
4316 // knows that ebp=esp
4317 "movl %ebp, %esp \n\t"
4321 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4322 __asm__ volatile( "fstpl %0;fwait" : "=m" (var2) : ); \
4323 __asm__ volatile( "fstpl %0;fwait" : "=m" (var1) : )
4325 static double exp_CIpow(void)
4327 FPU_DOUBLES(x,y);
4329 dbgprintf("_CIpow(%lf, %lf)\n", x, y);
4330 return pow(x, y);
4333 static double exppow(double x, double y)
4335 /*printf("Pow %f %f 0x%Lx 0x%Lx => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4336 return pow(x, y);
4339 static double expldexp(double x, int expo)
4341 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4342 return ldexp(x, expo);
4345 static double expfrexp(double x, int* expo)
4347 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4348 return frexp(x, expo);
4353 static int exp_stricmp(const char* s1, const char* s2)
4355 return strcasecmp(s1, s2);
4358 /* from declaration taken from Wine sources - this fountion seems to be
4359 * undocumented in any M$ doc */
4360 static int exp_setjmp3(void* jmpbuf, int x)
4362 //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4363 //return 0;
4364 __asm__ volatile
4366 //"mov 4(%%esp), %%edx \n\t"
4367 "mov (%%esp), %%eax \n\t"
4368 "mov %%eax, (%%edx) \n\t" // store ebp
4370 //"mov %%ebp, (%%edx) \n\t"
4371 "mov %%ebx, 4(%%edx) \n\t"
4372 "mov %%edi, 8(%%edx) \n\t"
4373 "mov %%esi, 12(%%edx) \n\t"
4374 "mov %%esp, 16(%%edx) \n\t"
4376 "mov 4(%%esp), %%eax \n\t"
4377 "mov %%eax, 20(%%edx) \n\t"
4379 "movl $0x56433230, 32(%%edx) \n\t" // VC20 ??
4380 "movl $0, 36(%%edx) \n\t"
4381 : // output
4382 : "d"(jmpbuf) // input
4383 : "eax"
4385 #if 1
4386 __asm__ volatile
4388 "mov %%fs:0, %%eax \n\t" // unsure
4389 "mov %%eax, 24(%%edx) \n\t"
4390 "cmp $0xffffffff, %%eax \n\t"
4391 "jnz l1 \n\t"
4392 "mov %%eax, 28(%%edx) \n\t"
4393 "l1: \n\t"
4396 : "eax"
4398 #endif
4400 return 0;
4403 static DWORD WINAPI expGetCurrentProcessId(void)
4405 dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4406 return getpid(); //(DWORD)NtCurrentTeb()->pid;
4410 typedef struct {
4411 UINT wPeriodMin;
4412 UINT wPeriodMax;
4413 } TIMECAPS, *LPTIMECAPS;
4415 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4417 dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4419 lpCaps->wPeriodMin = 1;
4420 lpCaps->wPeriodMax = 65535;
4421 return 0;
4424 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4426 dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4428 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4429 return 0;
4432 #ifdef QTX
4433 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4435 dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4437 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4438 return 0;
4440 #endif
4442 static void WINAPI expGlobalMemoryStatus(
4443 LPMEMORYSTATUS lpmem
4445 static MEMORYSTATUS cached_memstatus;
4446 static int cache_lastchecked = 0;
4447 SYSTEM_INFO si;
4448 FILE *f;
4450 if (time(NULL)==cache_lastchecked) {
4451 memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4452 return;
4455 #if 1
4456 f = fopen( "/proc/meminfo", "r" );
4457 if (f)
4459 char buffer[256];
4460 int total, used, free, shared, buffers, cached;
4462 lpmem->dwLength = sizeof(MEMORYSTATUS);
4463 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4464 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4465 while (fgets( buffer, sizeof(buffer), f ))
4467 /* old style /proc/meminfo ... */
4468 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4470 lpmem->dwTotalPhys += total;
4471 lpmem->dwAvailPhys += free + buffers + cached;
4473 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4475 lpmem->dwTotalPageFile += total;
4476 lpmem->dwAvailPageFile += free;
4479 /* new style /proc/meminfo ... */
4480 if (sscanf(buffer, "MemTotal: %d", &total))
4481 lpmem->dwTotalPhys = total*1024;
4482 if (sscanf(buffer, "MemFree: %d", &free))
4483 lpmem->dwAvailPhys = free*1024;
4484 if (sscanf(buffer, "SwapTotal: %d", &total))
4485 lpmem->dwTotalPageFile = total*1024;
4486 if (sscanf(buffer, "SwapFree: %d", &free))
4487 lpmem->dwAvailPageFile = free*1024;
4488 if (sscanf(buffer, "Buffers: %d", &buffers))
4489 lpmem->dwAvailPhys += buffers*1024;
4490 if (sscanf(buffer, "Cached: %d", &cached))
4491 lpmem->dwAvailPhys += cached*1024;
4493 fclose( f );
4495 if (lpmem->dwTotalPhys)
4497 DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4498 DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4499 lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4500 / (TotalPhysical / 100);
4502 } else
4503 #endif
4505 /* FIXME: should do something for other systems */
4506 lpmem->dwMemoryLoad = 0;
4507 lpmem->dwTotalPhys = 16*1024*1024;
4508 lpmem->dwAvailPhys = 16*1024*1024;
4509 lpmem->dwTotalPageFile = 16*1024*1024;
4510 lpmem->dwAvailPageFile = 16*1024*1024;
4512 expGetSystemInfo(&si);
4513 lpmem->dwTotalVirtual = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
4514 /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4515 lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
4516 memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4517 cache_lastchecked = time(NULL);
4519 /* it appears some memory display programs want to divide by these values */
4520 if(lpmem->dwTotalPageFile==0)
4521 lpmem->dwTotalPageFile++;
4523 if(lpmem->dwAvailPageFile==0)
4524 lpmem->dwAvailPageFile++;
4527 static INT WINAPI expGetThreadPriority(HANDLE hthread)
4529 dbgprintf("GetThreadPriority(%p)\n",hthread);
4530 return 0;
4533 /**********************************************************************
4534 * SetThreadPriority [KERNEL32.@] Sets priority for thread.
4536 * RETURNS
4537 * Success: TRUE
4538 * Failure: FALSE
4540 static WIN_BOOL WINAPI expSetThreadPriority(
4541 HANDLE hthread, /* [in] Handle to thread */
4542 INT priority) /* [in] Thread priority level */
4544 dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4545 return TRUE;
4548 static void WINAPI expExitProcess( DWORD status )
4550 printf("EXIT - code %ld\n",status);
4551 exit(status);
4554 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4555 printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4556 #ifdef QTX
4557 if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4558 return IDIGNORE;
4559 #endif
4560 return IDOK;
4563 /* these are needed for mss1 */
4566 * \brief this symbol is defined within exp_EH_prolog_dummy
4567 * \param dest jump target
4569 void exp_EH_prolog(void *dest);
4570 //! just a dummy function that acts a container for the asm section
4571 void exp_EH_prolog_dummy(void) {
4572 __asm__ volatile (
4573 // take care, this "function" may not change flags or
4574 // registers besides eax (which is also why we can't use
4575 // exp_EH_prolog_dummy directly)
4576 MANGLE(exp_EH_prolog)": \n\t"
4577 "pop %eax \n\t"
4578 "push %ebp \n\t"
4579 "mov %esp, %ebp \n\t"
4580 "lea -12(%esp), %esp \n\t"
4581 "jmp *%eax \n\t"
4585 #include <netinet/in.h>
4586 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4588 // dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4589 return htonl(hostlong);
4592 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4594 // dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4595 return ntohl(netlong);
4597 static void WINAPI expVariantInit(void* p)
4599 printf("InitCommonControls called!\n");
4600 return;
4603 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4605 dbgprintf("RegisterClassA(%p) => random id\n", wc);
4606 return time(NULL); /* be precise ! */
4609 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4611 dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4612 return 0;
4615 #ifdef QTX
4616 /* should be fixed bcs it's not fully strlen equivalent */
4617 static int expSysStringByteLen(void *str)
4619 dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4620 return strlen(str);
4623 static int expDirectDrawCreate(void)
4625 dbgprintf("DirectDrawCreate(...) => NULL\n");
4626 return 0;
4629 #if 1
4630 typedef struct tagPALETTEENTRY {
4631 BYTE peRed;
4632 BYTE peGreen;
4633 BYTE peBlue;
4634 BYTE peFlags;
4635 } PALETTEENTRY;
4637 /* reversed the first 2 entries */
4638 typedef struct tagLOGPALETTE {
4639 WORD palNumEntries;
4640 WORD palVersion;
4641 PALETTEENTRY palPalEntry[1];
4642 } LOGPALETTE;
4644 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4646 HPALETTE test;
4647 int i;
4649 dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4651 i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4652 test = (HPALETTE)malloc(i);
4653 memcpy((void *)test, lpgpl, i);
4655 return test;
4657 #else
4658 static int expCreatePalette(void)
4660 dbgprintf("CreatePalette(...) => NULL\n");
4661 return NULL;
4663 #endif
4665 static int WINAPI expGetClientRect(HWND win, RECT *r)
4667 dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4668 r->right = PSEUDO_SCREEN_WIDTH;
4669 r->left = 0;
4670 r->bottom = PSEUDO_SCREEN_HEIGHT;
4671 r->top = 0;
4672 return 1;
4675 #if 0
4676 typedef struct tagPOINT {
4677 LONG x;
4678 LONG y;
4679 } POINT, *PPOINT;
4680 #endif
4682 static int WINAPI expClientToScreen(HWND win, POINT *p)
4684 dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4685 p->x = 0;
4686 p->y = 0;
4687 return 1;
4689 #endif
4691 /* for m3jpeg */
4692 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4694 dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4695 return 0;
4698 static int WINAPI expMessageBeep(int type)
4700 dbgprintf("MessageBeep(%d) => 1\n", type);
4701 return 1;
4704 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4705 HWND parent, void *dialog_func, void *init_param)
4707 dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4708 inst, name, name, parent, dialog_func, init_param);
4709 return 0x42424242;
4712 static void WINAPI expRegisterClipboardFormatA(const char *name) {
4713 dbgprintf("RegisterClipboardFormatA(0x%x = %s)\n", name, name);
4716 /* needed by imagepower mjpeg2k */
4717 static void *exprealloc(void *ptr, size_t size)
4719 dbgprintf("realloc(0x%x, %x)\n", ptr, size);
4720 if (!ptr)
4721 return my_mreq(size,0);
4722 else
4723 return my_realloc(ptr, size);
4726 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
4727 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
4729 return 1;
4732 static char * WINAPI expPathFindExtensionA(const char *path) {
4733 char *ext;
4734 if (!path)
4735 ext = NULL;
4736 else {
4737 ext = strrchr(path, '.');
4738 if (!ext)
4739 ext = &path[strlen(path)];
4741 dbgprintf("PathFindExtensionA(0x%x = %s) => 0x%x, %s\n", path, path, ext, ext);
4742 return ext;
4745 static char * WINAPI expPathFindFileNameA(const char *path) {
4746 char *name;
4747 if (!path || strlen(path) < 2)
4748 name = path;
4749 else {
4750 name = strrchr(path - 1, '\\');
4751 if (!name)
4752 name = path;
4754 dbgprintf("PathFindFileNameA(0x%x = %s) => 0x%x, %s\n", path, path, name, name);
4755 return name;
4758 static double expfloor(double x)
4760 dbgprintf("floor(%lf)\n", x);
4761 return floor(x);
4764 #define FPU_DOUBLE(var) double var; \
4765 __asm__ volatile( "fstpl %0;fwait" : "=m" (var) : )
4767 static double exp_CIcos(void)
4769 FPU_DOUBLE(x);
4771 dbgprintf("_CIcos(%lf)\n", x);
4772 return cos(x);
4775 static double exp_CIsin(void)
4777 FPU_DOUBLE(x);
4779 dbgprintf("_CIsin(%lf)\n", x);
4780 return sin(x);
4783 static double exp_CIsqrt(void)
4785 FPU_DOUBLE(x);
4787 dbgprintf("_CIsqrt(%lf)\n", x);
4788 return sqrt(x);
4791 /* Needed by rp8 sipr decoder */
4792 static LPSTR WINAPI expCharNextA(LPCSTR ptr)
4794 if (!*ptr) return (LPSTR)ptr;
4795 // dbgprintf("CharNextA(0x%08x), %s\n", ptr, ptr);
4796 return (LPSTR)(ptr + 1);
4799 // Fake implementation, needed by wvc1dmod.dll
4800 static int WINAPI expPropVariantClear(void *pvar)
4802 // dbgprintf("PropVariantclear (0x%08x), %s\n", ptr, ptr);
4803 return 1;
4806 // This define is fake, the real thing is a struct
4807 #define LPDEVMODEA void*
4808 // Dummy implementation, always return 1
4809 // Required for frapsvid.dll 2.8.1, return value does not matter
4810 static WIN_BOOL WINAPI expEnumDisplaySettingsA(LPCSTR name ,DWORD n,
4811 LPDEVMODEA devmode)
4813 dbgprintf("EnumDisplaySettingsA (dummy) => 1\n");
4814 return 1;
4817 // Fake implementation of _decode_pointer from msvcr80.dll, needed by sirenacm.dll
4818 // NOTE: undocumented function, probably the declaration is not right
4819 static int exp_decode_pointer(void *ptr)
4821 dbgprintf("_decode_pointer (0x%08x)\n", ptr);
4822 return 0;
4825 /* Fake implementation of sdt::_Lockit::_Lockit(void) from msvcp60.dll
4826 Needed by SCLS.DLL */
4827 static int exp_0Lockit_dummy(void)
4829 dbgprintf("0Lockit_dummy (??0_Lockit@std@@QAE@XZ)\n");
4830 return 0;
4833 /* Fake implementation of sdt::_Lockit::~_Lockit(void) from msvcp60.dll
4834 Needed by SCLS.DLL */
4835 static int exp_1Lockit_dummy(void)
4837 dbgprintf("1Lockit_dummy (??1_Lockit@std@@QAE@XZ)\n");
4838 return 0;
4841 struct exports
4843 char name[64];
4844 int id;
4845 void* func;
4847 struct libs
4849 char name[64];
4850 int length;
4851 struct exports* exps;
4854 #define FF(X,Y) \
4855 {#X, Y, (void*)exp##X},
4857 #define UNDEFF(X, Y) \
4858 {#X, Y, (void*)-1},
4860 struct exports exp_kernel32[]=
4862 FF(GetVolumeInformationA,-1)
4863 FF(GetDriveTypeA,-1)
4864 FF(GetLogicalDriveStringsA,-1)
4865 FF(IsBadWritePtr, 357)
4866 FF(IsBadReadPtr, 354)
4867 FF(IsBadStringPtrW, -1)
4868 FF(IsBadStringPtrA, -1)
4869 FF(DisableThreadLibraryCalls, -1)
4870 FF(CreateThread, -1)
4871 FF(CreateEventA, -1)
4872 FF(SetEvent, -1)
4873 FF(ResetEvent, -1)
4874 FF(WaitForSingleObject, -1)
4875 #ifdef QTX
4876 FF(WaitForMultipleObjects, -1)
4877 FF(ExitThread, -1)
4878 FF(CreateMutexA,-1)
4879 FF(ReleaseMutex,-1)
4880 #endif
4881 FF(GetSystemInfo, -1)
4882 FF(GetVersion, 332)
4883 FF(HeapCreate, 461)
4884 FF(HeapAlloc, -1)
4885 FF(HeapDestroy, -1)
4886 FF(HeapFree, -1)
4887 FF(HeapSize, -1)
4888 FF(HeapReAlloc,-1)
4889 FF(GetProcessHeap, -1)
4890 FF(VirtualAlloc, -1)
4891 FF(VirtualFree, -1)
4892 FF(InitializeCriticalSection, -1)
4893 FF(EnterCriticalSection, -1)
4894 FF(LeaveCriticalSection, -1)
4895 FF(DeleteCriticalSection, -1)
4896 FF(TlsAlloc, -1)
4897 FF(TlsFree, -1)
4898 FF(TlsGetValue, -1)
4899 FF(TlsSetValue, -1)
4900 FF(GetCurrentThreadId, -1)
4901 FF(GetCurrentProcess, -1)
4902 FF(LocalAlloc, -1)
4903 FF(LocalReAlloc,-1)
4904 FF(LocalLock, -1)
4905 FF(GlobalAlloc, -1)
4906 FF(GlobalReAlloc, -1)
4907 FF(GlobalLock, -1)
4908 FF(GlobalSize, -1)
4909 FF(MultiByteToWideChar, 427)
4910 FF(WideCharToMultiByte, -1)
4911 FF(GetVersionExA, -1)
4912 FF(CreateSemaphoreA, -1)
4913 FF(QueryPerformanceCounter, -1)
4914 FF(QueryPerformanceFrequency, -1)
4915 FF(LocalHandle, -1)
4916 FF(LocalUnlock, -1)
4917 FF(LocalFree, -1)
4918 FF(GlobalHandle, -1)
4919 FF(GlobalUnlock, -1)
4920 FF(GlobalFree, -1)
4921 FF(LoadResource, -1)
4922 FF(ReleaseSemaphore, -1)
4923 FF(FindResourceA, -1)
4924 FF(LockResource, -1)
4925 FF(FreeResource, -1)
4926 FF(SizeofResource, -1)
4927 FF(CloseHandle, -1)
4928 FF(GetCommandLineA, -1)
4929 FF(GetEnvironmentStringsW, -1)
4930 FF(FreeEnvironmentStringsW, -1)
4931 FF(FreeEnvironmentStringsA, -1)
4932 FF(GetEnvironmentStrings, -1)
4933 FF(GetStartupInfoA, -1)
4934 FF(GetStdHandle, -1)
4935 FF(GetFileType, -1)
4936 #ifdef QTX
4937 FF(GetFileAttributesA, -1)
4938 #endif
4939 FF(SetHandleCount, -1)
4940 FF(GetACP, -1)
4941 FF(GetModuleFileNameA, -1)
4942 FF(SetUnhandledExceptionFilter, -1)
4943 FF(LoadLibraryA, -1)
4944 FF(GetProcAddress, -1)
4945 FF(FreeLibrary, -1)
4946 FF(CreateFileMappingA, -1)
4947 FF(OpenFileMappingA, -1)
4948 FF(MapViewOfFile, -1)
4949 FF(UnmapViewOfFile, -1)
4950 FF(Sleep, -1)
4951 FF(GetModuleHandleA, -1)
4952 FF(GetProfileIntA, -1)
4953 FF(GetPrivateProfileIntA, -1)
4954 FF(GetPrivateProfileStringA, -1)
4955 FF(WritePrivateProfileStringA, -1)
4956 FF(GetLastError, -1)
4957 FF(SetLastError, -1)
4958 FF(InterlockedIncrement, -1)
4959 FF(InterlockedDecrement, -1)
4960 FF(GetTimeZoneInformation, -1)
4961 FF(OutputDebugStringA, -1)
4962 FF(GetLocalTime, -1)
4963 FF(GetSystemTime, -1)
4964 FF(GetSystemTimeAsFileTime, -1)
4965 FF(GetEnvironmentVariableA, -1)
4966 FF(SetEnvironmentVariableA, -1)
4967 FF(RtlZeroMemory,-1)
4968 FF(RtlMoveMemory,-1)
4969 FF(RtlFillMemory,-1)
4970 FF(GetTempPathA,-1)
4971 FF(FindFirstFileA,-1)
4972 FF(FindNextFileA,-1)
4973 FF(FindClose,-1)
4974 FF(FileTimeToLocalFileTime,-1)
4975 FF(DeleteFileA,-1)
4976 FF(ReadFile,-1)
4977 FF(WriteFile,-1)
4978 FF(SetFilePointer,-1)
4979 FF(GetTempFileNameA,-1)
4980 FF(CreateFileA,-1)
4981 FF(GetSystemDirectoryA,-1)
4982 FF(GetWindowsDirectoryA,-1)
4983 #ifdef QTX
4984 FF(GetCurrentDirectoryA,-1)
4985 FF(SetCurrentDirectoryA,-1)
4986 FF(CreateDirectoryA,-1)
4987 #endif
4988 FF(GetShortPathNameA,-1)
4989 FF(GetFullPathNameA,-1)
4990 FF(SetErrorMode, -1)
4991 FF(IsProcessorFeaturePresent, -1)
4992 FF(GetProcessAffinityMask, -1)
4993 FF(InterlockedExchange, -1)
4994 FF(InterlockedCompareExchange, -1)
4995 FF(MulDiv, -1)
4996 FF(lstrcmpiA, -1)
4997 FF(lstrlenA, -1)
4998 FF(lstrcpyA, -1)
4999 FF(lstrcatA, -1)
5000 FF(lstrcpynA,-1)
5001 FF(GetProcessVersion,-1)
5002 FF(GetCurrentThread,-1)
5003 FF(GetOEMCP,-1)
5004 FF(GetCPInfo,-1)
5005 FF(DuplicateHandle,-1)
5006 FF(GetTickCount, -1)
5007 FF(SetThreadAffinityMask,-1)
5008 FF(GetCurrentProcessId,-1)
5009 FF(GlobalMemoryStatus,-1)
5010 FF(GetThreadPriority,-1)
5011 FF(SetThreadPriority,-1)
5012 FF(ExitProcess,-1)
5013 {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
5014 FF(SetThreadIdealProcessor,-1)
5015 FF(SetProcessAffinityMask, -1)
5016 UNDEFF(FlsAlloc, -1)
5017 UNDEFF(FlsGetValue, -1)
5018 UNDEFF(FlsSetValue, -1)
5019 UNDEFF(FlsFree, -1)
5022 struct exports exp_msvcrt[]={
5023 FF(malloc, -1)
5024 FF(_initterm, -1)
5025 FF(__dllonexit, -1)
5026 FF(_snprintf,-1)
5027 FF(free, -1)
5028 {"??3@YAXPAX@Z", -1, expdelete},
5029 {"??2@YAPAXI@Z", -1, expnew},
5030 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5031 {"_winver",-1,(void*)&_winver},
5032 FF(strrchr, -1)
5033 FF(strchr, -1)
5034 FF(strlen, -1)
5035 FF(strcpy, -1)
5036 FF(strncpy, -1)
5037 FF(wcscpy, -1)
5038 FF(strcmp, -1)
5039 FF(strncmp, -1)
5040 FF(strcat, -1)
5041 FF(_stricmp,-1)
5042 FF(_strdup,-1)
5043 FF(_setjmp3,-1)
5044 FF(isalnum, -1)
5045 FF(isspace, -1)
5046 FF(isalpha, -1)
5047 FF(isdigit, -1)
5048 FF(memmove, -1)
5049 FF(memcmp, -1)
5050 FF(memset, -1)
5051 FF(memcpy, -1)
5052 FF(time, -1)
5053 FF(rand, -1)
5054 FF(srand, -1)
5055 FF(log10, -1)
5056 FF(pow, -1)
5057 FF(cos, -1)
5058 FF(_ftol,-1)
5059 FF(_CIpow,-1)
5060 FF(_CIcos,-1)
5061 FF(_CIsin,-1)
5062 FF(_CIsqrt,-1)
5063 FF(ldexp,-1)
5064 FF(frexp,-1)
5065 FF(sprintf,-1)
5066 FF(sscanf,-1)
5067 FF(fopen,-1)
5068 FF(fprintf,-1)
5069 FF(printf,-1)
5070 FF(getenv,-1)
5071 FF(floor,-1)
5072 /* needed by frapsvid.dll */
5073 {"strstr",-1,(char *)&strstr},
5074 {"qsort",-1,(void *)&qsort},
5075 FF(_EH_prolog,-1)
5076 FF(calloc,-1)
5077 {"ceil",-1,(void*)&ceil},
5078 /* needed by imagepower mjpeg2k */
5079 {"clock",-1,(void*)&clock},
5080 {"memchr",-1,(void*)&memchr},
5081 {"vfprintf",-1,(void*)&vfprintf},
5082 // {"realloc",-1,(void*)&realloc},
5083 FF(realloc,-1)
5084 {"puts",-1,(void*)&puts}
5086 struct exports exp_winmm[]={
5087 FF(GetDriverModuleHandle, -1)
5088 FF(timeGetTime, -1)
5089 FF(DefDriverProc, -1)
5090 FF(OpenDriverA, -1)
5091 FF(OpenDriver, -1)
5092 FF(timeGetDevCaps, -1)
5093 FF(timeBeginPeriod, -1)
5094 #ifdef QTX
5095 FF(timeEndPeriod, -1)
5096 FF(waveOutGetNumDevs, -1)
5097 #endif
5099 struct exports exp_user32[]={
5100 FF(LoadIconA,-1)
5101 FF(LoadStringA, -1)
5102 FF(wsprintfA, -1)
5103 FF(GetDC, -1)
5104 FF(GetDesktopWindow, -1)
5105 FF(ReleaseDC, -1)
5106 FF(IsRectEmpty, -1)
5107 FF(LoadCursorA,-1)
5108 FF(SetCursor,-1)
5109 FF(GetCursorPos,-1)
5110 #ifdef QTX
5111 FF(ShowCursor,-1)
5112 #endif
5113 FF(RegisterWindowMessageA,-1)
5114 FF(GetSystemMetrics,-1)
5115 FF(GetSysColor,-1)
5116 FF(GetSysColorBrush,-1)
5117 FF(GetWindowDC, -1)
5118 FF(DrawTextA, -1)
5119 FF(MessageBoxA, -1)
5120 FF(RegisterClassA, -1)
5121 FF(UnregisterClassA, -1)
5122 #ifdef QTX
5123 FF(GetWindowRect, -1)
5124 FF(MonitorFromWindow, -1)
5125 FF(MonitorFromRect, -1)
5126 FF(MonitorFromPoint, -1)
5127 FF(EnumDisplayMonitors, -1)
5128 FF(GetMonitorInfoA, -1)
5129 FF(EnumDisplayDevicesA, -1)
5130 FF(GetClientRect, -1)
5131 FF(ClientToScreen, -1)
5132 FF(IsWindowVisible, -1)
5133 FF(GetActiveWindow, -1)
5134 FF(GetClassNameA, -1)
5135 FF(GetClassInfoA, -1)
5136 FF(GetWindowLongA, -1)
5137 FF(EnumWindows, -1)
5138 FF(GetWindowThreadProcessId, -1)
5139 FF(CreateWindowExA, -1)
5140 #endif
5141 FF(MessageBeep, -1)
5142 FF(DialogBoxParamA, -1)
5143 FF(RegisterClipboardFormatA, -1)
5144 FF(CharNextA, -1)
5145 FF(EnumDisplaySettingsA, -1)
5147 struct exports exp_advapi32[]={
5148 FF(RegCloseKey, -1)
5149 FF(RegCreateKeyA, -1)
5150 FF(RegCreateKeyExA, -1)
5151 FF(RegEnumKeyExA, -1)
5152 FF(RegEnumValueA, -1)
5153 FF(RegOpenKeyA, -1)
5154 FF(RegOpenKeyExA, -1)
5155 FF(RegQueryValueExA, -1)
5156 FF(RegSetValueExA, -1)
5157 FF(RegQueryInfoKeyA, -1)
5159 struct exports exp_gdi32[]={
5160 FF(CreateCompatibleDC, -1)
5161 FF(CreateFontA, -1)
5162 FF(DeleteDC, -1)
5163 FF(DeleteObject, -1)
5164 FF(GetDeviceCaps, -1)
5165 FF(GetSystemPaletteEntries, -1)
5166 #ifdef QTX
5167 FF(CreatePalette, -1)
5168 FF(GetObjectA, -1)
5169 FF(CreateRectRgn, -1)
5170 #endif
5172 struct exports exp_version[]={
5173 FF(GetFileVersionInfoSizeA, -1)
5175 struct exports exp_ole32[]={
5176 FF(CoCreateFreeThreadedMarshaler,-1)
5177 FF(CoCreateInstance, -1)
5178 FF(CoInitialize, -1)
5179 FF(CoInitializeEx, -1)
5180 FF(CoUninitialize, -1)
5181 FF(CoTaskMemAlloc, -1)
5182 FF(CoTaskMemFree, -1)
5183 FF(StringFromGUID2, -1)
5184 FF(PropVariantClear, -1)
5186 // do we really need crtdll ???
5187 // msvcrt is the correct place probably...
5188 struct exports exp_crtdll[]={
5189 FF(memcpy, -1)
5190 FF(wcscpy, -1)
5192 struct exports exp_comctl32[]={
5193 FF(StringFromGUID2, -1)
5194 FF(InitCommonControls, 17)
5195 #ifdef QTX
5196 FF(CreateUpDownControl, 16)
5197 #endif
5199 struct exports exp_wsock32[]={
5200 FF(htonl,8)
5201 FF(ntohl,14)
5203 struct exports exp_msdmo[]={
5204 FF(memcpy, -1) // just test
5205 FF(MoCopyMediaType, -1)
5206 FF(MoCreateMediaType, -1)
5207 FF(MoDeleteMediaType, -1)
5208 FF(MoDuplicateMediaType, -1)
5209 FF(MoFreeMediaType, -1)
5210 FF(MoInitMediaType, -1)
5212 struct exports exp_oleaut32[]={
5213 FF(VariantInit, 8)
5214 #ifdef QTX
5215 FF(SysStringByteLen, 149)
5216 #endif
5219 /* realplayer8:
5220 DLL Name: PNCRT.dll
5221 vma: Hint/Ord Member-Name
5222 22ff4 615 free
5223 2302e 250 _ftol
5224 22fea 666 malloc
5225 2303e 609 fprintf
5226 2305e 167 _adjust_fdiv
5227 23052 280 _initterm
5229 22ffc 176 _beginthreadex
5230 23036 284 _iob
5231 2300e 85 __CxxFrameHandler
5232 23022 411 _purecall
5234 #ifdef REALPLAYER
5235 struct exports exp_pncrt[]={
5236 FF(malloc, -1) // just test
5237 FF(free, -1) // just test
5238 FF(fprintf, -1) // just test
5239 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5240 FF(_ftol,-1)
5241 FF(_initterm, -1)
5242 {"??3@YAXPAX@Z", -1, expdelete},
5243 {"??2@YAPAXI@Z", -1, expnew},
5244 FF(__dllonexit, -1)
5245 FF(strncpy, -1)
5246 FF(_CIpow,-1)
5247 FF(calloc,-1)
5248 FF(memmove, -1)
5249 FF(ldexp, -1)
5250 FF(frexp, -1)
5252 #endif
5254 #ifdef QTX
5255 struct exports exp_ddraw[]={
5256 FF(DirectDrawCreate, -1)
5258 #endif
5260 struct exports exp_comdlg32[]={
5261 FF(GetOpenFileNameA, -1)
5264 struct exports exp_shlwapi[]={
5265 FF(PathFindExtensionA, -1)
5266 FF(PathFindFileNameA, -1)
5269 struct exports exp_msvcr80[]={
5270 FF(_CIpow,-1)
5271 FF(_CIsin,-1)
5272 FF(_CIcos,-1)
5273 FF(_CIsqrt,-1)
5274 FF(memset,-1)
5275 FF(_initterm_e, -1)
5276 FF(_initterm, -1)
5277 FF(_decode_pointer, -1)
5280 struct exports exp_msvcp60[]={
5281 {"??0_Lockit@std@@QAE@XZ", -1, exp_0Lockit_dummy},
5282 {"??1_Lockit@std@@QAE@XZ", -1, exp_1Lockit_dummy}
5285 #define LL(X) \
5286 {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5288 struct libs libraries[]={
5289 LL(kernel32)
5290 LL(msvcrt)
5291 LL(winmm)
5292 LL(user32)
5293 LL(advapi32)
5294 LL(gdi32)
5295 LL(version)
5296 LL(ole32)
5297 LL(oleaut32)
5298 LL(crtdll)
5299 LL(comctl32)
5300 LL(wsock32)
5301 LL(msdmo)
5302 #ifdef REALPLAYER
5303 LL(pncrt)
5304 #endif
5305 #ifdef QTX
5306 LL(ddraw)
5307 #endif
5308 LL(comdlg32)
5309 LL(shlwapi)
5310 LL(msvcr80)
5311 LL(msvcp60)
5314 static WIN_BOOL WINAPI ext_stubs(void)
5316 volatile int idx = 0xdeadabcd;
5317 // make sure gcc does not do eip-relative call or something like that
5318 volatile void (*my_printf)(char *, char *) = (void *)0xdeadfbcd;
5319 my_printf("Called unk_%s\n", export_names[idx]);
5320 return 0;
5323 #define MAX_STUB_SIZE 0x60
5324 #define MAX_NUM_STUBS 200
5325 static int pos=0;
5326 static char *extcode = NULL;
5328 static void* add_stub(void)
5330 int i;
5331 int found = 0;
5332 // generated code in runtime!
5333 char* answ;
5334 if (!extcode)
5335 extcode = mmap_anon(NULL, MAX_NUM_STUBS * MAX_STUB_SIZE,
5336 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0);
5337 answ = extcode + pos * MAX_STUB_SIZE;
5338 if (pos >= MAX_NUM_STUBS) {
5339 printf("too many stubs, expect crash\n");
5340 return NULL;
5342 memcpy(answ, ext_stubs, MAX_STUB_SIZE);
5343 for (i = 0; i < MAX_STUB_SIZE - 3; i++) {
5344 int *magic = (int *)(answ + i);
5345 if (*magic == 0xdeadabcd) {
5346 *magic = pos;
5347 found |= 1;
5349 if (*magic == 0xdeadfbcd) {
5350 *magic = (intptr_t)printf;
5351 found |= 2;
5354 if (found != 3) {
5355 printf("magic code not found in ext_subs, expect crash\n");
5356 return NULL;
5358 pos++;
5359 return (void*)answ;
5362 void* LookupExternal(const char* library, int ordinal)
5364 int i,j;
5365 if(library==0)
5367 printf("ERROR: library=0\n");
5368 return (void*)ext_unknown;
5370 // printf("%x %x\n", &unk_exp1, &unk_exp2);
5372 dbgprintf("External func %s:%d\n", library, ordinal);
5374 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5376 if(strcasecmp(library, libraries[i].name))
5377 continue;
5378 for(j=0; j<libraries[i].length; j++)
5380 if(ordinal!=libraries[i].exps[j].id)
5381 continue;
5382 //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5383 return libraries[i].exps[j].func;
5387 #ifndef LOADLIB_TRY_NATIVE
5388 /* hack for truespeech and vssh264*/
5389 if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5390 #endif
5391 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5393 int hand;
5394 WINE_MODREF *wm;
5395 void *func;
5397 hand = LoadLibraryA(library);
5398 if (!hand)
5399 goto no_dll;
5400 wm = MODULE32_LookupHMODULE(hand);
5401 if (!wm)
5403 FreeLibrary(hand);
5404 goto no_dll;
5406 func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5407 if (!func)
5409 printf("No such ordinal in external dll\n");
5410 FreeLibrary((int)hand);
5411 goto no_dll;
5414 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5415 hand, func);
5416 return func;
5419 no_dll:
5420 if(pos>150)return 0;
5421 sprintf(export_names[pos], "%s:%d", library, ordinal);
5422 return add_stub();
5425 void* LookupExternalByName(const char* library, const char* name)
5427 int i,j;
5428 // return (void*)ext_unknown;
5429 if(library==0)
5431 printf("ERROR: library=0\n");
5432 return (void*)ext_unknown;
5434 if((unsigned long)name<=0xffff)
5436 return LookupExternal(library, (int)name);
5438 dbgprintf("External func %s:%s\n", library, name);
5439 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5441 if(strcasecmp(library, libraries[i].name))
5442 continue;
5443 for(j=0; j<libraries[i].length; j++)
5445 if(strcmp(name, libraries[i].exps[j].name))
5446 continue;
5447 if((unsigned int)(libraries[i].exps[j].func) == -1)
5448 return NULL; //undefined func
5449 // printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5450 return libraries[i].exps[j].func;
5454 #ifndef LOADLIB_TRY_NATIVE
5455 /* hack for vss h264 */
5456 if (!strcmp(library,"vssh264core.dll") || !strcmp(library,"3ivx.dll"))
5457 #endif
5458 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5460 int hand;
5461 WINE_MODREF *wm;
5462 void *func;
5464 hand = LoadLibraryA(library);
5465 if (!hand)
5466 goto no_dll_byname;
5467 wm = MODULE32_LookupHMODULE(hand);
5468 if (!wm)
5470 FreeLibrary(hand);
5471 goto no_dll_byname;
5473 func = PE_FindExportedFunction(wm, name, 0);
5474 if (!func)
5476 printf("No such name in external dll\n");
5477 FreeLibrary((int)hand);
5478 goto no_dll_byname;
5481 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5482 hand, func);
5483 return func;
5486 no_dll_byname:
5487 if(pos>150)return 0;// to many symbols
5488 strcpy(export_names[pos], name);
5489 return add_stub();
5492 void my_garbagecollection(void)
5494 #ifdef GARBAGE
5495 int unfree = 0, unfreecnt = 0;
5497 int max_fatal = 8;
5498 free_registry();
5499 while (last_alloc)
5501 alloc_header* mem = last_alloc + 1;
5502 unfree += my_size(mem);
5503 unfreecnt++;
5504 if (my_release(mem) != 0)
5505 // avoid endless loop when memory is trashed
5506 if (--max_fatal < 0)
5507 break;
5509 dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5510 #endif
5511 g_tls = NULL;
5512 list = NULL;