]> git.sesse.net Git - vlc/blob - libs/loader/win32.c
Mac OS X gui: Revert r19259. We are not ready to do proper locking.
[vlc] / libs / loader / win32.c
1 /*
2  * $Id$
3  *
4  * Originally distributed under LPGL 2.1 (or later) by the Wine project.
5  *
6  * Modified for use with MPlayer, detailed CVS changelog at
7  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
8  *
9  * File now distributed as part of VLC media player with no modifications.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  */
25
26 /***********************************************************
27
28 Win32 emulation code. Functions that emulate
29 responses from corresponding Win32 API calls.
30 Since we are not going to be able to load
31 virtually any DLL, we can only implement this
32 much, adding needed functions with each new codec.
33
34 Basic principle of implementation: it's not good
35 for DLL to know too much about its environment.
36
37 ************************************************************/
38
39 #include "config.h"
40
41 #ifdef MPLAYER
42 #ifdef USE_QTX_CODECS
43 #define QTX
44 #endif
45 #define REALPLAYER
46 //#define LOADLIB_TRY_NATIVE
47 #endif
48
49 #ifdef QTX
50 #define PSEUDO_SCREEN_WIDTH     /*640*/800
51 #define PSEUDO_SCREEN_HEIGHT    /*480*/600
52 #endif
53
54 #include "wine/winbase.h"
55 #include "wine/winreg.h"
56 #include "wine/winnt.h"
57 #include "wine/winerror.h"
58 #include "wine/debugtools.h"
59 #include "wine/module.h"
60 #include "wine/winuser.h"
61
62 #include <stdio.h>
63 #include "win32.h"
64
65 #include "registry.h"
66 #include "loader.h"
67 #include "com.h"
68 #include "ext.h"
69
70 #include <stdlib.h>
71 #include <assert.h>
72 #include <stdarg.h>
73 #include <ctype.h>
74 #include <pthread.h>
75 #include <errno.h>
76 #ifdef HAVE_MALLOC_H
77 #include <malloc.h>
78 #endif
79 #include <time.h>
80 #include <math.h>
81 #include <unistd.h>
82 #include <fcntl.h>
83 #include <sys/types.h>
84 #include <dirent.h>
85 #include <sys/time.h>
86 #include <sys/timeb.h>
87 #ifdef  HAVE_KSTAT
88 #include <kstat.h>
89 #endif
90
91 #if HAVE_VSSCANF
92 int vsscanf( const char *str, const char *format, va_list ap);
93 #else
94 /* system has no vsscanf.  try to provide one */
95 static int vsscanf( const char *str, const char *format, va_list ap)
96 {
97     long p1 = va_arg(ap, long);
98     long p2 = va_arg(ap, long);
99     long p3 = va_arg(ap, long);
100     long p4 = va_arg(ap, long);
101     long p5 = va_arg(ap, long);
102     return sscanf(str, format, p1, p2, p3, p4, p5);
103 }
104 #endif
105
106 static char* def_path = WIN32_PATH;
107
108 static void do_cpuid(unsigned int ax, unsigned int *regs)
109 {
110     __asm__ __volatile__
111         (
112          "pushl %%ebx; pushl %%ecx; pushl %%edx;"
113          ".byte  0x0f, 0xa2;"
114          "movl   %%eax, (%2);"
115          "movl   %%ebx, 4(%2);"
116          "movl   %%ecx, 8(%2);"
117          "movl   %%edx, 12(%2);"
118          "popl %%edx; popl %%ecx; popl %%ebx;"
119          : "=a" (ax)
120          :  "0" (ax), "S" (regs)
121         );
122 }
123 static unsigned int c_localcount_tsc()
124 {
125     int a;
126     __asm__ __volatile__
127         (
128          "rdtsc\n\t"
129          :"=a"(a)
130          :
131          :"edx"
132         );
133     return a;
134 }
135 static void c_longcount_tsc(long long* z)
136 {
137     __asm__ __volatile__
138         (
139          "pushl %%ebx\n\t"
140          "movl %%eax, %%ebx\n\t"
141          "rdtsc\n\t"
142          "movl %%eax, 0(%%ebx)\n\t"
143          "movl %%edx, 4(%%ebx)\n\t"
144          "popl %%ebx\n\t"
145          ::"a"(z)
146          :"edx"
147         );
148 }
149 static unsigned int c_localcount_notsc()
150 {
151     struct timeval tv;
152     unsigned limit=~0;
153     limit/=1000000;
154     gettimeofday(&tv, 0);
155     return limit*tv.tv_usec;
156 }
157 static void c_longcount_notsc(long long* z)
158 {
159     struct timeval tv;
160     unsigned long long result;
161     unsigned limit=~0;
162     if(!z)return;
163     limit/=1000000;
164     gettimeofday(&tv, 0);
165     result=tv.tv_sec;
166     result<<=32;
167     result+=limit*tv.tv_usec;
168     *z=result;
169 }
170 static unsigned int localcount_stub(void);
171 static void longcount_stub(long long*);
172 static unsigned int (*localcount)()=localcount_stub;
173 static void (*longcount)(long long*)=longcount_stub;
174
175 static pthread_mutex_t memmut;
176
177 static unsigned int localcount_stub(void)
178 {
179     unsigned int regs[4];
180     do_cpuid(1, regs);
181     if ((regs[3] & 0x00000010) != 0)
182     {
183         localcount=c_localcount_tsc;
184         longcount=c_longcount_tsc;
185     }
186     else
187     {
188         localcount=c_localcount_notsc;
189         longcount=c_longcount_notsc;
190     }
191     return localcount();
192 }
193 static void longcount_stub(long long* z)
194 {
195     unsigned int regs[4];
196     do_cpuid(1, regs);
197     if ((regs[3] & 0x00000010) != 0)
198     {
199         localcount=c_localcount_tsc;
200         longcount=c_longcount_tsc;
201     }
202     else
203     {
204         localcount=c_localcount_notsc;
205         longcount=c_longcount_notsc;
206     }
207     longcount(z);
208 }
209
210 #ifdef MPLAYER
211 #include "../mp_msg.h"
212 #endif
213 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
214 //#define DETAILED_OUT
215 static inline void dbgprintf(char* fmt, ...)
216 {
217 #ifdef DETAILED_OUT
218     if(LOADER_DEBUG)
219     {
220         FILE* f;
221         va_list va;
222         va_start(va, fmt);
223         f=fopen("./log", "a");
224         vprintf(fmt, va);
225         fflush(stdout);
226         if(f)
227         {
228             vfprintf(f, fmt, va);
229             fsync(fileno(f));
230             fclose(f);
231         }
232         va_end(va);
233     }
234 #endif
235 #ifdef MPLAYER
236     if (verbose > 2)
237     {
238         va_list va;
239         
240         va_start(va, fmt);
241         vprintf(fmt, va);
242 //      mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
243         va_end(va);
244     }
245   fflush(stdout);
246 #endif
247 }
248
249
250 char export_names[300][32]={
251     "name1",
252     //"name2",
253     //"name3"
254 };
255 //#define min(x,y) ((x)<(y)?(x):(y))
256
257 void destroy_event(void* event);
258
259 struct th_list_t;
260 typedef struct th_list_t{
261     int id;
262     void* thread;
263     struct th_list_t* next;
264     struct th_list_t* prev;
265 } th_list;
266
267
268 // have to be cleared by GARBAGE COLLECTOR
269 static unsigned char* heap=NULL;
270 static int heap_counter=0;
271 static tls_t* g_tls=NULL;
272 static th_list* list=NULL;
273
274 static void test_heap(void)
275 {
276     int offset=0;
277     if(heap==0)
278         return;
279     while(offset<heap_counter)
280     {
281         if(*(int*)(heap+offset)!=0x433476)
282         {
283             printf("Heap corruption at address %d\n", offset);
284             return;
285         }
286         offset+=8+*(int*)(heap+offset+4);
287     }
288     for(;offset<min(offset+1000, 20000000); offset++)
289         if(heap[offset]!=0xCC)
290         {
291             printf("Free heap corruption at address %d\n", offset);
292         }
293 }
294 #undef MEMORY_DEBUG
295
296 #ifdef MEMORY_DEBUG
297
298 static void* my_mreq(int size, int to_zero)
299 {
300     static int test=0;
301     test++;
302     if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
303     //    test_heap();
304     if(heap==NULL)
305     {
306         heap=malloc(20000000);
307         memset(heap, 0xCC,20000000);
308     }
309     if(heap==0)
310     {
311         printf("No enough memory\n");
312         return 0;
313     }
314     if(heap_counter+size>20000000)
315     {
316         printf("No enough memory\n");
317         return 0;
318     }
319     *(int*)(heap+heap_counter)=0x433476;
320     heap_counter+=4;
321     *(int*)(heap+heap_counter)=size;
322     heap_counter+=4;
323     printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
324     if(to_zero)
325         memset(heap+heap_counter, 0, size);
326     else
327         memset(heap+heap_counter, 0xcc, size);  // make crash reproducable
328     heap_counter+=size;
329     return heap+heap_counter-size;
330 }
331 static int my_release(char* memory)
332 {
333     //    test_heap();
334     if(memory==NULL)
335     {
336         printf("ERROR: free(0)\n");
337         return 0;
338     }
339     if(*(int*)(memory-8)!=0x433476)
340     {
341         printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
342         return 0;
343     }
344     printf("Freed %d bytes of memory\n", *(int*)(memory-4));
345     //    memset(memory-8, *(int*)(memory-4), 0xCC);
346     return 0;
347 }
348
349 #else
350 #define GARBAGE
351 typedef struct alloc_header_t alloc_header;
352 struct alloc_header_t
353 {
354     // let's keep allocated data 16 byte aligned
355     alloc_header* prev;
356     alloc_header* next;
357     long deadbeef;
358     long size;
359     long type;
360     long reserved1;
361     long reserved2;
362     long reserved3;
363 };
364
365 #ifdef GARBAGE
366 static alloc_header* last_alloc = NULL;
367 static int alccnt = 0;
368 #endif
369
370 #define AREATYPE_CLIENT 0
371 #define AREATYPE_EVENT 1
372 #define AREATYPE_MUTEX 2
373 #define AREATYPE_COND 3
374 #define AREATYPE_CRITSECT 4
375
376 /* -- critical sections -- */
377 struct CRITSECT
378 {
379     pthread_t id;
380     pthread_mutex_t mutex;
381     int locked;
382     long deadbeef;
383 };
384
385 void* mreq_private(int size, int to_zero, int type);
386 void* mreq_private(int size, int to_zero, int type)
387 {
388     int nsize = size + sizeof(alloc_header);
389     alloc_header* header = (alloc_header* ) malloc(nsize);
390     if (!header)
391         return 0;
392     if (to_zero)
393         memset(header, 0, nsize);
394 #ifdef GARBAGE
395     if (!last_alloc)
396     {
397         pthread_mutex_init(&memmut, NULL);
398         pthread_mutex_lock(&memmut);
399     }
400     else
401     {
402         pthread_mutex_lock(&memmut);
403         last_alloc->next = header;  /* set next */
404     }
405
406     header->prev = last_alloc;
407     header->next = 0;
408     last_alloc = header;
409     alccnt++;
410     pthread_mutex_unlock(&memmut);
411 #endif
412     header->deadbeef = 0xdeadbeef;
413     header->size = size;
414     header->type = type;
415
416     //if (alccnt < 40000) printf("MY_REQ: %p\t%d   t:%d  (cnt:%d)\n",  header, size, type, alccnt);
417     return header + 1;
418 }
419
420 static int my_release(void* memory)
421 {
422     alloc_header* header = (alloc_header*) memory - 1;
423 #ifdef GARBAGE
424     alloc_header* prevmem;
425     alloc_header* nextmem;
426
427     if (memory == 0)
428         return 0;
429
430     if (header->deadbeef != (long) 0xdeadbeef)
431     {
432         dbgprintf("FATAL releasing corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
433         return 0;
434     }
435
436     pthread_mutex_lock(&memmut);
437
438     switch(header->type)
439     {
440     case AREATYPE_EVENT:
441         destroy_event(memory);
442         break;
443     case AREATYPE_COND:
444         pthread_cond_destroy((pthread_cond_t*)memory);
445         break;
446     case AREATYPE_MUTEX:
447         pthread_mutex_destroy((pthread_mutex_t*)memory);
448         break;
449     case AREATYPE_CRITSECT:
450         pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
451         break;
452     default:
453         //memset(memory, 0xcc, header->size);
454         ;
455     }
456
457     header->deadbeef = 0;
458     prevmem = header->prev;
459     nextmem = header->next;
460
461     if (prevmem)
462         prevmem->next = nextmem;
463     if (nextmem)
464         nextmem->prev = prevmem;
465
466     if (header == last_alloc)
467         last_alloc = prevmem;
468
469     alccnt--;
470
471     if (last_alloc)
472         pthread_mutex_unlock(&memmut);
473     else
474         pthread_mutex_destroy(&memmut);
475
476     //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld    (%d)\n", header, header->size, alccnt);
477 #else
478     if (memory == 0)
479         return 0;
480 #endif
481     //memset(header + 1, 0xcc, header->size);
482     free(header);
483     return 0;
484 }
485 #endif
486
487 static inline void* my_mreq(int size, int to_zero)
488 {
489     return mreq_private(size, to_zero, AREATYPE_CLIENT);
490 }
491
492 static int my_size(void* memory)
493 {
494     if(!memory) return 0;
495     return ((alloc_header*)memory)[-1].size;
496 }
497
498 static void* my_realloc(void* memory, int size)
499 {
500     void *ans = memory;
501     int osize;
502     if (memory == NULL)
503         return my_mreq(size, 0);
504     osize = my_size(memory);
505     if (osize < size)
506     {
507         ans = my_mreq(size, 0);
508         memcpy(ans, memory, osize);
509         my_release(memory);
510     }
511     return ans;
512 }
513
514 /*
515  *
516  *  WINE  API  - native implementation for several win32 libraries
517  *
518  */
519
520 static int WINAPI ext_unknown()
521 {
522     printf("Unknown func called\n");
523     return 0;
524 }
525
526 static int  WINAPI expGetVolumeInformationA( const char *root, char *label,
527                                        unsigned int label_len, unsigned int *serial,
528                                        unsigned int *filename_len,unsigned int *flags,
529                                        char *fsname, unsigned int fsname_len )
530 {
531 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
532                       root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
533 //hack Do not return any real data - do nothing
534 return 1;
535 }
536
537 static unsigned int WINAPI expGetDriveTypeA( const char *root )
538 {
539  dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
540  // hack return as Fixed Drive Type
541  return DRIVE_FIXED;
542 }
543
544 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
545 {
546  dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
547  // hack only have one drive c:\ in this hack
548   *buffer++='c';
549   *buffer++=':';
550   *buffer++='\\';
551   *buffer++='\0';
552   *buffer= '\0';
553 return 4; // 1 drive * 4 bytes (includes null)
554 }
555
556
557 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
558 {
559     int result = (count == 0 || ptr != 0) ? 0 : 1;
560     dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
561     return result;
562 }
563 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
564 {
565     int result = (count == 0 || ptr != 0) ? 0 : 1;
566     dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
567     return result;
568 }
569 static int WINAPI expDisableThreadLibraryCalls(int module)
570 {
571     dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
572     return 0;
573 }
574
575 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
576 {
577     HMODULE result;
578     if (pdrv==NULL)
579         result=0;
580     else
581         result=pdrv->hDriverModule;
582     dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
583     return result;
584 }
585
586 #define MODULE_HANDLE_kernel32  ((HMODULE)0x120)
587 #define MODULE_HANDLE_user32    ((HMODULE)0x121)
588 #ifdef QTX
589 #define MODULE_HANDLE_wininet   ((HMODULE)0x122)
590 #define MODULE_HANDLE_ddraw     ((HMODULE)0x123)
591 #define MODULE_HANDLE_advapi32  ((HMODULE)0x124)
592 #endif
593 #define MODULE_HANDLE_comdlg32  ((HMODULE)0x125)
594 #define MODULE_HANDLE_msvcrt    ((HMODULE)0x126)
595 #define MODULE_HANDLE_ole32     ((HMODULE)0x127)
596 #define MODULE_HANDLE_winmm     ((HMODULE)0x128)
597
598 static HMODULE WINAPI expGetModuleHandleA(const char* name)
599 {
600     WINE_MODREF* wm;
601     HMODULE result;
602     if(!name)
603 #ifdef QTX
604         result=1;
605 #else
606         result=0;
607 #endif
608     else
609     {
610         wm=MODULE_FindModule(name);
611         if(wm==0)result=0;
612         else
613             result=(HMODULE)(wm->module);
614     }
615     if(!result)
616     {
617         if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
618             result=MODULE_HANDLE_kernel32;
619 #ifdef QTX
620         if(name && strcasecmp(name, "user32")==0)
621             result=MODULE_HANDLE_user32;
622 #endif
623     }
624     dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
625     return result;
626 }
627
628 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
629                                     void* lpStartAddress, void* lpParameter,
630                                     long dwFlags, long* dwThreadId)
631 {
632     pthread_t *pth;
633     //    printf("CreateThread:");
634     pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
635     pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
636     if(dwFlags)
637         printf( "WARNING: CreateThread flags not supported\n");
638     if(dwThreadId)
639         *dwThreadId=(long)pth;
640     if(list==NULL)
641     {
642         list=my_mreq(sizeof(th_list), 1);
643         list->next=list->prev=NULL;
644     }
645     else
646     {
647         list->next=my_mreq(sizeof(th_list), 0);
648         list->next->prev=list;
649         list->next->next=NULL;
650         list=list->next;
651     }
652     list->thread=pth;
653     dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
654               pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
655     return pth;
656 }
657
658 struct mutex_list_t;
659
660 struct mutex_list_t
661 {
662     char type;
663     pthread_mutex_t *pm;
664     pthread_cond_t  *pc;
665     char state;
666     char reset;
667     char name[128];
668     int  semaphore;
669     struct mutex_list_t* next;
670     struct mutex_list_t* prev;
671 };
672 typedef struct mutex_list_t mutex_list;
673 static mutex_list* mlist=NULL;
674
675 void destroy_event(void* event)
676 {
677     mutex_list* pp=mlist;
678     //    printf("garbage collector: destroy_event(%x)\n", event);
679     while(pp)
680     {
681         if(pp==(mutex_list*)event)
682         {
683             if(pp->next)
684                 pp->next->prev=pp->prev;
685             if(pp->prev)
686                 pp->prev->next=pp->next;
687             if(mlist==(mutex_list*)event)
688                 mlist=mlist->prev;
689             /*
690              pp=mlist;
691              while(pp)
692              {
693              printf("%x => ", pp);
694              pp=pp->prev;
695              }
696              printf("0\n");
697              */
698             return;
699         }
700         pp=pp->prev;
701     }
702 }
703
704 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
705                                     char bInitialState, const char* name)
706 {
707     pthread_mutex_t *pm;
708     pthread_cond_t  *pc;
709     /*
710      mutex_list* pp;
711      pp=mlist;
712      while(pp)
713      {
714      printf("%x => ", pp);
715      pp=pp->prev;
716      }
717      printf("0\n");
718      */
719     if(mlist!=NULL)
720     {
721         mutex_list* pp=mlist;
722         if(name!=NULL)
723             do
724         {
725             if((strcmp(pp->name, name)==0) && (pp->type==0))
726             {
727                 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
728                           pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
729                 return pp->pm;
730             }
731         }while((pp=pp->prev) != NULL);
732     }
733     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
734     pthread_mutex_init(pm, NULL);
735     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
736     pthread_cond_init(pc, NULL);
737     if(mlist==NULL)
738     {
739         mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
740         mlist->next=mlist->prev=NULL;
741     }
742     else
743     {
744         mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
745         mlist->next->prev=mlist;
746         mlist->next->next=NULL;
747         mlist=mlist->next;
748     }
749     mlist->type=0; /* Type Event */
750     mlist->pm=pm;
751     mlist->pc=pc;
752     mlist->state=bInitialState;
753     mlist->reset=bManualReset;
754     if(name)
755         strncpy(mlist->name, name, 127);
756     else
757         mlist->name[0]=0;
758     if(pm==NULL)
759         dbgprintf("ERROR::: CreateEventA failure\n");
760     /*
761      if(bInitialState)
762      pthread_mutex_lock(pm);
763      */
764     if(name)
765         dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
766                   pSecAttr, bManualReset, bInitialState, name, name, mlist);
767     else
768         dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
769                   pSecAttr, bManualReset, bInitialState, mlist);
770     return mlist;
771 }
772
773 static void* WINAPI expSetEvent(void* event)
774 {
775     mutex_list *ml = (mutex_list *)event;
776     dbgprintf("SetEvent(%x) => 0x1\n", event);
777     pthread_mutex_lock(ml->pm);
778     if (ml->state == 0) {
779         ml->state = 1;
780         pthread_cond_signal(ml->pc);
781     }
782     pthread_mutex_unlock(ml->pm);
783
784     return (void *)1;
785 }
786 static void* WINAPI expResetEvent(void* event)
787 {
788     mutex_list *ml = (mutex_list *)event;
789     dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
790     pthread_mutex_lock(ml->pm);
791     ml->state = 0;
792     pthread_mutex_unlock(ml->pm);
793
794     return (void *)1;
795 }
796
797 static void* WINAPI expWaitForSingleObject(void* object, int duration)
798 {
799     mutex_list *ml = (mutex_list *)object;
800     // FIXME FIXME FIXME - this value is sometime unititialize !!!
801     int ret = WAIT_FAILED;
802     mutex_list* pp=mlist;
803     if(object == (void*)0xcfcf9898)
804     {
805         /**
806          From GetCurrentThread() documentation:
807          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.
808
809          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.
810
811          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.
812          **/
813         dbgprintf("WaitForSingleObject(thread_handle) called\n");
814         return (void*)WAIT_FAILED;
815     }
816     dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
817
818     // loop below was slightly fixed - its used just for checking if
819     // this object really exists in our list
820     if (!ml)
821         return (void*) ret;
822     while (pp && (pp->pm != ml->pm))
823         pp = pp->prev;
824     if (!pp) {
825         dbgprintf("WaitForSingleObject: NotFound\n");
826         return (void*)ret;
827     }
828
829     pthread_mutex_lock(ml->pm);
830
831     switch(ml->type) {
832     case 0: /* Event */
833         if (duration == 0) { /* Check Only */
834             if (ml->state == 1) ret = WAIT_FAILED;
835             else                   ret = WAIT_OBJECT_0;
836         }
837         if (duration == -1) { /* INFINITE */
838             if (ml->state == 0)
839                 pthread_cond_wait(ml->pc,ml->pm);
840             if (ml->reset)
841                 ml->state = 0;
842             ret = WAIT_OBJECT_0;
843         }
844         if (duration > 0) {  /* Timed Wait */
845             struct timespec abstime;
846             struct timeval now;
847             gettimeofday(&now, 0);
848             abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
849             abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
850             if (ml->state == 0)
851                 ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
852             if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
853             else                  ret = WAIT_OBJECT_0;
854             if (ml->reset)
855                 ml->state = 0;
856         }
857         break;
858     case 1:  /* Semaphore */
859         if (duration == 0) {
860             if(ml->semaphore==0) ret = WAIT_FAILED;
861             else {
862                 ml->semaphore++;
863                 ret = WAIT_OBJECT_0;
864             }
865         }
866         if (duration == -1) {
867             if (ml->semaphore==0)
868                 pthread_cond_wait(ml->pc,ml->pm);
869             ml->semaphore--;
870         }
871         break;
872     }
873     pthread_mutex_unlock(ml->pm);
874
875     dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
876     return (void *)ret;
877 }
878
879 #ifdef QTX
880 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
881                     int WaitAll, int duration)
882 {
883     int i;
884     void *object;
885     void *ret;
886
887     dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
888         count, objects, WaitAll, duration);
889     
890     for (i = 0; i < count; i++)
891     {
892         object = (void *)objects[i];
893         ret = expWaitForSingleObject(object, duration);
894         if (WaitAll)
895             dbgprintf("WaitAll flag not yet supported...\n");
896         else
897             return ret;
898     }
899     return NULL;
900 }
901
902 static void WINAPI expExitThread(int retcode)
903 {
904     dbgprintf("ExitThread(%d)\n", retcode);
905     pthread_exit(&retcode);
906 }
907
908 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
909                     char bInitialOwner, const char *name)
910 {
911     HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
912     
913     if (name)
914         dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
915             pSecAttr, bInitialOwner, name, mlist);
916     else
917         dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
918             pSecAttr, bInitialOwner, mlist);
919 #ifndef QTX
920     /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
921        waits for ever, else it works ;) */
922     return mlist;
923 #endif
924 }
925
926 static int WINAPI expReleaseMutex(HANDLE hMutex)
927 {
928     dbgprintf("ReleaseMutex(%x) => 1\n", hMutex);
929     /* FIXME:XXX !! not yet implemented */
930     return 1;
931 }
932 #endif
933
934 static int pf_set = 0;
935 static BYTE PF[64] = {0,};
936
937 static void DumpSystemInfo(const SYSTEM_INFO* si)
938 {
939     dbgprintf("  Processor architecture %d\n", si->u.s.wProcessorArchitecture);
940     dbgprintf("  Page size: %d\n", si->dwPageSize);
941     dbgprintf("  Minimum app address: %d\n", si->lpMinimumApplicationAddress);
942     dbgprintf("  Maximum app address: %d\n", si->lpMaximumApplicationAddress);
943     dbgprintf("  Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
944     dbgprintf("  Number of processors: %d\n", si->dwNumberOfProcessors);
945     dbgprintf("  Processor type: 0x%x\n", si->dwProcessorType);
946     dbgprintf("  Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
947     dbgprintf("  Processor level: 0x%x\n", si->wProcessorLevel);
948     dbgprintf("  Processor revision: 0x%x\n", si->wProcessorRevision);
949 }
950
951 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
952 {
953     /* FIXME: better values for the two entries below... */
954     static int cache = 0;
955     static SYSTEM_INFO cachedsi;
956     unsigned int regs[4];
957     dbgprintf("GetSystemInfo(%p) =>\n", si);
958
959     if (cache) {
960         memcpy(si,&cachedsi,sizeof(*si));
961         DumpSystemInfo(si);
962         return;
963     }
964     memset(PF,0,sizeof(PF));
965     pf_set = 1;
966
967     cachedsi.u.s.wProcessorArchitecture     = PROCESSOR_ARCHITECTURE_INTEL;
968     cachedsi.dwPageSize                         = getpagesize();
969
970     /* FIXME: better values for the two entries below... */
971     cachedsi.lpMinimumApplicationAddress        = (void *)0x00000000;
972     cachedsi.lpMaximumApplicationAddress        = (void *)0x7FFFFFFF;
973     cachedsi.dwActiveProcessorMask              = 1;
974     cachedsi.dwNumberOfProcessors               = 1;
975     cachedsi.dwProcessorType            = PROCESSOR_INTEL_386;
976     cachedsi.dwAllocationGranularity    = 0x10000;
977     cachedsi.wProcessorLevel            = 5; /* pentium */
978     cachedsi.wProcessorRevision         = 0x0101;
979
980 #ifdef MPLAYER
981     /* mplayer's way to detect PF's */
982     {
983 #include "../cpudetect.h"
984         extern CpuCaps gCpuCaps;
985
986         if (gCpuCaps.hasMMX)
987             PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
988         if (gCpuCaps.hasSSE)
989             PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
990         if (gCpuCaps.has3DNow)
991             PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
992
993             if (gCpuCaps.cpuType == 4)
994             {
995                 cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
996                 cachedsi.wProcessorLevel = 4;
997             }
998             else if (gCpuCaps.cpuType >= 5)
999             {
1000                 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1001                 cachedsi.wProcessorLevel = 5;
1002             }
1003             else
1004             {
1005                 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1006                 cachedsi.wProcessorLevel = 3;
1007             }
1008             cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
1009             cachedsi.dwNumberOfProcessors = 1;  /* hardcoded */
1010     }
1011 #endif
1012
1013 /* disable cpuid based detection (mplayer's cpudetect.c does this - see above) */
1014 #ifndef MPLAYER
1015 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__svr4__) || defined(__DragonFly__)
1016     do_cpuid(1, regs);
1017     switch ((regs[0] >> 8) & 0xf) {                     // cpu family
1018     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1019     cachedsi.wProcessorLevel= 3;
1020     break;
1021     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1022     cachedsi.wProcessorLevel= 4;
1023     break;
1024     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1025     cachedsi.wProcessorLevel= 5;
1026     break;
1027     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1028     cachedsi.wProcessorLevel= 5;
1029     break;
1030     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1031     cachedsi.wProcessorLevel= 5;
1032     break;
1033     }
1034     cachedsi.wProcessorRevision = regs[0] & 0xf;        // stepping
1035     if (regs[3] & (1 <<  8))
1036         PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1037     if (regs[3] & (1 << 23))
1038         PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1039     if (regs[3] & (1 << 25))
1040         PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1041     if (regs[3] & (1 << 31))
1042         PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1043     cachedsi.dwNumberOfProcessors=1;
1044 #endif
1045 #endif /* MPLAYER */
1046
1047 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
1048    fdiv_bug and fpu emulation flags -- alex/MPlayer */
1049 #ifdef __linux__
1050     {
1051         char buf[20];
1052         char line[200];
1053         FILE *f = fopen ("/proc/cpuinfo", "r");
1054
1055         if (!f)
1056             return;
1057         while (fgets(line,200,f)!=NULL) {
1058             char        *s,*value;
1059
1060             /* NOTE: the ':' is the only character we can rely on */
1061             if (!(value = strchr(line,':')))
1062                 continue;
1063             /* terminate the valuename */
1064             *value++ = '\0';
1065             /* skip any leading spaces */
1066             while (*value==' ') value++;
1067             if ((s=strchr(value,'\n')))
1068                 *s='\0';
1069
1070             /* 2.1 method */
1071             if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
1072                 if (isdigit (value[0])) {
1073                     switch (value[0] - '0') {
1074                     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1075                     cachedsi.wProcessorLevel= 3;
1076                     break;
1077                     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1078                     cachedsi.wProcessorLevel= 4;
1079                     break;
1080                     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1081                     cachedsi.wProcessorLevel= 5;
1082                     break;
1083                     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1084                     cachedsi.wProcessorLevel= 5;
1085                     break;
1086                     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1087                     cachedsi.wProcessorLevel= 5;
1088                     break;
1089                     }
1090                 }
1091                 /* set the CPU type of the current processor */
1092                 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1093                 continue;
1094             }
1095             /* old 2.0 method */
1096             if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
1097                 if (    isdigit (value[0]) && value[1] == '8' &&
1098                         value[2] == '6' && value[3] == 0
1099                    ) {
1100                     switch (value[0] - '0') {
1101                     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
1102                     cachedsi.wProcessorLevel= 3;
1103                     break;
1104                     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
1105                     cachedsi.wProcessorLevel= 4;
1106                     break;
1107                     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1108                     cachedsi.wProcessorLevel= 5;
1109                     break;
1110                     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1111                     cachedsi.wProcessorLevel= 5;
1112                     break;
1113                     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
1114                     cachedsi.wProcessorLevel= 5;
1115                     break;
1116                     }
1117                 }
1118                 /* set the CPU type of the current processor */
1119                 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
1120                 continue;
1121             }
1122             if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
1123                 if (!lstrncmpiA(value,"yes",3))
1124                     PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
1125
1126                 continue;
1127             }
1128             if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
1129                 if (!lstrncmpiA(value,"no",2))
1130                     PF[PF_FLOATING_POINT_EMULATED] = TRUE;
1131
1132                 continue;
1133             }
1134             if (!lstrncmpiA(line,"processor",strlen("processor"))) {
1135                 /* processor number counts up...*/
1136                 unsigned int x;
1137
1138                 if (sscanf(value,"%d",&x))
1139                     if (x+1>cachedsi.dwNumberOfProcessors)
1140                         cachedsi.dwNumberOfProcessors=x+1;
1141
1142                 /* Create a new processor subkey on a multiprocessor
1143                  * system
1144                  */
1145                 sprintf(buf,"%d",x);
1146             }
1147             if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
1148                 int     x;
1149
1150                 if (sscanf(value,"%d",&x))
1151                     cachedsi.wProcessorRevision = x;
1152             }
1153             if
1154                 ( (!lstrncmpiA(line,"flags",strlen("flags")))
1155                   || (!lstrncmpiA(line,"features",strlen("features"))) )
1156             {
1157                 if (strstr(value,"cx8"))
1158                     PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
1159                 if (strstr(value,"mmx"))
1160                     PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
1161                 if (strstr(value,"tsc"))
1162                     PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
1163                 if (strstr(value,"xmm"))
1164                     PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
1165                 if (strstr(value,"3dnow"))
1166                     PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
1167             }
1168         }
1169         fclose (f);
1170         /*
1171          *      ad hoc fix for smp machines.
1172          *      some problems on WaitForSingleObject,CreateEvent,SetEvent
1173          *                      CreateThread ...etc..
1174          *
1175          */
1176         cachedsi.dwNumberOfProcessors=1;
1177     }
1178 #endif /* __linux__ */
1179     cache = 1;
1180     memcpy(si,&cachedsi,sizeof(*si));
1181     DumpSystemInfo(si);
1182 }
1183
1184 // avoid undefined expGetSystemInfo
1185 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
1186 {
1187     WIN_BOOL result = 0;
1188     if (!pf_set)
1189     {
1190         SYSTEM_INFO si;
1191         expGetSystemInfo(&si);
1192     }
1193     if(v<64) result=PF[v];
1194     dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
1195     return result;
1196 }
1197
1198
1199 static long WINAPI expGetVersion()
1200 {
1201     dbgprintf("GetVersion() => 0xC0000004\n");
1202     return 0xC0000004;//Windows 95
1203 }
1204
1205 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
1206 {
1207     //    printf("HeapCreate:");
1208     HANDLE result;
1209     if(init_size==0)
1210         result=(HANDLE)my_mreq(0x110000, 0);
1211     else
1212         result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
1213     dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
1214     return result;
1215 }
1216
1217 // this is another dirty hack
1218 // VP31 is releasing one allocated Heap chunk twice
1219 // we will silently ignore this second call...
1220 static void* heapfreehack = 0;
1221 static int heapfreehackshown = 0;
1222 //extern void trapbug(void);
1223 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
1224 {
1225     void* z;
1226     /**
1227      Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
1228      HeapAlloc returns area larger than size argument :-/
1229
1230      actually according to M$ Doc  HeapCreate size should be rounded
1231      to page boundaries thus we should simulate this
1232      **/
1233     //if (size == 22276) trapbug();
1234     z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
1235     if(z==0)
1236         printf("HeapAlloc failure\n");
1237     dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
1238     heapfreehack = 0; // reset
1239     return z;
1240 }
1241 static long WINAPI expHeapDestroy(void* heap)
1242 {
1243     dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
1244     my_release(heap);
1245     return 1;
1246 }
1247
1248 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
1249 {
1250     dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
1251     if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
1252         && lpMem != (void*)0xbdbdbdbd)
1253         // 0xbdbdbdbd is for i263_drv.drv && libefence
1254         // it seems to be reading from relased memory
1255         // EF_PROTECT_FREE doens't show any probleme
1256         my_release(lpMem);
1257     else
1258     {
1259         if (!heapfreehackshown++)
1260             printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
1261     }
1262     heapfreehack = lpMem;
1263     return 1;
1264 }
1265 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
1266 {
1267     long result=my_size(pointer);
1268     dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
1269     return result;
1270 }
1271 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
1272 {
1273     long orgsize = my_size(lpMem);
1274     dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
1275     return my_realloc(lpMem, size);
1276 }
1277 static long WINAPI expGetProcessHeap(void)
1278 {
1279     dbgprintf("GetProcessHeap() => 1\n");
1280     return 1;
1281 }
1282 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
1283 {
1284     void* z = VirtualAlloc(v1, v2, v3, v4);
1285     if(z==0)
1286         printf("VirtualAlloc failure\n");
1287     dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
1288     return z;
1289 }
1290 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
1291 {
1292     int result = VirtualFree(v1,v2,v3);
1293     dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
1294     return result;
1295 }
1296
1297 /* we're building a table of critical sections. cs_win pointer uses the DLL
1298  cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
1299 struct critsecs_list_t
1300 {
1301     CRITICAL_SECTION *cs_win;
1302     struct CRITSECT *cs_unix;
1303 };
1304
1305 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
1306 #undef CRITSECS_NEWTYPE
1307 //#define CRITSECS_NEWTYPE 1
1308
1309 #ifdef CRITSECS_NEWTYPE
1310 /* increased due to ucod needs more than 32 entries */
1311 /* and 64 should be enough for everything */
1312 #define CRITSECS_LIST_MAX 64
1313 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
1314
1315 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
1316 {
1317     int i;
1318
1319     for (i=0; i < CRITSECS_LIST_MAX; i++)
1320         if (critsecs_list[i].cs_win == cs_win)
1321             return(i);
1322     return(-1);
1323 }
1324
1325 static int critsecs_get_unused(void)
1326 {
1327     int i;
1328
1329     for (i=0; i < CRITSECS_LIST_MAX; i++)
1330         if (critsecs_list[i].cs_win == NULL)
1331             return(i);
1332     return(-1);
1333 }
1334
1335 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
1336 {
1337     int i;
1338
1339     for (i=0; i < CRITSECS_LIST_MAX; i++)
1340         if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
1341             return(critsecs_list[i].cs_unix);
1342     return(NULL);
1343 }
1344 #endif
1345
1346 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
1347 {
1348     dbgprintf("InitializeCriticalSection(0x%x)\n", c);
1349     /*    if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
1350      {
1351      printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
1352      sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
1353      return;
1354      }*/
1355     /*    pthread_mutex_init((pthread_mutex_t*)c, NULL);   */
1356 #ifdef CRITSECS_NEWTYPE
1357     {
1358         struct CRITSECT *cs;
1359         int i = critsecs_get_unused();
1360
1361         if (i < 0)
1362         {
1363             printf("InitializeCriticalSection(%p) - no more space in list\n", c);
1364             return;
1365         }
1366         dbgprintf("got unused space at %d\n", i);
1367         cs = malloc(sizeof(struct CRITSECT));
1368         if (!cs)
1369         {
1370             printf("InitializeCriticalSection(%p) - out of memory\n", c);
1371             return;
1372         }
1373         pthread_mutex_init(&cs->mutex, NULL);
1374         cs->locked = 0;
1375         critsecs_list[i].cs_win = c;
1376         critsecs_list[i].cs_unix = cs;
1377         dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
1378                   i, c, cs);
1379     }
1380 #else
1381     {
1382         struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
1383                                            0, AREATYPE_CRITSECT);
1384         pthread_mutex_init(&cs->mutex, NULL);
1385         cs->locked=0;
1386         cs->deadbeef = 0xdeadbeef;
1387         *(void**)c = cs;
1388     }
1389 #endif
1390     return;
1391 }
1392
1393 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
1394 {
1395 #ifdef CRITSECS_NEWTYPE
1396     struct CRITSECT* cs = critsecs_get_unix(c);
1397 #else
1398     struct CRITSECT* cs = (*(struct CRITSECT**)c);
1399 #endif
1400     dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
1401     if (!cs)
1402     {
1403         dbgprintf("entered uninitialized critisec!\n");
1404         expInitializeCriticalSection(c);
1405 #ifdef CRITSECS_NEWTYPE
1406         cs=critsecs_get_unix(c);
1407 #else
1408         cs = (*(struct CRITSECT**)c);
1409 #endif
1410         dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
1411     }
1412     if(cs->locked)
1413         if(cs->id==pthread_self())
1414             return;
1415     pthread_mutex_lock(&(cs->mutex));
1416     cs->locked=1;
1417     cs->id=pthread_self();
1418     return;
1419 }
1420 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
1421 {
1422 #ifdef CRITSECS_NEWTYPE
1423     struct CRITSECT* cs = critsecs_get_unix(c);
1424 #else
1425     struct CRITSECT* cs = (*(struct CRITSECT**)c);
1426 #endif
1427     //    struct CRITSECT* cs=(struct CRITSECT*)c;
1428     dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
1429     if (!cs)
1430     {
1431         dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
1432         return;
1433     }
1434     if (cs->locked)
1435     {
1436         cs->locked=0;
1437         pthread_mutex_unlock(&(cs->mutex));
1438     }
1439     else
1440         dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
1441     return;
1442 }
1443
1444 static void expfree(void* mem); /* forward declaration */
1445
1446 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
1447 {
1448 #ifdef CRITSECS_NEWTYPE
1449     struct CRITSECT* cs = critsecs_get_unix(c);
1450 #else
1451     struct CRITSECT* cs= (*(struct CRITSECT**)c);
1452 #endif
1453     //    struct CRITSECT* cs=(struct CRITSECT*)c;
1454     dbgprintf("DeleteCriticalSection(0x%x)\n",c);
1455
1456     if (!cs)
1457     {
1458         dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
1459         return;
1460     }
1461     
1462     if (cs->locked)
1463     {
1464         dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
1465         pthread_mutex_unlock(&(cs->mutex));
1466     }
1467
1468 #ifndef GARBAGE
1469     pthread_mutex_destroy(&(cs->mutex));
1470     // released by GarbageCollector in my_relase otherwise
1471 #endif
1472     my_release(cs);
1473 #ifdef CRITSECS_NEWTYPE
1474     {
1475         int i = critsecs_get_pos(c);
1476
1477         if (i < 0)
1478         {
1479             printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
1480             return;
1481         }
1482
1483         critsecs_list[i].cs_win = NULL;
1484         expfree(critsecs_list[i].cs_unix);
1485         critsecs_list[i].cs_unix = NULL;
1486         dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
1487     }
1488 #endif
1489     return;
1490 }
1491 static int WINAPI expGetCurrentThreadId()
1492 {
1493     dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
1494     return pthread_self();
1495 }
1496 static int WINAPI expGetCurrentProcess()
1497 {
1498     dbgprintf("GetCurrentProcess() => %d\n", getpid());
1499     return getpid();
1500 }
1501
1502 #ifdef QTX
1503 // this version is required for Quicktime codecs (.qtx/.qts) to work.
1504 // (they assume some pointers at FS: segment)
1505
1506 extern void* fs_seg;
1507
1508 //static int tls_count;
1509 static int tls_use_map[64];
1510 static int WINAPI expTlsAlloc()
1511 {
1512     int i;
1513     for(i=0; i<64; i++)
1514         if(tls_use_map[i]==0)
1515         {
1516             tls_use_map[i]=1;
1517             dbgprintf("TlsAlloc() => %d\n",i);
1518             return i;
1519         }
1520     dbgprintf("TlsAlloc() => -1 (ERROR)\n");
1521     return -1;
1522 }
1523
1524 //static int WINAPI expTlsSetValue(DWORD index, void* value)
1525 static int WINAPI expTlsSetValue(int index, void* value)
1526 {
1527     dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
1528 //    if((index<0) || (index>64))
1529     if((index>=64))
1530         return 0;
1531     *(void**)((char*)fs_seg+0x88+4*index) = value;
1532     return 1;
1533 }
1534
1535 static void* WINAPI expTlsGetValue(DWORD index)
1536 {
1537     dbgprintf("TlsGetValue(%d)\n",index);
1538 //    if((index<0) || (index>64))
1539     if((index>=64)) return NULL;
1540     return *(void**)((char*)fs_seg+0x88+4*index);
1541 }
1542
1543 static int WINAPI expTlsFree(int idx)
1544 {
1545     int index = (int) idx;
1546     dbgprintf("TlsFree(%d)\n",index);
1547     if((index<0) || (index>64))
1548         return 0;
1549     tls_use_map[index]=0;
1550     return 1;
1551 }
1552
1553 #else
1554 struct tls_s {
1555     void* value;
1556     int used;
1557     struct tls_s* prev;
1558     struct tls_s* next;
1559 };
1560
1561 static void* WINAPI expTlsAlloc()
1562 {
1563     if (g_tls == NULL)
1564     {
1565         g_tls=my_mreq(sizeof(tls_t), 0);
1566         g_tls->next=g_tls->prev=NULL;
1567     }
1568     else
1569     {
1570         g_tls->next=my_mreq(sizeof(tls_t), 0);
1571         g_tls->next->prev=g_tls;
1572         g_tls->next->next=NULL;
1573         g_tls=g_tls->next;
1574     }
1575     dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
1576     if (g_tls)
1577         g_tls->value=0; /* XXX For Divx.dll */
1578     return g_tls;
1579 }
1580
1581 static int WINAPI expTlsSetValue(void* idx, void* value)
1582 {
1583     tls_t* index = (tls_t*) idx;
1584     int result;
1585     if(index==0)
1586         result=0;
1587     else
1588     {
1589         index->value=value;
1590         result=1;
1591     }
1592     dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
1593     return result;
1594 }
1595 static void* WINAPI expTlsGetValue(void* idx)
1596 {
1597     tls_t* index = (tls_t*) idx;
1598     void* result;
1599     if(index==0)
1600         result=0;
1601     else
1602         result=index->value;
1603     dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
1604     return result;
1605 }
1606 static int WINAPI expTlsFree(void* idx)
1607 {
1608     tls_t* index = (tls_t*) idx;
1609     int result;
1610     if(index==0)
1611         result=0;
1612     else
1613     {
1614         if(index->next)
1615             index->next->prev=index->prev;
1616         if(index->prev)
1617             index->prev->next=index->next;
1618         if (g_tls == index)
1619             g_tls = index->prev;
1620         my_release((void*)index);
1621         result=1;
1622     }
1623     dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
1624     return result;
1625 }
1626 #endif
1627
1628 static void* WINAPI expLocalAlloc(int flags, int size)
1629 {
1630     void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
1631     if (z == 0)
1632         printf("LocalAlloc() failed\n");
1633     dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1634     return z;
1635 }
1636
1637 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
1638 {
1639     void *newpointer;
1640     int oldsize;
1641
1642     newpointer=NULL;
1643     if (flags & LMEM_MODIFY) {
1644         dbgprintf("LocalReAlloc MODIFY\n");
1645         return (void *)handle;
1646     }
1647     oldsize = my_size((void *)handle);
1648     newpointer = my_realloc((void *)handle,size);
1649     dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
1650
1651     return newpointer;
1652 }
1653
1654 static void* WINAPI expLocalLock(void* z)
1655 {
1656     dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
1657     return z;
1658 }
1659
1660 static void* WINAPI expGlobalAlloc(int flags, int size)
1661 {
1662     void* z;
1663     dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
1664
1665     z=my_mreq(size, (flags & GMEM_ZEROINIT));
1666     //z=calloc(size, 1);
1667     //z=malloc(size);
1668     if(z==0)
1669         printf("GlobalAlloc() failed\n");
1670     dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
1671     return z;
1672 }
1673 static void* WINAPI expGlobalLock(void* z)
1674 {
1675     dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
1676     return z;
1677 }
1678 // pvmjpg20 - but doesn't work anyway
1679 static int WINAPI expGlobalSize(void* amem)
1680 {
1681     int size = 100000;
1682 #ifdef GARBAGE
1683     alloc_header* header = last_alloc;
1684     alloc_header* mem = (alloc_header*) amem - 1;
1685     if (amem == 0)
1686         return 0;
1687     pthread_mutex_lock(&memmut);
1688     while (header)
1689     {
1690         if (header->deadbeef != 0xdeadbeef)
1691         {
1692             dbgprintf("FATAL found corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
1693             break;
1694         }
1695
1696         if (header == mem)
1697         {
1698             size = header->size;
1699             break;
1700         }
1701
1702         header = header->prev;
1703     }
1704     pthread_mutex_unlock(&memmut);
1705 #endif
1706
1707     dbgprintf("GlobalSize(0x%x)\n", amem);
1708     return size;
1709 }
1710
1711 static int WINAPI expLoadIconA( long hinstance, char *name )
1712 {
1713  dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
1714  return 1;
1715 }
1716
1717 static int WINAPI expLoadStringA(long instance, long  id, void* buf, long size)
1718 {
1719     int result=LoadStringA(instance, id, buf, size);
1720     //    if(buf)
1721     dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
1722               instance, id, buf, size, result, buf);
1723     //    else
1724     //    dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
1725     //  instance, id, buf, size, result);
1726     return result;
1727 }
1728
1729 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
1730 {
1731 #warning FIXME
1732     int i;
1733     int result;
1734     if(s2==0)
1735         result=1;
1736     else
1737     {
1738         if(siz1>siz2/2)siz1=siz2/2;
1739         for(i=1; i<=siz1; i++)
1740         {
1741             *s2=*s1;
1742             if(!*s1)break;
1743             s2++;
1744             s1++;
1745         }
1746         result=i;
1747     }
1748     if(s1)
1749         dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
1750                   "size %d, dest buffer 0x%x, dest size %d) => %d\n",
1751                   v1, v2, s1, s1, siz1, s2, siz2, result);
1752     else
1753         dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
1754                   "size %d, dest buffer 0x%x, dest size %d) =>\n",
1755                   v1, v2, siz1, s2, siz2, result);
1756     return result;
1757 }
1758 static void wch_print(const short* str)
1759 {
1760     dbgprintf("  src: ");
1761     while(*str)dbgprintf("%c", *str++);
1762     dbgprintf("\n");
1763 }
1764 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
1765                                           char* s2, int siz2, char* c3, int* siz3)
1766 {
1767     int result;
1768     dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
1769               "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
1770     result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
1771     dbgprintf("=> %d\n", result);
1772     //if(s1)wch_print(s1);
1773     if(s2)dbgprintf("  dest: %s\n", s2);
1774     return result;
1775 }
1776 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
1777 {
1778     dbgprintf("GetVersionExA(0x%x) => 1\n");
1779     c->dwOSVersionInfoSize=sizeof(*c);
1780     c->dwMajorVersion=4;
1781     c->dwMinorVersion=0;
1782     c->dwBuildNumber=0x4000457;
1783 #if 1
1784     // leave it here for testing win9x-only codecs
1785     c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
1786     strcpy(c->szCSDVersion, " B");
1787 #else
1788     c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
1789     strcpy(c->szCSDVersion, "Service Pack 3");
1790 #endif
1791     dbgprintf("  Major version: 4\n  Minor version: 0\n  Build number: 0x4000457\n"
1792               "  Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 3'\n");
1793     return 1;
1794 }
1795 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
1796                                          long max_count, char* name)
1797 {
1798     pthread_mutex_t *pm;
1799     pthread_cond_t  *pc;
1800     mutex_list* pp;
1801     /*
1802      printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
1803      pp=mlist;
1804      while(pp)
1805      {
1806      printf("%p => ", pp);
1807      pp=pp->prev;
1808      }
1809      printf("0\n");
1810      */
1811     if(mlist!=NULL)
1812     {
1813         mutex_list* pp=mlist;
1814         if(name!=NULL)
1815             do
1816         {
1817             if((strcmp(pp->name, name)==0) && (pp->type==1))
1818             {
1819                 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1820                           v1, init_count, max_count, name, name, mlist);
1821                 return (HANDLE)mlist;
1822             }
1823         }while((pp=pp->prev) != NULL);
1824     }
1825     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
1826     pthread_mutex_init(pm, NULL);
1827     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
1828     pthread_cond_init(pc, NULL);
1829     if(mlist==NULL)
1830     {
1831         mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1832         mlist->next=mlist->prev=NULL;
1833     }
1834     else
1835     {
1836         mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
1837         mlist->next->prev=mlist;
1838         mlist->next->next=NULL;
1839         mlist=mlist->next;
1840         //      printf("new semaphore %p\n", mlist);
1841     }
1842     mlist->type=1; /* Type Semaphore */
1843     mlist->pm=pm;
1844     mlist->pc=pc;
1845     mlist->state=0;
1846     mlist->reset=0;
1847     mlist->semaphore=init_count;
1848     if(name!=NULL)
1849         strncpy(mlist->name, name, 64);
1850     else
1851         mlist->name[0]=0;
1852     if(pm==NULL)
1853         dbgprintf("ERROR::: CreateSemaphoreA failure\n");
1854     if(name)
1855         dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
1856                   v1, init_count, max_count, name, name, mlist);
1857     else
1858         dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
1859                   v1, init_count, max_count, mlist);
1860     return (HANDLE)mlist;
1861 }
1862
1863 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
1864 {
1865     // The state of a semaphore object is signaled when its count
1866     // is greater than zero and nonsignaled when its count is equal to zero
1867     // Each time a waiting thread is released because of the semaphore's signaled
1868     // state, the count of the semaphore is decreased by one.
1869     mutex_list *ml = (mutex_list *)hsem;
1870
1871     pthread_mutex_lock(ml->pm);
1872     if (prev_count != 0) *prev_count = ml->semaphore;
1873     if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
1874     ml->semaphore += increment;
1875     pthread_mutex_unlock(ml->pm);
1876     dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
1877               hsem, increment, prev_count);
1878     return 1;
1879 }
1880
1881
1882 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
1883 {
1884     long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
1885     dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
1886               key, subkey, reserved, access, newkey, result);
1887     if(newkey)dbgprintf("  New key: 0x%x\n", *newkey);
1888     return result;
1889 }
1890 static long WINAPI expRegCloseKey(long key)
1891 {
1892     long result=RegCloseKey(key);
1893     dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
1894     return result;
1895 }
1896 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
1897 {
1898     long result=RegQueryValueExA(key, value, reserved, type, data, count);
1899     dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
1900               " => 0x%x\n", key, value, reserved, data, count, result);
1901     if(data && count)dbgprintf("  read %d bytes: '%s'\n", *count, data);
1902     return result;
1903 }
1904
1905 //from wine source dlls/advapi32/registry.c
1906 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
1907 {
1908     dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
1909     return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
1910                             KEY_ALL_ACCESS , NULL, retkey, NULL );
1911 }
1912
1913 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
1914                                       void* classs, long options, long security,
1915                                       void* sec_attr, int* newkey, int* status)
1916 {
1917     long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
1918     dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
1919               " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
1920               key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
1921     if(!result && newkey) dbgprintf("  New key: 0x%x\n", *newkey);
1922     if(!result && status) dbgprintf("  New key status: 0x%x\n", *status);
1923     return result;
1924 }
1925 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
1926 {
1927     long result=RegSetValueExA(key, name, v1, v2, data, size);
1928     dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
1929               key, name, v1, v2, data, *(int*)data, data, size, result);
1930     return result;
1931 }
1932
1933 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
1934 {
1935     long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
1936     dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
1937               hKey, lpSubKey, phkResult, result);
1938     if(!result && phkResult) dbgprintf("  New key: 0x%x\n", *phkResult);
1939     return result;
1940 }
1941
1942 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1943                                      LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
1944 {
1945     return RegEnumValueA(hkey, index, value, val_count,
1946                          reserved, type, data, count);
1947 }
1948
1949 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
1950                                      LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
1951                                      LPFILETIME lpftLastWriteTime)
1952 {
1953     return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
1954                          lpcbClass, lpftLastWriteTime);
1955 }
1956
1957 static long WINAPI expQueryPerformanceCounter(long long* z)
1958 {
1959     longcount(z);
1960     dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
1961     return 1;
1962 }
1963
1964 /*
1965  * dummy function RegQueryInfoKeyA(), required by vss codecs
1966  */
1967 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
1968                                          LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
1969                                          LPDWORD values, LPDWORD max_value, LPDWORD max_data,
1970                                          LPDWORD security, FILETIME *modif )
1971 {
1972     return ERROR_SUCCESS;
1973 }
1974
1975 /*
1976  * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
1977  */
1978 static double linux_cpuinfo_freq()
1979 {
1980     double freq=-1;
1981     FILE *f;
1982     char line[200];
1983     char *s,*value;
1984
1985     f = fopen ("/proc/cpuinfo", "r");
1986     if (f != NULL) {
1987         while (fgets(line,sizeof(line),f)!=NULL) {
1988             /* NOTE: the ':' is the only character we can rely on */
1989             if (!(value = strchr(line,':')))
1990                 continue;
1991             /* terminate the valuename */
1992             *value++ = '\0';
1993             /* skip any leading spaces */
1994             while (*value==' ') value++;
1995             if ((s=strchr(value,'\n')))
1996                 *s='\0';
1997
1998             if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
1999                 && sscanf(value, "%lf", &freq) == 1) {
2000                 freq*=1000;
2001                 break;
2002             }
2003         }
2004         fclose(f);
2005     }
2006     return freq;
2007 }
2008
2009
2010 static double solaris_kstat_freq()
2011 {
2012 #if     defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
2013     /*
2014      * try to extract the CPU speed from the solaris kernel's kstat data
2015      */
2016     kstat_ctl_t   *kc;
2017     kstat_t       *ksp;
2018     kstat_named_t *kdata;
2019     int            mhz = 0;
2020
2021     kc = kstat_open();
2022     if (kc != NULL)
2023     {
2024         ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
2025
2026         /* kstat found and name/value pairs? */
2027         if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
2028         {
2029             /* read the kstat data from the kernel */
2030             if (kstat_read(kc, ksp, NULL) != -1)
2031             {
2032                 /*
2033                  * lookup desired "clock_MHz" entry, check the expected
2034                  * data type
2035                  */
2036                 kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
2037                 if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
2038                     mhz = kdata->value.i32;
2039             }
2040         }
2041         kstat_close(kc);
2042     }
2043
2044     if (mhz > 0)
2045         return mhz * 1000.;
2046 #endif  /* HAVE_LIBKSTAT */
2047     return -1;          // kstat stuff is not available, CPU freq is unknown
2048 }
2049
2050 /*
2051  * Measure CPU freq using the pentium's time stamp counter register (TSC)
2052  */
2053 static double tsc_freq()
2054 {
2055     static double ofreq=0.0;
2056     int i;
2057     int x,y;
2058     i=time(NULL);
2059     if (ofreq != 0.0) return ofreq;
2060     while(i==time(NULL));
2061     x=localcount();
2062     i++;
2063     while(i==time(NULL));
2064     y=localcount();
2065     ofreq = (double)(y-x)/1000.;
2066     return ofreq;
2067 }
2068
2069 static double CPU_Freq()
2070 {
2071     double freq;
2072
2073     if ((freq = linux_cpuinfo_freq()) > 0)
2074         return freq;
2075
2076     if ((freq = solaris_kstat_freq()) > 0)
2077         return freq;
2078
2079     return tsc_freq();
2080 }
2081
2082 static long WINAPI expQueryPerformanceFrequency(long long* z)
2083 {
2084     *z=(long long)CPU_Freq();
2085     dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
2086     return 1;
2087 }
2088 static long WINAPI exptimeGetTime()
2089 {
2090     struct timeval t;
2091     long result;
2092     gettimeofday(&t, 0);
2093     result=1000*t.tv_sec+t.tv_usec/1000;
2094     dbgprintf("timeGetTime() => %d\n", result);
2095     return result;
2096 }
2097 static void* WINAPI expLocalHandle(void* v)
2098 {
2099     dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
2100     return v;
2101 }
2102
2103 static void* WINAPI expGlobalHandle(void* v)
2104 {
2105     dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
2106     return v;
2107 }
2108 static int WINAPI expGlobalUnlock(void* v)
2109 {
2110     dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
2111     return 1;
2112 }
2113 static void* WINAPI expGlobalFree(void* v)
2114 {
2115     dbgprintf("GlobalFree(0x%x) => 0\n", v);
2116     my_release(v);
2117     //free(v);
2118     return 0;
2119 }
2120
2121 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
2122 {
2123     void* result=my_realloc(v, size);
2124     //void* result=realloc(v, size);
2125     dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
2126     return result;
2127 }
2128
2129 static int WINAPI expLocalUnlock(void* v)
2130 {
2131     dbgprintf("LocalUnlock(0x%x) => 1\n", v);
2132     return 1;
2133 }
2134 //
2135 static void* WINAPI expLocalFree(void* v)
2136 {
2137     dbgprintf("LocalFree(0x%x) => 0\n", v);
2138     my_release(v);
2139     return 0;
2140 }
2141 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
2142 {
2143     HRSRC result;
2144
2145     result=FindResourceA(module, name, type);
2146     dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
2147         module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
2148     return result;
2149 }
2150
2151 extern HRSRC WINAPI LoadResource(HMODULE, HRSRC);
2152 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
2153 {
2154     HGLOBAL result=LoadResource(module, res);
2155     dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
2156     return result;
2157 }
2158 static void* WINAPI expLockResource(long res)
2159 {
2160     void* result=LockResource(res);
2161     dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
2162     return result;
2163 }
2164 static int WINAPI expFreeResource(long res)
2165 {
2166     int result=FreeResource(res);
2167     dbgprintf("FreeResource(0x%x) => %d\n", res, result);
2168     return result;
2169 }
2170 //bool fun(HANDLE)
2171 //!0 on success
2172 static int WINAPI expCloseHandle(long v1)
2173 {
2174     dbgprintf("CloseHandle(0x%x) => 1\n", v1);
2175     /* do not close stdin,stdout and stderr */
2176     if (v1 > 2)
2177         if (!close(v1))
2178             return 0;
2179     return 1;
2180 }
2181
2182 static const char* WINAPI expGetCommandLineA()
2183 {
2184     dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
2185     return "c:\\aviplay.exe";
2186 }
2187 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
2188 static LPWSTR WINAPI expGetEnvironmentStringsW()
2189 {
2190     dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
2191     return 0;
2192 }
2193 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
2194 {
2195     void* result=memset(p,0,len);
2196     dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
2197     return result;
2198 }
2199 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
2200 {
2201     void* result=memmove(dst,src,len);
2202     dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
2203     return result;
2204 }
2205
2206 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
2207 {
2208     void* result=memset(p,ch,len);
2209     dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
2210     return result;
2211 }
2212 static int WINAPI expFreeEnvironmentStringsW(short* strings)
2213 {
2214     dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
2215     return 1;
2216 }
2217 static int WINAPI expFreeEnvironmentStringsA(char* strings)
2218 {
2219     dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
2220     return 1;
2221 }
2222
2223 static const char ch_envs[]=
2224 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
2225 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
2226 static LPCSTR WINAPI expGetEnvironmentStrings()
2227 {
2228     dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
2229     return (LPCSTR)ch_envs;
2230     // dbgprintf("GetEnvironmentStrings() => 0\n");
2231     // return 0;
2232 }
2233
2234 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
2235 {
2236     int i;
2237     dbgprintf("GetStartupInfoA(0x%x) => 1\n");
2238     memset(s, 0, sizeof(*s));
2239     s->cb=sizeof(*s);
2240     // s->lpReserved="Reserved";
2241     // s->lpDesktop="Desktop";
2242     // s->lpTitle="Title";
2243     // s->dwX=s->dwY=0;
2244     // s->dwXSize=s->dwYSize=200;
2245     s->dwFlags=s->wShowWindow=1;
2246     // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
2247     dbgprintf("  cb=%d\n", s->cb);
2248     dbgprintf("  lpReserved='%s'\n", s->lpReserved);
2249     dbgprintf("  lpDesktop='%s'\n", s->lpDesktop);
2250     dbgprintf("  lpTitle='%s'\n", s->lpTitle);
2251     dbgprintf("  dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
2252               s->dwX, s->dwY, s->dwXSize, s->dwYSize);
2253     dbgprintf("  dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
2254               s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
2255     dbgprintf("  dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
2256               s->dwFlags, s->wShowWindow, s->cbReserved2);
2257     dbgprintf("  lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
2258               s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
2259     return 1;
2260 }
2261
2262 static int WINAPI expGetStdHandle(int z)
2263 {
2264     dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
2265     return z+0x1234;
2266 }
2267
2268 #ifdef QTX
2269 #define FILE_HANDLE_quicktimeqts        ((HANDLE)0x444)
2270 #define FILE_HANDLE_quicktimeqtx        ((HANDLE)0x445)
2271 #endif
2272
2273 static int WINAPI expGetFileType(int handle)
2274 {
2275     dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
2276     return 0x3;
2277 }
2278 #ifdef QTX
2279 static int WINAPI expGetFileAttributesA(char *filename)
2280 {
2281     dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
2282     if (strstr(filename, "QuickTime.qts"))
2283         return FILE_ATTRIBUTE_SYSTEM;
2284     return FILE_ATTRIBUTE_NORMAL;
2285 }
2286 #endif
2287 static int WINAPI expSetHandleCount(int count)
2288 {
2289     dbgprintf("SetHandleCount(0x%x) => 1\n", count);
2290     return 1;
2291 }
2292 static int WINAPI expGetACP(void)
2293 {
2294     dbgprintf("GetACP() => 0\n");
2295     return 0;
2296 }
2297 extern WINE_MODREF *MODULE32_LookupHMODULE(HMODULE m);
2298 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
2299 {
2300     WINE_MODREF *mr;
2301     int result;
2302     //printf("File name of module %X (%s) requested\n", module, s);
2303
2304     if (module == 0 && len >= 12)
2305     {
2306         /* return caller program name */
2307         strcpy(s, "aviplay.dll");
2308         result=1;
2309     }
2310     else if(s==0)
2311         result=0;
2312     else
2313         if(len<35)
2314             result=0;
2315         else
2316         {
2317             result=1;
2318             strcpy(s, "c:\\windows\\system\\");
2319             mr=MODULE32_LookupHMODULE(module);
2320             if(mr==0)//oops
2321                 strcat(s, "aviplay.dll");
2322             else
2323                 if(strrchr(mr->filename, '/')==NULL)
2324                     strcat(s, mr->filename);
2325                 else
2326                     strcat(s, strrchr(mr->filename, '/')+1);
2327         }
2328     if(!s)
2329         dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
2330                   module, s, len, result);
2331     else
2332         dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
2333                   module, s, len, result, s);
2334     return result;
2335 }
2336
2337 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
2338 {
2339     dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
2340     return 1;//unsupported and probably won't ever be supported
2341 }
2342
2343 static int WINAPI expLoadLibraryA(char* name)
2344 {
2345     int result = 0;
2346     char* lastbc;
2347     int i;
2348     if (!name)
2349         return -1;
2350     // we skip to the last backslash
2351     // this is effectively eliminating weird characters in
2352     // the text output windows
2353
2354     lastbc = strrchr(name, '\\');
2355     if (lastbc)
2356     {
2357         int i;
2358         lastbc++;
2359         for (i = 0; 1 ;i++)
2360         {
2361             name[i] = *lastbc++;
2362             if (!name[i])
2363                 break;
2364         }
2365     }
2366     if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
2367     if(strncmp(name, ".\\", 2)==0) name += 2;
2368
2369     dbgprintf("Entering LoadLibraryA(%s)\n", name);
2370
2371     // PIMJ and VIVO audio are loading  kernel32.dll
2372     if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
2373         return MODULE_HANDLE_kernel32;
2374 //      return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
2375                               /* exported -> do not return failed! */
2376
2377     if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
2378 //      return MODULE_HANDLE_kernel32;
2379         return MODULE_HANDLE_user32;
2380
2381 #ifdef QTX
2382     if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
2383         return MODULE_HANDLE_wininet;
2384     if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
2385         return MODULE_HANDLE_ddraw;
2386     if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
2387         return MODULE_HANDLE_advapi32;
2388 #endif
2389
2390     if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
2391         return MODULE_HANDLE_comdlg32;
2392     if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
2393         return MODULE_HANDLE_msvcrt;
2394     if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
2395         return MODULE_HANDLE_ole32;
2396     if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
2397         return MODULE_HANDLE_winmm;
2398
2399     result=LoadLibraryA(name);
2400     dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
2401
2402     return result;
2403 }
2404
2405 static int WINAPI expFreeLibrary(int module)
2406 {
2407 #ifdef QTX
2408     int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
2409 #else
2410     int result=FreeLibrary(module);
2411 #endif
2412     dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
2413     return result;
2414 }
2415
2416 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
2417 {
2418     void* result;
2419     switch(mod){
2420     case MODULE_HANDLE_kernel32:
2421         result=LookupExternalByName("kernel32.dll", name); break;
2422     case MODULE_HANDLE_user32:
2423         result=LookupExternalByName("user32.dll", name); break;
2424 #ifdef QTX
2425     case MODULE_HANDLE_wininet:
2426         result=LookupExternalByName("wininet.dll", name); break;
2427     case MODULE_HANDLE_ddraw:
2428         result=LookupExternalByName("ddraw.dll", name); break;
2429     case MODULE_HANDLE_advapi32:
2430         result=LookupExternalByName("advapi32.dll", name); break;
2431 #endif
2432     case MODULE_HANDLE_comdlg32:
2433         result=LookupExternalByName("comdlg32.dll", name); break;
2434     case MODULE_HANDLE_msvcrt:
2435         result=LookupExternalByName("msvcrt.dll", name); break;
2436     case MODULE_HANDLE_ole32:
2437         result=LookupExternalByName("ole32.dll", name); break;
2438     case MODULE_HANDLE_winmm:
2439         result=LookupExternalByName("winmm.dll", name); break;
2440     default:
2441         result=GetProcAddress(mod, name);
2442     }
2443     dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
2444     return result;
2445 }
2446
2447 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
2448                                          long flProtect, long dwMaxHigh,
2449                                          long dwMaxLow, const char* name)
2450 {
2451     long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
2452     if(!name)
2453         dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2454                   "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
2455                   hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
2456     else
2457         dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
2458                   "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
2459                   hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
2460     return result;
2461 }
2462
2463 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
2464 {
2465     long result=OpenFileMappingA(hFile, hz, name);
2466     if(!name)
2467         dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
2468                   hFile, hz, result);
2469     else
2470         dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
2471                   hFile, hz, name, name, result);
2472     return result;
2473 }
2474
2475 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
2476                                      DWORD offLow, DWORD size)
2477 {
2478     dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
2479               file,mode,offHigh,offLow,size,(char*)file+offLow);
2480     return (char*)file+offLow;
2481 }
2482
2483 static void* WINAPI expUnmapViewOfFile(void* view)
2484 {
2485     dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
2486     return 0;
2487 }
2488
2489 static void* WINAPI expSleep(int time)
2490 {
2491 #if HAVE_NANOSLEEP
2492     /* solaris doesn't have thread safe usleep */
2493     struct timespec tsp;
2494     tsp.tv_sec  =  time / 1000000;
2495     tsp.tv_nsec = (time % 1000000) * 1000;
2496     nanosleep(&tsp, NULL);
2497 #else
2498     usleep(time);
2499 #endif
2500     dbgprintf("Sleep(%d) => 0\n", time);
2501     return 0;
2502 }
2503
2504 // why does IV32 codec want to call this? I don't know ...
2505 static int WINAPI expCreateCompatibleDC(int hdc)
2506 {
2507     int dc = 0;//0x81;
2508     //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
2509     dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
2510     return dc;
2511 }
2512
2513 static int WINAPI expGetDeviceCaps(int hdc, int unk)
2514 {
2515     dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
2516 #ifdef QTX
2517     #define BITSPIXEL 12
2518     #define PLANES    14
2519     if (unk == BITSPIXEL)
2520         return 24;
2521     if (unk == PLANES)
2522         return 1;
2523 #endif
2524     return 1;
2525 }
2526
2527 static WIN_BOOL WINAPI expDeleteDC(int hdc)
2528 {
2529     dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
2530     if (hdc == 0x81)
2531         return 1;
2532     return 0;
2533 }
2534
2535 static WIN_BOOL WINAPI expDeleteObject(int hdc)
2536 {
2537     dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
2538     /* FIXME - implement code here */
2539     return 1;
2540 }
2541
2542 /* btvvc32.drv wants this one */
2543 static void* WINAPI expGetWindowDC(int hdc)
2544 {
2545     dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
2546     return 0;
2547 }
2548
2549 #ifdef QTX
2550 static int WINAPI expGetWindowRect(HWND win, RECT *r)
2551 {
2552     dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
2553     /* (win == 0) => desktop */
2554     r->right = PSEUDO_SCREEN_WIDTH;
2555     r->left = 0;
2556     r->bottom = PSEUDO_SCREEN_HEIGHT;
2557     r->top = 0;
2558     return 1;
2559 }
2560
2561 static int WINAPI expMonitorFromWindow(HWND win, int flags)
2562 {
2563     dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
2564     return 0;
2565 }
2566
2567 static int WINAPI expMonitorFromRect(RECT *r, int flags)
2568 {
2569     dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
2570     return 0;
2571 }
2572
2573 static int WINAPI expMonitorFromPoint(void *p, int flags)
2574 {
2575     dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
2576     return 0;
2577 }
2578
2579 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r, 
2580     int WINAPI (*callback_proc)(), void *callback_param)
2581 {
2582     dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
2583         dc, r, callback_proc, callback_param);
2584     return callback_proc(0, dc, r, callback_param);
2585 }
2586
2587 #if 0
2588 typedef struct tagMONITORINFO {
2589     DWORD  cbSize; 
2590     RECT   rcMonitor; 
2591     RECT   rcWork; 
2592     DWORD  dwFlags; 
2593 } MONITORINFO, *LPMONITORINFO; 
2594 #endif
2595
2596 #define CCHDEVICENAME 8
2597 typedef struct tagMONITORINFOEX {  
2598     DWORD  cbSize; 
2599     RECT   rcMonitor; 
2600     RECT   rcWork; 
2601     DWORD  dwFlags; 
2602     TCHAR  szDevice[CCHDEVICENAME];
2603 } MONITORINFOEX, *LPMONITORINFOEX; 
2604
2605 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
2606 {
2607     dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
2608     
2609     lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
2610     lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
2611     lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
2612     lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
2613
2614     lpmi->dwFlags = 1; /* primary monitor */
2615
2616     if (lpmi->cbSize == sizeof(MONITORINFOEX))
2617     {
2618         LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
2619         dbgprintf("MONITORINFOEX!\n");
2620         strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
2621     }
2622     
2623     return 1;
2624 }
2625
2626 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
2627         void *dispdev, int flags)
2628 {
2629     dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
2630         device, device, devnum, dispdev, flags);
2631     return 1;
2632 }
2633
2634 static int WINAPI expIsWindowVisible(HWND win)
2635 {
2636     dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
2637     return 1;
2638 }
2639
2640 static HWND WINAPI expGetActiveWindow(void)
2641 {
2642     dbgprintf("GetActiveWindow() => 0\n");
2643     return (HWND)0;
2644 }
2645
2646 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
2647 {
2648     strncat(classname, "QuickTime", maxcount);
2649     dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
2650         win, classname, maxcount, strlen(classname));
2651     return strlen(classname);
2652 }
2653
2654 #define LPWNDCLASS void *
2655 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
2656 {
2657     dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
2658         classname, classname, wndclass);
2659     return 1;
2660 }
2661
2662 static int WINAPI expGetWindowLongA(HWND win, int index)
2663 {
2664     dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
2665     return 1;
2666 }
2667
2668 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
2669 {
2670     dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
2671     return objsize;
2672 }
2673
2674 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
2675 {
2676     dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
2677     return 0;
2678 }
2679
2680 static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
2681 {
2682     int i, i2;
2683     dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
2684     i = callback_func(0, callback_param);
2685     i2 = callback_func(1, callback_param);
2686     return i && i2;
2687 }
2688
2689 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
2690 {
2691     int tid = pthread_self();
2692     dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
2693         win, pid_data, tid);
2694     if (pid_data)
2695         *(int*)pid_data = tid;
2696     return tid;
2697 }
2698
2699 //HWND      WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
2700 //                                INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
2701
2702 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
2703     const char *winname, int style, int x, int y, int w, int h,
2704     HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
2705 {
2706     printf("CreateWindowEx() called\n");
2707     dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
2708         exstyle, classname, classname, winname, winname, style, x, y, w, h,
2709         parent, menu, inst, param);
2710     printf("CreateWindowEx() called okey\n");
2711     return 1;
2712 }
2713
2714 static int WINAPI expwaveOutGetNumDevs(void)
2715 {
2716     dbgprintf("waveOutGetNumDevs() => 0\n");
2717     return 0;
2718 }
2719 #endif
2720
2721 /*
2722  * Returns the number of milliseconds, modulo 2^32, since the start
2723  * of the wineserver.
2724  */
2725 static int WINAPI expGetTickCount(void)
2726 {
2727     static int tcstart = 0;
2728     struct timeval t;
2729     int tc;
2730     gettimeofday( &t, NULL );
2731     tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
2732     if (tcstart == 0)
2733     {
2734         tcstart = 0;
2735         tc = 0;
2736     }
2737     dbgprintf("GetTickCount() => %d\n", tc);
2738     return tc;
2739 }
2740
2741 static int WINAPI expCreateFontA(void)
2742 {
2743     dbgprintf("CreateFontA() => 0x0\n");
2744     return 1;
2745 }
2746
2747 /* tried to get pvmjpg work in a different way - no success */
2748 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
2749                                LPRECT lpRect, unsigned int uFormat)
2750 {
2751     dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
2752     return 8;
2753 }
2754
2755 static int WINAPI expGetPrivateProfileIntA(const char* appname,
2756                                            const char* keyname,
2757                                            int default_value,
2758                                            const char* filename)
2759 {
2760     int size=255;
2761     char buffer[256];
2762     char* fullname;
2763     int result;
2764
2765     buffer[255]=0;
2766     if(!(appname && keyname && filename) )
2767     {
2768         dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
2769         return default_value;
2770     }
2771     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2772     strcpy(fullname, "Software\\IniFileMapping\\");
2773     strcat(fullname, appname);
2774     strcat(fullname, "\\");
2775     strcat(fullname, keyname);
2776     strcat(fullname, "\\");
2777     strcat(fullname, filename);
2778     result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
2779     if((size>=0)&&(size<256))
2780         buffer[size]=0;
2781     //    printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
2782     free(fullname);
2783     if(result)
2784         result=default_value;
2785     else
2786         result=atoi(buffer);
2787     dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
2788     return result;
2789 }
2790 static int WINAPI expGetProfileIntA(const char* appname,
2791                                     const char* keyname,
2792                                     int default_value)
2793 {
2794     dbgprintf("GetProfileIntA -> ");
2795     return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
2796 }
2797
2798 static int WINAPI expGetPrivateProfileStringA(const char* appname,
2799                                               const char* keyname,
2800                                               const char* def_val,
2801                                               char* dest, unsigned int len,
2802                                               const char* filename)
2803 {
2804     int result;
2805     int size;
2806     char* fullname;
2807     dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
2808     if(!(appname && keyname && filename) ) return 0;
2809     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2810     strcpy(fullname, "Software\\IniFileMapping\\");
2811     strcat(fullname, appname);
2812     strcat(fullname, "\\");
2813     strcat(fullname, keyname);
2814     strcat(fullname, "\\");
2815     strcat(fullname, filename);
2816     size=len;
2817     result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
2818     free(fullname);
2819     if(result)
2820     {
2821         strncpy(dest, def_val, size);
2822         if (strlen(def_val)< size) size = strlen(def_val);
2823     }
2824     dbgprintf(" => %d ( '%s' )\n", size, dest);
2825     return size;
2826 }
2827 static int WINAPI expWritePrivateProfileStringA(const char* appname,
2828                                                 const char* keyname,
2829                                                 const char* string,
2830                                                 const char* filename)
2831 {
2832     int size=256;
2833     char* fullname;
2834     dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
2835     if(!(appname && keyname && filename) )
2836     {
2837         dbgprintf(" => -1\n");
2838         return -1;
2839     }
2840     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
2841     strcpy(fullname, "Software\\IniFileMapping\\");
2842     strcat(fullname, appname);
2843     strcat(fullname, "\\");
2844     strcat(fullname, keyname);
2845     strcat(fullname, "\\");
2846     strcat(fullname, filename);
2847     RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
2848     //    printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
2849     //    printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
2850     free(fullname);
2851     dbgprintf(" => 0\n");
2852     return 0;
2853 }
2854
2855 unsigned int _GetPrivateProfileIntA(const char* appname, const char* keyname, INT default_value, const char* filename)
2856 {
2857     return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
2858 }
2859 int _GetPrivateProfileStringA(const char* appname, const char* keyname,
2860                               const char* def_val, char* dest, unsigned int len, const char* filename)
2861 {
2862     return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
2863 }
2864 int _WritePrivateProfileStringA(const char* appname, const char* keyname,
2865                                 const char* string, const char* filename)
2866 {
2867     return expWritePrivateProfileStringA(appname, keyname, string, filename);
2868 }
2869
2870
2871
2872 static int WINAPI expDefDriverProc(int _private, int id, int msg, int arg1, int arg2)
2873 {
2874     dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", _private, id, msg, arg1, arg2);
2875     return 0;
2876 }
2877
2878 static int WINAPI expSizeofResource(int v1, int v2)
2879 {
2880     int result=SizeofResource(v1, v2);
2881     dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
2882     return result;
2883 }
2884
2885 static int WINAPI expGetLastError()
2886 {
2887     int result=GetLastError();
2888     dbgprintf("GetLastError() => 0x%x\n", result);
2889     return result;
2890 }
2891
2892 static void WINAPI expSetLastError(int error)
2893 {
2894     dbgprintf("SetLastError(0x%x)\n", error);
2895     SetLastError(error);
2896 }
2897
2898 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
2899 {
2900     int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
2901                         guid->f1, guid->f2, guid->f3,
2902                         (unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
2903                         (unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
2904                         (unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
2905                         (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
2906     dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
2907     return result;
2908 }
2909
2910
2911 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
2912 {
2913     dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
2914     return 0;
2915 }
2916
2917 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
2918 {
2919     int result;
2920     if(string==0)result=1; else result=0;
2921     dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
2922     if(string)wch_print(string);
2923     return result;
2924 }
2925 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
2926 {
2927     return expIsBadStringPtrW((const short*)string, nchars);
2928 }
2929 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
2930 {
2931     long ret;
2932     __asm__ __volatile__
2933         (
2934          "lock; xaddl %0,(%1)"
2935          : "=r" (ret)
2936          : "r" (dest), "0" (incr)
2937          : "memory"
2938         );
2939     return ret;
2940 }
2941
2942 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
2943 {
2944     unsigned long retval = *dest;
2945     if(*dest == comperand)
2946         *dest = exchange;
2947     return retval;
2948 }
2949
2950 static long WINAPI expInterlockedIncrement( long* dest )
2951 {
2952     long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
2953     dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
2954     return result;
2955 }
2956 static long WINAPI expInterlockedDecrement( long* dest )
2957 {
2958     long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
2959     dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
2960     return result;
2961 }
2962
2963 static void WINAPI expOutputDebugStringA( const char* string )
2964 {
2965     dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
2966     fprintf(stderr, "DEBUG: %s\n", string);
2967 }
2968
2969 static int WINAPI expGetDC(int hwnd)
2970 {
2971     dbgprintf("GetDC(0x%x) => 1\n", hwnd);
2972     return 1;
2973 }
2974
2975 static int WINAPI expReleaseDC(int hwnd, int hdc)
2976 {
2977     dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
2978     return 1;
2979 }
2980
2981 static int WINAPI expGetDesktopWindow()
2982 {
2983     dbgprintf("GetDesktopWindow() => 0\n");
2984     return 0;
2985 }
2986
2987 static int cursor[100];
2988
2989 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
2990 {
2991     dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
2992     return (int)&cursor[0];
2993 }
2994 static int WINAPI expSetCursor(void *cursor)
2995 {
2996     dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
2997     return (int)cursor;
2998 }
2999 static int WINAPI expGetCursorPos(void *cursor)
3000 {
3001     dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
3002     return 1;
3003 }
3004 #ifdef QTX
3005 static int show_cursor = 0;
3006 static int WINAPI expShowCursor(int show)
3007 {
3008     dbgprintf("ShowCursor(%d) => %d\n", show, show);
3009     if (show)
3010         show_cursor++;
3011     else
3012         show_cursor--;
3013     return show_cursor;
3014 }
3015 #endif
3016 static int WINAPI expRegisterWindowMessageA(char *message)
3017 {
3018     dbgprintf("RegisterWindowMessageA(%s)\n", message);
3019     return 1;
3020 }
3021 static int WINAPI expGetProcessVersion(int pid)
3022 {
3023     dbgprintf("GetProcessVersion(%d)\n", pid);
3024     return 1;
3025 }
3026 static int WINAPI expGetCurrentThread(void)
3027 {
3028 #warning FIXME!
3029     dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
3030     return 0xcfcf9898;
3031 }
3032 static int WINAPI expGetOEMCP(void)
3033 {
3034     dbgprintf("GetOEMCP()\n");
3035     return 1;
3036 }
3037 static int WINAPI expGetCPInfo(int cp,void *info)
3038 {
3039     dbgprintf("GetCPInfo()\n");
3040     return 0;
3041 }
3042 #ifdef QTX
3043 #define SM_CXSCREEN             0
3044 #define SM_CYSCREEN             1
3045 #define SM_XVIRTUALSCREEN       76
3046 #define SM_YVIRTUALSCREEN       77
3047 #define SM_CXVIRTUALSCREEN      78
3048 #define SM_CYVIRTUALSCREEN      79
3049 #define SM_CMONITORS            80
3050 #endif
3051 static int WINAPI expGetSystemMetrics(int index)
3052 {
3053     dbgprintf("GetSystemMetrics(%d)\n", index);
3054 #ifdef QTX
3055     switch(index)
3056     {
3057         case SM_XVIRTUALSCREEN:
3058         case SM_YVIRTUALSCREEN:
3059             return 0;
3060         case SM_CXSCREEN:
3061         case SM_CXVIRTUALSCREEN:
3062             return PSEUDO_SCREEN_WIDTH;
3063         case SM_CYSCREEN:
3064         case SM_CYVIRTUALSCREEN:
3065             return PSEUDO_SCREEN_HEIGHT;
3066         case SM_CMONITORS:
3067             return 1;
3068     }
3069 #endif
3070     return 1;
3071 }
3072 static int WINAPI expGetSysColor(int index)
3073 {
3074     dbgprintf("GetSysColor(%d) => 1\n", index);
3075     return 1;
3076 }
3077 static int WINAPI expGetSysColorBrush(int index)
3078 {
3079     dbgprintf("GetSysColorBrush(%d)\n", index);
3080     return 1;
3081 }
3082
3083
3084
3085 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
3086 {
3087     dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
3088               hdc, iStartIndex, nEntries, lppe);
3089     return 0;
3090 }
3091
3092 /*
3093  typedef struct _TIME_ZONE_INFORMATION {
3094  long Bias;
3095  char StandardName[32];
3096  SYSTEMTIME StandardDate;
3097  long StandardBias;
3098  char DaylightName[32];
3099  SYSTEMTIME DaylightDate;
3100  long DaylightBias;
3101  } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
3102  */
3103
3104 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
3105 {
3106     const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
3107     'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
3108     const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
3109     'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
3110     dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
3111     memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
3112     lpTimeZoneInformation->Bias=360;//GMT-6
3113     memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
3114     lpTimeZoneInformation->StandardDate.wMonth=10;
3115     lpTimeZoneInformation->StandardDate.wDay=5;
3116     lpTimeZoneInformation->StandardDate.wHour=2;
3117     lpTimeZoneInformation->StandardBias=0;
3118     memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
3119     lpTimeZoneInformation->DaylightDate.wMonth=4;
3120     lpTimeZoneInformation->DaylightDate.wDay=1;
3121     lpTimeZoneInformation->DaylightDate.wHour=2;
3122     lpTimeZoneInformation->DaylightBias=-60;
3123     return TIME_ZONE_ID_STANDARD;
3124 }
3125
3126 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
3127 {
3128     time_t local_time;
3129     struct tm *local_tm;
3130     struct timeval tv;
3131
3132     dbgprintf("GetLocalTime(0x%x)\n");
3133     gettimeofday(&tv, NULL);
3134     local_time=tv.tv_sec;
3135     local_tm=localtime(&local_time);
3136
3137     systime->wYear = local_tm->tm_year + 1900;
3138     systime->wMonth = local_tm->tm_mon + 1;
3139     systime->wDayOfWeek = local_tm->tm_wday;
3140     systime->wDay = local_tm->tm_mday;
3141     systime->wHour = local_tm->tm_hour;
3142     systime->wMinute = local_tm->tm_min;
3143     systime->wSecond = local_tm->tm_sec;
3144     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3145     dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
3146               "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
3147               "  Milliseconds: %d\n",
3148               systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3149               systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3150 }
3151
3152 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
3153 {
3154     time_t local_time;
3155     struct tm *local_tm;
3156     struct timeval tv;
3157
3158     dbgprintf("GetSystemTime(0x%x)\n", systime);
3159     gettimeofday(&tv, NULL);
3160     local_time=tv.tv_sec;
3161     local_tm=gmtime(&local_time);
3162
3163     systime->wYear = local_tm->tm_year + 1900;
3164     systime->wMonth = local_tm->tm_mon + 1;
3165     systime->wDayOfWeek = local_tm->tm_wday;
3166     systime->wDay = local_tm->tm_mday;
3167     systime->wHour = local_tm->tm_hour;
3168     systime->wMinute = local_tm->tm_min;
3169     systime->wSecond = local_tm->tm_sec;
3170     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
3171     dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
3172               "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
3173               "  Milliseconds: %d\n",
3174               systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
3175               systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
3176     return 0;
3177 }
3178
3179 #define SECS_1601_TO_1970  ((369 * 365 + 89) * 86400ULL)
3180 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
3181 {
3182     struct tm *local_tm;
3183     struct timeval tv;
3184     unsigned long long secs;
3185
3186     dbgprintf("GetSystemTime(0x%x)\n", systime);
3187     gettimeofday(&tv, NULL);
3188     secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
3189     secs += tv.tv_usec * 10;
3190     systime->dwLowDateTime = secs & 0xffffffff;
3191     systime->dwHighDateTime = (secs >> 32);
3192 }
3193
3194 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
3195 {
3196     char *p;
3197     //    printf("%s %x %x\n", name, field, size);
3198     if(field)field[0]=0;
3199     /*
3200      p = getenv(name);
3201      if (p) strncpy(field,p,size);
3202      */
3203     if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
3204         strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
3205     dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
3206     return strlen(field);
3207 }
3208
3209 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
3210 {
3211     dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
3212     return 0;
3213 }
3214
3215 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
3216 {
3217     return my_mreq(cb, 0);
3218 }
3219 static void WINAPI expCoTaskMemFree(void* cb)
3220 {
3221     my_release(cb);
3222 }
3223
3224
3225
3226
3227 void* CoTaskMemAlloc(unsigned long cb)
3228 {
3229     return expCoTaskMemAlloc(cb);
3230 }
3231 void CoTaskMemFree(void* cb)
3232 {
3233     expCoTaskMemFree(cb);
3234 }
3235
3236 struct COM_OBJECT_INFO
3237 {
3238     GUID clsid;
3239     long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
3240 };
3241
3242 static struct COM_OBJECT_INFO* com_object_table=0;
3243 static int com_object_size=0;
3244 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3245 {
3246     if(!clsid || !gcs)
3247         return -1;
3248     com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
3249     com_object_table[com_object_size-1].clsid=*clsid;
3250     com_object_table[com_object_size-1].GetClassObject=gcs;
3251     return 0;
3252 }
3253
3254 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
3255 {
3256     int found = 0;
3257     int i = 0;
3258     if(!clsid || !gcs)
3259         return -1;
3260
3261     if (com_object_table == 0)
3262         printf("Warning: UnregisterComClass() called without any registered class\n");
3263     while (i < com_object_size)
3264     {
3265         if (found && i > 0)
3266         {
3267             memcpy(&com_object_table[i - 1].clsid,
3268                    &com_object_table[i].clsid, sizeof(GUID));
3269             com_object_table[i - 1].GetClassObject =
3270                 com_object_table[i].GetClassObject;
3271         }
3272         else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
3273                  && com_object_table[i].GetClassObject == gcs)
3274         {
3275             found++;
3276         }
3277         i++;
3278     }
3279     if (found)
3280     {
3281         if (--com_object_size == 0)
3282         {
3283             free(com_object_table);
3284             com_object_table = 0;
3285         }
3286     }
3287     return 0;
3288 }
3289
3290
3291 const GUID IID_IUnknown =
3292 {
3293     0x00000000, 0x0000, 0x0000,
3294     {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3295 };
3296 const GUID IID_IClassFactory =
3297 {
3298     0x00000001, 0x0000, 0x0000,
3299     {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
3300 };
3301
3302 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3303                                        long dwClsContext, const GUID* riid, void** ppv)
3304 {
3305     int i;
3306     struct COM_OBJECT_INFO* ci=0;
3307     for(i=0; i<com_object_size; i++)
3308         if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
3309             ci=&com_object_table[i];
3310     if(!ci)return REGDB_E_CLASSNOTREG;
3311     // in 'real' world we should mess with IClassFactory here
3312     i=ci->GetClassObject(rclsid, riid, ppv);
3313     return i;
3314 }
3315
3316 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
3317                       long dwClsContext, const GUID* riid, void** ppv)
3318 {
3319     return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
3320 }
3321
3322 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
3323 {
3324     int r = 0;
3325     int w,h;
3326 //trapbug();
3327     if (lprc)
3328     {
3329         w = lprc->right - lprc->left;
3330         h = lprc->bottom - lprc->top;
3331         if (w <= 0 || h <= 0)
3332             r = 1;
3333     }
3334     else
3335         r = 1;
3336
3337     dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
3338     //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
3339 //    return 0; // wmv9?
3340     return r; // TM20
3341 }
3342
3343 static int _adjust_fdiv=0; //what's this? - used to adjust division
3344
3345
3346
3347
3348 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
3349 {
3350     dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
3351     if(len<5)
3352     {
3353         dbgprintf(" => 0\n");
3354         return 0;
3355     }
3356     strcpy(path, "/tmp");
3357     dbgprintf(" => 5 ( '/tmp' )\n");
3358     return 5;
3359 }
3360 /*
3361  FYI:
3362  typedef struct
3363  {
3364  DWORD     dwFileAttributes;
3365  FILETIME  ftCreationTime;
3366  FILETIME  ftLastAccessTime;
3367  FILETIME  ftLastWriteTime;
3368  DWORD     nFileSizeHigh;
3369  DWORD     nFileSizeLow;
3370  DWORD     dwReserved0;
3371  DWORD     dwReserved1;
3372  CHAR      cFileName[260];
3373  CHAR      cAlternateFileName[14];
3374  } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
3375  */
3376
3377 static DIR* qtx_dir=NULL;
3378
3379 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
3380 {
3381 #ifdef QTX
3382     dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
3383     if(h==FILE_HANDLE_quicktimeqtx){
3384         struct dirent* d;
3385         if(!qtx_dir) return 0;
3386         while((d=readdir(qtx_dir))){
3387             char* x=strrchr(d->d_name,'.');
3388             if(!x) continue;
3389             if(strcmp(x,".qtx")) continue;
3390             strcpy(lpfd->cFileName,d->d_name);
3391 //          sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
3392             strcpy(lpfd->cAlternateFileName,"foobar.qtx");
3393             printf("### FindNext: %s\n",lpfd->cFileName);
3394             return 1;
3395         }
3396         closedir(qtx_dir); qtx_dir=NULL;
3397         return 0;
3398     }
3399 #endif
3400     return 0;
3401 }
3402
3403 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
3404 {
3405     dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
3406 //    printf("\n### FindFirstFileA('%s')...\n",s);
3407 #ifdef QTX
3408     if(strstr(s, "quicktime\\*.QTX")){
3409         dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
3410         printf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",def_path);
3411         qtx_dir=opendir(def_path);
3412         if(!qtx_dir) return (HANDLE)-1;
3413         memset(lpfd,0,sizeof(*lpfd));
3414         if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
3415             return FILE_HANDLE_quicktimeqtx;
3416         printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",def_path);
3417         return (HANDLE)-1;
3418     }
3419 #if 0
3420     if(strstr(s, "QuickTime.qts")){
3421         dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
3422 //      if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
3423 //          return (HANDLE)-1;
3424         strcpy(lpfd->cFileName, "QuickTime.qts");
3425         strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
3426         return FILE_HANDLE_quicktimeqts;
3427     }
3428 #endif
3429 #endif
3430     if(strstr(s, "*.vwp")){
3431         // hack for VoxWare codec plugins:
3432         strcpy(lpfd->cFileName, "msms001.vwp");
3433         strcpy(lpfd->cAlternateFileName, "msms001.vwp");
3434         return (HANDLE)0;
3435     }
3436     // return 'file not found'
3437     return (HANDLE)-1;
3438 }
3439
3440 static WIN_BOOL WINAPI expFindClose(HANDLE h)
3441 {
3442     dbgprintf("FindClose(0x%x) => 0\n", h);
3443 #ifdef QTX
3444 //    if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
3445 //      closedir(qtx_dir);
3446 //      qtx_dir=NULL;
3447 //    }
3448 #endif
3449     return 0;
3450 }
3451 static UINT WINAPI expSetErrorMode(UINT i)
3452 {
3453     dbgprintf("SetErrorMode(%d) => 0\n", i);
3454     return 0;
3455 }
3456 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
3457 {
3458     char windir[]="c:\\windows";
3459     int result;
3460     strncpy(s, windir, c);
3461     result=1+((c<strlen(windir))?c:strlen(windir));
3462     dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
3463     return result;
3464 }
3465 #ifdef QTX
3466 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
3467 {
3468     char curdir[]="c:\\";
3469     int result;
3470     strncpy(s, curdir, c);
3471     result=1+((c<strlen(curdir))?c:strlen(curdir));
3472     dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
3473     return result;
3474 }
3475
3476 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
3477 {
3478     dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
3479 #if 0
3480     if (strrchr(pathname, '\\'))
3481         chdir(strcat(strrchr(pathname, '\\')+1, '/'));
3482     else
3483         chdir(pathname);
3484 #endif
3485     return 1;
3486 }
3487
3488 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
3489 {
3490     dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
3491         pathname, pathname, sa);
3492 #if 0
3493     p = strrchr(pathname, '\\')+1;
3494     strcpy(&buf[0], p); /* should be strncpy */
3495     if (!strlen(p))
3496     {
3497         buf[0] = '.';
3498         buf[1] = 0;
3499     }
3500 #if 0    
3501     if (strrchr(pathname, '\\'))
3502         mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
3503     else
3504         mkdir(pathname, 666);
3505 #endif
3506     mkdir(&buf);
3507 #endif
3508     return 1;
3509 }
3510 #endif
3511 static WIN_BOOL  WINAPI expDeleteFileA(LPCSTR s)
3512 {
3513     dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
3514     return 0;
3515 }
3516 static WIN_BOOL  WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
3517 {
3518     dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
3519     return 0;
3520 }
3521
3522 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
3523 {
3524     char mask[16]="/tmp/AP_XXXXXX";
3525     int result;
3526     dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
3527     if(i && i<10)
3528     {
3529         dbgprintf(" => -1\n");
3530         return -1;
3531     }
3532     result=mkstemp(mask);
3533     sprintf(ps, "AP%d", result);
3534     dbgprintf(" => %d\n", strlen(ps));
3535     return strlen(ps);
3536 }
3537 //
3538 // This func might need proper implementation if we want AngelPotion codec.
3539 // They try to open APmpeg4v1.apl with it.
3540 // DLL will close opened file with CloseHandle().
3541 //
3542 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
3543                                     LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
3544 {
3545     dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
3546               i2, p1, i3, i4, i5);
3547     if((!cs1) || (strlen(cs1)<2))return -1;
3548
3549 #ifdef QTX
3550     if(strstr(cs1, "QuickTime.qts"))
3551     {
3552         int result;
3553         char* tmp=(char*)malloc(strlen(def_path)+50);
3554         strcpy(tmp, def_path);
3555         strcat(tmp, "/");
3556         strcat(tmp, "QuickTime.qts");
3557         result=open(tmp, O_RDONLY);
3558         free(tmp);
3559         return result;
3560     }
3561     if(strstr(cs1, ".qtx"))
3562     {
3563         int result;
3564         char* tmp=(char*)malloc(strlen(def_path)+250);
3565         char* x=strrchr(cs1,'\\');
3566         sprintf(tmp,"%s/%s",def_path,x?(x+1):cs1);
3567 //      printf("### Open: %s -> %s\n",cs1,tmp);
3568         result=open(tmp, O_RDONLY);
3569         free(tmp);
3570         return result;
3571     }
3572 #endif
3573
3574     if(strncmp(cs1, "AP", 2) == 0)
3575     {
3576         int result;
3577         char* tmp=(char*)malloc(strlen(def_path)+50);
3578         strcpy(tmp, def_path);
3579         strcat(tmp, "/");
3580         strcat(tmp, "APmpg4v1.apl");
3581         result=open(tmp, O_RDONLY);
3582         free(tmp);
3583         return result;
3584     }
3585     if (strstr(cs1, "vp3"))
3586     {
3587         int r;
3588         int flg = 0;
3589         char* tmp=(char*)malloc(20 + strlen(cs1));
3590         strcpy(tmp, "/tmp/");
3591         strcat(tmp, cs1);
3592         r = 4;
3593         while (tmp[r])
3594         {
3595             if (tmp[r] == ':' || tmp[r] == '\\')
3596                 tmp[r] = '_';
3597             r++;
3598         }
3599         if (GENERIC_READ & i1)
3600             flg |= O_RDONLY;
3601         else if (GENERIC_WRITE & i1)
3602         {
3603             flg |= O_WRONLY;
3604             printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", tmp, r, flg);
3605         }
3606         r=open(tmp, flg);
3607         free(tmp);
3608         return r;
3609     }
3610
3611     // Needed by wnvplay1.dll
3612     if (strstr(cs1, "WINNOV.bmp"))
3613     {
3614         int r;
3615         r=open("/dev/null", 0);
3616         return r;
3617     }
3618
3619 #if 0
3620     /* we need this for some virtualdub filters */
3621     {
3622         int r;
3623         int flg = 0;
3624         if (GENERIC_READ & i1)
3625             flg |= O_RDONLY;
3626         else if (GENERIC_WRITE & i1)
3627         {
3628             flg |= O_WRONLY;
3629             printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", cs1, r, flg);
3630         }
3631         r=open(cs1, flg);
3632         return r;
3633     }
3634 #endif
3635
3636     return atoi(cs1+2);
3637 }
3638 static UINT WINAPI expGetSystemDirectoryA(
3639   char* lpBuffer,  // address of buffer for system directory
3640   UINT uSize        // size of directory buffer
3641 ){
3642     dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
3643     if(!lpBuffer) strcpy(lpBuffer,".");
3644     return 1;
3645 }
3646 /*
3647 static char sysdir[]=".";
3648 static LPCSTR WINAPI expGetSystemDirectoryA()
3649 {
3650     dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
3651     return sysdir;
3652 }
3653 */
3654 static DWORD WINAPI expGetFullPathNameA
3655 (
3656         LPCTSTR lpFileName,
3657         DWORD nBufferLength,
3658         LPTSTR lpBuffer,
3659         LPTSTR lpFilePart
3660 ){
3661     if(!lpFileName) return 0;
3662     dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
3663         lpBuffer, lpFilePart);
3664 #if 0
3665 #ifdef QTX
3666     strcpy(lpFilePart, "Quick123.qts");
3667 #else
3668     strcpy(lpFilePart, lpFileName);
3669 #endif
3670 #else
3671     if (strrchr(lpFileName, '\\'))
3672         lpFilePart = strrchr(lpFileName, '\\');
3673     else
3674         lpFilePart = (LPTSTR)lpFileName;
3675 #endif
3676     strcpy(lpBuffer, lpFileName);
3677 //    strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
3678     return strlen(lpBuffer);
3679 }
3680
3681 static DWORD WINAPI expGetShortPathNameA
3682 (
3683         LPCSTR longpath,
3684         LPSTR shortpath,
3685         DWORD shortlen
3686 ){
3687     if(!longpath) return 0;
3688     dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
3689     strcpy(shortpath,longpath);
3690     return strlen(shortpath);
3691 }
3692
3693 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
3694 {
3695     int result;
3696     dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
3697     result=read(h, pv, size);
3698     if(rd)*rd=result;
3699     if(!result)return 0;
3700     return 1;
3701 }
3702
3703 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
3704 {
3705     int result;
3706     dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
3707     if(h==1234)h=1;
3708     result=write(h, pv, size);
3709     if(wr)*wr=result;
3710     if(!result)return 0;
3711     return 1;
3712 }
3713 static DWORD  WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
3714 {
3715     int wh;
3716     dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, *ext, whence);
3717     //why would DLL want temporary file with >2Gb size?
3718     switch(whence)
3719     {
3720     case FILE_BEGIN:
3721         wh=SEEK_SET;break;
3722     case FILE_END:
3723         wh=SEEK_END;break;
3724     case FILE_CURRENT:
3725         wh=SEEK_CUR;break;
3726     default:
3727         return -1;
3728     }
3729 #ifdef QTX
3730     if (val == 0 && ext != 0)
3731         val = val&(*ext);
3732 #endif
3733     return lseek(h, val, wh);
3734 }
3735
3736 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
3737                                    LPARAM lParam2)
3738 {
3739     dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName,  szDriverName, szSectionName, szSectionName, lParam2);
3740     return -1;
3741 }
3742 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
3743                                   LPARAM lParam2)
3744 {
3745     dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
3746     return -1;
3747 }
3748
3749
3750 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
3751                                                  LPDWORD lpProcessAffinityMask,
3752                                                  LPDWORD lpSystemAffinityMask)
3753 {
3754     dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
3755               hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
3756     if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
3757     if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
3758     return 1;
3759 }
3760
3761 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
3762 {
3763     static const long long max_int=0x7FFFFFFFLL;
3764     static const long long min_int=-0x80000000LL;
3765     long long tmp=(long long)nNumber*(long long)nNumerator;
3766     dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
3767     if(!nDenominator)return 1;
3768     tmp/=nDenominator;
3769     if(tmp<min_int) return 1;
3770     if(tmp>max_int) return 1;
3771     return (int)tmp;
3772 }
3773
3774 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
3775 {
3776     LONG result=strcasecmp(str1, str2);
3777     dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
3778     return result;
3779 }
3780
3781 static LONG WINAPI explstrlenA(const char* str1)
3782 {
3783     LONG result=strlen(str1);
3784     dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
3785     return result;
3786 }
3787
3788 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
3789 {
3790     int result= (int) strcpy(str1, str2);
3791     dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
3792     return result;
3793 }
3794 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
3795 {
3796     int result;
3797     if (strlen(str2)>len)
3798         result = (int) strncpy(str1, str2,len);
3799     else
3800         result = (int) strcpy(str1,str2);
3801     dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
3802     return result;
3803 }
3804 static LONG WINAPI explstrcatA(char* str1, const char* str2)
3805 {
3806     int result= (int) strcat(str1, str2);
3807     dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
3808     return result;
3809 }
3810
3811
3812 static LONG WINAPI expInterlockedExchange(long *dest, long l)
3813 {
3814     long retval = *dest;
3815     *dest = l;
3816     return retval;
3817 }
3818
3819 static void WINAPI expInitCommonControls(void)
3820 {
3821     dbgprintf("InitCommonControls called!\n");
3822     return;
3823 }
3824
3825 #ifdef QTX
3826 /* needed by QuickTime.qts */
3827 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
3828               HWND parent, INT id, HINSTANCE inst,
3829               HWND buddy, INT maxVal, INT minVal, INT curVal)
3830 {
3831     dbgprintf("CreateUpDownControl(...)\n");
3832     return 0;
3833 }
3834 #endif
3835
3836 /* alex: implement this call! needed for 3ivx */
3837 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
3838 {
3839     dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
3840            pUnkOuter, ppUnkInner);
3841 //    return 0;
3842     return ERROR_CALL_NOT_IMPLEMENTED;
3843 }
3844
3845
3846 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle,  // handle to source process
3847                                      HANDLE hSourceHandle,         // handle to duplicate
3848                                      HANDLE hTargetProcessHandle,  // handle to target process
3849                                      HANDLE* lpTargetHandle,      // duplicate handle
3850                                      DWORD dwDesiredAccess,        // requested access
3851                                      int bInheritHandle,          // handle inheritance option
3852                                      DWORD dwOptions               // optional actions
3853                                     )
3854 {
3855     dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
3856               hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
3857               lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
3858     *lpTargetHandle = hSourceHandle;
3859     return 1;
3860 }
3861
3862 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
3863 static HRESULT WINAPI expCoInitialize(
3864                                       LPVOID lpReserved /* [in] pointer to win32 malloc interface
3865                                       (obsolete, should be NULL) */
3866                                      )
3867 {
3868     /*
3869      * Just delegate to the newer method.
3870      */
3871     return 0; //CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
3872 }
3873
3874 static DWORD WINAPI expSetThreadAffinityMask
3875 (
3876         HANDLE hThread,
3877         DWORD dwThreadAffinityMask
3878 ){
3879     return 0;
3880 };
3881
3882 /*
3883  * no WINAPI functions - CDECL
3884  */
3885 static void* expmalloc(int size)
3886 {
3887     //printf("malloc");
3888     //    return malloc(size);
3889     void* result=my_mreq(size,0);
3890     dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
3891     if(result==0)
3892         printf("WARNING: malloc() failed\n");
3893     return result;
3894 }
3895 static void expfree(void* mem)
3896 {
3897     //    return free(mem);
3898     dbgprintf("free(%p)\n", mem);
3899     my_release(mem);
3900 }
3901 /* needed by atrac3.acm */
3902 static void *expcalloc(int num, int size)
3903 {
3904     void* result=my_mreq(num*size,1);
3905     dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
3906     if(result==0)
3907         printf("WARNING: calloc() failed\n");
3908     return result;
3909 }
3910 static void* expnew(int size)
3911 {
3912     //    printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
3913     //    printf("%08x %08x %08x %08x\n",
3914     //    size, *(1+(int*)&size),
3915     //    *(2+(int*)&size),*(3+(int*)&size));
3916     void* result;
3917     assert(size >= 0);
3918
3919     result=my_mreq(size,0);
3920     dbgprintf("new(%d) => %p\n", size, result);
3921     if (result==0)
3922         printf("WARNING: new() failed\n");
3923     return result;
3924
3925 }
3926 static int expdelete(void* memory)
3927 {
3928     dbgprintf("delete(%p)\n", memory);
3929     my_release(memory);
3930     return 0;
3931 }
3932
3933 /*
3934  * local definition - we need only the last two members at this point
3935  * otherwice we would have to introduce here GUIDs and some more types..
3936  */
3937 typedef struct __attribute__((__packed__))
3938 {
3939     char hay[0x40];
3940     unsigned long cbFormat;             //0x40
3941     char*       pbFormat;               //0x44
3942 } MY_MEDIA_TYPE;
3943 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
3944 {
3945     if (!dest || !src)
3946         return E_POINTER;
3947     memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
3948     if (dest->cbFormat)
3949     {
3950         dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
3951         if (!dest->pbFormat)
3952             return E_OUTOFMEMORY;
3953         memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
3954     }
3955     return S_OK;
3956 }
3957 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
3958 {
3959     if (!dest)
3960         return E_POINTER;
3961     memset(dest, 0, sizeof(MY_MEDIA_TYPE));
3962     if (cbFormat)
3963     {
3964         dest->pbFormat = (char*) my_mreq(cbFormat, 0);
3965         if (!dest->pbFormat)
3966             return E_OUTOFMEMORY;
3967     }
3968     return S_OK;
3969 }
3970 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
3971 {
3972     if (!dest)
3973         return E_POINTER;
3974     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3975     return expMoInitMediaType(*dest, cbFormat);
3976 }
3977 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
3978 {
3979     if (!dest)
3980         return E_POINTER;
3981     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3982     return expMoCopyMediaType(*dest, src);
3983 }
3984 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
3985 {
3986     if (!dest)
3987         return E_POINTER;
3988     if (dest->pbFormat)
3989     {
3990         my_release(dest->pbFormat);
3991         dest->pbFormat = 0;
3992         dest->cbFormat = 0;
3993     }
3994     return S_OK;
3995 }
3996 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
3997 {
3998     if (!dest)
3999         return E_POINTER;
4000     expMoFreeMediaType(dest);
4001     my_release(dest);
4002     return S_OK;
4003 }
4004
4005 static int exp_snprintf( char *str, int size, const char *format, ... )
4006 {
4007       int x;
4008       va_list va;
4009       va_start(va, format);
4010       x=snprintf(str,size,format,va);
4011       dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
4012       va_end(va);
4013       return x;
4014 }
4015
4016 #if 0
4017 static int exp_initterm(int v1, int v2)
4018 {
4019     dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
4020     return 0;
4021 }
4022 #else
4023 /* merged from wine - 2002.04.21 */
4024 typedef void (*_INITTERMFUNC)();
4025 static int exp_initterm(_INITTERMFUNC *start, _INITTERMFUNC *end)
4026 {
4027     dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
4028     while (start < end)
4029     {
4030         if (*start)
4031         {
4032             //printf("call _initfunc: from: %p %d\n", *start);
4033             // ok this trick with push/pop is necessary as otherwice
4034             // edi/esi registers are being trashed
4035             void* p = *start;
4036             __asm__ __volatile__
4037                 (
4038                  "pushl %%ebx           \n\t"
4039                  "pushl %%ecx           \n\t"
4040                  "pushl %%edx           \n\t"
4041                  "pushl %%edi           \n\t"
4042                  "pushl %%esi           \n\t"
4043                  "call  *%%eax          \n\t"
4044                  "popl  %%esi           \n\t"
4045                  "popl  %%edi           \n\t"
4046                  "popl  %%edx           \n\t"
4047                  "popl  %%ecx           \n\t"
4048                  "popl  %%ebx           \n\t"
4049                  :
4050                  : "a"(p)
4051                  : "memory"
4052                 );
4053             //printf("done  %p  %d:%d\n", end);
4054         }
4055         start++;
4056     }
4057     return 0;
4058 }
4059 #endif
4060
4061 static void* exp__dllonexit()
4062 {
4063     // FIXME extract from WINE
4064     return NULL;
4065 }
4066
4067 static int expwsprintfA(char* string, const char* format, ...)
4068 {
4069     va_list va;
4070     int result;
4071     va_start(va, format);
4072     result = vsprintf(string, format, va);
4073     dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4074     va_end(va);
4075     return result;
4076 }
4077
4078 static int expsprintf(char* str, const char* format, ...)
4079 {
4080     va_list args;
4081     int r;
4082     dbgprintf("sprintf(0x%x, %s)\n", str, format);
4083     va_start(args, format);
4084     r = vsprintf(str, format, args);
4085     va_end(args);
4086     return r;
4087 }
4088 static int expsscanf(const char* str, const char* format, ...)
4089 {
4090     va_list args;
4091     int r;
4092     dbgprintf("sscanf(%s, %s)\n", str, format);
4093     va_start(args, format);
4094     r = vsscanf(str, format, args);
4095     va_end(args);
4096     return r;
4097 }
4098 static void* expfopen(const char* path, const char* mode)
4099 {
4100     printf("fopen: \"%s\"  mode:%s\n", path, mode);
4101     //return fopen(path, mode);
4102     return fdopen(0, mode); // everything on screen
4103 }
4104 static int expfprintf(void* stream, const char* format, ...)
4105 {
4106     va_list args;
4107     int r = 0;
4108     dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4109 #if 1
4110     va_start(args, format);
4111     r = vfprintf((FILE*) stream, format, args);
4112     va_end(args);
4113 #endif
4114     return r;
4115 }
4116
4117 static int expprintf(const char* format, ...)
4118 {
4119     va_list args;
4120     int r;
4121     dbgprintf("printf(%s, ...)\n", format);
4122     va_start(args, format);
4123     r = vprintf(format, args);
4124     va_end(args);
4125     return r;
4126 }
4127
4128 static char* expgetenv(const char* varname)
4129 {
4130     char* v = getenv(varname);
4131     dbgprintf("getenv(%s) => %s\n", varname, v);
4132     return v;
4133 }
4134
4135 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4136 {
4137     WCHAR* p = dst;
4138     while ((*p++ = *src++))
4139         ;
4140     return dst;
4141 }
4142
4143 static char* expstrrchr(char* string, int value)
4144 {
4145     char* result=strrchr(string, value);
4146     if(result)
4147         dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4148     else
4149         dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4150     return result;
4151 }
4152
4153 static char* expstrchr(char* string, int value)
4154 {
4155     char* result=strchr(string, value);
4156     if(result)
4157         dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4158     else
4159         dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4160     return result;
4161 }
4162 static int expstrlen(char* str)
4163 {
4164     int result=strlen(str);
4165     dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4166     return result;
4167 }
4168 static char* expstrcpy(char* str1, const char* str2)
4169 {
4170     char* result= strcpy(str1, str2);
4171     dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4172     return result;
4173 }
4174 static char* expstrncpy(char* str1, const char* str2, size_t count)
4175 {
4176     char* result= strncpy(str1, str2, count);
4177     dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4178     return result;
4179 }
4180 static int expstrcmp(const char* str1, const char* str2)
4181 {
4182     int result=strcmp(str1, str2);
4183     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4184     return result;
4185 }
4186 static int expstrncmp(const char* str1, const char* str2,int x)
4187 {
4188     int result=strncmp(str1, str2,x);
4189     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4190     return result;
4191 }
4192 static char* expstrcat(char* str1, const char* str2)
4193 {
4194     char* result = strcat(str1, str2);
4195     dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4196     return result;
4197 }
4198 static char* exp_strdup(const char* str1)
4199 {
4200     int l = strlen(str1);
4201     char* result = (char*) my_mreq(l + 1,0);
4202     if (result)
4203         strcpy(result, str1);
4204     dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4205     return result;
4206 }
4207 static int expisalnum(int c)
4208 {
4209     int result= (int) isalnum(c);
4210     dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4211     return result;
4212 }
4213 static int expisspace(int c)
4214 {
4215     int result= (int) isspace(c);
4216     dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4217     return result;
4218 }
4219 static int expisalpha(int c)
4220 {
4221     int result= (int) isalpha(c);
4222     dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4223     return result;
4224 }
4225 static int expisdigit(int c)
4226 {
4227     int result= (int) isdigit(c);
4228     dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4229     return result;
4230 }
4231 static void* expmemmove(void* dest, void* src, int n)
4232 {
4233     void* result = memmove(dest, src, n);
4234     dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4235     return result;
4236 }
4237 static int expmemcmp(void* dest, void* src, int n)
4238 {
4239     int result = memcmp(dest, src, n);
4240     dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4241     return result;
4242 }
4243 static void* expmemcpy(void* dest, void* src, int n)
4244 {
4245     void *result = memcpy(dest, src, n);
4246     dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4247     return result;
4248 }
4249 static void* expmemset(void* dest, int c, size_t n)
4250 {
4251     void *result = memset(dest, c, n);
4252     dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4253     return result;
4254 }
4255 static time_t exptime(time_t* t)
4256 {
4257     time_t result = time(t);
4258     dbgprintf("time(0x%x) => %d\n", t, result);
4259     return result;
4260 }
4261
4262 static int exprand(void)
4263 {
4264     return rand();
4265 }
4266
4267 static void expsrand(int seed)
4268 {
4269     srand(seed);
4270 }
4271
4272 #if 1
4273
4274 // preferred compilation with  -O2 -ffast-math !
4275
4276 static double explog10(double x)
4277 {
4278     /*printf("Log10 %f => %f    0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4279     return log10(x);
4280 }
4281
4282 static double expcos(double x)
4283 {
4284     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4285     return cos(x);
4286 }
4287
4288 /* doens't work */
4289 static long exp_ftol_wrong(double x)
4290 {
4291     return (long) x;
4292 }
4293
4294 #else
4295
4296 static void explog10(void)
4297 {
4298     __asm__ __volatile__
4299         (
4300          "fldl 8(%esp)  \n\t"
4301          "fldln2        \n\t"
4302          "fxch %st(1)   \n\t"
4303          "fyl2x         \n\t"
4304         );
4305 }
4306
4307 static void expcos(void)
4308 {
4309     __asm__ __volatile__
4310         (
4311          "fldl 8(%esp)  \n\t"
4312          "fcos          \n\t"
4313         );
4314 }
4315
4316 #endif
4317
4318 // this seem to be the only how to make this function working properly
4319 // ok - I've spent tremendous amount of time (many many many hours
4320 // of debuging fixing & testing - it's almost unimaginable - kabi
4321
4322 // _ftol - operated on the float value which is already on the FPU stack
4323
4324 static void exp_ftol(void)
4325 {
4326     __asm__ __volatile__
4327         (
4328          "sub $12, %esp         \n\t"
4329          "fstcw   -2(%ebp)      \n\t"
4330          "wait                  \n\t"
4331          "movw    -2(%ebp), %ax \n\t"
4332          "orb    $0x0C, %ah     \n\t"
4333          "movw    %ax, -4(%ebp) \n\t"
4334          "fldcw   -4(%ebp)      \n\t"
4335          "fistpl -12(%ebp)      \n\t"
4336          "fldcw   -2(%ebp)      \n\t"
4337          "movl   -12(%ebp), %eax \n\t"
4338          //Note: gcc 3.03 does not do the following op if it
4339          //      knows that ebp=esp
4340          "movl %ebp, %esp       \n\t"
4341         );
4342 }
4343
4344 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4345   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
4346   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
4347
4348 static double exp_CIpow(void)
4349 {
4350     FPU_DOUBLES(x,y);
4351
4352     dbgprintf("_CIpow(%lf, %lf)\n", x, y);
4353     return pow(x, y);
4354 }
4355
4356 static double exppow(double x, double y)
4357 {
4358     /*printf("Pow %f  %f    0x%Lx  0x%Lx  => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4359     return pow(x, y);
4360 }
4361
4362 static double expldexp(double x, int expo)
4363 {
4364     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4365     return ldexp(x, expo);
4366 }
4367
4368 static double expfrexp(double x, int* expo)
4369 {
4370     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4371     return frexp(x, expo);
4372 }
4373
4374
4375
4376 static int exp_stricmp(const char* s1, const char* s2)
4377 {
4378     return strcasecmp(s1, s2);
4379 }
4380
4381 /* from declaration taken from Wine sources - this fountion seems to be
4382  * undocumented in any M$ doc */
4383 static int exp_setjmp3(void* jmpbuf, int x)
4384 {
4385     //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4386     //return 0;
4387     __asm__ __volatile__
4388         (
4389          //"mov 4(%%esp), %%edx \n\t"
4390          "mov (%%esp), %%eax   \n\t"
4391          "mov %%eax, (%%edx)    \n\t" // store ebp
4392
4393          //"mov %%ebp, (%%edx)  \n\t"
4394          "mov %%ebx, 4(%%edx)   \n\t"
4395          "mov %%edi, 8(%%edx)   \n\t"
4396          "mov %%esi, 12(%%edx)  \n\t"
4397          "mov %%esp, 16(%%edx)  \n\t"
4398
4399          "mov 4(%%esp), %%eax   \n\t"
4400          "mov %%eax, 20(%%edx)  \n\t"
4401
4402          "movl $0x56433230, 32(%%edx)   \n\t" // VC20 ??
4403          "movl $0, 36(%%edx)    \n\t"
4404          : // output
4405          : "d"(jmpbuf) // input
4406          : "eax"
4407         );
4408 #if 1
4409     __asm__ __volatile__
4410         (
4411          "mov %%fs:0, %%eax     \n\t" // unsure
4412          "mov %%eax, 24(%%edx)  \n\t"
4413          "cmp $0xffffffff, %%eax \n\t"
4414          "jnz l1                \n\t"
4415          "mov %%eax, 28(%%edx)  \n\t"
4416          "l1:                   \n\t"
4417          :
4418          :
4419          : "eax"
4420         );
4421 #endif
4422
4423         return 0;
4424 }
4425
4426 static DWORD WINAPI expGetCurrentProcessId(void)
4427 {
4428     dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4429     return getpid(); //(DWORD)NtCurrentTeb()->pid;
4430 }
4431
4432
4433 typedef struct {
4434     UINT        wPeriodMin;
4435     UINT        wPeriodMax;
4436 } TIMECAPS, *LPTIMECAPS;
4437
4438 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4439 {
4440     dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4441
4442     lpCaps->wPeriodMin = 1;
4443     lpCaps->wPeriodMax = 65535;
4444     return 0;
4445 }
4446
4447 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4448 {
4449     dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4450
4451     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4452     return 0;
4453 }
4454
4455 #ifdef QTX
4456 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4457 {
4458     dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4459
4460     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4461     return 0;
4462 }
4463 #endif
4464
4465 static void WINAPI expGlobalMemoryStatus(
4466             LPMEMORYSTATUS lpmem
4467 ) {
4468     static MEMORYSTATUS cached_memstatus;
4469     static int cache_lastchecked = 0;
4470     SYSTEM_INFO si;
4471     FILE *f;
4472
4473     if (time(NULL)==cache_lastchecked) {
4474         memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4475         return;
4476     }
4477
4478 #if 1
4479     f = fopen( "/proc/meminfo", "r" );
4480     if (f)
4481     {
4482         char buffer[256];
4483         int total, used, free, shared, buffers, cached;
4484
4485         lpmem->dwLength = sizeof(MEMORYSTATUS);
4486         lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4487         lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4488         while (fgets( buffer, sizeof(buffer), f ))
4489         {
4490             /* old style /proc/meminfo ... */
4491             if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4492             {
4493                 lpmem->dwTotalPhys += total;
4494                 lpmem->dwAvailPhys += free + buffers + cached;
4495             }
4496             if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4497             {
4498                 lpmem->dwTotalPageFile += total;
4499                 lpmem->dwAvailPageFile += free;
4500             }
4501
4502             /* new style /proc/meminfo ... */
4503             if (sscanf(buffer, "MemTotal: %d", &total))
4504                 lpmem->dwTotalPhys = total*1024;
4505             if (sscanf(buffer, "MemFree: %d", &free))
4506                 lpmem->dwAvailPhys = free*1024;
4507             if (sscanf(buffer, "SwapTotal: %d", &total))
4508                 lpmem->dwTotalPageFile = total*1024;
4509             if (sscanf(buffer, "SwapFree: %d", &free))
4510                 lpmem->dwAvailPageFile = free*1024;
4511             if (sscanf(buffer, "Buffers: %d", &buffers))
4512                 lpmem->dwAvailPhys += buffers*1024;
4513             if (sscanf(buffer, "Cached: %d", &cached))
4514                 lpmem->dwAvailPhys += cached*1024;
4515         }
4516         fclose( f );
4517
4518         if (lpmem->dwTotalPhys)
4519         {
4520             DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4521             DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4522             lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4523                                       / (TotalPhysical / 100);
4524         }
4525     } else
4526 #endif
4527     {
4528         /* FIXME: should do something for other systems */
4529         lpmem->dwMemoryLoad    = 0;
4530         lpmem->dwTotalPhys     = 16*1024*1024;
4531         lpmem->dwAvailPhys     = 16*1024*1024;
4532         lpmem->dwTotalPageFile = 16*1024*1024;
4533         lpmem->dwAvailPageFile = 16*1024*1024;
4534     }
4535     expGetSystemInfo(&si);
4536     lpmem->dwTotalVirtual  = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
4537     /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4538     lpmem->dwAvailVirtual  = lpmem->dwTotalVirtual-64*1024;
4539     memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4540     cache_lastchecked = time(NULL);
4541
4542     /* it appears some memory display programs want to divide by these values */
4543     if(lpmem->dwTotalPageFile==0)
4544         lpmem->dwTotalPageFile++;
4545
4546     if(lpmem->dwAvailPageFile==0)
4547         lpmem->dwAvailPageFile++;
4548 }
4549
4550 /**********************************************************************
4551  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
4552  *
4553  * RETURNS
4554  *    Success: TRUE
4555  *    Failure: FALSE
4556  */
4557 static WIN_BOOL WINAPI expSetThreadPriority(
4558     HANDLE hthread, /* [in] Handle to thread */
4559     INT priority)   /* [in] Thread priority level */
4560 {
4561     dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4562     return TRUE;
4563 }
4564
4565 static void WINAPI expExitProcess( DWORD status )
4566 {
4567     printf("EXIT - code %ld\n",status);
4568     exit(status);
4569 }
4570
4571 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4572     printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4573 #ifdef QTX
4574     if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4575         return IDIGNORE;
4576 #endif
4577     return IDOK;
4578 }
4579
4580 /* these are needed for mss1 */
4581
4582 /* defined in stubs.s */
4583 void exp_EH_prolog(void);
4584
4585 #include <netinet/in.h>
4586 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4587 {
4588 //    dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4589     return htonl(hostlong);
4590 }
4591
4592 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4593 {
4594 //    dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4595     return ntohl(netlong);
4596 }
4597 static void WINAPI expVariantInit(void* p)
4598 {
4599     printf("InitCommonControls called!\n");
4600     return;
4601 }
4602
4603 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4604 {
4605     dbgprintf("RegisterClassA(%p) => random id\n", wc);
4606     return time(NULL); /* be precise ! */
4607 }
4608
4609 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4610 {
4611     dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4612     return 0;
4613 }
4614
4615 #ifdef QTX
4616 /* should be fixed bcs it's not fully strlen equivalent */
4617 static int expSysStringByteLen(void *str)
4618 {
4619     dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4620     return strlen(str);
4621 }
4622
4623 static int expDirectDrawCreate(void)
4624 {
4625     dbgprintf("DirectDrawCreate(...) => NULL\n");
4626     return 0;
4627 }
4628
4629 #if 1
4630 typedef struct tagPALETTEENTRY { 
4631     BYTE peRed; 
4632     BYTE peGreen; 
4633     BYTE peBlue; 
4634     BYTE peFlags; 
4635 } PALETTEENTRY; 
4636
4637 /* reversed the first 2 entries */
4638 typedef struct tagLOGPALETTE { 
4639     WORD         palNumEntries; 
4640     WORD         palVersion; 
4641     PALETTEENTRY palPalEntry[1]; 
4642 } LOGPALETTE; 
4643
4644 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4645 {
4646     HPALETTE test;
4647     int i;
4648     
4649     dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4650
4651     i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4652     test = (HPALETTE)malloc(i);
4653     memcpy((void *)test, lpgpl, i);
4654
4655     return test;
4656 }
4657 #else
4658 static int expCreatePalette(void)
4659 {
4660     dbgprintf("CreatePalette(...) => NULL\n");
4661     return NULL;
4662 }
4663 #endif
4664
4665 static int WINAPI expGetClientRect(HWND win, RECT *r)
4666 {
4667     dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4668     r->right = PSEUDO_SCREEN_WIDTH;
4669     r->left = 0;
4670     r->bottom = PSEUDO_SCREEN_HEIGHT;
4671     r->top = 0;
4672     return 1;
4673 }
4674
4675 #if 0
4676 typedef struct tagPOINT { 
4677     LONG x; 
4678     LONG y; 
4679 } POINT, *PPOINT; 
4680 #endif
4681
4682 static int WINAPI expClientToScreen(HWND win, POINT *p)
4683 {
4684     dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4685     p->x = 0;
4686     p->y = 0;
4687     return 1;
4688 }
4689 #endif
4690
4691 /* for m3jpeg */
4692 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4693 {
4694     dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4695     return 0;
4696 }
4697
4698 static int WINAPI expMessageBeep(int type)
4699 {
4700     dbgprintf("MessageBeep(%d) => 1\n", type);
4701     return 1;
4702 }
4703
4704 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4705     HWND parent, void *dialog_func, void *init_param)
4706 {
4707     dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4708         inst, name, name, parent, dialog_func, init_param);
4709     return 0x42424242;
4710 }
4711
4712 /* needed by imagepower mjpeg2k */
4713 static void *exprealloc(void *ptr, size_t size)
4714 {
4715     dbgprintf("realloc(0x%x, %x)\n", ptr, size);
4716     if (!ptr)
4717         return my_mreq(size,0);
4718     else
4719         return my_realloc(ptr, size);        
4720 }
4721
4722 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
4723 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
4724 {
4725     return 1;
4726 }
4727
4728 static double expfloor(double x)
4729 {
4730     dbgprintf("floor(%lf)\n", x);
4731     return floor(x);
4732 }
4733
4734 #define FPU_DOUBLE(var) double var; \
4735   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
4736
4737 static double exp_CIcos(void)
4738 {
4739     FPU_DOUBLE(x);
4740
4741     dbgprintf("_CIcos(%lf)\n", x);
4742     return cos(x);
4743 }
4744
4745 static double exp_CIsin(void)
4746 {
4747     FPU_DOUBLE(x);
4748
4749     dbgprintf("_CIsin(%lf)\n", x);
4750     return sin(x);
4751 }
4752
4753 struct exports
4754 {
4755     char name[64];
4756     int id;
4757     void* func;
4758 };
4759 struct libs
4760 {
4761     char name[64];
4762     int length;
4763     struct exports* exps;
4764 };
4765
4766 #define FF(X,Y) \
4767     {#X, Y, (void*)exp##X},
4768
4769 struct exports exp_kernel32[]=
4770 {
4771     FF(GetVolumeInformationA,-1)
4772     FF(GetDriveTypeA,-1)
4773     FF(GetLogicalDriveStringsA,-1)
4774     FF(IsBadWritePtr, 357)
4775     FF(IsBadReadPtr, 354)
4776     FF(IsBadStringPtrW, -1)
4777     FF(IsBadStringPtrA, -1)
4778     FF(DisableThreadLibraryCalls, -1)
4779     FF(CreateThread, -1)
4780     FF(CreateEventA, -1)
4781     FF(SetEvent, -1)
4782     FF(ResetEvent, -1)
4783     FF(WaitForSingleObject, -1)
4784 #ifdef QTX
4785     FF(WaitForMultipleObjects, -1)
4786     FF(ExitThread, -1)
4787     FF(CreateMutexA,-1)
4788     FF(ReleaseMutex,-1)
4789 #endif
4790     FF(GetSystemInfo, -1)
4791     FF(GetVersion, 332)
4792     FF(HeapCreate, 461)
4793     FF(HeapAlloc, -1)
4794     FF(HeapDestroy, -1)
4795     FF(HeapFree, -1)
4796     FF(HeapSize, -1)
4797     FF(HeapReAlloc,-1)
4798     FF(GetProcessHeap, -1)
4799     FF(VirtualAlloc, -1)
4800     FF(VirtualFree, -1)
4801     FF(InitializeCriticalSection, -1)
4802     FF(EnterCriticalSection, -1)
4803     FF(LeaveCriticalSection, -1)
4804     FF(DeleteCriticalSection, -1)
4805     FF(TlsAlloc, -1)
4806     FF(TlsFree, -1)
4807     FF(TlsGetValue, -1)
4808     FF(TlsSetValue, -1)
4809     FF(GetCurrentThreadId, -1)
4810     FF(GetCurrentProcess, -1)
4811     FF(LocalAlloc, -1)
4812     FF(LocalReAlloc,-1)
4813     FF(LocalLock, -1)
4814     FF(GlobalAlloc, -1)
4815     FF(GlobalReAlloc, -1)
4816     FF(GlobalLock, -1)
4817     FF(GlobalSize, -1)
4818     FF(MultiByteToWideChar, 427)
4819     FF(WideCharToMultiByte, -1)
4820     FF(GetVersionExA, -1)
4821     FF(CreateSemaphoreA, -1)
4822     FF(QueryPerformanceCounter, -1)
4823     FF(QueryPerformanceFrequency, -1)
4824     FF(LocalHandle, -1)
4825     FF(LocalUnlock, -1)
4826     FF(LocalFree, -1)
4827     FF(GlobalHandle, -1)
4828     FF(GlobalUnlock, -1)
4829     FF(GlobalFree, -1)
4830     FF(LoadResource, -1)
4831     FF(ReleaseSemaphore, -1)
4832     FF(FindResourceA, -1)
4833     FF(LockResource, -1)
4834     FF(FreeResource, -1)
4835     FF(SizeofResource, -1)
4836     FF(CloseHandle, -1)
4837     FF(GetCommandLineA, -1)
4838     FF(GetEnvironmentStringsW, -1)
4839     FF(FreeEnvironmentStringsW, -1)
4840     FF(FreeEnvironmentStringsA, -1)
4841     FF(GetEnvironmentStrings, -1)
4842     FF(GetStartupInfoA, -1)
4843     FF(GetStdHandle, -1)
4844     FF(GetFileType, -1)
4845 #ifdef QTX
4846     FF(GetFileAttributesA, -1)
4847 #endif
4848     FF(SetHandleCount, -1)
4849     FF(GetACP, -1)
4850     FF(GetModuleFileNameA, -1)
4851     FF(SetUnhandledExceptionFilter, -1)
4852     FF(LoadLibraryA, -1)
4853     FF(GetProcAddress, -1)
4854     FF(FreeLibrary, -1)
4855     FF(CreateFileMappingA, -1)
4856     FF(OpenFileMappingA, -1)
4857     FF(MapViewOfFile, -1)
4858     FF(UnmapViewOfFile, -1)
4859     FF(Sleep, -1)
4860     FF(GetModuleHandleA, -1)
4861     FF(GetProfileIntA, -1)
4862     FF(GetPrivateProfileIntA, -1)
4863     FF(GetPrivateProfileStringA, -1)
4864     FF(WritePrivateProfileStringA, -1)
4865     FF(GetLastError, -1)
4866     FF(SetLastError, -1)
4867     FF(InterlockedIncrement, -1)
4868     FF(InterlockedDecrement, -1)
4869     FF(GetTimeZoneInformation, -1)
4870     FF(OutputDebugStringA, -1)
4871     FF(GetLocalTime, -1)
4872     FF(GetSystemTime, -1)
4873     FF(GetSystemTimeAsFileTime, -1)
4874     FF(GetEnvironmentVariableA, -1)
4875     FF(SetEnvironmentVariableA, -1)
4876     FF(RtlZeroMemory,-1)
4877     FF(RtlMoveMemory,-1)
4878     FF(RtlFillMemory,-1)
4879     FF(GetTempPathA,-1)
4880     FF(FindFirstFileA,-1)
4881     FF(FindNextFileA,-1)
4882     FF(FindClose,-1)
4883     FF(FileTimeToLocalFileTime,-1)
4884     FF(DeleteFileA,-1)
4885     FF(ReadFile,-1)
4886     FF(WriteFile,-1)
4887     FF(SetFilePointer,-1)
4888     FF(GetTempFileNameA,-1)
4889     FF(CreateFileA,-1)
4890     FF(GetSystemDirectoryA,-1)
4891     FF(GetWindowsDirectoryA,-1)
4892 #ifdef QTX
4893     FF(GetCurrentDirectoryA,-1)
4894     FF(SetCurrentDirectoryA,-1)
4895     FF(CreateDirectoryA,-1)
4896 #endif
4897     FF(GetShortPathNameA,-1)
4898     FF(GetFullPathNameA,-1)
4899     FF(SetErrorMode, -1)
4900     FF(IsProcessorFeaturePresent, -1)
4901     FF(GetProcessAffinityMask, -1)
4902     FF(InterlockedExchange, -1)
4903     FF(InterlockedCompareExchange, -1)
4904     FF(MulDiv, -1)
4905     FF(lstrcmpiA, -1)
4906     FF(lstrlenA, -1)
4907     FF(lstrcpyA, -1)
4908     FF(lstrcatA, -1)
4909     FF(lstrcpynA,-1)
4910     FF(GetProcessVersion,-1)
4911     FF(GetCurrentThread,-1)
4912     FF(GetOEMCP,-1)
4913     FF(GetCPInfo,-1)
4914     FF(DuplicateHandle,-1)
4915     FF(GetTickCount, -1)
4916     FF(SetThreadAffinityMask,-1)
4917     FF(GetCurrentProcessId,-1)
4918     FF(GlobalMemoryStatus,-1)
4919     FF(SetThreadPriority,-1)
4920     FF(ExitProcess,-1)
4921     {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
4922     FF(SetThreadIdealProcessor,-1)
4923 };
4924
4925 struct exports exp_msvcrt[]={
4926     FF(malloc, -1)
4927     FF(_initterm, -1)
4928     FF(__dllonexit, -1)
4929     FF(_snprintf,-1)
4930     FF(free, -1)
4931     {"??3@YAXPAX@Z", -1, expdelete},
4932     {"??2@YAPAXI@Z", -1, expnew},
4933     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
4934     FF(strrchr, -1)
4935     FF(strchr, -1)
4936     FF(strlen, -1)
4937     FF(strcpy, -1)
4938     FF(strncpy, -1)
4939     FF(wcscpy, -1)
4940     FF(strcmp, -1)
4941     FF(strncmp, -1)
4942     FF(strcat, -1)
4943     FF(_stricmp,-1)
4944     FF(_strdup,-1)
4945     FF(_setjmp3,-1)
4946     FF(isalnum, -1)
4947     FF(isspace, -1)
4948     FF(isalpha, -1)
4949     FF(isdigit, -1)
4950     FF(memmove, -1)
4951     FF(memcmp, -1)
4952     FF(memset, -1)
4953     FF(memcpy, -1)
4954     FF(time, -1)
4955     FF(rand, -1)
4956     FF(srand, -1)
4957     FF(log10, -1)
4958     FF(pow, -1)
4959     FF(cos, -1)
4960     FF(_ftol,-1)
4961     FF(_CIpow,-1)
4962     FF(_CIcos,-1)
4963     FF(_CIsin,-1)
4964     FF(ldexp,-1)
4965     FF(frexp,-1)
4966     FF(sprintf,-1)
4967     FF(sscanf,-1)
4968     FF(fopen,-1)
4969     FF(fprintf,-1)
4970     FF(printf,-1)
4971     FF(getenv,-1)
4972     FF(floor,-1)
4973 /* needed by frapsvid.dll */
4974     {"strstr",-1,(char *)&strstr},
4975     {"qsort",-1,(void *)&qsort},
4976 #ifdef MPLAYER
4977     FF(_EH_prolog,-1)
4978 #endif
4979     FF(calloc,-1)
4980     {"ceil",-1,(void*)&ceil},
4981 /* needed by imagepower mjpeg2k */
4982     {"clock",-1,(void*)&clock},
4983     {"memchr",-1,(void*)&memchr},
4984     {"vfprintf",-1,(void*)&vfprintf},
4985 //    {"realloc",-1,(void*)&realloc},
4986     FF(realloc,-1)
4987     {"puts",-1,(void*)&puts}
4988 };
4989 struct exports exp_winmm[]={
4990     FF(GetDriverModuleHandle, -1)
4991     FF(timeGetTime, -1)
4992     FF(DefDriverProc, -1)
4993     FF(OpenDriverA, -1)
4994     FF(OpenDriver, -1)
4995     FF(timeGetDevCaps, -1)
4996     FF(timeBeginPeriod, -1)
4997 #ifdef QTX
4998     FF(timeEndPeriod, -1)
4999     FF(waveOutGetNumDevs, -1)
5000 #endif
5001 };
5002 struct exports exp_user32[]={
5003     FF(LoadIconA,-1)
5004     FF(LoadStringA, -1)
5005     FF(wsprintfA, -1)
5006     FF(GetDC, -1)
5007     FF(GetDesktopWindow, -1)
5008     FF(ReleaseDC, -1)
5009     FF(IsRectEmpty, -1)
5010     FF(LoadCursorA,-1)
5011     FF(SetCursor,-1)
5012     FF(GetCursorPos,-1)
5013 #ifdef QTX
5014     FF(ShowCursor,-1)
5015 #endif
5016     FF(RegisterWindowMessageA,-1)
5017     FF(GetSystemMetrics,-1)
5018     FF(GetSysColor,-1)
5019     FF(GetSysColorBrush,-1)
5020     FF(GetWindowDC, -1)
5021     FF(DrawTextA, -1)
5022     FF(MessageBoxA, -1)
5023     FF(RegisterClassA, -1)
5024     FF(UnregisterClassA, -1)
5025 #ifdef QTX
5026     FF(GetWindowRect, -1)
5027     FF(MonitorFromWindow, -1)
5028     FF(MonitorFromRect, -1)
5029     FF(MonitorFromPoint, -1)
5030     FF(EnumDisplayMonitors, -1)
5031     FF(GetMonitorInfoA, -1)
5032     FF(EnumDisplayDevicesA, -1)
5033     FF(GetClientRect, -1)
5034     FF(ClientToScreen, -1)
5035     FF(IsWindowVisible, -1)
5036     FF(GetActiveWindow, -1)
5037     FF(GetClassNameA, -1)
5038     FF(GetClassInfoA, -1)
5039     FF(GetWindowLongA, -1)
5040     FF(EnumWindows, -1)
5041     FF(GetWindowThreadProcessId, -1)
5042     FF(CreateWindowExA, -1)
5043 #endif
5044     FF(MessageBeep, -1)
5045     FF(DialogBoxParamA, -1)
5046 };
5047 struct exports exp_advapi32[]={
5048     FF(RegCloseKey, -1)
5049     FF(RegCreateKeyA, -1)
5050     FF(RegCreateKeyExA, -1)
5051     FF(RegEnumKeyExA, -1)
5052     FF(RegEnumValueA, -1)
5053     FF(RegOpenKeyA, -1)
5054     FF(RegOpenKeyExA, -1)
5055     FF(RegQueryValueExA, -1)
5056     FF(RegSetValueExA, -1)
5057     FF(RegQueryInfoKeyA, -1)
5058 };
5059 struct exports exp_gdi32[]={
5060     FF(CreateCompatibleDC, -1)
5061     FF(CreateFontA, -1)
5062     FF(DeleteDC, -1)
5063     FF(DeleteObject, -1)
5064     FF(GetDeviceCaps, -1)
5065     FF(GetSystemPaletteEntries, -1)
5066 #ifdef QTX
5067     FF(CreatePalette, -1)
5068     FF(GetObjectA, -1)
5069     FF(CreateRectRgn, -1)
5070 #endif
5071 };
5072 struct exports exp_version[]={
5073     FF(GetFileVersionInfoSizeA, -1)
5074 };
5075 struct exports exp_ole32[]={
5076     FF(CoCreateFreeThreadedMarshaler,-1)
5077     FF(CoCreateInstance, -1)
5078     FF(CoInitialize, -1)
5079     FF(CoTaskMemAlloc, -1)
5080     FF(CoTaskMemFree, -1)
5081     FF(StringFromGUID2, -1)
5082 };
5083 // do we really need crtdll ???
5084 // msvcrt is the correct place probably...
5085 struct exports exp_crtdll[]={
5086     FF(memcpy, -1)
5087     FF(wcscpy, -1)
5088 };
5089 struct exports exp_comctl32[]={
5090     FF(StringFromGUID2, -1)
5091     FF(InitCommonControls, 17)
5092 #ifdef QTX
5093     FF(CreateUpDownControl, 16)
5094 #endif
5095 };
5096 struct exports exp_wsock32[]={
5097     FF(htonl,8)
5098     FF(ntohl,14)
5099 };
5100 struct exports exp_msdmo[]={
5101     FF(memcpy, -1) // just test
5102     FF(MoCopyMediaType, -1)
5103     FF(MoCreateMediaType, -1)
5104     FF(MoDeleteMediaType, -1)
5105     FF(MoDuplicateMediaType, -1)
5106     FF(MoFreeMediaType, -1)
5107     FF(MoInitMediaType, -1)
5108 };
5109 struct exports exp_oleaut32[]={
5110     FF(VariantInit, 8)
5111 #ifdef QTX
5112     FF(SysStringByteLen, 149)
5113 #endif
5114 };
5115
5116 /*  realplayer8:
5117         DLL Name: PNCRT.dll
5118         vma:  Hint/Ord Member-Name
5119         22ff4     615  free
5120         2302e     250  _ftol
5121         22fea     666  malloc
5122         2303e     609  fprintf
5123         2305e     167  _adjust_fdiv
5124         23052     280  _initterm
5125
5126         22ffc     176  _beginthreadex
5127         23036     284  _iob
5128         2300e      85  __CxxFrameHandler
5129         23022     411  _purecall
5130 */
5131 #ifdef REALPLAYER
5132 struct exports exp_pncrt[]={
5133     FF(malloc, -1) // just test
5134     FF(free, -1) // just test
5135     FF(fprintf, -1) // just test
5136     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5137     FF(_ftol,-1)
5138     FF(_initterm, -1)
5139     {"??3@YAXPAX@Z", -1, expdelete},
5140     {"??2@YAPAXI@Z", -1, expnew},
5141     FF(__dllonexit, -1)
5142     FF(strncpy, -1)
5143     FF(_CIpow,-1)
5144     FF(calloc,-1)
5145     FF(memmove, -1)
5146 };
5147 #endif
5148
5149 #ifdef QTX
5150 struct exports exp_ddraw[]={
5151     FF(DirectDrawCreate, -1)
5152 };
5153 #endif
5154
5155 struct exports exp_comdlg32[]={
5156     FF(GetOpenFileNameA, -1)
5157 };
5158
5159 #define LL(X) \
5160     {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5161
5162 struct libs libraries[]={
5163     LL(kernel32)
5164     LL(msvcrt)
5165     LL(winmm)
5166     LL(user32)
5167     LL(advapi32)
5168     LL(gdi32)
5169     LL(version)
5170     LL(ole32)
5171     LL(oleaut32)
5172     LL(crtdll)
5173     LL(comctl32)
5174     LL(wsock32)
5175     LL(msdmo)
5176 #ifdef REALPLAYER
5177     LL(pncrt)
5178 #endif
5179 #ifdef QTX
5180     LL(ddraw)
5181 #endif
5182     LL(comdlg32)
5183 };
5184
5185 static void ext_stubs(void)
5186 {
5187     // expects:
5188     //  ax  position index
5189     //  cx  address of printf function
5190 #if 1
5191     __asm__ __volatile__
5192         (
5193          "push %%edx            \n\t"
5194          "movl $0xdeadbeef, %%eax \n\t"
5195          "movl $0xdeadbeef, %%edx \n\t"
5196          "shl $5, %%eax         \n\t"                   // ax * 32
5197          "addl $0xdeadbeef, %%eax \n\t"                 // overwrite export_names
5198          "pushl %%eax           \n\t"
5199          "pushl $0xdeadbeef     \n\t"                   // overwrite called_unk
5200          "call *%%edx           \n\t"                   // printf (via dx)
5201          "addl $8, %%esp        \n\t"
5202          "xorl %%eax, %%eax     \n\t"
5203          "pop %%edx             \n\t"
5204          :
5205          :
5206          : "eax"
5207         );
5208 #else
5209     __asm__ __volatile__
5210         (
5211          "push %%edx            \n\t"
5212          "movl $0, %%eax        \n\t"
5213          "movl $0, %%edx        \n\t"
5214          "shl $5, %%eax         \n\t"                   // ax * 32
5215          "addl %0, %%eax        \n\t"
5216          "pushl %%eax           \n\t"
5217          "pushl %1              \n\t"
5218          "call *%%edx           \n\t"                   // printf (via dx)
5219          "addl $8, %%esp        \n\t"
5220          "xorl %%eax, %%eax     \n\t"
5221          "pop %%edx             \n\t"
5222          ::"m"(*export_names), "m"(*called_unk)
5223         : "memory", "edx", "eax"
5224         );
5225 #endif
5226
5227 }
5228
5229 //static void add_stub(int pos)
5230
5231 extern int unk_exp1;
5232 static int pos=0;
5233 static char extcode[20000];// place for 200 unresolved exports
5234 static const char* called_unk = "Called unk_%s\n";
5235
5236 static void* add_stub(void)
5237 {
5238     // generated code in runtime!
5239     char* answ = (char*)extcode+pos*0x30;
5240 #if 0
5241     memcpy(answ, &unk_exp1, 0x64);
5242     *(int*)(answ+9)=pos;
5243     *(int*)(answ+47)-=((int)answ-(int)&unk_exp1);
5244 #endif
5245     memcpy(answ, ext_stubs, 0x2f); // 0x2c is current size
5246     //answ[4] = 0xb8; // movl $0, eax  (0xb8 0x00000000)
5247     *((int*) (answ + 5)) = pos;
5248     //answ[9] = 0xba; // movl $0, edx  (0xba 0x00000000)
5249     *((long*) (answ + 10)) = (long)printf;
5250     //answ[17] = 0x05; // addl $0, eax  (0x05 0x00000000)
5251     *((long*) (answ + 18)) = (long)export_names;
5252     //answ[23] = 0x68; // pushl $0  (0x68 0x00000000)
5253     *((long*) (answ + 24)) = (long)called_unk;
5254     pos++;
5255     return (void*)answ;
5256 }
5257
5258 void* LookupExternal(const char* library, int ordinal)
5259 {
5260     int i,j;
5261     if(library==0)
5262     {
5263         printf("ERROR: library=0\n");
5264         return (void*)ext_unknown;
5265     }
5266     //    printf("%x %x\n", &unk_exp1, &unk_exp2);
5267
5268     dbgprintf("External func %s:%d\n", library, ordinal);
5269
5270     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5271     {
5272         if(strcasecmp(library, libraries[i].name))
5273             continue;
5274         for(j=0; j<libraries[i].length; j++)
5275         {
5276             if(ordinal!=libraries[i].exps[j].id)
5277                 continue;
5278             //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5279             return libraries[i].exps[j].func;
5280         }
5281     }
5282
5283 #ifndef LOADLIB_TRY_NATIVE
5284   /* hack for truespeech and vssh264*/
5285   if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5286 #endif
5287     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5288     {
5289         int hand;
5290         WINE_MODREF *wm;
5291         void *func;
5292
5293         hand = LoadLibraryA(library);
5294         if (!hand)
5295             goto no_dll;
5296         wm = MODULE32_LookupHMODULE(hand);
5297         if (!wm)
5298         {
5299             FreeLibrary(hand);
5300             goto no_dll;
5301         }
5302         func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5303         if (!func)
5304         {
5305             printf("No such ordinal in external dll\n");
5306             FreeLibrary((int)hand);
5307             goto no_dll;
5308         }
5309
5310         printf("External dll loaded (offset: 0x%x, func: %p)\n",
5311                hand, func);
5312         return func;
5313     }
5314
5315 no_dll:
5316     if(pos>150)return 0;
5317     sprintf(export_names[pos], "%s:%d", library, ordinal);
5318     return add_stub();
5319 }
5320
5321 void* LookupExternalByName(const char* library, const char* name)
5322 {
5323     char* answ;
5324     int i,j;
5325     //   return (void*)ext_unknown;
5326     if(library==0)
5327     {
5328         printf("ERROR: library=0\n");
5329         return (void*)ext_unknown;
5330     }
5331     if(name==0)
5332     {
5333         printf("ERROR: name=0\n");
5334         return (void*)ext_unknown;
5335     }
5336     dbgprintf("External func %s:%s\n", library, name);
5337     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5338     {
5339         if(strcasecmp(library, libraries[i].name))
5340             continue;
5341         for(j=0; j<libraries[i].length; j++)
5342         {
5343             if(strcmp(name, libraries[i].exps[j].name))
5344                 continue;
5345             //      printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5346             return libraries[i].exps[j].func;
5347         }
5348     }
5349
5350 #ifndef LOADLIB_TRY_NATIVE
5351   /* hack for vss h264 */
5352   if (!strcmp(library,"vssh264core.dll"))
5353 #endif
5354     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5355     {
5356         int hand;
5357         WINE_MODREF *wm;
5358         void *func;
5359
5360         hand = LoadLibraryA(library);
5361         if (!hand)
5362             goto no_dll_byname;
5363         wm = MODULE32_LookupHMODULE(hand);
5364         if (!wm)
5365         {
5366             FreeLibrary(hand);
5367             goto no_dll_byname;
5368         }
5369         func = PE_FindExportedFunction(wm, name, 0);
5370         if (!func)
5371         {
5372             printf("No such name in external dll\n");
5373             FreeLibrary((int)hand);
5374             goto no_dll_byname;
5375         }
5376
5377         printf("External dll loaded (offset: 0x%x, func: %p)\n",
5378                hand, func);
5379         return func;
5380     }
5381
5382 no_dll_byname:
5383     if(pos>150)return 0;// to many symbols
5384     strcpy(export_names[pos], name);
5385     return add_stub();
5386 }
5387
5388 void my_garbagecollection(void)
5389 {
5390 #ifdef GARBAGE
5391     int unfree = 0, unfreecnt = 0;
5392
5393     int max_fatal = 8;
5394     free_registry();
5395     while (last_alloc)
5396     {
5397         alloc_header* mem = last_alloc + 1;
5398         unfree += my_size(mem);
5399         unfreecnt++;
5400         if (my_release(mem) != 0)
5401             // avoid endless loop when memory is trashed
5402             if (--max_fatal < 0)
5403                 break;
5404     }
5405     dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5406 #endif
5407     g_tls = NULL;
5408     list = NULL;
5409 }