Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

win32.c

00001 /***********************************************************
00002 
00003 Win32 emulation code. Functions that emulate
00004 responses from corresponding Win32 API calls.
00005 Since we are not going to be able to load
00006 virtually any DLL, we can only implement this
00007 much, adding needed functions with each new codec.
00008 
00009 Basic principle of implementation: it's not good
00010 for DLL to know too much about its environment.
00011 
00012 ************************************************************/
00013 
00014 /*
00015  * Modified for use with MPlayer, detailed CVS changelog at
00016  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
00017  * $Id: win32.c 11593 2005-06-28 18:02:01Z courmisch $
00018  */
00019 
00020 #include "config.h"
00021 
00022 #ifdef MPLAYER
00023 #ifdef USE_QTX_CODECS
00024 #define QTX
00025 #endif
00026 #define REALPLAYER
00027 //#define LOADLIB_TRY_NATIVE
00028 #endif
00029 
00030 #ifdef QTX
00031 #define PSEUDO_SCREEN_WIDTH     /*640*/800
00032 #define PSEUDO_SCREEN_HEIGHT    /*480*/600
00033 #endif
00034 
00035 #include "wine/winbase.h"
00036 #include "wine/winreg.h"
00037 #include "wine/winnt.h"
00038 #include "wine/winerror.h"
00039 #include "wine/debugtools.h"
00040 #include "wine/module.h"
00041 #include "wine/winuser.h"
00042 
00043 #include <stdio.h>
00044 #include "win32.h"
00045 
00046 #include "registry.h"
00047 #include "loader.h"
00048 #include "com.h"
00049 #include "ext.h"
00050 
00051 #include <stdlib.h>
00052 #include <assert.h>
00053 #include <stdarg.h>
00054 #include <ctype.h>
00055 #include <pthread.h>
00056 #include <errno.h>
00057 #ifdef HAVE_MALLOC_H
00058 #include <malloc.h>
00059 #endif
00060 #include <time.h>
00061 #include <math.h>
00062 #include <unistd.h>
00063 #include <fcntl.h>
00064 #include <sys/types.h>
00065 #include <dirent.h>
00066 #include <sys/time.h>
00067 #include <sys/timeb.h>
00068 #ifdef  HAVE_KSTAT
00069 #include <kstat.h>
00070 #endif
00071 
00072 #if HAVE_VSSCANF
00073 int vsscanf( const char *str, const char *format, va_list ap);
00074 #else
00075 /* system has no vsscanf.  try to provide one */
00076 static int vsscanf( const char *str, const char *format, va_list ap)
00077 {
00078     long p1 = va_arg(ap, long);
00079     long p2 = va_arg(ap, long);
00080     long p3 = va_arg(ap, long);
00081     long p4 = va_arg(ap, long);
00082     long p5 = va_arg(ap, long);
00083     return sscanf(str, format, p1, p2, p3, p4, p5);
00084 }
00085 #endif
00086 
00087 char* def_path = WIN32_PATH;
00088 
00089 static void do_cpuid(unsigned int ax, unsigned int *regs)
00090 {
00091     __asm__ __volatile__
00092         (
00093          "pushl %%ebx; pushl %%ecx; pushl %%edx;"
00094          ".byte  0x0f, 0xa2;"
00095          "movl   %%eax, (%2);"
00096          "movl   %%ebx, 4(%2);"
00097          "movl   %%ecx, 8(%2);"
00098          "movl   %%edx, 12(%2);"
00099          "popl %%edx; popl %%ecx; popl %%ebx;"
00100          : "=a" (ax)
00101          :  "0" (ax), "S" (regs)
00102         );
00103 }
00104 static unsigned int c_localcount_tsc()
00105 {
00106     int a;
00107     __asm__ __volatile__
00108         (
00109          "rdtsc\n\t"
00110          :"=a"(a)
00111          :
00112          :"edx"
00113         );
00114     return a;
00115 }
00116 static void c_longcount_tsc(long long* z)
00117 {
00118     __asm__ __volatile__
00119         (
00120          "pushl %%ebx\n\t"
00121          "movl %%eax, %%ebx\n\t"
00122          "rdtsc\n\t"
00123          "movl %%eax, 0(%%ebx)\n\t"
00124          "movl %%edx, 4(%%ebx)\n\t"
00125          "popl %%ebx\n\t"
00126          ::"a"(z)
00127          :"edx"
00128         );
00129 }
00130 static unsigned int c_localcount_notsc()
00131 {
00132     struct timeval tv;
00133     unsigned limit=~0;
00134     limit/=1000000;
00135     gettimeofday(&tv, 0);
00136     return limit*tv.tv_usec;
00137 }
00138 static void c_longcount_notsc(long long* z)
00139 {
00140     struct timeval tv;
00141     unsigned long long result;
00142     unsigned limit=~0;
00143     if(!z)return;
00144     limit/=1000000;
00145     gettimeofday(&tv, 0);
00146     result=tv.tv_sec;
00147     result<<=32;
00148     result+=limit*tv.tv_usec;
00149     *z=result;
00150 }
00151 static unsigned int localcount_stub(void);
00152 static void longcount_stub(long long*);
00153 static unsigned int (*localcount)()=localcount_stub;
00154 static void (*longcount)(long long*)=longcount_stub;
00155 
00156 static pthread_mutex_t memmut;
00157 
00158 static unsigned int localcount_stub(void)
00159 {
00160     unsigned int regs[4];
00161     do_cpuid(1, regs);
00162     if ((regs[3] & 0x00000010) != 0)
00163     {
00164         localcount=c_localcount_tsc;
00165         longcount=c_longcount_tsc;
00166     }
00167     else
00168     {
00169         localcount=c_localcount_notsc;
00170         longcount=c_longcount_notsc;
00171     }
00172     return localcount();
00173 }
00174 static void longcount_stub(long long* z)
00175 {
00176     unsigned int regs[4];
00177     do_cpuid(1, regs);
00178     if ((regs[3] & 0x00000010) != 0)
00179     {
00180         localcount=c_localcount_tsc;
00181         longcount=c_longcount_tsc;
00182     }
00183     else
00184     {
00185         localcount=c_localcount_notsc;
00186         longcount=c_longcount_notsc;
00187     }
00188     longcount(z);
00189 }
00190 
00191 #ifdef MPLAYER
00192 #include "../mp_msg.h"
00193 #endif
00194 int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
00195 //#define DETAILED_OUT
00196 static inline void dbgprintf(char* fmt, ...)
00197 {
00198 #ifdef DETAILED_OUT
00199     if(LOADER_DEBUG)
00200     {
00201         FILE* f;
00202         va_list va;
00203         va_start(va, fmt);
00204         f=fopen("./log", "a");
00205         vprintf(fmt, va);
00206         fflush(stdout);
00207         if(f)
00208         {
00209             vfprintf(f, fmt, va);
00210             fsync(fileno(f));
00211             fclose(f);
00212         }
00213         va_end(va);
00214     }
00215 #endif
00216 #ifdef MPLAYER
00217     if (verbose > 2)
00218     {
00219         va_list va;
00220         
00221         va_start(va, fmt);
00222         vprintf(fmt, va);
00223 //      mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
00224         va_end(va);
00225     }
00226   fflush(stdout);
00227 #endif
00228 }
00229 
00230 
00231 char export_names[300][32]={
00232     "name1",
00233     //"name2",
00234     //"name3"
00235 };
00236 //#define min(x,y) ((x)<(y)?(x):(y))
00237 
00238 void destroy_event(void* event);
00239 
00240 struct th_list_t;
00241 typedef struct th_list_t{
00242     int id;
00243     void* thread;
00244     struct th_list_t* next;
00245     struct th_list_t* prev;
00246 } th_list;
00247 
00248 
00249 // have to be cleared by GARBAGE COLLECTOR
00250 static unsigned char* heap=NULL;
00251 static int heap_counter=0;
00252 static tls_t* g_tls=NULL;
00253 static th_list* list=NULL;
00254 
00255 static void test_heap(void)
00256 {
00257     int offset=0;
00258     if(heap==0)
00259         return;
00260     while(offset<heap_counter)
00261     {
00262         if(*(int*)(heap+offset)!=0x433476)
00263         {
00264             printf("Heap corruption at address %d\n", offset);
00265             return;
00266         }
00267         offset+=8+*(int*)(heap+offset+4);
00268     }
00269     for(;offset<min(offset+1000, 20000000); offset++)
00270         if(heap[offset]!=0xCC)
00271         {
00272             printf("Free heap corruption at address %d\n", offset);
00273         }
00274 }
00275 #undef MEMORY_DEBUG
00276 
00277 #ifdef MEMORY_DEBUG
00278 
00279 static void* my_mreq(int size, int to_zero)
00280 {
00281     static int test=0;
00282     test++;
00283     if(test%10==0)printf("Memory: %d bytes allocated\n", heap_counter);
00284     //    test_heap();
00285     if(heap==NULL)
00286     {
00287         heap=malloc(20000000);
00288         memset(heap, 0xCC,20000000);
00289     }
00290     if(heap==0)
00291     {
00292         printf("No enough memory\n");
00293         return 0;
00294     }
00295     if(heap_counter+size>20000000)
00296     {
00297         printf("No enough memory\n");
00298         return 0;
00299     }
00300     *(int*)(heap+heap_counter)=0x433476;
00301     heap_counter+=4;
00302     *(int*)(heap+heap_counter)=size;
00303     heap_counter+=4;
00304     printf("Allocated %d bytes of memory: sys %d, user %d-%d\n", size, heap_counter-8, heap_counter, heap_counter+size);
00305     if(to_zero)
00306         memset(heap+heap_counter, 0, size);
00307     else
00308         memset(heap+heap_counter, 0xcc, size);  // make crash reproducable
00309     heap_counter+=size;
00310     return heap+heap_counter-size;
00311 }
00312 static int my_release(char* memory)
00313 {
00314     //    test_heap();
00315     if(memory==NULL)
00316     {
00317         printf("ERROR: free(0)\n");
00318         return 0;
00319     }
00320     if(*(int*)(memory-8)!=0x433476)
00321     {
00322         printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!\n");
00323         return 0;
00324     }
00325     printf("Freed %d bytes of memory\n", *(int*)(memory-4));
00326     //    memset(memory-8, *(int*)(memory-4), 0xCC);
00327     return 0;
00328 }
00329 
00330 #else
00331 #define GARBAGE
00332 typedef struct alloc_header_t alloc_header;
00333 struct alloc_header_t
00334 {
00335     // let's keep allocated data 16 byte aligned
00336     alloc_header* prev;
00337     alloc_header* next;
00338     long deadbeef;
00339     long size;
00340     long type;
00341     long reserved1;
00342     long reserved2;
00343     long reserved3;
00344 };
00345 
00346 #ifdef GARBAGE
00347 static alloc_header* last_alloc = NULL;
00348 static int alccnt = 0;
00349 #endif
00350 
00351 #define AREATYPE_CLIENT 0
00352 #define AREATYPE_EVENT 1
00353 #define AREATYPE_MUTEX 2
00354 #define AREATYPE_COND 3
00355 #define AREATYPE_CRITSECT 4
00356 
00357 /* -- critical sections -- */
00358 struct CRITSECT
00359 {
00360     pthread_t id;
00361     pthread_mutex_t mutex;
00362     int locked;
00363     long deadbeef;
00364 };
00365 
00366 void* mreq_private(int size, int to_zero, int type);
00367 void* mreq_private(int size, int to_zero, int type)
00368 {
00369     int nsize = size + sizeof(alloc_header);
00370     alloc_header* header = (alloc_header* ) malloc(nsize);
00371     if (!header)
00372         return 0;
00373     if (to_zero)
00374         memset(header, 0, nsize);
00375 #ifdef GARBAGE
00376     if (!last_alloc)
00377     {
00378         pthread_mutex_init(&memmut, NULL);
00379         pthread_mutex_lock(&memmut);
00380     }
00381     else
00382     {
00383         pthread_mutex_lock(&memmut);
00384         last_alloc->next = header;  /* set next */
00385     }
00386 
00387     header->prev = last_alloc;
00388     header->next = 0;
00389     last_alloc = header;
00390     alccnt++;
00391     pthread_mutex_unlock(&memmut);
00392 #endif
00393     header->deadbeef = 0xdeadbeef;
00394     header->size = size;
00395     header->type = type;
00396 
00397     //if (alccnt < 40000) printf("MY_REQ: %p\t%d   t:%d  (cnt:%d)\n",  header, size, type, alccnt);
00398     return header + 1;
00399 }
00400 
00401 static int my_release(void* memory)
00402 {
00403     alloc_header* header = (alloc_header*) memory - 1;
00404 #ifdef GARBAGE
00405     alloc_header* prevmem;
00406     alloc_header* nextmem;
00407 
00408     if (memory == 0)
00409         return 0;
00410 
00411     if (header->deadbeef != (long) 0xdeadbeef)
00412     {
00413         dbgprintf("FATAL releasing corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
00414         return 0;
00415     }
00416 
00417     pthread_mutex_lock(&memmut);
00418 
00419     switch(header->type)
00420     {
00421     case AREATYPE_EVENT:
00422         destroy_event(memory);
00423         break;
00424     case AREATYPE_COND:
00425         pthread_cond_destroy((pthread_cond_t*)memory);
00426         break;
00427     case AREATYPE_MUTEX:
00428         pthread_mutex_destroy((pthread_mutex_t*)memory);
00429         break;
00430     case AREATYPE_CRITSECT:
00431         pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
00432         break;
00433     default:
00434         //memset(memory, 0xcc, header->size);
00435         ;
00436     }
00437 
00438     header->deadbeef = 0;
00439     prevmem = header->prev;
00440     nextmem = header->next;
00441 
00442     if (prevmem)
00443         prevmem->next = nextmem;
00444     if (nextmem)
00445         nextmem->prev = prevmem;
00446 
00447     if (header == last_alloc)
00448         last_alloc = prevmem;
00449 
00450     alccnt--;
00451 
00452     if (last_alloc)
00453         pthread_mutex_unlock(&memmut);
00454     else
00455         pthread_mutex_destroy(&memmut);
00456 
00457     //if (alccnt < 40000) printf("MY_RELEASE: %p\t%ld    (%d)\n", header, header->size, alccnt);
00458 #else
00459     if (memory == 0)
00460         return 0;
00461 #endif
00462     //memset(header + 1, 0xcc, header->size);
00463     free(header);
00464     return 0;
00465 }
00466 #endif
00467 
00468 static inline void* my_mreq(int size, int to_zero)
00469 {
00470     return mreq_private(size, to_zero, AREATYPE_CLIENT);
00471 }
00472 
00473 static int my_size(void* memory)
00474 {
00475     if(!memory) return 0;
00476     return ((alloc_header*)memory)[-1].size;
00477 }
00478 
00479 static void* my_realloc(void* memory, int size)
00480 {
00481     void *ans = memory;
00482     int osize;
00483     if (memory == NULL)
00484         return my_mreq(size, 0);
00485     osize = my_size(memory);
00486     if (osize < size)
00487     {
00488         ans = my_mreq(size, 0);
00489         memcpy(ans, memory, osize);
00490         my_release(memory);
00491     }
00492     return ans;
00493 }
00494 
00495 /*
00496  *
00497  *  WINE  API  - native implementation for several win32 libraries
00498  *
00499  */
00500 
00501 static int WINAPI ext_unknown()
00502 {
00503     printf("Unknown func called\n");
00504     return 0;
00505 }
00506 
00507 static int  WINAPI expGetVolumeInformationA( const char *root, char *label,
00508                                        unsigned int label_len, unsigned int *serial,
00509                                        unsigned int *filename_len,unsigned int *flags,
00510                                        char *fsname, unsigned int fsname_len )
00511 {
00512 dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1\n",
00513                       root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
00514 //hack Do not return any real data - do nothing
00515 return 1;
00516 }
00517 
00518 static unsigned int WINAPI expGetDriveTypeA( const char *root )
00519 {
00520  dbgprintf("GetDriveTypeA( %s ) => %d\n",root,DRIVE_FIXED);
00521  // hack return as Fixed Drive Type
00522  return DRIVE_FIXED;
00523 }
00524 
00525 static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
00526 {
00527  dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4\n",len,buffer);
00528  // hack only have one drive c:\ in this hack
00529   *buffer++='c';
00530   *buffer++=':';
00531   *buffer++='\\';
00532   *buffer++='\0';
00533   *buffer= '\0';
00534 return 4; // 1 drive * 4 bytes (includes null)
00535 }
00536 
00537 
00538 static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
00539 {
00540     int result = (count == 0 || ptr != 0) ? 0 : 1;
00541     dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %d\n", ptr, count, result);
00542     return result;
00543 }
00544 static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
00545 {
00546     int result = (count == 0 || ptr != 0) ? 0 : 1;
00547     dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %d\n", ptr, count, result);
00548     return result;
00549 }
00550 static int WINAPI expDisableThreadLibraryCalls(int module)
00551 {
00552     dbgprintf("DisableThreadLibraryCalls(0x%x) => 0\n", module);
00553     return 0;
00554 }
00555 
00556 static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
00557 {
00558     HMODULE result;
00559     if (pdrv==NULL)
00560         result=0;
00561     else
00562         result=pdrv->hDriverModule;
00563     dbgprintf("GetDriverModuleHandle(%p) => %p\n", pdrv, result);
00564     return result;
00565 }
00566 
00567 #define MODULE_HANDLE_kernel32  ((HMODULE)0x120)
00568 #define MODULE_HANDLE_user32    ((HMODULE)0x121)
00569 #ifdef QTX
00570 #define MODULE_HANDLE_wininet   ((HMODULE)0x122)
00571 #define MODULE_HANDLE_ddraw     ((HMODULE)0x123)
00572 #define MODULE_HANDLE_advapi32  ((HMODULE)0x124)
00573 #endif
00574 #define MODULE_HANDLE_comdlg32  ((HMODULE)0x125)
00575 #define MODULE_HANDLE_msvcrt    ((HMODULE)0x126)
00576 #define MODULE_HANDLE_ole32     ((HMODULE)0x127)
00577 #define MODULE_HANDLE_winmm     ((HMODULE)0x128)
00578 
00579 static HMODULE WINAPI expGetModuleHandleA(const char* name)
00580 {
00581     WINE_MODREF* wm;
00582     HMODULE result;
00583     if(!name)
00584 #ifdef QTX
00585         result=1;
00586 #else
00587         result=0;
00588 #endif
00589     else
00590     {
00591         wm=MODULE_FindModule(name);
00592         if(wm==0)result=0;
00593         else
00594             result=(HMODULE)(wm->module);
00595     }
00596     if(!result)
00597     {
00598         if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
00599             result=MODULE_HANDLE_kernel32;
00600 #ifdef QTX
00601         if(name && strcasecmp(name, "user32")==0)
00602             result=MODULE_HANDLE_user32;
00603 #endif
00604     }
00605     dbgprintf("GetModuleHandleA('%s') => 0x%x\n", name, result);
00606     return result;
00607 }
00608 
00609 static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
00610                                     void* lpStartAddress, void* lpParameter,
00611                                     long dwFlags, long* dwThreadId)
00612 {
00613     pthread_t *pth;
00614     //    printf("CreateThread:");
00615     pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
00616     pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
00617     if(dwFlags)
00618         printf( "WARNING: CreateThread flags not supported\n");
00619     if(dwThreadId)
00620         *dwThreadId=(long)pth;
00621     if(list==NULL)
00622     {
00623         list=my_mreq(sizeof(th_list), 1);
00624         list->next=list->prev=NULL;
00625     }
00626     else
00627     {
00628         list->next=my_mreq(sizeof(th_list), 0);
00629         list->next->prev=list;
00630         list->next->next=NULL;
00631         list=list->next;
00632     }
00633     list->thread=pth;
00634     dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n",
00635               pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
00636     return pth;
00637 }
00638 
00639 struct mutex_list_t;
00640 
00641 struct mutex_list_t
00642 {
00643     char type;
00644     pthread_mutex_t *pm;
00645     pthread_cond_t  *pc;
00646     char state;
00647     char reset;
00648     char name[128];
00649     int  semaphore;
00650     struct mutex_list_t* next;
00651     struct mutex_list_t* prev;
00652 };
00653 typedef struct mutex_list_t mutex_list;
00654 static mutex_list* mlist=NULL;
00655 
00656 void destroy_event(void* event)
00657 {
00658     mutex_list* pp=mlist;
00659     //    printf("garbage collector: destroy_event(%x)\n", event);
00660     while(pp)
00661     {
00662         if(pp==(mutex_list*)event)
00663         {
00664             if(pp->next)
00665                 pp->next->prev=pp->prev;
00666             if(pp->prev)
00667                 pp->prev->next=pp->next;
00668             if(mlist==(mutex_list*)event)
00669                 mlist=mlist->prev;
00670             /*
00671              pp=mlist;
00672              while(pp)
00673              {
00674              printf("%x => ", pp);
00675              pp=pp->prev;
00676              }
00677              printf("0\n");
00678              */
00679             return;
00680         }
00681         pp=pp->prev;
00682     }
00683 }
00684 
00685 static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
00686                                     char bInitialState, const char* name)
00687 {
00688     pthread_mutex_t *pm;
00689     pthread_cond_t  *pc;
00690     /*
00691      mutex_list* pp;
00692      pp=mlist;
00693      while(pp)
00694      {
00695      printf("%x => ", pp);
00696      pp=pp->prev;
00697      }
00698      printf("0\n");
00699      */
00700     if(mlist!=NULL)
00701     {
00702         mutex_list* pp=mlist;
00703         if(name!=NULL)
00704             do
00705         {
00706             if((strcmp(pp->name, name)==0) && (pp->type==0))
00707             {
00708                 dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
00709                           pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
00710                 return pp->pm;
00711             }
00712         }while((pp=pp->prev) != NULL);
00713     }
00714     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
00715     pthread_mutex_init(pm, NULL);
00716     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
00717     pthread_cond_init(pc, NULL);
00718     if(mlist==NULL)
00719     {
00720         mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
00721         mlist->next=mlist->prev=NULL;
00722     }
00723     else
00724     {
00725         mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
00726         mlist->next->prev=mlist;
00727         mlist->next->next=NULL;
00728         mlist=mlist->next;
00729     }
00730     mlist->type=0; /* Type Event */
00731     mlist->pm=pm;
00732     mlist->pc=pc;
00733     mlist->state=bInitialState;
00734     mlist->reset=bManualReset;
00735     if(name)
00736         strncpy(mlist->name, name, 127);
00737     else
00738         mlist->name[0]=0;
00739     if(pm==NULL)
00740         dbgprintf("ERROR::: CreateEventA failure\n");
00741     /*
00742      if(bInitialState)
00743      pthread_mutex_lock(pm);
00744      */
00745     if(name)
00746         dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n",
00747                   pSecAttr, bManualReset, bInitialState, name, name, mlist);
00748     else
00749         dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n",
00750                   pSecAttr, bManualReset, bInitialState, mlist);
00751     return mlist;
00752 }
00753 
00754 static void* WINAPI expSetEvent(void* event)
00755 {
00756     mutex_list *ml = (mutex_list *)event;
00757     dbgprintf("SetEvent(%x) => 0x1\n", event);
00758     pthread_mutex_lock(ml->pm);
00759     if (ml->state == 0) {
00760         ml->state = 1;
00761         pthread_cond_signal(ml->pc);
00762     }
00763     pthread_mutex_unlock(ml->pm);
00764 
00765     return (void *)1;
00766 }
00767 static void* WINAPI expResetEvent(void* event)
00768 {
00769     mutex_list *ml = (mutex_list *)event;
00770     dbgprintf("ResetEvent(0x%x) => 0x1\n", event);
00771     pthread_mutex_lock(ml->pm);
00772     ml->state = 0;
00773     pthread_mutex_unlock(ml->pm);
00774 
00775     return (void *)1;
00776 }
00777 
00778 static void* WINAPI expWaitForSingleObject(void* object, int duration)
00779 {
00780     mutex_list *ml = (mutex_list *)object;
00781     // FIXME FIXME FIXME - this value is sometime unititialize !!!
00782     int ret = WAIT_FAILED;
00783     mutex_list* pp=mlist;
00784     if(object == (void*)0xcfcf9898)
00785     {
00794         dbgprintf("WaitForSingleObject(thread_handle) called\n");
00795         return (void*)WAIT_FAILED;
00796     }
00797     dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration);
00798 
00799     // loop below was slightly fixed - its used just for checking if
00800     // this object really exists in our list
00801     if (!ml)
00802         return (void*) ret;
00803     while (pp && (pp->pm != ml->pm))
00804         pp = pp->prev;
00805     if (!pp) {
00806         dbgprintf("WaitForSingleObject: NotFound\n");
00807         return (void*)ret;
00808     }
00809 
00810     pthread_mutex_lock(ml->pm);
00811 
00812     switch(ml->type) {
00813     case 0: /* Event */
00814         if (duration == 0) { /* Check Only */
00815             if (ml->state == 1) ret = WAIT_FAILED;
00816             else                   ret = WAIT_OBJECT_0;
00817         }
00818         if (duration == -1) { /* INFINITE */
00819             if (ml->state == 0)
00820                 pthread_cond_wait(ml->pc,ml->pm);
00821             if (ml->reset)
00822                 ml->state = 0;
00823             ret = WAIT_OBJECT_0;
00824         }
00825         if (duration > 0) {  /* Timed Wait */
00826             struct timespec abstime;
00827             struct timeval now;
00828             gettimeofday(&now, 0);
00829             abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
00830             abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
00831             if (ml->state == 0)
00832                 ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
00833             if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
00834             else                  ret = WAIT_OBJECT_0;
00835             if (ml->reset)
00836                 ml->state = 0;
00837         }
00838         break;
00839     case 1:  /* Semaphore */
00840         if (duration == 0) {
00841             if(ml->semaphore==0) ret = WAIT_FAILED;
00842             else {
00843                 ml->semaphore++;
00844                 ret = WAIT_OBJECT_0;
00845             }
00846         }
00847         if (duration == -1) {
00848             if (ml->semaphore==0)
00849                 pthread_cond_wait(ml->pc,ml->pm);
00850             ml->semaphore--;
00851         }
00852         break;
00853     }
00854     pthread_mutex_unlock(ml->pm);
00855 
00856     dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x \n",object,duration,ml,ret);
00857     return (void *)ret;
00858 }
00859 
00860 #ifdef QTX
00861 static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
00862                     int WaitAll, int duration)
00863 {
00864     int i;
00865     void *object;
00866     void *ret;
00867 
00868     dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>\n",
00869         count, objects, WaitAll, duration);
00870     
00871     for (i = 0; i < count; i++)
00872     {
00873         object = (void *)objects[i];
00874         ret = expWaitForSingleObject(object, duration);
00875         if (WaitAll)
00876             dbgprintf("WaitAll flag not yet supported...\n");
00877         else
00878             return ret;
00879     }
00880     return NULL;
00881 }
00882 
00883 static void WINAPI expExitThread(int retcode)
00884 {
00885     dbgprintf("ExitThread(%d)\n", retcode);
00886     pthread_exit(&retcode);
00887 }
00888 
00889 static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
00890                     char bInitialOwner, const char *name)
00891 {
00892     HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
00893     
00894     if (name)
00895         dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n",
00896             pSecAttr, bInitialOwner, name, mlist);
00897     else
00898         dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n",
00899             pSecAttr, bInitialOwner, mlist);
00900 #ifndef QTX
00901     /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
00902        waits for ever, else it works ;) */
00903     return mlist;
00904 #endif
00905 }
00906 
00907 static int WINAPI expReleaseMutex(HANDLE hMutex)
00908 {
00909     dbgprintf("ReleaseMutex(%x) => 1\n", hMutex);
00910     /* FIXME:XXX !! not yet implemented */
00911     return 1;
00912 }
00913 #endif
00914 
00915 static int pf_set = 0;
00916 static BYTE PF[64] = {0,};
00917 
00918 static void DumpSystemInfo(const SYSTEM_INFO* si)
00919 {
00920     dbgprintf("  Processor architecture %d\n", si->u.s.wProcessorArchitecture);
00921     dbgprintf("  Page size: %d\n", si->dwPageSize);
00922     dbgprintf("  Minimum app address: %d\n", si->lpMinimumApplicationAddress);
00923     dbgprintf("  Maximum app address: %d\n", si->lpMaximumApplicationAddress);
00924     dbgprintf("  Active processor mask: 0x%x\n", si->dwActiveProcessorMask);
00925     dbgprintf("  Number of processors: %d\n", si->dwNumberOfProcessors);
00926     dbgprintf("  Processor type: 0x%x\n", si->dwProcessorType);
00927     dbgprintf("  Allocation granularity: 0x%x\n", si->dwAllocationGranularity);
00928     dbgprintf("  Processor level: 0x%x\n", si->wProcessorLevel);
00929     dbgprintf("  Processor revision: 0x%x\n", si->wProcessorRevision);
00930 }
00931 
00932 static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
00933 {
00934     /* FIXME: better values for the two entries below... */
00935     static int cache = 0;
00936     static SYSTEM_INFO cachedsi;
00937     unsigned int regs[4];
00938     dbgprintf("GetSystemInfo(%p) =>\n", si);
00939 
00940     if (cache) {
00941         memcpy(si,&cachedsi,sizeof(*si));
00942         DumpSystemInfo(si);
00943         return;
00944     }
00945     memset(PF,0,sizeof(PF));
00946     pf_set = 1;
00947 
00948     cachedsi.u.s.wProcessorArchitecture     = PROCESSOR_ARCHITECTURE_INTEL;
00949     cachedsi.dwPageSize                         = getpagesize();
00950 
00951     /* FIXME: better values for the two entries below... */
00952     cachedsi.lpMinimumApplicationAddress        = (void *)0x00000000;
00953     cachedsi.lpMaximumApplicationAddress        = (void *)0x7FFFFFFF;
00954     cachedsi.dwActiveProcessorMask              = 1;
00955     cachedsi.dwNumberOfProcessors               = 1;
00956     cachedsi.dwProcessorType            = PROCESSOR_INTEL_386;
00957     cachedsi.dwAllocationGranularity    = 0x10000;
00958     cachedsi.wProcessorLevel            = 5; /* pentium */
00959     cachedsi.wProcessorRevision         = 0x0101;
00960 
00961 #ifdef MPLAYER
00962     /* mplayer's way to detect PF's */
00963     {
00964 #include "../cpudetect.h"
00965         extern CpuCaps gCpuCaps;
00966 
00967         if (gCpuCaps.hasMMX)
00968             PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
00969         if (gCpuCaps.hasSSE)
00970             PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
00971         if (gCpuCaps.has3DNow)
00972             PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
00973 
00974             if (gCpuCaps.cpuType == 4)
00975             {
00976                 cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
00977                 cachedsi.wProcessorLevel = 4;
00978             }
00979             else if (gCpuCaps.cpuType >= 5)
00980             {
00981                 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
00982                 cachedsi.wProcessorLevel = 5;
00983             }
00984             else
00985             {
00986                 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
00987                 cachedsi.wProcessorLevel = 3;
00988             }
00989             cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
00990             cachedsi.dwNumberOfProcessors = 1;  /* hardcoded */
00991     }
00992 #endif
00993 
00994 /* disable cpuid based detection (mplayer's cpudetect.c does this - see above) */
00995 #ifndef MPLAYER
00996 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__svr4__) || defined(__DragonFly__)
00997     do_cpuid(1, regs);
00998     switch ((regs[0] >> 8) & 0xf) {                     // cpu family
00999     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
01000     cachedsi.wProcessorLevel= 3;
01001     break;
01002     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
01003     cachedsi.wProcessorLevel= 4;
01004     break;
01005     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01006     cachedsi.wProcessorLevel= 5;
01007     break;
01008     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01009     cachedsi.wProcessorLevel= 5;
01010     break;
01011     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01012     cachedsi.wProcessorLevel= 5;
01013     break;
01014     }
01015     cachedsi.wProcessorRevision = regs[0] & 0xf;        // stepping
01016     if (regs[3] & (1 <<  8))
01017         PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
01018     if (regs[3] & (1 << 23))
01019         PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
01020     if (regs[3] & (1 << 25))
01021         PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
01022     if (regs[3] & (1 << 31))
01023         PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
01024     cachedsi.dwNumberOfProcessors=1;
01025 #endif
01026 #endif /* MPLAYER */
01027 
01028 /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
01029    fdiv_bug and fpu emulation flags -- alex/MPlayer */
01030 #ifdef __linux__
01031     {
01032         char buf[20];
01033         char line[200];
01034         FILE *f = fopen ("/proc/cpuinfo", "r");
01035 
01036         if (!f)
01037             return;
01038         while (fgets(line,200,f)!=NULL) {
01039             char        *s,*value;
01040 
01041             /* NOTE: the ':' is the only character we can rely on */
01042             if (!(value = strchr(line,':')))
01043                 continue;
01044             /* terminate the valuename */
01045             *value++ = '\0';
01046             /* skip any leading spaces */
01047             while (*value==' ') value++;
01048             if ((s=strchr(value,'\n')))
01049                 *s='\0';
01050 
01051             /* 2.1 method */
01052             if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
01053                 if (isdigit (value[0])) {
01054                     switch (value[0] - '0') {
01055                     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
01056                     cachedsi.wProcessorLevel= 3;
01057                     break;
01058                     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
01059                     cachedsi.wProcessorLevel= 4;
01060                     break;
01061                     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01062                     cachedsi.wProcessorLevel= 5;
01063                     break;
01064                     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01065                     cachedsi.wProcessorLevel= 5;
01066                     break;
01067                     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01068                     cachedsi.wProcessorLevel= 5;
01069                     break;
01070                     }
01071                 }
01072                 /* set the CPU type of the current processor */
01073                 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
01074                 continue;
01075             }
01076             /* old 2.0 method */
01077             if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
01078                 if (    isdigit (value[0]) && value[1] == '8' &&
01079                         value[2] == '6' && value[3] == 0
01080                    ) {
01081                     switch (value[0] - '0') {
01082                     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
01083                     cachedsi.wProcessorLevel= 3;
01084                     break;
01085                     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
01086                     cachedsi.wProcessorLevel= 4;
01087                     break;
01088                     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01089                     cachedsi.wProcessorLevel= 5;
01090                     break;
01091                     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01092                     cachedsi.wProcessorLevel= 5;
01093                     break;
01094                     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
01095                     cachedsi.wProcessorLevel= 5;
01096                     break;
01097                     }
01098                 }
01099                 /* set the CPU type of the current processor */
01100                 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
01101                 continue;
01102             }
01103             if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
01104                 if (!lstrncmpiA(value,"yes",3))
01105                     PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
01106 
01107                 continue;
01108             }
01109             if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
01110                 if (!lstrncmpiA(value,"no",2))
01111                     PF[PF_FLOATING_POINT_EMULATED] = TRUE;
01112 
01113                 continue;
01114             }
01115             if (!lstrncmpiA(line,"processor",strlen("processor"))) {
01116                 /* processor number counts up...*/
01117                 unsigned int x;
01118 
01119                 if (sscanf(value,"%d",&x))
01120                     if (x+1>cachedsi.dwNumberOfProcessors)
01121                         cachedsi.dwNumberOfProcessors=x+1;
01122 
01123                 /* Create a new processor subkey on a multiprocessor
01124                  * system
01125                  */
01126                 sprintf(buf,"%d",x);
01127             }
01128             if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
01129                 int     x;
01130 
01131                 if (sscanf(value,"%d",&x))
01132                     cachedsi.wProcessorRevision = x;
01133             }
01134             if
01135                 ( (!lstrncmpiA(line,"flags",strlen("flags")))
01136                   || (!lstrncmpiA(line,"features",strlen("features"))) )
01137             {
01138                 if (strstr(value,"cx8"))
01139                     PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
01140                 if (strstr(value,"mmx"))
01141                     PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
01142                 if (strstr(value,"tsc"))
01143                     PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
01144                 if (strstr(value,"xmm"))
01145                     PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
01146                 if (strstr(value,"3dnow"))
01147                     PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
01148             }
01149         }
01150         fclose (f);
01151         /*
01152          *      ad hoc fix for smp machines.
01153          *      some problems on WaitForSingleObject,CreateEvent,SetEvent
01154          *                      CreateThread ...etc..
01155          *
01156          */
01157         cachedsi.dwNumberOfProcessors=1;
01158     }
01159 #endif /* __linux__ */
01160     cache = 1;
01161     memcpy(si,&cachedsi,sizeof(*si));
01162     DumpSystemInfo(si);
01163 }
01164 
01165 // avoid undefined expGetSystemInfo
01166 static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
01167 {
01168     WIN_BOOL result = 0;
01169     if (!pf_set)
01170     {
01171         SYSTEM_INFO si;
01172         expGetSystemInfo(&si);
01173     }
01174     if(v<64) result=PF[v];
01175     dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%x\n", v, result);
01176     return result;
01177 }
01178 
01179 
01180 static long WINAPI expGetVersion()
01181 {
01182     dbgprintf("GetVersion() => 0xC0000004\n");
01183     return 0xC0000004;//Windows 95
01184 }
01185 
01186 static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
01187 {
01188     //    printf("HeapCreate:");
01189     HANDLE result;
01190     if(init_size==0)
01191         result=(HANDLE)my_mreq(0x110000, 0);
01192     else
01193         result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
01194     dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%x\n", flags, init_size, max_size, result);
01195     return result;
01196 }
01197 
01198 // this is another dirty hack
01199 // VP31 is releasing one allocated Heap chunk twice
01200 // we will silently ignore this second call...
01201 static void* heapfreehack = 0;
01202 static int heapfreehackshown = 0;
01203 //extern void trapbug(void);
01204 static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
01205 {
01206     void* z;
01214     //if (size == 22276) trapbug();
01215     z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
01216     if(z==0)
01217         printf("HeapAlloc failure\n");
01218     dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%x\n", heap, flags, size, z);
01219     heapfreehack = 0; // reset
01220     return z;
01221 }
01222 static long WINAPI expHeapDestroy(void* heap)
01223 {
01224     dbgprintf("HeapDestroy(heap 0x%x) => 1\n", heap);
01225     my_release(heap);
01226     return 1;
01227 }
01228 
01229 static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
01230 {
01231     dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1\n", heap, dwFlags, lpMem);
01232     if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
01233         && lpMem != (void*)0xbdbdbdbd)
01234         // 0xbdbdbdbd is for i263_drv.drv && libefence
01235         // it seems to be reading from relased memory
01236         // EF_PROTECT_FREE doens't show any probleme
01237         my_release(lpMem);
01238     else
01239     {
01240         if (!heapfreehackshown++)
01241             printf("Info: HeapFree deallocating same memory twice! (%p)\n", lpMem);
01242     }
01243     heapfreehack = lpMem;
01244     return 1;
01245 }
01246 static long WINAPI expHeapSize(int heap, int flags, void* pointer)
01247 {
01248     long result=my_size(pointer);
01249     dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %d\n", heap, flags, pointer, result);
01250     return result;
01251 }
01252 static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
01253 {
01254     long orgsize = my_size(lpMem);
01255     dbgprintf("HeapReAlloc() Size %ld org %d\n",orgsize,size);
01256     return my_realloc(lpMem, size);
01257 }
01258 static long WINAPI expGetProcessHeap(void)
01259 {
01260     dbgprintf("GetProcessHeap() => 1\n");
01261     return 1;
01262 }
01263 static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
01264 {
01265     void* z = VirtualAlloc(v1, v2, v3, v4);
01266     if(z==0)
01267         printf("VirtualAlloc failure\n");
01268     dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x \n",v1,v2,v3,v4, z);
01269     return z;
01270 }
01271 static int WINAPI expVirtualFree(void* v1, int v2, int v3)
01272 {
01273     int result = VirtualFree(v1,v2,v3);
01274     dbgprintf("VirtualFree(0x%x, %d, %d) => %d\n",v1,v2,v3, result);
01275     return result;
01276 }
01277 
01278 /* we're building a table of critical sections. cs_win pointer uses the DLL
01279  cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
01280 struct critsecs_list_t
01281 {
01282     CRITICAL_SECTION *cs_win;
01283     struct CRITSECT *cs_unix;
01284 };
01285 
01286 /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
01287 #undef CRITSECS_NEWTYPE
01288 //#define CRITSECS_NEWTYPE 1
01289 
01290 #ifdef CRITSECS_NEWTYPE
01291 /* increased due to ucod needs more than 32 entries */
01292 /* and 64 should be enough for everything */
01293 #define CRITSECS_LIST_MAX 64
01294 static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
01295 
01296 static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
01297 {
01298     int i;
01299 
01300     for (i=0; i < CRITSECS_LIST_MAX; i++)
01301         if (critsecs_list[i].cs_win == cs_win)
01302             return(i);
01303     return(-1);
01304 }
01305 
01306 static int critsecs_get_unused(void)
01307 {
01308     int i;
01309 
01310     for (i=0; i < CRITSECS_LIST_MAX; i++)
01311         if (critsecs_list[i].cs_win == NULL)
01312             return(i);
01313     return(-1);
01314 }
01315 
01316 struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
01317 {
01318     int i;
01319 
01320     for (i=0; i < CRITSECS_LIST_MAX; i++)
01321         if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
01322             return(critsecs_list[i].cs_unix);
01323     return(NULL);
01324 }
01325 #endif
01326 
01327 static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
01328 {
01329     dbgprintf("InitializeCriticalSection(0x%x)\n", c);
01330     /*    if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
01331      {
01332      printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!\n",
01333      sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
01334      return;
01335      }*/
01336     /*    pthread_mutex_init((pthread_mutex_t*)c, NULL);   */
01337 #ifdef CRITSECS_NEWTYPE
01338     {
01339         struct CRITSECT *cs;
01340         int i = critsecs_get_unused();
01341 
01342         if (i < 0)
01343         {
01344             printf("InitializeCriticalSection(%p) - no more space in list\n", c);
01345             return;
01346         }
01347         dbgprintf("got unused space at %d\n", i);
01348         cs = malloc(sizeof(struct CRITSECT));
01349         if (!cs)
01350         {
01351             printf("InitializeCriticalSection(%p) - out of memory\n", c);
01352             return;
01353         }
01354         pthread_mutex_init(&cs->mutex, NULL);
01355         cs->locked = 0;
01356         critsecs_list[i].cs_win = c;
01357         critsecs_list[i].cs_unix = cs;
01358         dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
01359                   i, c, cs);
01360     }
01361 #else
01362     {
01363         struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
01364                                            0, AREATYPE_CRITSECT);
01365         pthread_mutex_init(&cs->mutex, NULL);
01366         cs->locked=0;
01367         cs->deadbeef = 0xdeadbeef;
01368         *(void**)c = cs;
01369     }
01370 #endif
01371     return;
01372 }
01373 
01374 static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
01375 {
01376 #ifdef CRITSECS_NEWTYPE
01377     struct CRITSECT* cs = critsecs_get_unix(c);
01378 #else
01379     struct CRITSECT* cs = (*(struct CRITSECT**)c);
01380 #endif
01381     dbgprintf("EnterCriticalSection(0x%x) %p\n",c, cs);
01382     if (!cs)
01383     {
01384         dbgprintf("entered uninitialized critisec!\n");
01385         expInitializeCriticalSection(c);
01386 #ifdef CRITSECS_NEWTYPE
01387         cs=critsecs_get_unix(c);
01388 #else
01389         cs = (*(struct CRITSECT**)c);
01390 #endif
01391         dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
01392     }
01393     if(cs->locked)
01394         if(cs->id==pthread_self())
01395             return;
01396     pthread_mutex_lock(&(cs->mutex));
01397     cs->locked=1;
01398     cs->id=pthread_self();
01399     return;
01400 }
01401 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
01402 {
01403 #ifdef CRITSECS_NEWTYPE
01404     struct CRITSECT* cs = critsecs_get_unix(c);
01405 #else
01406     struct CRITSECT* cs = (*(struct CRITSECT**)c);
01407 #endif
01408     //    struct CRITSECT* cs=(struct CRITSECT*)c;
01409     dbgprintf("LeaveCriticalSection(0x%x) 0x%x\n",c, cs);
01410     if (!cs)
01411     {
01412         dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
01413         return;
01414     }
01415     if (cs->locked)
01416     {
01417         cs->locked=0;
01418         pthread_mutex_unlock(&(cs->mutex));
01419     }
01420     else
01421         dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
01422     return;
01423 }
01424 
01425 static void expfree(void* mem); /* forward declaration */
01426 
01427 static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
01428 {
01429 #ifdef CRITSECS_NEWTYPE
01430     struct CRITSECT* cs = critsecs_get_unix(c);
01431 #else
01432     struct CRITSECT* cs= (*(struct CRITSECT**)c);
01433 #endif
01434     //    struct CRITSECT* cs=(struct CRITSECT*)c;
01435     dbgprintf("DeleteCriticalSection(0x%x)\n",c);
01436 
01437     if (!cs)
01438     {
01439         dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!\n", c);
01440         return;
01441     }
01442     
01443     if (cs->locked)
01444     {
01445         dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
01446         pthread_mutex_unlock(&(cs->mutex));
01447     }
01448 
01449 #ifndef GARBAGE
01450     pthread_mutex_destroy(&(cs->mutex));
01451     // released by GarbageCollector in my_relase otherwise
01452 #endif
01453     my_release(cs);
01454 #ifdef CRITSECS_NEWTYPE
01455     {
01456         int i = critsecs_get_pos(c);
01457 
01458         if (i < 0)
01459         {
01460             printf("DeleteCriticalSection(%p) error (critsec not found)\n", c);
01461             return;
01462         }
01463 
01464         critsecs_list[i].cs_win = NULL;
01465         expfree(critsecs_list[i].cs_unix);
01466         critsecs_list[i].cs_unix = NULL;
01467         dbgprintf("DeleteCriticalSection -> itemno=%d\n", i);
01468     }
01469 #endif
01470     return;
01471 }
01472 static int WINAPI expGetCurrentThreadId()
01473 {
01474     dbgprintf("GetCurrentThreadId() => %d\n", pthread_self());
01475     return pthread_self();
01476 }
01477 static int WINAPI expGetCurrentProcess()
01478 {
01479     dbgprintf("GetCurrentProcess() => %d\n", getpid());
01480     return getpid();
01481 }
01482 
01483 #ifdef QTX
01484 // this version is required for Quicktime codecs (.qtx/.qts) to work.
01485 // (they assume some pointers at FS: segment)
01486 
01487 extern void* fs_seg;
01488 
01489 //static int tls_count;
01490 static int tls_use_map[64];
01491 static int WINAPI expTlsAlloc()
01492 {
01493     int i;
01494     for(i=0; i<64; i++)
01495         if(tls_use_map[i]==0)
01496         {
01497             tls_use_map[i]=1;
01498             dbgprintf("TlsAlloc() => %d\n",i);
01499             return i;
01500         }
01501     dbgprintf("TlsAlloc() => -1 (ERROR)\n");
01502     return -1;
01503 }
01504 
01505 //static int WINAPI expTlsSetValue(DWORD index, void* value)
01506 static int WINAPI expTlsSetValue(int index, void* value)
01507 {
01508     dbgprintf("TlsSetValue(%d,0x%x) => 1\n",index,value);
01509 //    if((index<0) || (index>64))
01510     if((index>=64))
01511         return 0;
01512     *(void**)((char*)fs_seg+0x88+4*index) = value;
01513     return 1;
01514 }
01515 
01516 static void* WINAPI expTlsGetValue(DWORD index)
01517 {
01518     dbgprintf("TlsGetValue(%d)\n",index);
01519 //    if((index<0) || (index>64))
01520     if((index>=64)) return NULL;
01521     return *(void**)((char*)fs_seg+0x88+4*index);
01522 }
01523 
01524 static int WINAPI expTlsFree(int idx)
01525 {
01526     int index = (int) idx;
01527     dbgprintf("TlsFree(%d)\n",index);
01528     if((index<0) || (index>64))
01529         return 0;
01530     tls_use_map[index]=0;
01531     return 1;
01532 }
01533 
01534 #else
01535 struct tls_s {
01536     void* value;
01537     int used;
01538     struct tls_s* prev;
01539     struct tls_s* next;
01540 };
01541 
01542 static void* WINAPI expTlsAlloc()
01543 {
01544     if (g_tls == NULL)
01545     {
01546         g_tls=my_mreq(sizeof(tls_t), 0);
01547         g_tls->next=g_tls->prev=NULL;
01548     }
01549     else
01550     {
01551         g_tls->next=my_mreq(sizeof(tls_t), 0);
01552         g_tls->next->prev=g_tls;
01553         g_tls->next->next=NULL;
01554         g_tls=g_tls->next;
01555     }
01556     dbgprintf("TlsAlloc() => 0x%x\n", g_tls);
01557     if (g_tls)
01558         g_tls->value=0; /* XXX For Divx.dll */
01559     return g_tls;
01560 }
01561 
01562 static int WINAPI expTlsSetValue(void* idx, void* value)
01563 {
01564     tls_t* index = (tls_t*) idx;
01565     int result;
01566     if(index==0)
01567         result=0;
01568     else
01569     {
01570         index->value=value;
01571         result=1;
01572     }
01573     dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d \n", index, value, result );
01574     return result;
01575 }
01576 static void* WINAPI expTlsGetValue(void* idx)
01577 {
01578     tls_t* index = (tls_t*) idx;
01579     void* result;
01580     if(index==0)
01581         result=0;
01582     else
01583         result=index->value;
01584     dbgprintf("TlsGetValue(index 0x%x) => 0x%x\n", index, result);
01585     return result;
01586 }
01587 static int WINAPI expTlsFree(void* idx)
01588 {
01589     tls_t* index = (tls_t*) idx;
01590     int result;
01591     if(index==0)
01592         result=0;
01593     else
01594     {
01595         if(index->next)
01596             index->next->prev=index->prev;
01597         if(index->prev)
01598             index->prev->next=index->next;
01599         if (g_tls == index)
01600             g_tls = index->prev;
01601         my_release((void*)index);
01602         result=1;
01603     }
01604     dbgprintf("TlsFree(index 0x%x) => %d\n", index, result);
01605     return result;
01606 }
01607 #endif
01608 
01609 static void* WINAPI expLocalAlloc(int flags, int size)
01610 {
01611     void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
01612     if (z == 0)
01613         printf("LocalAlloc() failed\n");
01614     dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
01615     return z;
01616 }
01617 
01618 static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
01619 {
01620     void *newpointer;
01621     int oldsize;
01622 
01623     newpointer=NULL;
01624     if (flags & LMEM_MODIFY) {
01625         dbgprintf("LocalReAlloc MODIFY\n");
01626         return (void *)handle;
01627     }
01628     oldsize = my_size((void *)handle);
01629     newpointer = my_realloc((void *)handle,size);
01630     dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%x\n", handle,size,oldsize, flags,newpointer);
01631 
01632     return newpointer;
01633 }
01634 
01635 static void* WINAPI expLocalLock(void* z)
01636 {
01637     dbgprintf("LocalLock(0x%x) => 0x%x\n", z, z);
01638     return z;
01639 }
01640 
01641 static void* WINAPI expGlobalAlloc(int flags, int size)
01642 {
01643     void* z;
01644     dbgprintf("GlobalAlloc(%d, flags 0x%X)\n", size, flags);
01645 
01646     z=my_mreq(size, (flags & GMEM_ZEROINIT));
01647     //z=calloc(size, 1);
01648     //z=malloc(size);
01649     if(z==0)
01650         printf("GlobalAlloc() failed\n");
01651     dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%x\n", size, flags, z);
01652     return z;
01653 }
01654 static void* WINAPI expGlobalLock(void* z)
01655 {
01656     dbgprintf("GlobalLock(0x%x) => 0x%x\n", z, z);
01657     return z;
01658 }
01659 // pvmjpg20 - but doesn't work anyway
01660 static int WINAPI expGlobalSize(void* amem)
01661 {
01662     int size = 100000;
01663 #ifdef GARBAGE
01664     alloc_header* header = last_alloc;
01665     alloc_header* mem = (alloc_header*) amem - 1;
01666     if (amem == 0)
01667         return 0;
01668     pthread_mutex_lock(&memmut);
01669     while (header)
01670     {
01671         if (header->deadbeef != 0xdeadbeef)
01672         {
01673             dbgprintf("FATAL found corrupted memory! %p  0x%lx  (%d)\n", header, header->deadbeef, alccnt);
01674             break;
01675         }
01676 
01677         if (header == mem)
01678         {
01679             size = header->size;
01680             break;
01681         }
01682 
01683         header = header->prev;
01684     }
01685     pthread_mutex_unlock(&memmut);
01686 #endif
01687 
01688     dbgprintf("GlobalSize(0x%x)\n", amem);
01689     return size;
01690 }
01691 
01692 static int WINAPI expLoadIconA( long hinstance, char *name )
01693 {
01694  dbgprintf("LoadIconA( %ld, 0x%x ) => 1\n",hinstance,name);
01695  return 1;
01696 }
01697 
01698 static int WINAPI expLoadStringA(long instance, long  id, void* buf, long size)
01699 {
01700     int result=LoadStringA(instance, id, buf, size);
01701     //    if(buf)
01702     dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )\n",
01703               instance, id, buf, size, result, buf);
01704     //    else
01705     //    dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d\n",
01706     //  instance, id, buf, size, result);
01707     return result;
01708 }
01709 
01710 static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
01711 {
01712 #warning FIXME
01713     int i;
01714     int result;
01715     if(s2==0)
01716         result=1;
01717     else
01718     {
01719         if(siz1>siz2/2)siz1=siz2/2;
01720         for(i=1; i<=siz1; i++)
01721         {
01722             *s2=*s1;
01723             if(!*s1)break;
01724             s2++;
01725             s1++;
01726         }
01727         result=i;
01728     }
01729     if(s1)
01730         dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
01731                   "size %d, dest buffer 0x%x, dest size %d) => %d\n",
01732                   v1, v2, s1, s1, siz1, s2, siz2, result);
01733     else
01734         dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
01735                   "size %d, dest buffer 0x%x, dest size %d) =>\n",
01736                   v1, v2, siz1, s2, siz2, result);
01737     return result;
01738 }
01739 static void wch_print(const short* str)
01740 {
01741     dbgprintf("  src: ");
01742     while(*str)dbgprintf("%c", *str++);
01743     dbgprintf("\n");
01744 }
01745 static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
01746                                           char* s2, int siz2, char* c3, int* siz3)
01747 {
01748     int result;
01749     dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
01750               "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
01751     result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
01752     dbgprintf("=> %d\n", result);
01753     //if(s1)wch_print(s1);
01754     if(s2)dbgprintf("  dest: %s\n", s2);
01755     return result;
01756 }
01757 static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
01758 {
01759     dbgprintf("GetVersionExA(0x%x) => 1\n");
01760     c->dwOSVersionInfoSize=sizeof(*c);
01761     c->dwMajorVersion=4;
01762     c->dwMinorVersion=0;
01763     c->dwBuildNumber=0x4000457;
01764 #if 1
01765     // leave it here for testing win9x-only codecs
01766     c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
01767     strcpy(c->szCSDVersion, " B");
01768 #else
01769     c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
01770     strcpy(c->szCSDVersion, "Service Pack 3");
01771 #endif
01772     dbgprintf("  Major version: 4\n  Minor version: 0\n  Build number: 0x4000457\n"
01773               "  Platform Id: VER_PLATFORM_WIN32_NT\n Version string: 'Service Pack 3'\n");
01774     return 1;
01775 }
01776 static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
01777                                          long max_count, char* name)
01778 {
01779     pthread_mutex_t *pm;
01780     pthread_cond_t  *pc;
01781     mutex_list* pp;
01782     /*
01783      printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "<null>"));
01784      pp=mlist;
01785      while(pp)
01786      {
01787      printf("%p => ", pp);
01788      pp=pp->prev;
01789      }
01790      printf("0\n");
01791      */
01792     if(mlist!=NULL)
01793     {
01794         mutex_list* pp=mlist;
01795         if(name!=NULL)
01796             do
01797         {
01798             if((strcmp(pp->name, name)==0) && (pp->type==1))
01799             {
01800                 dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
01801                           v1, init_count, max_count, name, name, mlist);
01802                 return (HANDLE)mlist;
01803             }
01804         }while((pp=pp->prev) != NULL);
01805     }
01806     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
01807     pthread_mutex_init(pm, NULL);
01808     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
01809     pthread_cond_init(pc, NULL);
01810     if(mlist==NULL)
01811     {
01812         mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
01813         mlist->next=mlist->prev=NULL;
01814     }
01815     else
01816     {
01817         mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
01818         mlist->next->prev=mlist;
01819         mlist->next->next=NULL;
01820         mlist=mlist->next;
01821         //      printf("new semaphore %p\n", mlist);
01822     }
01823     mlist->type=1; /* Type Semaphore */
01824     mlist->pm=pm;
01825     mlist->pc=pc;
01826     mlist->state=0;
01827     mlist->reset=0;
01828     mlist->semaphore=init_count;
01829     if(name!=NULL)
01830         strncpy(mlist->name, name, 64);
01831     else
01832         mlist->name[0]=0;
01833     if(pm==NULL)
01834         dbgprintf("ERROR::: CreateSemaphoreA failure\n");
01835     if(name)
01836         dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n",
01837                   v1, init_count, max_count, name, name, mlist);
01838     else
01839         dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n",
01840                   v1, init_count, max_count, mlist);
01841     return (HANDLE)mlist;
01842 }
01843 
01844 static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
01845 {
01846     // The state of a semaphore object is signaled when its count
01847     // is greater than zero and nonsignaled when its count is equal to zero
01848     // Each time a waiting thread is released because of the semaphore's signaled
01849     // state, the count of the semaphore is decreased by one.
01850     mutex_list *ml = (mutex_list *)hsem;
01851 
01852     pthread_mutex_lock(ml->pm);
01853     if (prev_count != 0) *prev_count = ml->semaphore;
01854     if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
01855     ml->semaphore += increment;
01856     pthread_mutex_unlock(ml->pm);
01857     dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1\n",
01858               hsem, increment, prev_count);
01859     return 1;
01860 }
01861 
01862 
01863 static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
01864 {
01865     long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
01866     dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %d\n",
01867               key, subkey, reserved, access, newkey, result);
01868     if(newkey)dbgprintf("  New key: 0x%x\n", *newkey);
01869     return result;
01870 }
01871 static long WINAPI expRegCloseKey(long key)
01872 {
01873     long result=RegCloseKey(key);
01874     dbgprintf("RegCloseKey(0x%x) => %d\n", key, result);
01875     return result;
01876 }
01877 static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
01878 {
01879     long result=RegQueryValueExA(key, value, reserved, type, data, count);
01880     dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
01881               " => 0x%x\n", key, value, reserved, data, count, result);
01882     if(data && count)dbgprintf("  read %d bytes: '%s'\n", *count, data);
01883     return result;
01884 }
01885 
01886 //from wine source dlls/advapi32/registry.c
01887 static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
01888 {
01889     dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)\n",hkey,name,retkey);
01890     return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
01891                             KEY_ALL_ACCESS , NULL, retkey, NULL );
01892 }
01893 
01894 static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
01895                                       void* classs, long options, long security,
01896                                       void* sec_attr, int* newkey, int* status)
01897 {
01898     long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
01899     dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
01900               " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %d\n",
01901               key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
01902     if(!result && newkey) dbgprintf("  New key: 0x%x\n", *newkey);
01903     if(!result && status) dbgprintf("  New key status: 0x%x\n", *status);
01904     return result;
01905 }
01906 static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
01907 {
01908     long result=RegSetValueExA(key, name, v1, v2, data, size);
01909     dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
01910               key, name, v1, v2, data, *(int*)data, data, size, result);
01911     return result;
01912 }
01913 
01914 static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
01915 {
01916     long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
01917     dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %d\n",
01918               hKey, lpSubKey, phkResult, result);
01919     if(!result && phkResult) dbgprintf("  New key: 0x%x\n", *phkResult);
01920     return result;
01921 }
01922 
01923 static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
01924                                      LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
01925 {
01926     return RegEnumValueA(hkey, index, value, val_count,
01927                          reserved, type, data, count);
01928 }
01929 
01930 static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
01931                                      LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
01932                                      LPFILETIME lpftLastWriteTime)
01933 {
01934     return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
01935                          lpcbClass, lpftLastWriteTime);
01936 }
01937 
01938 static long WINAPI expQueryPerformanceCounter(long long* z)
01939 {
01940     longcount(z);
01941     dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )\n", z, *z);
01942     return 1;
01943 }
01944 
01945 /*
01946  * dummy function RegQueryInfoKeyA(), required by vss codecs
01947  */
01948 static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
01949                                          LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
01950                                          LPDWORD values, LPDWORD max_value, LPDWORD max_data,
01951                                          LPDWORD security, FILETIME *modif )
01952 {
01953     return ERROR_SUCCESS;
01954 }
01955 
01956 /*
01957  * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
01958  */
01959 static double linux_cpuinfo_freq()
01960 {
01961     double freq=-1;
01962     FILE *f;
01963     char line[200];
01964     char *s,*value;
01965 
01966     f = fopen ("/proc/cpuinfo", "r");
01967     if (f != NULL) {
01968         while (fgets(line,sizeof(line),f)!=NULL) {
01969             /* NOTE: the ':' is the only character we can rely on */
01970             if (!(value = strchr(line,':')))
01971                 continue;
01972             /* terminate the valuename */
01973             *value++ = '\0';
01974             /* skip any leading spaces */
01975             while (*value==' ') value++;
01976             if ((s=strchr(value,'\n')))
01977                 *s='\0';
01978 
01979             if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
01980                 && sscanf(value, "%lf", &freq) == 1) {
01981                 freq*=1000;
01982                 break;
01983             }
01984         }
01985         fclose(f);
01986     }
01987     return freq;
01988 }
01989 
01990 
01991 static double solaris_kstat_freq()
01992 {
01993 #if     defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
01994     /*
01995      * try to extract the CPU speed from the solaris kernel's kstat data
01996      */
01997     kstat_ctl_t   *kc;
01998     kstat_t       *ksp;
01999     kstat_named_t *kdata;
02000     int            mhz = 0;
02001 
02002     kc = kstat_open();
02003     if (kc != NULL)
02004     {
02005         ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
02006 
02007         /* kstat found and name/value pairs? */
02008         if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
02009         {
02010             /* read the kstat data from the kernel */
02011             if (kstat_read(kc, ksp, NULL) != -1)
02012             {
02013                 /*
02014                  * lookup desired "clock_MHz" entry, check the expected
02015                  * data type
02016                  */
02017                 kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
02018                 if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
02019                     mhz = kdata->value.i32;
02020             }
02021         }
02022         kstat_close(kc);
02023     }
02024 
02025     if (mhz > 0)
02026         return mhz * 1000.;
02027 #endif  /* HAVE_LIBKSTAT */
02028     return -1;          // kstat stuff is not available, CPU freq is unknown
02029 }
02030 
02031 /*
02032  * Measure CPU freq using the pentium's time stamp counter register (TSC)
02033  */
02034 static double tsc_freq()
02035 {
02036     static double ofreq=0.0;
02037     int i;
02038     int x,y;
02039     i=time(NULL);
02040     if (ofreq != 0.0) return ofreq;
02041     while(i==time(NULL));
02042     x=localcount();
02043     i++;
02044     while(i==time(NULL));
02045     y=localcount();
02046     ofreq = (double)(y-x)/1000.;
02047     return ofreq;
02048 }
02049 
02050 static double CPU_Freq()
02051 {
02052     double freq;
02053 
02054     if ((freq = linux_cpuinfo_freq()) > 0)
02055         return freq;
02056 
02057     if ((freq = solaris_kstat_freq()) > 0)
02058         return freq;
02059 
02060     return tsc_freq();
02061 }
02062 
02063 static long WINAPI expQueryPerformanceFrequency(long long* z)
02064 {
02065     *z=(long long)CPU_Freq();
02066     dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )\n", z, *z);
02067     return 1;
02068 }
02069 static long WINAPI exptimeGetTime()
02070 {
02071     struct timeval t;
02072     long result;
02073     gettimeofday(&t, 0);
02074     result=1000*t.tv_sec+t.tv_usec/1000;
02075     dbgprintf("timeGetTime() => %d\n", result);
02076     return result;
02077 }
02078 static void* WINAPI expLocalHandle(void* v)
02079 {
02080     dbgprintf("LocalHandle(0x%x) => 0x%x\n", v, v);
02081     return v;
02082 }
02083 
02084 static void* WINAPI expGlobalHandle(void* v)
02085 {
02086     dbgprintf("GlobalHandle(0x%x) => 0x%x\n", v, v);
02087     return v;
02088 }
02089 static int WINAPI expGlobalUnlock(void* v)
02090 {
02091     dbgprintf("GlobalUnlock(0x%x) => 1\n", v);
02092     return 1;
02093 }
02094 static void* WINAPI expGlobalFree(void* v)
02095 {
02096     dbgprintf("GlobalFree(0x%x) => 0\n", v);
02097     my_release(v);
02098     //free(v);
02099     return 0;
02100 }
02101 
02102 static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
02103 {
02104     void* result=my_realloc(v, size);
02105     //void* result=realloc(v, size);
02106     dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%x\n", v,size,flags,result);
02107     return result;
02108 }
02109 
02110 static int WINAPI expLocalUnlock(void* v)
02111 {
02112     dbgprintf("LocalUnlock(0x%x) => 1\n", v);
02113     return 1;
02114 }
02115 //
02116 static void* WINAPI expLocalFree(void* v)
02117 {
02118     dbgprintf("LocalFree(0x%x) => 0\n", v);
02119     my_release(v);
02120     return 0;
02121 }
02122 static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
02123 {
02124     HRSRC result;
02125 
02126     result=FindResourceA(module, name, type);
02127     dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%x\n",
02128         module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
02129     return result;
02130 }
02131 
02132 extern HRSRC WINAPI LoadResource(HMODULE, HRSRC);
02133 static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
02134 {
02135     HGLOBAL result=LoadResource(module, res);
02136     dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%x\n", module, res, result);
02137     return result;
02138 }
02139 static void* WINAPI expLockResource(long res)
02140 {
02141     void* result=LockResource(res);
02142     dbgprintf("LockResource(0x%x) => 0x%x\n", res, result);
02143     return result;
02144 }
02145 static int WINAPI expFreeResource(long res)
02146 {
02147     int result=FreeResource(res);
02148     dbgprintf("FreeResource(0x%x) => %d\n", res, result);
02149     return result;
02150 }
02151 //bool fun(HANDLE)
02153 static int WINAPI expCloseHandle(long v1)
02154 {
02155     dbgprintf("CloseHandle(0x%x) => 1\n", v1);
02156     /* do not close stdin,stdout and stderr */
02157     if (v1 > 2)
02158         if (!close(v1))
02159             return 0;
02160     return 1;
02161 }
02162 
02163 static const char* WINAPI expGetCommandLineA()
02164 {
02165     dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n");
02166     return "c:\\aviplay.exe";
02167 }
02168 static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0};
02169 static LPWSTR WINAPI expGetEnvironmentStringsW()
02170 {
02171     dbgprintf("GetEnvironmentStringsW() => 0\n", envs);
02172     return 0;
02173 }
02174 static void * WINAPI expRtlZeroMemory(void *p, size_t len)
02175 {
02176     void* result=memset(p,0,len);
02177     dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%x\n",p,len,result);
02178     return result;
02179 }
02180 static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
02181 {
02182     void* result=memmove(dst,src,len);
02183     dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%x\n",dst,src,len,result);
02184     return result;
02185 }
02186 
02187 static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
02188 {
02189     void* result=memset(p,ch,len);
02190     dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%x\n",p,ch,len,result);
02191     return result;
02192 }
02193 static int WINAPI expFreeEnvironmentStringsW(short* strings)
02194 {
02195     dbgprintf("FreeEnvironmentStringsW(0x%x) => 1\n", strings);
02196     return 1;
02197 }
02198 static int WINAPI expFreeEnvironmentStringsA(char* strings)
02199 {
02200     dbgprintf("FreeEnvironmentStringsA(0x%x) => 1\n", strings);
02201     return 1;
02202 }
02203 
02204 static const char ch_envs[]=
02205 "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1\r\n"
02206 "PATH=C:\\;C:\\windows\\;C:\\windows\\system\r\n";
02207 static LPCSTR WINAPI expGetEnvironmentStrings()
02208 {
02209     dbgprintf("GetEnvironmentStrings() => 0x%x\n", ch_envs);
02210     return (LPCSTR)ch_envs;
02211     // dbgprintf("GetEnvironmentStrings() => 0\n");
02212     // return 0;
02213 }
02214 
02215 static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
02216 {
02217     int i;
02218     dbgprintf("GetStartupInfoA(0x%x) => 1\n");
02219     memset(s, 0, sizeof(*s));
02220     s->cb=sizeof(*s);
02221     // s->lpReserved="Reserved";
02222     // s->lpDesktop="Desktop";
02223     // s->lpTitle="Title";
02224     // s->dwX=s->dwY=0;
02225     // s->dwXSize=s->dwYSize=200;
02226     s->dwFlags=s->wShowWindow=1;
02227     // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
02228     dbgprintf("  cb=%d\n", s->cb);
02229     dbgprintf("  lpReserved='%s'\n", s->lpReserved);
02230     dbgprintf("  lpDesktop='%s'\n", s->lpDesktop);
02231     dbgprintf("  lpTitle='%s'\n", s->lpTitle);
02232     dbgprintf("  dwX=%d dwY=%d dwXSize=%d dwYSize=%d\n",
02233               s->dwX, s->dwY, s->dwXSize, s->dwYSize);
02234     dbgprintf("  dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%d\n",
02235               s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
02236     dbgprintf("  dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%x\n",
02237               s->dwFlags, s->wShowWindow, s->cbReserved2);
02238     dbgprintf("  lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%x\n",
02239               s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
02240     return 1;
02241 }
02242 
02243 static int WINAPI expGetStdHandle(int z)
02244 {
02245     dbgprintf("GetStdHandle(0x%x) => 0x%x\n", z+0x1234);
02246     return z+0x1234;
02247 }
02248 
02249 #ifdef QTX
02250 #define FILE_HANDLE_quicktimeqts        ((HANDLE)0x444)
02251 #define FILE_HANDLE_quicktimeqtx        ((HANDLE)0x445)
02252 #endif
02253 
02254 static int WINAPI expGetFileType(int handle)
02255 {
02256     dbgprintf("GetFileType(0x%x) => 0x3 = pipe\n", handle);
02257     return 0x3;
02258 }
02259 #ifdef QTX
02260 static int WINAPI expGetFileAttributesA(char *filename)
02261 {
02262     dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMAL\n", filename);
02263     if (strstr(filename, "QuickTime.qts"))
02264         return FILE_ATTRIBUTE_SYSTEM;
02265     return FILE_ATTRIBUTE_NORMAL;
02266 }
02267 #endif
02268 static int WINAPI expSetHandleCount(int count)
02269 {
02270     dbgprintf("SetHandleCount(0x%x) => 1\n", count);
02271     return 1;
02272 }
02273 static int WINAPI expGetACP(void)
02274 {
02275     dbgprintf("GetACP() => 0\n");
02276     return 0;
02277 }
02278 extern WINE_MODREF *MODULE32_LookupHMODULE(HMODULE m);
02279 static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
02280 {
02281     WINE_MODREF *mr;
02282     int result;
02283     //printf("File name of module %X (%s) requested\n", module, s);
02284 
02285     if (module == 0 && len >= 12)
02286     {
02287         /* return caller program name */
02288         strcpy(s, "aviplay.dll");
02289         result=1;
02290     }
02291     else if(s==0)
02292         result=0;
02293     else
02294         if(len<35)
02295             result=0;
02296         else
02297         {
02298             result=1;
02299             strcpy(s, "c:\\windows\\system\\");
02300             mr=MODULE32_LookupHMODULE(module);
02301             if(mr==0)//oops
02302                 strcat(s, "aviplay.dll");
02303             else
02304                 if(strrchr(mr->filename, '/')==NULL)
02305                     strcat(s, mr->filename);
02306                 else
02307                     strcat(s, strrchr(mr->filename, '/')+1);
02308         }
02309     if(!s)
02310         dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d\n",
02311                   module, s, len, result);
02312     else
02313         dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )\n",
02314                   module, s, len, result, s);
02315     return result;
02316 }
02317 
02318 static int WINAPI expSetUnhandledExceptionFilter(void* filter)
02319 {
02320     dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1\n", filter);
02321     return 1;//unsupported and probably won't ever be supported
02322 }
02323 
02324 static int WINAPI expLoadLibraryA(char* name)
02325 {
02326     int result = 0;
02327     char* lastbc;
02328     int i;
02329     if (!name)
02330         return -1;
02331     // we skip to the last backslash
02332     // this is effectively eliminating weird characters in
02333     // the text output windows
02334 
02335     lastbc = strrchr(name, '\\');
02336     if (lastbc)
02337     {
02338         int i;
02339         lastbc++;
02340         for (i = 0; 1 ;i++)
02341         {
02342             name[i] = *lastbc++;
02343             if (!name[i])
02344                 break;
02345         }
02346     }
02347     if(strncmp(name, "c:\\windows\\", 11)==0) name += 11;
02348     if(strncmp(name, ".\\", 2)==0) name += 2;
02349 
02350     dbgprintf("Entering LoadLibraryA(%s)\n", name);
02351 
02352     // PIMJ and VIVO audio are loading  kernel32.dll
02353     if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
02354         return MODULE_HANDLE_kernel32;
02355 //      return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
02356                               /* exported -> do not return failed! */
02357 
02358     if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
02359 //      return MODULE_HANDLE_kernel32;
02360         return MODULE_HANDLE_user32;
02361 
02362 #ifdef QTX
02363     if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
02364         return MODULE_HANDLE_wininet;
02365     if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
02366         return MODULE_HANDLE_ddraw;
02367     if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
02368         return MODULE_HANDLE_advapi32;
02369 #endif
02370 
02371     if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
02372         return MODULE_HANDLE_comdlg32;
02373     if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
02374         return MODULE_HANDLE_msvcrt;
02375     if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
02376         return MODULE_HANDLE_ole32;
02377     if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
02378         return MODULE_HANDLE_winmm;
02379 
02380     result=LoadLibraryA(name);
02381     dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%x\n", name, name, def_path, result);
02382 
02383     return result;
02384 }
02385 
02386 static int WINAPI expFreeLibrary(int module)
02387 {
02388 #ifdef QTX
02389     int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
02390 #else
02391     int result=FreeLibrary(module);
02392 #endif
02393     dbgprintf("FreeLibrary(0x%x) => %d\n", module, result);
02394     return result;
02395 }
02396 
02397 static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
02398 {
02399     void* result;
02400     switch(mod){
02401     case MODULE_HANDLE_kernel32:
02402         result=LookupExternalByName("kernel32.dll", name); break;
02403     case MODULE_HANDLE_user32:
02404         result=LookupExternalByName("user32.dll", name); break;
02405 #ifdef QTX
02406     case MODULE_HANDLE_wininet:
02407         result=LookupExternalByName("wininet.dll", name); break;
02408     case MODULE_HANDLE_ddraw:
02409         result=LookupExternalByName("ddraw.dll", name); break;
02410     case MODULE_HANDLE_advapi32:
02411         result=LookupExternalByName("advapi32.dll", name); break;
02412 #endif
02413     case MODULE_HANDLE_comdlg32:
02414         result=LookupExternalByName("comdlg32.dll", name); break;
02415     case MODULE_HANDLE_msvcrt:
02416         result=LookupExternalByName("msvcrt.dll", name); break;
02417     case MODULE_HANDLE_ole32:
02418         result=LookupExternalByName("ole32.dll", name); break;
02419     case MODULE_HANDLE_winmm:
02420         result=LookupExternalByName("winmm.dll", name); break;
02421     default:
02422         result=GetProcAddress(mod, name);
02423     }
02424     dbgprintf("GetProcAddress(0x%x, '%s') => 0x%x\n", mod, name, result);
02425     return result;
02426 }
02427 
02428 static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
02429                                          long flProtect, long dwMaxHigh,
02430                                          long dwMaxLow, const char* name)
02431 {
02432     long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
02433     if(!name)
02434         dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
02435                   "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %d\n",
02436                   hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
02437     else
02438         dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
02439                   "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %d\n",
02440                   hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
02441     return result;
02442 }
02443 
02444 static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
02445 {
02446     long result=OpenFileMappingA(hFile, hz, name);
02447     if(!name)
02448         dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %d\n",
02449                   hFile, hz, result);
02450     else
02451         dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %d\n",
02452                   hFile, hz, name, name, result);
02453     return result;
02454 }
02455 
02456 static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
02457                                      DWORD offLow, DWORD size)
02458 {
02459     dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%x\n",
02460               file,mode,offHigh,offLow,size,(char*)file+offLow);
02461     return (char*)file+offLow;
02462 }
02463 
02464 static void* WINAPI expUnmapViewOfFile(void* view)
02465 {
02466     dbgprintf("UnmapViewOfFile(0x%x) => 0\n", view);
02467     return 0;
02468 }
02469 
02470 static void* WINAPI expSleep(int time)
02471 {
02472 #if HAVE_NANOSLEEP
02473     /* solaris doesn't have thread safe usleep */
02474     struct timespec tsp;
02475     tsp.tv_sec  =  time / 1000000;
02476     tsp.tv_nsec = (time % 1000000) * 1000;
02477     nanosleep(&tsp, NULL);
02478 #else
02479     usleep(time);
02480 #endif
02481     dbgprintf("Sleep(%d) => 0\n", time);
02482     return 0;
02483 }
02484 
02485 // why does IV32 codec want to call this? I don't know ...
02486 static int WINAPI expCreateCompatibleDC(int hdc)
02487 {
02488     int dc = 0;//0x81;
02489     //dbgprintf("CreateCompatibleDC(%d) => 0x81\n", hdc);
02490     dbgprintf("CreateCompatibleDC(%d) => %d\n", hdc, dc);
02491     return dc;
02492 }
02493 
02494 static int WINAPI expGetDeviceCaps(int hdc, int unk)
02495 {
02496     dbgprintf("GetDeviceCaps(0x%x, %d) => 0\n", hdc, unk);
02497 #ifdef QTX
02498     #define BITSPIXEL 12
02499     #define PLANES    14
02500     if (unk == BITSPIXEL)
02501         return 24;
02502     if (unk == PLANES)
02503         return 1;
02504 #endif
02505     return 1;
02506 }
02507 
02508 static WIN_BOOL WINAPI expDeleteDC(int hdc)
02509 {
02510     dbgprintf("DeleteDC(0x%x) => 0\n", hdc);
02511     if (hdc == 0x81)
02512         return 1;
02513     return 0;
02514 }
02515 
02516 static WIN_BOOL WINAPI expDeleteObject(int hdc)
02517 {
02518     dbgprintf("DeleteObject(0x%x) => 1\n", hdc);
02519     /* FIXME - implement code here */
02520     return 1;
02521 }
02522 
02523 /* btvvc32.drv wants this one */
02524 static void* WINAPI expGetWindowDC(int hdc)
02525 {
02526     dbgprintf("GetWindowDC(%d) => 0x0\n", hdc);
02527     return 0;
02528 }
02529 
02530 #ifdef QTX
02531 static int WINAPI expGetWindowRect(HWND win, RECT *r)
02532 {
02533     dbgprintf("GetWindowRect(0x%x, 0x%x) => 1\n", win, r);
02534     /* (win == 0) => desktop */
02535     r->right = PSEUDO_SCREEN_WIDTH;
02536     r->left = 0;
02537     r->bottom = PSEUDO_SCREEN_HEIGHT;
02538     r->top = 0;
02539     return 1;
02540 }
02541 
02542 static int WINAPI expMonitorFromWindow(HWND win, int flags)
02543 {
02544     dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0\n", win, flags);
02545     return 0;
02546 }
02547 
02548 static int WINAPI expMonitorFromRect(RECT *r, int flags)
02549 {
02550     dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0\n", r, flags);
02551     return 0;
02552 }
02553 
02554 static int WINAPI expMonitorFromPoint(void *p, int flags)
02555 {
02556     dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0\n", p, flags);
02557     return 0;
02558 }
02559 
02560 static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r, 
02561     int WINAPI (*callback_proc)(), void *callback_param)
02562 {
02563     dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?\n",
02564         dc, r, callback_proc, callback_param);
02565     return callback_proc(0, dc, r, callback_param);
02566 }
02567 
02568 #if 0
02569 typedef struct tagMONITORINFO {
02570     DWORD  cbSize; 
02571     RECT   rcMonitor; 
02572     RECT   rcWork; 
02573     DWORD  dwFlags; 
02574 } MONITORINFO, *LPMONITORINFO; 
02575 #endif
02576 
02577 #define CCHDEVICENAME 8
02578 typedef struct tagMONITORINFOEX {  
02579     DWORD  cbSize; 
02580     RECT   rcMonitor; 
02581     RECT   rcWork; 
02582     DWORD  dwFlags; 
02583     TCHAR  szDevice[CCHDEVICENAME];
02584 } MONITORINFOEX, *LPMONITORINFOEX; 
02585 
02586 static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
02587 {
02588     dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1\n", mon, lpmi);
02589     
02590     lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
02591     lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
02592     lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
02593     lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
02594 
02595     lpmi->dwFlags = 1; /* primary monitor */
02596 
02597     if (lpmi->cbSize == sizeof(MONITORINFOEX))
02598     {
02599         LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
02600         dbgprintf("MONITORINFOEX!\n");
02601         strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
02602     }
02603     
02604     return 1;
02605 }
02606 
02607 static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
02608         void *dispdev, int flags)
02609 {
02610     dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1\n",
02611         device, device, devnum, dispdev, flags);
02612     return 1;
02613 }
02614 
02615 static int WINAPI expIsWindowVisible(HWND win)
02616 {
02617     dbgprintf("IsWindowVisible(0x%x) => 1\n", win);
02618     return 1;
02619 }
02620 
02621 static HWND WINAPI expGetActiveWindow(void)
02622 {
02623     dbgprintf("GetActiveWindow() => 0\n");
02624     return (HWND)0;
02625 }
02626 
02627 static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
02628 {
02629     strncat(classname, "QuickTime", maxcount);
02630     dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %d\n",
02631         win, classname, maxcount, strlen(classname));
02632     return strlen(classname);
02633 }
02634 
02635 #define LPWNDCLASS void *
02636 static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
02637 {
02638     dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1\n", inst,
02639         classname, classname, wndclass);
02640     return 1;
02641 }
02642 
02643 static int WINAPI expGetWindowLongA(HWND win, int index)
02644 {
02645     dbgprintf("GetWindowLongA(0x%x, %d) => 0\n", win, index);
02646     return 1;
02647 }
02648 
02649 static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
02650 {
02651     dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %d\n", hobj, objsize, obj, objsize);
02652     return objsize;
02653 }
02654 
02655 static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
02656 {
02657     dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0\n", x, y, width, height);
02658     return 0;
02659 }
02660 
02661 static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
02662 {
02663     int i, i2;
02664     dbgprintf("EnumWindows(0x%x, 0x%x) => 1\n", callback_func, callback_param);
02665     i = callback_func(0, callback_param);
02666     i2 = callback_func(1, callback_param);
02667     return i && i2;
02668 }
02669 
02670 static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
02671 {
02672     int tid = pthread_self();
02673     dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %d\n",
02674         win, pid_data, tid);
02675     if (pid_data)
02676         *(int*)pid_data = tid;
02677     return tid;
02678 }
02679 
02680 //HWND      WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
02681 //                                INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
02682 
02683 static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
02684     const char *winname, int style, int x, int y, int w, int h,
02685     HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
02686 {
02687     printf("CreateWindowEx() called\n");
02688     dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1\n",
02689         exstyle, classname, classname, winname, winname, style, x, y, w, h,
02690         parent, menu, inst, param);
02691     printf("CreateWindowEx() called okey\n");
02692     return 1;
02693 }
02694 
02695 static int WINAPI expwaveOutGetNumDevs(void)
02696 {
02697     dbgprintf("waveOutGetNumDevs() => 0\n");
02698     return 0;
02699 }
02700 #endif
02701 
02702 /*
02703  * Returns the number of milliseconds, modulo 2^32, since the start
02704  * of the wineserver.
02705  */
02706 static int WINAPI expGetTickCount(void)
02707 {
02708     static int tcstart = 0;
02709     struct timeval t;
02710     int tc;
02711     gettimeofday( &t, NULL );
02712     tc = ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - tcstart;
02713     if (tcstart == 0)
02714     {
02715         tcstart = 0;
02716         tc = 0;
02717     }
02718     dbgprintf("GetTickCount() => %d\n", tc);
02719     return tc;
02720 }
02721 
02722 static int WINAPI expCreateFontA(void)
02723 {
02724     dbgprintf("CreateFontA() => 0x0\n");
02725     return 1;
02726 }
02727 
02728 /* tried to get pvmjpg work in a different way - no success */
02729 static int WINAPI expDrawTextA(int hDC, char* lpString, int nCount,
02730                                LPRECT lpRect, unsigned int uFormat)
02731 {
02732     dbgprintf("expDrawTextA(%p,...) => 8\n", hDC);
02733     return 8;
02734 }
02735 
02736 static int WINAPI expGetPrivateProfileIntA(const char* appname,
02737                                            const char* keyname,
02738                                            int default_value,
02739                                            const char* filename)
02740 {
02741     int size=255;
02742     char buffer[256];
02743     char* fullname;
02744     int result;
02745 
02746     buffer[255]=0;
02747     if(!(appname && keyname && filename) )
02748     {
02749         dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, default_value );
02750         return default_value;
02751     }
02752     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
02753     strcpy(fullname, "Software\\IniFileMapping\\");
02754     strcat(fullname, appname);
02755     strcat(fullname, "\\");
02756     strcat(fullname, keyname);
02757     strcat(fullname, "\\");
02758     strcat(fullname, filename);
02759     result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)buffer, &size);
02760     if((size>=0)&&(size<256))
02761         buffer[size]=0;
02762     //    printf("GetPrivateProfileIntA(%s, %s, %s) -> %s\n", appname, keyname, filename, buffer);
02763     free(fullname);
02764     if(result)
02765         result=default_value;
02766     else
02767         result=atoi(buffer);
02768     dbgprintf("GetPrivateProfileIntA('%s', '%s', %d, '%s') => %d\n", appname, keyname, default_value, filename, result);
02769     return result;
02770 }
02771 static int WINAPI expGetProfileIntA(const char* appname,
02772                                     const char* keyname,
02773                                     int default_value)
02774 {
02775     dbgprintf("GetProfileIntA -> ");
02776     return expGetPrivateProfileIntA(appname, keyname, default_value, "default");
02777 }
02778 
02779 static int WINAPI expGetPrivateProfileStringA(const char* appname,
02780                                               const char* keyname,
02781                                               const char* def_val,
02782                                               char* dest, unsigned int len,
02783                                               const char* filename)
02784 {
02785     int result;
02786     int size;
02787     char* fullname;
02788     dbgprintf("GetPrivateProfileStringA('%s', '%s', def_val '%s', 0x%x, 0x%x, '%s')", appname, keyname, def_val, dest, len, filename );
02789     if(!(appname && keyname && filename) ) return 0;
02790     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
02791     strcpy(fullname, "Software\\IniFileMapping\\");
02792     strcat(fullname, appname);
02793     strcat(fullname, "\\");
02794     strcat(fullname, keyname);
02795     strcat(fullname, "\\");
02796     strcat(fullname, filename);
02797     size=len;
02798     result=RegQueryValueExA(HKEY_LOCAL_MACHINE, fullname, NULL, NULL, (int*)dest, &size);
02799     free(fullname);
02800     if(result)
02801     {
02802         strncpy(dest, def_val, size);
02803         if (strlen(def_val)< size) size = strlen(def_val);
02804     }
02805     dbgprintf(" => %d ( '%s' )\n", size, dest);
02806     return size;
02807 }
02808 static int WINAPI expWritePrivateProfileStringA(const char* appname,
02809                                                 const char* keyname,
02810                                                 const char* string,
02811                                                 const char* filename)
02812 {
02813     int size=256;
02814     char* fullname;
02815     dbgprintf("WritePrivateProfileStringA('%s', '%s', '%s', '%s')", appname, keyname, string, filename );
02816     if(!(appname && keyname && filename) )
02817     {
02818         dbgprintf(" => -1\n");
02819         return -1;
02820     }
02821     fullname=(char*)malloc(50+strlen(appname)+strlen(keyname)+strlen(filename));
02822     strcpy(fullname, "Software\\IniFileMapping\\");
02823     strcat(fullname, appname);
02824     strcat(fullname, "\\");
02825     strcat(fullname, keyname);
02826     strcat(fullname, "\\");
02827     strcat(fullname, filename);
02828     RegSetValueExA(HKEY_LOCAL_MACHINE, fullname, 0, REG_SZ, (int*)string, strlen(string));
02829     //    printf("RegSetValueExA(%s,%d)\n", string, strlen(string));
02830     //    printf("WritePrivateProfileStringA(%s, %s, %s, %s)\n", appname, keyname, string, filename );
02831     free(fullname);
02832     dbgprintf(" => 0\n");
02833     return 0;
02834 }
02835 
02836 unsigned int _GetPrivateProfileIntA(const char* appname, const char* keyname, INT default_value, const char* filename)
02837 {
02838     return expGetPrivateProfileIntA(appname, keyname, default_value, filename);
02839 }
02840 int _GetPrivateProfileStringA(const char* appname, const char* keyname,
02841                               const char* def_val, char* dest, unsigned int len, const char* filename)
02842 {
02843     return expGetPrivateProfileStringA(appname, keyname, def_val, dest, len, filename);
02844 }
02845 int _WritePrivateProfileStringA(const char* appname, const char* keyname,
02846                                 const char* string, const char* filename)
02847 {
02848     return expWritePrivateProfileStringA(appname, keyname, string, filename);
02849 }
02850 
02851 
02852 
02853 static int WINAPI expDefDriverProc(int _private, int id, int msg, int arg1, int arg2)
02854 {
02855     dbgprintf("DefDriverProc(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0\n", _private, id, msg, arg1, arg2);
02856     return 0;
02857 }
02858 
02859 static int WINAPI expSizeofResource(int v1, int v2)
02860 {
02861     int result=SizeofResource(v1, v2);
02862     dbgprintf("SizeofResource(0x%x, 0x%x) => %d\n", v1, v2, result);
02863     return result;
02864 }
02865 
02866 static int WINAPI expGetLastError()
02867 {
02868     int result=GetLastError();
02869     dbgprintf("GetLastError() => 0x%x\n", result);
02870     return result;
02871 }
02872 
02873 static void WINAPI expSetLastError(int error)
02874 {
02875     dbgprintf("SetLastError(0x%x)\n", error);
02876     SetLastError(error);
02877 }
02878 
02879 static int WINAPI expStringFromGUID2(GUID* guid, char* str, int cbMax)
02880 {
02881     int result=snprintf(str, cbMax, "%.8x-%.4x-%.4x-%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
02882                         guid->f1, guid->f2, guid->f3,
02883                         (unsigned char)guid->f4[0], (unsigned char)guid->f4[1],
02884                         (unsigned char)guid->f4[2], (unsigned char)guid->f4[3],
02885                         (unsigned char)guid->f4[4], (unsigned char)guid->f4[5],
02886                         (unsigned char)guid->f4[6], (unsigned char)guid->f4[7]);
02887     dbgprintf("StringFromGUID2(0x%x, 0x%x='%s', %d) => %d\n", guid, str, str, cbMax, result);
02888     return result;
02889 }
02890 
02891 
02892 static int WINAPI expGetFileVersionInfoSizeA(const char* name, int* lpHandle)
02893 {
02894     dbgprintf("GetFileVersionInfoSizeA(0x%x='%s', 0x%X) => 0\n", name, name, lpHandle);
02895     return 0;
02896 }
02897 
02898 static int WINAPI expIsBadStringPtrW(const short* string, int nchars)
02899 {
02900     int result;
02901     if(string==0)result=1; else result=0;
02902     dbgprintf("IsBadStringPtrW(0x%x, %d) => %d", string, nchars, result);
02903     if(string)wch_print(string);
02904     return result;
02905 }
02906 static int WINAPI expIsBadStringPtrA(const char* string, int nchars)
02907 {
02908     return expIsBadStringPtrW((const short*)string, nchars);
02909 }
02910 static long WINAPI expInterlockedExchangeAdd( long* dest, long incr )
02911 {
02912     long ret;
02913     __asm__ __volatile__
02914         (
02915          "lock; xaddl %0,(%1)"
02916          : "=r" (ret)
02917          : "r" (dest), "0" (incr)
02918          : "memory"
02919         );
02920     return ret;
02921 }
02922 
02923 static long WINAPI expInterlockedCompareExchange( unsigned long* dest, unsigned long exchange, unsigned long comperand)
02924 {
02925     unsigned long retval = *dest;
02926     if(*dest == comperand)
02927         *dest = exchange;
02928     return retval;
02929 }
02930 
02931 static long WINAPI expInterlockedIncrement( long* dest )
02932 {
02933     long result=expInterlockedExchangeAdd( dest, 1 ) + 1;
02934     dbgprintf("InterlockedIncrement(0x%x => %d) => %d\n", dest, *dest, result);
02935     return result;
02936 }
02937 static long WINAPI expInterlockedDecrement( long* dest )
02938 {
02939     long result=expInterlockedExchangeAdd( dest, -1 ) - 1;
02940     dbgprintf("InterlockedDecrement(0x%x => %d) => %d\n", dest, *dest, result);
02941     return result;
02942 }
02943 
02944 static void WINAPI expOutputDebugStringA( const char* string )
02945 {
02946     dbgprintf("OutputDebugStringA(0x%x='%s')\n", string);
02947     fprintf(stderr, "DEBUG: %s\n", string);
02948 }
02949 
02950 static int WINAPI expGetDC(int hwnd)
02951 {
02952     dbgprintf("GetDC(0x%x) => 1\n", hwnd);
02953     return 1;
02954 }
02955 
02956 static int WINAPI expReleaseDC(int hwnd, int hdc)
02957 {
02958     dbgprintf("ReleaseDC(0x%x, 0x%x) => 1\n", hwnd, hdc);
02959     return 1;
02960 }
02961 
02962 static int WINAPI expGetDesktopWindow()
02963 {
02964     dbgprintf("GetDesktopWindow() => 0\n");
02965     return 0;
02966 }
02967 
02968 static int cursor[100];
02969 
02970 static int WINAPI expLoadCursorA(int handle,LPCSTR name)
02971 {
02972     dbgprintf("LoadCursorA(%d, 0x%x='%s') => 0x%x\n", handle, name, (int)&cursor[0]);
02973     return (int)&cursor[0];
02974 }
02975 static int WINAPI expSetCursor(void *cursor)
02976 {
02977     dbgprintf("SetCursor(0x%x) => 0x%x\n", cursor, cursor);
02978     return (int)cursor;
02979 }
02980 static int WINAPI expGetCursorPos(void *cursor)
02981 {
02982     dbgprintf("GetCursorPos(0x%x) => 0x%x\n", cursor, cursor);
02983     return 1;
02984 }
02985 #ifdef QTX
02986 static int show_cursor = 0;
02987 static int WINAPI expShowCursor(int show)
02988 {
02989     dbgprintf("ShowCursor(%d) => %d\n", show, show);
02990     if (show)
02991         show_cursor++;
02992     else
02993         show_cursor--;
02994     return show_cursor;
02995 }
02996 #endif
02997 static int WINAPI expRegisterWindowMessageA(char *message)
02998 {
02999     dbgprintf("RegisterWindowMessageA(%s)\n", message);
03000     return 1;
03001 }
03002 static int WINAPI expGetProcessVersion(int pid)
03003 {
03004     dbgprintf("GetProcessVersion(%d)\n", pid);
03005     return 1;
03006 }
03007 static int WINAPI expGetCurrentThread(void)
03008 {
03009 #warning FIXME!
03010     dbgprintf("GetCurrentThread() => %x\n", 0xcfcf9898);
03011     return 0xcfcf9898;
03012 }
03013 static int WINAPI expGetOEMCP(void)
03014 {
03015     dbgprintf("GetOEMCP()\n");
03016     return 1;
03017 }
03018 static int WINAPI expGetCPInfo(int cp,void *info)
03019 {
03020     dbgprintf("GetCPInfo()\n");
03021     return 0;
03022 }
03023 #ifdef QTX
03024 #define SM_CXSCREEN             0
03025 #define SM_CYSCREEN             1
03026 #define SM_XVIRTUALSCREEN       76
03027 #define SM_YVIRTUALSCREEN       77
03028 #define SM_CXVIRTUALSCREEN      78
03029 #define SM_CYVIRTUALSCREEN      79
03030 #define SM_CMONITORS            80
03031 #endif
03032 static int WINAPI expGetSystemMetrics(int index)
03033 {
03034     dbgprintf("GetSystemMetrics(%d)\n", index);
03035 #ifdef QTX
03036     switch(index)
03037     {
03038         case SM_XVIRTUALSCREEN:
03039         case SM_YVIRTUALSCREEN:
03040             return 0;
03041         case SM_CXSCREEN:
03042         case SM_CXVIRTUALSCREEN:
03043             return PSEUDO_SCREEN_WIDTH;
03044         case SM_CYSCREEN:
03045         case SM_CYVIRTUALSCREEN:
03046             return PSEUDO_SCREEN_HEIGHT;
03047         case SM_CMONITORS:
03048             return 1;
03049     }
03050 #endif
03051     return 1;
03052 }
03053 static int WINAPI expGetSysColor(int index)
03054 {
03055     dbgprintf("GetSysColor(%d) => 1\n", index);
03056     return 1;
03057 }
03058 static int WINAPI expGetSysColorBrush(int index)
03059 {
03060     dbgprintf("GetSysColorBrush(%d)\n", index);
03061     return 1;
03062 }
03063 
03064 
03065 
03066 static int WINAPI expGetSystemPaletteEntries(int hdc, int iStartIndex, int nEntries, void* lppe)
03067 {
03068     dbgprintf("GetSystemPaletteEntries(0x%x, 0x%x, 0x%x, 0x%x) => 0\n",
03069               hdc, iStartIndex, nEntries, lppe);
03070     return 0;
03071 }
03072 
03073 /*
03074  typedef struct _TIME_ZONE_INFORMATION {
03075  long Bias;
03076  char StandardName[32];
03077  SYSTEMTIME StandardDate;
03078  long StandardBias;
03079  char DaylightName[32];
03080  SYSTEMTIME DaylightDate;
03081  long DaylightBias;
03082  } TIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
03083  */
03084 
03085 static int WINAPI expGetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
03086 {
03087     const short name[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'S', 't', 'a',
03088     'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e', 0};
03089     const short pname[]={'C', 'e', 'n', 't', 'r', 'a', 'l', ' ', 'D', 'a', 'y',
03090     'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e', 0};
03091     dbgprintf("GetTimeZoneInformation(0x%x) => TIME_ZONE_ID_STANDARD\n");
03092     memset(lpTimeZoneInformation, 0, sizeof(TIME_ZONE_INFORMATION));
03093     lpTimeZoneInformation->Bias=360;//GMT-6
03094     memcpy(lpTimeZoneInformation->StandardName, name, sizeof(name));
03095     lpTimeZoneInformation->StandardDate.wMonth=10;
03096     lpTimeZoneInformation->StandardDate.wDay=5;
03097     lpTimeZoneInformation->StandardDate.wHour=2;
03098     lpTimeZoneInformation->StandardBias=0;
03099     memcpy(lpTimeZoneInformation->DaylightName, pname, sizeof(pname));
03100     lpTimeZoneInformation->DaylightDate.wMonth=4;
03101     lpTimeZoneInformation->DaylightDate.wDay=1;
03102     lpTimeZoneInformation->DaylightDate.wHour=2;
03103     lpTimeZoneInformation->DaylightBias=-60;
03104     return TIME_ZONE_ID_STANDARD;
03105 }
03106 
03107 static void WINAPI expGetLocalTime(SYSTEMTIME* systime)
03108 {
03109     time_t local_time;
03110     struct tm *local_tm;
03111     struct timeval tv;
03112 
03113     dbgprintf("GetLocalTime(0x%x)\n");
03114     gettimeofday(&tv, NULL);
03115     local_time=tv.tv_sec;
03116     local_tm=localtime(&local_time);
03117 
03118     systime->wYear = local_tm->tm_year + 1900;
03119     systime->wMonth = local_tm->tm_mon + 1;
03120     systime->wDayOfWeek = local_tm->tm_wday;
03121     systime->wDay = local_tm->tm_mday;
03122     systime->wHour = local_tm->tm_hour;
03123     systime->wMinute = local_tm->tm_min;
03124     systime->wSecond = local_tm->tm_sec;
03125     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
03126     dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
03127               "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
03128               "  Milliseconds: %d\n",
03129               systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
03130               systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
03131 }
03132 
03133 static int WINAPI expGetSystemTime(SYSTEMTIME* systime)
03134 {
03135     time_t local_time;
03136     struct tm *local_tm;
03137     struct timeval tv;
03138 
03139     dbgprintf("GetSystemTime(0x%x)\n", systime);
03140     gettimeofday(&tv, NULL);
03141     local_time=tv.tv_sec;
03142     local_tm=gmtime(&local_time);
03143 
03144     systime->wYear = local_tm->tm_year + 1900;
03145     systime->wMonth = local_tm->tm_mon + 1;
03146     systime->wDayOfWeek = local_tm->tm_wday;
03147     systime->wDay = local_tm->tm_mday;
03148     systime->wHour = local_tm->tm_hour;
03149     systime->wMinute = local_tm->tm_min;
03150     systime->wSecond = local_tm->tm_sec;
03151     systime->wMilliseconds = (tv.tv_usec / 1000) % 1000;
03152     dbgprintf("  Year: %d\n  Month: %d\n  Day of week: %d\n"
03153               "  Day: %d\n  Hour: %d\n  Minute: %d\n  Second:  %d\n"
03154               "  Milliseconds: %d\n",
03155               systime->wYear, systime->wMonth, systime->wDayOfWeek, systime->wDay,
03156               systime->wHour, systime->wMinute, systime->wSecond, systime->wMilliseconds);
03157     return 0;
03158 }
03159 
03160 #define SECS_1601_TO_1970  ((369 * 365 + 89) * 86400ULL)
03161 static void WINAPI expGetSystemTimeAsFileTime(FILETIME* systime)
03162 {
03163     struct tm *local_tm;
03164     struct timeval tv;
03165     unsigned long long secs;
03166 
03167     dbgprintf("GetSystemTime(0x%x)\n", systime);
03168     gettimeofday(&tv, NULL);
03169     secs = (tv.tv_sec + SECS_1601_TO_1970) * 10000000;
03170     secs += tv.tv_usec * 10;
03171     systime->dwLowDateTime = secs & 0xffffffff;
03172     systime->dwHighDateTime = (secs >> 32);
03173 }
03174 
03175 static int WINAPI expGetEnvironmentVariableA(const char* name, char* field, int size)
03176 {
03177     char *p;
03178     //    printf("%s %x %x\n", name, field, size);
03179     if(field)field[0]=0;
03180     /*
03181      p = getenv(name);
03182      if (p) strncpy(field,p,size);
03183      */
03184     if (strcmp(name,"__MSVCRT_HEAP_SELECT")==0)
03185         strcpy(field,"__GLOBAL_HEAP_SELECTED,1");
03186     dbgprintf("GetEnvironmentVariableA(0x%x='%s', 0x%x, %d) => %d\n", name, name, field, size, strlen(field));
03187     return strlen(field);
03188 }
03189 
03190 static int WINAPI expSetEnvironmentVariableA(const char *name, const char *value)
03191 {
03192     dbgprintf("SetEnvironmentVariableA(%s, %s)\n", name, value);
03193     return 0;
03194 }
03195 
03196 static void* WINAPI expCoTaskMemAlloc(ULONG cb)
03197 {
03198     return my_mreq(cb, 0);
03199 }
03200 static void WINAPI expCoTaskMemFree(void* cb)
03201 {
03202     my_release(cb);
03203 }
03204 
03205 
03206 
03207 
03208 void* CoTaskMemAlloc(unsigned long cb)
03209 {
03210     return expCoTaskMemAlloc(cb);
03211 }
03212 void CoTaskMemFree(void* cb)
03213 {
03214     expCoTaskMemFree(cb);
03215 }
03216 
03217 struct COM_OBJECT_INFO
03218 {
03219     GUID clsid;
03220     long (*GetClassObject) (GUID* clsid, const GUID* iid, void** ppv);
03221 };
03222 
03223 static struct COM_OBJECT_INFO* com_object_table=0;
03224 static int com_object_size=0;
03225 int RegisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
03226 {
03227     if(!clsid || !gcs)
03228         return -1;
03229     com_object_table=realloc(com_object_table, sizeof(struct COM_OBJECT_INFO)*(++com_object_size));
03230     com_object_table[com_object_size-1].clsid=*clsid;
03231     com_object_table[com_object_size-1].GetClassObject=gcs;
03232     return 0;
03233 }
03234 
03235 int UnregisterComClass(const GUID* clsid, GETCLASSOBJECT gcs)
03236 {
03237     int found = 0;
03238     int i = 0;
03239     if(!clsid || !gcs)
03240         return -1;
03241 
03242     if (com_object_table == 0)
03243         printf("Warning: UnregisterComClass() called without any registered class\n");
03244     while (i < com_object_size)
03245     {
03246         if (found && i > 0)
03247         {
03248             memcpy(&com_object_table[i - 1].clsid,
03249                    &com_object_table[i].clsid, sizeof(GUID));
03250             com_object_table[i - 1].GetClassObject =
03251                 com_object_table[i].GetClassObject;
03252         }
03253         else if (memcmp(&com_object_table[i].clsid, clsid, sizeof(GUID)) == 0
03254                  && com_object_table[i].GetClassObject == gcs)
03255         {
03256             found++;
03257         }
03258         i++;
03259     }
03260     if (found)
03261     {
03262         if (--com_object_size == 0)
03263         {
03264             free(com_object_table);
03265             com_object_table = 0;
03266         }
03267     }
03268     return 0;
03269 }
03270 
03271 
03272 const GUID IID_IUnknown =
03273 {
03274     0x00000000, 0x0000, 0x0000,
03275     {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
03276 };
03277 const GUID IID_IClassFactory =
03278 {
03279     0x00000001, 0x0000, 0x0000,
03280     {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
03281 };
03282 
03283 static long WINAPI expCoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
03284                                        long dwClsContext, const GUID* riid, void** ppv)
03285 {
03286     int i;
03287     struct COM_OBJECT_INFO* ci=0;
03288     for(i=0; i<com_object_size; i++)
03289         if(!memcmp(rclsid, &com_object_table[i].clsid, sizeof(GUID)))
03290             ci=&com_object_table[i];
03291     if(!ci)return REGDB_E_CLASSNOTREG;
03292     // in 'real' world we should mess with IClassFactory here
03293     i=ci->GetClassObject(rclsid, riid, ppv);
03294     return i;
03295 }
03296 
03297 long CoCreateInstance(GUID* rclsid, struct IUnknown* pUnkOuter,
03298                       long dwClsContext, const GUID* riid, void** ppv)
03299 {
03300     return expCoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
03301 }
03302 
03303 static int WINAPI expIsRectEmpty(CONST RECT *lprc)
03304 {
03305     int r = 0;
03306     int w,h;
03307 //trapbug();
03308     if (lprc)
03309     {
03310         w = lprc->right - lprc->left;
03311         h = lprc->bottom - lprc->top;
03312         if (w <= 0 || h <= 0)
03313             r = 1;
03314     }
03315     else
03316         r = 1;
03317 
03318     dbgprintf("IsRectEmpty(%p) => %s\n", lprc, (r) ? "TRUE" : "FALSE");
03319     //printf("Rect: left: %d, top: %d, right: %d, bottom: %d\n", lprc->left, lprc->top, lprc->right, lprc->bottom);
03320 //    return 0; // wmv9?
03321     return r; // TM20
03322 }
03323 
03324 static int _adjust_fdiv=0; //what's this? - used to adjust division
03325 
03326 
03327 
03328 
03329 static unsigned int WINAPI expGetTempPathA(unsigned int len, char* path)
03330 {
03331     dbgprintf("GetTempPathA(%d, 0x%x)", len, path);
03332     if(len<5)
03333     {
03334         dbgprintf(" => 0\n");
03335         return 0;
03336     }
03337     strcpy(path, "/tmp");
03338     dbgprintf(" => 5 ( '/tmp' )\n");
03339     return 5;
03340 }
03341 /*
03342  FYI:
03343  typedef struct
03344  {
03345  DWORD     dwFileAttributes;
03346  FILETIME  ftCreationTime;
03347  FILETIME  ftLastAccessTime;
03348  FILETIME  ftLastWriteTime;
03349  DWORD     nFileSizeHigh;
03350  DWORD     nFileSizeLow;
03351  DWORD     dwReserved0;
03352  DWORD     dwReserved1;
03353  CHAR      cFileName[260];
03354  CHAR      cAlternateFileName[14];
03355  } WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
03356  */
03357 
03358 static DIR* qtx_dir=NULL;
03359 
03360 static WIN_BOOL WINAPI expFindNextFileA(HANDLE h,LPWIN32_FIND_DATAA lpfd)
03361 {
03362 #ifdef QTX
03363     dbgprintf("FindNextFileA(0x%x, 0x%x) => 0\n", h, lpfd);
03364     if(h==FILE_HANDLE_quicktimeqtx){
03365         struct dirent* d;
03366         if(!qtx_dir) return 0;
03367         while((d=readdir(qtx_dir))){
03368             char* x=strrchr(d->d_name,'.');
03369             if(!x) continue;
03370             if(strcmp(x,".qtx")) continue;
03371             strcpy(lpfd->cFileName,d->d_name);
03372 //          sprintf(lpfd->cAlternateFileName,"%-8s.qtx",d->d_name);
03373             strcpy(lpfd->cAlternateFileName,"foobar.qtx");
03374             printf("### FindNext: %s\n",lpfd->cFileName);
03375             return 1;
03376         }
03377         closedir(qtx_dir); qtx_dir=NULL;
03378         return 0;
03379     }
03380 #endif
03381     return 0;
03382 }
03383 
03384 static HANDLE WINAPI expFindFirstFileA(LPCSTR s, LPWIN32_FIND_DATAA lpfd)
03385 {
03386     dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => 0\n", s, s, lpfd);
03387 //    printf("\n### FindFirstFileA('%s')...\n",s);
03388 #ifdef QTX
03389     if(strstr(s, "quicktime\\*.QTX")){
03390         dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTX\n", s, s, lpfd);
03391         printf("\n### Searching for QuickTime plugins (*.qtx) at %s...\n",def_path);
03392         qtx_dir=opendir(def_path);
03393         if(!qtx_dir) return (HANDLE)-1;
03394         memset(lpfd,0,sizeof(*lpfd));
03395         if(expFindNextFileA(FILE_HANDLE_quicktimeqtx,lpfd))
03396             return FILE_HANDLE_quicktimeqtx;
03397         printf("loader: Couldn't find the QuickTime plugins (.qtx files) at %s\n",def_path);
03398         return (HANDLE)-1;
03399     }
03400 #if 0
03401     if(strstr(s, "QuickTime.qts")){
03402         dbgprintf("FindFirstFileA(0x%x='%s', 0x%x) => QTS\n", s, s, lpfd);
03403 //      if(!strcmp(s,"C:\\windows\\QuickTime.qts\\QuickTime.qts\\*.QTX"))
03404 //          return (HANDLE)-1;
03405         strcpy(lpfd->cFileName, "QuickTime.qts");
03406         strcpy(lpfd->cAlternateFileName, "QuickT~1.qts");
03407         return FILE_HANDLE_quicktimeqts;
03408     }
03409 #endif
03410 #endif
03411     if(strstr(s, "*.vwp")){
03412         // hack for VoxWare codec plugins:
03413         strcpy(lpfd->cFileName, "msms001.vwp");
03414         strcpy(lpfd->cAlternateFileName, "msms001.vwp");
03415         return (HANDLE)0;
03416     }
03417     // return 'file not found'
03418     return (HANDLE)-1;
03419 }
03420 
03421 static WIN_BOOL WINAPI expFindClose(HANDLE h)
03422 {
03423     dbgprintf("FindClose(0x%x) => 0\n", h);
03424 #ifdef QTX
03425 //    if(h==FILE_HANDLE_quicktimeqtx && qtx_dir){
03426 //      closedir(qtx_dir);
03427 //      qtx_dir=NULL;
03428 //    }
03429 #endif
03430     return 0;
03431 }
03432 static UINT WINAPI expSetErrorMode(UINT i)
03433 {
03434     dbgprintf("SetErrorMode(%d) => 0\n", i);
03435     return 0;
03436 }
03437 static UINT WINAPI expGetWindowsDirectoryA(LPSTR s,UINT c)
03438 {
03439     char windir[]="c:\\windows";
03440     int result;
03441     strncpy(s, windir, c);
03442     result=1+((c<strlen(windir))?c:strlen(windir));
03443     dbgprintf("GetWindowsDirectoryA(0x%x, %d) => %d\n", s, c, result);
03444     return result;
03445 }
03446 #ifdef QTX
03447 static UINT WINAPI expGetCurrentDirectoryA(UINT c, LPSTR s)
03448 {
03449     char curdir[]="c:\\";
03450     int result;
03451     strncpy(s, curdir, c);
03452     result=1+((c<strlen(curdir))?c:strlen(curdir));
03453     dbgprintf("GetCurrentDirectoryA(0x%x, %d) => %d\n", s, c, result);
03454     return result;
03455 }
03456 
03457 static int WINAPI expSetCurrentDirectoryA(const char *pathname)
03458 {
03459     dbgprintf("SetCurrentDirectoryA(0x%x = %s) => 1\n", pathname, pathname);
03460 #if 0
03461     if (strrchr(pathname, '\\'))
03462         chdir(strcat(strrchr(pathname, '\\')+1, '/'));
03463     else
03464         chdir(pathname);
03465 #endif
03466     return 1;
03467 }
03468 
03469 static int WINAPI expCreateDirectoryA(const char *pathname, void *sa)
03470 {
03471     dbgprintf("CreateDirectory(0x%x = %s, 0x%x) => 1\n",
03472         pathname, pathname, sa);
03473 #if 0
03474     p = strrchr(pathname, '\\')+1;
03475     strcpy(&buf[0], p); /* should be strncpy */
03476     if (!strlen(p))
03477     {
03478         buf[0] = '.';
03479         buf[1] = 0;
03480     }
03481 #if 0    
03482     if (strrchr(pathname, '\\'))
03483         mkdir(strcat(strrchr(pathname, '\\')+1, '/'), 666);
03484     else
03485         mkdir(pathname, 666);
03486 #endif
03487     mkdir(&buf);
03488 #endif
03489     return 1;
03490 }
03491 #endif
03492 static WIN_BOOL  WINAPI expDeleteFileA(LPCSTR s)
03493 {
03494     dbgprintf("DeleteFileA(0x%x='%s') => 0\n", s, s);
03495     return 0;
03496 }
03497 static WIN_BOOL  WINAPI expFileTimeToLocalFileTime(const FILETIME* cpf, LPFILETIME pf)
03498 {
03499     dbgprintf("FileTimeToLocalFileTime(0x%x, 0x%x) => 0\n", cpf, pf);
03500     return 0;
03501 }
03502 
03503 static UINT WINAPI expGetTempFileNameA(LPCSTR cs1,LPCSTR cs2,UINT i,LPSTR ps)
03504 {
03505     char mask[16]="/tmp/AP_XXXXXX";
03506     int result;
03507     dbgprintf("GetTempFileNameA(0x%x='%s', 0x%x='%s', %d, 0x%x)", cs1, cs1, cs2, cs2, i, ps);
03508     if(i && i<10)
03509     {
03510         dbgprintf(" => -1\n");
03511         return -1;
03512     }
03513     result=mkstemp(mask);
03514     sprintf(ps, "AP%d", result);
03515     dbgprintf(" => %d\n", strlen(ps));
03516     return strlen(ps);
03517 }
03518 //
03519 // This func might need proper implementation if we want AngelPotion codec.
03520 // They try to open APmpeg4v1.apl with it.
03521 // DLL will close opened file with CloseHandle().
03522 //
03523 static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2,
03524                                     LPSECURITY_ATTRIBUTES p1, DWORD i3,DWORD i4,HANDLE i5)
03525 {
03526     dbgprintf("CreateFileA(0x%x='%s', %d, %d, 0x%x, %d, %d, 0x%x)\n", cs1, cs1, i1,
03527               i2, p1, i3, i4, i5);
03528     if((!cs1) || (strlen(cs1)<2))return -1;
03529 
03530 #ifdef QTX
03531     if(strstr(cs1, "QuickTime.qts"))
03532     {
03533         int result;
03534         char* tmp=(char*)malloc(strlen(def_path)+50);
03535         strcpy(tmp, def_path);
03536         strcat(tmp, "/");
03537         strcat(tmp, "QuickTime.qts");
03538         result=open(tmp, O_RDONLY);
03539         free(tmp);
03540         return result;
03541     }
03542     if(strstr(cs1, ".qtx"))
03543     {
03544         int result;
03545         char* tmp=(char*)malloc(strlen(def_path)+250);
03546         char* x=strrchr(cs1,'\\');
03547         sprintf(tmp,"%s/%s",def_path,x?(x+1):cs1);
03548 //      printf("### Open: %s -> %s\n",cs1,tmp);
03549         result=open(tmp, O_RDONLY);
03550         free(tmp);
03551         return result;
03552     }
03553 #endif
03554 
03555     if(strncmp(cs1, "AP", 2) == 0)
03556     {
03557         int result;
03558         char* tmp=(char*)malloc(strlen(def_path)+50);
03559         strcpy(tmp, def_path);
03560         strcat(tmp, "/");
03561         strcat(tmp, "APmpg4v1.apl");
03562         result=open(tmp, O_RDONLY);
03563         free(tmp);
03564         return result;
03565     }
03566     if (strstr(cs1, "vp3"))
03567     {
03568         int r;
03569         int flg = 0;
03570         char* tmp=(char*)malloc(20 + strlen(cs1));
03571         strcpy(tmp, "/tmp/");
03572         strcat(tmp, cs1);
03573         r = 4;
03574         while (tmp[r])
03575         {
03576             if (tmp[r] == ':' || tmp[r] == '\\')
03577                 tmp[r] = '_';
03578             r++;
03579         }
03580         if (GENERIC_READ & i1)
03581             flg |= O_RDONLY;
03582         else if (GENERIC_WRITE & i1)
03583         {
03584             flg |= O_WRONLY;
03585             printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", tmp, r, flg);
03586         }
03587         r=open(tmp, flg);
03588         free(tmp);
03589         return r;
03590     }
03591 
03592     // Needed by wnvplay1.dll
03593     if (strstr(cs1, "WINNOV.bmp"))
03594     {
03595         int r;
03596         r=open("/dev/null", 0);
03597         return r;
03598     }
03599 
03600 #if 0
03601     /* we need this for some virtualdub filters */
03602     {
03603         int r;
03604         int flg = 0;
03605         if (GENERIC_READ & i1)
03606             flg |= O_RDONLY;
03607         else if (GENERIC_WRITE & i1)
03608         {
03609             flg |= O_WRONLY;
03610             printf("Warning: openning filename %s  %d (flags; 0x%x) for write\n", cs1, r, flg);
03611         }
03612         r=open(cs1, flg);
03613         return r;
03614     }
03615 #endif
03616 
03617     return atoi(cs1+2);
03618 }
03619 static UINT WINAPI expGetSystemDirectoryA(
03620   char* lpBuffer,  // address of buffer for system directory
03621   UINT uSize        // size of directory buffer
03622 ){
03623     dbgprintf("GetSystemDirectoryA(%p,%d)\n", lpBuffer,uSize);
03624     if(!lpBuffer) strcpy(lpBuffer,".");
03625     return 1;
03626 }
03627 /*
03628 static char sysdir[]=".";
03629 static LPCSTR WINAPI expGetSystemDirectoryA()
03630 {
03631     dbgprintf("GetSystemDirectoryA() => 0x%x='%s'\n", sysdir, sysdir);
03632     return sysdir;
03633 }
03634 */
03635 static DWORD WINAPI expGetFullPathNameA
03636 (
03637         LPCTSTR lpFileName,
03638         DWORD nBufferLength,
03639         LPTSTR lpBuffer,
03640         LPTSTR lpFilePart
03641 ){
03642     if(!lpFileName) return 0;
03643     dbgprintf("GetFullPathNameA('%s',%d,%p,%p)\n",lpFileName,nBufferLength,
03644         lpBuffer, lpFilePart);
03645 #if 0
03646 #ifdef QTX
03647     strcpy(lpFilePart, "Quick123.qts");
03648 #else
03649     strcpy(lpFilePart, lpFileName);
03650 #endif
03651 #else
03652     if (strrchr(lpFileName, '\\'))
03653         lpFilePart = strrchr(lpFileName, '\\');
03654     else
03655         lpFilePart = (LPTSTR)lpFileName;
03656 #endif
03657     strcpy(lpBuffer, lpFileName);
03658 //    strncpy(lpBuffer, lpFileName, rindex(lpFileName, '\\')-lpFileName);
03659     return strlen(lpBuffer);
03660 }
03661 
03662 static DWORD WINAPI expGetShortPathNameA
03663 (
03664         LPCSTR longpath,
03665         LPSTR shortpath,
03666         DWORD shortlen
03667 ){
03668     if(!longpath) return 0;
03669     dbgprintf("GetShortPathNameA('%s',%p,%d)\n",longpath,shortpath,shortlen);
03670     strcpy(shortpath,longpath);
03671     return strlen(shortpath);
03672 }
03673 
03674 static WIN_BOOL WINAPI expReadFile(HANDLE h,LPVOID pv,DWORD size,LPDWORD rd,LPOVERLAPPED unused)
03675 {
03676     int result;
03677     dbgprintf("ReadFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, rd);
03678     result=read(h, pv, size);
03679     if(rd)*rd=result;
03680     if(!result)return 0;
03681     return 1;
03682 }
03683 
03684 static WIN_BOOL WINAPI expWriteFile(HANDLE h,LPCVOID pv,DWORD size,LPDWORD wr,LPOVERLAPPED unused)
03685 {
03686     int result;
03687     dbgprintf("WriteFile(%d, 0x%x, %d -> 0x%x)\n", h, pv, size, wr);
03688     if(h==1234)h=1;
03689     result=write(h, pv, size);
03690     if(wr)*wr=result;
03691     if(!result)return 0;
03692     return 1;
03693 }
03694 static DWORD  WINAPI expSetFilePointer(HANDLE h, LONG val, LPLONG ext, DWORD whence)
03695 {
03696     int wh;
03697     dbgprintf("SetFilePointer(%d, 0x%x, 0x%x = %d, %d)\n", h, val, ext, *ext, whence);
03698     //why would DLL want temporary file with >2Gb size?
03699     switch(whence)
03700     {
03701     case FILE_BEGIN:
03702         wh=SEEK_SET;break;
03703     case FILE_END:
03704         wh=SEEK_END;break;
03705     case FILE_CURRENT:
03706         wh=SEEK_CUR;break;
03707     default:
03708         return -1;
03709     }
03710 #ifdef QTX
03711     if (val == 0 && ext != 0)
03712         val = val&(*ext);
03713 #endif
03714     return lseek(h, val, wh);
03715 }
03716 
03717 static HDRVR WINAPI expOpenDriverA(LPCSTR szDriverName, LPCSTR szSectionName,
03718                                    LPARAM lParam2)
03719 {
03720     dbgprintf("OpenDriverA(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName,  szDriverName, szSectionName, szSectionName, lParam2);
03721     return -1;
03722 }
03723 static HDRVR WINAPI expOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName,
03724                                   LPARAM lParam2)
03725 {
03726     dbgprintf("OpenDriver(0x%x='%s', 0x%x='%s', 0x%x) => -1\n", szDriverName, szDriverName, szSectionName, szSectionName, lParam2);
03727     return -1;
03728 }
03729 
03730 
03731 static WIN_BOOL WINAPI expGetProcessAffinityMask(HANDLE hProcess,
03732                                                  LPDWORD lpProcessAffinityMask,
03733                                                  LPDWORD lpSystemAffinityMask)
03734 {
03735     dbgprintf("GetProcessAffinityMask(0x%x, 0x%x, 0x%x) => 1\n",
03736               hProcess, lpProcessAffinityMask, lpSystemAffinityMask);
03737     if(lpProcessAffinityMask)*lpProcessAffinityMask=1;
03738     if(lpSystemAffinityMask)*lpSystemAffinityMask=1;
03739     return 1;
03740 }
03741 
03742 static int WINAPI expMulDiv(int nNumber, int nNumerator, int nDenominator)
03743 {
03744     static const long long max_int=0x7FFFFFFFLL;
03745     static const long long min_int=-0x80000000LL;
03746     long long tmp=(long long)nNumber*(long long)nNumerator;
03747     dbgprintf("expMulDiv %d * %d / %d\n", nNumber, nNumerator, nDenominator);
03748     if(!nDenominator)return 1;
03749     tmp/=nDenominator;
03750     if(tmp<min_int) return 1;
03751     if(tmp>max_int) return 1;
03752     return (int)tmp;
03753 }
03754 
03755 static LONG WINAPI explstrcmpiA(const char* str1, const char* str2)
03756 {
03757     LONG result=strcasecmp(str1, str2);
03758     dbgprintf("strcmpi(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
03759     return result;
03760 }
03761 
03762 static LONG WINAPI explstrlenA(const char* str1)
03763 {
03764     LONG result=strlen(str1);
03765     dbgprintf("strlen(0x%x='%.50s') => %d\n", str1, str1, result);
03766     return result;
03767 }
03768 
03769 static LONG WINAPI explstrcpyA(char* str1, const char* str2)
03770 {
03771     int result= (int) strcpy(str1, str2);
03772     dbgprintf("strcpy(0x%.50x, 0x%.50x='%.50s') => %d\n", str1, str2, str2, result);
03773     return result;
03774 }
03775 static LONG WINAPI explstrcpynA(char* str1, const char* str2,int len)
03776 {
03777     int result;
03778     if (strlen(str2)>len)
03779         result = (int) strncpy(str1, str2,len);
03780     else
03781         result = (int) strcpy(str1,str2);
03782     dbgprintf("strncpy(0x%x, 0x%x='%s' len %d strlen %d) => %x\n", str1, str2, str2,len, strlen(str2),result);
03783     return result;
03784 }
03785 static LONG WINAPI explstrcatA(char* str1, const char* str2)
03786 {
03787     int result= (int) strcat(str1, str2);
03788     dbgprintf("strcat(0x%x, 0x%x='%s') => %d\n", str1, str2, str2, result);
03789     return result;
03790 }
03791 
03792 
03793 static LONG WINAPI expInterlockedExchange(long *dest, long l)
03794 {
03795     long retval = *dest;
03796     *dest = l;
03797     return retval;
03798 }
03799 
03800 static void WINAPI expInitCommonControls(void)
03801 {
03802     dbgprintf("InitCommonControls called!\n");
03803     return;
03804 }
03805 
03806 #ifdef QTX
03807 /* needed by QuickTime.qts */
03808 static HWND WINAPI expCreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
03809               HWND parent, INT id, HINSTANCE inst,
03810               HWND buddy, INT maxVal, INT minVal, INT curVal)
03811 {
03812     dbgprintf("CreateUpDownControl(...)\n");
03813     return 0;
03814 }
03815 #endif
03816 
03817 /* alex: implement this call! needed for 3ivx */
03818 static HRESULT WINAPI expCoCreateFreeThreadedMarshaler(void *pUnkOuter, void **ppUnkInner)
03819 {
03820     dbgprintf("CoCreateFreeThreadedMarshaler(%p, %p) called!\n",
03821            pUnkOuter, ppUnkInner);
03822 //    return 0;
03823     return ERROR_CALL_NOT_IMPLEMENTED;
03824 }
03825 
03826 
03827 static int WINAPI expDuplicateHandle(HANDLE hSourceProcessHandle,  // handle to source process
03828                                      HANDLE hSourceHandle,         // handle to duplicate
03829                                      HANDLE hTargetProcessHandle,  // handle to target process
03830                                      HANDLE* lpTargetHandle,      // duplicate handle
03831                                      DWORD dwDesiredAccess,        // requested access
03832                                      int bInheritHandle,          // handle inheritance option
03833                                      DWORD dwOptions               // optional actions
03834                                     )
03835 {
03836     dbgprintf("DuplicateHandle(%p, %p, %p, %p, 0x%x, %d, %d) called\n",
03837               hSourceProcessHandle, hSourceHandle, hTargetProcessHandle,
03838               lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions);
03839     *lpTargetHandle = hSourceHandle;
03840     return 1;
03841 }
03842 
03843 // required by PIM1 codec (used by win98 PCTV Studio capture sw)
03844 static HRESULT WINAPI expCoInitialize(
03845                                       LPVOID lpReserved /* [in] pointer to win32 malloc interface
03846                                       (obsolete, should be NULL) */
03847                                      )
03848 {
03849     /*
03850      * Just delegate to the newer method.
03851      */
03852     return 0; //CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
03853 }
03854 
03855 static DWORD WINAPI expSetThreadAffinityMask
03856 (
03857         HANDLE hThread,
03858         DWORD dwThreadAffinityMask
03859 ){
03860     return 0;
03861 };
03862 
03863 /*
03864  * no WINAPI functions - CDECL
03865  */
03866 static void* expmalloc(int size)
03867 {
03868     //printf("malloc");
03869     //    return malloc(size);
03870     void* result=my_mreq(size,0);
03871     dbgprintf("malloc(0x%x) => 0x%x\n", size,result);
03872     if(result==0)
03873         printf("WARNING: malloc() failed\n");
03874     return result;
03875 }
03876 static void expfree(void* mem)
03877 {
03878     //    return free(mem);
03879     dbgprintf("free(%p)\n", mem);
03880     my_release(mem);
03881 }
03882 /* needed by atrac3.acm */
03883 static void *expcalloc(int num, int size)
03884 {
03885     void* result=my_mreq(num*size,1);
03886     dbgprintf("calloc(%d,%d) => %p\n", num,size,result);
03887     if(result==0)
03888         printf("WARNING: calloc() failed\n");
03889     return result;
03890 }
03891 static void* expnew(int size)
03892 {
03893     //    printf("NEW:: Call from address %08x\n STACK DUMP:\n", *(-1+(int*)&size));
03894     //    printf("%08x %08x %08x %08x\n",
03895     //    size, *(1+(int*)&size),
03896     //    *(2+(int*)&size),*(3+(int*)&size));
03897     void* result;
03898     assert(size >= 0);
03899 
03900     result=my_mreq(size,0);
03901     dbgprintf("new(%d) => %p\n", size, result);
03902     if (result==0)
03903         printf("WARNING: new() failed\n");
03904     return result;
03905 
03906 }
03907 static int expdelete(void* memory)
03908 {
03909     dbgprintf("delete(%p)\n", memory);
03910     my_release(memory);
03911     return 0;
03912 }
03913 
03914 /*
03915  * local definition - we need only the last two members at this point
03916  * otherwice we would have to introduce here GUIDs and some more types..
03917  */
03918 typedef struct __attribute__((__packed__))
03919 {
03920     char hay[0x40];
03921     unsigned long cbFormat;             //0x40
03922     char*       pbFormat;               //0x44
03923 } MY_MEDIA_TYPE;
03924 static HRESULT WINAPI expMoCopyMediaType(MY_MEDIA_TYPE* dest, const MY_MEDIA_TYPE* src)
03925 {
03926     if (!dest || !src)
03927         return E_POINTER;
03928     memcpy(dest, src, sizeof(MY_MEDIA_TYPE));
03929     if (dest->cbFormat)
03930     {
03931         dest->pbFormat = (char*) my_mreq(dest->cbFormat, 0);
03932         if (!dest->pbFormat)
03933             return E_OUTOFMEMORY;
03934         memcpy(dest->pbFormat, src->pbFormat, dest->cbFormat);
03935     }
03936     return S_OK;
03937 }
03938 static HRESULT WINAPI expMoInitMediaType(MY_MEDIA_TYPE* dest, DWORD cbFormat)
03939 {
03940     if (!dest)
03941         return E_POINTER;
03942     memset(dest, 0, sizeof(MY_MEDIA_TYPE));
03943     if (cbFormat)
03944     {
03945         dest->pbFormat = (char*) my_mreq(cbFormat, 0);
03946         if (!dest->pbFormat)
03947             return E_OUTOFMEMORY;
03948     }
03949     return S_OK;
03950 }
03951 static HRESULT WINAPI expMoCreateMediaType(MY_MEDIA_TYPE** dest, DWORD cbFormat)
03952 {
03953     if (!dest)
03954         return E_POINTER;
03955     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
03956     return expMoInitMediaType(*dest, cbFormat);
03957 }
03958 static HRESULT WINAPI expMoDuplicateMediaType(MY_MEDIA_TYPE** dest, const void* src)
03959 {
03960     if (!dest)
03961         return E_POINTER;
03962     *dest = my_mreq(sizeof(MY_MEDIA_TYPE), 0);
03963     return expMoCopyMediaType(*dest, src);
03964 }
03965 static HRESULT WINAPI expMoFreeMediaType(MY_MEDIA_TYPE* dest)
03966 {
03967     if (!dest)
03968         return E_POINTER;
03969     if (dest->pbFormat)
03970     {
03971         my_release(dest->pbFormat);
03972         dest->pbFormat = 0;
03973         dest->cbFormat = 0;
03974     }
03975     return S_OK;
03976 }
03977 static HRESULT WINAPI expMoDeleteMediaType(MY_MEDIA_TYPE* dest)
03978 {
03979     if (!dest)
03980         return E_POINTER;
03981     expMoFreeMediaType(dest);
03982     my_release(dest);
03983     return S_OK;
03984 }
03985 
03986 static int exp_snprintf( char *str, int size, const char *format, ... )
03987 {
03988       int x;
03989       va_list va;
03990       va_start(va, format);
03991       x=snprintf(str,size,format,va);
03992       dbgprintf("_snprintf( 0x%x, %d, %s, ... ) => %d\n",str,size,format,x);
03993       va_end(va);
03994       return x;
03995 }
03996 
03997 #if 0
03998 static int exp_initterm(int v1, int v2)
03999 {
04000     dbgprintf("_initterm(0x%x, 0x%x) => 0\n", v1, v2);
04001     return 0;
04002 }
04003 #else
04004 /* merged from wine - 2002.04.21 */
04005 typedef void (*_INITTERMFUNC)();
04006 static int exp_initterm(_INITTERMFUNC *start, _INITTERMFUNC *end)
04007 {
04008     dbgprintf("_initterm(0x%x, 0x%x) %p\n", start, end, *start);
04009     while (start < end)
04010     {
04011         if (*start)
04012         {
04013             //printf("call _initfunc: from: %p %d\n", *start);
04014             // ok this trick with push/pop is necessary as otherwice
04015             // edi/esi registers are being trashed
04016             void* p = *start;
04017             __asm__ __volatile__
04018                 (
04019                  "pushl %%ebx           \n\t"
04020                  "pushl %%ecx           \n\t"
04021                  "pushl %%edx           \n\t"
04022                  "pushl %%edi           \n\t"
04023                  "pushl %%esi           \n\t"
04024                  "call  *%%eax          \n\t"
04025                  "popl  %%esi           \n\t"
04026                  "popl  %%edi           \n\t"
04027                  "popl  %%edx           \n\t"
04028                  "popl  %%ecx           \n\t"
04029                  "popl  %%ebx           \n\t"
04030                  :
04031                  : "a"(p)
04032                  : "memory"
04033                 );
04034             //printf("done  %p  %d:%d\n", end);
04035         }
04036         start++;
04037     }
04038     return 0;
04039 }
04040 #endif
04041 
04042 static void* exp__dllonexit()
04043 {
04044     // FIXME extract from WINE
04045     return NULL;
04046 }
04047 
04048 static int expwsprintfA(char* string, const char* format, ...)
04049 {
04050     va_list va;
04051     int result;
04052     va_start(va, format);
04053     result = vsprintf(string, format, va);
04054     dbgprintf("wsprintfA(0x%x, '%s', ...) => %d\n", string, format, result);
04055     va_end(va);
04056     return result;
04057 }
04058 
04059 static int expsprintf(char* str, const char* format, ...)
04060 {
04061     va_list args;
04062     int r;
04063     dbgprintf("sprintf(0x%x, %s)\n", str, format);
04064     va_start(args, format);
04065     r = vsprintf(str, format, args);
04066     va_end(args);
04067     return r;
04068 }
04069 static int expsscanf(const char* str, const char* format, ...)
04070 {
04071     va_list args;
04072     int r;
04073     dbgprintf("sscanf(%s, %s)\n", str, format);
04074     va_start(args, format);
04075     r = vsscanf(str, format, args);
04076     va_end(args);
04077     return r;
04078 }
04079 static void* expfopen(const char* path, const char* mode)
04080 {
04081     printf("fopen: \"%s\"  mode:%s\n", path, mode);
04082     //return fopen(path, mode);
04083     return fdopen(0, mode); // everything on screen
04084 }
04085 static int expfprintf(void* stream, const char* format, ...)
04086 {
04087     va_list args;
04088     int r = 0;
04089     dbgprintf("fprintf(%p, %s, ...)\n", stream, format);
04090 #if 1
04091     va_start(args, format);
04092     r = vfprintf((FILE*) stream, format, args);
04093     va_end(args);
04094 #endif
04095     return r;
04096 }
04097 
04098 static int expprintf(const char* format, ...)
04099 {
04100     va_list args;
04101     int r;
04102     dbgprintf("printf(%s, ...)\n", format);
04103     va_start(args, format);
04104     r = vprintf(format, args);
04105     va_end(args);
04106     return r;
04107 }
04108 
04109 static char* expgetenv(const char* varname)
04110 {
04111     char* v = getenv(varname);
04112     dbgprintf("getenv(%s) => %s\n", varname, v);
04113     return v;
04114 }
04115 
04116 static void* expwcscpy(WCHAR* dst, const WCHAR* src)
04117 {
04118     WCHAR* p = dst;
04119     while ((*p++ = *src++))
04120         ;
04121     return dst;
04122 }
04123 
04124 static char* expstrrchr(char* string, int value)
04125 {
04126     char* result=strrchr(string, value);
04127     if(result)
04128         dbgprintf("strrchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
04129     else
04130         dbgprintf("strrchr(0x%x='%s', %d) => 0", string, string, value);
04131     return result;
04132 }
04133 
04134 static char* expstrchr(char* string, int value)
04135 {
04136     char* result=strchr(string, value);
04137     if(result)
04138         dbgprintf("strchr(0x%x='%s', %d) => 0x%x='%s'", string, string, value, result, result);
04139     else
04140         dbgprintf("strchr(0x%x='%s', %d) => 0", string, string, value);
04141     return result;
04142 }
04143 static int expstrlen(char* str)
04144 {
04145     int result=strlen(str);
04146     dbgprintf("strlen(0x%x='%s') => %d\n", str, str, result);
04147     return result;
04148 }
04149 static char* expstrcpy(char* str1, const char* str2)
04150 {
04151     char* result= strcpy(str1, str2);
04152     dbgprintf("strcpy(0x%x, 0x%x='%s') => %p\n", str1, str2, str2, result);
04153     return result;
04154 }
04155 static char* expstrncpy(char* str1, const char* str2, size_t count)
04156 {
04157     char* result= strncpy(str1, str2, count);
04158     dbgprintf("strncpy(0x%x, 0x%x='%s', %d) => %p\n", str1, str2, str2, count, result);
04159     return result;
04160 }
04161 static int expstrcmp(const char* str1, const char* str2)
04162 {
04163     int result=strcmp(str1, str2);
04164     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
04165     return result;
04166 }
04167 static int expstrncmp(const char* str1, const char* str2,int x)
04168 {
04169     int result=strncmp(str1, str2,x);
04170     dbgprintf("strcmp(0x%x='%s', 0x%x='%s') => %d\n", str1, str1, str2, str2, result);
04171     return result;
04172 }
04173 static char* expstrcat(char* str1, const char* str2)
04174 {
04175     char* result = strcat(str1, str2);
04176     dbgprintf("strcat(0x%x='%s', 0x%x='%s') => %p\n", str1, str1, str2, str2, result);
04177     return result;
04178 }
04179 static char* exp_strdup(const char* str1)
04180 {
04181     int l = strlen(str1);
04182     char* result = (char*) my_mreq(l + 1,0);
04183     if (result)
04184         strcpy(result, str1);
04185     dbgprintf("_strdup(0x%x='%s') => %p\n", str1, str1, result);
04186     return result;
04187 }
04188 static int expisalnum(int c)
04189 {
04190     int result= (int) isalnum(c);
04191     dbgprintf("isalnum(0x%x='%c' => %d\n", c, c, result);
04192     return result;
04193 }
04194 static int expisspace(int c)
04195 {
04196     int result= (int) isspace(c);
04197     dbgprintf("isspace(0x%x='%c' => %d\n", c, c, result);
04198     return result;
04199 }
04200 static int expisalpha(int c)
04201 {
04202     int result= (int) isalpha(c);
04203     dbgprintf("isalpha(0x%x='%c' => %d\n", c, c, result);
04204     return result;
04205 }
04206 static int expisdigit(int c)
04207 {
04208     int result= (int) isdigit(c);
04209     dbgprintf("isdigit(0x%x='%c' => %d\n", c, c, result);
04210     return result;
04211 }
04212 static void* expmemmove(void* dest, void* src, int n)
04213 {
04214     void* result = memmove(dest, src, n);
04215     dbgprintf("memmove(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
04216     return result;
04217 }
04218 static int expmemcmp(void* dest, void* src, int n)
04219 {
04220     int result = memcmp(dest, src, n);
04221     dbgprintf("memcmp(0x%x, 0x%x, %d) => %d\n", dest, src, n, result);
04222     return result;
04223 }
04224 static void* expmemcpy(void* dest, void* src, int n)
04225 {
04226     void *result = memcpy(dest, src, n);
04227     dbgprintf("memcpy(0x%x, 0x%x, %d) => %p\n", dest, src, n, result);
04228     return result;
04229 }
04230 static void* expmemset(void* dest, int c, size_t n)
04231 {
04232     void *result = memset(dest, c, n);
04233     dbgprintf("memset(0x%x, %d, %d) => %p\n", dest, c, n, result);
04234     return result;
04235 }
04236 static time_t exptime(time_t* t)
04237 {
04238     time_t result = time(t);
04239     dbgprintf("time(0x%x) => %d\n", t, result);
04240     return result;
04241 }
04242 
04243 static int exprand(void)
04244 {
04245     return rand();
04246 }
04247 
04248 static void expsrand(int seed)
04249 {
04250     srand(seed);
04251 }
04252 
04253 #if 1
04254 
04255 // prefered compilation with  -O2 -ffast-math !
04256 
04257 static double explog10(double x)
04258 {
04259     /*printf("Log10 %f => %f    0x%Lx\n", x, log10(x), *((int64_t*)&x));*/
04260     return log10(x);
04261 }
04262 
04263 static double expcos(double x)
04264 {
04265     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
04266     return cos(x);
04267 }
04268 
04269 /* doens't work */
04270 static long exp_ftol_wrong(double x)
04271 {
04272     return (long) x;
04273 }
04274 
04275 #else
04276 
04277 static void explog10(void)
04278 {
04279     __asm__ __volatile__
04280         (
04281          "fldl 8(%esp)  \n\t"
04282          "fldln2        \n\t"
04283          "fxch %st(1)   \n\t"
04284          "fyl2x         \n\t"
04285         );
04286 }
04287 
04288 static void expcos(void)
04289 {
04290     __asm__ __volatile__
04291         (
04292          "fldl 8(%esp)  \n\t"
04293          "fcos          \n\t"
04294         );
04295 }
04296 
04297 #endif
04298 
04299 // this seem to be the only how to make this function working properly
04300 // ok - I've spent tremendous amount of time (many many many hours
04301 // of debuging fixing & testing - it's almost unimaginable - kabi
04302 
04303 // _ftol - operated on the float value which is already on the FPU stack
04304 
04305 static void exp_ftol(void)
04306 {
04307     __asm__ __volatile__
04308         (
04309          "sub $12, %esp         \n\t"
04310          "fstcw   -2(%ebp)      \n\t"
04311          "wait                  \n\t"
04312          "movw    -2(%ebp), %ax \n\t"
04313          "orb    $0x0C, %ah     \n\t"
04314          "movw    %ax, -4(%ebp) \n\t"
04315          "fldcw   -4(%ebp)      \n\t"
04316          "fistpl -12(%ebp)      \n\t"
04317          "fldcw   -2(%ebp)      \n\t"
04318          "movl   -12(%ebp), %eax \n\t"
04319          //Note: gcc 3.03 does not do the following op if it
04320          //      knows that ebp=esp
04321          "movl %ebp, %esp       \n\t"
04322         );
04323 }
04324 
04325 #define FPU_DOUBLES(var1,var2) double var1,var2; \
04326   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
04327   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
04328 
04329 static double exp_CIpow(void)
04330 {
04331     FPU_DOUBLES(x,y);
04332 
04333     dbgprintf("_CIpow(%lf, %lf)\n", x, y);
04334     return pow(x, y);
04335 }
04336 
04337 static double exppow(double x, double y)
04338 {
04339     /*printf("Pow %f  %f    0x%Lx  0x%Lx  => %f\n", x, y, *((int64_t*)&x), *((int64_t*)&y), pow(x, y));*/
04340     return pow(x, y);
04341 }
04342 
04343 static double expldexp(double x, int expo)
04344 {
04345     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
04346     return ldexp(x, expo);
04347 }
04348 
04349 static double expfrexp(double x, int* expo)
04350 {
04351     /*printf("Cos %f => %f  0x%Lx\n", x, cos(x), *((int64_t*)&x));*/
04352     return frexp(x, expo);
04353 }
04354 
04355 
04356 
04357 static int exp_stricmp(const char* s1, const char* s2)
04358 {
04359     return strcasecmp(s1, s2);
04360 }
04361 
04362 /* from declaration taken from Wine sources - this fountion seems to be
04363  * undocumented in any M$ doc */
04364 static int exp_setjmp3(void* jmpbuf, int x)
04365 {
04366     //dbgprintf("!!!!UNIMPLEMENTED: setjmp3(%p, %d) => 0\n", jmpbuf, x);
04367     //return 0;
04368     __asm__ __volatile__
04369         (
04370          //"mov 4(%%esp), %%edx \n\t"
04371          "mov (%%esp), %%eax   \n\t"
04372          "mov %%eax, (%%edx)    \n\t" // store ebp
04373 
04374          //"mov %%ebp, (%%edx)  \n\t"
04375          "mov %%ebx, 4(%%edx)   \n\t"
04376          "mov %%edi, 8(%%edx)   \n\t"
04377          "mov %%esi, 12(%%edx)  \n\t"
04378          "mov %%esp, 16(%%edx)  \n\t"
04379 
04380          "mov 4(%%esp), %%eax   \n\t"
04381          "mov %%eax, 20(%%edx)  \n\t"
04382 
04383          "movl $0x56433230, 32(%%edx)   \n\t" // VC20 ??
04384          "movl $0, 36(%%edx)    \n\t"
04385          : // output
04386          : "d"(jmpbuf) // input
04387          : "eax"
04388         );
04389 #if 1
04390     __asm__ __volatile__
04391         (
04392          "mov %%fs:0, %%eax     \n\t" // unsure
04393          "mov %%eax, 24(%%edx)  \n\t"
04394          "cmp $0xffffffff, %%eax \n\t"
04395          "jnz l1                \n\t"
04396          "mov %%eax, 28(%%edx)  \n\t"
04397          "l1:                   \n\t"
04398          :
04399          :
04400          : "eax"
04401         );
04402 #endif
04403 
04404         return 0;
04405 }
04406 
04407 static DWORD WINAPI expGetCurrentProcessId(void)
04408 {
04409     dbgprintf("GetCurrentProcessId(void) => %d\n", getpid());
04410     return getpid(); //(DWORD)NtCurrentTeb()->pid;
04411 }
04412 
04413 
04414 typedef struct {
04415     UINT        wPeriodMin;
04416     UINT        wPeriodMax;
04417 } TIMECAPS, *LPTIMECAPS;
04418 
04419 static MMRESULT WINAPI exptimeGetDevCaps(LPTIMECAPS lpCaps, UINT wSize)
04420 {
04421     dbgprintf("timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
04422 
04423     lpCaps->wPeriodMin = 1;
04424     lpCaps->wPeriodMax = 65535;
04425     return 0;
04426 }
04427 
04428 static MMRESULT WINAPI exptimeBeginPeriod(UINT wPeriod)
04429 {
04430     dbgprintf("timeBeginPeriod(%u) !\n", wPeriod);
04431 
04432     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
04433     return 0;
04434 }
04435 
04436 #ifdef QTX
04437 static MMRESULT WINAPI exptimeEndPeriod(UINT wPeriod)
04438 {
04439     dbgprintf("timeEndPeriod(%u) !\n", wPeriod);
04440 
04441     if (wPeriod < 1 || wPeriod > 65535) return 96+1; //TIMERR_NOCANDO;
04442     return 0;
04443 }
04444 #endif
04445 
04446 static void WINAPI expGlobalMemoryStatus(
04447             LPMEMORYSTATUS lpmem
04448 ) {
04449     static MEMORYSTATUS cached_memstatus;
04450     static int cache_lastchecked = 0;
04451     SYSTEM_INFO si;
04452     FILE *f;
04453 
04454     if (time(NULL)==cache_lastchecked) {
04455         memcpy(lpmem,&cached_memstatus,sizeof(MEMORYSTATUS));
04456         return;
04457     }
04458 
04459 #if 1
04460     f = fopen( "/proc/meminfo", "r" );
04461     if (f)
04462     {
04463         char buffer[256];
04464         int total, used, free, shared, buffers, cached;
04465 
04466         lpmem->dwLength = sizeof(MEMORYSTATUS);
04467         lpmem->dwTotalPhys = lpmem->dwAvailPhys = 0;
04468         lpmem->dwTotalPageFile = lpmem->dwAvailPageFile = 0;
04469         while (fgets( buffer, sizeof(buffer), f ))
04470         {
04471             /* old style /proc/meminfo ... */
04472             if (sscanf( buffer, "Mem: %d %d %d %d %d %d", &total, &used, &free, &shared, &buffers, &cached ))
04473             {
04474                 lpmem->dwTotalPhys += total;
04475                 lpmem->dwAvailPhys += free + buffers + cached;
04476             }
04477             if (sscanf( buffer, "Swap: %d %d %d", &total, &used, &free ))
04478             {
04479                 lpmem->dwTotalPageFile += total;
04480                 lpmem->dwAvailPageFile += free;
04481             }
04482 
04483             /* new style /proc/meminfo ... */
04484             if (sscanf(buffer, "MemTotal: %d", &total))
04485                 lpmem->dwTotalPhys = total*1024;
04486             if (sscanf(buffer, "MemFree: %d", &free))
04487                 lpmem->dwAvailPhys = free*1024;
04488             if (sscanf(buffer, "SwapTotal: %d", &total))
04489                 lpmem->dwTotalPageFile = total*1024;
04490             if (sscanf(buffer, "SwapFree: %d", &free))
04491                 lpmem->dwAvailPageFile = free*1024;
04492             if (sscanf(buffer, "Buffers: %d", &buffers))
04493                 lpmem->dwAvailPhys += buffers*1024;
04494             if (sscanf(buffer, "Cached: %d", &cached))
04495                 lpmem->dwAvailPhys += cached*1024;
04496         }
04497         fclose( f );
04498 
04499         if (lpmem->dwTotalPhys)
04500         {
04501             DWORD TotalPhysical = lpmem->dwTotalPhys+lpmem->dwTotalPageFile;
04502             DWORD AvailPhysical = lpmem->dwAvailPhys+lpmem->dwAvailPageFile;
04503             lpmem->dwMemoryLoad = (TotalPhysical-AvailPhysical)
04504                                       / (TotalPhysical / 100);
04505         }
04506     } else
04507 #endif
04508     {
04509         /* FIXME: should do something for other systems */
04510         lpmem->dwMemoryLoad    = 0;
04511         lpmem->dwTotalPhys     = 16*1024*1024;
04512         lpmem->dwAvailPhys     = 16*1024*1024;
04513         lpmem->dwTotalPageFile = 16*1024*1024;
04514         lpmem->dwAvailPageFile = 16*1024*1024;
04515     }
04516     expGetSystemInfo(&si);
04517     lpmem->dwTotalVirtual  = si.lpMaximumApplicationAddress-si.lpMinimumApplicationAddress;
04518     /* FIXME: we should track down all the already allocated VM pages and substract them, for now arbitrarily remove 64KB so that it matches NT */
04519     lpmem->dwAvailVirtual  = lpmem->dwTotalVirtual-64*1024;
04520     memcpy(&cached_memstatus,lpmem,sizeof(MEMORYSTATUS));
04521     cache_lastchecked = time(NULL);
04522 
04523     /* it appears some memory display programs want to divide by these values */
04524     if(lpmem->dwTotalPageFile==0)
04525         lpmem->dwTotalPageFile++;
04526 
04527     if(lpmem->dwAvailPageFile==0)
04528         lpmem->dwAvailPageFile++;
04529 }
04530 
04531 /**********************************************************************
04532  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
04533  *
04534  * RETURNS
04535  *    Success: TRUE
04536  *    Failure: FALSE
04537  */
04538 static WIN_BOOL WINAPI expSetThreadPriority(
04539     HANDLE hthread, /* [in] Handle to thread */
04540     INT priority)   /* [in] Thread priority level */
04541 {
04542     dbgprintf("SetThreadPriority(%p,%d)\n",hthread,priority);
04543     return TRUE;
04544 }
04545 
04546 static void WINAPI expExitProcess( DWORD status )
04547 {
04548     printf("EXIT - code %ld\n",status);
04549     exit(status);
04550 }
04551 
04552 static INT WINAPI expMessageBoxA(HWND hWnd, LPCSTR text, LPCSTR title, UINT type){
04553     printf("MSGBOX '%s' '%s' (%d)\n",text,title,type);
04554 #ifdef QTX
04555     if (type == MB_ICONHAND && !strlen(text) && !strlen(title))
04556         return IDIGNORE;
04557 #endif
04558     return IDOK;
04559 }
04560 
04561 /* these are needed for mss1 */
04562 
04563 /* defined in stubs.s */
04564 void exp_EH_prolog(void);
04565 
04566 #include <netinet/in.h>
04567 static WINAPI inline unsigned long int exphtonl(unsigned long int hostlong)
04568 {
04569 //    dbgprintf("htonl(%x) => %x\n", hostlong, htonl(hostlong));
04570     return htonl(hostlong);
04571 }
04572 
04573 static WINAPI inline unsigned long int expntohl(unsigned long int netlong)
04574 {
04575 //    dbgprintf("ntohl(%x) => %x\n", netlong, ntohl(netlong));
04576     return ntohl(netlong);
04577 }
04578 static void WINAPI expVariantInit(void* p)
04579 {
04580     printf("InitCommonControls called!\n");
04581     return;
04582 }
04583 
04584 static int WINAPI expRegisterClassA(const void/*WNDCLASSA*/ *wc)
04585 {
04586     dbgprintf("RegisterClassA(%p) => random id\n", wc);
04587     return time(NULL); /* be precise ! */
04588 }
04589 
04590 static int WINAPI expUnregisterClassA(const char *className, HINSTANCE hInstance)
04591 {
04592     dbgprintf("UnregisterClassA(%s, %p) => 0\n", className, hInstance);
04593     return 0;
04594 }
04595 
04596 #ifdef QTX
04597 /* should be fixed bcs it's not fully strlen equivalent */
04598 static int expSysStringByteLen(void *str)
04599 {
04600     dbgprintf("SysStringByteLen(%p) => %d\n", str, strlen(str));
04601     return strlen(str);
04602 }
04603 
04604 static int expDirectDrawCreate(void)
04605 {
04606     dbgprintf("DirectDrawCreate(...) => NULL\n");
04607     return 0;
04608 }
04609 
04610 #if 1
04611 typedef struct tagPALETTEENTRY { 
04612     BYTE peRed; 
04613     BYTE peGreen; 
04614     BYTE peBlue; 
04615     BYTE peFlags; 
04616 } PALETTEENTRY; 
04617 
04618 /* reversed the first 2 entries */
04619 typedef struct tagLOGPALETTE { 
04620     WORD         palNumEntries; 
04621     WORD         palVersion; 
04622     PALETTEENTRY palPalEntry[1]; 
04623 } LOGPALETTE; 
04624 
04625 static HPALETTE WINAPI expCreatePalette(CONST LOGPALETTE *lpgpl)
04626 {
04627     HPALETTE test;
04628     int i;
04629     
04630     dbgprintf("CreatePalette(%x) => NULL\n", lpgpl);
04631 
04632     i = sizeof(LOGPALETTE)+((lpgpl->palNumEntries-1)*sizeof(PALETTEENTRY));
04633     test = (HPALETTE)malloc(i);
04634     memcpy((void *)test, lpgpl, i);
04635 
04636     return test;
04637 }
04638 #else
04639 static int expCreatePalette(void)
04640 {
04641     dbgprintf("CreatePalette(...) => NULL\n");
04642     return NULL;
04643 }
04644 #endif
04645 
04646 static int WINAPI expGetClientRect(HWND win, RECT *r)
04647 {
04648     dbgprintf("GetClientRect(0x%x, 0x%x) => 1\n", win, r);
04649     r->right = PSEUDO_SCREEN_WIDTH;
04650     r->left = 0;
04651     r->bottom = PSEUDO_SCREEN_HEIGHT;
04652     r->top = 0;
04653     return 1;
04654 }
04655 
04656 #if 0
04657 typedef struct tagPOINT { 
04658     LONG x; 
04659     LONG y; 
04660 } POINT, *PPOINT; 
04661 #endif
04662 
04663 static int WINAPI expClientToScreen(HWND win, POINT *p)
04664 {
04665     dbgprintf("ClientToScreen(0x%x, 0x%x = %d,%d) => 1\n", win, p, p->x, p->y);
04666     p->x = 0;
04667     p->y = 0;
04668     return 1;
04669 }
04670 #endif
04671 
04672 /* for m3jpeg */
04673 static int WINAPI expSetThreadIdealProcessor(HANDLE thread, int proc)
04674 {
04675     dbgprintf("SetThreadIdealProcessor(0x%x, %x) => 0\n", thread, proc);
04676     return 0;
04677 }
04678 
04679 static int WINAPI expMessageBeep(int type)
04680 {
04681     dbgprintf("MessageBeep(%d) => 1\n", type);
04682     return 1;
04683 }
04684 
04685 static int WINAPI expDialogBoxParamA(void *inst, const char *name,
04686     HWND parent, void *dialog_func, void *init_param)
04687 {
04688     dbgprintf("DialogBoxParamA(0x%x, 0x%x = %s, 0x%x, 0x%x, 0x%x) => 0x42424242\n",
04689         inst, name, name, parent, dialog_func, init_param);
04690     return 0x42424242;
04691 }
04692 
04693 /* needed by imagepower mjpeg2k */
04694 static void *exprealloc(void *ptr, size_t size)
04695 {
04696     dbgprintf("realloc(0x%x, %x)\n", ptr, size);
04697     if (!ptr)
04698         return my_mreq(size,0);
04699     else
04700         return my_realloc(ptr, size);        
04701 }
04702 
04703 /* Fake GetOpenFileNameA from comdlg32.dll for ViVD codec */
04704 static WIN_BOOL WINAPI expGetOpenFileNameA(/*LPOPENFILENAMEA*/ void* lpfn)
04705 {
04706     return 1;
04707 }
04708 
04709 static double expfloor(double x)
04710 {
04711     dbgprintf("floor(%lf)\n", x);
04712     return floor(x);
04713 }
04714 
04715 #define FPU_DOUBLE(var) double var; \
04716   __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
04717 
04718 static double exp_CIcos(void)
04719 {
04720     FPU_DOUBLE(x);
04721 
04722     dbgprintf("_CIcos(%lf)\n", x);
04723     return cos(x);
04724 }
04725 
04726 static double exp_CIsin(void)
04727 {
04728     FPU_DOUBLE(x);
04729 
04730     dbgprintf("_CIsin(%lf)\n", x);
04731     return sin(x);
04732 }
04733 
04734 struct exports
04735 {
04736     char name[64];
04737     int id;
04738     void* func;
04739 };
04740 struct libs
04741 {
04742     char name[64];
04743     int length;
04744     struct exports* exps;
04745 };
04746 
04747 #define FF(X,Y) \
04748     {#X, Y, (void*)exp##X},
04749 
04750 struct exports exp_kernel32[]=
04751 {
04752     FF(GetVolumeInformationA,-1)
04753     FF(GetDriveTypeA,-1)
04754     FF(GetLogicalDriveStringsA,-1)
04755     FF(IsBadWritePtr, 357)
04756     FF(IsBadReadPtr, 354)
04757     FF(IsBadStringPtrW, -1)
04758     FF(IsBadStringPtrA, -1)
04759     FF(DisableThreadLibraryCalls, -1)
04760     FF(CreateThread, -1)
04761     FF(CreateEventA, -1)
04762     FF(SetEvent, -1)
04763     FF(ResetEvent, -1)
04764     FF(WaitForSingleObject, -1)
04765 #ifdef QTX
04766     FF(WaitForMultipleObjects, -1)
04767     FF(ExitThread, -1)
04768     FF(CreateMutexA,-1)
04769     FF(ReleaseMutex,-1)
04770 #endif
04771     FF(GetSystemInfo, -1)
04772     FF(GetVersion, 332)
04773     FF(HeapCreate, 461)
04774     FF(HeapAlloc, -1)
04775     FF(HeapDestroy, -1)
04776     FF(HeapFree, -1)
04777     FF(HeapSize, -1)
04778     FF(HeapReAlloc,-1)
04779     FF(GetProcessHeap, -1)
04780     FF(VirtualAlloc, -1)
04781     FF(VirtualFree, -1)
04782     FF(InitializeCriticalSection, -1)
04783     FF(EnterCriticalSection, -1)
04784     FF(LeaveCriticalSection, -1)
04785     FF(DeleteCriticalSection, -1)
04786     FF(TlsAlloc, -1)
04787     FF(TlsFree, -1)
04788     FF(TlsGetValue, -1)
04789     FF(TlsSetValue, -1)
04790     FF(GetCurrentThreadId, -1)
04791     FF(GetCurrentProcess, -1)
04792     FF(LocalAlloc, -1)
04793     FF(LocalReAlloc,-1)
04794     FF(LocalLock, -1)
04795     FF(GlobalAlloc, -1)
04796     FF(GlobalReAlloc, -1)
04797     FF(GlobalLock, -1)
04798     FF(GlobalSize, -1)
04799     FF(MultiByteToWideChar, 427)
04800     FF(WideCharToMultiByte, -1)
04801     FF(GetVersionExA, -1)
04802     FF(CreateSemaphoreA, -1)
04803     FF(QueryPerformanceCounter, -1)
04804     FF(QueryPerformanceFrequency, -1)
04805     FF(LocalHandle, -1)
04806     FF(LocalUnlock, -1)
04807     FF(LocalFree, -1)
04808     FF(GlobalHandle, -1)
04809     FF(GlobalUnlock, -1)
04810     FF(GlobalFree, -1)
04811     FF(LoadResource, -1)
04812     FF(ReleaseSemaphore, -1)
04813     FF(FindResourceA, -1)
04814     FF(LockResource, -1)
04815     FF(FreeResource, -1)
04816     FF(SizeofResource, -1)
04817     FF(CloseHandle, -1)
04818     FF(GetCommandLineA, -1)
04819     FF(GetEnvironmentStringsW, -1)
04820     FF(FreeEnvironmentStringsW, -1)
04821     FF(FreeEnvironmentStringsA, -1)
04822     FF(GetEnvironmentStrings, -1)
04823     FF(GetStartupInfoA, -1)
04824     FF(GetStdHandle, -1)
04825     FF(GetFileType, -1)
04826 #ifdef QTX
04827     FF(GetFileAttributesA, -1)
04828 #endif
04829     FF(SetHandleCount, -1)
04830     FF(GetACP, -1)
04831     FF(GetModuleFileNameA, -1)
04832     FF(SetUnhandledExceptionFilter, -1)
04833     FF(LoadLibraryA, -1)
04834     FF(GetProcAddress, -1)
04835     FF(FreeLibrary, -1)
04836     FF(CreateFileMappingA, -1)
04837     FF(OpenFileMappingA, -1)
04838     FF(MapViewOfFile, -1)
04839     FF(UnmapViewOfFile, -1)
04840     FF(Sleep, -1)
04841     FF(GetModuleHandleA, -1)
04842     FF(GetProfileIntA, -1)
04843     FF(GetPrivateProfileIntA, -1)
04844     FF(GetPrivateProfileStringA, -1)
04845     FF(WritePrivateProfileStringA, -1)
04846     FF(GetLastError, -1)
04847     FF(SetLastError, -1)
04848     FF(InterlockedIncrement, -1)
04849     FF(InterlockedDecrement, -1)
04850     FF(GetTimeZoneInformation, -1)
04851     FF(OutputDebugStringA, -1)
04852     FF(GetLocalTime, -1)
04853     FF(GetSystemTime, -1)
04854     FF(GetSystemTimeAsFileTime, -1)
04855     FF(GetEnvironmentVariableA, -1)
04856     FF(SetEnvironmentVariableA, -1)
04857     FF(RtlZeroMemory,-1)
04858     FF(RtlMoveMemory,-1)
04859     FF(RtlFillMemory,-1)
04860     FF(GetTempPathA,-1)
04861     FF(FindFirstFileA,-1)
04862     FF(FindNextFileA,-1)
04863     FF(FindClose,-1)
04864     FF(FileTimeToLocalFileTime,-1)
04865     FF(DeleteFileA,-1)
04866     FF(ReadFile,-1)
04867     FF(WriteFile,-1)
04868     FF(SetFilePointer,-1)
04869     FF(GetTempFileNameA,-1)
04870     FF(CreateFileA,-1)
04871     FF(GetSystemDirectoryA,-1)
04872     FF(GetWindowsDirectoryA,-1)
04873 #ifdef QTX
04874     FF(GetCurrentDirectoryA,-1)
04875     FF(SetCurrentDirectoryA,-1)
04876     FF(CreateDirectoryA,-1)
04877 #endif
04878     FF(GetShortPathNameA,-1)
04879     FF(GetFullPathNameA,-1)
04880     FF(SetErrorMode, -1)
04881     FF(IsProcessorFeaturePresent, -1)
04882     FF(GetProcessAffinityMask, -1)
04883     FF(InterlockedExchange, -1)
04884     FF(InterlockedCompareExchange, -1)
04885     FF(MulDiv, -1)
04886     FF(lstrcmpiA, -1)
04887     FF(lstrlenA, -1)
04888     FF(lstrcpyA, -1)
04889     FF(lstrcatA, -1)
04890     FF(lstrcpynA,-1)
04891     FF(GetProcessVersion,-1)
04892     FF(GetCurrentThread,-1)
04893     FF(GetOEMCP,-1)
04894     FF(GetCPInfo,-1)
04895     FF(DuplicateHandle,-1)
04896     FF(GetTickCount, -1)
04897     FF(SetThreadAffinityMask,-1)
04898     FF(GetCurrentProcessId,-1)
04899     FF(GlobalMemoryStatus,-1)
04900     FF(SetThreadPriority,-1)
04901     FF(ExitProcess,-1)
04902     {"LoadLibraryExA", -1, (void*)&LoadLibraryExA},
04903     FF(SetThreadIdealProcessor,-1)
04904 };
04905 
04906 struct exports exp_msvcrt[]={
04907     FF(malloc, -1)
04908     FF(_initterm, -1)
04909     FF(__dllonexit, -1)
04910     FF(_snprintf,-1)
04911     FF(free, -1)
04912     {"??3@YAXPAX@Z", -1, expdelete},
04913     {"??2@YAPAXI@Z", -1, expnew},
04914     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
04915     FF(strrchr, -1)
04916     FF(strchr, -1)
04917     FF(strlen, -1)
04918     FF(strcpy, -1)
04919     FF(strncpy, -1)
04920     FF(wcscpy, -1)
04921     FF(strcmp, -1)
04922     FF(strncmp, -1)
04923     FF(strcat, -1)
04924     FF(_stricmp,-1)
04925     FF(_strdup,-1)
04926     FF(_setjmp3,-1)
04927     FF(isalnum, -1)
04928     FF(isspace, -1)
04929     FF(isalpha, -1)
04930     FF(isdigit, -1)
04931     FF(memmove, -1)
04932     FF(memcmp, -1)
04933     FF(memset, -1)
04934     FF(memcpy, -1)
04935     FF(time, -1)
04936     FF(rand, -1)
04937     FF(srand, -1)
04938     FF(log10, -1)
04939     FF(pow, -1)
04940     FF(cos, -1)
04941     FF(_ftol,-1)
04942     FF(_CIpow,-1)
04943     FF(_CIcos,-1)
04944     FF(_CIsin,-1)
04945     FF(ldexp,-1)
04946     FF(frexp,-1)
04947     FF(sprintf,-1)
04948     FF(sscanf,-1)
04949     FF(fopen,-1)
04950     FF(fprintf,-1)
04951     FF(printf,-1)
04952     FF(getenv,-1)
04953     FF(floor,-1)
04954 /* needed by frapsvid.dll */
04955     {"strstr",-1,(char *)&strstr},
04956     {"qsort",-1,(void *)&qsort},
04957 #ifdef MPLAYER
04958     FF(_EH_prolog,-1)
04959 #endif
04960     FF(calloc,-1)
04961     {"ceil",-1,(void*)&ceil},
04962 /* needed by imagepower mjpeg2k */
04963     {"clock",-1,(void*)&clock},
04964     {"memchr",-1,(void*)&memchr},
04965     {"vfprintf",-1,(void*)&vfprintf},
04966 //    {"realloc",-1,(void*)&realloc},
04967     FF(realloc,-1)
04968     {"puts",-1,(void*)&puts}
04969 };
04970 struct exports exp_winmm[]={
04971     FF(GetDriverModuleHandle, -1)
04972     FF(timeGetTime, -1)
04973     FF(DefDriverProc, -1)
04974     FF(OpenDriverA, -1)
04975     FF(OpenDriver, -1)
04976     FF(timeGetDevCaps, -1)
04977     FF(timeBeginPeriod, -1)
04978 #ifdef QTX
04979     FF(timeEndPeriod, -1)
04980     FF(waveOutGetNumDevs, -1)
04981 #endif
04982 };
04983 struct exports exp_user32[]={
04984     FF(LoadIconA,-1)
04985     FF(LoadStringA, -1)
04986     FF(wsprintfA, -1)
04987     FF(GetDC, -1)
04988     FF(GetDesktopWindow, -1)
04989     FF(ReleaseDC, -1)
04990     FF(IsRectEmpty, -1)
04991     FF(LoadCursorA,-1)
04992     FF(SetCursor,-1)
04993     FF(GetCursorPos,-1)
04994 #ifdef QTX
04995     FF(ShowCursor,-1)
04996 #endif
04997     FF(RegisterWindowMessageA,-1)
04998     FF(GetSystemMetrics,-1)
04999     FF(GetSysColor,-1)
05000     FF(GetSysColorBrush,-1)
05001     FF(GetWindowDC, -1)
05002     FF(DrawTextA, -1)
05003     FF(MessageBoxA, -1)
05004     FF(RegisterClassA, -1)
05005     FF(UnregisterClassA, -1)
05006 #ifdef QTX
05007     FF(GetWindowRect, -1)
05008     FF(MonitorFromWindow, -1)
05009     FF(MonitorFromRect, -1)
05010     FF(MonitorFromPoint, -1)
05011     FF(EnumDisplayMonitors, -1)
05012     FF(GetMonitorInfoA, -1)
05013     FF(EnumDisplayDevicesA, -1)
05014     FF(GetClientRect, -1)
05015     FF(ClientToScreen, -1)
05016     FF(IsWindowVisible, -1)
05017     FF(GetActiveWindow, -1)
05018     FF(GetClassNameA, -1)
05019     FF(GetClassInfoA, -1)
05020     FF(GetWindowLongA, -1)
05021     FF(EnumWindows, -1)
05022     FF(GetWindowThreadProcessId, -1)
05023     FF(CreateWindowExA, -1)
05024 #endif
05025     FF(MessageBeep, -1)
05026     FF(DialogBoxParamA, -1)
05027 };
05028 struct exports exp_advapi32[]={
05029     FF(RegCloseKey, -1)
05030     FF(RegCreateKeyA, -1)
05031     FF(RegCreateKeyExA, -1)
05032     FF(RegEnumKeyExA, -1)
05033     FF(RegEnumValueA, -1)
05034     FF(RegOpenKeyA, -1)
05035     FF(RegOpenKeyExA, -1)
05036     FF(RegQueryValueExA, -1)
05037     FF(RegSetValueExA, -1)
05038     FF(RegQueryInfoKeyA, -1)
05039 };
05040 struct exports exp_gdi32[]={
05041     FF(CreateCompatibleDC, -1)
05042     FF(CreateFontA, -1)
05043     FF(DeleteDC, -1)
05044     FF(DeleteObject, -1)
05045     FF(GetDeviceCaps, -1)
05046     FF(GetSystemPaletteEntries, -1)
05047 #ifdef QTX
05048     FF(CreatePalette, -1)
05049     FF(GetObjectA, -1)
05050     FF(CreateRectRgn, -1)
05051 #endif
05052 };
05053 struct exports exp_version[]={
05054     FF(GetFileVersionInfoSizeA, -1)
05055 };
05056 struct exports exp_ole32[]={
05057     FF(CoCreateFreeThreadedMarshaler,-1)
05058     FF(CoCreateInstance, -1)
05059     FF(CoInitialize, -1)
05060     FF(CoTaskMemAlloc, -1)
05061     FF(CoTaskMemFree, -1)
05062     FF(StringFromGUID2, -1)
05063 };
05064 // do we really need crtdll ???
05065 // msvcrt is the correct place probably...
05066 struct exports exp_crtdll[]={
05067     FF(memcpy, -1)
05068     FF(wcscpy, -1)
05069 };
05070 struct exports exp_comctl32[]={
05071     FF(StringFromGUID2, -1)
05072     FF(InitCommonControls, 17)
05073 #ifdef QTX
05074     FF(CreateUpDownControl, 16)
05075 #endif
05076 };
05077 struct exports exp_wsock32[]={
05078     FF(htonl,8)
05079     FF(ntohl,14)
05080 };
05081 struct exports exp_msdmo[]={
05082     FF(memcpy, -1) // just test
05083     FF(MoCopyMediaType, -1)
05084     FF(MoCreateMediaType, -1)
05085     FF(MoDeleteMediaType, -1)
05086     FF(MoDuplicateMediaType, -1)
05087     FF(MoFreeMediaType, -1)
05088     FF(MoInitMediaType, -1)
05089 };
05090 struct exports exp_oleaut32[]={
05091     FF(VariantInit, 8)
05092 #ifdef QTX
05093     FF(SysStringByteLen, 149)
05094 #endif
05095 };
05096 
05097 /*  realplayer8:
05098         DLL Name: PNCRT.dll
05099         vma:  Hint/Ord Member-Name
05100         22ff4     615  free
05101         2302e     250  _ftol
05102         22fea     666  malloc
05103         2303e     609  fprintf
05104         2305e     167  _adjust_fdiv
05105         23052     280  _initterm
05106 
05107         22ffc     176  _beginthreadex
05108         23036     284  _iob
05109         2300e      85  __CxxFrameHandler
05110         23022     411  _purecall
05111 */
05112 #ifdef REALPLAYER
05113 struct exports exp_pncrt[]={
05114     FF(malloc, -1) // just test
05115     FF(free, -1) // just test
05116     FF(fprintf, -1) // just test
05117     {"_adjust_fdiv", -1, (void*)&_adjust_fdiv},
05118     FF(_ftol,-1)
05119     FF(_initterm, -1)
05120     {"??3@YAXPAX@Z", -1, expdelete},
05121     {"??2@YAPAXI@Z", -1, expnew},
05122     FF(__dllonexit, -1)
05123     FF(strncpy, -1)
05124     FF(_CIpow,-1)
05125     FF(calloc,-1)
05126     FF(memmove, -1)
05127 };
05128 #endif
05129 
05130 #ifdef QTX
05131 struct exports exp_ddraw[]={
05132     FF(DirectDrawCreate, -1)
05133 };
05134 #endif
05135 
05136 struct exports exp_comdlg32[]={
05137     FF(GetOpenFileNameA, -1)
05138 };
05139 
05140 #define LL(X) \
05141     {#X".dll", sizeof(exp_##X)/sizeof(struct exports), exp_##X},
05142 
05143 struct libs libraries[]={
05144     LL(kernel32)
05145     LL(msvcrt)
05146     LL(winmm)
05147     LL(user32)
05148     LL(advapi32)
05149     LL(gdi32)
05150     LL(version)
05151     LL(ole32)
05152     LL(oleaut32)
05153     LL(crtdll)
05154     LL(comctl32)
05155     LL(wsock32)
05156     LL(msdmo)
05157 #ifdef REALPLAYER
05158     LL(pncrt)
05159 #endif
05160 #ifdef QTX
05161     LL(ddraw)
05162 #endif
05163     LL(comdlg32)
05164 };
05165 
05166 static void ext_stubs(void)
05167 {
05168     // expects:
05169     //  ax  position index
05170     //  cx  address of printf function
05171 #if 1
05172     __asm__ __volatile__
05173         (
05174          "push %%edx            \n\t"
05175          "movl $0xdeadbeef, %%eax \n\t"
05176          "movl $0xdeadbeef, %%edx \n\t"
05177          "shl $5, %%eax         \n\t"                   // ax * 32
05178          "addl $0xdeadbeef, %%eax \n\t"                 // overwrite export_names
05179          "pushl %%eax           \n\t"
05180          "pushl $0xdeadbeef     \n\t"                   // overwrite called_unk
05181          "call *%%edx           \n\t"                   // printf (via dx)
05182          "addl $8, %%esp        \n\t"
05183          "xorl %%eax, %%eax     \n\t"
05184          "pop %%edx             \n\t"
05185          :
05186          :
05187          : "eax"
05188         );
05189 #else
05190     __asm__ __volatile__
05191         (
05192          "push %%edx            \n\t"
05193          "movl $0, %%eax        \n\t"
05194          "movl $0, %%edx        \n\t"
05195          "shl $5, %%eax         \n\t"                   // ax * 32
05196          "addl %0, %%eax        \n\t"
05197          "pushl %%eax           \n\t"
05198          "pushl %1              \n\t"
05199          "call *%%edx           \n\t"                   // printf (via dx)
05200          "addl $8, %%esp        \n\t"
05201          "xorl %%eax, %%eax     \n\t"
05202          "pop %%edx             \n\t"
05203          ::"m"(*export_names), "m"(*called_unk)
05204         : "memory", "edx", "eax"
05205         );
05206 #endif
05207 
05208 }
05209 
05210 //static void add_stub(int pos)
05211 
05212 extern int unk_exp1;
05213 static int pos=0;
05214 static char extcode[20000];// place for 200 unresolved exports
05215 static const char* called_unk = "Called unk_%s\n";
05216 
05217 static void* add_stub(void)
05218 {
05219     // generated code in runtime!
05220     char* answ = (char*)extcode+pos*0x30;
05221 #if 0
05222     memcpy(answ, &unk_exp1, 0x64);
05223     *(int*)(answ+9)=pos;
05224     *(int*)(answ+47)-=((int)answ-(int)&unk_exp1);
05225 #endif
05226     memcpy(answ, ext_stubs, 0x2f); // 0x2c is current size
05227     //answ[4] = 0xb8; // movl $0, eax  (0xb8 0x00000000)
05228     *((int*) (answ + 5)) = pos;
05229     //answ[9] = 0xba; // movl $0, edx  (0xba 0x00000000)
05230     *((long*) (answ + 10)) = (long)printf;
05231     //answ[17] = 0x05; // addl $0, eax  (0x05 0x00000000)
05232     *((long*) (answ + 18)) = (long)export_names;
05233     //answ[23] = 0x68; // pushl $0  (0x68 0x00000000)
05234     *((long*) (answ + 24)) = (long)called_unk;
05235     pos++;
05236     return (void*)answ;
05237 }
05238 
05239 void* LookupExternal(const char* library, int ordinal)
05240 {
05241     int i,j;
05242     if(library==0)
05243     {
05244         printf("ERROR: library=0\n");
05245         return (void*)ext_unknown;
05246     }
05247     //    printf("%x %x\n", &unk_exp1, &unk_exp2);
05248 
05249     dbgprintf("External func %s:%d\n", library, ordinal);
05250 
05251     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
05252     {
05253         if(strcasecmp(library, libraries[i].name))
05254             continue;
05255         for(j=0; j<libraries[i].length; j++)
05256         {
05257             if(ordinal!=libraries[i].exps[j].id)
05258                 continue;
05259             //printf("Hit: 0x%p\n", libraries[i].exps[j].func);
05260             return libraries[i].exps[j].func;
05261         }
05262     }
05263 
05264 #ifndef LOADLIB_TRY_NATIVE
05265   /* hack for truespeech and vssh264*/
05266   if (!strcmp(library, "tsd32.dll") || !strcmp(library,"vssh264dec.dll") || !strcmp(library,"LCMW2.dll") || !strcmp(library,"VDODEC32.dll"))
05267 #endif
05268     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
05269     {
05270         int hand;
05271         WINE_MODREF *wm;
05272         void *func;
05273 
05274         hand = LoadLibraryA(library);
05275         if (!hand)
05276             goto no_dll;
05277         wm = MODULE32_LookupHMODULE(hand);
05278         if (!wm)
05279         {
05280             FreeLibrary(hand);
05281             goto no_dll;
05282         }
05283         func = PE_FindExportedFunction(wm, (LPCSTR) ordinal, 0);
05284         if (!func)
05285         {
05286             printf("No such ordinal in external dll\n");
05287             FreeLibrary((int)hand);
05288             goto no_dll;
05289         }
05290 
05291         printf("External dll loaded (offset: 0x%x, func: %p)\n",
05292                hand, func);
05293         return func;
05294     }
05295 
05296 no_dll:
05297     if(pos>150)return 0;
05298     sprintf(export_names[pos], "%s:%d", library, ordinal);
05299     return add_stub();
05300 }
05301 
05302 void* LookupExternalByName(const char* library, const char* name)
05303 {
05304     char* answ;
05305     int i,j;
05306     //   return (void*)ext_unknown;
05307     if(library==0)
05308     {
05309         printf("ERROR: library=0\n");
05310         return (void*)ext_unknown;
05311     }
05312     if(name==0)
05313     {
05314         printf("ERROR: name=0\n");
05315         return (void*)ext_unknown;
05316     }
05317     dbgprintf("External func %s:%s\n", library, name);
05318     for(i=0; i<sizeof(libraries)/sizeof(struct libs); i++)
05319     {
05320         if(strcasecmp(library, libraries[i].name))
05321             continue;
05322         for(j=0; j<libraries[i].length; j++)
05323         {
05324             if(strcmp(name, libraries[i].exps[j].name))
05325                 continue;
05326             //      printf("Hit: 0x%08X\n", libraries[i].exps[j].func);
05327             return libraries[i].exps[j].func;
05328         }
05329     }
05330 
05331 #ifndef LOADLIB_TRY_NATIVE
05332   /* hack for vss h264 */
05333   if (!strcmp(library,"vssh264core.dll"))
05334 #endif
05335     /* ok, this is a hack, and a big memory leak. should be fixed. - alex */
05336     {
05337         int hand;
05338         WINE_MODREF *wm;
05339         void *func;
05340 
05341         hand = LoadLibraryA(library);
05342         if (!hand)
05343             goto no_dll_byname;
05344         wm = MODULE32_LookupHMODULE(hand);
05345         if (!wm)
05346         {
05347             FreeLibrary(hand);
05348             goto no_dll_byname;
05349         }
05350         func = PE_FindExportedFunction(wm, name, 0);
05351         if (!func)
05352         {
05353             printf("No such name in external dll\n");
05354             FreeLibrary((int)hand);
05355             goto no_dll_byname;
05356         }
05357 
05358         printf("External dll loaded (offset: 0x%x, func: %p)\n",
05359                hand, func);
05360         return func;
05361     }
05362 
05363 no_dll_byname:
05364     if(pos>150)return 0;// to many symbols
05365     strcpy(export_names[pos], name);
05366     return add_stub();
05367 }
05368 
05369 void my_garbagecollection(void)
05370 {
05371 #ifdef GARBAGE
05372     int unfree = 0, unfreecnt = 0;
05373 
05374     int max_fatal = 8;
05375     free_registry();
05376     while (last_alloc)
05377     {
05378         alloc_header* mem = last_alloc + 1;
05379         unfree += my_size(mem);
05380         unfreecnt++;
05381         if (my_release(mem) != 0)
05382             // avoid endless loop when memory is trashed
05383             if (--max_fatal < 0)
05384                 break;
05385     }
05386     dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt);
05387 #endif
05388     g_tls = NULL;
05389     list = NULL;
05390 }

Generated on Tue Dec 20 10:14:22 2005 for vlc-0.8.4a by  doxygen 1.4.2