]> git.sesse.net Git - vlc/blob - libs/loader/win32.c
loader: fix a warning
[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(const 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[0x3C];
3940     void*       pbUnknown;              //0x3C
3941     unsigned long cbFormat;             //0x40
3942     char*       pbFormat;               //0x44
3943 } MY_MEDIA_TYPE;
3944 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
3945 {
3946     if (!dest || !src)
3947         return E_POINTER;
3948     memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
3949     if (dest->cbFormat)
3950     {
3951         dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
3952         if (!dest->pbFormat)
3953             return E_OUTOFMEMORY;
3954         memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
3955     }
3956     return S_OK;
3957 }
3958 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
3959 {
3960     if (!dest)
3961         return E_POINTER;
3962
3963     dest->pbUnknown = NULL;
3964     dest->cbFormat = cbFormat;
3965     if (cbFormat)
3966     {
3967         dest->pbFormat = (char*) my_mreq(cbFormat, 0);
3968         if (!dest->pbFormat)
3969             return E_OUTOFMEMORY;
3970     }
3971     else 
3972     {
3973     dest->pbFormat=NULL;
3974     }
3975     return S_OK;
3976 }
3977 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
3978 {
3979     if (!dest)
3980         return E_POINTER;
3981     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3982     return expMoInitMediaType(*dest, cbFormat);
3983 }
3984 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
3985 {
3986     if (!dest)
3987         return E_POINTER;
3988     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
3989     return expMoCopyMediaType(*dest, src);
3990 }
3991 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
3992 {
3993     if (!dest)
3994         return E_POINTER;
3995     if (dest->pbFormat)
3996     {
3997         my_release(dest->pbFormat);
3998         dest->pbFormat = 0;
3999         dest->cbFormat = 0;
4000     }
4001     return S_OK;
4002 }
4003 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
4004 {
4005     if (!dest)
4006         return E_POINTER;
4007     expMoFreeMediaType(dest);
4008     my_release(dest);
4009     return S_OK;
4010 }
4011
4012 static int exp_snprintf( char *str, int size, const char *format, ... )
4013 {
4014       int x;
4015       va_list va;
4016       va_start(va, format);
4017       x=snprintf(str,size,format,va);
4018       dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
4019       va_end(va);
4020       return x;
4021 }
4022
4023 #if 0
4024 static int exp_initterm(int v1, int v2)
4025 {
4026     dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
4027     return 0;
4028 }
4029 #else
4030 /* merged from wine - 2002.04.21 */
4031 typedef void (*_INITTERMFUNC)();
4032 static int exp_initterm(_INITTERMFUNC *start, _INITTERMFUNC *end)
4033 {
4034     dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
4035     while (start < end)
4036     {
4037         if (*start)
4038         {
4039             //printf("call _initfunc: from: %p %d\n", *start);
4040             // ok this trick with push/pop is necessary as otherwice
4041             // edi/esi registers are being trashed
4042             void* p = *start;
4043             __asm__ __volatile__
4044                 (
4045                  "pushl %%ebx           \n\t"
4046                  "pushl %%ecx           \n\t"
4047                  "pushl %%edx           \n\t"
4048                  "pushl %%edi           \n\t"
4049                  "pushl %%esi           \n\t"
4050                  "call  *%%eax          \n\t"
4051                  "popl  %%esi           \n\t"
4052                  "popl  %%edi           \n\t"
4053                  "popl  %%edx           \n\t"
4054                  "popl  %%ecx           \n\t"
4055                  "popl  %%ebx           \n\t"
4056                  :
4057                  : "a"(p)
4058                  : "memory"
4059                 );
4060             //printf("done  %p  %d:%d\n", end);
4061         }
4062         start++;
4063     }
4064     return 0;
4065 }
4066 #endif
4067
4068 static void* exp__dllonexit()
4069 {
4070     // FIXME extract from WINE
4071     return NULL;
4072 }
4073
4074 static int expwsprintfA(char* string, const char* format, ...)
4075 {
4076     va_list va;
4077     int result;
4078     va_start(va, format);
4079     result = vsprintf(string, format, va);
4080     dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
4081     va_end(va);
4082     return result;
4083 }
4084
4085 static int expsprintf(char* str, const char* format, ...)
4086 {
4087     va_list args;
4088     int r;
4089     dbgprintf("sprintf(0x%x, %s)\n", str, format);
4090     va_start(args, format);
4091     r = vsprintf(str, format, args);
4092     va_end(args);
4093     return r;
4094 }
4095 static int expsscanf(const char* str, const char* format, ...)
4096 {
4097     va_list args;
4098     int r;
4099     dbgprintf("sscanf(%s, %s)\n", str, format);
4100     va_start(args, format);
4101     r = vsscanf(str, format, args);
4102     va_end(args);
4103     return r;
4104 }
4105 static void* expfopen(const char* path, const char* mode)
4106 {
4107     printf("fopen: \"%s\"  mode:%s\n", path, mode);
4108     //return fopen(path, mode);
4109     return fdopen(0, mode); // everything on screen
4110 }
4111 static int expfprintf(void* stream, const char* format, ...)
4112 {
4113     va_list args;
4114     int r = 0;
4115     dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
4116 #if 1
4117     va_start(args, format);
4118     r = vfprintf((FILE*) stream, format, args);
4119     va_end(args);
4120 #endif
4121     return r;
4122 }
4123
4124 static int expprintf(const char* format, ...)
4125 {
4126     va_list args;
4127     int r;
4128     dbgprintf("printf(%s, ...)\n", format);
4129     va_start(args, format);
4130     r = vprintf(format, args);
4131     va_end(args);
4132     return r;
4133 }
4134
4135 static char* expgetenv(const char* varname)
4136 {
4137     char* v = getenv(varname);
4138     dbgprintf("getenv(%s) => %s\n", varname, v);
4139     return v;
4140 }
4141
4142 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
4143 {
4144     WCHAR* p = dst;
4145     while ((*p++ = *src++))
4146         ;
4147     return dst;
4148 }
4149
4150 static char* expstrrchr(char* string, int value)
4151 {
4152     char* result=strrchr(string, value);
4153     if(result)
4154         dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4155     else
4156         dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
4157     return result;
4158 }
4159
4160 static char* expstrchr(char* string, int value)
4161 {
4162     char* result=strchr(string, value);
4163     if(result)
4164         dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
4165     else
4166         dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
4167     return result;
4168 }
4169 static int expstrlen(char* str)
4170 {
4171     int result=strlen(str);
4172     dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
4173     return result;
4174 }
4175 static char* expstrcpy(char* str1, const char* str2)
4176 {
4177     char* result= strcpy(str1, str2);
4178     dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
4179     return result;
4180 }
4181 static char* expstrncpy(char* str1, const char* str2, size_t count)
4182 {
4183     char* result= strncpy(str1, str2, count);
4184     dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
4185     return result;
4186 }
4187 static int expstrcmp(const char* str1, const char* str2)
4188 {
4189     int result=strcmp(str1, str2);
4190     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4191     return result;
4192 }
4193 static int expstrncmp(const char* str1, const char* str2,int x)
4194 {
4195     int result=strncmp(str1, str2,x);
4196     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
4197     return result;
4198 }
4199 static char* expstrcat(char* str1, const char* str2)
4200 {
4201     char* result = strcat(str1, str2);
4202     dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
4203     return result;
4204 }
4205 static char* exp_strdup(const char* str1)
4206 {
4207     int l = strlen(str1);
4208     char* result = (char*) my_mreq(l + 1,0);
4209     if (result)
4210         strcpy(result, str1);
4211     dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
4212     return result;
4213 }
4214 static int expisalnum(int c)
4215 {
4216     int result= (int) isalnum(c);
4217     dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
4218     return result;
4219 }
4220 static int expisspace(int c)
4221 {
4222     int result= (int) isspace(c);
4223     dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
4224     return result;
4225 }
4226 static int expisalpha(int c)
4227 {
4228     int result= (int) isalpha(c);
4229     dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
4230     return result;
4231 }
4232 static int expisdigit(int c)
4233 {
4234     int result= (int) isdigit(c);
4235     dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
4236     return result;
4237 }
4238 static void* expmemmove(void* dest, void* src, int n)
4239 {
4240     void* result = memmove(dest, src, n);
4241     dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4242     return result;
4243 }
4244 static int expmemcmp(void* dest, void* src, int n)
4245 {
4246     int result = memcmp(dest, src, n);
4247     dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
4248     return result;
4249 }
4250 static void* expmemcpy(void* dest, void* src, int n)
4251 {
4252     void *result = memcpy(dest, src, n);
4253     dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
4254     return result;
4255 }
4256 static void* expmemset(void* dest, int c, size_t n)
4257 {
4258     void *result = memset(dest, c, n);
4259     dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
4260     return result;
4261 }
4262 static time_t exptime(time_t* t)
4263 {
4264     time_t result = time(t);
4265     dbgprintf("time(0x%x) => %d\n", t, result);
4266     return result;
4267 }
4268
4269 static int exprand(void)
4270 {
4271     return rand();
4272 }
4273
4274 static void expsrand(int seed)
4275 {
4276     srand(seed);
4277 }
4278
4279 #if 1
4280
4281 // preferred compilation with  -O2 -ffast-math !
4282
4283 static double explog10(double x)
4284 {
4285     /*printf("Log10 %f => %f    0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
4286     return log10(x);
4287 }
4288
4289 static double expcos(double x)
4290 {
4291     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4292     return cos(x);
4293 }
4294
4295 /* doens't work */
4296 static long exp_ftol_wrong(double x)
4297 {
4298     return (long) x;
4299 }
4300
4301 #else
4302
4303 static void explog10(void)
4304 {
4305     __asm__ __volatile__
4306         (
4307          "fldl 8(%esp)  \n\t"
4308          "fldln2        \n\t"
4309          "fxch %st(1)   \n\t"
4310          "fyl2x         \n\t"
4311         );
4312 }
4313
4314 static void expcos(void)
4315 {
4316     __asm__ __volatile__
4317         (
4318          "fldl 8(%esp)  \n\t"
4319          "fcos          \n\t"
4320         );
4321 }
4322
4323 #endif
4324
4325 // this seem to be the only how to make this function working properly
4326 // ok - I've spent tremendous amount of time (many many many hours
4327 // of debuging fixing & testing - it's almost unimaginable - kabi
4328
4329 // _ftol - operated on the float value which is already on the FPU stack
4330
4331 static void exp_ftol(void)
4332 {
4333     __asm__ __volatile__
4334         (
4335          "sub $12, %esp         \n\t"
4336          "fstcw   -2(%ebp)      \n\t"
4337          "wait                  \n\t"
4338          "movw    -2(%ebp), %ax \n\t"
4339          "orb    $0x0C, %ah     \n\t"
4340          "movw    %ax, -4(%ebp) \n\t"
4341          "fldcw   -4(%ebp)      \n\t"
4342          "fistpl -12(%ebp)      \n\t"
4343          "fldcw   -2(%ebp)      \n\t"
4344          "movl   -12(%ebp), %eax \n\t"
4345          //Note: gcc 3.03 does not do the following op if it
4346          //      knows that ebp=esp
4347          "movl %ebp, %esp       \n\t"
4348         );
4349 }
4350
4351 #define FPU_DOUBLES(var1,var2) double var1,var2; \
4352   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
4353   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
4354
4355 static double exp_CIpow(void)
4356 {
4357     FPU_DOUBLES(x,y);
4358
4359     dbgprintf("_CIpow(%lf, %lf)\n", x, y);
4360     return pow(x, y);
4361 }
4362
4363 static double exppow(double x, double y)
4364 {
4365     /*printf("Pow %f  %f    0x%Lx  0x%Lx  => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
4366     return pow(x, y);
4367 }
4368
4369 static double expldexp(double x, int expo)
4370 {
4371     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4372     return ldexp(x, expo);
4373 }
4374
4375 static double expfrexp(double x, int* expo)
4376 {
4377     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
4378     return frexp(x, expo);
4379 }
4380
4381
4382
4383 static int exp_stricmp(const char* s1, const char* s2)
4384 {
4385     return strcasecmp(s1, s2);
4386 }
4387
4388 /* from declaration taken from Wine sources - this fountion seems to be
4389  * undocumented in any M$ doc */
4390 static int exp_setjmp3(void* jmpbuf, int x)
4391 {
4392     //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
4393     //return 0;
4394     __asm__ __volatile__
4395         (
4396          //"mov 4(%%esp), %%edx \n\t"
4397          "mov (%%esp), %%eax   \n\t"
4398          "mov %%eax, (%%edx)    \n\t" // store ebp
4399
4400          //"mov %%ebp, (%%edx)  \n\t"
4401          "mov %%ebx, 4(%%edx)   \n\t"
4402          "mov %%edi, 8(%%edx)   \n\t"
4403          "mov %%esi, 12(%%edx)  \n\t"
4404          "mov %%esp, 16(%%edx)  \n\t"
4405
4406          "mov 4(%%esp), %%eax   \n\t"
4407          "mov %%eax, 20(%%edx)  \n\t"
4408
4409          "movl $0x56433230, 32(%%edx)   \n\t" // VC20 ??
4410          "movl $0, 36(%%edx)    \n\t"
4411          : // output
4412          : "d"(jmpbuf) // input
4413          : "eax"
4414         );
4415 #if 1
4416     __asm__ __volatile__
4417         (
4418          "mov %%fs:0, %%eax     \n\t" // unsure
4419          "mov %%eax, 24(%%edx)  \n\t"
4420          "cmp $0xffffffff, %%eax \n\t"
4421          "jnz l1                \n\t"
4422          "mov %%eax, 28(%%edx)  \n\t"
4423          "l1:                   \n\t"
4424          :
4425          :
4426          : "eax"
4427         );
4428 #endif
4429
4430         return 0;
4431 }
4432
4433 static DWORD WINAPI expGetCurrentProcessId(void)
4434 {
4435     dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
4436     return getpid(); //(DWORD)NtCurrentTeb()->pid;
4437 }
4438
4439
4440 typedef struct {
4441     UINT        wPeriodMin;
4442     UINT        wPeriodMax;
4443 } TIMECAPS, *LPTIMECAPS;
4444
4445 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
4446 {
4447     dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
4448
4449     lpCaps->wPeriodMin = 1;
4450     lpCaps->wPeriodMax = 65535;
4451     return 0;
4452 }
4453
4454 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
4455 {
4456     dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
4457
4458     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4459     return 0;
4460 }
4461
4462 #ifdef QTX
4463 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
4464 {
4465     dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
4466
4467     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
4468     return 0;
4469 }
4470 #endif
4471
4472 static void WINAPI expGlobalMemoryStatus(
4473             LPMEMORYSTATUS lpmem
4474 ) {
4475     static MEMORYSTATUS cached_memstatus;
4476     static int cache_lastchecked = 0;
4477     SYSTEM_INFO si;
4478     FILE *f;
4479
4480     if (time(NULL)==cache_lastchecked) {
4481         memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
4482         return;
4483     }
4484
4485 #if 1
4486     f = fopen( "/proc/meminfo", "r" );
4487     if (f)
4488     {
4489         char buffer[256];
4490         int total, used, free, shared, buffers, cached;
4491
4492         lpmem->dwLength = sizeof(MEMORYSTATUS);
4493         lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
4494         lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
4495         while (fgets( buffer, sizeof(buffer), f ))
4496         {
4497             /* old style /proc/meminfo ... */
4498             if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
4499             {
4500                 lpmem->dwTotalPhys += total;
4501                 lpmem->dwAvailPhys += free + buffers + cached;
4502             }
4503             if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
4504             {
4505                 lpmem->dwTotalPageFile += total;
4506                 lpmem->dwAvailPageFile += free;
4507             }
4508
4509             /* new style /proc/meminfo ... */
4510             if (sscanf(buffer, "MemTotal: %d", &total))
4511                 lpmem->dwTotalPhys = total*1024;
4512             if (sscanf(buffer, "MemFree: %d", &free))
4513                 lpmem->dwAvailPhys = free*1024;
4514             if (sscanf(buffer, "SwapTotal: %d", &total))
4515                 lpmem->dwTotalPageFile = total*1024;
4516             if (sscanf(buffer, "SwapFree: %d", &free))
4517                 lpmem->dwAvailPageFile = free*1024;
4518             if (sscanf(buffer, "Buffers: %d", &buffers))
4519                 lpmem->dwAvailPhys += buffers*1024;
4520             if (sscanf(buffer, "Cached: %d", &cached))
4521                 lpmem->dwAvailPhys += cached*1024;
4522         }
4523         fclose( f );
4524
4525         if (lpmem->dwTotalPhys)
4526         {
4527             DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
4528             DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
4529             lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
4530                                       / (TotalPhysical / 100);
4531         }
4532     } else
4533 #endif
4534     {
4535         /* FIXME: should do something for other systems */
4536         lpmem->dwMemoryLoad    = 0;
4537         lpmem->dwTotalPhys     = 16*1024*1024;
4538         lpmem->dwAvailPhys     = 16*1024*1024;
4539         lpmem->dwTotalPageFile = 16*1024*1024;
4540         lpmem->dwAvailPageFile = 16*1024*1024;
4541     }
4542     expGetSystemInfo(&si);
4543     lpmem->dwTotalVirtual  = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
4544     /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
4545     lpmem->dwAvailVirtual  = lpmem->dwTotalVirtual-64*1024;
4546     memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
4547     cache_lastchecked = time(NULL);
4548
4549     /* it appears some memory display programs want to divide by these values */
4550     if(lpmem->dwTotalPageFile==0)
4551         lpmem->dwTotalPageFile++;
4552
4553     if(lpmem->dwAvailPageFile==0)
4554         lpmem->dwAvailPageFile++;
4555 }
4556
4557 /**********************************************************************
4558  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
4559  *
4560  * RETURNS
4561  *    Success: TRUE
4562  *    Failure: FALSE
4563  */
4564 static WIN_BOOL WINAPI expSetThreadPriority(
4565     HANDLE hthread, /* [in] Handle to thread */
4566     INT priority)   /* [in] Thread priority level */
4567 {
4568     dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
4569     return TRUE;
4570 }
4571
4572 static void WINAPI expExitProcess( DWORD status )
4573 {
4574     printf("EXIT - code %ld\n",status);
4575     exit(status);
4576 }
4577
4578 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
4579     printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
4580 #ifdef QTX
4581     if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
4582         return IDIGNORE;
4583 #endif
4584     return IDOK;
4585 }
4586
4587 /* these are needed for mss1 */
4588
4589 /* defined in stubs.s */
4590 void exp_EH_prolog(void);
4591
4592 #include <netinet/in.h>
4593 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
4594 {
4595 //    dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
4596     return htonl(hostlong);
4597 }
4598
4599 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
4600 {
4601 //    dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
4602     return ntohl(netlong);
4603 }
4604 static void WINAPI expVariantInit(void* p)
4605 {
4606     printf("InitCommonControls called!\n");
4607     return;
4608 }
4609
4610 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
4611 {
4612     dbgprintf("RegisterClassA(%p) => random id\n", wc);
4613     return time(NULL); /* be precise ! */
4614 }
4615
4616 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
4617 {
4618     dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
4619     return 0;
4620 }
4621
4622 #ifdef QTX
4623 /* should be fixed bcs it's not fully strlen equivalent */
4624 static int expSysStringByteLen(void *str)
4625 {
4626     dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
4627     return strlen(str);
4628 }
4629
4630 static int expDirectDrawCreate(void)
4631 {
4632     dbgprintf("DirectDrawCreate(...) => NULL\n");
4633     return 0;
4634 }
4635
4636 #if 1
4637 typedef struct tagPALETTEENTRY { 
4638     BYTE peRed; 
4639     BYTE peGreen; 
4640     BYTE peBlue; 
4641     BYTE peFlags; 
4642 } PALETTEENTRY; 
4643
4644 /* reversed the first 2 entries */
4645 typedef struct tagLOGPALETTE { 
4646     WORD         palNumEntries; 
4647     WORD         palVersion; 
4648     PALETTEENTRY palPalEntry[1]; 
4649 } LOGPALETTE; 
4650
4651 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
4652 {
4653     HPALETTE test;
4654     int i;
4655     
4656     dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
4657
4658     i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
4659     test = (HPALETTE)malloc(i);
4660     memcpy((void *)test, lpgpl, i);
4661
4662     return test;
4663 }
4664 #else
4665 static int expCreatePalette(void)
4666 {
4667     dbgprintf("CreatePalette(...) => NULL\n");
4668     return NULL;
4669 }
4670 #endif
4671
4672 static int WINAPI expGetClientRect(HWND win, RECT *r)
4673 {
4674     dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
4675     r->right = PSEUDO_SCREEN_WIDTH;
4676     r->left = 0;
4677     r->bottom = PSEUDO_SCREEN_HEIGHT;
4678     r->top = 0;
4679     return 1;
4680 }
4681
4682 #if 0
4683 typedef struct tagPOINT { 
4684     LONG x; 
4685     LONG y; 
4686 } POINT, *PPOINT; 
4687 #endif
4688
4689 static int WINAPI expClientToScreen(HWND win, POINT *p)
4690 {
4691     dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
4692     p->x = 0;
4693     p->y = 0;
4694     return 1;
4695 }
4696 #endif
4697
4698 /* for m3jpeg */
4699 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
4700 {
4701     dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
4702     return 0;
4703 }
4704
4705 static int WINAPI expMessageBeep(int type)
4706 {
4707     dbgprintf("MessageBeep(%d) => 1\n", type);
4708     return 1;
4709 }
4710
4711 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
4712     HWND parent, void *dialog_func, void *init_param)
4713 {
4714     dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
4715         inst, name, name, parent, dialog_func, init_param);
4716     return 0x42424242;
4717 }
4718
4719 /* needed by imagepower mjpeg2k */
4720 static void *exprealloc(void *ptr, size_t size)
4721 {
4722     dbgprintf("realloc(0x%x, %x)\n", ptr, size);
4723     if (!ptr)
4724         return my_mreq(size,0);
4725     else
4726         return my_realloc(ptr, size);        
4727 }
4728
4729 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
4730 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
4731 {
4732     return 1;
4733 }
4734
4735 static double expfloor(double x)
4736 {
4737     dbgprintf("floor(%lf)\n", x);
4738     return floor(x);
4739 }
4740
4741 #define FPU_DOUBLE(var) double var; \
4742   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
4743
4744 static double exp_CIcos(void)
4745 {
4746     FPU_DOUBLE(x);
4747
4748     dbgprintf("_CIcos(%lf)\n", x);
4749     return cos(x);
4750 }
4751
4752 static double exp_CIsin(void)
4753 {
4754     FPU_DOUBLE(x);
4755
4756     dbgprintf("_CIsin(%lf)\n", x);
4757     return sin(x);
4758 }
4759
4760 struct exports
4761 {
4762     char name[64];
4763     int id;
4764     void* func;
4765 };
4766 struct libs
4767 {
4768     char name[64];
4769     int length;
4770     struct exports* exps;
4771 };
4772
4773 #define FF(X,Y) \
4774     {#X, Y, (void*)exp##X},
4775
4776 struct exports exp_kernel32[]=
4777 {
4778     FF(GetVolumeInformationA,-1)
4779     FF(GetDriveTypeA,-1)
4780     FF(GetLogicalDriveStringsA,-1)
4781     FF(IsBadWritePtr, 357)
4782     FF(IsBadReadPtr, 354)
4783     FF(IsBadStringPtrW, -1)
4784     FF(IsBadStringPtrA, -1)
4785     FF(DisableThreadLibraryCalls, -1)
4786     FF(CreateThread, -1)
4787     FF(CreateEventA, -1)
4788     FF(SetEvent, -1)
4789     FF(ResetEvent, -1)
4790     FF(WaitForSingleObject, -1)
4791 #ifdef QTX
4792     FF(WaitForMultipleObjects, -1)
4793     FF(ExitThread, -1)
4794     FF(CreateMutexA,-1)
4795     FF(ReleaseMutex,-1)
4796 #endif
4797     FF(GetSystemInfo, -1)
4798     FF(GetVersion, 332)
4799     FF(HeapCreate, 461)
4800     FF(HeapAlloc, -1)
4801     FF(HeapDestroy, -1)
4802     FF(HeapFree, -1)
4803     FF(HeapSize, -1)
4804     FF(HeapReAlloc,-1)
4805     FF(GetProcessHeap, -1)
4806     FF(VirtualAlloc, -1)
4807     FF(VirtualFree, -1)
4808     FF(InitializeCriticalSection, -1)
4809     FF(EnterCriticalSection, -1)
4810     FF(LeaveCriticalSection, -1)
4811     FF(DeleteCriticalSection, -1)
4812     FF(TlsAlloc, -1)
4813     FF(TlsFree, -1)
4814     FF(TlsGetValue, -1)
4815     FF(TlsSetValue, -1)
4816     FF(GetCurrentThreadId, -1)
4817     FF(GetCurrentProcess, -1)
4818     FF(LocalAlloc, -1)
4819     FF(LocalReAlloc,-1)
4820     FF(LocalLock, -1)
4821     FF(GlobalAlloc, -1)
4822     FF(GlobalReAlloc, -1)
4823     FF(GlobalLock, -1)
4824     FF(GlobalSize, -1)
4825     FF(MultiByteToWideChar, 427)
4826     FF(WideCharToMultiByte, -1)
4827     FF(GetVersionExA, -1)
4828     FF(CreateSemaphoreA, -1)
4829     FF(QueryPerformanceCounter, -1)
4830     FF(QueryPerformanceFrequency, -1)
4831     FF(LocalHandle, -1)
4832     FF(LocalUnlock, -1)
4833     FF(LocalFree, -1)
4834     FF(GlobalHandle, -1)
4835     FF(GlobalUnlock, -1)
4836     FF(GlobalFree, -1)
4837     FF(LoadResource, -1)
4838     FF(ReleaseSemaphore, -1)
4839     FF(FindResourceA, -1)
4840     FF(LockResource, -1)
4841     FF(FreeResource, -1)
4842     FF(SizeofResource, -1)
4843     FF(CloseHandle, -1)
4844     FF(GetCommandLineA, -1)
4845     FF(GetEnvironmentStringsW, -1)
4846     FF(FreeEnvironmentStringsW, -1)
4847     FF(FreeEnvironmentStringsA, -1)
4848     FF(GetEnvironmentStrings, -1)
4849     FF(GetStartupInfoA, -1)
4850     FF(GetStdHandle, -1)
4851     FF(GetFileType, -1)
4852 #ifdef QTX
4853     FF(GetFileAttributesA, -1)
4854 #endif
4855     FF(SetHandleCount, -1)
4856     FF(GetACP, -1)
4857     FF(GetModuleFileNameA, -1)
4858     FF(SetUnhandledExceptionFilter, -1)
4859     FF(LoadLibraryA, -1)
4860     FF(GetProcAddress, -1)
4861     FF(FreeLibrary, -1)
4862     FF(CreateFileMappingA, -1)
4863     FF(OpenFileMappingA, -1)
4864     FF(MapViewOfFile, -1)
4865     FF(UnmapViewOfFile, -1)
4866     FF(Sleep, -1)
4867     FF(GetModuleHandleA, -1)
4868     FF(GetProfileIntA, -1)
4869     FF(GetPrivateProfileIntA, -1)
4870     FF(GetPrivateProfileStringA, -1)
4871     FF(WritePrivateProfileStringA, -1)
4872     FF(GetLastError, -1)
4873     FF(SetLastError, -1)
4874     FF(InterlockedIncrement, -1)
4875     FF(InterlockedDecrement, -1)
4876     FF(GetTimeZoneInformation, -1)
4877     FF(OutputDebugStringA, -1)
4878     FF(GetLocalTime, -1)
4879     FF(GetSystemTime, -1)
4880     FF(GetSystemTimeAsFileTime, -1)
4881     FF(GetEnvironmentVariableA, -1)
4882     FF(SetEnvironmentVariableA, -1)
4883     FF(RtlZeroMemory,-1)
4884     FF(RtlMoveMemory,-1)
4885     FF(RtlFillMemory,-1)
4886     FF(GetTempPathA,-1)
4887     FF(FindFirstFileA,-1)
4888     FF(FindNextFileA,-1)
4889     FF(FindClose,-1)
4890     FF(FileTimeToLocalFileTime,-1)
4891     FF(DeleteFileA,-1)
4892     FF(ReadFile,-1)
4893     FF(WriteFile,-1)
4894     FF(SetFilePointer,-1)
4895     FF(GetTempFileNameA,-1)
4896     FF(CreateFileA,-1)
4897     FF(GetSystemDirectoryA,-1)
4898     FF(GetWindowsDirectoryA,-1)
4899 #ifdef QTX
4900     FF(GetCurrentDirectoryA,-1)
4901     FF(SetCurrentDirectoryA,-1)
4902     FF(CreateDirectoryA,-1)
4903 #endif
4904     FF(GetShortPathNameA,-1)
4905     FF(GetFullPathNameA,-1)
4906     FF(SetErrorMode, -1)
4907     FF(IsProcessorFeaturePresent, -1)
4908     FF(GetProcessAffinityMask, -1)
4909     FF(InterlockedExchange, -1)
4910     FF(InterlockedCompareExchange, -1)
4911     FF(MulDiv, -1)
4912     FF(lstrcmpiA, -1)
4913     FF(lstrlenA, -1)
4914     FF(lstrcpyA, -1)
4915     FF(lstrcatA, -1)
4916     FF(lstrcpynA,-1)
4917     FF(GetProcessVersion,-1)
4918     FF(GetCurrentThread,-1)
4919     FF(GetOEMCP,-1)
4920     FF(GetCPInfo,-1)
4921     FF(DuplicateHandle,-1)
4922     FF(GetTickCount, -1)
4923     FF(SetThreadAffinityMask,-1)
4924     FF(GetCurrentProcessId,-1)
4925     FF(GlobalMemoryStatus,-1)
4926     FF(SetThreadPriority,-1)
4927     FF(ExitProcess,-1)
4928     {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
4929     FF(SetThreadIdealProcessor,-1)
4930 };
4931
4932 struct exports exp_msvcrt[]={
4933     FF(malloc, -1)
4934     FF(_initterm, -1)
4935     FF(__dllonexit, -1)
4936     FF(_snprintf,-1)
4937     FF(free, -1)
4938     {"??3@YAXPAX@Z", -1, expdelete},
4939     {"??2@YAPAXI@Z", -1, expnew},
4940     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
4941     FF(strrchr, -1)
4942     FF(strchr, -1)
4943     FF(strlen, -1)
4944     FF(strcpy, -1)
4945     FF(strncpy, -1)
4946     FF(wcscpy, -1)
4947     FF(strcmp, -1)
4948     FF(strncmp, -1)
4949     FF(strcat, -1)
4950     FF(_stricmp,-1)
4951     FF(_strdup,-1)
4952     FF(_setjmp3,-1)
4953     FF(isalnum, -1)
4954     FF(isspace, -1)
4955     FF(isalpha, -1)
4956     FF(isdigit, -1)
4957     FF(memmove, -1)
4958     FF(memcmp, -1)
4959     FF(memset, -1)
4960     FF(memcpy, -1)
4961     FF(time, -1)
4962     FF(rand, -1)
4963     FF(srand, -1)
4964     FF(log10, -1)
4965     FF(pow, -1)
4966     FF(cos, -1)
4967     FF(_ftol,-1)
4968     FF(_CIpow,-1)
4969     FF(_CIcos,-1)
4970     FF(_CIsin,-1)
4971     FF(ldexp,-1)
4972     FF(frexp,-1)
4973     FF(sprintf,-1)
4974     FF(sscanf,-1)
4975     FF(fopen,-1)
4976     FF(fprintf,-1)
4977     FF(printf,-1)
4978     FF(getenv,-1)
4979     FF(floor,-1)
4980 /* needed by frapsvid.dll */
4981     {"strstr",-1,(char *)&strstr},
4982     {"qsort",-1,(void *)&qsort},
4983 #ifdef MPLAYER
4984     FF(_EH_prolog,-1)
4985 #endif
4986     FF(calloc,-1)
4987     {"ceil",-1,(void*)&ceil},
4988 /* needed by imagepower mjpeg2k */
4989     {"clock",-1,(void*)&clock},
4990     {"memchr",-1,(void*)&memchr},
4991     {"vfprintf",-1,(void*)&vfprintf},
4992 //    {"realloc",-1,(void*)&realloc},
4993     FF(realloc,-1)
4994     {"puts",-1,(void*)&puts}
4995 };
4996 struct exports exp_winmm[]={
4997     FF(GetDriverModuleHandle, -1)
4998     FF(timeGetTime, -1)
4999     FF(DefDriverProc, -1)
5000     FF(OpenDriverA, -1)
5001     FF(OpenDriver, -1)
5002     FF(timeGetDevCaps, -1)
5003     FF(timeBeginPeriod, -1)
5004 #ifdef QTX
5005     FF(timeEndPeriod, -1)
5006     FF(waveOutGetNumDevs, -1)
5007 #endif
5008 };
5009 struct exports exp_user32[]={
5010     FF(LoadIconA,-1)
5011     FF(LoadStringA, -1)
5012     FF(wsprintfA, -1)
5013     FF(GetDC, -1)
5014     FF(GetDesktopWindow, -1)
5015     FF(ReleaseDC, -1)
5016     FF(IsRectEmpty, -1)
5017     FF(LoadCursorA,-1)
5018     FF(SetCursor,-1)
5019     FF(GetCursorPos,-1)
5020 #ifdef QTX
5021     FF(ShowCursor,-1)
5022 #endif
5023     FF(RegisterWindowMessageA,-1)
5024     FF(GetSystemMetrics,-1)
5025     FF(GetSysColor,-1)
5026     FF(GetSysColorBrush,-1)
5027     FF(GetWindowDC, -1)
5028     FF(DrawTextA, -1)
5029     FF(MessageBoxA, -1)
5030     FF(RegisterClassA, -1)
5031     FF(UnregisterClassA, -1)
5032 #ifdef QTX
5033     FF(GetWindowRect, -1)
5034     FF(MonitorFromWindow, -1)
5035     FF(MonitorFromRect, -1)
5036     FF(MonitorFromPoint, -1)
5037     FF(EnumDisplayMonitors, -1)
5038     FF(GetMonitorInfoA, -1)
5039     FF(EnumDisplayDevicesA, -1)
5040     FF(GetClientRect, -1)
5041     FF(ClientToScreen, -1)
5042     FF(IsWindowVisible, -1)
5043     FF(GetActiveWindow, -1)
5044     FF(GetClassNameA, -1)
5045     FF(GetClassInfoA, -1)
5046     FF(GetWindowLongA, -1)
5047     FF(EnumWindows, -1)
5048     FF(GetWindowThreadProcessId, -1)
5049     FF(CreateWindowExA, -1)
5050 #endif
5051     FF(MessageBeep, -1)
5052     FF(DialogBoxParamA, -1)
5053 };
5054 struct exports exp_advapi32[]={
5055     FF(RegCloseKey, -1)
5056     FF(RegCreateKeyA, -1)
5057     FF(RegCreateKeyExA, -1)
5058     FF(RegEnumKeyExA, -1)
5059     FF(RegEnumValueA, -1)
5060     FF(RegOpenKeyA, -1)
5061     FF(RegOpenKeyExA, -1)
5062     FF(RegQueryValueExA, -1)
5063     FF(RegSetValueExA, -1)
5064     FF(RegQueryInfoKeyA, -1)
5065 };
5066 struct exports exp_gdi32[]={
5067     FF(CreateCompatibleDC, -1)
5068     FF(CreateFontA, -1)
5069     FF(DeleteDC, -1)
5070     FF(DeleteObject, -1)
5071     FF(GetDeviceCaps, -1)
5072     FF(GetSystemPaletteEntries, -1)
5073 #ifdef QTX
5074     FF(CreatePalette, -1)
5075     FF(GetObjectA, -1)
5076     FF(CreateRectRgn, -1)
5077 #endif
5078 };
5079 struct exports exp_version[]={
5080     FF(GetFileVersionInfoSizeA, -1)
5081 };
5082 struct exports exp_ole32[]={
5083     FF(CoCreateFreeThreadedMarshaler,-1)
5084     FF(CoCreateInstance, -1)
5085     FF(CoInitialize, -1)
5086     FF(CoTaskMemAlloc, -1)
5087     FF(CoTaskMemFree, -1)
5088     FF(StringFromGUID2, -1)
5089 };
5090 // do we really need crtdll ???
5091 // msvcrt is the correct place probably...
5092 struct exports exp_crtdll[]={
5093     FF(memcpy, -1)
5094     FF(wcscpy, -1)
5095 };
5096 struct exports exp_comctl32[]={
5097     FF(StringFromGUID2, -1)
5098     FF(InitCommonControls, 17)
5099 #ifdef QTX
5100     FF(CreateUpDownControl, 16)
5101 #endif
5102 };
5103 struct exports exp_wsock32[]={
5104     FF(htonl,8)
5105     FF(ntohl,14)
5106 };
5107 struct exports exp_msdmo[]={
5108     FF(memcpy, -1) // just test
5109     FF(MoCopyMediaType, -1)
5110     FF(MoCreateMediaType, -1)
5111     FF(MoDeleteMediaType, -1)
5112     FF(MoDuplicateMediaType, -1)
5113     FF(MoFreeMediaType, -1)
5114     FF(MoInitMediaType, -1)
5115 };
5116 struct exports exp_oleaut32[]={
5117     FF(VariantInit, 8)
5118 #ifdef QTX
5119     FF(SysStringByteLen, 149)
5120 #endif
5121 };
5122
5123 /*  realplayer8:
5124         DLL Name: PNCRT.dll
5125         vma:  Hint/Ord Member-Name
5126         22ff4     615  free
5127         2302e     250  _ftol
5128         22fea     666  malloc
5129         2303e     609  fprintf
5130         2305e     167  _adjust_fdiv
5131         23052     280  _initterm
5132
5133         22ffc     176  _beginthreadex
5134         23036     284  _iob
5135         2300e      85  __CxxFrameHandler
5136         23022     411  _purecall
5137 */
5138 #ifdef REALPLAYER
5139 struct exports exp_pncrt[]={
5140     FF(malloc, -1) // just test
5141     FF(free, -1) // just test
5142     FF(fprintf, -1) // just test
5143     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
5144     FF(_ftol,-1)
5145     FF(_initterm, -1)
5146     {"??3@YAXPAX@Z", -1, expdelete},
5147     {"??2@YAPAXI@Z", -1, expnew},
5148     FF(__dllonexit, -1)
5149     FF(strncpy, -1)
5150     FF(_CIpow,-1)
5151     FF(calloc,-1)
5152     FF(memmove, -1)
5153 };
5154 #endif
5155
5156 #ifdef QTX
5157 struct exports exp_ddraw[]={
5158     FF(DirectDrawCreate, -1)
5159 };
5160 #endif
5161
5162 struct exports exp_comdlg32[]={
5163     FF(GetOpenFileNameA, -1)
5164 };
5165
5166 #define LL(X) \
5167     {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
5168
5169 struct libs libraries[]={
5170     LL(kernel32)
5171     LL(msvcrt)
5172     LL(winmm)
5173     LL(user32)
5174     LL(advapi32)
5175     LL(gdi32)
5176     LL(version)
5177     LL(ole32)
5178     LL(oleaut32)
5179     LL(crtdll)
5180     LL(comctl32)
5181     LL(wsock32)
5182     LL(msdmo)
5183 #ifdef REALPLAYER
5184     LL(pncrt)
5185 #endif
5186 #ifdef QTX
5187     LL(ddraw)
5188 #endif
5189     LL(comdlg32)
5190 };
5191
5192 static void ext_stubs(void)
5193 {
5194     // expects:
5195     //  ax  position index
5196     //  cx  address of printf function
5197 #if 1
5198     __asm__ __volatile__
5199         (
5200          "push %%edx            \n\t"
5201          "movl $0xdeadbeef, %%eax \n\t"
5202          "movl $0xdeadbeef, %%edx \n\t"
5203          "shl $5, %%eax         \n\t"                   // ax * 32
5204          "addl $0xdeadbeef, %%eax \n\t"                 // overwrite export_names
5205          "pushl %%eax           \n\t"
5206          "pushl $0xdeadbeef     \n\t"                   // overwrite called_unk
5207          "call *%%edx           \n\t"                   // printf (via dx)
5208          "addl $8, %%esp        \n\t"
5209          "xorl %%eax, %%eax     \n\t"
5210          "pop %%edx             \n\t"
5211          :
5212          :
5213          : "eax"
5214         );
5215 #else
5216     __asm__ __volatile__
5217         (
5218          "push %%edx            \n\t"
5219          "movl $0, %%eax        \n\t"
5220          "movl $0, %%edx        \n\t"
5221          "shl $5, %%eax         \n\t"                   // ax * 32
5222          "addl %0, %%eax        \n\t"
5223          "pushl %%eax           \n\t"
5224          "pushl %1              \n\t"
5225          "call *%%edx           \n\t"                   // printf (via dx)
5226          "addl $8, %%esp        \n\t"
5227          "xorl %%eax, %%eax     \n\t"
5228          "pop %%edx             \n\t"
5229          ::"m"(*export_names), "m"(*called_unk)
5230         : "memory", "edx", "eax"
5231         );
5232 #endif
5233
5234 }
5235
5236 //static void add_stub(int pos)
5237
5238 extern int unk_exp1;
5239 static int pos=0;
5240 static char extcode[20000];// place for 200 unresolved exports
5241 static const char* called_unk = "Called unk_%s\n";
5242
5243 static void* add_stub(void)
5244 {
5245     // generated code in runtime!
5246     char* answ = (char*)extcode+pos*0x30;
5247 #if 0
5248     memcpy(answ, &unk_exp1, 0x64);
5249     *(int*)(answ+9)=pos;
5250     *(int*)(answ+47)-=((int)answ-(int)&unk_exp1);
5251 #endif
5252     memcpy(answ, ext_stubs, 0x2f); // 0x2c is current size
5253     //answ[4] = 0xb8; // movl $0, eax  (0xb8 0x00000000)
5254     *((int*) (answ + 5)) = pos;
5255     //answ[9] = 0xba; // movl $0, edx  (0xba 0x00000000)
5256     *((long*) (answ + 10)) = (long)printf;
5257     //answ[17] = 0x05; // addl $0, eax  (0x05 0x00000000)
5258     *((long*) (answ + 18)) = (long)export_names;
5259     //answ[23] = 0x68; // pushl $0  (0x68 0x00000000)
5260     *((long*) (answ + 24)) = (long)called_unk;
5261     pos++;
5262     return (void*)answ;
5263 }
5264
5265 void* LookupExternal(const char* library, int ordinal)
5266 {
5267     int i,j;
5268     if(library==0)
5269     {
5270         printf("ERROR: library=0\n");
5271         return (void*)ext_unknown;
5272     }
5273     //    printf("%x %x\n", &unk_exp1, &unk_exp2);
5274
5275     dbgprintf("External func %s:%d\n", library, ordinal);
5276
5277     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5278     {
5279         if(strcasecmp(library, libraries[i].name))
5280             continue;
5281         for(j=0; j<libraries[i].length; j++)
5282         {
5283             if(ordinal!=libraries[i].exps[j].id)
5284                 continue;
5285             //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
5286             return libraries[i].exps[j].func;
5287         }
5288     }
5289
5290 #ifndef LOADLIB_TRY_NATIVE
5291   /* hack for truespeech and vssh264*/
5292   if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
5293 #endif
5294     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5295     {
5296         int hand;
5297         WINE_MODREF *wm;
5298         void *func;
5299
5300         hand = LoadLibraryA(library);
5301         if (!hand)
5302             goto no_dll;
5303         wm = MODULE32_LookupHMODULE(hand);
5304         if (!wm)
5305         {
5306             FreeLibrary(hand);
5307             goto no_dll;
5308         }
5309         func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
5310         if (!func)
5311         {
5312             printf("No such ordinal in external dll\n");
5313             FreeLibrary((int)hand);
5314             goto no_dll;
5315         }
5316
5317         printf("External dll loaded (offset: 0x%x, func: %p)\n",
5318                hand, func);
5319         return func;
5320     }
5321
5322 no_dll:
5323     if(pos>150)return 0;
5324     sprintf(export_names[pos], "%s:%d", library, ordinal);
5325     return add_stub();
5326 }
5327
5328 void* LookupExternalByName(const char* library, const char* name)
5329 {
5330     char* answ;
5331     int i,j;
5332     //   return (void*)ext_unknown;
5333     if(library==0)
5334     {
5335         printf("ERROR: library=0\n");
5336         return (void*)ext_unknown;
5337     }
5338     if(name==0)
5339     {
5340         printf("ERROR: name=0\n");
5341         return (void*)ext_unknown;
5342     }
5343     dbgprintf("External func %s:%s\n", library, name);
5344     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
5345     {
5346         if(strcasecmp(library, libraries[i].name))
5347             continue;
5348         for(j=0; j<libraries[i].length; j++)
5349         {
5350             if(strcmp(name, libraries[i].exps[j].name))
5351                 continue;
5352             //      printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
5353             return libraries[i].exps[j].func;
5354         }
5355     }
5356
5357 #ifndef LOADLIB_TRY_NATIVE
5358   /* hack for vss h264 */
5359   if (!strcmp(library,"vssh264core.dll"))
5360 #endif
5361     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
5362     {
5363         int hand;
5364         WINE_MODREF *wm;
5365         void *func;
5366
5367         hand = LoadLibraryA(library);
5368         if (!hand)
5369             goto no_dll_byname;
5370         wm = MODULE32_LookupHMODULE(hand);
5371         if (!wm)
5372         {
5373             FreeLibrary(hand);
5374             goto no_dll_byname;
5375         }
5376         func = PE_FindExportedFunction(wm, name, 0);
5377         if (!func)
5378         {
5379             printf("No such name in external dll\n");
5380             FreeLibrary((int)hand);
5381             goto no_dll_byname;
5382         }
5383
5384         printf("External dll loaded (offset: 0x%x, func: %p)\n",
5385                hand, func);
5386         return func;
5387     }
5388
5389 no_dll_byname:
5390     if(pos>150)return 0;// to many symbols
5391     strcpy(export_names[pos], name);
5392     return add_stub();
5393 }
5394
5395 void my_garbagecollection(void)
5396 {
5397 #ifdef GARBAGE
5398     int unfree = 0, unfreecnt = 0;
5399
5400     int max_fatal = 8;
5401     free_registry();
5402     while (last_alloc)
5403     {
5404         alloc_header* mem = last_alloc + 1;
5405         unfree += my_size(mem);
5406         unfreecnt++;
5407         if (my_release(mem) != 0)
5408             // avoid endless loop when memory is trashed
5409             if (--max_fatal < 0)
5410                 break;
5411     }
5412     dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
5413 #endif
5414     g_tls = NULL;
5415     list = NULL;
5416 }