~ubuntu-dev/mplayer/ubuntu-feisty

« back to all changes in this revision

Viewing changes to loader/win32.c

  • Committer: Reinhard Tartler
  • Date: 2006-07-08 08:45:33 UTC
  • Revision ID: siretart@tauware.de-20060708084533-dbc155bde7122e78
imported mplayer_0.99+1.0pre7try2+cvs20060117

Show diffs side-by-side

added added

removed removed

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