Add support for extracting the release version number from a VERSION file.
[mplayer/glamo.git] / loader / win32.c
blob2ee9f1ea7e5087d3dbd30be6c015d42d25d3b648
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 #if 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 #ifdef HAVE_KSTAT
67 #include <kstat.h>
68 #endif
70 #ifdef HAVE_SYS_MMAN_H
71 #include <sys/mman.h>
72 #else
73 #include "osdep/mmap.h"
74 #endif
75 #include "osdep/mmap_anon.h"
77 char* def_path = WIN32_PATH;
79 static void do_cpuid(unsigned int ax, unsigned int *regs)
81 __asm__ volatile
83 "pushl %%ebx; pushl %%ecx; pushl %%edx;"
84 ".byte 0x0f, 0xa2;"
85 "movl %%eax, (%2);"
86 "movl %%ebx, 4(%2);"
87 "movl %%ecx, 8(%2);"
88 "movl %%edx, 12(%2);"
89 "popl %%edx; popl %%ecx; popl %%ebx;"
90 : "=a" (ax)
91 : "0" (ax), "S" (regs)
94 static unsigned int c_localcount_tsc()
96 int a;
97 __asm__ volatile
99 "rdtsc\n\t"
100 :"=a"(a)
102 :"edx"
104 return a;
106 static void c_longcount_tsc(long long* z)
108 __asm__ volatile
110 "pushl %%ebx\n\t"
111 "movl %%eax, %%ebx\n\t"
112 "rdtsc\n\t"
113 "movl %%eax, 0(%%ebx)\n\t"
114 "movl %%edx, 4(%%ebx)\n\t"
115 "popl %%ebx\n\t"
116 ::"a"(z)
117 :"edx"
120 static unsigned int c_localcount_notsc()
122 struct timeval tv;
123 unsigned limit=~0;
124 limit/=1000000;
125 gettimeofday(&tv, 0);
126 return limit*tv.tv_usec;
128 static void c_longcount_notsc(long long* z)
130 struct timeval tv;
131 unsigned long long result;
132 unsigned limit=~0;
133 if(!z)return;
134 limit/=1000000;
135 gettimeofday(&tv, 0);
136 result=tv.tv_sec;
137 result<<=32;
138 result+=limit*tv.tv_usec;
139 *z=result;
141 static unsigned int localcount_stub(void);
142 static void longcount_stub(long long*);
143 static unsigned int (*localcount)()=localcount_stub;
144 static void (*longcount)(long long*)=longcount_stub;
146 static pthread_mutex_t memmut;
148 static unsigned int localcount_stub(void)
150 unsigned int regs[4];
151 do_cpuid(1, regs);
152 if ((regs[3] & 0x00000010) != 0)
154 localcount=c_localcount_tsc;
155 longcount=c_longcount_tsc;
157 else
159 localcount=c_localcount_notsc;
160 longcount=c_longcount_notsc;
162 return localcount();
164 static void longcount_stub(long long* z)
166 unsigned int regs[4];
167 do_cpuid(1, regs);
168 if ((regs[3] & 0x00000010) != 0)
170 localcount=c_localcount_tsc;
171 longcount=c_longcount_tsc;
173 else
175 localcount=c_localcount_notsc;
176 longcount=c_longcount_notsc;
178 longcount(z);
181 #include "mp_msg.h"
182 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
183 //#define DETAILED_OUT
184 static inline void dbgprintf(char* fmt, ...)
186 #ifdef DETAILED_OUT
187 if(LOADER_DEBUG)
189 FILE* f;
190 va_list va;
191 va_start(va, fmt);
192 f=fopen("./log", "a");
193 vprintf(fmt, va);
194 fflush(stdout);
195 if(f)
197 vfprintf(f, fmt, va);
198 fsync(fileno(f));
199 fclose(f);
201 va_end(va);
203 #endif
204 if ( mp_msg_test(MSGT_WIN32,MSGL_DBG3) )
206 va_list va;
208 va_start(va, fmt);
209 vprintf(fmt, va);
210 // mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
211 va_end(va);
213 fflush(stdout);
217 char export_names[300][32]={
218 "name1",
219 //"name2",
220 //"name3"
222 //#define min(x,y) ((x)<(y)?(x):(y))
224 void destroy_event(void* event);
226 struct th_list_t;
227 typedef struct th_list_t{
228 int id;
229 void* thread;
230 struct th_list_t* next;
231 struct th_list_t* prev;
232 } th_list;
235 // have to be cleared by GARBAGE COLLECTOR
236 //static unsigned char* heap=NULL;
237 //static int heap_counter=0;
238 static tls_t* g_tls=NULL;
239 static th_list* list=NULL;
241 #if 0
242 static void test_heap(void)
244 int offset=0;
245 if(heap==0)
246 return;
247 while(offset<heap_counter)
249 if(*(int*)(heap+offset)!=0x433476)
251 printf("Heap corruption at address %d\n", offset);
252 return;
254 offset+=8+*(int*)(heap+offset+4);
256 for(;offset<min(offset+1000, 20000000); offset++)
257 if(heap[offset]!=0xCC)
259 printf("Free heap corruption at address %d\n", offset);
262 #endif
263 #undef MEMORY_DEBUG
265 #ifdef MEMORY_DEBUG
267 static void* my_mreq(int size, int to_zero)
269 static int test=0;
270 test++;
271 if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
272 // test_heap();
273 if(heap==NULL)
275 heap=malloc(20000000);
276 memset(heap, 0xCC,20000000);
278 if(heap==0)
280 printf("No enough memory\n");
281 return 0;
283 if(heap_counter+size>20000000)
285 printf("No enough memory\n");
286 return 0;
288 *(int*)(heap+heap_counter)=0x433476;
289 heap_counter+=4;
290 *(int*)(heap+heap_counter)=size;
291 heap_counter+=4;
292 printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
293 if(to_zero)
294 memset(heap+heap_counter, 0, size);
295 else
296 memset(heap+heap_counter, 0xcc, size); // make crash reproducable
297 heap_counter+=size;
298 return heap+heap_counter-size;
300 static int my_release(char* memory)
302 // test_heap();
303 if(memory==NULL)
305 printf("ERROR: free(0)\n");
306 return 0;
308 if(*(int*)(memory-8)!=0x433476)
310 printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
311 return 0;
313 printf("Freed %d bytes of memory\n", *(int*)(memory-4));
314 // memset(memory-8, *(int*)(memory-4), 0xCC);
315 return 0;
318 #else
319 #define GARBAGE
320 typedef struct alloc_header_t alloc_header;
321 struct alloc_header_t
323 // let's keep allocated data 16 byte aligned
324 alloc_header* prev;
325 alloc_header* next;
326 long deadbeef;
327 long size;
328 long type;
329 long reserved1;
330 long reserved2;
331 long reserved3;
334 #ifdef GARBAGE
335 static alloc_header* last_alloc = NULL;
336 static int alccnt = 0;
337 #endif
339 #define AREATYPE_CLIENT 0
340 #define AREATYPE_EVENT 1
341 #define AREATYPE_MUTEX 2
342 #define AREATYPE_COND 3
343 #define AREATYPE_CRITSECT 4
345 /* -- critical sections -- */
346 struct CRITSECT
348 pthread_t id;
349 pthread_mutex_t mutex;
350 int locked;
351 long deadbeef;
354 void* mreq_private(int size, int to_zero, int type);
355 void* mreq_private(int size, int to_zero, int type)
357 int nsize = size + sizeof(alloc_header);
358 alloc_header* header = (alloc_header* ) malloc(nsize);
359 if (!header)
360 return 0;
361 if (to_zero)
362 memset(header, 0, nsize);
363 #ifdef GARBAGE
364 if (!last_alloc)
366 pthread_mutex_init(&memmut, NULL);
367 pthread_mutex_lock(&memmut);
369 else
371 pthread_mutex_lock(&memmut);
372 last_alloc->next = header; /* set next */
375 header->prev = last_alloc;
376 header->next = 0;
377 last_alloc = header;
378 alccnt++;
379 pthread_mutex_unlock(&memmut);
380 #endif
381 header->deadbeef = 0xdeadbeef;
382 header->size = size;
383 header->type = type;
385 //if (alccnt < 40000) printf("MY_REQ: %p\t%d t:%d (cnt:%d)\n", header, size, type, alccnt);
386 return header + 1;
389 static int my_release(void* memory)
391 alloc_header* header = (alloc_header*) memory - 1;
392 #ifdef GARBAGE
393 alloc_header* prevmem;
394 alloc_header* nextmem;
396 if (memory == 0)
397 return 0;
399 if (header->deadbeef != (long) 0xdeadbeef)
401 dbgprintf("FATAL releasing corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
402 return 0;
405 pthread_mutex_lock(&memmut);
407 switch(header->type)
409 case AREATYPE_EVENT:
410 destroy_event(memory);
411 break;
412 case AREATYPE_COND:
413 pthread_cond_destroy((pthread_cond_t*)memory);
414 break;
415 case AREATYPE_MUTEX:
416 pthread_mutex_destroy((pthread_mutex_t*)memory);
417 break;
418 case AREATYPE_CRITSECT:
419 pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
420 break;
421 default:
422 //memset(memory, 0xcc, header->size);
426 header->deadbeef = 0;
427 prevmem = header->prev;
428 nextmem = header->next;
430 if (prevmem)
431 prevmem->next = nextmem;
432 if (nextmem)
433 nextmem->prev = prevmem;
435 if (header == last_alloc)
436 last_alloc = prevmem;
438 alccnt--;
440 if (last_alloc)
441 pthread_mutex_unlock(&memmut);
442 else
443 pthread_mutex_destroy(&memmut);
445 //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld (%d)\n", header, header->size, alccnt);
446 #else
447 if (memory == 0)
448 return 0;
449 #endif
450 //memset(header + 1, 0xcc, header->size);
451 free(header);
452 return 0;
454 #endif
456 static inline void* my_mreq(int size, int to_zero)
458 return mreq_private(size, to_zero, AREATYPE_CLIENT);
461 static int my_size(void* memory)
463 if(!memory) return 0;
464 return ((alloc_header*)memory)[-1].size;
467 static void* my_realloc(void* memory, int size)
469 void *ans = memory;
470 int osize;
471 if (memory == NULL)
472 return my_mreq(size, 0);
473 osize = my_size(memory);
474 if (osize < size)
476 ans = my_mreq(size, 0);
477 memcpy(ans, memory, osize);
478 my_release(memory);
480 return ans;
485 * WINE API - native implementation for several win32 libraries
489 static int WINAPI ext_unknown()
491 printf("Unknown func called\n");
492 return 0;
495 static int WINAPI expGetVolumeInformationA( const char *root, char *label,
496 unsigned int label_len, unsigned int *serial,
497 unsigned int *filename_len,unsigned int *flags,
498 char *fsname, unsigned int fsname_len )
500 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
501 root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
502 //hack Do not return any real data - do nothing
503 return 1;
506 static unsigned int WINAPI expGetDriveTypeA( const char *root )
508 dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
509 // hack return as Fixed Drive Type
510 return DRIVE_FIXED;
513 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
515 dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
516 // hack only have one drive c:\ in this hack
517 *buffer++='c';
518 *buffer++=':';
519 *buffer++='\\';
520 *buffer++='\0';
521 *buffer= '\0';
522 return 4; // 1 drive * 4 bytes (includes null)
526 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
528 int result = (count == 0 || ptr != 0) ? 0 : 1;
529 dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
530 return result;
532 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
534 int result = (count == 0 || ptr != 0) ? 0 : 1;
535 dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
536 return result;
538 static int WINAPI expDisableThreadLibraryCalls(int module)
540 dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
541 return 0;
544 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
546 HMODULE result;
547 if (pdrv==NULL)
548 result=0;
549 else
550 result=pdrv->hDriverModule;
551 dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
552 return result;
555 #define MODULE_HANDLE_kernel32 ((HMODULE)0x120)
556 #define MODULE_HANDLE_user32 ((HMODULE)0x121)
557 #ifdef QTX
558 #define MODULE_HANDLE_wininet ((HMODULE)0x122)
559 #define MODULE_HANDLE_ddraw ((HMODULE)0x123)
560 #define MODULE_HANDLE_advapi32 ((HMODULE)0x124)
561 #endif
562 #define MODULE_HANDLE_comdlg32 ((HMODULE)0x125)
563 #define MODULE_HANDLE_msvcrt ((HMODULE)0x126)
564 #define MODULE_HANDLE_ole32 ((HMODULE)0x127)
565 #define MODULE_HANDLE_winmm ((HMODULE)0x128)
567 static HMODULE WINAPI expGetModuleHandleA(const char* name)
569 WINE_MODREF* wm;
570 HMODULE result;
571 if(!name)
572 #ifdef QTX
573 result=1;
574 #else
575 result=0;
576 #endif
577 else
579 wm=MODULE_FindModule(name);
580 if(wm==0)result=0;
581 else
582 result=(HMODULE)(wm->module);
584 if(!result)
586 if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
587 result=MODULE_HANDLE_kernel32;
588 #ifdef QTX
589 if(name && strcasecmp(name, "user32")==0)
590 result=MODULE_HANDLE_user32;
591 #endif
593 dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
594 return result;
597 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
598 void* lpStartAddress, void* lpParameter,
599 long dwFlags, long* dwThreadId)
601 pthread_t *pth;
602 // printf("CreateThread:");
603 pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
604 pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
605 if(dwFlags)
606 printf( "WARNING: CreateThread flags not supported\n");
607 if(dwThreadId)
608 *dwThreadId=(long)pth;
609 if(list==NULL)
611 list=my_mreq(sizeof(th_list), 1);
612 list->next=list->prev=NULL;
614 else
616 list->next=my_mreq(sizeof(th_list), 0);
617 list->next->prev=list;
618 list->next->next=NULL;
619 list=list->next;
621 list->thread=pth;
622 dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
623 pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
624 return pth;
627 struct mutex_list_t;
629 struct mutex_list_t
631 char type;
632 pthread_mutex_t *pm;
633 pthread_cond_t *pc;
634 char state;
635 char reset;
636 char name[128];
637 int semaphore;
638 struct mutex_list_t* next;
639 struct mutex_list_t* prev;
641 typedef struct mutex_list_t mutex_list;
642 static mutex_list* mlist=NULL;
644 void destroy_event(void* event)
646 mutex_list* pp=mlist;
647 // printf("garbage collector: destroy_event(%x)\n", event);
648 while(pp)
650 if(pp==(mutex_list*)event)
652 if(pp->next)
653 pp->next->prev=pp->prev;
654 if(pp->prev)
655 pp->prev->next=pp->next;
656 if(mlist==(mutex_list*)event)
657 mlist=mlist->prev;
659 pp=mlist;
660 while(pp)
662 printf("%x => ", pp);
663 pp=pp->prev;
665 printf("0\n");
667 return;
669 pp=pp->prev;
673 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
674 char bInitialState, const char* name)
676 pthread_mutex_t *pm;
677 pthread_cond_t *pc;
679 mutex_list* pp;
680 pp=mlist;
681 while(pp)
683 printf("%x => ", pp);
684 pp=pp->prev;
686 printf("0\n");
688 if(mlist!=NULL)
690 mutex_list* pp=mlist;
691 if(name!=NULL)
694 if((strcmp(pp->name, name)==0) && (pp->type==0))
696 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
697 pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
698 return pp->pm;
700 }while((pp=pp->prev) != NULL);
702 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
703 pthread_mutex_init(pm, NULL);
704 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
705 pthread_cond_init(pc, NULL);
706 if(mlist==NULL)
708 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
709 mlist->next=mlist->prev=NULL;
711 else
713 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
714 mlist->next->prev=mlist;
715 mlist->next->next=NULL;
716 mlist=mlist->next;
718 mlist->type=0; /* Type Event */
719 mlist->pm=pm;
720 mlist->pc=pc;
721 mlist->state=bInitialState;
722 mlist->reset=bManualReset;
723 if(name)
724 strncpy(mlist->name, name, 127);
725 else
726 mlist->name[0]=0;
727 if(pm==NULL)
728 dbgprintf("ERROR::: CreateEventA failure\n");
730 if(bInitialState)
731 pthread_mutex_lock(pm);
733 if(name)
734 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
735 pSecAttr, bManualReset, bInitialState, name, name, mlist);
736 else
737 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
738 pSecAttr, bManualReset, bInitialState, mlist);
739 return mlist;
742 static void* WINAPI expSetEvent(void* event)
744 mutex_list *ml = (mutex_list *)event;
745 dbgprintf("SetEvent(%x) => 0x1\n", event);
746 pthread_mutex_lock(ml->pm);
747 if (ml->state == 0) {
748 ml->state = 1;
749 pthread_cond_signal(ml->pc);
751 pthread_mutex_unlock(ml->pm);
753 return (void *)1;
755 static void* WINAPI expResetEvent(void* event)
757 mutex_list *ml = (mutex_list *)event;
758 dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
759 pthread_mutex_lock(ml->pm);
760 ml->state = 0;
761 pthread_mutex_unlock(ml->pm);
763 return (void *)1;
766 static void* WINAPI expWaitForSingleObject(void* object, int duration)
768 mutex_list *ml = (mutex_list *)object;
769 // FIXME FIXME FIXME - this value is sometime unititialize !!!
770 int ret = WAIT_FAILED;
771 mutex_list* pp=mlist;
772 if(object == (void*)0xcfcf9898)
775 From GetCurrentThread() documentation:
776 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.
778 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.
780 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.
782 dbgprintf("WaitForSingleObject(thread_handle) called\n");
783 return (void*)WAIT_FAILED;
785 dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
787 // loop below was slightly fixed - its used just for checking if
788 // this object really exists in our list
789 if (!ml)
790 return (void*) ret;
791 while (pp && (pp->pm != ml->pm))
792 pp = pp->prev;
793 if (!pp) {
794 dbgprintf("WaitForSingleObject: NotFound\n");
795 return (void*)ret;
798 pthread_mutex_lock(ml->pm);
800 switch(ml->type) {
801 case 0: /* Event */
802 if (duration == 0) { /* Check Only */
803 if (ml->state == 1) ret = WAIT_FAILED;
804 else ret = WAIT_OBJECT_0;
806 if (duration == -1) { /* INFINITE */
807 if (ml->state == 0)
808 pthread_cond_wait(ml->pc,ml->pm);
809 if (ml->reset)
810 ml->state = 0;
811 ret = WAIT_OBJECT_0;
813 if (duration > 0) { /* Timed Wait */
814 struct timespec abstime;
815 struct timeval now;
816 gettimeofday(&now, 0);
817 abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
818 abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
819 if (ml->state == 0)
820 ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
821 if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
822 else ret = WAIT_OBJECT_0;
823 if (ml->reset)
824 ml->state = 0;
826 break;
827 case 1: /* Semaphore */
828 if (duration == 0) {
829 if(ml->semaphore==0) ret = WAIT_FAILED;
830 else {
831 ml->semaphore++;
832 ret = WAIT_OBJECT_0;
835 if (duration == -1) {
836 if (ml->semaphore==0)
837 pthread_cond_wait(ml->pc,ml->pm);
838 ml->semaphore--;
840 break;
842 pthread_mutex_unlock(ml->pm);
844 dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
845 return (void *)ret;
848 #ifdef QTX
849 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
850 int WaitAll, int duration)
852 int i;
853 void *object;
854 void *ret;
856 dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
857 count, objects, WaitAll, duration);
859 for (i = 0; i < count; i++)
861 object = (void *)objects[i];
862 ret = expWaitForSingleObject(object, duration);
863 if (WaitAll)
864 dbgprintf("WaitAll flag not yet supported...\n");
865 else
866 return ret;
868 return NULL;
871 static void WINAPI expExitThread(int retcode)
873 dbgprintf("ExitThread(%d)\n", retcode);
874 pthread_exit(&retcode);
877 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
878 char bInitialOwner, const char *name)
880 HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
882 if (name)
883 dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
884 pSecAttr, bInitialOwner, name, mlist);
885 else
886 dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
887 pSecAttr, bInitialOwner, mlist);
888 #ifndef QTX
889 /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
890 waits for ever, else it works ;) */
891 return mlist;
892 #endif
895 static int WINAPI expReleaseMutex(HANDLE hMutex)
897 dbgprintf("ReleaseMutex(%x) => 1\n", hMutex);
898 /* FIXME:XXX !! not yet implemented */
899 return 1;
901 #endif
903 static int pf_set = 0;
904 static BYTE PF[64] = {0,};
906 static void DumpSystemInfo(const SYSTEM_INFO* si)
908 dbgprintf(" Processor architecture %d\n", si->u.s.wProcessorArchitecture);
909 dbgprintf(" Page size: %d\n", si->dwPageSize);
910 dbgprintf(" Minimum app address: %d\n", si->lpMinimumApplicationAddress);
911 dbgprintf(" Maximum app address: %d\n", si->lpMaximumApplicationAddress);
912 dbgprintf(" Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
913 dbgprintf(" Number of processors: %d\n", si->dwNumberOfProcessors);
914 dbgprintf(" Processor type: 0x%x\n", si->dwProcessorType);
915 dbgprintf(" Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
916 dbgprintf(" Processor level: 0x%x\n", si->wProcessorLevel);
917 dbgprintf(" Processor revision: 0x%x\n", si->wProcessorRevision);
920 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
922 /* FIXME: better values for the two entries below... */
923 static int cache = 0;
924 static SYSTEM_INFO cachedsi;
925 dbgprintf("GetSystemInfo(%p) =>\n", si);
927 if (cache) {
928 goto exit;
930 memset(PF,0,sizeof(PF));
931 pf_set = 1;
933 cachedsi.u.s.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
934 cachedsi.dwPageSize = getpagesize();
936 /* FIXME: better values for the two entries below... */
937 cachedsi.lpMinimumApplicationAddress = (void *)0x00000000;
938 cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
939 cachedsi.dwActiveProcessorMask = 1;
940 cachedsi.dwNumberOfProcessors = 1;
941 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
942 cachedsi.dwAllocationGranularity = 0x10000;
943 cachedsi.wProcessorLevel = 5; /* pentium */
944 cachedsi.wProcessorRevision = 0x0101;
946 /* mplayer's way to detect PF's */
948 #include "cpudetect.h"
950 if (gCpuCaps.hasMMX)
951 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
952 if (gCpuCaps.hasSSE)
953 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
954 if (gCpuCaps.hasSSE2)
955 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
956 if (gCpuCaps.has3DNow)
957 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
959 if (gCpuCaps.cpuType == 4)
961 cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
962 cachedsi.wProcessorLevel = 4;
964 else if (gCpuCaps.cpuType >= 5)
966 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
967 cachedsi.wProcessorLevel = 5;
969 else
971 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
972 cachedsi.wProcessorLevel = 3;
974 cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
975 cachedsi.dwNumberOfProcessors = 1; /* hardcoded */
978 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
979 fdiv_bug and fpu emulation flags -- alex/MPlayer */
980 #ifdef __linux__
982 char buf[20];
983 char line[200];
984 FILE *f = fopen ("/proc/cpuinfo", "r");
986 if (!f)
988 mp_msg(MSGT_WIN32, MSGL_WARN, "expGetSystemInfo: "
989 "/proc/cpuinfo not readable! "
990 "Expect bad performance and/or weird behaviour\n");
991 goto exit;
993 while (fgets(line,200,f)!=NULL) {
994 char *s,*value;
996 /* NOTE: the ':' is the only character we can rely on */
997 if (!(value = strchr(line,':')))
998 continue;
999 /* terminate the valuename */
1000 *value++ = '\0';
1001 /* skip any leading spaces */
1002 while (*value==' ') value++;
1003 if ((s=strchr(value,'\n')))
1004 *s='\0';
1006 /* 2.1 method */
1007 if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
1008 if (isdigit (value[0])) {
1009 switch (value[0] - '0') {
1010 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1011 cachedsi.wProcessorLevel= 3;
1012 break;
1013 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1014 cachedsi.wProcessorLevel= 4;
1015 break;
1016 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1017 cachedsi.wProcessorLevel= 5;
1018 break;
1019 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1020 cachedsi.wProcessorLevel= 5;
1021 break;
1022 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1023 cachedsi.wProcessorLevel= 5;
1024 break;
1027 /* set the CPU type of the current processor */
1028 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1029 continue;
1031 /* old 2.0 method */
1032 if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
1033 if ( isdigit (value[0]) && value[1] == '8' &&
1034 value[2] == '6' && value[3] == 0
1036 switch (value[0] - '0') {
1037 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1038 cachedsi.wProcessorLevel= 3;
1039 break;
1040 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1041 cachedsi.wProcessorLevel= 4;
1042 break;
1043 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1044 cachedsi.wProcessorLevel= 5;
1045 break;
1046 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1047 cachedsi.wProcessorLevel= 5;
1048 break;
1049 default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1050 cachedsi.wProcessorLevel= 5;
1051 break;
1054 /* set the CPU type of the current processor */
1055 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1056 continue;
1058 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
1059 if (!lstrncmpiA(value,"yes",3))
1060 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
1062 continue;
1064 if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
1065 if (!lstrncmpiA(value,"no",2))
1066 PF[PF_FLOATING_POINT_EMULATED] = TRUE;
1068 continue;
1070 if (!lstrncmpiA(line,"processor",strlen("processor"))) {
1071 /* processor number counts up...*/
1072 unsigned int x;
1074 if (sscanf(value,"%d",&x))
1075 if (x+1>cachedsi.dwNumberOfProcessors)
1076 cachedsi.dwNumberOfProcessors=x+1;
1078 /* Create a new processor subkey on a multiprocessor
1079 * system
1081 sprintf(buf,"%d",x);
1083 if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
1084 int x;
1086 if (sscanf(value,"%d",&x))
1087 cachedsi.wProcessorRevision = x;
1090 ( (!lstrncmpiA(line,"flags",strlen("flags")))
1091 || (!lstrncmpiA(line,"features",strlen("features"))) )
1093 if (strstr(value,"cx8"))
1094 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1095 if (strstr(value,"mmx"))
1096 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1097 if (strstr(value,"tsc"))
1098 PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
1099 if (strstr(value,"xmm") || strstr(value,"sse"))
1100 PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1101 if (strstr(value,"sse2"))
1102 PF[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
1103 if (strstr(value,"3dnow"))
1104 PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1107 fclose (f);
1109 * ad hoc fix for smp machines.
1110 * some problems on WaitForSingleObject,CreateEvent,SetEvent
1111 * CreateThread ...etc..
1114 cachedsi.dwNumberOfProcessors=1;
1116 #endif /* __linux__ */
1117 cache = 1;
1118 exit:
1119 memcpy(si,&cachedsi,sizeof(*si));
1120 DumpSystemInfo(si);
1123 // avoid undefined expGetSystemInfo
1124 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
1126 WIN_BOOL result = 0;
1127 if (!pf_set)
1129 SYSTEM_INFO si;
1130 expGetSystemInfo(&si);
1132 if(v<64) result=PF[v];
1133 dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
1134 return result;
1138 static long WINAPI expGetVersion()
1140 dbgprintf("GetVersion() => 0xC0000004\n");
1141 return 0xC0000004;//Windows 95
1144 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
1146 // printf("HeapCreate:");
1147 HANDLE result;
1148 if(init_size==0)
1149 result=(HANDLE)my_mreq(0x110000, 0);
1150 else
1151 result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
1152 dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
1153 return result;
1156 // this is another dirty hack
1157 // VP31 is releasing one allocated Heap chunk twice
1158 // we will silently ignore this second call...
1159 static void* heapfreehack = 0;
1160 static int heapfreehackshown = 0;
1161 //void trapbug(void);
1162 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
1164 void* z;
1166 Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
1167 HeapAlloc returns area larger than size argument :-/
1169 actually according to M$ Doc HeapCreate size should be rounded
1170 to page boundaries thus we should simulate this
1172 //if (size == 22276) trapbug();
1173 z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
1174 if(z==0)
1175 printf("HeapAlloc failure\n");
1176 dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
1177 heapfreehack = 0; // reset
1178 return z;
1180 static long WINAPI expHeapDestroy(void* heap)
1182 dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
1183 my_release(heap);
1184 return 1;
1187 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
1189 dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
1190 if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
1191 && lpMem != (void*)0xbdbdbdbd)
1192 // 0xbdbdbdbd is for i263_drv.drv && libefence
1193 // it seems to be reading from relased memory
1194 // EF_PROTECT_FREE doens't show any probleme
1195 my_release(lpMem);
1196 else
1198 if (!heapfreehackshown++)
1199 printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
1201 heapfreehack = lpMem;
1202 return 1;
1204 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
1206 long result=my_size(pointer);
1207 dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
1208 return result;
1210 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
1212 long orgsize = my_size(lpMem);
1213 dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
1214 return my_realloc(lpMem, size);
1216 static long WINAPI expGetProcessHeap(void)
1218 dbgprintf("GetProcessHeap() => 1\n");
1219 return 1;
1221 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
1223 void* z = VirtualAlloc(v1, v2, v3, v4);
1224 if(z==0)
1225 printf("VirtualAlloc failure\n");
1226 dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
1227 return z;
1229 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
1231 int result = VirtualFree(v1,v2,v3);
1232 dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
1233 return result;
1236 /* we're building a table of critical sections. cs_win pointer uses the DLL
1237 cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
1238 struct critsecs_list_t
1240 CRITICAL_SECTION *cs_win;
1241 struct CRITSECT *cs_unix;
1244 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
1245 #undef CRITSECS_NEWTYPE
1246 //#define CRITSECS_NEWTYPE 1
1248 #ifdef CRITSECS_NEWTYPE
1249 /* increased due to ucod needs more than 32 entries */
1250 /* and 64 should be enough for everything */
1251 #define CRITSECS_LIST_MAX 64
1252 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
1254 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
1256 int i;
1258 for (i=0; i < CRITSECS_LIST_MAX; i++)
1259 if (critsecs_list[i].cs_win == cs_win)
1260 return i;
1261 return -1;
1264 static int critsecs_get_unused(void)
1266 int i;
1268 for (i=0; i < CRITSECS_LIST_MAX; i++)
1269 if (critsecs_list[i].cs_win == NULL)
1270 return i;
1271 return -1;
1274 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
1276 int i;
1278 for (i=0; i < CRITSECS_LIST_MAX; i++)
1279 if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
1280 return critsecs_list[i].cs_unix;
1281 return NULL;
1283 #endif
1285 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
1287 dbgprintf("InitializeCriticalSection(0x%x)\n", c);
1288 /* if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
1290 printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
1291 sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
1292 return;
1294 /* pthread_mutex_init((pthread_mutex_t*)c, NULL); */
1295 #ifdef CRITSECS_NEWTYPE
1297 struct CRITSECT *cs;
1298 int i = critsecs_get_unused();
1300 if (i < 0)
1302 printf("InitializeCriticalSection(%p) - no more space in list\n", c);
1303 return;
1305 dbgprintf("got unused space at %d\n", i);
1306 cs = malloc(sizeof(struct CRITSECT));
1307 if (!cs)
1309 printf("InitializeCriticalSection(%p) - out of memory\n", c);
1310 return;
1312 pthread_mutex_init(&cs->mutex, NULL);
1313 cs->locked = 0;
1314 critsecs_list[i].cs_win = c;
1315 critsecs_list[i].cs_unix = cs;
1316 dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
1317 i, c, cs);
1319 #else
1321 struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
1322 0, AREATYPE_CRITSECT);
1323 pthread_mutex_init(&cs->mutex, NULL);
1324 cs->locked=0;
1325 cs->deadbeef = 0xdeadbeef;
1326 *(void**)c = cs;
1328 #endif
1329 return;
1332 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
1334 #ifdef CRITSECS_NEWTYPE
1335 struct CRITSECT* cs = critsecs_get_unix(c);
1336 #else
1337 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1338 #endif
1339 dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
1340 if (!cs)
1342 dbgprintf("entered uninitialized critisec!\n");
1343 expInitializeCriticalSection(c);
1344 #ifdef CRITSECS_NEWTYPE
1345 cs=critsecs_get_unix(c);
1346 #else
1347 cs = (*(struct CRITSECT**)c);
1348 #endif
1349 dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
1351 if(cs->locked)
1352 if(cs->id==pthread_self())
1353 return;
1354 pthread_mutex_lock(&(cs->mutex));
1355 cs->locked=1;
1356 cs->id=pthread_self();
1357 return;
1359 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
1361 #ifdef CRITSECS_NEWTYPE
1362 struct CRITSECT* cs = critsecs_get_unix(c);
1363 #else
1364 struct CRITSECT* cs = (*(struct CRITSECT**)c);
1365 #endif
1366 // struct CRITSECT* cs=(struct CRITSECT*)c;
1367 dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
1368 if (!cs)
1370 dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
1371 return;
1373 if (cs->locked)
1375 cs->locked=0;
1376 pthread_mutex_unlock(&(cs->mutex));
1378 else
1379 dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
1380 return;
1383 static void expfree(void* mem); /* forward declaration */
1385 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
1387 #ifdef CRITSECS_NEWTYPE
1388 struct CRITSECT* cs = critsecs_get_unix(c);
1389 #else
1390 struct CRITSECT* cs= (*(struct CRITSECT**)c);
1391 #endif
1392 // struct CRITSECT* cs=(struct CRITSECT*)c;
1393 dbgprintf("DeleteCriticalSection(0x%x)\n",c);
1395 if (!cs)
1397 dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
1398 return;
1401 if (cs->locked)
1403 dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
1404 pthread_mutex_unlock(&(cs->mutex));
1407 #ifndef GARBAGE
1408 pthread_mutex_destroy(&(cs->mutex));
1409 // released by GarbageCollector in my_relase otherwise
1410 #endif
1411 my_release(cs);
1412 #ifdef CRITSECS_NEWTYPE
1414 int i = critsecs_get_pos(c);
1416 if (i < 0)
1418 printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
1419 return;
1422 critsecs_list[i].cs_win = NULL;
1423 expfree(critsecs_list[i].cs_unix);
1424 critsecs_list[i].cs_unix = NULL;
1425 dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
1427 #endif
1428 return;
1430 static int WINAPI expGetCurrentThreadId()
1432 dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
1433 return pthread_self();
1435 static int WINAPI expGetCurrentProcess()
1437 dbgprintf("GetCurrentProcess() => %d\n", getpid());
1438 return getpid();
1441 #ifdef QTX
1442 // this version is required for Quicktime codecs (.qtx/.qts) to work.
1443 // (they assume some pointers at FS: segment)
1445 extern void* fs_seg;
1447 //static int tls_count;
1448 static int tls_use_map[64];
1449 static int WINAPI expTlsAlloc()
1451 int i;
1452 for(i=0; i<64; i++)
1453 if(tls_use_map[i]==0)
1455 tls_use_map[i]=1;
1456 dbgprintf("TlsAlloc() => %d\n",i);
1457 return i;
1459 dbgprintf("TlsAlloc() => -1 (ERROR)\n");
1460 return -1;
1463 //static int WINAPI expTlsSetValue(DWORD index, void* value)
1464 static int WINAPI expTlsSetValue(int index, void* value)
1466 dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
1467 // if((index<0) || (index>64))
1468 if((index>=64))
1469 return 0;
1470 *(void**)((char*)fs_seg+0x88+4*index) = value;
1471 return 1;
1474 static void* WINAPI expTlsGetValue(DWORD index)
1476 dbgprintf("TlsGetValue(%d)\n",index);
1477 // if((index<0) || (index>64))
1478 if((index>=64)) return NULL;
1479 return *(void**)((char*)fs_seg+0x88+4*index);
1482 static int WINAPI expTlsFree(int idx)
1484 int index = (int) idx;
1485 dbgprintf("TlsFree(%d)\n",index);
1486 if((index<0) || (index>64))
1487 return 0;
1488 tls_use_map[index]=0;
1489 return 1;
1492 #else
1493 struct tls_s {
1494 void* value;
1495 int used;
1496 struct tls_s* prev;
1497 struct tls_s* next;
1500 static void* WINAPI expTlsAlloc()
1502 if (g_tls == NULL)
1504 g_tls=my_mreq(sizeof(tls_t), 0);
1505 g_tls->next=g_tls->prev=NULL;
1507 else
1509 g_tls->next=my_mreq(sizeof(tls_t), 0);
1510 g_tls->next->prev=g_tls;
1511 g_tls->next->next=NULL;
1512 g_tls=g_tls->next;
1514 dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
1515 if (g_tls)
1516 g_tls->value=0; /* XXX For Divx.dll */
1517 return g_tls;
1520 static int WINAPI expTlsSetValue(void* idx, void* value)
1522 tls_t* index = (tls_t*) idx;
1523 int result;
1524 if(index==0)
1525 result=0;
1526 else
1528 index->value=value;
1529 result=1;
1531 dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
1532 return result;
1534 static void* WINAPI expTlsGetValue(void* idx)
1536 tls_t* index = (tls_t*) idx;
1537 void* result;
1538 if(index==0)
1539 result=0;
1540 else
1541 result=index->value;
1542 dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
1543 return result;
1545 static int WINAPI expTlsFree(void* idx)
1547 tls_t* index = (tls_t*) idx;
1548 int result;
1549 if(index==0)
1550 result=0;
1551 else
1553 if(index->next)
1554 index->next->prev=index->prev;
1555 if(index->prev)
1556 index->prev->next=index->next;
1557 if (g_tls == index)
1558 g_tls = index->prev;
1559 my_release((void*)index);
1560 result=1;
1562 dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
1563 return result;
1565 #endif
1567 static void* WINAPI expLocalAlloc(int flags, int size)
1569 void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
1570 if (z == 0)
1571 printf("LocalAlloc() failed\n");
1572 dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1573 return z;
1576 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
1578 void *newpointer;
1579 int oldsize;
1581 newpointer=NULL;
1582 if (flags & LMEM_MODIFY) {
1583 dbgprintf("LocalReAlloc MODIFY\n");
1584 return (void *)handle;
1586 oldsize = my_size((void *)handle);
1587 newpointer = my_realloc((void *)handle,size);
1588 dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
1590 return newpointer;
1593 static void* WINAPI expLocalLock(void* z)
1595 dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
1596 return z;
1599 static void* WINAPI expGlobalAlloc(int flags, int size)
1601 void* z;
1602 dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
1604 z=my_mreq(size, (flags & GMEM_ZEROINIT));
1605 //z=calloc(size, 1);
1606 //z=malloc(size);
1607 if(z==0)
1608 printf("GlobalAlloc() failed\n");
1609 dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1610 return z;
1612 static void* WINAPI expGlobalLock(void* z)
1614 dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
1615 return z;
1617 // pvmjpg20 - but doesn't work anyway
1618 static int WINAPI expGlobalSize(void* amem)
1620 int size = 100000;
1621 #ifdef GARBAGE
1622 alloc_header* header = last_alloc;
1623 alloc_header* mem = (alloc_header*) amem - 1;
1624 if (amem == 0)
1625 return 0;
1626 pthread_mutex_lock(&memmut);
1627 while (header)
1629 if (header->deadbeef != 0xdeadbeef)
1631 dbgprintf("FATAL found corrupted memory! %p 0x%lx (%d)\n", header, header->deadbeef, alccnt);
1632 break;
1635 if (header == mem)
1637 size = header->size;
1638 break;
1641 header = header->prev;
1643 pthread_mutex_unlock(&memmut);
1644 #endif
1646 dbgprintf("GlobalSize(0x%x)\n", amem);
1647 return size;
1650 static int WINAPI expLoadIconA( long hinstance, char *name )
1652 dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
1653 return 1;
1656 static int WINAPI expLoadStringA(long instance, long id, void* buf, long size)
1658 int result=LoadStringA(instance, id, buf, size);
1659 // if(buf)
1660 dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
1661 instance, id, buf, size, result, buf);
1662 // else
1663 // dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
1664 // instance, id, buf, size, result);
1665 return result;
1668 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
1670 #warning FIXME
1671 int i;
1672 int result;
1673 if(s2==0)
1674 result=1;
1675 else
1677 if(siz1>siz2/2)siz1=siz2/2;
1678 for(i=1; i<=siz1; i++)
1680 *s2=*s1;
1681 if(!*s1)break;
1682 s2++;
1683 s1++;
1685 result=i;
1687 if(s1)
1688 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
1689 "size %d, dest buffer 0x%x, dest size %d) => %d\n",
1690 v1, v2, s1, s1, siz1, s2, siz2, result);
1691 else
1692 dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
1693 "size %d, dest buffer 0x%x, dest size %d) =>\n",
1694 v1, v2, siz1, s2, siz2, result);
1695 return result;
1697 static void wch_print(const short* str)
1699 dbgprintf(" src: ");
1700 while(*str)dbgprintf("%c", *str++);
1701 dbgprintf("\n");
1703 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
1704 char* s2, int siz2, char* c3, int* siz3)
1706 int result;
1707 dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
1708 "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
1709 result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
1710 dbgprintf("=> %d\n", result);
1711 //if(s1)wch_print(s1);
1712 if(s2)dbgprintf(" dest: %s\n", s2);
1713 return result;
1715 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
1717 dbgprintf("GetVersionExA(0x%x) => 1\n");
1718 c->dwOSVersionInfoSize=sizeof(*c);
1719 c->dwMajorVersion=4;
1720 c->dwMinorVersion=0;
1721 c->dwBuildNumber=0x4000457;
1722 #if 1
1723 // leave it here for testing win9x-only codecs
1724 c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
1725 strcpy(c->szCSDVersion, " B");
1726 #else
1727 c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
1728 strcpy(c->szCSDVersion, "Service Pack 3");
1729 #endif
1730 dbgprintf(" Major version: 4\n Minor version: 0\n Build number: 0x4000457\n"
1731 " Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 3'\n");
1732 return 1;
1734 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
1735 long max_count, char* name)
1737 pthread_mutex_t *pm;
1738 pthread_cond_t *pc;
1740 mutex_list* pp;
1741 printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
1742 pp=mlist;
1743 while(pp)
1745 printf("%p => ", pp);
1746 pp=pp->prev;
1748 printf("0\n");
1750 if(mlist!=NULL)
1752 mutex_list* pp=mlist;
1753 if(name!=NULL)
1756 if((strcmp(pp->name, name)==0) && (pp->type==1))
1758 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1759 v1, init_count, max_count, name, name, mlist);
1760 return (HANDLE)mlist;
1762 }while((pp=pp->prev) != NULL);
1764 pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1765 pthread_mutex_init(pm, NULL);
1766 pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1767 pthread_cond_init(pc, NULL);
1768 if(mlist==NULL)
1770 mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1771 mlist->next=mlist->prev=NULL;
1773 else
1775 mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1776 mlist->next->prev=mlist;
1777 mlist->next->next=NULL;
1778 mlist=mlist->next;
1779 // printf("new semaphore %p\n", mlist);
1781 mlist->type=1; /* Type Semaphore */
1782 mlist->pm=pm;
1783 mlist->pc=pc;
1784 mlist->state=0;
1785 mlist->reset=0;
1786 mlist->semaphore=init_count;
1787 if(name!=NULL)
1788 strncpy(mlist->name, name, 64);
1789 else
1790 mlist->name[0]=0;
1791 if(pm==NULL)
1792 dbgprintf("ERROR::: CreateSemaphoreA failure\n");
1793 if(name)
1794 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1795 v1, init_count, max_count, name, name, mlist);
1796 else
1797 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
1798 v1, init_count, max_count, mlist);
1799 return (HANDLE)mlist;
1802 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
1804 // The state of a semaphore object is signaled when its count
1805 // is greater than zero and nonsignaled when its count is equal to zero
1806 // Each time a waiting thread is released because of the semaphore's signaled
1807 // state, the count of the semaphore is decreased by one.
1808 mutex_list *ml = (mutex_list *)hsem;
1810 pthread_mutex_lock(ml->pm);
1811 if (prev_count != 0) *prev_count = ml->semaphore;
1812 if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
1813 ml->semaphore += increment;
1814 pthread_mutex_unlock(ml->pm);
1815 dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
1816 hsem, increment, prev_count);
1817 return 1;
1821 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
1823 long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
1824 dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
1825 key, subkey, reserved, access, newkey, result);
1826 if(newkey)dbgprintf(" New key: 0x%x\n", *newkey);
1827 return result;
1829 static long WINAPI expRegCloseKey(long key)
1831 long result=RegCloseKey(key);
1832 dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
1833 return result;
1835 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
1837 long result=RegQueryValueExA(key, value, reserved, type, data, count);
1838 dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
1839 " => 0x%x\n", key, value, reserved, data, count, result);
1840 if(data && count)dbgprintf(" read %d bytes: '%s'\n", *count, data);
1841 return result;
1844 //from wine source dlls/advapi32/registry.c
1845 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
1847 dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
1848 return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
1849 KEY_ALL_ACCESS , NULL, retkey, NULL );
1852 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
1853 void* classs, long options, long security,
1854 void* sec_attr, int* newkey, int* status)
1856 long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
1857 dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
1858 " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
1859 key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
1860 if(!result && newkey) dbgprintf(" New key: 0x%x\n", *newkey);
1861 if(!result && status) dbgprintf(" New key status: 0x%x\n", *status);
1862 return result;
1864 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
1866 long result=RegSetValueExA(key, name, v1, v2, data, size);
1867 dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
1868 key, name, v1, v2, data, *(int*)data, data, size, result);
1869 return result;
1872 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
1874 long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
1875 dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
1876 hKey, lpSubKey, phkResult, result);
1877 if(!result && phkResult) dbgprintf(" New key: 0x%x\n", *phkResult);
1878 return result;
1881 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1882 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
1884 return RegEnumValueA(hkey, index, value, val_count,
1885 reserved, type, data, count);
1888 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
1889 LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
1890 LPFILETIME lpftLastWriteTime)
1892 return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
1893 lpcbClass, lpftLastWriteTime);
1896 static long WINAPI expQueryPerformanceCounter(long long* z)
1898 longcount(z);
1899 dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
1900 return 1;
1904 * dummy function RegQueryInfoKeyA(), required by vss codecs
1906 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
1907 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
1908 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
1909 LPDWORD security, FILETIME *modif )
1911 return ERROR_SUCCESS;
1915 * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
1917 static double linux_cpuinfo_freq()
1919 double freq=-1;
1920 FILE *f;
1921 char line[200];
1922 char *s,*value;
1924 f = fopen ("/proc/cpuinfo", "r");
1925 if (f != NULL) {
1926 while (fgets(line,sizeof(line),f)!=NULL) {
1927 /* NOTE: the ':' is the only character we can rely on */
1928 if (!(value = strchr(line,':')))
1929 continue;
1930 /* terminate the valuename */
1931 *value++ = '\0';
1932 /* skip any leading spaces */
1933 while (*value==' ') value++;
1934 if ((s=strchr(value,'\n')))
1935 *s='\0';
1937 if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
1938 && sscanf(value, "%lf", &freq) == 1) {
1939 freq*=1000;
1940 break;
1943 fclose(f);
1945 return freq;
1949 static double solaris_kstat_freq()
1951 #if defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
1953 * try to extract the CPU speed from the solaris kernel's kstat data
1955 kstat_ctl_t *kc;
1956 kstat_t *ksp;
1957 kstat_named_t *kdata;
1958 int mhz = 0;
1960 kc = kstat_open();
1961 if (kc != NULL)
1963 ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
1965 /* kstat found and name/value pairs? */
1966 if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
1968 /* read the kstat data from the kernel */
1969 if (kstat_read(kc, ksp, NULL) != -1)
1972 * lookup desired "clock_MHz" entry, check the expected
1973 * data type
1975 kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
1976 if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
1977 mhz = kdata->value.i32;
1980 kstat_close(kc);
1983 if (mhz > 0)
1984 return mhz * 1000.;
1985 #endif /* HAVE_LIBKSTAT */
1986 return -1; // kstat stuff is not available, CPU freq is unknown
1990 * Measure CPU freq using the pentium's time stamp counter register (TSC)
1992 static double tsc_freq()
1994 static double ofreq=0.0;
1995 int i;
1996 int x,y;
1997 i=time(NULL);
1998 if (ofreq != 0.0) return ofreq;
1999 while(i==time(NULL));
2000 x=localcount();
2001 i++;
2002 while(i==time(NULL));
2003 y=localcount();
2004 ofreq = (double)(y-x)/1000.;
2005 return ofreq;
2008 static double CPU_Freq()
2010 double freq;
2012 if ((freq = linux_cpuinfo_freq()) > 0)
2013 return freq;
2015 if ((freq = solaris_kstat_freq()) > 0)
2016 return freq;
2018 return tsc_freq();
2021 static long WINAPI expQueryPerformanceFrequency(long long* z)
2023 *z=(long long)CPU_Freq();
2024 dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
2025 return 1;
2027 static long WINAPI exptimeGetTime()
2029 struct timeval t;
2030 long result;
2031 gettimeofday(&t, 0);
2032 result=1000*t.tv_sec+t.tv_usec/1000;
2033 dbgprintf("timeGetTime() => %d\n", result);
2034 return result;
2036 static void* WINAPI expLocalHandle(void* v)
2038 dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
2039 return v;
2042 static void* WINAPI expGlobalHandle(void* v)
2044 dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
2045 return v;
2047 static int WINAPI expGlobalUnlock(void* v)
2049 dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
2050 return 1;
2052 static void* WINAPI expGlobalFree(void* v)
2054 dbgprintf("GlobalFree(0x%x) => 0\n", v);
2055 my_release(v);
2056 //free(v);
2057 return 0;
2060 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
2062 void* result=my_realloc(v, size);
2063 //void* result=realloc(v, size);
2064 dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
2065 return result;
2068 static int WINAPI expLocalUnlock(void* v)
2070 dbgprintf("LocalUnlock(0x%x) => 1\n", v);
2071 return 1;
2074 static void* WINAPI expLocalFree(void* v)
2076 dbgprintf("LocalFree(0x%x) => 0\n", v);
2077 my_release(v);
2078 return 0;
2080 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
2082 HRSRC result;
2084 result=FindResourceA(module, name, type);
2085 dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
2086 module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
2087 return result;
2090 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
2092 HGLOBAL result=LoadResource(module, res);
2093 dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
2094 return result;
2096 static void* WINAPI expLockResource(long res)
2098 void* result=LockResource(res);
2099 dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
2100 return result;
2102 static int WINAPI expFreeResource(long res)
2104 int result=FreeResource(res);
2105 dbgprintf("FreeResource(0x%x) => %d\n", res, result);
2106 return result;
2108 //bool fun(HANDLE)
2109 //!0 on success
2110 static int WINAPI expCloseHandle(long v1)
2112 dbgprintf("CloseHandle(0x%x) => 1\n", v1);
2113 /* do not close stdin,stdout and stderr */
2114 if (v1 > 2)
2115 if (!close(v1))
2116 return 0;
2117 return 1;
2120 static const char* WINAPI expGetCommandLineA()
2122 dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
2123 return "c:\\aviplay.exe";
2125 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
2126 static LPWSTR WINAPI expGetEnvironmentStringsW()
2128 dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
2129 return 0;
2131 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
2133 void* result=memset(p,0,len);
2134 dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
2135 return result;
2137 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
2139 void* result=memmove(dst,src,len);
2140 dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
2141 return result;
2144 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
2146 void* result=memset(p,ch,len);
2147 dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
2148 return result;
2150 static int WINAPI expFreeEnvironmentStringsW(short* strings)
2152 dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
2153 return 1;
2155 static int WINAPI expFreeEnvironmentStringsA(char* strings)
2157 dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
2158 return 1;
2161 static const char ch_envs[]=
2162 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
2163 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
2164 static LPCSTR WINAPI expGetEnvironmentStrings()
2166 dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
2167 return (LPCSTR)ch_envs;
2168 // dbgprintf("GetEnvironmentStrings() => 0\n");
2169 // return 0;
2172 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
2174 dbgprintf("GetStartupInfoA(0x%x) => 1\n");
2175 memset(s, 0, sizeof(*s));
2176 s->cb=sizeof(*s);
2177 // s->lpReserved="Reserved";
2178 // s->lpDesktop="Desktop";
2179 // s->lpTitle="Title";
2180 // s->dwX=s->dwY=0;
2181 // s->dwXSize=s->dwYSize=200;
2182 s->dwFlags=s->wShowWindow=1;
2183 // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
2184 dbgprintf(" cb=%d\n", s->cb);
2185 dbgprintf(" lpReserved='%s'\n", s->lpReserved);
2186 dbgprintf(" lpDesktop='%s'\n", s->lpDesktop);
2187 dbgprintf(" lpTitle='%s'\n", s->lpTitle);
2188 dbgprintf(" dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
2189 s->dwX, s->dwY, s->dwXSize, s->dwYSize);
2190 dbgprintf(" dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
2191 s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
2192 dbgprintf(" dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
2193 s->dwFlags, s->wShowWindow, s->cbReserved2);
2194 dbgprintf(" lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
2195 s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
2196 return 1;
2199 static int WINAPI expGetStdHandle(int z)
2201 dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
2202 return z+0x1234;
2205 #ifdef QTX
2206 #define FILE_HANDLE_quicktimeqts ((HANDLE)0x444)
2207 #define FILE_HANDLE_quicktimeqtx ((HANDLE)0x445)
2208 #endif
2210 static int WINAPI expGetFileType(int handle)
2212 dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
2213 return 0x3;
2215 #ifdef QTX
2216 static int WINAPI expGetFileAttributesA(char *filename)
2218 dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
2219 if (strstr(filename, "QuickTime.qts"))
2220 return FILE_ATTRIBUTE_SYSTEM;
2221 return FILE_ATTRIBUTE_NORMAL;
2223 #endif
2224 static int WINAPI expSetHandleCount(int count)
2226 dbgprintf("SetHandleCount(0x%x) => 1\n", count);
2227 return 1;
2229 static int WINAPI expGetACP(void)
2231 dbgprintf("GetACP() => 0\n");
2232 return 0;
2234 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
2236 WINE_MODREF *mr;
2237 int result;
2238 //printf("File name of module %X (%s) requested\n", module, s);
2240 if (module == 0 && len >= 12)
2242 /* return caller program name */
2243 strcpy(s, "aviplay.dll");
2244 result=1;
2246 else if(s==0)
2247 result=0;
2248 else
2249 if(len<35)
2250 result=0;
2251 else
2253 result=1;
2254 strcpy(s, "c:\\windows\\system\\");
2255 mr=MODULE32_LookupHMODULE(module);
2256 if(mr==0)//oops
2257 strcat(s, "aviplay.dll");
2258 else
2259 if(strrchr(mr->filename, '/')==NULL)
2260 strcat(s, mr->filename);
2261 else
2262 strcat(s, strrchr(mr->filename, '/')+1);
2264 if(!s)
2265 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
2266 module, s, len, result);
2267 else
2268 dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
2269 module, s, len, result, s);
2270 return result;
2273 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
2275 dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
2276 return 1;//unsupported and probably won't ever be supported
2279 static int WINAPI expLoadLibraryA(char* name)
2281 int result = 0;
2282 char* lastbc;
2283 if (!name)
2284 return -1;
2285 // we skip to the last backslash
2286 // this is effectively eliminating weird characters in
2287 // the text output windows
2289 lastbc = strrchr(name, '\\');
2290 if (lastbc)
2292 int i;
2293 lastbc++;
2294 for (i = 0; 1 ;i++)
2296 name[i] = *lastbc++;
2297 if (!name[i])
2298 break;
2301 if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
2302 if(strncmp(name, ".\\", 2)==0) name += 2;
2304 dbgprintf("Entering LoadLibraryA(%s)\n", name);
2306 // PIMJ and VIVO audio are loading kernel32.dll
2307 if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
2308 return MODULE_HANDLE_kernel32;
2309 // return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
2310 /* exported -> do not return failed! */
2312 if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
2313 // return MODULE_HANDLE_kernel32;
2314 return MODULE_HANDLE_user32;
2316 #ifdef QTX
2317 if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
2318 return MODULE_HANDLE_wininet;
2319 if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
2320 return MODULE_HANDLE_ddraw;
2321 if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
2322 return MODULE_HANDLE_advapi32;
2323 #endif
2325 if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
2326 return MODULE_HANDLE_comdlg32;
2327 if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
2328 return MODULE_HANDLE_msvcrt;
2329 if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
2330 return MODULE_HANDLE_ole32;
2331 if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
2332 return MODULE_HANDLE_winmm;
2334 result=LoadLibraryA(name);
2335 dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
2337 return result;
2340 static int WINAPI expFreeLibrary(int module)
2342 #ifdef QTX
2343 int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
2344 #else
2345 int result=FreeLibrary(module);
2346 #endif
2347 dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
2348 return result;
2351 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
2353 void* result;
2354 switch(mod){
2355 case MODULE_HANDLE_kernel32:
2356 result=LookupExternalByName("kernel32.dll", name); break;
2357 case MODULE_HANDLE_user32:
2358 result=LookupExternalByName("user32.dll", name); break;
2359 #ifdef QTX
2360 case MODULE_HANDLE_wininet:
2361 result=LookupExternalByName("wininet.dll", name); break;
2362 case MODULE_HANDLE_ddraw:
2363 result=LookupExternalByName("ddraw.dll", name); break;
2364 case MODULE_HANDLE_advapi32:
2365 result=LookupExternalByName("advapi32.dll", name); break;
2366 #endif
2367 case MODULE_HANDLE_comdlg32:
2368 result=LookupExternalByName("comdlg32.dll", name); break;
2369 case MODULE_HANDLE_msvcrt:
2370 result=LookupExternalByName("msvcrt.dll", name); break;
2371 case MODULE_HANDLE_ole32:
2372 result=LookupExternalByName("ole32.dll", name); break;
2373 case MODULE_HANDLE_winmm:
2374 result=LookupExternalByName("winmm.dll", name); break;
2375 default:
2376 result=GetProcAddress(mod, name);
2378 if((unsigned int)name > 0xffff)
2379 dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
2380 else
2381 dbgprintf("GetProcAddress(0x%x, '%d') => 0x%x\n", mod, (int)name, result);
2382 return result;
2385 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
2386 long flProtect, long dwMaxHigh,
2387 long dwMaxLow, const char* name)
2389 long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
2390 if(!name)
2391 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2392 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
2393 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
2394 else
2395 dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2396 "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
2397 hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
2398 return result;
2401 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
2403 long result=OpenFileMappingA(hFile, hz, name);
2404 if(!name)
2405 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
2406 hFile, hz, result);
2407 else
2408 dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
2409 hFile, hz, name, name, result);
2410 return result;
2413 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
2414 DWORD offLow, DWORD size)
2416 dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
2417 file,mode,offHigh,offLow,size,(char*)file+offLow);
2418 return (char*)file+offLow;
2421 static void* WINAPI expUnmapViewOfFile(void* view)
2423 dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
2424 return 0;
2427 static void* WINAPI expSleep(int time)
2429 #if HAVE_NANOSLEEP
2430 /* solaris doesn't have thread safe usleep */
2431 struct timespec tsp;
2432 tsp.tv_sec = time / 1000000;
2433 tsp.tv_nsec = (time % 1000000) * 1000;
2434 nanosleep(&tsp, NULL);
2435 #else
2436 usleep(time);
2437 #endif
2438 dbgprintf("Sleep(%d) => 0\n", time);
2439 return 0;
2442 // why does IV32 codec want to call this? I don't know ...
2443 static int WINAPI expCreateCompatibleDC(int hdc)
2445 int dc = 0;//0x81;
2446 //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
2447 dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
2448 return dc;
2451 static int WINAPI expGetDeviceCaps(int hdc, int unk)
2453 dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
2454 #ifdef QTX
2455 #define BITSPIXEL 12
2456 #define PLANES 14
2457 if (unk == BITSPIXEL)
2458 return 24;
2459 if (unk == PLANES)
2460 return 1;
2461 #endif
2462 return 1;
2465 static WIN_BOOL WINAPI expDeleteDC(int hdc)
2467 dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
2468 if (hdc == 0x81)
2469 return 1;
2470 return 0;
2473 static WIN_BOOL WINAPI expDeleteObject(int hdc)
2475 dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
2476 /* FIXME - implement code here */
2477 return 1;
2480 /* btvvc32.drv wants this one */
2481 static void* WINAPI expGetWindowDC(int hdc)
2483 dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
2484 return 0;
2487 #ifdef QTX
2488 static int WINAPI expGetWindowRect(HWND win, RECT *r)
2490 dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
2491 /* (win == 0) => desktop */
2492 r->right = PSEUDO_SCREEN_WIDTH;
2493 r->left = 0;
2494 r->bottom = PSEUDO_SCREEN_HEIGHT;
2495 r->top = 0;
2496 return 1;
2499 static int WINAPI expMonitorFromWindow(HWND win, int flags)
2501 dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
2502 return 0;
2505 static int WINAPI expMonitorFromRect(RECT *r, int flags)
2507 dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
2508 return 0;
2511 static int WINAPI expMonitorFromPoint(void *p, int flags)
2513 dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
2514 return 0;
2517 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r,
2518 int WINAPI (*callback_proc)(), void *callback_param)
2520 dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
2521 dc, r, callback_proc, callback_param);
2522 return callback_proc(0, dc, r, callback_param);
2525 #if 0
2526 typedef struct tagMONITORINFO {
2527 DWORD cbSize;
2528 RECT rcMonitor;
2529 RECT rcWork;
2530 DWORD dwFlags;
2531 } MONITORINFO, *LPMONITORINFO;
2532 #endif
2534 #define CCHDEVICENAME 8
2535 typedef struct tagMONITORINFOEX {
2536 DWORD cbSize;
2537 RECT rcMonitor;
2538 RECT rcWork;
2539 DWORD dwFlags;
2540 TCHAR szDevice[CCHDEVICENAME];
2541 } MONITORINFOEX, *LPMONITORINFOEX;
2543 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
2545 dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
2547 lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
2548 lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
2549 lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
2550 lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
2552 lpmi->dwFlags = 1; /* primary monitor */
2554 if (lpmi->cbSize == sizeof(MONITORINFOEX))
2556 LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
2557 dbgprintf("MONITORINFOEX!\n");
2558 strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
2561 return 1;
2564 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
2565 void *dispdev, int flags)
2567 dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
2568 device, device, devnum, dispdev, flags);
2569 return 1;
2572 static int WINAPI expIsWindowVisible(HWND win)
2574 dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
2575 return 1;
2578 static HWND WINAPI expGetActiveWindow(void)
2580 dbgprintf("GetActiveWindow() => 0\n");
2581 return (HWND)0;
2584 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
2586 strncat(classname, "QuickTime", maxcount);
2587 dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
2588 win, classname, maxcount, strlen(classname));
2589 return strlen(classname);
2592 #define LPWNDCLASS void *
2593 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
2595 dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
2596 classname, classname, wndclass);
2597 return 1;
2600 static int WINAPI expGetWindowLongA(HWND win, int index)
2602 dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
2603 return 1;
2606 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
2608 dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
2609 return objsize;
2612 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
2614 dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
2615 return 0;
2618 static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
2620 int i, i2;
2621 dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
2622 i = callback_func(0, callback_param);
2623 i2 = callback_func(1, callback_param);
2624 return i && i2;
2627 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
2629 int tid = pthread_self();
2630 dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
2631 win, pid_data, tid);
2632 if (pid_data)
2633 *(int*)pid_data = tid;
2634 return tid;
2637 //HWND WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
2638 // INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
2640 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
2641 const char *winname, int style, int x, int y, int w, int h,
2642 HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
2644 printf("CreateWindowEx() called\n");
2645 dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
2646 exstyle, classname, classname, winname, winname, style, x, y, w, h,
2647 parent, menu, inst, param);
2648 printf("CreateWindowEx() called okey\n");
2649 return 1;
2652 static int WINAPI expwaveOutGetNumDevs(void)
2654 dbgprintf("waveOutGetNumDevs() => 0\n");
2655 return 0;
2657 #endif
2660 * Returns the number of milliseconds, modulo 2^32, since the start
2661 * of the wineserver.
2663 static int WINAPI expGetTickCount(void)
2665 static int tcstart = 0;
2666 struct timeval t;
2667 int tc;
2668 gettimeofday( &t, NULL );
2669 tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
2670 if (tcstart == 0)
2672 tcstart = 0;
2673 tc = 0;
2675 dbgprintf("GetTickCount() => %d\n", tc);
2676 return tc;
2679 static int WINAPI expCreateFontA(void)
2681 dbgprintf("CreateFontA() => 0x0\n");
2682 return 1;
2685 /* tried to get pvmjpg work in a different way - no success */
2686 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
2687 LPRECT lpRect, unsigned int uFormat)
2689 dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
2690 return 8;
2693 static int WINAPI expGetPrivateProfileIntA(const char* appname,
2694 const char* keyname,
2695 int default_value,
2696 const char* filename)
2698 int size=255;
2699 char buffer[256];
2700 char* fullname;
2701 int result;
2703 buffer[255]=0;
2704 if(!(appname && keyname && filename) )
2706 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
2707 return default_value;
2709 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2710 strcpy(fullname, "Software\\IniFileMapping\\");
2711 strcat(fullname, appname);
2712 strcat(fullname, "\\");
2713 strcat(fullname, keyname);
2714 strcat(fullname, "\\");
2715 strcat(fullname, filename);
2716 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
2717 if((size>=0)&&(size<256))
2718 buffer[size]=0;
2719 // printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
2720 free(fullname);
2721 if(result)
2722 result=default_value;
2723 else
2724 result=atoi(buffer);
2725 dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
2726 return result;
2728 static int WINAPI expGetProfileIntA(const char* appname,
2729 const char* keyname,
2730 int default_value)
2732 dbgprintf("GetProfileIntA -> ");
2733 return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
2736 static int WINAPI expGetPrivateProfileStringA(const char* appname,
2737 const char* keyname,
2738 const char* def_val,
2739 char* dest, unsigned int len,
2740 const char* filename)
2742 int result;
2743 int size;
2744 char* fullname;
2745 dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
2746 if(!(appname && keyname && filename) ) return 0;
2747 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2748 strcpy(fullname, "Software\\IniFileMapping\\");
2749 strcat(fullname, appname);
2750 strcat(fullname, "\\");
2751 strcat(fullname, keyname);
2752 strcat(fullname, "\\");
2753 strcat(fullname, filename);
2754 size=len;
2755 result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
2756 free(fullname);
2757 if(result)
2759 strncpy(dest, def_val, size);
2760 if (strlen(def_val)< size) size = strlen(def_val);
2762 dbgprintf(" => %d ( '%s' )\n", size, dest);
2763 return size;
2765 static int WINAPI expWritePrivateProfileStringA(const char* appname,
2766 const char* keyname,
2767 const char* string,
2768 const char* filename)
2770 char* fullname;
2771 dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
2772 if(!(appname && keyname && filename) )
2774 dbgprintf(" => -1\n");
2775 return -1;
2777 fullname=malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2778 strcpy(fullname, "Software\\IniFileMapping\\");
2779 strcat(fullname, appname);
2780 strcat(fullname, "\\");
2781 strcat(fullname, keyname);
2782 strcat(fullname, "\\");
2783 strcat(fullname, filename);
2784 RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
2785 // printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
2786 // printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
2787 free(fullname);
2788 dbgprintf(" => 0\n");
2789 return 0;
2792 unsigned int GetPrivateProfileIntA_(const char* appname, const char* keyname, INT default_value, const char* filename)
2794 return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
2796 int GetPrivateProfileStringA_(const char* appname, const char* keyname,
2797 const char* def_val, char* dest, unsigned int len, const char* filename)
2799 return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
2801 int WritePrivateProfileStringA_(const char* appname, const char* keyname,
2802 const char* string, const char* filename)
2804 return expWritePrivateProfileStringA(appname, keyname, string, filename);
2809 static int WINAPI expDefDriverProc(int private, int id, int msg, int arg1, int arg2)
2811 dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", private, id, msg, arg1, arg2);
2812 return 0;
2815 static int WINAPI expSizeofResource(int v1, int v2)
2817 int result=SizeofResource(v1, v2);
2818 dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
2819 return result;
2822 static int WINAPI expGetLastError()
2824 int result=GetLastError();
2825 dbgprintf("GetLastError() => 0x%x\n", result);
2826 return result;
2829 static void WINAPI expSetLastError(int error)
2831 dbgprintf("SetLastError(0x%x)\n", error);
2832 SetLastError(error);
2835 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
2837 int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
2838 guid->f1, guid->f2, guid->f3,
2839 (unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
2840 (unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
2841 (unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
2842 (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
2843 dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
2844 return result;
2848 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
2850 dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
2851 return 0;
2854 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
2856 int result;
2857 if(string==0)result=1; else result=0;
2858 dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
2859 if(string)wch_print(string);
2860 return result;
2862 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
2864 return expIsBadStringPtrW((const short*)string, nchars);
2866 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
2868 long ret;
2869 __asm__ volatile
2871 "lock; xaddl %0,(%1)"
2872 : "=r" (ret)
2873 : "r" (dest), "0" (incr)
2874 : "memory"
2876 return ret;
2879 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
2881 unsigned long retval = *dest;
2882 if(*dest == comperand)
2883 *dest = exchange;
2884 return retval;
2887 static long WINAPI expInterlockedIncrement( long* dest )
2889 long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
2890 dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
2891 return result;
2893 static long WINAPI expInterlockedDecrement( long* dest )
2895 long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
2896 dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
2897 return result;
2900 static void WINAPI expOutputDebugStringA( const char* string )
2902 dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
2903 fprintf(stderr, "DEBUG: %s\n", string);
2906 static int WINAPI expGetDC(int hwnd)
2908 dbgprintf("GetDC(0x%x) => 1\n", hwnd);
2909 return 1;
2912 static int WINAPI expReleaseDC(int hwnd, int hdc)
2914 dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
2915 return 1;
2918 static int WINAPI expGetDesktopWindow()
2920 dbgprintf("GetDesktopWindow() => 0\n");
2921 return 0;
2924 static int cursor[100];
2926 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
2928 dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
2929 return (int)&cursor[0];
2931 static int WINAPI expSetCursor(void *cursor)
2933 dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
2934 return (int)cursor;
2936 static int WINAPI expGetCursorPos(void *cursor)
2938 dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
2939 return 1;
2941 #ifdef QTX
2942 static int show_cursor = 0;
2943 static int WINAPI expShowCursor(int show)
2945 dbgprintf("ShowCursor(%d) => %d\n", show, show);
2946 if (show)
2947 show_cursor++;
2948 else
2949 show_cursor--;
2950 return show_cursor;
2952 #endif
2953 static int WINAPI expRegisterWindowMessageA(char *message)
2955 dbgprintf("RegisterWindowMessageA(%s)\n", message);
2956 return 1;
2958 static int WINAPI expGetProcessVersion(int pid)
2960 dbgprintf("GetProcessVersion(%d)\n", pid);
2961 return 1;
2963 static int WINAPI expGetCurrentThread(void)
2965 #warning FIXME!
2966 dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
2967 return 0xcfcf9898;
2969 static int WINAPI expGetOEMCP(void)
2971 dbgprintf("GetOEMCP()\n");
2972 return 1;
2974 static int WINAPI expGetCPInfo(int cp,void *info)
2976 dbgprintf("GetCPInfo()\n");
2977 return 0;
2979 #ifdef QTX
2980 #define SM_CXSCREEN 0
2981 #define SM_CYSCREEN 1
2982 #define SM_XVIRTUALSCREEN 76
2983 #define SM_YVIRTUALSCREEN 77
2984 #define SM_CXVIRTUALSCREEN 78
2985 #define SM_CYVIRTUALSCREEN 79
2986 #define SM_CMONITORS 80
2987 #endif
2988 static int WINAPI expGetSystemMetrics(int index)
2990 dbgprintf("GetSystemMetrics(%d)\n", index);
2991 #ifdef QTX
2992 switch(index)
2994 case SM_XVIRTUALSCREEN:
2995 case SM_YVIRTUALSCREEN:
2996 return 0;
2997 case SM_CXSCREEN:
2998 case SM_CXVIRTUALSCREEN:
2999 return PSEUDO_SCREEN_WIDTH;
3000 case SM_CYSCREEN:
3001 case SM_CYVIRTUALSCREEN:
3002 return PSEUDO_SCREEN_HEIGHT;
3003 case SM_CMONITORS:
3004 return 1;
3006 #endif
3007 return 1;
3009 static int WINAPI expGetSysColor(int index)
3011 dbgprintf("GetSysColor(%d) => 1\n", index);
3012 return 1;
3014 static int WINAPI expGetSysColorBrush(int index)
3016 dbgprintf("GetSysColorBrush(%d)\n", index);
3017 return 1;
3022 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
3024 dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
3025 hdc, iStartIndex, nEntries, lppe);
3026 return 0;
3030 typedef struct TIME_ZONE_INFORMATION {
3031 long Bias;
3032 char StandardName[32];
3033 SYSTEMTIME StandardDate;
3034 long StandardBias;
3035 char DaylightName[32];
3036 SYSTEMTIME DaylightDate;
3037 long DaylightBias;
3038 } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
3041 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
3043 const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
3044 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
3045 const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
3046 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
3047 dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
3048 memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
3049 lpTimeZoneInformation->Bias=360;//GMT-6
3050 memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
3051 lpTimeZoneInformation->StandardDate.wMonth=10;
3052 lpTimeZoneInformation->StandardDate.wDay=5;
3053 lpTimeZoneInformation->StandardDate.wHour=2;
3054 lpTimeZoneInformation->StandardBias=0;
3055 memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
3056 lpTimeZoneInformation->DaylightDate.wMonth=4;
3057 lpTimeZoneInformation->DaylightDate.wDay=1;
3058 lpTimeZoneInformation->DaylightDate.wHour=2;
3059 lpTimeZoneInformation->DaylightBias=-60;
3060 return TIME_ZONE_ID_STANDARD;
3063 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
3065 time_t local_time;
3066 struct tm *local_tm;
3067 struct timeval tv;
3069 dbgprintf("GetLocalTime(0x%x)\n");
3070 gettimeofday(&tv, NULL);
3071 local_time=tv.tv_sec;
3072 local_tm=localtime(&local_time);
3074 systime->wYear = local_tm->tm_year + 1900;
3075 systime->wMonth = local_tm->tm_mon + 1;
3076 systime->wDayOfWeek = local_tm->tm_wday;
3077 systime->wDay = local_tm->tm_mday;
3078 systime->wHour = local_tm->tm_hour;
3079 systime->wMinute = local_tm->tm_min;
3080 systime->wSecond = local_tm->tm_sec;
3081 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3082 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3083 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3084 " Milliseconds: %d\n",
3085 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3086 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3089 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
3091 time_t local_time;
3092 struct tm *local_tm;
3093 struct timeval tv;
3095 dbgprintf("GetSystemTime(0x%x)\n", systime);
3096 gettimeofday(&tv, NULL);
3097 local_time=tv.tv_sec;
3098 local_tm=gmtime(&local_time);
3100 systime->wYear = local_tm->tm_year + 1900;
3101 systime->wMonth = local_tm->tm_mon + 1;
3102 systime->wDayOfWeek = local_tm->tm_wday;
3103 systime->wDay = local_tm->tm_mday;
3104 systime->wHour = local_tm->tm_hour;
3105 systime->wMinute = local_tm->tm_min;
3106 systime->wSecond = local_tm->tm_sec;
3107 systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3108 dbgprintf(" Year: %d\n Month: %d\n Day of week: %d\n"
3109 " Day: %d\n Hour: %d\n Minute: %d\n Second: %d\n"
3110 " Milliseconds: %d\n",
3111 systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3112 systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3113 return 0;
3116 #define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ULL)
3117 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
3119 struct timeval tv;
3120 unsigned long long secs;
3122 dbgprintf("GetSystemTime(0x%x)\n", systime);
3123 gettimeofday(&tv, NULL);
3124 secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
3125 secs += tv.tv_usec * 10;
3126 systime->dwLowDateTime = secs & 0xffffffff;
3127 systime->dwHighDateTime = (secs >> 32);
3130 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
3132 //char *p;
3133 // printf("%s %x %x\n", name, field, size);
3134 if(field)field[0]=0;
3136 p = getenv(name);
3137 if (p) strncpy(field,p,size);
3139 if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
3140 strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
3141 dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
3142 return strlen(field);
3145 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
3147 dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
3148 return 0;
3151 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
3153 return my_mreq(cb, 0);
3155 static void WINAPI expCoTaskMemFree(void* cb)
3157 my_release(cb);
3163 void* CoTaskMemAlloc(unsigned long cb)
3165 return expCoTaskMemAlloc(cb);
3167 void CoTaskMemFree(void* cb)
3169 expCoTaskMemFree(cb);
3172 struct COM_OBJECT_INFO
3174 GUID clsid;
3175 long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
3178 static struct COM_OBJECT_INFO* com_object_table=0;
3179 static int com_object_size=0;
3180 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3182 if(!clsid || !gcs)
3183 return -1;
3184 com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
3185 com_object_table[com_object_size-1].clsid=*clsid;
3186 com_object_table[com_object_size-1].GetClassObject=gcs;
3187 return 0;
3190 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3192 int found = 0;
3193 int i = 0;
3194 if(!clsid || !gcs)
3195 return -1;
3197 if (com_object_table == 0)
3198 printf("Warning: UnregisterComClass() called without any registered class\n");
3199 while (i < com_object_size)
3201 if (found && i > 0)
3203 memcpy(&com_object_table[i - 1].clsid,
3204 &com_object_table[i].clsid, sizeof(GUID));
3205 com_object_table[i - 1].GetClassObject =
3206 com_object_table[i].GetClassObject;
3208 else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
3209 && com_object_table[i].GetClassObject == gcs)
3211 found++;
3213 i++;
3215 if (found)
3217 if (--com_object_size == 0)
3219 free(com_object_table);
3220 com_object_table = 0;
3223 return 0;
3227 const GUID IID_IUnknown =
3229 0x00000000, 0x0000, 0x0000,
3230 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3232 const GUID IID_IClassFactory =
3234 0x00000001, 0x0000, 0x0000,
3235 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3238 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3239 long dwClsContext, const GUID* riid, void** ppv)
3241 int i;
3242 struct COM_OBJECT_INFO* ci=0;
3243 for(i=0; i<com_object_size; i++)
3244 if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
3245 ci=&com_object_table[i];
3246 if(!ci)return REGDB_E_CLASSNOTREG;
3247 // in 'real' world we should mess with IClassFactory here
3248 i=ci->GetClassObject(rclsid, riid, ppv);
3249 return i;
3252 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3253 long dwClsContext, const GUID* riid, void** ppv)
3255 return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
3258 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
3260 int r = 0;
3261 int w,h;
3262 //trapbug();
3263 if (lprc)
3265 w = lprc->right - lprc->left;
3266 h = lprc->bottom - lprc->top;
3267 if (w <= 0 || h <= 0)
3268 r = 1;
3270 else
3271 r = 1;
3273 dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
3274 //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
3275 // return 0; // wmv9?
3276 return r; // TM20
3279 static int _adjust_fdiv=0; //what's this? - used to adjust division
3280 static int _winver = 0x510; // windows version
3285 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
3287 dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
3288 if(len<5)
3290 dbgprintf(" => 0\n");
3291 return 0;
3293 strcpy(path, "/tmp");
3294 dbgprintf(" => 5 ( '/tmp' )\n");
3295 return 5;
3298 FYI:
3299 typedef struct
3301 DWORD dwFileAttributes;
3302 FILETIME ftCreationTime;
3303 FILETIME ftLastAccessTime;
3304 FILETIME ftLastWriteTime;
3305 DWORD nFileSizeHigh;
3306 DWORD nFileSizeLow;
3307 DWORD dwReserved0;
3308 DWORD dwReserved1;
3309 CHAR cFileName[260];
3310 CHAR cAlternateFileName[14];
3311 } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
3314 static DIR* qtx_dir=NULL;
3316 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
3318 #ifdef QTX
3319 dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
3320 if(h==FILE_HANDLE_quicktimeqtx){
3321 struct dirent* d;
3322 if(!qtx_dir) return 0;
3323 while((d=readdir(qtx_dir))){
3324 char* x=strrchr(d->d_name,'.');
3325 if(!x) continue;
3326 if(strcmp(x,".qtx")) continue;
3327 strcpy(lpfd->cFileName,d->d_name);
3328 // sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
3329 strcpy(lpfd->cAlternateFileName,"foobar.qtx");
3330 dbgprintf("### FindNext: %s\n",lpfd->cFileName);
3331 return 1;
3333 closedir(qtx_dir); qtx_dir=NULL;
3334 return 0;
3336 #endif
3337 return 0;
3340 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
3342 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
3343 // printf("\n### FindFirstFileA('%s')...\n",s);
3344 #ifdef QTX
3345 if(strstr(s, "quicktime\\*.QTX")){
3346 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
3347 dbgprintf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",def_path);
3348 qtx_dir=opendir(def_path);
3349 if(!qtx_dir) return (HANDLE)-1;
3350 memset(lpfd,0,sizeof(*lpfd));
3351 if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
3352 return FILE_HANDLE_quicktimeqtx;
3353 printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",def_path);
3354 return (HANDLE)-1;
3356 #if 0
3357 if(strstr(s, "QuickTime.qts")){
3358 dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
3359 // if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
3360 // return (HANDLE)-1;
3361 strcpy(lpfd->cFileName, "QuickTime.qts");
3362 strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
3363 return FILE_HANDLE_quicktimeqts;
3365 #endif
3366 #endif
3367 if(strstr(s, "*.vwp")){
3368 // hack for VoxWare codec plugins:
3369 strcpy(lpfd->cFileName, "msms001.vwp");
3370 strcpy(lpfd->cAlternateFileName, "msms001.vwp");
3371 return (HANDLE)0;
3373 // return 'file not found'
3374 return (HANDLE)-1;
3377 static WIN_BOOL WINAPI expFindClose(HANDLE h)
3379 dbgprintf("FindClose(0x%x) => 0\n", h);
3380 #ifdef QTX
3381 // if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
3382 // closedir(qtx_dir);
3383 // qtx_dir=NULL;
3384 // }
3385 #endif
3386 return 0;
3388 static UINT WINAPI expSetErrorMode(UINT i)
3390 dbgprintf("SetErrorMode(%d) => 0\n", i);
3391 return 0;
3393 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
3395 char windir[]="c:\\windows";
3396 int result;
3397 strncpy(s, windir, c);
3398 result=1+((c<strlen(windir))?c:strlen(windir));
3399 dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
3400 return result;
3402 #ifdef QTX
3403 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
3405 char curdir[]="c:\\";
3406 int result;
3407 strncpy(s, curdir, c);
3408 result=1+((c<strlen(curdir))?c:strlen(curdir));
3409 dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
3410 return result;
3413 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
3415 dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
3416 #if 0
3417 if (strrchr(pathname, '\\'))
3418 chdir(strcat(strrchr(pathname, '\\')+1, '/'));
3419 else
3420 chdir(pathname);
3421 #endif
3422 return 1;
3425 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
3427 dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
3428 pathname, pathname, sa);
3429 #if 0
3430 p = strrchr(pathname, '\\')+1;
3431 strcpy(&buf[0], p); /* should be strncpy */
3432 if (!strlen(p))
3434 buf[0] = '.';
3435 buf[1] = 0;
3437 #if 0
3438 if (strrchr(pathname, '\\'))
3439 mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
3440 else
3441 mkdir(pathname, 666);
3442 #endif
3443 mkdir(&buf);
3444 #endif
3445 return 1;
3447 #endif
3448 static WIN_BOOL WINAPI expDeleteFileA(LPCSTR s)
3450 dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
3451 return 0;
3453 static WIN_BOOL WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
3455 dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
3456 return 0;
3459 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
3461 char mask[16]="/tmp/AP_XXXXXX";
3462 int result;
3463 dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
3464 if(i && i<10)
3466 dbgprintf(" => -1\n");
3467 return -1;
3469 result=mkstemp(mask);
3470 sprintf(ps, "AP%d", result);
3471 dbgprintf(" => %d\n", strlen(ps));
3472 return strlen(ps);
3475 // This func might need proper implementation if we want AngelPotion codec.
3476 // They try to open APmpeg4v1.apl with it.
3477 // DLL will close opened file with CloseHandle().
3479 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
3480 LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
3482 dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
3483 i2, p1, i3, i4, i5);
3484 if((!cs1) || (strlen(cs1)<2))return -1;
3486 #ifdef QTX
3487 if(strstr(cs1, "QuickTime.qts"))
3489 int result;
3490 char* tmp=malloc(strlen(def_path)+50);
3491 strcpy(tmp, def_path);
3492 strcat(tmp, "/");
3493 strcat(tmp, "QuickTime.qts");
3494 result=open(tmp, O_RDONLY);
3495 free(tmp);
3496 return result;
3498 if(strstr(cs1, ".qtx"))
3500 int result;
3501 char* tmp=malloc(strlen(def_path)+250);
3502 char* x=strrchr(cs1,'\\');
3503 sprintf(tmp,"%s/%s",def_path,x?(x+1):cs1);
3504 // printf("### Open: %s -> %s\n",cs1,tmp);
3505 result=open(tmp, O_RDONLY);
3506 free(tmp);
3507 return result;
3509 #endif
3511 if(strncmp(cs1, "AP", 2) == 0)
3513 int result;
3514 char* tmp=malloc(strlen(def_path)+50);
3515 strcpy(tmp, def_path);
3516 strcat(tmp, "/");
3517 strcat(tmp, "APmpg4v1.apl");
3518 result=open(tmp, O_RDONLY);
3519 free(tmp);
3520 return result;
3522 if (strstr(cs1, "vp3"))
3524 int r;
3525 int flg = 0;
3526 char* tmp=malloc(20 + strlen(cs1));
3527 strcpy(tmp, "/tmp/");
3528 strcat(tmp, cs1);
3529 r = 4;
3530 while (tmp[r])
3532 if (tmp[r] == ':' || tmp[r] == '\\')
3533 tmp[r] = '_';
3534 r++;
3536 if (GENERIC_READ & i1)
3537 flg |= O_RDONLY;
3538 else if (GENERIC_WRITE & i1)
3540 flg |= O_WRONLY;
3541 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", tmp, r, flg);
3543 r=open(tmp, flg);
3544 free(tmp);
3545 return r;
3548 // Needed by wnvplay1.dll
3549 if (strstr(cs1, "WINNOV.bmp"))
3551 int r;
3552 r=open("/dev/null", O_RDONLY);
3553 return r;
3556 #if 0
3557 /* we need this for some virtualdub filters */
3559 int r;
3560 int flg = 0;
3561 if (GENERIC_READ & i1)
3562 flg |= O_RDONLY;
3563 else if (GENERIC_WRITE & i1)
3565 flg |= O_WRONLY;
3566 printf("Warning: openning filename %s %d (flags; 0x%x) for write\n", cs1, r, flg);
3568 r=open(cs1, flg);
3569 return r;
3571 #endif
3573 return atoi(cs1+2);
3575 static UINT WINAPI expGetSystemDirectoryA(
3576 char* lpBuffer, // address of buffer for system directory
3577 UINT uSize // size of directory buffer
3579 dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
3580 if(!lpBuffer) strcpy(lpBuffer,".");
3581 return 1;
3584 static char sysdir[]=".";
3585 static LPCSTR WINAPI expGetSystemDirectoryA()
3587 dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
3588 return sysdir;
3591 static DWORD WINAPI expGetFullPathNameA
3593 LPCTSTR lpFileName,
3594 DWORD nBufferLength,
3595 LPTSTR lpBuffer,
3596 LPTSTR lpFilePart
3598 if(!lpFileName) return 0;
3599 dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
3600 lpBuffer, lpFilePart);
3601 #if 0
3602 #ifdef QTX
3603 strcpy(lpFilePart, "Quick123.qts");
3604 #else
3605 strcpy(lpFilePart, lpFileName);
3606 #endif
3607 #else
3608 if (strrchr(lpFileName, '\\'))
3609 lpFilePart = strrchr(lpFileName, '\\');
3610 else
3611 lpFilePart = (LPTSTR)lpFileName;
3612 #endif
3613 strcpy(lpBuffer, lpFileName);
3614 // strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
3615 return strlen(lpBuffer);
3618 static DWORD WINAPI expGetShortPathNameA
3620 LPCSTR longpath,
3621 LPSTR shortpath,
3622 DWORD shortlen
3624 if(!longpath) return 0;
3625 dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
3626 strcpy(shortpath,longpath);
3627 return strlen(shortpath);
3630 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
3632 int result;
3633 dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
3634 result=read(h, pv, size);
3635 if(rd)*rd=result;
3636 if(!result)return 0;
3637 return 1;
3640 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
3642 int result;
3643 dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
3644 if(h==1234)h=1;
3645 result=write(h, pv, size);
3646 if(wr)*wr=result;
3647 if(!result)return 0;
3648 return 1;
3650 static DWORD WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
3652 int wh;
3653 dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, ext ? *ext : NULL, whence);
3654 //why would DLL want temporary file with >2Gb size?
3655 switch(whence)
3657 case FILE_BEGIN:
3658 wh=SEEK_SET;break;
3659 case FILE_END:
3660 wh=SEEK_END;break;
3661 case FILE_CURRENT:
3662 wh=SEEK_CUR;break;
3663 default:
3664 return -1;
3666 #ifdef QTX
3667 if (val == 0 && ext != 0)
3668 val = val&(*ext);
3669 #endif
3670 return lseek(h, val, wh);
3673 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
3674 LPARAM lParam2)
3676 dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3677 return -1;
3679 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
3680 LPARAM lParam2)
3682 dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3683 return -1;
3687 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
3688 LPDWORD lpProcessAffinityMask,
3689 LPDWORD lpSystemAffinityMask)
3691 dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
3692 hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
3693 if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
3694 if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
3695 return 1;
3698 // Fake implementation: does nothing, but does it right :)
3699 static WIN_BOOL WINAPI expSetProcessAffinityMask(HANDLE hProcess,
3700 LPDWORD dwProcessAffinityMask)
3702 dbgprintf("SetProcessAffinityMask(0x%x, 0x%x) => 1\n",
3703 hProcess, dwProcessAffinityMask);
3705 return 1;
3708 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
3710 static const long long max_int=0x7FFFFFFFLL;
3711 static const long long min_int=-0x80000000LL;
3712 long long tmp=(long long)nNumber*(long long)nNumerator;
3713 dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
3714 if(!nDenominator)return 1;
3715 tmp/=nDenominator;
3716 if(tmp<min_int) return 1;
3717 if(tmp>max_int) return 1;
3718 return (int)tmp;
3721 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
3723 LONG result=strcasecmp(str1, str2);
3724 dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
3725 return result;
3728 static LONG WINAPI explstrlenA(const char* str1)
3730 LONG result=strlen(str1);
3731 dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
3732 return result;
3735 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
3737 int result= (int) strcpy(str1, str2);
3738 dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
3739 return result;
3741 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
3743 int result;
3744 if (strlen(str2)>len)
3745 result = (int) strncpy(str1, str2,len);
3746 else
3747 result = (int) strcpy(str1,str2);
3748 dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
3749 return result;
3751 static LONG WINAPI explstrcatA(char* str1, const char* str2)
3753 int result= (int) strcat(str1, str2);
3754 dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
3755 return result;
3759 static LONG WINAPI expInterlockedExchange(long *dest, long l)
3761 long retval = *dest;
3762 *dest = l;
3763 return retval;
3766 static void WINAPI expInitCommonControls(void)
3768 dbgprintf("InitCommonControls called!\n");
3769 return;
3772 #ifdef QTX
3773 /* needed by QuickTime.qts */
3774 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
3775 HWND parent, INT id, HINSTANCE inst,
3776 HWND buddy, INT maxVal, INT minVal, INT curVal)
3778 dbgprintf("CreateUpDownControl(...)\n");
3779 return 0;
3781 #endif
3783 /* alex: implement this call! needed for 3ivx */
3784 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
3786 dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
3787 pUnkOuter, ppUnkInner);
3788 // return 0;
3789 return ERROR_CALL_NOT_IMPLEMENTED;
3793 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle, // handle to source process
3794 HANDLE hSourceHandle, // handle to duplicate
3795 HANDLE hTargetProcessHandle, // handle to target process
3796 HANDLE* lpTargetHandle, // duplicate handle
3797 DWORD dwDesiredAccess, // requested access
3798 int bInheritHandle, // handle inheritance option
3799 DWORD dwOptions // optional actions
3802 dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
3803 hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
3804 lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
3805 *lpTargetHandle = hSourceHandle;
3806 return 1;
3809 static HRESULT WINAPI expCoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3811 dbgprintf("CoInitializeEx(%p, %d) called\n", lpReserved, dwCoInit);
3812 return S_OK;
3815 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
3816 static HRESULT WINAPI expCoInitialize(
3817 LPVOID lpReserved /* [in] pointer to win32 malloc interface
3818 (obsolete, should be NULL) */
3822 * Just delegate to the newer method.
3824 return expCoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
3827 static void WINAPI expCoUninitialize(void)
3829 dbgprintf("CoUninitialize() called\n");
3832 /* allow static linking */
3833 HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
3835 return expCoInitializeEx(lpReserved, dwCoInit);
3837 HRESULT WINAPI CoInitialize(LPVOID lpReserved)
3839 return expCoInitialize(lpReserved);
3841 void WINAPI CoUninitialize(void)
3843 return expCoUninitialize();
3846 static DWORD WINAPI expSetThreadAffinityMask
3848 HANDLE hThread,
3849 DWORD dwThreadAffinityMask
3851 return 0;
3855 * no WINAPI functions - CDECL
3857 static void* expmalloc(int size)
3859 //printf("malloc");
3860 // return malloc(size);
3861 void* result=my_mreq(size,0);
3862 dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
3863 if(result==0)
3864 printf("WARNING: malloc() failed\n");
3865 return result;
3867 static void expfree(void* mem)
3869 // return free(mem);
3870 dbgprintf("free(%p)\n", mem);
3871 my_release(mem);
3873 /* needed by atrac3.acm */
3874 static void *expcalloc(int num, int size)
3876 void* result=my_mreq(num*size,1);
3877 dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
3878 if(result==0)
3879 printf("WARNING: calloc() failed\n");
3880 return result;
3882 static void* expnew(int size)
3884 // printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
3885 // printf("%08x %08x %08x %08x\n",
3886 // size, *(1+(int*)&size),
3887 // *(2+(int*)&size),*(3+(int*)&size));
3888 void* result;
3889 assert(size >= 0);
3891 result=my_mreq(size,0);
3892 dbgprintf("new(%d) => %p\n", size, result);
3893 if (result==0)
3894 printf("WARNING: new() failed\n");
3895 return result;
3898 static int expdelete(void* memory)
3900 dbgprintf("delete(%p)\n", memory);
3901 my_release(memory);
3902 return 0;
3906 * local definition - we need only the last two members at this point
3907 * otherwice we would have to introduce here GUIDs and some more types..
3909 typedef struct __attribute__((__packed__))
3911 char hay[0x40];
3912 unsigned long cbFormat; //0x40
3913 char* pbFormat; //0x44
3914 } MY_MEDIA_TYPE;
3915 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
3917 if (!dest || !src)
3918 return E_POINTER;
3919 memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
3920 if (dest->cbFormat)
3922 dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
3923 if (!dest->pbFormat)
3924 return E_OUTOFMEMORY;
3925 memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
3927 return S_OK;
3929 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
3931 if (!dest)
3932 return E_POINTER;
3933 memset(dest, 0, sizeof(MY_MEDIA_TYPE));
3934 if (cbFormat)
3936 dest->pbFormat = (char*) my_mreq(cbFormat, 0);
3937 if (!dest->pbFormat)
3938 return E_OUTOFMEMORY;
3940 return S_OK;
3942 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
3944 if (!dest)
3945 return E_POINTER;
3946 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3947 return expMoInitMediaType(*dest, cbFormat);
3949 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
3951 if (!dest)
3952 return E_POINTER;
3953 *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3954 return expMoCopyMediaType(*dest, src);
3956 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
3958 if (!dest)
3959 return E_POINTER;
3960 if (dest->pbFormat)
3962 my_release(dest->pbFormat);
3963 dest->pbFormat = 0;
3964 dest->cbFormat = 0;
3966 return S_OK;
3968 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
3970 if (!dest)
3971 return E_POINTER;
3972 expMoFreeMediaType(dest);
3973 my_release(dest);
3974 return S_OK;
3977 static int exp_snprintf( char *str, int size, const char *format, ... )
3979 int x;
3980 va_list va;
3981 va_start(va, format);
3982 x=snprintf(str,size,format,va);
3983 dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
3984 va_end(va);
3985 return x;
3988 #if 0
3989 static int exp_initterm(int v1, int v2)
3991 dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
3992 return 0;
3994 #else
3995 /* merged from wine - 2002.04.21 */
3996 typedef void (*INITTERMFUNC)();
3997 static int exp_initterm(INITTERMFUNC *start, INITTERMFUNC *end)
3999 dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
4000 while (start < end)
4002 if (*start)
4004 //printf("call _initfunc: from: %p %d\n", *start);
4005 // ok this trick with push/pop is necessary as otherwice
4006 // edi/esi registers are being trashed
4007 void* p = *start;
4008 __asm__ volatile
4010 "pushl %%ebx \n\t"
4011 "pushl %%ecx \n\t"
4012 "pushl %%edx \n\t"
4013 "pushl %%edi \n\t"
4014 "pushl %%esi \n\t"
4015 "call *%%eax \n\t"
4016 "popl %%esi \n\t"
4017 "popl %%edi \n\t"
4018 "popl %%edx \n\t"
4019 "popl %%ecx \n\t"
4020 "popl %%ebx \n\t"
4022 : "a"(p)
4023 : "memory"
4025 //printf("done %p %d:%d\n", end);
4027 start++;
4029 return 0;
4031 #endif
4033 /* Fake _initterm_e from msvcr80.dll, needed by sirenacm.dll
4034 * NOTE: If I make this an alias for _initterm, then sirenacm.dll tries to call
4035 other uninmplemented functions; keep this in mind if some future codec needs
4036 a real implementation of this function */
4037 static int exp_initterm_e(INITTERMFUNC *start, INITTERMFUNC *end)
4039 dbgprintf("_initterm_e(0x%x, 0x%x)\n", start, end);
4040 return 0;
4043 static void* exp__dllonexit()
4045 // FIXME extract from WINE
4046 return NULL;
4049 static int expwsprintfA(char* string, const char* format, ...)
4051 va_list va;
4052 int result;
4053 va_start(va, format);
4054 result = vsprintf(string, format, va);
4055 dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4056 va_end(va);
4057 return result;
4060 static int expsprintf(char* str, const char* format, ...)
4062 va_list args;
4063 int r;
4064 dbgprintf("sprintf(0x%x, %s)\n", str, format);
4065 va_start(args, format);
4066 r = vsprintf(str, format, args);
4067 va_end(args);
4068 return r;
4070 static int expsscanf(const char* str, const char* format, ...)
4072 va_list args;
4073 int r;
4074 dbgprintf("sscanf(%s, %s)\n", str, format);
4075 va_start(args, format);
4076 r = vsscanf(str, format, args);
4077 va_end(args);
4078 return r;
4080 static void* expfopen(const char* path, const char* mode)
4082 printf("fopen: \"%s\" mode:%s\n", path, mode);
4083 //return fopen(path, mode);
4084 return fdopen(0, mode); // everything on screen
4086 static int expfprintf(void* stream, const char* format, ...)
4088 va_list args;
4089 int r = 0;
4090 dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4091 #if 1
4092 va_start(args, format);
4093 r = vfprintf((FILE*) stream, format, args);
4094 va_end(args);
4095 #endif
4096 return r;
4099 static int expprintf(const char* format, ...)
4101 va_list args;
4102 int r;
4103 dbgprintf("printf(%s, ...)\n", format);
4104 va_start(args, format);
4105 r = vprintf(format, args);
4106 va_end(args);
4107 return r;
4110 static char* expgetenv(const char* varname)
4112 char* v = getenv(varname);
4113 dbgprintf("getenv(%s) => %s\n", varname, v);
4114 return v;
4117 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4119 WCHAR* p = dst;
4120 while ((*p++ = *src++))
4122 return dst;
4125 static char* expstrrchr(char* string, int value)
4127 char* result=strrchr(string, value);
4128 if(result)
4129 dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4130 else
4131 dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4132 return result;
4135 static char* expstrchr(char* string, int value)
4137 char* result=strchr(string, value);
4138 if(result)
4139 dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4140 else
4141 dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4142 return result;
4144 static int expstrlen(char* str)
4146 int result=strlen(str);
4147 dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4148 return result;
4150 static char* expstrcpy(char* str1, const char* str2)
4152 char* result= strcpy(str1, str2);
4153 dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4154 return result;
4156 static char* expstrncpy(char* str1, const char* str2, size_t count)
4158 char* result= strncpy(str1, str2, count);
4159 dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4160 return result;
4162 static int expstrcmp(const char* str1, const char* str2)
4164 int result=strcmp(str1, str2);
4165 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4166 return result;
4168 static int expstrncmp(const char* str1, const char* str2,int x)
4170 int result=strncmp(str1, str2,x);
4171 dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4172 return result;
4174 static char* expstrcat(char* str1, const char* str2)
4176 char* result = strcat(str1, str2);
4177 dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4178 return result;
4180 static char* exp_strdup(const char* str1)
4182 int l = strlen(str1);
4183 char* result = (char*) my_mreq(l + 1,0);
4184 if (result)
4185 strcpy(result, str1);
4186 dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4187 return result;
4189 static int expisalnum(int c)
4191 int result= (int) isalnum(c);
4192 dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4193 return result;
4195 static int expisspace(int c)
4197 int result= (int) isspace(c);
4198 dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4199 return result;
4201 static int expisalpha(int c)
4203 int result= (int) isalpha(c);
4204 dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4205 return result;
4207 static int expisdigit(int c)
4209 int result= (int) isdigit(c);
4210 dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4211 return result;
4213 static void* expmemmove(void* dest, void* src, int n)
4215 void* result = memmove(dest, src, n);
4216 dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4217 return result;
4219 static int expmemcmp(void* dest, void* src, int n)
4221 int result = memcmp(dest, src, n);
4222 dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4223 return result;
4225 static void* expmemcpy(void* dest, void* src, int n)
4227 void *result = memcpy(dest, src, n);
4228 dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4229 return result;
4231 static void* expmemset(void* dest, int c, size_t n)
4233 void *result = memset(dest, c, n);
4234 dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4235 return result;
4237 static time_t exptime(time_t* t)
4239 time_t result = time(t);
4240 dbgprintf("time(0x%x) => %d\n", t, result);
4241 return result;
4244 static int exprand(void)
4246 return rand();
4249 static void expsrand(int seed)
4251 srand(seed);
4254 #if 1
4256 // preferred compilation with -O2 -ffast-math !
4258 static double explog10(double x)
4260 /*printf("Log10 %f => %f 0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4261 return log10(x);
4264 static double expcos(double x)
4266 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4267 return cos(x);
4270 #else
4272 static void explog10(void)
4274 __asm__ volatile
4276 "fldl 8(%esp) \n\t"
4277 "fldln2 \n\t"
4278 "fxch %st(1) \n\t"
4279 "fyl2x \n\t"
4283 static void expcos(void)
4285 __asm__ volatile
4287 "fldl 8(%esp) \n\t"
4288 "fcos \n\t"
4292 #endif
4294 // this seem to be the only how to make this function working properly
4295 // ok - I've spent tremendous amount of time (many many many hours
4296 // of debuging fixing & testing - it's almost unimaginable - kabi
4298 // _ftol - operated on the float value which is already on the FPU stack
4300 static void exp_ftol(void)
4302 __asm__ volatile
4304 "sub $12, %esp \n\t"
4305 "fstcw -2(%ebp) \n\t"
4306 "wait \n\t"
4307 "movw -2(%ebp), %ax \n\t"
4308 "orb $0x0C, %ah \n\t"
4309 "movw %ax, -4(%ebp) \n\t"
4310 "fldcw -4(%ebp) \n\t"
4311 "fistpl -12(%ebp) \n\t"
4312 "fldcw -2(%ebp) \n\t"
4313 "movl -12(%ebp), %eax \n\t"
4314 //Note: gcc 3.03 does not do the following op if it
4315 // knows that ebp=esp
4316 "movl %ebp, %esp \n\t"
4320 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4321 __asm__ volatile( "fstpl %0;fwait" : "=m" (var2) : ); \
4322 __asm__ volatile( "fstpl %0;fwait" : "=m" (var1) : )
4324 static double exp_CIpow(void)
4326 FPU_DOUBLES(x,y);
4328 dbgprintf("_CIpow(%lf, %lf)\n", x, y);
4329 return pow(x, y);
4332 static double exppow(double x, double y)
4334 /*printf("Pow %f %f 0x%Lx 0x%Lx => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4335 return pow(x, y);
4338 static double expldexp(double x, int expo)
4340 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4341 return ldexp(x, expo);
4344 static double expfrexp(double x, int* expo)
4346 /*printf("Cos %f => %f 0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4347 return frexp(x, expo);
4352 static int exp_stricmp(const char* s1, const char* s2)
4354 return strcasecmp(s1, s2);
4357 /* from declaration taken from Wine sources - this fountion seems to be
4358 * undocumented in any M$ doc */
4359 static int exp_setjmp3(void* jmpbuf, int x)
4361 //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4362 //return 0;
4363 __asm__ volatile
4365 //"mov 4(%%esp), %%edx \n\t"
4366 "mov (%%esp), %%eax \n\t"
4367 "mov %%eax, (%%edx) \n\t" // store ebp
4369 //"mov %%ebp, (%%edx) \n\t"
4370 "mov %%ebx, 4(%%edx) \n\t"
4371 "mov %%edi, 8(%%edx) \n\t"
4372 "mov %%esi, 12(%%edx) \n\t"
4373 "mov %%esp, 16(%%edx) \n\t"
4375 "mov 4(%%esp), %%eax \n\t"
4376 "mov %%eax, 20(%%edx) \n\t"
4378 "movl $0x56433230, 32(%%edx) \n\t" // VC20 ??
4379 "movl $0, 36(%%edx) \n\t"
4380 : // output
4381 : "d"(jmpbuf) // input
4382 : "eax"
4384 #if 1
4385 __asm__ volatile
4387 "mov %%fs:0, %%eax \n\t" // unsure
4388 "mov %%eax, 24(%%edx) \n\t"
4389 "cmp $0xffffffff, %%eax \n\t"
4390 "jnz l1 \n\t"
4391 "mov %%eax, 28(%%edx) \n\t"
4392 "l1: \n\t"
4395 : "eax"
4397 #endif
4399 return 0;
4402 static DWORD WINAPI expGetCurrentProcessId(void)
4404 dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4405 return getpid(); //(DWORD)NtCurrentTeb()->pid;
4409 typedef struct {
4410 UINT wPeriodMin;
4411 UINT wPeriodMax;
4412 } TIMECAPS, *LPTIMECAPS;
4414 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4416 dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4418 lpCaps->wPeriodMin = 1;
4419 lpCaps->wPeriodMax = 65535;
4420 return 0;
4423 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4425 dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4427 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4428 return 0;
4431 #ifdef QTX
4432 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4434 dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4436 if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4437 return 0;
4439 #endif
4441 static void WINAPI expGlobalMemoryStatus(
4442 LPMEMORYSTATUS lpmem
4444 static MEMORYSTATUS cached_memstatus;
4445 static int cache_lastchecked = 0;
4446 SYSTEM_INFO si;
4447 FILE *f;
4449 if (time(NULL)==cache_lastchecked) {
4450 memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4451 return;
4454 #if 1
4455 f = fopen( "/proc/meminfo", "r" );
4456 if (f)
4458 char buffer[256];
4459 int total, used, free, shared, buffers, cached;
4461 lpmem->dwLength = sizeof(MEMORYSTATUS);
4462 lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4463 lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4464 while (fgets( buffer, sizeof(buffer), f ))
4466 /* old style /proc/meminfo ... */
4467 if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4469 lpmem->dwTotalPhys += total;
4470 lpmem->dwAvailPhys += free + buffers + cached;
4472 if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4474 lpmem->dwTotalPageFile += total;
4475 lpmem->dwAvailPageFile += free;
4478 /* new style /proc/meminfo ... */
4479 if (sscanf(buffer, "MemTotal: %d", &total))
4480 lpmem->dwTotalPhys = total*1024;
4481 if (sscanf(buffer, "MemFree: %d", &free))
4482 lpmem->dwAvailPhys = free*1024;
4483 if (sscanf(buffer, "SwapTotal: %d", &total))
4484 lpmem->dwTotalPageFile = total*1024;
4485 if (sscanf(buffer, "SwapFree: %d", &free))
4486 lpmem->dwAvailPageFile = free*1024;
4487 if (sscanf(buffer, "Buffers: %d", &buffers))
4488 lpmem->dwAvailPhys += buffers*1024;
4489 if (sscanf(buffer, "Cached: %d", &cached))
4490 lpmem->dwAvailPhys += cached*1024;
4492 fclose( f );
4494 if (lpmem->dwTotalPhys)
4496 DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4497 DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4498 lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4499 / (TotalPhysical / 100);
4501 } else
4502 #endif
4504 /* FIXME: should do something for other systems */
4505 lpmem->dwMemoryLoad = 0;
4506 lpmem->dwTotalPhys = 16*1024*1024;
4507 lpmem->dwAvailPhys = 16*1024*1024;
4508 lpmem->dwTotalPageFile = 16*1024*1024;
4509 lpmem->dwAvailPageFile = 16*1024*1024;
4511 expGetSystemInfo(&si);
4512 lpmem->dwTotalVirtual = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
4513 /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4514 lpmem->dwAvailVirtual = lpmem->dwTotalVirtual-64*1024;
4515 memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4516 cache_lastchecked = time(NULL);
4518 /* it appears some memory display programs want to divide by these values */
4519 if(lpmem->dwTotalPageFile==0)
4520 lpmem->dwTotalPageFile++;
4522 if(lpmem->dwAvailPageFile==0)
4523 lpmem->dwAvailPageFile++;
4526 static INT WINAPI expGetThreadPriority(HANDLE hthread)
4528 dbgprintf("GetThreadPriority(%p)\n",hthread);
4529 return 0;
4532 /**********************************************************************
4533 * SetThreadPriority [KERNEL32.@] Sets priority for thread.
4535 * RETURNS
4536 * Success: TRUE
4537 * Failure: FALSE
4539 static WIN_BOOL WINAPI expSetThreadPriority(
4540 HANDLE hthread, /* [in] Handle to thread */
4541 INT priority) /* [in] Thread priority level */
4543 dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4544 return TRUE;
4547 static void WINAPI expExitProcess( DWORD status )
4549 printf("EXIT - code %ld\n",status);
4550 exit(status);
4553 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4554 printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4555 #ifdef QTX
4556 if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4557 return IDIGNORE;
4558 #endif
4559 return IDOK;
4562 /* these are needed for mss1 */
4565 * \brief this symbol is defined within exp_EH_prolog_dummy
4566 * \param dest jump target
4568 void exp_EH_prolog(void *dest);
4569 //! just a dummy function that acts a container for the asm section
4570 void exp_EH_prolog_dummy(void) {
4571 __asm__ volatile (
4572 // take care, this "function" may not change flags or
4573 // registers besides eax (which is also why we can't use
4574 // exp_EH_prolog_dummy directly)
4575 MANGLE(exp_EH_prolog)": \n\t"
4576 "pop %eax \n\t"
4577 "push %ebp \n\t"
4578 "mov %esp, %ebp \n\t"
4579 "lea -12(%esp), %esp \n\t"
4580 "jmp *%eax \n\t"
4584 #include <netinet/in.h>
4585 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4587 // dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4588 return htonl(hostlong);
4591 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4593 // dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4594 return ntohl(netlong);
4596 static void WINAPI expVariantInit(void* p)
4598 printf("InitCommonControls called!\n");
4599 return;
4602 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4604 dbgprintf("RegisterClassA(%p) => random id\n", wc);
4605 return time(NULL); /* be precise ! */
4608 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4610 dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4611 return 0;
4614 #ifdef QTX
4615 /* should be fixed bcs it's not fully strlen equivalent */
4616 static int expSysStringByteLen(void *str)
4618 dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4619 return strlen(str);
4622 static int expDirectDrawCreate(void)
4624 dbgprintf("DirectDrawCreate(...) => NULL\n");
4625 return 0;
4628 #if 1
4629 typedef struct tagPALETTEENTRY {
4630 BYTE peRed;
4631 BYTE peGreen;
4632 BYTE peBlue;
4633 BYTE peFlags;
4634 } PALETTEENTRY;
4636 /* reversed the first 2 entries */
4637 typedef struct tagLOGPALETTE {
4638 WORD palNumEntries;
4639 WORD palVersion;
4640 PALETTEENTRY palPalEntry[1];
4641 } LOGPALETTE;
4643 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4645 HPALETTE test;
4646 int i;
4648 dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4650 i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4651 test = (HPALETTE)malloc(i);
4652 memcpy((void *)test, lpgpl, i);
4654 return test;
4656 #else
4657 static int expCreatePalette(void)
4659 dbgprintf("CreatePalette(...) => NULL\n");
4660 return NULL;
4662 #endif
4664 static int WINAPI expGetClientRect(HWND win, RECT *r)
4666 dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4667 r->right = PSEUDO_SCREEN_WIDTH;
4668 r->left = 0;
4669 r->bottom = PSEUDO_SCREEN_HEIGHT;
4670 r->top = 0;
4671 return 1;
4674 #if 0
4675 typedef struct tagPOINT {
4676 LONG x;
4677 LONG y;
4678 } POINT, *PPOINT;
4679 #endif
4681 static int WINAPI expClientToScreen(HWND win, POINT *p)
4683 dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4684 p->x = 0;
4685 p->y = 0;
4686 return 1;
4688 #endif
4690 /* for m3jpeg */
4691 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4693 dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4694 return 0;
4697 static int WINAPI expMessageBeep(int type)
4699 dbgprintf("MessageBeep(%d) => 1\n", type);
4700 return 1;
4703 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4704 HWND parent, void *dialog_func, void *init_param)
4706 dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4707 inst, name, name, parent, dialog_func, init_param);
4708 return 0x42424242;
4711 static void WINAPI expRegisterClipboardFormatA(const char *name) {
4712 dbgprintf("RegisterClipboardFormatA(0x%x = %s)\n", name, name);
4715 /* needed by imagepower mjpeg2k */
4716 static void *exprealloc(void *ptr, size_t size)
4718 dbgprintf("realloc(0x%x, %x)\n", ptr, size);
4719 if (!ptr)
4720 return my_mreq(size,0);
4721 else
4722 return my_realloc(ptr, size);
4725 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
4726 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
4728 return 1;
4731 static char * WINAPI expPathFindExtensionA(const char *path) {
4732 char *ext;
4733 if (!path)
4734 ext = NULL;
4735 else {
4736 ext = strrchr(path, '.');
4737 if (!ext)
4738 ext = &path[strlen(path)];
4740 dbgprintf("PathFindExtensionA(0x%x = %s) => 0x%x, %s\n", path, path, ext, ext);
4741 return ext;
4744 static char * WINAPI expPathFindFileNameA(const char *path) {
4745 char *name;
4746 if (!path || strlen(path) < 2)
4747 name = path;
4748 else {
4749 name = strrchr(path - 1, '\\');
4750 if (!name)
4751 name = path;
4753 dbgprintf("PathFindFileNameA(0x%x = %s) => 0x%x, %s\n", path, path, name, name);
4754 return name;
4757 static double expfloor(double x)
4759 dbgprintf("floor(%lf)\n", x);
4760 return floor(x);
4763 #define FPU_DOUBLE(var) double var; \
4764 __asm__ volatile( "fstpl %0;fwait" : "=m" (var) : )
4766 static double exp_CIcos(void)
4768 FPU_DOUBLE(x);
4770 dbgprintf("_CIcos(%lf)\n", x);
4771 return cos(x);
4774 static double exp_CIsin(void)
4776 FPU_DOUBLE(x);
4778 dbgprintf("_CIsin(%lf)\n", x);
4779 return sin(x);
4782 static double exp_CIsqrt(void)
4784 FPU_DOUBLE(x);
4786 dbgprintf("_CIsqrt(%lf)\n", x);
4787 return sqrt(x);
4790 /* Needed by rp8 sipr decoder */
4791 static LPSTR WINAPI expCharNextA(LPCSTR ptr)
4793 if (!*ptr) return (LPSTR)ptr;
4794 // dbgprintf("CharNextA(0x%08x), %s\n", ptr, ptr);
4795 return (LPSTR)(ptr + 1);
4798 // Fake implementation, needed by wvc1dmod.dll
4799 static int WINAPI expPropVariantClear(void *pvar)
4801 // dbgprintf("PropVariantclear (0x%08x), %s\n", ptr, ptr);
4802 return 1;
4805 // This define is fake, the real thing is a struct
4806 #define LPDEVMODEA void*
4807 // Dummy implementation, always return 1
4808 // Required for frapsvid.dll 2.8.1, return value does not matter
4809 static WIN_BOOL WINAPI expEnumDisplaySettingsA(LPCSTR name ,DWORD n,
4810 LPDEVMODEA devmode)
4812 dbgprintf("EnumDisplaySettingsA (dummy) => 1\n");
4813 return 1;
4816 // Fake implementation of _decode_pointer from msvcr80.dll, needed by sirenacm.dll
4817 // NOTE: undocumented function, probably the declaration is not right
4818 static int exp_decode_pointer(void *ptr)
4820 dbgprintf("_decode_pointer (0x%08x)\n", ptr);
4821 return 0;
4824 /* Fake implementation of sdt::_Lockit::_Lockit(void) from msvcp60.dll
4825 Needed by SCLS.DLL */
4826 static int exp_0Lockit_dummy(void)
4828 dbgprintf("0Lockit_dummy (??0_Lockit@std@@QAE@XZ)\n");
4829 return 0;
4832 /* Fake implementation of sdt::_Lockit::~_Lockit(void) from msvcp60.dll
4833 Needed by SCLS.DLL */
4834 static int exp_1Lockit_dummy(void)
4836 dbgprintf("1Lockit_dummy (??1_Lockit@std@@QAE@XZ)\n");
4837 return 0;
4840 struct exports
4842 char name[64];
4843 int id;
4844 void* func;
4846 struct libs
4848 char name[64];
4849 int length;
4850 struct exports* exps;
4853 #define FF(X,Y) \
4854 {#X, Y, (void*)exp##X},
4856 #define UNDEFF(X, Y) \
4857 {#X, Y, (void*)-1},
4859 struct exports exp_kernel32[]=
4861 FF(GetVolumeInformationA,-1)
4862 FF(GetDriveTypeA,-1)
4863 FF(GetLogicalDriveStringsA,-1)
4864 FF(IsBadWritePtr, 357)
4865 FF(IsBadReadPtr, 354)
4866 FF(IsBadStringPtrW, -1)
4867 FF(IsBadStringPtrA, -1)
4868 FF(DisableThreadLibraryCalls, -1)
4869 FF(CreateThread, -1)
4870 FF(CreateEventA, -1)
4871 FF(SetEvent, -1)
4872 FF(ResetEvent, -1)
4873 FF(WaitForSingleObject, -1)
4874 #ifdef QTX
4875 FF(WaitForMultipleObjects, -1)
4876 FF(ExitThread, -1)
4877 FF(CreateMutexA,-1)
4878 FF(ReleaseMutex,-1)
4879 #endif
4880 FF(GetSystemInfo, -1)
4881 FF(GetVersion, 332)
4882 FF(HeapCreate, 461)
4883 FF(HeapAlloc, -1)
4884 FF(HeapDestroy, -1)
4885 FF(HeapFree, -1)
4886 FF(HeapSize, -1)
4887 FF(HeapReAlloc,-1)
4888 FF(GetProcessHeap, -1)
4889 FF(VirtualAlloc, -1)
4890 FF(VirtualFree, -1)
4891 FF(InitializeCriticalSection, -1)
4892 FF(EnterCriticalSection, -1)
4893 FF(LeaveCriticalSection, -1)
4894 FF(DeleteCriticalSection, -1)
4895 FF(TlsAlloc, -1)
4896 FF(TlsFree, -1)
4897 FF(TlsGetValue, -1)
4898 FF(TlsSetValue, -1)
4899 FF(GetCurrentThreadId, -1)
4900 FF(GetCurrentProcess, -1)
4901 FF(LocalAlloc, -1)
4902 FF(LocalReAlloc,-1)
4903 FF(LocalLock, -1)
4904 FF(GlobalAlloc, -1)
4905 FF(GlobalReAlloc, -1)
4906 FF(GlobalLock, -1)
4907 FF(GlobalSize, -1)
4908 FF(MultiByteToWideChar, 427)
4909 FF(WideCharToMultiByte, -1)
4910 FF(GetVersionExA, -1)
4911 FF(CreateSemaphoreA, -1)
4912 FF(QueryPerformanceCounter, -1)
4913 FF(QueryPerformanceFrequency, -1)
4914 FF(LocalHandle, -1)
4915 FF(LocalUnlock, -1)
4916 FF(LocalFree, -1)
4917 FF(GlobalHandle, -1)
4918 FF(GlobalUnlock, -1)
4919 FF(GlobalFree, -1)
4920 FF(LoadResource, -1)
4921 FF(ReleaseSemaphore, -1)
4922 FF(FindResourceA, -1)
4923 FF(LockResource, -1)
4924 FF(FreeResource, -1)
4925 FF(SizeofResource, -1)
4926 FF(CloseHandle, -1)
4927 FF(GetCommandLineA, -1)
4928 FF(GetEnvironmentStringsW, -1)
4929 FF(FreeEnvironmentStringsW, -1)
4930 FF(FreeEnvironmentStringsA, -1)
4931 FF(GetEnvironmentStrings, -1)
4932 FF(GetStartupInfoA, -1)
4933 FF(GetStdHandle, -1)
4934 FF(GetFileType, -1)
4935 #ifdef QTX
4936 FF(GetFileAttributesA, -1)
4937 #endif
4938 FF(SetHandleCount, -1)
4939 FF(GetACP, -1)
4940 FF(GetModuleFileNameA, -1)
4941 FF(SetUnhandledExceptionFilter, -1)
4942 FF(LoadLibraryA, -1)
4943 FF(GetProcAddress, -1)
4944 FF(FreeLibrary, -1)
4945 FF(CreateFileMappingA, -1)
4946 FF(OpenFileMappingA, -1)
4947 FF(MapViewOfFile, -1)
4948 FF(UnmapViewOfFile, -1)
4949 FF(Sleep, -1)
4950 FF(GetModuleHandleA, -1)
4951 FF(GetProfileIntA, -1)
4952 FF(GetPrivateProfileIntA, -1)
4953 FF(GetPrivateProfileStringA, -1)
4954 FF(WritePrivateProfileStringA, -1)
4955 FF(GetLastError, -1)
4956 FF(SetLastError, -1)
4957 FF(InterlockedIncrement, -1)
4958 FF(InterlockedDecrement, -1)
4959 FF(GetTimeZoneInformation, -1)
4960 FF(OutputDebugStringA, -1)
4961 FF(GetLocalTime, -1)
4962 FF(GetSystemTime, -1)
4963 FF(GetSystemTimeAsFileTime, -1)
4964 FF(GetEnvironmentVariableA, -1)
4965 FF(SetEnvironmentVariableA, -1)
4966 FF(RtlZeroMemory,-1)
4967 FF(RtlMoveMemory,-1)
4968 FF(RtlFillMemory,-1)
4969 FF(GetTempPathA,-1)
4970 FF(FindFirstFileA,-1)
4971 FF(FindNextFileA,-1)
4972 FF(FindClose,-1)
4973 FF(FileTimeToLocalFileTime,-1)
4974 FF(DeleteFileA,-1)
4975 FF(ReadFile,-1)
4976 FF(WriteFile,-1)
4977 FF(SetFilePointer,-1)
4978 FF(GetTempFileNameA,-1)
4979 FF(CreateFileA,-1)
4980 FF(GetSystemDirectoryA,-1)
4981 FF(GetWindowsDirectoryA,-1)
4982 #ifdef QTX
4983 FF(GetCurrentDirectoryA,-1)
4984 FF(SetCurrentDirectoryA,-1)
4985 FF(CreateDirectoryA,-1)
4986 #endif
4987 FF(GetShortPathNameA,-1)
4988 FF(GetFullPathNameA,-1)
4989 FF(SetErrorMode, -1)
4990 FF(IsProcessorFeaturePresent, -1)
4991 FF(GetProcessAffinityMask, -1)
4992 FF(InterlockedExchange, -1)
4993 FF(InterlockedCompareExchange, -1)
4994 FF(MulDiv, -1)
4995 FF(lstrcmpiA, -1)
4996 FF(lstrlenA, -1)
4997 FF(lstrcpyA, -1)
4998 FF(lstrcatA, -1)
4999 FF(lstrcpynA,-1)
5000 FF(GetProcessVersion,-1)
5001 FF(GetCurrentThread,-1)
5002 FF(GetOEMCP,-1)
5003 FF(GetCPInfo,-1)
5004 FF(DuplicateHandle,-1)
5005 FF(GetTickCount, -1)
5006 FF(SetThreadAffinityMask,-1)
5007 FF(GetCurrentProcessId,-1)
5008 FF(GlobalMemoryStatus,-1)
5009 FF(GetThreadPriority,-1)
5010 FF(SetThreadPriority,-1)
5011 FF(ExitProcess,-1)
5012 {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
5013 FF(SetThreadIdealProcessor,-1)
5014 FF(SetProcessAffinityMask, -1)
5015 UNDEFF(FlsAlloc, -1)
5016 UNDEFF(FlsGetValue, -1)
5017 UNDEFF(FlsSetValue, -1)
5018 UNDEFF(FlsFree, -1)
5021 struct exports exp_msvcrt[]={
5022 FF(malloc, -1)
5023 FF(_initterm, -1)
5024 FF(__dllonexit, -1)
5025 FF(_snprintf,-1)
5026 FF(free, -1)
5027 {"??3@YAXPAX@Z", -1, expdelete},
5028 {"??2@YAPAXI@Z", -1, expnew},
5029 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5030 {"_winver",-1,(void*)&_winver},
5031 FF(strrchr, -1)
5032 FF(strchr, -1)
5033 FF(strlen, -1)
5034 FF(strcpy, -1)
5035 FF(strncpy, -1)
5036 FF(wcscpy, -1)
5037 FF(strcmp, -1)
5038 FF(strncmp, -1)
5039 FF(strcat, -1)
5040 FF(_stricmp,-1)
5041 FF(_strdup,-1)
5042 FF(_setjmp3,-1)
5043 FF(isalnum, -1)
5044 FF(isspace, -1)
5045 FF(isalpha, -1)
5046 FF(isdigit, -1)
5047 FF(memmove, -1)
5048 FF(memcmp, -1)
5049 FF(memset, -1)
5050 FF(memcpy, -1)
5051 FF(time, -1)
5052 FF(rand, -1)
5053 FF(srand, -1)
5054 FF(log10, -1)
5055 FF(pow, -1)
5056 FF(cos, -1)
5057 FF(_ftol,-1)
5058 FF(_CIpow,-1)
5059 FF(_CIcos,-1)
5060 FF(_CIsin,-1)
5061 FF(_CIsqrt,-1)
5062 FF(ldexp,-1)
5063 FF(frexp,-1)
5064 FF(sprintf,-1)
5065 FF(sscanf,-1)
5066 FF(fopen,-1)
5067 FF(fprintf,-1)
5068 FF(printf,-1)
5069 FF(getenv,-1)
5070 FF(floor,-1)
5071 /* needed by frapsvid.dll */
5072 {"strstr",-1,(char *)&strstr},
5073 {"qsort",-1,(void *)&qsort},
5074 FF(_EH_prolog,-1)
5075 FF(calloc,-1)
5076 {"ceil",-1,(void*)&ceil},
5077 /* needed by imagepower mjpeg2k */
5078 {"clock",-1,(void*)&clock},
5079 {"memchr",-1,(void*)&memchr},
5080 {"vfprintf",-1,(void*)&vfprintf},
5081 // {"realloc",-1,(void*)&realloc},
5082 FF(realloc,-1)
5083 {"puts",-1,(void*)&puts}
5085 struct exports exp_winmm[]={
5086 FF(GetDriverModuleHandle, -1)
5087 FF(timeGetTime, -1)
5088 FF(DefDriverProc, -1)
5089 FF(OpenDriverA, -1)
5090 FF(OpenDriver, -1)
5091 FF(timeGetDevCaps, -1)
5092 FF(timeBeginPeriod, -1)
5093 #ifdef QTX
5094 FF(timeEndPeriod, -1)
5095 FF(waveOutGetNumDevs, -1)
5096 #endif
5098 struct exports exp_user32[]={
5099 FF(LoadIconA,-1)
5100 FF(LoadStringA, -1)
5101 FF(wsprintfA, -1)
5102 FF(GetDC, -1)
5103 FF(GetDesktopWindow, -1)
5104 FF(ReleaseDC, -1)
5105 FF(IsRectEmpty, -1)
5106 FF(LoadCursorA,-1)
5107 FF(SetCursor,-1)
5108 FF(GetCursorPos,-1)
5109 #ifdef QTX
5110 FF(ShowCursor,-1)
5111 #endif
5112 FF(RegisterWindowMessageA,-1)
5113 FF(GetSystemMetrics,-1)
5114 FF(GetSysColor,-1)
5115 FF(GetSysColorBrush,-1)
5116 FF(GetWindowDC, -1)
5117 FF(DrawTextA, -1)
5118 FF(MessageBoxA, -1)
5119 FF(RegisterClassA, -1)
5120 FF(UnregisterClassA, -1)
5121 #ifdef QTX
5122 FF(GetWindowRect, -1)
5123 FF(MonitorFromWindow, -1)
5124 FF(MonitorFromRect, -1)
5125 FF(MonitorFromPoint, -1)
5126 FF(EnumDisplayMonitors, -1)
5127 FF(GetMonitorInfoA, -1)
5128 FF(EnumDisplayDevicesA, -1)
5129 FF(GetClientRect, -1)
5130 FF(ClientToScreen, -1)
5131 FF(IsWindowVisible, -1)
5132 FF(GetActiveWindow, -1)
5133 FF(GetClassNameA, -1)
5134 FF(GetClassInfoA, -1)
5135 FF(GetWindowLongA, -1)
5136 FF(EnumWindows, -1)
5137 FF(GetWindowThreadProcessId, -1)
5138 FF(CreateWindowExA, -1)
5139 #endif
5140 FF(MessageBeep, -1)
5141 FF(DialogBoxParamA, -1)
5142 FF(RegisterClipboardFormatA, -1)
5143 FF(CharNextA, -1)
5144 FF(EnumDisplaySettingsA, -1)
5146 struct exports exp_advapi32[]={
5147 FF(RegCloseKey, -1)
5148 FF(RegCreateKeyA, -1)
5149 FF(RegCreateKeyExA, -1)
5150 FF(RegEnumKeyExA, -1)
5151 FF(RegEnumValueA, -1)
5152 FF(RegOpenKeyA, -1)
5153 FF(RegOpenKeyExA, -1)
5154 FF(RegQueryValueExA, -1)
5155 FF(RegSetValueExA, -1)
5156 FF(RegQueryInfoKeyA, -1)
5158 struct exports exp_gdi32[]={
5159 FF(CreateCompatibleDC, -1)
5160 FF(CreateFontA, -1)
5161 FF(DeleteDC, -1)
5162 FF(DeleteObject, -1)
5163 FF(GetDeviceCaps, -1)
5164 FF(GetSystemPaletteEntries, -1)
5165 #ifdef QTX
5166 FF(CreatePalette, -1)
5167 FF(GetObjectA, -1)
5168 FF(CreateRectRgn, -1)
5169 #endif
5171 struct exports exp_version[]={
5172 FF(GetFileVersionInfoSizeA, -1)
5174 struct exports exp_ole32[]={
5175 FF(CoCreateFreeThreadedMarshaler,-1)
5176 FF(CoCreateInstance, -1)
5177 FF(CoInitialize, -1)
5178 FF(CoInitializeEx, -1)
5179 FF(CoUninitialize, -1)
5180 FF(CoTaskMemAlloc, -1)
5181 FF(CoTaskMemFree, -1)
5182 FF(StringFromGUID2, -1)
5183 FF(PropVariantClear, -1)
5185 // do we really need crtdll ???
5186 // msvcrt is the correct place probably...
5187 struct exports exp_crtdll[]={
5188 FF(memcpy, -1)
5189 FF(wcscpy, -1)
5191 struct exports exp_comctl32[]={
5192 FF(StringFromGUID2, -1)
5193 FF(InitCommonControls, 17)
5194 #ifdef QTX
5195 FF(CreateUpDownControl, 16)
5196 #endif
5198 struct exports exp_wsock32[]={
5199 FF(htonl,8)
5200 FF(ntohl,14)
5202 struct exports exp_msdmo[]={
5203 FF(memcpy, -1) // just test
5204 FF(MoCopyMediaType, -1)
5205 FF(MoCreateMediaType, -1)
5206 FF(MoDeleteMediaType, -1)
5207 FF(MoDuplicateMediaType, -1)
5208 FF(MoFreeMediaType, -1)
5209 FF(MoInitMediaType, -1)
5211 struct exports exp_oleaut32[]={
5212 FF(VariantInit, 8)
5213 #ifdef QTX
5214 FF(SysStringByteLen, 149)
5215 #endif
5218 /* realplayer8:
5219 DLL Name: PNCRT.dll
5220 vma: Hint/Ord Member-Name
5221 22ff4 615 free
5222 2302e 250 _ftol
5223 22fea 666 malloc
5224 2303e 609 fprintf
5225 2305e 167 _adjust_fdiv
5226 23052 280 _initterm
5228 22ffc 176 _beginthreadex
5229 23036 284 _iob
5230 2300e 85 __CxxFrameHandler
5231 23022 411 _purecall
5233 #ifdef REALPLAYER
5234 struct exports exp_pncrt[]={
5235 FF(malloc, -1) // just test
5236 FF(free, -1) // just test
5237 FF(fprintf, -1) // just test
5238 {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5239 FF(_ftol,-1)
5240 FF(_initterm, -1)
5241 {"??3@YAXPAX@Z", -1, expdelete},
5242 {"??2@YAPAXI@Z", -1, expnew},
5243 FF(__dllonexit, -1)
5244 FF(strncpy, -1)
5245 FF(_CIpow,-1)
5246 FF(calloc,-1)
5247 FF(memmove, -1)
5248 FF(ldexp, -1)
5249 FF(frexp, -1)
5251 #endif
5253 #ifdef QTX
5254 struct exports exp_ddraw[]={
5255 FF(DirectDrawCreate, -1)
5257 #endif
5259 struct exports exp_comdlg32[]={
5260 FF(GetOpenFileNameA, -1)
5263 struct exports exp_shlwapi[]={
5264 FF(PathFindExtensionA, -1)
5265 FF(PathFindFileNameA, -1)
5268 struct exports exp_msvcr80[]={
5269 FF(_CIpow,-1)
5270 FF(_CIsin,-1)
5271 FF(_CIcos,-1)
5272 FF(_CIsqrt,-1)
5273 FF(memset,-1)
5274 FF(_initterm_e, -1)
5275 FF(_initterm, -1)
5276 FF(_decode_pointer, -1)
5279 struct exports exp_msvcp60[]={
5280 {"??0_Lockit@std@@QAE@XZ", -1, exp_0Lockit_dummy},
5281 {"??1_Lockit@std@@QAE@XZ", -1, exp_1Lockit_dummy}
5284 #define LL(X) \
5285 {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5287 struct libs libraries[]={
5288 LL(kernel32)
5289 LL(msvcrt)
5290 LL(winmm)
5291 LL(user32)
5292 LL(advapi32)
5293 LL(gdi32)
5294 LL(version)
5295 LL(ole32)
5296 LL(oleaut32)
5297 LL(crtdll)
5298 LL(comctl32)
5299 LL(wsock32)
5300 LL(msdmo)
5301 #ifdef REALPLAYER
5302 LL(pncrt)
5303 #endif
5304 #ifdef QTX
5305 LL(ddraw)
5306 #endif
5307 LL(comdlg32)
5308 LL(shlwapi)
5309 LL(msvcr80)
5310 LL(msvcp60)
5313 static WIN_BOOL WINAPI ext_stubs(void)
5315 volatile int idx = 0xdeadabcd;
5316 // make sure gcc does not do eip-relative call or something like that
5317 volatile void (*my_printf)(char *, char *) = (void *)0xdeadfbcd;
5318 my_printf("Called unk_%s\n", export_names[idx]);
5319 return 0;
5322 #define MAX_STUB_SIZE 0x60
5323 #define MAX_NUM_STUBS 200
5324 static int pos=0;
5325 static char *extcode = NULL;
5327 static void* add_stub(void)
5329 int i;
5330 int found = 0;
5331 // generated code in runtime!
5332 char* answ;
5333 if (!extcode)
5334 extcode = mmap_anon(NULL, MAX_NUM_STUBS * MAX_STUB_SIZE,
5335 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0);
5336 answ = extcode + pos * MAX_STUB_SIZE;
5337 if (pos >= MAX_NUM_STUBS) {
5338 printf("too many stubs, expect crash\n");
5339 return NULL;
5341 memcpy(answ, ext_stubs, MAX_STUB_SIZE);
5342 for (i = 0; i < MAX_STUB_SIZE - 3; i++) {
5343 int *magic = (int *)(answ + i);
5344 if (*magic == 0xdeadabcd) {
5345 *magic = pos;
5346 found |= 1;
5348 if (*magic == 0xdeadfbcd) {
5349 *magic = (intptr_t)printf;
5350 found |= 2;
5353 if (found != 3) {
5354 printf("magic code not found in ext_subs, expect crash\n");
5355 return NULL;
5357 pos++;
5358 return (void*)answ;
5361 void* LookupExternal(const char* library, int ordinal)
5363 int i,j;
5364 if(library==0)
5366 printf("ERROR: library=0\n");
5367 return (void*)ext_unknown;
5369 // printf("%x %x\n", &unk_exp1, &unk_exp2);
5371 dbgprintf("External func %s:%d\n", library, ordinal);
5373 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5375 if(strcasecmp(library, libraries[i].name))
5376 continue;
5377 for(j=0; j<libraries[i].length; j++)
5379 if(ordinal!=libraries[i].exps[j].id)
5380 continue;
5381 //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5382 return libraries[i].exps[j].func;
5386 #ifndef LOADLIB_TRY_NATIVE
5387 /* hack for truespeech and vssh264*/
5388 if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5389 #endif
5390 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5392 int hand;
5393 WINE_MODREF *wm;
5394 void *func;
5396 hand = LoadLibraryA(library);
5397 if (!hand)
5398 goto no_dll;
5399 wm = MODULE32_LookupHMODULE(hand);
5400 if (!wm)
5402 FreeLibrary(hand);
5403 goto no_dll;
5405 func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5406 if (!func)
5408 printf("No such ordinal in external dll\n");
5409 FreeLibrary((int)hand);
5410 goto no_dll;
5413 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5414 hand, func);
5415 return func;
5418 no_dll:
5419 if(pos>150)return 0;
5420 sprintf(export_names[pos], "%s:%d", library, ordinal);
5421 return add_stub();
5424 void* LookupExternalByName(const char* library, const char* name)
5426 int i,j;
5427 // return (void*)ext_unknown;
5428 if(library==0)
5430 printf("ERROR: library=0\n");
5431 return (void*)ext_unknown;
5433 if((unsigned long)name<=0xffff)
5435 return LookupExternal(library, (int)name);
5437 dbgprintf("External func %s:%s\n", library, name);
5438 for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5440 if(strcasecmp(library, libraries[i].name))
5441 continue;
5442 for(j=0; j<libraries[i].length; j++)
5444 if(strcmp(name, libraries[i].exps[j].name))
5445 continue;
5446 if((unsigned int)(libraries[i].exps[j].func) == -1)
5447 return NULL; //undefined func
5448 // printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5449 return libraries[i].exps[j].func;
5453 #ifndef LOADLIB_TRY_NATIVE
5454 /* hack for vss h264 */
5455 if (!strcmp(library,"vssh264core.dll") || !strcmp(library,"3ivx.dll"))
5456 #endif
5457 /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5459 int hand;
5460 WINE_MODREF *wm;
5461 void *func;
5463 hand = LoadLibraryA(library);
5464 if (!hand)
5465 goto no_dll_byname;
5466 wm = MODULE32_LookupHMODULE(hand);
5467 if (!wm)
5469 FreeLibrary(hand);
5470 goto no_dll_byname;
5472 func = PE_FindExportedFunction(wm, name, 0);
5473 if (!func)
5475 printf("No such name in external dll\n");
5476 FreeLibrary((int)hand);
5477 goto no_dll_byname;
5480 printf("External dll loaded (offset: 0x%x, func: %p)\n",
5481 hand, func);
5482 return func;
5485 no_dll_byname:
5486 if(pos>150)return 0;// to many symbols
5487 strcpy(export_names[pos], name);
5488 return add_stub();
5491 void my_garbagecollection(void)
5493 #ifdef GARBAGE
5494 int unfree = 0, unfreecnt = 0;
5496 int max_fatal = 8;
5497 free_registry();
5498 while (last_alloc)
5500 alloc_header* mem = last_alloc + 1;
5501 unfree += my_size(mem);
5502 unfreecnt++;
5503 if (my_release(mem) != 0)
5504 // avoid endless loop when memory is trashed
5505 if (--max_fatal < 0)
5506 break;
5508 dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5509 #endif
5510 g_tls = NULL;
5511 list = NULL;