win32.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:138k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: 7f4acf121296f902d385b21ad02325ddfe536df4 $
  3.  *
  4.  * Originally distributed under LPGL 2.1 (or later) by the Wine project.
  5.  *
  6.  * Modified for use with MPlayer, detailed CVS changelog at
  7.  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
  8.  *
  9.  * File now distributed as part of VLC media player with no modifications.
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  */
  25. /***********************************************************
  26. Win32 emulation code. Functions that emulate
  27. responses from corresponding Win32 API calls.
  28. Since we are not going to be able to load
  29. virtually any DLL, we can only implement this
  30. much, adding needed functions with each new codec.
  31. Basic principle of implementation: it's not good
  32. for DLL to know too much about its environment.
  33. ************************************************************/
  34. #include "config.h"
  35. #ifdef MPLAYER
  36. #ifdef USE_QTX_CODECS
  37. #define QTX
  38. #endif
  39. #define REALPLAYER
  40. //#define LOADLIB_TRY_NATIVE
  41. #endif
  42. #ifdef QTX
  43. #define PSEUDO_SCREEN_WIDTH /*640*/800
  44. #define PSEUDO_SCREEN_HEIGHT /*480*/600
  45. #endif
  46. #include "wine/winbase.h"
  47. #include "wine/winreg.h"
  48. #include "wine/winnt.h"
  49. #include "wine/winerror.h"
  50. #include "wine/debugtools.h"
  51. #include "wine/module.h"
  52. #include "wine/winuser.h"
  53. #include <stdio.h>
  54. #include "win32.h"
  55. #include "registry.h"
  56. #include "loader.h"
  57. #include "com.h"
  58. #include "ext.h"
  59. #include <stdlib.h>
  60. #include <assert.h>
  61. #include <stdarg.h>
  62. #include <ctype.h>
  63. #include <pthread.h>
  64. #include <errno.h>
  65. #ifdef HAVE_MALLOC_H
  66. #include <malloc.h>
  67. #endif
  68. #include <time.h>
  69. #include <math.h>
  70. #include <unistd.h>
  71. #include <fcntl.h>
  72. #include <sys/types.h>
  73. #include <dirent.h>
  74. #include <sys/time.h>
  75. #include <sys/timeb.h>
  76. #ifdef HAVE_KSTAT
  77. #include <kstat.h>
  78. #endif
  79. #if HAVE_VSSCANF
  80. int vsscanf( const char *str, const char *format, va_list ap);
  81. #else
  82. /* system has no vsscanf.  try to provide one */
  83. static int vsscanf( const char *str, const char *format, va_list ap)
  84. {
  85.     long p1 = va_arg(ap, long);
  86.     long p2 = va_arg(ap, long);
  87.     long p3 = va_arg(ap, long);
  88.     long p4 = va_arg(ap, long);
  89.     long p5 = va_arg(ap, long);
  90.     return sscanf(str, format, p1, p2, p3, p4, p5);
  91. }
  92. #endif
  93. static char* def_path = WIN32_PATH;
  94. static void do_cpuid(unsigned int ax, unsigned int *regs)
  95. {
  96.     __asm__ __volatile__
  97. (
  98.  "pushl %%ebx; pushl %%ecx; pushl %%edx;"
  99.  ".byte  0x0f, 0xa2;"
  100.  "movl   %%eax, (%2);"
  101.  "movl   %%ebx, 4(%2);"
  102.  "movl   %%ecx, 8(%2);"
  103.  "movl   %%edx, 12(%2);"
  104.  "popl %%edx; popl %%ecx; popl %%ebx;"
  105.  : "=a" (ax)
  106.  :  "0" (ax), "S" (regs)
  107. );
  108. }
  109. static unsigned int c_localcount_tsc()
  110. {
  111.     int a;
  112.     __asm__ __volatile__
  113. (
  114.  "rdtscnt"
  115.  :"=a"(a)
  116.  :
  117.  :"edx"
  118. );
  119.     return a;
  120. }
  121. static void c_longcount_tsc(long long* z)
  122. {
  123.     __asm__ __volatile__
  124. (
  125.  "pushl %%ebxnt"
  126.  "movl %%eax, %%ebxnt"
  127.  "rdtscnt"
  128.  "movl %%eax, 0(%%ebx)nt"
  129.  "movl %%edx, 4(%%ebx)nt"
  130.  "popl %%ebxnt"
  131.  ::"a"(z)
  132.  :"edx"
  133. );
  134. }
  135. static unsigned int c_localcount_notsc()
  136. {
  137.     struct timeval tv;
  138.     unsigned limit=~0;
  139.     limit/=1000000;
  140.     gettimeofday(&tv, 0);
  141.     return limit*tv.tv_usec;
  142. }
  143. static void c_longcount_notsc(long long* z)
  144. {
  145.     struct timeval tv;
  146.     unsigned long long result;
  147.     unsigned limit=~0;
  148.     if(!z)return;
  149.     limit/=1000000;
  150.     gettimeofday(&tv, 0);
  151.     result=tv.tv_sec;
  152.     result<<=32;
  153.     result+=limit*tv.tv_usec;
  154.     *z=result;
  155. }
  156. static unsigned int localcount_stub(void);
  157. static void longcount_stub(long long*);
  158. static unsigned int (*localcount)()=localcount_stub;
  159. static void (*longcount)(long long*)=longcount_stub;
  160. static pthread_mutex_t memmut;
  161. static unsigned int localcount_stub(void)
  162. {
  163.     unsigned int regs[4];
  164.     do_cpuid(1, regs);
  165.     if ((regs[3] & 0x00000010) != 0)
  166.     {
  167. localcount=c_localcount_tsc;
  168. longcount=c_longcount_tsc;
  169.     }
  170.     else
  171.     {
  172. localcount=c_localcount_notsc;
  173. longcount=c_longcount_notsc;
  174.     }
  175.     return localcount();
  176. }
  177. static void longcount_stub(long long* z)
  178. {
  179.     unsigned int regs[4];
  180.     do_cpuid(1, regs);
  181.     if ((regs[3] & 0x00000010) != 0)
  182.     {
  183. localcount=c_localcount_tsc;
  184. longcount=c_longcount_tsc;
  185.     }
  186.     else
  187.     {
  188. localcount=c_localcount_notsc;
  189. longcount=c_longcount_notsc;
  190.     }
  191.     longcount(z);
  192. }
  193. #ifdef MPLAYER
  194. #include "../mp_msg.h"
  195. #endif
  196. int LOADER_DEBUG=1; // active only if compiled with -DDETAILED_OUT
  197. //#define DETAILED_OUT
  198. static inline void dbgprintf(const char* fmt, ...)
  199. {
  200. #ifdef DETAILED_OUT
  201.     if(LOADER_DEBUG)
  202.     {
  203. FILE* f;
  204. va_list va;
  205. va_start(va, fmt);
  206. f=fopen("./log", "a");
  207. vprintf(fmt, va);
  208. fflush(stdout);
  209. if(f)
  210. {
  211.     vfprintf(f, fmt, va);
  212.     fsync(fileno(f));
  213.     fclose(f);
  214. }
  215. va_end(va);
  216.     }
  217. #endif
  218. #ifdef MPLAYER
  219.     if (verbose > 2)
  220.     {
  221. va_list va;
  222. va_start(va, fmt);
  223. vprintf(fmt, va);
  224. // mp_dbg(MSGT_WIN32, MSGL_DBG3, fmt, va);
  225. va_end(va);
  226.     }
  227.   fflush(stdout);
  228. #endif
  229. }
  230. char export_names[300][32]={
  231.     "name1",
  232.     //"name2",
  233.     //"name3"
  234. };
  235. //#define min(x,y) ((x)<(y)?(x):(y))
  236. void destroy_event(void* event);
  237. struct th_list_t;
  238. typedef struct th_list_t{
  239.     int id;
  240.     void* thread;
  241.     struct th_list_t* next;
  242.     struct th_list_t* prev;
  243. } th_list;
  244. // have to be cleared by GARBAGE COLLECTOR
  245. static unsigned char* heap=NULL;
  246. static int heap_counter=0;
  247. static tls_t* g_tls=NULL;
  248. static th_list* list=NULL;
  249. static void test_heap(void)
  250. {
  251.     int offset=0;
  252.     if(heap==0)
  253. return;
  254.     while(offset<heap_counter)
  255.     {
  256. if(*(int*)(heap+offset)!=0x433476)
  257. {
  258.     printf("Heap corruption at address %dn", offset);
  259.     return;
  260. }
  261. offset+=8+*(int*)(heap+offset+4);
  262.     }
  263.     for(;offset<min(offset+1000, 20000000); offset++)
  264. if(heap[offset]!=0xCC)
  265. {
  266.     printf("Free heap corruption at address %dn", offset);
  267. }
  268. }
  269. #undef MEMORY_DEBUG
  270. #ifdef MEMORY_DEBUG
  271. static void* my_mreq(int size, int to_zero)
  272. {
  273.     static int test=0;
  274.     test++;
  275.     if(test%10==0)printf("Memory: %d bytes allocatedn", heap_counter);
  276.     //    test_heap();
  277.     if(heap==NULL)
  278.     {
  279. heap=malloc(20000000);
  280. memset(heap, 0xCC,20000000);
  281.     }
  282.     if(heap==0)
  283.     {
  284. printf("No enough memoryn");
  285. return 0;
  286.     }
  287.     if(heap_counter+size>20000000)
  288.     {
  289. printf("No enough memoryn");
  290. return 0;
  291.     }
  292.     *(int*)(heap+heap_counter)=0x433476;
  293.     heap_counter+=4;
  294.     *(int*)(heap+heap_counter)=size;
  295.     heap_counter+=4;
  296.     printf("Allocated %d bytes of memory: sys %d, user %d-%dn", size, heap_counter-8, heap_counter, heap_counter+size);
  297.     if(to_zero)
  298. memset(heap+heap_counter, 0, size);
  299.     else
  300. memset(heap+heap_counter, 0xcc, size);  // make crash reproducable
  301.     heap_counter+=size;
  302.     return heap+heap_counter-size;
  303. }
  304. static int my_release(char* memory)
  305. {
  306.     //    test_heap();
  307.     if(memory==NULL)
  308.     {
  309. printf("ERROR: free(0)n");
  310. return 0;
  311.     }
  312.     if(*(int*)(memory-8)!=0x433476)
  313.     {
  314. printf("MEMORY CORRUPTION !!!!!!!!!!!!!!!!!!!n");
  315. return 0;
  316.     }
  317.     printf("Freed %d bytes of memoryn", *(int*)(memory-4));
  318.     //    memset(memory-8, *(int*)(memory-4), 0xCC);
  319.     return 0;
  320. }
  321. #else
  322. #define GARBAGE
  323. typedef struct alloc_header_t alloc_header;
  324. struct alloc_header_t
  325. {
  326.     // let's keep allocated data 16 byte aligned
  327.     alloc_header* prev;
  328.     alloc_header* next;
  329.     long deadbeef;
  330.     long size;
  331.     long type;
  332.     long reserved1;
  333.     long reserved2;
  334.     long reserved3;
  335. };
  336. #ifdef GARBAGE
  337. static alloc_header* last_alloc = NULL;
  338. static int alccnt = 0;
  339. #endif
  340. #define AREATYPE_CLIENT 0
  341. #define AREATYPE_EVENT 1
  342. #define AREATYPE_MUTEX 2
  343. #define AREATYPE_COND 3
  344. #define AREATYPE_CRITSECT 4
  345. /* -- critical sections -- */
  346. struct CRITSECT
  347. {
  348.     pthread_t id;
  349.     pthread_mutex_t mutex;
  350.     int locked;
  351.     long deadbeef;
  352. };
  353. void* mreq_private(int size, int to_zero, int type);
  354. void* mreq_private(int size, int to_zero, int type)
  355. {
  356.     int nsize = size + sizeof(alloc_header);
  357.     alloc_header* header = (alloc_header* ) malloc(nsize);
  358.     if (!header)
  359.         return 0;
  360.     if (to_zero)
  361. memset(header, 0, nsize);
  362. #ifdef GARBAGE
  363.     if (!last_alloc)
  364.     {
  365. pthread_mutex_init(&memmut, NULL);
  366. pthread_mutex_lock(&memmut);
  367.     }
  368.     else
  369.     {
  370. pthread_mutex_lock(&memmut);
  371. last_alloc->next = header;  /* set next */
  372.     }
  373.     header->prev = last_alloc;
  374.     header->next = 0;
  375.     last_alloc = header;
  376.     alccnt++;
  377.     pthread_mutex_unlock(&memmut);
  378. #endif
  379.     header->deadbeef = 0xdeadbeef;
  380.     header->size = size;
  381.     header->type = type;
  382.     //if (alccnt < 40000) printf("MY_REQ: %pt%d   t:%d  (cnt:%d)n",  header, size, type, alccnt);
  383.     return header + 1;
  384. }
  385. static int my_release(void* memory)
  386. {
  387.     alloc_header* header = (alloc_header*) memory - 1;
  388. #ifdef GARBAGE
  389.     alloc_header* prevmem;
  390.     alloc_header* nextmem;
  391.     if (memory == 0)
  392. return 0;
  393.     if (header->deadbeef != (long) 0xdeadbeef)
  394.     {
  395. dbgprintf("FATAL releasing corrupted memory! %p  0x%lx  (%d)n", header, header->deadbeef, alccnt);
  396. return 0;
  397.     }
  398.     pthread_mutex_lock(&memmut);
  399.     switch(header->type)
  400.     {
  401.     case AREATYPE_EVENT:
  402. destroy_event(memory);
  403. break;
  404.     case AREATYPE_COND:
  405. pthread_cond_destroy((pthread_cond_t*)memory);
  406. break;
  407.     case AREATYPE_MUTEX:
  408. pthread_mutex_destroy((pthread_mutex_t*)memory);
  409. break;
  410.     case AREATYPE_CRITSECT:
  411. pthread_mutex_destroy(&((struct CRITSECT*)memory)->mutex);
  412. break;
  413.     default:
  414. //memset(memory, 0xcc, header->size);
  415. ;
  416.     }
  417.     header->deadbeef = 0;
  418.     prevmem = header->prev;
  419.     nextmem = header->next;
  420.     if (prevmem)
  421. prevmem->next = nextmem;
  422.     if (nextmem)
  423. nextmem->prev = prevmem;
  424.     if (header == last_alloc)
  425. last_alloc = prevmem;
  426.     alccnt--;
  427.     if (last_alloc)
  428. pthread_mutex_unlock(&memmut);
  429.     else
  430. pthread_mutex_destroy(&memmut);
  431.     //if (alccnt < 40000) printf("MY_RELEASE: %pt%ld    (%d)n", header, header->size, alccnt);
  432. #else
  433.     if (memory == 0)
  434. return 0;
  435. #endif
  436.     //memset(header + 1, 0xcc, header->size);
  437.     free(header);
  438.     return 0;
  439. }
  440. #endif
  441. static inline void* my_mreq(int size, int to_zero)
  442. {
  443.     return mreq_private(size, to_zero, AREATYPE_CLIENT);
  444. }
  445. static int my_size(void* memory)
  446. {
  447.     if(!memory) return 0;
  448.     return ((alloc_header*)memory)[-1].size;
  449. }
  450. static void* my_realloc(void* memory, int size)
  451. {
  452.     void *ans = memory;
  453.     int osize;
  454.     if (memory == NULL)
  455. return my_mreq(size, 0);
  456.     osize = my_size(memory);
  457.     if (osize < size)
  458.     {
  459. ans = my_mreq(size, 0);
  460. memcpy(ans, memory, osize);
  461. my_release(memory);
  462.     }
  463.     return ans;
  464. }
  465. /*
  466.  *
  467.  *  WINE  API  - native implementation for several win32 libraries
  468.  *
  469.  */
  470. static int WINAPI ext_unknown()
  471. {
  472.     printf("Unknown func calledn");
  473.     return 0;
  474. }
  475. static int  WINAPI expGetVolumeInformationA( const char *root, char *label,
  476.                                        unsigned int label_len, unsigned int *serial,
  477.                                        unsigned int *filename_len,unsigned int *flags,
  478.                                        char *fsname, unsigned int fsname_len )
  479. {
  480. dbgprintf("GetVolumeInformationA( %s, 0x%x, %ld, 0x%x, 0x%x, 0x%x, 0x%x, %ld) => 1n",
  481.       root,label,label_len,serial,filename_len,flags,fsname,fsname_len);
  482. //hack Do not return any real data - do nothing
  483. return 1;
  484. }
  485. static unsigned int WINAPI expGetDriveTypeA( const char *root )
  486. {
  487.  dbgprintf("GetDriveTypeA( %s ) => %dn",root,DRIVE_FIXED);
  488.  // hack return as Fixed Drive Type
  489.  return DRIVE_FIXED;
  490. }
  491. static unsigned int WINAPI expGetLogicalDriveStringsA( unsigned int len, char *buffer )
  492. {
  493.  dbgprintf("GetLogicalDriveStringsA(%d, 0x%x) => 4n",len,buffer);
  494.  // hack only have one drive c: in this hack
  495.   *buffer++='c';
  496.   *buffer++=':';
  497.   *buffer++='\';
  498.   *buffer++='';
  499.   *buffer= '';
  500. return 4; // 1 drive * 4 bytes (includes null)
  501. }
  502. static int WINAPI expIsBadWritePtr(void* ptr, unsigned int count)
  503. {
  504.     int result = (count == 0 || ptr != 0) ? 0 : 1;
  505.     dbgprintf("IsBadWritePtr(0x%x, 0x%x) => %dn", ptr, count, result);
  506.     return result;
  507. }
  508. static int WINAPI expIsBadReadPtr(void* ptr, unsigned int count)
  509. {
  510.     int result = (count == 0 || ptr != 0) ? 0 : 1;
  511.     dbgprintf("IsBadReadPtr(0x%x, 0x%x) => %dn", ptr, count, result);
  512.     return result;
  513. }
  514. static int WINAPI expDisableThreadLibraryCalls(int module)
  515. {
  516.     dbgprintf("DisableThreadLibraryCalls(0x%x) => 0n", module);
  517.     return 0;
  518. }
  519. static HMODULE WINAPI expGetDriverModuleHandle(DRVR* pdrv)
  520. {
  521.     HMODULE result;
  522.     if (pdrv==NULL)
  523. result=0;
  524.     else
  525. result=pdrv->hDriverModule;
  526.     dbgprintf("GetDriverModuleHandle(%p) => %pn", pdrv, result);
  527.     return result;
  528. }
  529. #define MODULE_HANDLE_kernel32 ((HMODULE)0x120)
  530. #define MODULE_HANDLE_user32 ((HMODULE)0x121)
  531. #ifdef QTX
  532. #define MODULE_HANDLE_wininet ((HMODULE)0x122)
  533. #define MODULE_HANDLE_ddraw ((HMODULE)0x123)
  534. #define MODULE_HANDLE_advapi32 ((HMODULE)0x124)
  535. #endif
  536. #define MODULE_HANDLE_comdlg32 ((HMODULE)0x125)
  537. #define MODULE_HANDLE_msvcrt ((HMODULE)0x126)
  538. #define MODULE_HANDLE_ole32 ((HMODULE)0x127)
  539. #define MODULE_HANDLE_winmm ((HMODULE)0x128)
  540. static HMODULE WINAPI expGetModuleHandleA(const char* name)
  541. {
  542.     WINE_MODREF* wm;
  543.     HMODULE result;
  544.     if(!name)
  545. #ifdef QTX
  546. result=1;
  547. #else
  548. result=0;
  549. #endif
  550.     else
  551.     {
  552. wm=MODULE_FindModule(name);
  553. if(wm==0)result=0;
  554. else
  555.     result=(HMODULE)(wm->module);
  556.     }
  557.     if(!result)
  558.     {
  559. if(name && (strcasecmp(name, "kernel32")==0 || !strcasecmp(name, "kernel32.dll")))
  560.     result=MODULE_HANDLE_kernel32;
  561. #ifdef QTX
  562. if(name && strcasecmp(name, "user32")==0)
  563.     result=MODULE_HANDLE_user32;
  564. #endif
  565.     }
  566.     dbgprintf("GetModuleHandleA('%s') => 0x%xn", name, result);
  567.     return result;
  568. }
  569. static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize,
  570.     void* lpStartAddress, void* lpParameter,
  571.     long dwFlags, long* dwThreadId)
  572. {
  573.     pthread_t *pth;
  574.     //    printf("CreateThread:");
  575.     pth = (pthread_t*) my_mreq(sizeof(pthread_t), 0);
  576.     pthread_create(pth, NULL, (void*(*)(void*))lpStartAddress, lpParameter);
  577.     if(dwFlags)
  578. printf( "WARNING: CreateThread flags not supportedn");
  579.     if(dwThreadId)
  580. *dwThreadId=(long)pth;
  581.     if(list==NULL)
  582.     {
  583. list=my_mreq(sizeof(th_list), 1);
  584. list->next=list->prev=NULL;
  585.     }
  586.     else
  587.     {
  588. list->next=my_mreq(sizeof(th_list), 0);
  589. list->next->prev=list;
  590. list->next->next=NULL;
  591. list=list->next;
  592.     }
  593.     list->thread=pth;
  594.     dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%xn",
  595.       pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth);
  596.     return pth;
  597. }
  598. struct mutex_list_t;
  599. struct mutex_list_t
  600. {
  601.     char type;
  602.     pthread_mutex_t *pm;
  603.     pthread_cond_t  *pc;
  604.     char state;
  605.     char reset;
  606.     char name[128];
  607.     int  semaphore;
  608.     struct mutex_list_t* next;
  609.     struct mutex_list_t* prev;
  610. };
  611. typedef struct mutex_list_t mutex_list;
  612. static mutex_list* mlist=NULL;
  613. void destroy_event(void* event)
  614. {
  615.     mutex_list* pp=mlist;
  616.     //    printf("garbage collector: destroy_event(%x)n", event);
  617.     while(pp)
  618.     {
  619. if(pp==(mutex_list*)event)
  620. {
  621.     if(pp->next)
  622. pp->next->prev=pp->prev;
  623.     if(pp->prev)
  624. pp->prev->next=pp->next;
  625.     if(mlist==(mutex_list*)event)
  626. mlist=mlist->prev;
  627.     /*
  628.      pp=mlist;
  629.      while(pp)
  630.      {
  631.      printf("%x => ", pp);
  632.      pp=pp->prev;
  633.      }
  634.      printf("0n");
  635.      */
  636.     return;
  637. }
  638. pp=pp->prev;
  639.     }
  640. }
  641. static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset,
  642.     char bInitialState, const char* name)
  643. {
  644.     pthread_mutex_t *pm;
  645.     pthread_cond_t  *pc;
  646.     /*
  647.      mutex_list* pp;
  648.      pp=mlist;
  649.      while(pp)
  650.      {
  651.      printf("%x => ", pp);
  652.      pp=pp->prev;
  653.      }
  654.      printf("0n");
  655.      */
  656.     if(mlist!=NULL)
  657.     {
  658. mutex_list* pp=mlist;
  659. if(name!=NULL)
  660.     do
  661. {
  662.     if((strcmp(pp->name, name)==0) && (pp->type==0))
  663.     {
  664. dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%xn",
  665.   pSecAttr, bManualReset, bInitialState, name, name, pp->pm);
  666. return pp->pm;
  667.     }
  668. }while((pp=pp->prev) != NULL);
  669.     }
  670.     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
  671.     pthread_mutex_init(pm, NULL);
  672.     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
  673.     pthread_cond_init(pc, NULL);
  674.     if(mlist==NULL)
  675.     {
  676. mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
  677. mlist->next=mlist->prev=NULL;
  678.     }
  679.     else
  680.     {
  681. mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
  682. mlist->next->prev=mlist;
  683. mlist->next->next=NULL;
  684. mlist=mlist->next;
  685.     }
  686.     mlist->type=0; /* Type Event */
  687.     mlist->pm=pm;
  688.     mlist->pc=pc;
  689.     mlist->state=bInitialState;
  690.     mlist->reset=bManualReset;
  691.     if(name)
  692. strncpy(mlist->name, name, 127);
  693.     else
  694. mlist->name[0]=0;
  695.     if(pm==NULL)
  696. dbgprintf("ERROR::: CreateEventA failuren");
  697.     /*
  698.      if(bInitialState)
  699.      pthread_mutex_lock(pm);
  700.      */
  701.     if(name)
  702. dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%xn",
  703.   pSecAttr, bManualReset, bInitialState, name, name, mlist);
  704.     else
  705. dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%xn",
  706.   pSecAttr, bManualReset, bInitialState, mlist);
  707.     return mlist;
  708. }
  709. static void* WINAPI expSetEvent(void* event)
  710. {
  711.     mutex_list *ml = (mutex_list *)event;
  712.     dbgprintf("SetEvent(%x) => 0x1n", event);
  713.     pthread_mutex_lock(ml->pm);
  714.     if (ml->state == 0) {
  715. ml->state = 1;
  716. pthread_cond_signal(ml->pc);
  717.     }
  718.     pthread_mutex_unlock(ml->pm);
  719.     return (void *)1;
  720. }
  721. static void* WINAPI expResetEvent(void* event)
  722. {
  723.     mutex_list *ml = (mutex_list *)event;
  724.     dbgprintf("ResetEvent(0x%x) => 0x1n", event);
  725.     pthread_mutex_lock(ml->pm);
  726.     ml->state = 0;
  727.     pthread_mutex_unlock(ml->pm);
  728.     return (void *)1;
  729. }
  730. static void* WINAPI expWaitForSingleObject(void* object, int duration)
  731. {
  732.     mutex_list *ml = (mutex_list *)object;
  733.     // FIXME FIXME FIXME - this value is sometime unititialize !!!
  734.     int ret = WAIT_FAILED;
  735.     mutex_list* pp=mlist;
  736.     if(object == (void*)0xcfcf9898)
  737.     {
  738. /**
  739.  From GetCurrentThread() documentation:
  740.  A pseudo handle is a special constant that is interpreted as the current thread handle. The calling thread can use this handle to specify itself whenever a thread handle is required. Pseudo handles are not inherited by child processes.
  741.  This handle has the maximum possible access to the thread object. For systems that support security descriptors, this is the maximum access allowed by the security descriptor for the calling process. For systems that do not support security descriptors, this is THREAD_ALL_ACCESS.
  742.  The function cannot be used by one thread to create a handle that can be used by other threads to refer to the first thread. The handle is always interpreted as referring to the thread that is using it. A thread can create a "real" handle to itself that can be used by other threads, or inherited by other processes, by specifying the pseudo handle as the source handle in a call to the DuplicateHandle function.
  743.  **/
  744. dbgprintf("WaitForSingleObject(thread_handle) calledn");
  745. return (void*)WAIT_FAILED;
  746.     }
  747.     dbgprintf("WaitForSingleObject(0x%x, duration %d) =>n",object, duration);
  748.     // loop below was slightly fixed - its used just for checking if
  749.     // this object really exists in our list
  750.     if (!ml)
  751. return (void*) ret;
  752.     while (pp && (pp->pm != ml->pm))
  753. pp = pp->prev;
  754.     if (!pp) {
  755. dbgprintf("WaitForSingleObject: NotFoundn");
  756. return (void*)ret;
  757.     }
  758.     pthread_mutex_lock(ml->pm);
  759.     switch(ml->type) {
  760.     case 0: /* Event */
  761. if (duration == 0) { /* Check Only */
  762.     if (ml->state == 1) ret = WAIT_FAILED;
  763.     else                   ret = WAIT_OBJECT_0;
  764. }
  765. if (duration == -1) { /* INFINITE */
  766.     if (ml->state == 0)
  767. pthread_cond_wait(ml->pc,ml->pm);
  768.     if (ml->reset)
  769. ml->state = 0;
  770.     ret = WAIT_OBJECT_0;
  771. }
  772. if (duration > 0) {  /* Timed Wait */
  773.     struct timespec abstime;
  774.     struct timeval now;
  775.     gettimeofday(&now, 0);
  776.     abstime.tv_sec = now.tv_sec + (now.tv_usec+duration)/1000000;
  777.     abstime.tv_nsec = ((now.tv_usec+duration)%1000000)*1000;
  778.     if (ml->state == 0)
  779. ret=pthread_cond_timedwait(ml->pc,ml->pm,&abstime);
  780.     if (ret == ETIMEDOUT) ret = WAIT_TIMEOUT;
  781.     else                  ret = WAIT_OBJECT_0;
  782.     if (ml->reset)
  783. ml->state = 0;
  784. }
  785. break;
  786.     case 1:  /* Semaphore */
  787. if (duration == 0) {
  788.     if(ml->semaphore==0) ret = WAIT_FAILED;
  789.     else {
  790. ml->semaphore++;
  791. ret = WAIT_OBJECT_0;
  792.     }
  793. }
  794. if (duration == -1) {
  795.     if (ml->semaphore==0)
  796. pthread_cond_wait(ml->pc,ml->pm);
  797.     ml->semaphore--;
  798. }
  799. break;
  800.     }
  801.     pthread_mutex_unlock(ml->pm);
  802.     dbgprintf("WaitForSingleObject(0x%x, %d): 0x%x => 0x%x n",object,duration,ml,ret);
  803.     return (void *)ret;
  804. }
  805. #ifdef QTX
  806. static void* WINAPI expWaitForMultipleObjects(int count, const void** objects,
  807.     int WaitAll, int duration)
  808. {
  809.     int i;
  810.     void *object;
  811.     void *ret;
  812.     dbgprintf("WaitForMultipleObjects(%d, 0x%x, %d, duration %d) =>n",
  813. count, objects, WaitAll, duration);
  814.     
  815.     for (i = 0; i < count; i++)
  816.     {
  817. object = (void *)objects[i];
  818. ret = expWaitForSingleObject(object, duration);
  819. if (WaitAll)
  820.     dbgprintf("WaitAll flag not yet supported...n");
  821. else
  822.     return ret;
  823.     }
  824.     return NULL;
  825. }
  826. static void WINAPI expExitThread(int retcode)
  827. {
  828.     dbgprintf("ExitThread(%d)n", retcode);
  829.     pthread_exit(&retcode);
  830. }
  831. static HANDLE WINAPI expCreateMutexA(void *pSecAttr,
  832.     char bInitialOwner, const char *name)
  833. {
  834.     HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name);
  835.     
  836.     if (name)
  837. dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%xn",
  838.     pSecAttr, bInitialOwner, name, mlist);
  839.     else
  840. dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%xn",
  841.     pSecAttr, bInitialOwner, mlist);
  842. #ifndef QTX
  843.     /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject
  844.        waits for ever, else it works ;) */
  845.     return mlist;
  846. #endif
  847. }
  848. static int WINAPI expReleaseMutex(HANDLE hMutex)
  849. {
  850.     dbgprintf("ReleaseMutex(%x) => 1n", hMutex);
  851.     /* FIXME:XXX !! not yet implemented */
  852.     return 1;
  853. }
  854. #endif
  855. static int pf_set = 0;
  856. static BYTE PF[64] = {0,};
  857. static void DumpSystemInfo(const SYSTEM_INFO* si)
  858. {
  859.     dbgprintf("  Processor architecture %dn", si->u.s.wProcessorArchitecture);
  860.     dbgprintf("  Page size: %dn", si->dwPageSize);
  861.     dbgprintf("  Minimum app address: %dn", si->lpMinimumApplicationAddress);
  862.     dbgprintf("  Maximum app address: %dn", si->lpMaximumApplicationAddress);
  863.     dbgprintf("  Active processor mask: 0x%xn", si->dwActiveProcessorMask);
  864.     dbgprintf("  Number of processors: %dn", si->dwNumberOfProcessors);
  865.     dbgprintf("  Processor type: 0x%xn", si->dwProcessorType);
  866.     dbgprintf("  Allocation granularity: 0x%xn", si->dwAllocationGranularity);
  867.     dbgprintf("  Processor level: 0x%xn", si->wProcessorLevel);
  868.     dbgprintf("  Processor revision: 0x%xn", si->wProcessorRevision);
  869. }
  870. static void WINAPI expGetSystemInfo(SYSTEM_INFO* si)
  871. {
  872.     /* FIXME: better values for the two entries below... */
  873.     static int cache = 0;
  874.     static SYSTEM_INFO cachedsi;
  875.     unsigned int regs[4];
  876.     dbgprintf("GetSystemInfo(%p) =>n", si);
  877.     if (cache) {
  878. memcpy(si,&cachedsi,sizeof(*si));
  879. DumpSystemInfo(si);
  880. return;
  881.     }
  882.     memset(PF,0,sizeof(PF));
  883.     pf_set = 1;
  884.     cachedsi.u.s.wProcessorArchitecture     = PROCESSOR_ARCHITECTURE_INTEL;
  885.     cachedsi.dwPageSize  = getpagesize();
  886.     /* FIXME: better values for the two entries below... */
  887.     cachedsi.lpMinimumApplicationAddress = (void *)0x00000000;
  888.     cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
  889.     cachedsi.dwActiveProcessorMask = 1;
  890.     cachedsi.dwNumberOfProcessors = 1;
  891.     cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
  892.     cachedsi.dwAllocationGranularity = 0x10000;
  893.     cachedsi.wProcessorLevel = 5; /* pentium */
  894.     cachedsi.wProcessorRevision = 0x0101;
  895. #ifdef MPLAYER
  896.     /* mplayer's way to detect PF's */
  897.     {
  898. #include "../cpudetect.h"
  899. extern CpuCaps gCpuCaps;
  900. if (gCpuCaps.hasMMX)
  901.     PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
  902. if (gCpuCaps.hasSSE)
  903.     PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
  904. if (gCpuCaps.has3DNow)
  905.     PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
  906.     if (gCpuCaps.cpuType == 4)
  907.     {
  908.         cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
  909. cachedsi.wProcessorLevel = 4;
  910.     }
  911.     else if (gCpuCaps.cpuType >= 5)
  912.     {
  913. cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  914. cachedsi.wProcessorLevel = 5;
  915.     }
  916.     else
  917.     {
  918.         cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
  919. cachedsi.wProcessorLevel = 3;
  920.     }
  921.     cachedsi.wProcessorRevision = gCpuCaps.cpuStepping;
  922.          cachedsi.dwNumberOfProcessors = 1; /* hardcoded */
  923.     }
  924. #endif
  925. /* disable cpuid based detection (mplayer's cpudetect.c does this - see above) */
  926. #ifndef MPLAYER
  927. #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__svr4__) || defined(__DragonFly__)
  928.     do_cpuid(1, regs);
  929.     switch ((regs[0] >> 8) & 0xf) { // cpu family
  930.     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
  931.     cachedsi.wProcessorLevel= 3;
  932.     break;
  933.     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
  934.     cachedsi.wProcessorLevel= 4;
  935.     break;
  936.     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  937.     cachedsi.wProcessorLevel= 5;
  938.     break;
  939.     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  940.     cachedsi.wProcessorLevel= 5;
  941.     break;
  942.     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  943.     cachedsi.wProcessorLevel= 5;
  944.     break;
  945.     }
  946.     cachedsi.wProcessorRevision = regs[0] & 0xf; // stepping
  947.     if (regs[3] & (1 <<  8))
  948. PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
  949.     if (regs[3] & (1 << 23))
  950. PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
  951.     if (regs[3] & (1 << 25))
  952. PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
  953.     if (regs[3] & (1 << 31))
  954. PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
  955.     cachedsi.dwNumberOfProcessors=1;
  956. #endif
  957. #endif /* MPLAYER */
  958. /* MPlayer: linux detection enabled (based on proc/cpuinfo) for checking
  959.    fdiv_bug and fpu emulation flags -- alex/MPlayer */
  960. #ifdef __linux__
  961.     {
  962. char buf[20];
  963. char line[200];
  964. FILE *f = fopen ("/proc/cpuinfo", "r");
  965. if (!f)
  966.     return;
  967. while (fgets(line,200,f)!=NULL) {
  968.     char *s,*value;
  969.     /* NOTE: the ':' is the only character we can rely on */
  970.     if (!(value = strchr(line,':')))
  971. continue;
  972.     /* terminate the valuename */
  973.     *value++ = '';
  974.     /* skip any leading spaces */
  975.     while (*value==' ') value++;
  976.     if ((s=strchr(value,'n')))
  977. *s='';
  978.     /* 2.1 method */
  979.     if (!lstrncmpiA(line, "cpu family",strlen("cpu family"))) {
  980. if (isdigit (value[0])) {
  981.     switch (value[0] - '0') {
  982.     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
  983.     cachedsi.wProcessorLevel= 3;
  984.     break;
  985.     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
  986.     cachedsi.wProcessorLevel= 4;
  987.     break;
  988.     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  989.     cachedsi.wProcessorLevel= 5;
  990.     break;
  991.     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  992.     cachedsi.wProcessorLevel= 5;
  993.     break;
  994.     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  995.     cachedsi.wProcessorLevel= 5;
  996.     break;
  997.     }
  998. }
  999. /* set the CPU type of the current processor */
  1000. sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
  1001. continue;
  1002.     }
  1003.     /* old 2.0 method */
  1004.     if (!lstrncmpiA(line, "cpu",strlen("cpu"))) {
  1005. if ( isdigit (value[0]) && value[1] == '8' &&
  1006. value[2] == '6' && value[3] == 0
  1007.    ) {
  1008.     switch (value[0] - '0') {
  1009.     case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
  1010.     cachedsi.wProcessorLevel= 3;
  1011.     break;
  1012.     case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
  1013.     cachedsi.wProcessorLevel= 4;
  1014.     break;
  1015.     case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  1016.     cachedsi.wProcessorLevel= 5;
  1017.     break;
  1018.     case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  1019.     cachedsi.wProcessorLevel= 5;
  1020.     break;
  1021.     default:cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
  1022.     cachedsi.wProcessorLevel= 5;
  1023.     break;
  1024.     }
  1025. }
  1026. /* set the CPU type of the current processor */
  1027. sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
  1028. continue;
  1029.     }
  1030.     if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
  1031. if (!lstrncmpiA(value,"yes",3))
  1032.     PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
  1033. continue;
  1034.     }
  1035.     if (!lstrncmpiA(line,"fpu",strlen("fpu"))) {
  1036. if (!lstrncmpiA(value,"no",2))
  1037.     PF[PF_FLOATING_POINT_EMULATED] = TRUE;
  1038. continue;
  1039.     }
  1040.     if (!lstrncmpiA(line,"processor",strlen("processor"))) {
  1041. /* processor number counts up...*/
  1042. unsigned int x;
  1043. if (sscanf(value,"%d",&x))
  1044.     if (x+1>cachedsi.dwNumberOfProcessors)
  1045. cachedsi.dwNumberOfProcessors=x+1;
  1046. /* Create a new processor subkey on a multiprocessor
  1047.  * system
  1048.  */
  1049. sprintf(buf,"%d",x);
  1050.     }
  1051.     if (!lstrncmpiA(line,"stepping",strlen("stepping"))) {
  1052. int x;
  1053. if (sscanf(value,"%d",&x))
  1054.     cachedsi.wProcessorRevision = x;
  1055.     }
  1056.     if
  1057. ( (!lstrncmpiA(line,"flags",strlen("flags")))
  1058.   || (!lstrncmpiA(line,"features",strlen("features"))) )
  1059.     {
  1060. if (strstr(value,"cx8"))
  1061.     PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
  1062. if (strstr(value,"mmx"))
  1063.     PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
  1064. if (strstr(value,"tsc"))
  1065.     PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
  1066. if (strstr(value,"xmm"))
  1067.     PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
  1068. if (strstr(value,"3dnow"))
  1069.     PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = TRUE;
  1070.     }
  1071. }
  1072. fclose (f);
  1073. /*
  1074.  * ad hoc fix for smp machines.
  1075.  * some problems on WaitForSingleObject,CreateEvent,SetEvent
  1076.  * CreateThread ...etc..
  1077.  *
  1078.  */
  1079. cachedsi.dwNumberOfProcessors=1;
  1080.     }
  1081. #endif /* __linux__ */
  1082.     cache = 1;
  1083.     memcpy(si,&cachedsi,sizeof(*si));
  1084.     DumpSystemInfo(si);
  1085. }
  1086. // avoid undefined expGetSystemInfo
  1087. static WIN_BOOL WINAPI expIsProcessorFeaturePresent(DWORD v)
  1088. {
  1089.     WIN_BOOL result = 0;
  1090.     if (!pf_set)
  1091.     {
  1092. SYSTEM_INFO si;
  1093. expGetSystemInfo(&si);
  1094.     }
  1095.     if(v<64) result=PF[v];
  1096.     dbgprintf("IsProcessorFeaturePresent(0x%x) => 0x%xn", v, result);
  1097.     return result;
  1098. }
  1099. static long WINAPI expGetVersion()
  1100. {
  1101.     dbgprintf("GetVersion() => 0xC0000004n");
  1102.     return 0xC0000004;//Windows 95
  1103. }
  1104. static HANDLE WINAPI expHeapCreate(long flags, long init_size, long max_size)
  1105. {
  1106.     //    printf("HeapCreate:");
  1107.     HANDLE result;
  1108.     if(init_size==0)
  1109. result=(HANDLE)my_mreq(0x110000, 0);
  1110.     else
  1111. result=(HANDLE)my_mreq((init_size + 0xfff) & 0x7ffff000 , 0);
  1112.     dbgprintf("HeapCreate(flags 0x%x, initial size %d, maximum size %d) => 0x%xn", flags, init_size, max_size, result);
  1113.     return result;
  1114. }
  1115. // this is another dirty hack
  1116. // VP31 is releasing one allocated Heap chunk twice
  1117. // we will silently ignore this second call...
  1118. static void* heapfreehack = 0;
  1119. static int heapfreehackshown = 0;
  1120. //extern void trapbug(void);
  1121. static void* WINAPI expHeapAlloc(HANDLE heap, int flags, int size)
  1122. {
  1123.     void* z;
  1124.     /**
  1125.      Morgan's m3jpeg32.dll v. 2.0 encoder expects that request for
  1126.      HeapAlloc returns area larger than size argument :-/
  1127.      actually according to M$ Doc  HeapCreate size should be rounded
  1128.      to page boundaries thus we should simulate this
  1129.      **/
  1130.     //if (size == 22276) trapbug();
  1131.     z=my_mreq((size + 0xfff) & 0x7ffff000, (flags & HEAP_ZERO_MEMORY));
  1132.     if(z==0)
  1133. printf("HeapAlloc failuren");
  1134.     dbgprintf("HeapAlloc(heap 0x%x, flags 0x%x, size %d) => 0x%xn", heap, flags, size, z);
  1135.     heapfreehack = 0; // reset
  1136.     return z;
  1137. }
  1138. static long WINAPI expHeapDestroy(void* heap)
  1139. {
  1140.     dbgprintf("HeapDestroy(heap 0x%x) => 1n", heap);
  1141.     my_release(heap);
  1142.     return 1;
  1143. }
  1144. static long WINAPI expHeapFree(HANDLE heap, DWORD dwFlags, LPVOID lpMem)
  1145. {
  1146.     dbgprintf("HeapFree(0x%x, 0x%x, pointer 0x%x) => 1n", heap, dwFlags, lpMem);
  1147.     if (heapfreehack != lpMem && lpMem != (void*)0xffffffff
  1148. && lpMem != (void*)0xbdbdbdbd)
  1149. // 0xbdbdbdbd is for i263_drv.drv && libefence
  1150. // it seems to be reading from relased memory
  1151.         // EF_PROTECT_FREE doens't show any probleme
  1152. my_release(lpMem);
  1153.     else
  1154.     {
  1155. if (!heapfreehackshown++)
  1156.     printf("Info: HeapFree deallocating same memory twice! (%p)n", lpMem);
  1157.     }
  1158.     heapfreehack = lpMem;
  1159.     return 1;
  1160. }
  1161. static long WINAPI expHeapSize(int heap, int flags, void* pointer)
  1162. {
  1163.     long result=my_size(pointer);
  1164.     dbgprintf("HeapSize(heap 0x%x, flags 0x%x, pointer 0x%x) => %dn", heap, flags, pointer, result);
  1165.     return result;
  1166. }
  1167. static void* WINAPI expHeapReAlloc(HANDLE heap,int flags,void *lpMem,int size)
  1168. {
  1169.     long orgsize = my_size(lpMem);
  1170.     dbgprintf("HeapReAlloc() Size %ld org %dn",orgsize,size);
  1171.     return my_realloc(lpMem, size);
  1172. }
  1173. static long WINAPI expGetProcessHeap(void)
  1174. {
  1175.     dbgprintf("GetProcessHeap() => 1n");
  1176.     return 1;
  1177. }
  1178. static void* WINAPI expVirtualAlloc(void* v1, long v2, long v3, long v4)
  1179. {
  1180.     void* z = VirtualAlloc(v1, v2, v3, v4);
  1181.     if(z==0)
  1182. printf("VirtualAlloc failuren");
  1183.     dbgprintf("VirtualAlloc(0x%x, %d, %d, %d) => 0x%x n",v1,v2,v3,v4, z);
  1184.     return z;
  1185. }
  1186. static int WINAPI expVirtualFree(void* v1, int v2, int v3)
  1187. {
  1188.     int result = VirtualFree(v1,v2,v3);
  1189.     dbgprintf("VirtualFree(0x%x, %d, %d) => %dn",v1,v2,v3, result);
  1190.     return result;
  1191. }
  1192. /* we're building a table of critical sections. cs_win pointer uses the DLL
  1193.  cs_unix is the real structure, we're using cs_win only to identifying cs_unix */
  1194. struct critsecs_list_t
  1195. {
  1196.     CRITICAL_SECTION *cs_win;
  1197.     struct CRITSECT *cs_unix;
  1198. };
  1199. /* 'NEWTYPE' is working with VIVO, 3ivX and QTX dll (no more segfaults) -- alex */
  1200. #undef CRITSECS_NEWTYPE
  1201. //#define CRITSECS_NEWTYPE 1
  1202. #ifdef CRITSECS_NEWTYPE
  1203. /* increased due to ucod needs more than 32 entries */
  1204. /* and 64 should be enough for everything */
  1205. #define CRITSECS_LIST_MAX 64
  1206. static struct critsecs_list_t critsecs_list[CRITSECS_LIST_MAX];
  1207. static int critsecs_get_pos(CRITICAL_SECTION *cs_win)
  1208. {
  1209.     int i;
  1210.     for (i=0; i < CRITSECS_LIST_MAX; i++)
  1211. if (critsecs_list[i].cs_win == cs_win)
  1212.     return(i);
  1213.     return(-1);
  1214. }
  1215. static int critsecs_get_unused(void)
  1216. {
  1217.     int i;
  1218.     for (i=0; i < CRITSECS_LIST_MAX; i++)
  1219. if (critsecs_list[i].cs_win == NULL)
  1220.     return(i);
  1221.     return(-1);
  1222. }
  1223. struct CRITSECT *critsecs_get_unix(CRITICAL_SECTION *cs_win)
  1224. {
  1225.     int i;
  1226.     for (i=0; i < CRITSECS_LIST_MAX; i++)
  1227. if (critsecs_list[i].cs_win == cs_win && critsecs_list[i].cs_unix)
  1228.     return(critsecs_list[i].cs_unix);
  1229.     return(NULL);
  1230. }
  1231. #endif
  1232. static void WINAPI expInitializeCriticalSection(CRITICAL_SECTION* c)
  1233. {
  1234.     dbgprintf("InitializeCriticalSection(0x%x)n", c);
  1235.     /*    if(sizeof(pthread_mutex_t)>sizeof(CRITICAL_SECTION))
  1236.      {
  1237.      printf(" ERROR:::: sizeof(pthread_mutex_t) is %d, expected <=%d!n",
  1238.      sizeof(pthread_mutex_t), sizeof(CRITICAL_SECTION));
  1239.      return;
  1240.      }*/
  1241.     /*    pthread_mutex_init((pthread_mutex_t*)c, NULL);   */
  1242. #ifdef CRITSECS_NEWTYPE
  1243.     {
  1244. struct CRITSECT *cs;
  1245. int i = critsecs_get_unused();
  1246. if (i < 0)
  1247. {
  1248.     printf("InitializeCriticalSection(%p) - no more space in listn", c);
  1249.     return;
  1250. }
  1251. dbgprintf("got unused space at %dn", i);
  1252. cs = malloc(sizeof(struct CRITSECT));
  1253. if (!cs)
  1254. {
  1255.     printf("InitializeCriticalSection(%p) - out of memoryn", c);
  1256.     return;
  1257. }
  1258. pthread_mutex_init(&cs->mutex, NULL);
  1259. cs->locked = 0;
  1260. critsecs_list[i].cs_win = c;
  1261. critsecs_list[i].cs_unix = cs;
  1262. dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%pn",
  1263.   i, c, cs);
  1264.     }
  1265. #else
  1266.     {
  1267. struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
  1268.    0, AREATYPE_CRITSECT);
  1269. pthread_mutex_init(&cs->mutex, NULL);
  1270. cs->locked=0;
  1271.         cs->deadbeef = 0xdeadbeef;
  1272. *(void**)c = cs;
  1273.     }
  1274. #endif
  1275.     return;
  1276. }
  1277. static void WINAPI expEnterCriticalSection(CRITICAL_SECTION* c)
  1278. {
  1279. #ifdef CRITSECS_NEWTYPE
  1280.     struct CRITSECT* cs = critsecs_get_unix(c);
  1281. #else
  1282.     struct CRITSECT* cs = (*(struct CRITSECT**)c);
  1283. #endif
  1284.     dbgprintf("EnterCriticalSection(0x%x) %pn",c, cs);
  1285.     if (!cs)
  1286.     {
  1287. dbgprintf("entered uninitialized critisec!n");
  1288. expInitializeCriticalSection(c);
  1289. #ifdef CRITSECS_NEWTYPE
  1290. cs=critsecs_get_unix(c);
  1291. #else
  1292. cs = (*(struct CRITSECT**)c);
  1293. #endif
  1294. dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!n", c);
  1295.     }
  1296.     if(cs->locked)
  1297. if(cs->id==pthread_self())
  1298.     return;
  1299.     pthread_mutex_lock(&(cs->mutex));
  1300.     cs->locked=1;
  1301.     cs->id=pthread_self();
  1302.     return;
  1303. }
  1304. static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
  1305. {
  1306. #ifdef CRITSECS_NEWTYPE
  1307.     struct CRITSECT* cs = critsecs_get_unix(c);
  1308. #else
  1309.     struct CRITSECT* cs = (*(struct CRITSECT**)c);
  1310. #endif
  1311.     //    struct CRITSECT* cs=(struct CRITSECT*)c;
  1312.     dbgprintf("LeaveCriticalSection(0x%x) 0x%xn",c, cs);
  1313.     if (!cs)
  1314.     {
  1315. dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!n", c);
  1316. return;
  1317.     }
  1318.     if (cs->locked)
  1319.     {
  1320. cs->locked=0;
  1321. pthread_mutex_unlock(&(cs->mutex));
  1322.     }
  1323.     else
  1324. dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!n", c);
  1325.     return;
  1326. }
  1327. static void expfree(void* mem); /* forward declaration */
  1328. static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c)
  1329. {
  1330. #ifdef CRITSECS_NEWTYPE
  1331.     struct CRITSECT* cs = critsecs_get_unix(c);
  1332. #else
  1333.     struct CRITSECT* cs= (*(struct CRITSECT**)c);
  1334. #endif
  1335.     //    struct CRITSECT* cs=(struct CRITSECT*)c;
  1336.     dbgprintf("DeleteCriticalSection(0x%x)n",c);
  1337.     if (!cs)
  1338.     {
  1339. dbgprintf("Win32 Warning: Deleting uninitialized Critical Section %p!!n", c);
  1340. return;
  1341.     }
  1342.     
  1343.     if (cs->locked)
  1344.     {
  1345. dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!n", c);
  1346. pthread_mutex_unlock(&(cs->mutex));
  1347.     }
  1348. #ifndef GARBAGE
  1349.     pthread_mutex_destroy(&(cs->mutex));
  1350.     // released by GarbageCollector in my_relase otherwise
  1351. #endif
  1352.     my_release(cs);
  1353. #ifdef CRITSECS_NEWTYPE
  1354.     {
  1355. int i = critsecs_get_pos(c);
  1356. if (i < 0)
  1357. {
  1358.     printf("DeleteCriticalSection(%p) error (critsec not found)n", c);
  1359.     return;
  1360. }
  1361. critsecs_list[i].cs_win = NULL;
  1362. expfree(critsecs_list[i].cs_unix);
  1363. critsecs_list[i].cs_unix = NULL;
  1364. dbgprintf("DeleteCriticalSection -> itemno=%dn", i);
  1365.     }
  1366. #endif
  1367.     return;
  1368. }
  1369. static int WINAPI expGetCurrentThreadId()
  1370. {
  1371.     dbgprintf("GetCurrentThreadId() => %dn", pthread_self());
  1372.     return pthread_self();
  1373. }
  1374. static int WINAPI expGetCurrentProcess()
  1375. {
  1376.     dbgprintf("GetCurrentProcess() => %dn", getpid());
  1377.     return getpid();
  1378. }
  1379. #ifdef QTX
  1380. // this version is required for Quicktime codecs (.qtx/.qts) to work.
  1381. // (they assume some pointers at FS: segment)
  1382. extern void* fs_seg;
  1383. //static int tls_count;
  1384. static int tls_use_map[64];
  1385. static int WINAPI expTlsAlloc()
  1386. {
  1387.     int i;
  1388.     for(i=0; i<64; i++)
  1389. if(tls_use_map[i]==0)
  1390. {
  1391.     tls_use_map[i]=1;
  1392.     dbgprintf("TlsAlloc() => %dn",i);
  1393.     return i;
  1394. }
  1395.     dbgprintf("TlsAlloc() => -1 (ERROR)n");
  1396.     return -1;
  1397. }
  1398. //static int WINAPI expTlsSetValue(DWORD index, void* value)
  1399. static int WINAPI expTlsSetValue(int index, void* value)
  1400. {
  1401.     dbgprintf("TlsSetValue(%d,0x%x) => 1n",index,value);
  1402. //    if((index<0) || (index>64))
  1403.     if((index>=64))
  1404. return 0;
  1405.     *(void**)((char*)fs_seg+0x88+4*index) = value;
  1406.     return 1;
  1407. }
  1408. static void* WINAPI expTlsGetValue(DWORD index)
  1409. {
  1410.     dbgprintf("TlsGetValue(%d)n",index);
  1411. //    if((index<0) || (index>64))
  1412.     if((index>=64)) return NULL;
  1413.     return *(void**)((char*)fs_seg+0x88+4*index);
  1414. }
  1415. static int WINAPI expTlsFree(int idx)
  1416. {
  1417.     int index = (int) idx;
  1418.     dbgprintf("TlsFree(%d)n",index);
  1419.     if((index<0) || (index>64))
  1420. return 0;
  1421.     tls_use_map[index]=0;
  1422.     return 1;
  1423. }
  1424. #else
  1425. struct tls_s {
  1426.     void* value;
  1427.     int used;
  1428.     struct tls_s* prev;
  1429.     struct tls_s* next;
  1430. };
  1431. static void* WINAPI expTlsAlloc()
  1432. {
  1433.     if (g_tls == NULL)
  1434.     {
  1435. g_tls=my_mreq(sizeof(tls_t), 0);
  1436. g_tls->next=g_tls->prev=NULL;
  1437.     }
  1438.     else
  1439.     {
  1440. g_tls->next=my_mreq(sizeof(tls_t), 0);
  1441. g_tls->next->prev=g_tls;
  1442. g_tls->next->next=NULL;
  1443. g_tls=g_tls->next;
  1444.     }
  1445.     dbgprintf("TlsAlloc() => 0x%xn", g_tls);
  1446.     if (g_tls)
  1447. g_tls->value=0; /* XXX For Divx.dll */
  1448.     return g_tls;
  1449. }
  1450. static int WINAPI expTlsSetValue(void* idx, void* value)
  1451. {
  1452.     tls_t* index = (tls_t*) idx;
  1453.     int result;
  1454.     if(index==0)
  1455. result=0;
  1456.     else
  1457.     {
  1458. index->value=value;
  1459. result=1;
  1460.     }
  1461.     dbgprintf("TlsSetValue(index 0x%x, value 0x%x) => %d n", index, value, result );
  1462.     return result;
  1463. }
  1464. static void* WINAPI expTlsGetValue(void* idx)
  1465. {
  1466.     tls_t* index = (tls_t*) idx;
  1467.     void* result;
  1468.     if(index==0)
  1469. result=0;
  1470.     else
  1471. result=index->value;
  1472.     dbgprintf("TlsGetValue(index 0x%x) => 0x%xn", index, result);
  1473.     return result;
  1474. }
  1475. static int WINAPI expTlsFree(void* idx)
  1476. {
  1477.     tls_t* index = (tls_t*) idx;
  1478.     int result;
  1479.     if(index==0)
  1480. result=0;
  1481.     else
  1482.     {
  1483. if(index->next)
  1484.     index->next->prev=index->prev;
  1485. if(index->prev)
  1486.     index->prev->next=index->next;
  1487. if (g_tls == index)
  1488.             g_tls = index->prev;
  1489. my_release((void*)index);
  1490. result=1;
  1491.     }
  1492.     dbgprintf("TlsFree(index 0x%x) => %dn", index, result);
  1493.     return result;
  1494. }
  1495. #endif
  1496. static void* WINAPI expLocalAlloc(int flags, int size)
  1497. {
  1498.     void* z = my_mreq(size, (flags & GMEM_ZEROINIT));
  1499.     if (z == 0)
  1500. printf("LocalAlloc() failedn");
  1501.     dbgprintf("LocalAlloc(%d, flags 0x%x) => 0x%xn", size, flags, z);
  1502.     return z;
  1503. }
  1504. static void* WINAPI expLocalReAlloc(int handle,int size, int flags)
  1505. {
  1506.     void *newpointer;
  1507.     int oldsize;
  1508.     newpointer=NULL;
  1509.     if (flags & LMEM_MODIFY) {
  1510. dbgprintf("LocalReAlloc MODIFYn");
  1511. return (void *)handle;
  1512.     }
  1513.     oldsize = my_size((void *)handle);
  1514.     newpointer = my_realloc((void *)handle,size);
  1515.     dbgprintf("LocalReAlloc(%x %d(old %d), flags 0x%x) => 0x%xn", handle,size,oldsize, flags,newpointer);
  1516.     return newpointer;
  1517. }
  1518. static void* WINAPI expLocalLock(void* z)
  1519. {
  1520.     dbgprintf("LocalLock(0x%x) => 0x%xn", z, z);
  1521.     return z;
  1522. }
  1523. static void* WINAPI expGlobalAlloc(int flags, int size)
  1524. {
  1525.     void* z;
  1526.     dbgprintf("GlobalAlloc(%d, flags 0x%X)n", size, flags);
  1527.     z=my_mreq(size, (flags & GMEM_ZEROINIT));
  1528.     //z=calloc(size, 1);
  1529.     //z=malloc(size);
  1530.     if(z==0)
  1531. printf("GlobalAlloc() failedn");
  1532.     dbgprintf("GlobalAlloc(%d, flags 0x%x) => 0x%xn", size, flags, z);
  1533.     return z;
  1534. }
  1535. static void* WINAPI expGlobalLock(void* z)
  1536. {
  1537.     dbgprintf("GlobalLock(0x%x) => 0x%xn", z, z);
  1538.     return z;
  1539. }
  1540. // pvmjpg20 - but doesn't work anyway
  1541. static int WINAPI expGlobalSize(void* amem)
  1542. {
  1543.     int size = 100000;
  1544. #ifdef GARBAGE
  1545.     alloc_header* header = last_alloc;
  1546.     alloc_header* mem = (alloc_header*) amem - 1;
  1547.     if (amem == 0)
  1548. return 0;
  1549.     pthread_mutex_lock(&memmut);
  1550.     while (header)
  1551.     {
  1552. if (header->deadbeef != 0xdeadbeef)
  1553. {
  1554.     dbgprintf("FATAL found corrupted memory! %p  0x%lx  (%d)n", header, header->deadbeef, alccnt);
  1555.     break;
  1556. }
  1557. if (header == mem)
  1558. {
  1559.     size = header->size;
  1560.     break;
  1561. }
  1562. header = header->prev;
  1563.     }
  1564.     pthread_mutex_unlock(&memmut);
  1565. #endif
  1566.     dbgprintf("GlobalSize(0x%x)n", amem);
  1567.     return size;
  1568. }
  1569. static int WINAPI expLoadIconA( long hinstance, char *name )
  1570. {
  1571.  dbgprintf("LoadIconA( %ld, 0x%x ) => 1n",hinstance,name);
  1572.  return 1;
  1573. }
  1574. static int WINAPI expLoadStringA(long instance, long  id, void* buf, long size)
  1575. {
  1576.     int result=LoadStringA(instance, id, buf, size);
  1577.     //    if(buf)
  1578.     dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %d ( %s )n",
  1579.       instance, id, buf, size, result, buf);
  1580.     //    else
  1581.     //    dbgprintf("LoadStringA(instance 0x%x, id 0x%x, buffer 0x%x, size %d) => %dn",
  1582.     // instance, id, buf, size, result);
  1583.     return result;
  1584. }
  1585. static long WINAPI expMultiByteToWideChar(long v1, long v2, char* s1, long siz1, short* s2, int siz2)
  1586. {
  1587. #warning FIXME
  1588.     int i;
  1589.     int result;
  1590.     if(s2==0)
  1591. result=1;
  1592.     else
  1593.     {
  1594. if(siz1>siz2/2)siz1=siz2/2;
  1595. for(i=1; i<=siz1; i++)
  1596. {
  1597.     *s2=*s1;
  1598.     if(!*s1)break;
  1599.     s2++;
  1600.     s1++;
  1601. }
  1602. result=i;
  1603.     }
  1604.     if(s1)
  1605. dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string 0x%x='%s',"
  1606.   "size %d, dest buffer 0x%x, dest size %d) => %dn",
  1607.   v1, v2, s1, s1, siz1, s2, siz2, result);
  1608.     else
  1609. dbgprintf("MultiByteToWideChar(codepage %d, flags 0x%x, string NULL,"
  1610.   "size %d, dest buffer 0x%x, dest size %d) =>n",
  1611.   v1, v2, siz1, s2, siz2, result);
  1612.     return result;
  1613. }
  1614. static void wch_print(const short* str)
  1615. {
  1616.     dbgprintf("  src: ");
  1617.     while(*str)dbgprintf("%c", *str++);
  1618.     dbgprintf("n");
  1619. }
  1620. static long WINAPI expWideCharToMultiByte(long v1, long v2, short* s1, long siz1,
  1621.   char* s2, int siz2, char* c3, int* siz3)
  1622. {
  1623.     int result;
  1624.     dbgprintf("WideCharToMultiByte(codepage %d, flags 0x%x, src 0x%x, src size %d, "
  1625.       "dest 0x%x, dest size %d, defch 0x%x, used_defch 0x%x)", v1, v2, s1, siz1, s2, siz2, c3, siz3);
  1626.     result=WideCharToMultiByte(v1, v2, s1, siz1, s2, siz2, c3, siz3);
  1627.     dbgprintf("=> %dn", result);
  1628.     //if(s1)wch_print(s1);
  1629.     if(s2)dbgprintf("  dest: %sn", s2);
  1630.     return result;
  1631. }
  1632. static long WINAPI expGetVersionExA(OSVERSIONINFOA* c)
  1633. {
  1634.     dbgprintf("GetVersionExA(0x%x) => 1n");
  1635.     c->dwOSVersionInfoSize=sizeof(*c);
  1636.     c->dwMajorVersion=4;
  1637.     c->dwMinorVersion=0;
  1638.     c->dwBuildNumber=0x4000457;
  1639. #if 1
  1640.     // leave it here for testing win9x-only codecs
  1641.     c->dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
  1642.     strcpy(c->szCSDVersion, " B");
  1643. #else
  1644.     c->dwPlatformId=VER_PLATFORM_WIN32_NT; // let's not make DLL assume that it can read CR* registers
  1645.     strcpy(c->szCSDVersion, "Service Pack 3");
  1646. #endif
  1647.     dbgprintf("  Major version: 4n  Minor version: 0n  Build number: 0x4000457n"
  1648.       "  Platform Id: VER_PLATFORM_WIN32_NTn Version string: 'Service Pack 3'n");
  1649.     return 1;
  1650. }
  1651. static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count,
  1652.  long max_count, char* name)
  1653. {
  1654.     pthread_mutex_t *pm;
  1655.     pthread_cond_t  *pc;
  1656.     mutex_list* pp;
  1657.     /*
  1658.      printf("CreateSemaphoreA(%p = %s)n", name, (name ? name : "<null>"));
  1659.      pp=mlist;
  1660.      while(pp)
  1661.      {
  1662.      printf("%p => ", pp);
  1663.      pp=pp->prev;
  1664.      }
  1665.      printf("0n");
  1666.      */
  1667.     if(mlist!=NULL)
  1668.     {
  1669. mutex_list* pp=mlist;
  1670. if(name!=NULL)
  1671.     do
  1672. {
  1673.     if((strcmp(pp->name, name)==0) && (pp->type==1))
  1674.     {
  1675. dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%xn",
  1676.   v1, init_count, max_count, name, name, mlist);
  1677. return (HANDLE)mlist;
  1678.     }
  1679. }while((pp=pp->prev) != NULL);
  1680.     }
  1681.     pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX);
  1682.     pthread_mutex_init(pm, NULL);
  1683.     pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND);
  1684.     pthread_cond_init(pc, NULL);
  1685.     if(mlist==NULL)
  1686.     {
  1687. mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
  1688. mlist->next=mlist->prev=NULL;
  1689.     }
  1690.     else
  1691.     {
  1692. mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT);
  1693. mlist->next->prev=mlist;
  1694. mlist->next->next=NULL;
  1695. mlist=mlist->next;
  1696. // printf("new semaphore %pn", mlist);
  1697.     }
  1698.     mlist->type=1; /* Type Semaphore */
  1699.     mlist->pm=pm;
  1700.     mlist->pc=pc;
  1701.     mlist->state=0;
  1702.     mlist->reset=0;
  1703.     mlist->semaphore=init_count;
  1704.     if(name!=NULL)
  1705. strncpy(mlist->name, name, 64);
  1706.     else
  1707. mlist->name[0]=0;
  1708.     if(pm==NULL)
  1709. dbgprintf("ERROR::: CreateSemaphoreA failuren");
  1710.     if(name)
  1711. dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%xn",
  1712.   v1, init_count, max_count, name, name, mlist);
  1713.     else
  1714. dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%xn",
  1715.   v1, init_count, max_count, mlist);
  1716.     return (HANDLE)mlist;
  1717. }
  1718. static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count)
  1719. {
  1720.     // The state of a semaphore object is signaled when its count
  1721.     // is greater than zero and nonsignaled when its count is equal to zero
  1722.     // Each time a waiting thread is released because of the semaphore's signaled
  1723.     // state, the count of the semaphore is decreased by one.
  1724.     mutex_list *ml = (mutex_list *)hsem;
  1725.     pthread_mutex_lock(ml->pm);
  1726.     if (prev_count != 0) *prev_count = ml->semaphore;
  1727.     if (ml->semaphore == 0) pthread_cond_signal(ml->pc);
  1728.     ml->semaphore += increment;
  1729.     pthread_mutex_unlock(ml->pm);
  1730.     dbgprintf("ReleaseSemaphore(semaphore 0x%x, increment %d, prev_count 0x%x) => 1n",
  1731.       hsem, increment, prev_count);
  1732.     return 1;
  1733. }
  1734. static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey)
  1735. {
  1736.     long result=RegOpenKeyExA(key, subkey, reserved, access, newkey);
  1737.     dbgprintf("RegOpenKeyExA(key 0x%x, subkey %s, reserved %d, access 0x%x, pnewkey 0x%x) => %dn",
  1738.       key, subkey, reserved, access, newkey, result);
  1739.     if(newkey)dbgprintf("  New key: 0x%xn", *newkey);
  1740.     return result;
  1741. }
  1742. static long WINAPI expRegCloseKey(long key)
  1743. {
  1744.     long result=RegCloseKey(key);
  1745.     dbgprintf("RegCloseKey(0x%x) => %dn", key, result);
  1746.     return result;
  1747. }
  1748. static long WINAPI expRegQueryValueExA(long key, const char* value, int* reserved, int* type, int* data, int* count)
  1749. {
  1750.     long result=RegQueryValueExA(key, value, reserved, type, data, count);
  1751.     dbgprintf("RegQueryValueExA(key 0x%x, value %s, reserved 0x%x, data 0x%x, count 0x%x)"
  1752.       " => 0x%xn", key, value, reserved, data, count, result);
  1753.     if(data && count)dbgprintf("  read %d bytes: '%s'n", *count, data);
  1754.     return result;
  1755. }
  1756. //from wine source dlls/advapi32/registry.c
  1757. static long WINAPI expRegCreateKeyA(long hkey, const char* name, int *retkey)
  1758. {
  1759.     dbgprintf("RegCreateKeyA(key 0x%x, name 0x%x='%s',newkey=0x%x)n",hkey,name,retkey);
  1760.     return RegCreateKeyExA( hkey, name, 0, NULL,REG_OPTION_NON_VOLATILE,
  1761.                             KEY_ALL_ACCESS , NULL, retkey, NULL );
  1762. }
  1763. static long WINAPI expRegCreateKeyExA(long key, const char* name, long reserved,
  1764.       void* classs, long options, long security,
  1765.       void* sec_attr, int* newkey, int* status)
  1766. {
  1767.     long result=RegCreateKeyExA(key, name, reserved, classs, options, security, sec_attr, newkey, status);
  1768.     dbgprintf("RegCreateKeyExA(key 0x%x, name 0x%x='%s', reserved=0x%x,"
  1769.       " 0x%x, 0x%x, 0x%x, newkey=0x%x, status=0x%x) => %dn",
  1770.       key, name, name, reserved, classs, options, security, sec_attr, newkey, status, result);
  1771.     if(!result && newkey) dbgprintf("  New key: 0x%xn", *newkey);
  1772.     if(!result && status) dbgprintf("  New key status: 0x%xn", *status);
  1773.     return result;
  1774. }
  1775. static long WINAPI expRegSetValueExA(long key, const char* name, long v1, long v2, void* data, long size)
  1776. {
  1777.     long result=RegSetValueExA(key, name, v1, v2, data, size);
  1778.     dbgprintf("RegSetValueExA(key 0x%x, name '%s', 0x%x, 0x%x, data 0x%x -> 0x%x '%s', size=%d) => %d",
  1779.       key, name, v1, v2, data, *(int*)data, data, size, result);
  1780.     return result;
  1781. }
  1782. static long WINAPI expRegOpenKeyA (long hKey, LPCSTR lpSubKey, int* phkResult)
  1783. {
  1784.     long result=RegOpenKeyExA(hKey, lpSubKey, 0, 0, phkResult);
  1785.     dbgprintf("RegOpenKeyExA(key 0x%x, subkey '%s', 0x%x) => %dn",
  1786.       hKey, lpSubKey, phkResult, result);
  1787.     if(!result && phkResult) dbgprintf("  New key: 0x%xn", *phkResult);
  1788.     return result;
  1789. }
  1790. static DWORD WINAPI expRegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
  1791.      LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
  1792. {
  1793.     return RegEnumValueA(hkey, index, value, val_count,
  1794.  reserved, type, data, count);
  1795. }
  1796. static DWORD WINAPI expRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName,
  1797.      LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass,
  1798.      LPFILETIME lpftLastWriteTime)
  1799. {
  1800.     return RegEnumKeyExA(hKey, dwIndex, lpName, lpcbName, lpReserved, lpClass,
  1801.  lpcbClass, lpftLastWriteTime);
  1802. }
  1803. static long WINAPI expQueryPerformanceCounter(long long* z)
  1804. {
  1805.     longcount(z);
  1806.     dbgprintf("QueryPerformanceCounter(0x%x) => 1 ( %Ld )n", z, *z);
  1807.     return 1;
  1808. }
  1809. /*
  1810.  * dummy function RegQueryInfoKeyA(), required by vss codecs
  1811.  */
  1812. static DWORD WINAPI expRegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
  1813.                                          LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
  1814.                                          LPDWORD values, LPDWORD max_value, LPDWORD max_data,
  1815.                                          LPDWORD security, FILETIME *modif )
  1816. {
  1817.     return ERROR_SUCCESS;
  1818. }
  1819. /*
  1820.  * return CPU clock (in kHz), using linux's /proc filesystem (/proc/cpuinfo)
  1821.  */
  1822. static double linux_cpuinfo_freq()
  1823. {
  1824.     double freq=-1;
  1825.     FILE *f;
  1826.     char line[200];
  1827.     char *s,*value;
  1828.     f = fopen ("/proc/cpuinfo", "r");
  1829.     if (f != NULL) {
  1830. while (fgets(line,sizeof(line),f)!=NULL) {
  1831.     /* NOTE: the ':' is the only character we can rely on */
  1832.     if (!(value = strchr(line,':')))
  1833. continue;
  1834.     /* terminate the valuename */
  1835.     *value++ = '';
  1836.     /* skip any leading spaces */
  1837.     while (*value==' ') value++;
  1838.     if ((s=strchr(value,'n')))
  1839. *s='';
  1840.     if (!strncasecmp(line, "cpu MHz",strlen("cpu MHz"))
  1841. && sscanf(value, "%lf", &freq) == 1) {
  1842. freq*=1000;
  1843. break;
  1844.     }
  1845. }
  1846. fclose(f);
  1847.     }
  1848.     return freq;
  1849. }
  1850. static double solaris_kstat_freq()
  1851. {
  1852. #if defined(HAVE_LIBKSTAT) && defined(KSTAT_DATA_INT32)
  1853.     /*
  1854.      * try to extract the CPU speed from the solaris kernel's kstat data
  1855.      */
  1856.     kstat_ctl_t   *kc;
  1857.     kstat_t       *ksp;
  1858.     kstat_named_t *kdata;
  1859.     int            mhz = 0;
  1860.     kc = kstat_open();
  1861.     if (kc != NULL)
  1862.     {
  1863. ksp = kstat_lookup(kc, "cpu_info", 0, "cpu_info0");
  1864. /* kstat found and name/value pairs? */
  1865. if (ksp != NULL && ksp->ks_type == KSTAT_TYPE_NAMED)
  1866. {
  1867.     /* read the kstat data from the kernel */
  1868.     if (kstat_read(kc, ksp, NULL) != -1)
  1869.     {
  1870. /*
  1871.  * lookup desired "clock_MHz" entry, check the expected
  1872.  * data type
  1873.  */
  1874. kdata = (kstat_named_t *)kstat_data_lookup(ksp, "clock_MHz");
  1875. if (kdata != NULL && kdata->data_type == KSTAT_DATA_INT32)
  1876.     mhz = kdata->value.i32;
  1877.     }
  1878. }
  1879. kstat_close(kc);
  1880.     }
  1881.     if (mhz > 0)
  1882. return mhz * 1000.;
  1883. #endif /* HAVE_LIBKSTAT */
  1884.     return -1; // kstat stuff is not available, CPU freq is unknown
  1885. }
  1886. /*
  1887.  * Measure CPU freq using the pentium's time stamp counter register (TSC)
  1888.  */
  1889. static double tsc_freq()
  1890. {
  1891.     static double ofreq=0.0;
  1892.     int i;
  1893.     int x,y;
  1894.     i=time(NULL);
  1895.     if (ofreq != 0.0) return ofreq;
  1896.     while(i==time(NULL));
  1897.     x=localcount();
  1898.     i++;
  1899.     while(i==time(NULL));
  1900.     y=localcount();
  1901.     ofreq = (double)(y-x)/1000.;
  1902.     return ofreq;
  1903. }
  1904. static double CPU_Freq()
  1905. {
  1906.     double freq;
  1907.     if ((freq = linux_cpuinfo_freq()) > 0)
  1908. return freq;
  1909.     if ((freq = solaris_kstat_freq()) > 0)
  1910. return freq;
  1911.     return tsc_freq();
  1912. }
  1913. static long WINAPI expQueryPerformanceFrequency(long long* z)
  1914. {
  1915.     *z=(long long)CPU_Freq();
  1916.     dbgprintf("QueryPerformanceFrequency(0x%x) => 1 ( %Ld )n", z, *z);
  1917.     return 1;
  1918. }
  1919. static long WINAPI exptimeGetTime()
  1920. {
  1921.     struct timeval t;
  1922.     long result;
  1923.     gettimeofday(&t, 0);
  1924.     result=1000*t.tv_sec+t.tv_usec/1000;
  1925.     dbgprintf("timeGetTime() => %dn", result);
  1926.     return result;
  1927. }
  1928. static void* WINAPI expLocalHandle(void* v)
  1929. {
  1930.     dbgprintf("LocalHandle(0x%x) => 0x%xn", v, v);
  1931.     return v;
  1932. }
  1933. static void* WINAPI expGlobalHandle(void* v)
  1934. {
  1935.     dbgprintf("GlobalHandle(0x%x) => 0x%xn", v, v);
  1936.     return v;
  1937. }
  1938. static int WINAPI expGlobalUnlock(void* v)
  1939. {
  1940.     dbgprintf("GlobalUnlock(0x%x) => 1n", v);
  1941.     return 1;
  1942. }
  1943. static void* WINAPI expGlobalFree(void* v)
  1944. {
  1945.     dbgprintf("GlobalFree(0x%x) => 0n", v);
  1946.     my_release(v);
  1947.     //free(v);
  1948.     return 0;
  1949. }
  1950. static void* WINAPI expGlobalReAlloc(void* v, int size, int flags)
  1951. {
  1952.     void* result=my_realloc(v, size);
  1953.     //void* result=realloc(v, size);
  1954.     dbgprintf("GlobalReAlloc(0x%x, size %d, flags 0x%x) => 0x%xn", v,size,flags,result);
  1955.     return result;
  1956. }
  1957. static int WINAPI expLocalUnlock(void* v)
  1958. {
  1959.     dbgprintf("LocalUnlock(0x%x) => 1n", v);
  1960.     return 1;
  1961. }
  1962. //
  1963. static void* WINAPI expLocalFree(void* v)
  1964. {
  1965.     dbgprintf("LocalFree(0x%x) => 0n", v);
  1966.     my_release(v);
  1967.     return 0;
  1968. }
  1969. static HRSRC WINAPI expFindResourceA(HMODULE module, char* name, char* type)
  1970. {
  1971.     HRSRC result;
  1972.     result=FindResourceA(module, name, type);
  1973.     dbgprintf("FindResourceA(module 0x%x, name 0x%x(%s), type 0x%x(%s)) => 0x%xn",
  1974. module, name, HIWORD(name) ? name : "UNICODE", type, HIWORD(type) ? type : "UNICODE", result);
  1975.     return result;
  1976. }
  1977. extern HRSRC WINAPI LoadResource(HMODULE, HRSRC);
  1978. static HGLOBAL WINAPI expLoadResource(HMODULE module, HRSRC res)
  1979. {
  1980.     HGLOBAL result=LoadResource(module, res);
  1981.     dbgprintf("LoadResource(module 0x%x, resource 0x%x) => 0x%xn", module, res, result);
  1982.     return result;
  1983. }
  1984. static void* WINAPI expLockResource(long res)
  1985. {
  1986.     void* result=LockResource(res);
  1987.     dbgprintf("LockResource(0x%x) => 0x%xn", res, result);
  1988.     return result;
  1989. }
  1990. static int WINAPI expFreeResource(long res)
  1991. {
  1992.     int result=FreeResource(res);
  1993.     dbgprintf("FreeResource(0x%x) => %dn", res, result);
  1994.     return result;
  1995. }
  1996. //bool fun(HANDLE)
  1997. //!0 on success
  1998. static int WINAPI expCloseHandle(long v1)
  1999. {
  2000.     dbgprintf("CloseHandle(0x%x) => 1n", v1);
  2001.     /* do not close stdin,stdout and stderr */
  2002.     if (v1 > 2)
  2003. if (!close(v1))
  2004.     return 0;
  2005.     return 1;
  2006. }
  2007. static const char* WINAPI expGetCommandLineA()
  2008. {
  2009.     dbgprintf("GetCommandLineA() => "c:\aviplay.exe"n");
  2010.     return "c:\aviplay.exe";
  2011. }
  2012. static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\', 0, 0};
  2013. static LPWSTR WINAPI expGetEnvironmentStringsW()
  2014. {
  2015.     dbgprintf("GetEnvironmentStringsW() => 0n", envs);
  2016.     return 0;
  2017. }
  2018. static void * WINAPI expRtlZeroMemory(void *p, size_t len)
  2019. {
  2020.     void* result=memset(p,0,len);
  2021.     dbgprintf("RtlZeroMemory(0x%x, len %d) => 0x%xn",p,len,result);
  2022.     return result;
  2023. }
  2024. static void * WINAPI expRtlMoveMemory(void *dst, void *src, size_t len)
  2025. {
  2026.     void* result=memmove(dst,src,len);
  2027.     dbgprintf("RtlMoveMemory (dest 0x%x, src 0x%x, len %d) => 0x%xn",dst,src,len,result);
  2028.     return result;
  2029. }
  2030. static void * WINAPI expRtlFillMemory(void *p, int ch, size_t len)
  2031. {
  2032.     void* result=memset(p,ch,len);
  2033.     dbgprintf("RtlFillMemory(0x%x, char 0x%x, len %d) => 0x%xn",p,ch,len,result);
  2034.     return result;
  2035. }
  2036. static int WINAPI expFreeEnvironmentStringsW(short* strings)
  2037. {
  2038.     dbgprintf("FreeEnvironmentStringsW(0x%x) => 1n", strings);
  2039.     return 1;
  2040. }
  2041. static int WINAPI expFreeEnvironmentStringsA(char* strings)
  2042. {
  2043.     dbgprintf("FreeEnvironmentStringsA(0x%x) => 1n", strings);
  2044.     return 1;
  2045. }
  2046. static const char ch_envs[]=
  2047. "__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1rn"
  2048. "PATH=C:\;C:\windows\;C:\windows\systemrn";
  2049. static LPCSTR WINAPI expGetEnvironmentStrings()
  2050. {
  2051.     dbgprintf("GetEnvironmentStrings() => 0x%xn", ch_envs);
  2052.     return (LPCSTR)ch_envs;
  2053.     // dbgprintf("GetEnvironmentStrings() => 0n");
  2054.     // return 0;
  2055. }
  2056. static int WINAPI expGetStartupInfoA(STARTUPINFOA *s)
  2057. {
  2058.     int i;
  2059.     dbgprintf("GetStartupInfoA(0x%x) => 1n");
  2060.     memset(s, 0, sizeof(*s));
  2061.     s->cb=sizeof(*s);
  2062.     // s->lpReserved="Reserved";
  2063.     // s->lpDesktop="Desktop";
  2064.     // s->lpTitle="Title";
  2065.     // s->dwX=s->dwY=0;
  2066.     // s->dwXSize=s->dwYSize=200;
  2067.     s->dwFlags=s->wShowWindow=1;
  2068.     // s->hStdInput=s->hStdOutput=s->hStdError=0x1234;
  2069.     dbgprintf("  cb=%dn", s->cb);
  2070.     dbgprintf("  lpReserved='%s'n", s->lpReserved);
  2071.     dbgprintf("  lpDesktop='%s'n", s->lpDesktop);
  2072.     dbgprintf("  lpTitle='%s'n", s->lpTitle);
  2073.     dbgprintf("  dwX=%d dwY=%d dwXSize=%d dwYSize=%dn",
  2074.       s->dwX, s->dwY, s->dwXSize, s->dwYSize);
  2075.     dbgprintf("  dwXCountChars=%d dwYCountChars=%d dwFillAttribute=%dn",
  2076.       s->dwXCountChars, s->dwYCountChars, s->dwFillAttribute);
  2077.     dbgprintf("  dwFlags=0x%x wShowWindow=0x%x cbReserved2=0x%xn",
  2078.       s->dwFlags, s->wShowWindow, s->cbReserved2);
  2079.     dbgprintf("  lpReserved2=0x%x hStdInput=0x%x hStdOutput=0x%x hStdError=0x%xn",
  2080.       s->lpReserved2, s->hStdInput, s->hStdOutput, s->hStdError);
  2081.     return 1;
  2082. }
  2083. static int WINAPI expGetStdHandle(int z)
  2084. {
  2085.     dbgprintf("GetStdHandle(0x%x) => 0x%xn", z+0x1234);
  2086.     return z+0x1234;
  2087. }
  2088. #ifdef QTX
  2089. #define FILE_HANDLE_quicktimeqts ((HANDLE)0x444)
  2090. #define FILE_HANDLE_quicktimeqtx ((HANDLE)0x445)
  2091. #endif
  2092. static int WINAPI expGetFileType(int handle)
  2093. {
  2094.     dbgprintf("GetFileType(0x%x) => 0x3 = pipen", handle);
  2095.     return 0x3;
  2096. }
  2097. #ifdef QTX
  2098. static int WINAPI expGetFileAttributesA(char *filename)
  2099. {
  2100.     dbgprintf("GetFileAttributesA(%s) => FILE_ATTR_NORMALn", filename);
  2101.     if (strstr(filename, "QuickTime.qts"))
  2102. return FILE_ATTRIBUTE_SYSTEM;
  2103.     return FILE_ATTRIBUTE_NORMAL;
  2104. }
  2105. #endif
  2106. static int WINAPI expSetHandleCount(int count)
  2107. {
  2108.     dbgprintf("SetHandleCount(0x%x) => 1n", count);
  2109.     return 1;
  2110. }
  2111. static int WINAPI expGetACP(void)
  2112. {
  2113.     dbgprintf("GetACP() => 0n");
  2114.     return 0;
  2115. }
  2116. extern WINE_MODREF *MODULE32_LookupHMODULE(HMODULE m);
  2117. static int WINAPI expGetModuleFileNameA(int module, char* s, int len)
  2118. {
  2119.     WINE_MODREF *mr;
  2120.     int result;
  2121.     //printf("File name of module %X (%s) requestedn", module, s);
  2122.     if (module == 0 && len >= 12)
  2123.     {
  2124. /* return caller program name */
  2125. strcpy(s, "aviplay.dll");
  2126. result=1;
  2127.     }
  2128.     else if(s==0)
  2129. result=0;
  2130.     else
  2131. if(len<35)
  2132.     result=0;
  2133. else
  2134. {
  2135.     result=1;
  2136.     strcpy(s, "c:\windows\system\");
  2137.     mr=MODULE32_LookupHMODULE(module);
  2138.     if(mr==0)//oops
  2139. strcat(s, "aviplay.dll");
  2140.     else
  2141. if(strrchr(mr->filename, '/')==NULL)
  2142.     strcat(s, mr->filename);
  2143. else
  2144.     strcat(s, strrchr(mr->filename, '/')+1);
  2145. }
  2146.     if(!s)
  2147. dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %dn",
  2148.   module, s, len, result);
  2149.     else
  2150. dbgprintf("GetModuleFileNameA(0x%x, 0x%x, %d) => %d ( '%s' )n",
  2151.   module, s, len, result, s);
  2152.     return result;
  2153. }
  2154. static int WINAPI expSetUnhandledExceptionFilter(void* filter)
  2155. {
  2156.     dbgprintf("SetUnhandledExceptionFilter(0x%x) => 1n", filter);
  2157.     return 1;//unsupported and probably won't ever be supported
  2158. }
  2159. static int WINAPI expLoadLibraryA(char* name)
  2160. {
  2161.     int result = 0;
  2162.     char* lastbc;
  2163.     int i;
  2164.     if (!name)
  2165. return -1;
  2166.     // we skip to the last backslash
  2167.     // this is effectively eliminating weird characters in
  2168.     // the text output windows
  2169.     lastbc = strrchr(name, '\');
  2170.     if (lastbc)
  2171.     {
  2172. int i;
  2173. lastbc++;
  2174. for (i = 0; 1 ;i++)
  2175. {
  2176.     name[i] = *lastbc++;
  2177.     if (!name[i])
  2178. break;
  2179. }
  2180.     }
  2181.     if(strncmp(name, "c:\windows\", 11)==0) name += 11;
  2182.     if(strncmp(name, ".\", 2)==0) name += 2;
  2183.     dbgprintf("Entering LoadLibraryA(%s)n", name);
  2184.     // PIMJ and VIVO audio are loading  kernel32.dll
  2185.     if (strcasecmp(name, "kernel32.dll") == 0 || strcasecmp(name, "kernel32") == 0)
  2186. return MODULE_HANDLE_kernel32;
  2187. // return ERROR_SUCCESS; /* yeah, we have also the kernel32 calls */
  2188.       /* exported -> do not return failed! */
  2189.     if (strcasecmp(name, "user32.dll") == 0 || strcasecmp(name, "user32") == 0)
  2190. // return MODULE_HANDLE_kernel32;
  2191. return MODULE_HANDLE_user32;
  2192. #ifdef QTX
  2193.     if (strcasecmp(name, "wininet.dll") == 0 || strcasecmp(name, "wininet") == 0)
  2194. return MODULE_HANDLE_wininet;
  2195.     if (strcasecmp(name, "ddraw.dll") == 0 || strcasecmp(name, "ddraw") == 0)
  2196. return MODULE_HANDLE_ddraw;
  2197.     if (strcasecmp(name, "advapi32.dll") == 0 || strcasecmp(name, "advapi32") == 0)
  2198. return MODULE_HANDLE_advapi32;
  2199. #endif
  2200.     if (strcasecmp(name, "comdlg32.dll") == 0 || strcasecmp(name, "comdlg32") == 0)
  2201. return MODULE_HANDLE_comdlg32;
  2202.     if (strcasecmp(name, "msvcrt.dll") == 0 || strcasecmp(name, "msvcrt") == 0)
  2203. return MODULE_HANDLE_msvcrt;
  2204.     if (strcasecmp(name, "ole32.dll") == 0 || strcasecmp(name, "ole32") == 0)
  2205. return MODULE_HANDLE_ole32;
  2206.     if (strcasecmp(name, "winmm.dll") == 0 || strcasecmp(name, "winmm") == 0)
  2207. return MODULE_HANDLE_winmm;
  2208.     result=LoadLibraryA(name);
  2209.     dbgprintf("Returned LoadLibraryA(0x%x='%s'), def_path=%s => 0x%xn", name, name, def_path, result);
  2210.     return result;
  2211. }
  2212. static int WINAPI expFreeLibrary(int module)
  2213. {
  2214. #ifdef QTX
  2215.     int result=0; /* FIXME:XXX: qtx svq3 frees up qt.qts */
  2216. #else
  2217.     int result=FreeLibrary(module);
  2218. #endif
  2219.     dbgprintf("FreeLibrary(0x%x) => %dn", module, result);
  2220.     return result;
  2221. }
  2222. static void* WINAPI expGetProcAddress(HMODULE mod, char* name)
  2223. {
  2224.     void* result;
  2225.     switch(mod){
  2226.     case MODULE_HANDLE_kernel32:
  2227. result=LookupExternalByName("kernel32.dll", name); break;
  2228.     case MODULE_HANDLE_user32:
  2229. result=LookupExternalByName("user32.dll", name); break;
  2230. #ifdef QTX
  2231.     case MODULE_HANDLE_wininet:
  2232. result=LookupExternalByName("wininet.dll", name); break;
  2233.     case MODULE_HANDLE_ddraw:
  2234. result=LookupExternalByName("ddraw.dll", name); break;
  2235.     case MODULE_HANDLE_advapi32:
  2236. result=LookupExternalByName("advapi32.dll", name); break;
  2237. #endif
  2238.     case MODULE_HANDLE_comdlg32:
  2239. result=LookupExternalByName("comdlg32.dll", name); break;
  2240.     case MODULE_HANDLE_msvcrt:
  2241. result=LookupExternalByName("msvcrt.dll", name); break;
  2242.     case MODULE_HANDLE_ole32:
  2243. result=LookupExternalByName("ole32.dll", name); break;
  2244.     case MODULE_HANDLE_winmm:
  2245. result=LookupExternalByName("winmm.dll", name); break;
  2246.     default:
  2247. result=GetProcAddress(mod, name);
  2248.     }
  2249.     dbgprintf("GetProcAddress(0x%x, '%s') => 0x%xn", mod, name, result);
  2250.     return result;
  2251. }
  2252. static long WINAPI expCreateFileMappingA(int hFile, void* lpAttr,
  2253.  long flProtect, long dwMaxHigh,
  2254.  long dwMaxLow, const char* name)
  2255. {
  2256.     long result=CreateFileMappingA(hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name);
  2257.     if(!name)
  2258. dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
  2259.   "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0) => %dn",
  2260.   hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, result);
  2261.     else
  2262. dbgprintf("CreateFileMappingA(file 0x%x, lpAttr 0x%x,"
  2263.   "flProtect 0x%x, dwMaxHigh 0x%x, dwMaxLow 0x%x, name 0x%x='%s') => %dn",
  2264.   hFile, lpAttr, flProtect, dwMaxHigh, dwMaxLow, name, name, result);
  2265.     return result;
  2266. }
  2267. static long WINAPI expOpenFileMappingA(long hFile, long hz, const char* name)
  2268. {
  2269.     long result=OpenFileMappingA(hFile, hz, name);
  2270.     if(!name)
  2271. dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0) => %dn",
  2272.   hFile, hz, result);
  2273.     else
  2274. dbgprintf("OpenFileMappingA(0x%x, 0x%x, 0x%x='%s') => %dn",
  2275.   hFile, hz, name, name, result);
  2276.     return result;
  2277. }
  2278. static void* WINAPI expMapViewOfFile(HANDLE file, DWORD mode, DWORD offHigh,
  2279.      DWORD offLow, DWORD size)
  2280. {
  2281.     dbgprintf("MapViewOfFile(0x%x, 0x%x, 0x%x, 0x%x, size %d) => 0x%xn",
  2282.       file,mode,offHigh,offLow,size,(char*)file+offLow);
  2283.     return (char*)file+offLow;
  2284. }
  2285. static void* WINAPI expUnmapViewOfFile(void* view)
  2286. {
  2287.     dbgprintf("UnmapViewOfFile(0x%x) => 0n", view);
  2288.     return 0;
  2289. }
  2290. static void* WINAPI expSleep(int time)
  2291. {
  2292. #if HAVE_NANOSLEEP
  2293.     /* solaris doesn't have thread safe usleep */
  2294.     struct timespec tsp;
  2295.     tsp.tv_sec  =  time / 1000000;
  2296.     tsp.tv_nsec = (time % 1000000) * 1000;
  2297.     nanosleep(&tsp, NULL);
  2298. #else
  2299.     usleep(time);
  2300. #endif
  2301.     dbgprintf("Sleep(%d) => 0n", time);
  2302.     return 0;
  2303. }
  2304. // why does IV32 codec want to call this? I don't know ...
  2305. static int WINAPI expCreateCompatibleDC(int hdc)
  2306. {
  2307.     int dc = 0;//0x81;
  2308.     //dbgprintf("CreateCompatibleDC(%d) => 0x81n", hdc);
  2309.     dbgprintf("CreateCompatibleDC(%d) => %dn", hdc, dc);
  2310.     return dc;
  2311. }
  2312. static int WINAPI expGetDeviceCaps(int hdc, int unk)
  2313. {
  2314.     dbgprintf("GetDeviceCaps(0x%x, %d) => 0n", hdc, unk);
  2315. #ifdef QTX
  2316.     #define BITSPIXEL 12
  2317.     #define PLANES    14
  2318.     if (unk == BITSPIXEL)
  2319. return 24;
  2320.     if (unk == PLANES)
  2321. return 1;
  2322. #endif
  2323.     return 1;
  2324. }
  2325. static WIN_BOOL WINAPI expDeleteDC(int hdc)
  2326. {
  2327.     dbgprintf("DeleteDC(0x%x) => 0n", hdc);
  2328.     if (hdc == 0x81)
  2329. return 1;
  2330.     return 0;
  2331. }
  2332. static WIN_BOOL WINAPI expDeleteObject(int hdc)
  2333. {
  2334.     dbgprintf("DeleteObject(0x%x) => 1n", hdc);
  2335.     /* FIXME - implement code here */
  2336.     return 1;
  2337. }
  2338. /* btvvc32.drv wants this one */
  2339. static void* WINAPI expGetWindowDC(int hdc)
  2340. {
  2341.     dbgprintf("GetWindowDC(%d) => 0x0n", hdc);
  2342.     return 0;
  2343. }
  2344. #ifdef QTX
  2345. static int WINAPI expGetWindowRect(HWND win, RECT *r)
  2346. {
  2347.     dbgprintf("GetWindowRect(0x%x, 0x%x) => 1n", win, r);
  2348.     /* (win == 0) => desktop */
  2349.     r->right = PSEUDO_SCREEN_WIDTH;
  2350.     r->left = 0;
  2351.     r->bottom = PSEUDO_SCREEN_HEIGHT;
  2352.     r->top = 0;
  2353.     return 1;
  2354. }
  2355. static int WINAPI expMonitorFromWindow(HWND win, int flags)
  2356. {
  2357.     dbgprintf("MonitorFromWindow(0x%x, 0x%x) => 0n", win, flags);
  2358.     return 0;
  2359. }
  2360. static int WINAPI expMonitorFromRect(RECT *r, int flags)
  2361. {
  2362.     dbgprintf("MonitorFromRect(0x%x, 0x%x) => 0n", r, flags);
  2363.     return 0;
  2364. }
  2365. static int WINAPI expMonitorFromPoint(void *p, int flags)
  2366. {
  2367.     dbgprintf("MonitorFromPoint(0x%x, 0x%x) => 0n", p, flags);
  2368.     return 0;
  2369. }
  2370. static int WINAPI expEnumDisplayMonitors(void *dc, RECT *r, 
  2371.     int WINAPI (*callback_proc)(), void *callback_param)
  2372. {
  2373.     dbgprintf("EnumDisplayMonitors(0x%x, 0x%x, 0x%x, 0x%x) => ?n",
  2374. dc, r, callback_proc, callback_param);
  2375.     return callback_proc(0, dc, r, callback_param);
  2376. }
  2377. #if 0
  2378. typedef struct tagMONITORINFO {
  2379.     DWORD  cbSize; 
  2380.     RECT   rcMonitor; 
  2381.     RECT   rcWork; 
  2382.     DWORD  dwFlags; 
  2383. } MONITORINFO, *LPMONITORINFO; 
  2384. #endif
  2385. #define CCHDEVICENAME 8
  2386. typedef struct tagMONITORINFOEX {  
  2387.     DWORD  cbSize; 
  2388.     RECT   rcMonitor; 
  2389.     RECT   rcWork; 
  2390.     DWORD  dwFlags; 
  2391.     TCHAR  szDevice[CCHDEVICENAME];
  2392. } MONITORINFOEX, *LPMONITORINFOEX; 
  2393. static int WINAPI expGetMonitorInfoA(void *mon, LPMONITORINFO lpmi)
  2394. {
  2395.     dbgprintf("GetMonitorInfoA(0x%x, 0x%x) => 1n", mon, lpmi);
  2396.     
  2397.     lpmi->rcMonitor.right = lpmi->rcWork.right = PSEUDO_SCREEN_WIDTH;
  2398.     lpmi->rcMonitor.left = lpmi->rcWork.left = 0;
  2399.     lpmi->rcMonitor.bottom = lpmi->rcWork.bottom = PSEUDO_SCREEN_HEIGHT;
  2400.     lpmi->rcMonitor.top = lpmi->rcWork.top = 0;
  2401.     lpmi->dwFlags = 1; /* primary monitor */
  2402.     if (lpmi->cbSize == sizeof(MONITORINFOEX))
  2403.     {
  2404. LPMONITORINFOEX lpmiex = (LPMONITORINFOEX)lpmi;
  2405. dbgprintf("MONITORINFOEX!n");
  2406. strncpy(lpmiex->szDevice, "Monitor1", CCHDEVICENAME);
  2407.     }
  2408.     
  2409.     return 1;
  2410. }
  2411. static int WINAPI expEnumDisplayDevicesA(const char *device, int devnum,
  2412. void *dispdev, int flags)
  2413. {
  2414.     dbgprintf("EnumDisplayDevicesA(0x%x = %s, %d, 0x%x, %x) => 1n",
  2415. device, device, devnum, dispdev, flags);
  2416.     return 1;
  2417. }
  2418. static int WINAPI expIsWindowVisible(HWND win)
  2419. {
  2420.     dbgprintf("IsWindowVisible(0x%x) => 1n", win);
  2421.     return 1;
  2422. }
  2423. static HWND WINAPI expGetActiveWindow(void)
  2424. {
  2425.     dbgprintf("GetActiveWindow() => 0n");
  2426.     return (HWND)0;
  2427. }
  2428. static int WINAPI expGetClassNameA(HWND win, LPTSTR classname, int maxcount)
  2429. {
  2430.     strncat(classname, "QuickTime", maxcount);
  2431.     dbgprintf("GetClassNameA(0x%x, 0x%x, %d) => %dn",
  2432. win, classname, maxcount, strlen(classname));
  2433.     return strlen(classname);
  2434. }
  2435. #define LPWNDCLASS void *
  2436. static int WINAPI expGetClassInfoA(HINSTANCE inst, LPCSTR classname, LPWNDCLASS wndclass)
  2437. {
  2438.     dbgprintf("GetClassInfoA(0x%x, 0x%x = %s, 0x%x) => 1n", inst,
  2439. classname, classname, wndclass);
  2440.     return 1;
  2441. }
  2442. static int WINAPI expGetWindowLongA(HWND win, int index)
  2443. {
  2444.     dbgprintf("GetWindowLongA(0x%x, %d) => 0n", win, index);
  2445.     return 1;
  2446. }
  2447. static int WINAPI expGetObjectA(HGDIOBJ hobj, int objsize, LPVOID obj)
  2448. {
  2449.     dbgprintf("GetObjectA(0x%x, %d, 0x%x) => %dn", hobj, objsize, obj, objsize);
  2450.     return objsize;
  2451. }
  2452. static int WINAPI expCreateRectRgn(int x, int y, int width, int height)
  2453. {
  2454.     dbgprintf("CreateRectRgn(%d, %d, %d, %d) => 0n", x, y, width, height);
  2455.     return 0;
  2456. }
  2457. static int WINAPI expEnumWindows(int (*callback_func)(), void *callback_param)
  2458. {
  2459.     int i, i2;
  2460.     dbgprintf("EnumWindows(0x%x, 0x%x) => 1n", callback_func, callback_param);
  2461.     i = callback_func(0, callback_param);
  2462.     i2 = callback_func(1, callback_param);
  2463.     return i && i2;
  2464. }
  2465. static int WINAPI expGetWindowThreadProcessId(HWND win, int *pid_data)
  2466. {
  2467.     int tid = pthread_self();
  2468.     dbgprintf("GetWindowThreadProcessId(0x%x, 0x%x) => %dn",
  2469. win, pid_data, tid);
  2470.     if (pid_data)
  2471. *(int*)pid_data = tid;
  2472.     return tid;
  2473. }
  2474. //HWND      WINAPI CreateWindowExA(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,
  2475. //                                INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
  2476. static HWND WINAPI expCreateWindowExA(int exstyle, const char *classname,
  2477.     const char *winname, int style, int x, int y, int w, int h,
  2478.     HWND parent, HMENU menu, HINSTANCE inst, LPVOID param)
  2479. {
  2480.     printf("CreateWindowEx() calledn");
  2481.     dbgprintf("CreateWindowEx(%d, 0x%x = %s, 0x%x = %s, %d, %d, %d, %d, %d, 0x%x, 0x%x, 0x%x, 0x%x) => 1n",
  2482. exstyle, classname, classname, winname, winname, style, x, y, w, h,
  2483. parent, menu, inst, param);