]> git.sesse.net Git - vlc/blob - libs/loader/ext.c
3680dc344d56d2c55afbfd0d69ba93a87e723d78
[vlc] / libs / loader / ext.c
1 /********************************************************
2  *
3  *
4  *      Stub functions for Wine module
5  *
6  *
7  ********************************************************/
8
9 /*
10  * Modified for use with MPlayer, detailed CVS changelog at
11  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
12  * $Id$
13  */
14
15 #include "config.h"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #ifdef HAVE_MALLOC_H
19 #include <malloc.h>
20 #endif
21 #include <unistd.h>
22 #include <sys/mman.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28
29 #include "wine/windef.h"
30 #include "wine/winbase.h"
31 #include "wine/debugtools.h"
32 #include "wine/heap.h"
33 #include "ext.h"
34
35 #if 0
36 //REMOVE SIMPLIFY
37 static void* mymalloc(unsigned int size)
38 {
39     printf("malloc %d\n", size);
40     return malloc(size);
41 }
42
43 #undef malloc
44 #define malloc mymalloc
45 #endif
46
47 int dbg_header_err( const char *dbg_channel, const char *func )
48 {
49     return 0;
50 }
51 int dbg_header_warn( const char *dbg_channel, const char *func )
52 {
53     return 0;
54 }
55 int dbg_header_fixme( const char *dbg_channel, const char *func )
56 {
57     return 0;
58 }
59 int dbg_header_trace( const char *dbg_channel, const char *func )
60 {
61     return 0;
62 }
63 int dbg_vprintf( const char *format, va_list args )
64 {
65     return 0;
66 }
67 int __vprintf( const char *format, ... )
68 {
69 #ifdef DETAILED_OUT
70     va_list va;
71     va_start(va, format);
72     vprintf(format, va);
73     va_end(va);
74 #endif
75     return 0;
76 }
77
78 HANDLE WINAPI GetProcessHeap(void)
79 {
80     return 1;
81 }
82
83 LPVOID WINAPI HeapAlloc(HANDLE heap, DWORD flags, DWORD size)
84 {
85     static int i = 5;
86     void* m = (flags & 0x8) ? calloc(size, 1) : malloc(size);
87     //printf("HeapAlloc %p  %d  (%d)\n", m, size, flags);
88     //if (--i == 0)
89     //    abort();
90     return m;
91 }
92
93 WIN_BOOL WINAPI HeapFree(HANDLE heap, DWORD flags, LPVOID mem)
94 {
95     free( mem );
96     //printf("HeapFree  %p\n", mem);
97     //if (!mem)
98     //    abort();
99     return 1;
100 }
101
102 static int last_error;
103
104 DWORD WINAPI GetLastError(void)
105 {
106     return last_error;
107 }
108
109 VOID WINAPI SetLastError(DWORD error)
110 {
111     last_error=error;
112 }
113
114 WIN_BOOL WINAPI ReadFile(HANDLE handle, LPVOID mem, DWORD size, LPDWORD result, LPOVERLAPPED flags)
115 {
116     *result=read(handle, mem, size);
117     return *result;
118 }
119 INT WINAPI lstrcmpiA(LPCSTR c1, LPCSTR c2)
120 {
121     return strcasecmp(c1,c2);
122 }
123 LPSTR WINAPI lstrcpynA(LPSTR dest, LPCSTR src, INT num)
124 {
125     return strncpy(dest,src,num);
126 }
127 INT WINAPI lstrlenA(LPCSTR s)
128 {
129     return strlen(s);
130 }
131 INT WINAPI lstrlenW(LPCWSTR s)
132 {
133     int l;
134     if(!s)
135         return 0;
136     l=0;
137     while(s[l])
138         l++;
139      return l;
140 }
141 LPSTR WINAPI lstrcpynWtoA(LPSTR dest, LPCWSTR src, INT count)
142 {
143     LPSTR result = dest;
144     int moved=0;
145     if((dest==0) || (src==0))
146         return 0;
147     while(moved<count)
148     {
149         *dest=*src;
150         moved++;
151         if(*src==0)
152             break;
153         src++;
154         dest++;
155     }
156     return result;
157 }
158 /* i stands here for ignore case! */
159 int wcsnicmp(const unsigned short* s1, const unsigned short* s2, int n)
160 {
161     /*
162     if(s1==0)
163         return;
164     if(s2==0)
165         return;
166     */
167     while(n>0)
168     {
169         if (((*s1 | *s2) & 0xff00) || toupper((char)*s1) != toupper((char)*s2))
170         {
171
172             if(*s1<*s2)
173                 return -1;
174             else
175                 if(*s1>*s2)
176                     return 1;
177                 else
178                     if(*s1==0)
179                         return 0;
180         }
181         s1++;
182         s2++;
183         n--;
184     }
185     return 0;
186 }
187
188 WIN_BOOL WINAPI IsBadReadPtr(LPCVOID data, UINT size)
189 {
190     if(size==0)
191         return 0;
192     if(data==NULL)
193         return 1;
194     return 0;
195 }
196 LPSTR HEAP_strdupA(HANDLE heap, DWORD flags, LPCSTR string)
197 {
198 //    return strdup(string);
199     char* answ = (char*) malloc(strlen(string) + 1);
200     strcpy(answ, string);
201     return answ;
202 }
203 LPWSTR HEAP_strdupAtoW(HANDLE heap, DWORD flags, LPCSTR string)
204 {
205     int size, i;
206     WCHAR* answer;
207     if(string==0)
208         return 0;
209     size=strlen(string);
210     answer = (WCHAR*) malloc(sizeof(WCHAR) * (size + 1));
211     for(i=0; i<=size; i++)
212         answer[i]=(short)string[i];
213     return answer;
214 }
215 LPSTR HEAP_strdupWtoA(HANDLE heap, DWORD flags, LPCWSTR string)
216 {
217     int size, i;
218     char* answer;
219     if(string==0)
220         return 0;
221     size=0;
222     while(string[size])
223        size++;
224     answer = (char*) malloc(size + 2);
225     for(i=0; i<=size; i++)
226         answer[i]=(char)string[i];
227     return answer;
228 }
229
230 /***********************************************************************
231  *           FILE_dommap
232  */
233
234 //#define MAP_PRIVATE
235 //#define MAP_SHARED
236 #undef MAP_ANON
237 LPVOID FILE_dommap( int unix_handle, LPVOID start,
238                     DWORD size_high, DWORD size_low,
239                     DWORD offset_high, DWORD offset_low,
240                     int prot, int flags )
241 {
242     int fd = -1;
243     int pos;
244     LPVOID ret;
245
246     if (size_high || offset_high)
247         printf("offsets larger than 4Gb not supported\n");
248
249     if (unix_handle == -1)
250     {
251 #ifdef MAP_ANON
252 //      printf("Anonymous\n");
253         flags |= MAP_ANON;
254 #else
255         static int fdzero = -1;
256
257         if (fdzero == -1)
258         {
259             if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
260             {
261                 perror( "Cannot open /dev/zero for READ. Check permissions! error: " );
262                 exit(1);
263             }
264         }
265         fd = fdzero;
266 #endif  /* MAP_ANON */
267         /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
268 #ifdef MAP_SHARED
269         flags &= ~MAP_SHARED;
270 #endif
271 #ifdef MAP_PRIVATE
272         flags |= MAP_PRIVATE;
273 #endif
274     }
275     else fd = unix_handle;
276 //    printf("fd %x, start %x, size %x, pos %x, prot %x\n",fd,start,size_low, offset_low, prot);
277 //    if ((ret = mmap( start, size_low, prot,
278 //                     flags, fd, offset_low )) != (LPVOID)-1)
279     if ((ret = mmap( start, size_low, prot,
280                      MAP_PRIVATE | MAP_FIXED, fd, offset_low )) != (LPVOID)-1)
281     {
282 //          printf("address %08x\n", *(int*)ret);
283 //      printf("%x\n", ret);
284             return ret;
285     }
286
287 //    printf("mmap %d\n", errno);
288
289     /* mmap() failed; if this is because the file offset is not    */
290     /* page-aligned (EINVAL), or because the underlying filesystem */
291     /* does not support mmap() (ENOEXEC), we do it by hand.        */
292
293     if (unix_handle == -1) return ret;
294     if ((errno != ENOEXEC) && (errno != EINVAL)) return ret;
295     if (prot & PROT_WRITE)
296     {
297         /* We cannot fake shared write mappings */
298 #ifdef MAP_SHARED
299         if (flags & MAP_SHARED) return ret;
300 #endif
301 #ifdef MAP_PRIVATE
302         if (!(flags & MAP_PRIVATE)) return ret;
303 #endif
304     }
305 /*    printf( "FILE_mmap: mmap failed (%d), faking it\n", errno );*/
306     /* Reserve the memory with an anonymous mmap */
307     ret = FILE_dommap( -1, start, size_high, size_low, 0, 0,
308                        PROT_READ | PROT_WRITE, flags );
309     if (ret == (LPVOID)-1)
310 //    {
311 //      perror(
312          return ret;
313     /* Now read in the file */
314     if ((pos = lseek( fd, offset_low, SEEK_SET )) == -1)
315     {
316         FILE_munmap( ret, size_high, size_low );
317 //      printf("lseek\n");
318         return (LPVOID)-1;
319     }
320     read( fd, ret, size_low );
321     lseek( fd, pos, SEEK_SET );  /* Restore the file pointer */
322     mprotect( ret, size_low, prot );  /* Set the right protection */
323 //    printf("address %08x\n", *(int*)ret);
324     return ret;
325 }
326
327
328 /***********************************************************************
329  *           FILE_munmap
330  */
331 int FILE_munmap( LPVOID start, DWORD size_high, DWORD size_low )
332 {
333     if (size_high)
334       printf("offsets larger than 4Gb not supported\n");
335     return munmap( start, size_low );
336 }
337 static int mapping_size=0;
338
339 struct file_mapping_s;
340 typedef struct file_mapping_s
341 {
342     int mapping_size;
343     char* name;
344     LPVOID handle;
345     struct file_mapping_s* next;
346     struct file_mapping_s* prev;
347 }file_mapping;
348 static file_mapping* fm=0;
349
350
351
352 #define PAGE_NOACCESS           0x01
353 #define PAGE_READONLY           0x02
354 #define PAGE_READWRITE          0x04
355 #define PAGE_WRITECOPY          0x08
356 #define PAGE_EXECUTE            0x10
357 #define PAGE_EXECUTE_READ       0x20
358 #define PAGE_EXECUTE_READWRITE  0x40
359 #define PAGE_EXECUTE_WRITECOPY  0x80
360 #define PAGE_GUARD              0x100
361 #define PAGE_NOCACHE            0x200
362
363 HANDLE WINAPI CreateFileMappingA(HANDLE handle, LPSECURITY_ATTRIBUTES lpAttr,
364                                  DWORD flProtect,
365                                  DWORD dwMaxHigh, DWORD dwMaxLow,
366                                  LPCSTR name)
367 {
368     int hFile = (int)handle;
369     unsigned int len;
370     LPVOID answer;
371     int anon=0;
372     int mmap_access=0;
373     if(hFile<0)
374     {
375         anon=1;
376         hFile=open("/dev/zero", O_RDWR);
377         if(hFile<0){
378             perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " );
379             return 0;
380         }
381     }
382     if(!anon)
383     {
384         len=lseek(hFile, 0, SEEK_END);
385         lseek(hFile, 0, SEEK_SET);
386     }
387     else len=dwMaxLow;
388
389     if(flProtect & PAGE_READONLY)
390         mmap_access |=PROT_READ;
391     else
392         mmap_access |=PROT_READ|PROT_WRITE;
393
394     answer=mmap(NULL, len, mmap_access, MAP_PRIVATE, hFile, 0);
395     if(anon)
396         close(hFile);
397     if(answer!=(LPVOID)-1)
398     {
399         if(fm==0)
400         {
401             fm = (file_mapping*) malloc(sizeof(file_mapping));
402             fm->prev=NULL;
403         }
404         else
405         {
406             fm->next = (file_mapping*) malloc(sizeof(file_mapping));
407             fm->next->prev=fm;
408             fm=fm->next;
409         }
410         fm->next=NULL;
411         fm->handle=answer;
412         if(name)
413         {
414             fm->name = (char*) malloc(strlen(name)+1);
415             strcpy(fm->name, name);
416         }
417         else
418             fm->name=NULL;
419         fm->mapping_size=len;
420
421         if(anon)
422             close(hFile);
423         return (HANDLE)answer;
424     }
425     return (HANDLE)0;
426 }
427 WIN_BOOL WINAPI UnmapViewOfFile(LPVOID handle)
428 {
429     file_mapping* p;
430     int result;
431     if(fm==0)
432         return 0;
433     for(p=fm; p; p=p->next)
434     {
435         if(p->handle==handle)
436         {
437             result=munmap((void*)handle, p->mapping_size);
438             if(p->next)p->next->prev=p->prev;
439             if(p->prev)p->prev->next=p->next;
440             free(p->name);
441             if(p==fm)
442                 fm=p->prev;
443             free(p);
444             return result;
445         }
446     }
447     return 0;
448 }
449 //static int va_size=0;
450 struct virt_alloc_s;
451 typedef struct virt_alloc_s
452 {
453     int mapping_size;
454     char* address;
455     struct virt_alloc_s* next;
456     struct virt_alloc_s* prev;
457     int state;
458 }virt_alloc;
459 static virt_alloc* vm=0;
460 #define MEM_COMMIT              0x00001000
461 #define MEM_RESERVE             0x00002000
462
463 LPVOID WINAPI VirtualAlloc(LPVOID address, DWORD size, DWORD type,  DWORD protection)
464 {
465     void* answer;
466     int fd;
467     long pgsz;
468
469     //printf("VirtualAlloc(0x%08X, %u, 0x%08X, 0x%08X)\n", (unsigned)address, size, type, protection);
470
471     if ((type&(MEM_RESERVE|MEM_COMMIT)) == 0) return NULL;
472
473     fd=open("/dev/zero", O_RDWR);
474     if(fd<0){
475         perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " );
476         return NULL;
477     }
478
479     if (type&MEM_RESERVE && (unsigned)address&0xffff) {
480         size += (unsigned)address&0xffff;
481         address = (unsigned)address&~0xffff;
482     }
483     pgsz = sysconf(_SC_PAGESIZE);
484     if (type&MEM_COMMIT && (unsigned)address%pgsz) {
485         size += (unsigned)address%pgsz;
486         address -= (unsigned)address%pgsz;
487     }
488
489     if (type&MEM_RESERVE && size<0x10000) size = 0x10000;
490     if (size%pgsz) size += pgsz - size%pgsz;
491
492     if(address!=0)
493     {
494     //check whether we can allow to allocate this
495         virt_alloc* str=vm;
496         while(str)
497         {
498             if((unsigned)address>=(unsigned)str->address+str->mapping_size)
499             {
500                 str=str->prev;
501                 continue;
502             }
503             if((unsigned)address+size<=(unsigned)str->address)
504             {
505                 str=str->prev;
506                 continue;
507             }
508             if(str->state==0)
509             {
510 #warning FIXME
511                 if(   ((unsigned)address >= (unsigned)str->address)
512                    && ((unsigned)address+size<=(unsigned)str->address+str->mapping_size)
513                    && (type & MEM_COMMIT))
514                 {
515                     close(fd);
516                     return address; //returning previously reserved memory
517                 }
518                 //printf(" VirtualAlloc(...) does not commit or not entirely within reserved, and\n");
519             }
520             /*printf(" VirtualAlloc(...) (0x%08X, %u) overlaps with (0x%08X, %u, state=%d)\n",
521                    (unsigned)address, size, (unsigned)str->address, str->mapping_size, str->state);*/
522             close(fd);
523             return NULL;
524         }
525     }
526
527     answer=mmap(address, size, PROT_READ | PROT_WRITE | PROT_EXEC,
528                 MAP_PRIVATE, fd, 0);
529 //    answer=FILE_dommap(-1, address, 0, size, 0, 0,
530 //      PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
531     close(fd);
532     if (answer != (void *)-1 && address && answer != address) {
533         /* It is dangerous to try mmap() with MAP_FIXED since it does not
534            always detect conflicts or non-allocation and chaos ensues after
535            a successful call but an overlapping or non-allocated region.  */
536         munmap(answer, size);
537         answer = (void *) -1;
538         errno = EINVAL;
539         //printf(" VirtualAlloc(...) cannot satisfy requested address but address=NULL would work.\n");
540     }
541     if(answer==(void*)-1)
542     {
543         /*printf(" VirtualAlloc(...) mmap(0x%08X, %u, ...) failed with errno=%d (\"%s\")\n",
544                (unsigned)address, size, errno, strerror(errno));*/
545         return NULL;
546     }
547     else
548     {
549         virt_alloc *new_vm = (virt_alloc*) malloc(sizeof(virt_alloc));
550         new_vm->mapping_size=size;
551         new_vm->address=(char*)answer;
552         new_vm->prev=vm;
553         if(type == MEM_RESERVE)
554             new_vm->state=0;
555         else
556             new_vm->state=1;
557         if(vm)
558             vm->next=new_vm;
559         vm=new_vm;
560         vm->next=0;
561         //if(va_size!=0)
562         //    printf("Multiple VirtualAlloc!\n");
563         //printf(" VirtualAlloc(...) provides (0x%08X, %u)\n", (unsigned)answer, size);
564         return answer;
565     }
566 }
567
568 WIN_BOOL WINAPI VirtualFree(LPVOID  address, SIZE_T dwSize, DWORD dwFreeType)//not sure
569 {
570     virt_alloc* str=vm;
571     int answer;
572
573     //printf("VirtualFree(0x%08X, %d, 0x%08X)\n", (unsigned)address, dwSize, dwFreeType);
574     while(str)
575     {
576         if(address!=str->address)
577         {
578             str=str->prev;
579             continue;
580         }
581         //printf(" VirtualFree(...) munmap(0x%08X, %d)\n", (unsigned)str->address, str->mapping_size);
582         answer=munmap(str->address, str->mapping_size);
583         if(str->next)str->next->prev=str->prev;
584         if(str->prev)str->prev->next=str->next;
585         if(vm==str)vm=str->prev;
586         free(str);
587         return 0;
588     }
589     return -1;
590 }
591
592 INT WINAPI WideCharToMultiByte(UINT codepage, DWORD flags, LPCWSTR src,
593      INT srclen,LPSTR dest, INT destlen, LPCSTR defch, WIN_BOOL* used_defch)
594 {
595     int i;
596     if(src==0)
597         return 0;
598     if ((srclen==-1)&&(dest==0)) return 0;
599     if(srclen==-1){srclen=0; while(src[srclen++]);}
600 //    for(i=0; i<srclen; i++)
601 //      printf("%c", src[i]);
602 //    printf("\n");
603     if(dest==0)
604     {
605     for(i=0; i<srclen; i++)
606     {
607         src++;
608         if(*src==0)
609             return i+1;
610     }
611         return srclen+1;
612     }
613     if(used_defch)
614         *used_defch=0;
615     for(i=0; i<min(srclen, destlen); i++)
616     {
617         *dest=(char)*src;
618         dest++;
619         src++;
620         if(*src==0)
621             return i+1;
622     }
623     return min(srclen, destlen);
624 }
625 INT WINAPI MultiByteToWideChar(UINT codepage,DWORD flags, LPCSTR src, INT srclen,
626     LPWSTR dest, INT destlen)
627 {
628     return 0;
629 }
630 HANDLE WINAPI OpenFileMappingA(DWORD access, WIN_BOOL prot, LPCSTR name)
631 {
632     file_mapping* p;
633     if(fm==0)
634         return (HANDLE)0;
635     if(name==0)
636         return (HANDLE)0;
637     for(p=fm; p; p=p->prev)
638     {
639         if(p->name==0)
640             continue;
641         if(strcmp(p->name, name)==0)
642             return (HANDLE)p->handle;
643     }
644     return 0;
645 }