]> git.sesse.net Git - vlc/blob - libs/loader/ext.c
Create a modules-like directory for libraries
[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     if (mem) 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             if(p->name)
441                 free(p->name);
442             if(p==fm)
443                 fm=p->prev;
444             free(p);
445             return result;
446         }
447     }
448     return 0;
449 }
450 //static int va_size=0;
451 struct virt_alloc_s;
452 typedef struct virt_alloc_s
453 {
454     int mapping_size;
455     char* address;
456     struct virt_alloc_s* next;
457     struct virt_alloc_s* prev;
458     int state;
459 }virt_alloc;
460 static virt_alloc* vm=0;
461 #define MEM_COMMIT              0x00001000
462 #define MEM_RESERVE             0x00002000
463
464 LPVOID WINAPI VirtualAlloc(LPVOID address, DWORD size, DWORD type,  DWORD protection)
465 {
466     void* answer;
467     int fd;
468     long pgsz;
469
470     //printf("VirtualAlloc(0x%08X, %u, 0x%08X, 0x%08X)\n", (unsigned)address, size, type, protection);
471
472     if ((type&(MEM_RESERVE|MEM_COMMIT)) == 0) return NULL;
473
474     fd=open("/dev/zero", O_RDWR);
475     if(fd<0){
476         perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " );
477         return NULL;
478     }
479
480     if (type&MEM_RESERVE && (unsigned)address&0xffff) {
481         size += (unsigned)address&0xffff;
482         address = (unsigned)address&~0xffff;
483     }
484     pgsz = sysconf(_SC_PAGESIZE);
485     if (type&MEM_COMMIT && (unsigned)address%pgsz) {
486         size += (unsigned)address%pgsz;
487         address -= (unsigned)address%pgsz;
488     }
489
490     if (type&MEM_RESERVE && size<0x10000) size = 0x10000;
491     if (size%pgsz) size += pgsz - size%pgsz;
492
493     if(address!=0)
494     {
495     //check whether we can allow to allocate this
496         virt_alloc* str=vm;
497         while(str)
498         {
499             if((unsigned)address>=(unsigned)str->address+str->mapping_size)
500             {
501                 str=str->prev;
502                 continue;
503             }
504             if((unsigned)address+size<=(unsigned)str->address)
505             {
506                 str=str->prev;
507                 continue;
508             }
509             if(str->state==0)
510             {
511 #warning FIXME
512                 if(   ((unsigned)address >= (unsigned)str->address)
513                    && ((unsigned)address+size<=(unsigned)str->address+str->mapping_size)
514                    && (type & MEM_COMMIT))
515                 {
516                     close(fd);
517                     return address; //returning previously reserved memory
518                 }
519                 //printf(" VirtualAlloc(...) does not commit or not entirely within reserved, and\n");
520             }
521             /*printf(" VirtualAlloc(...) (0x%08X, %u) overlaps with (0x%08X, %u, state=%d)\n",
522                    (unsigned)address, size, (unsigned)str->address, str->mapping_size, str->state);*/
523             close(fd);
524             return NULL;
525         }
526     }
527
528     answer=mmap(address, size, PROT_READ | PROT_WRITE | PROT_EXEC,
529                 MAP_PRIVATE, fd, 0);
530 //    answer=FILE_dommap(-1, address, 0, size, 0, 0,
531 //      PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
532     close(fd);
533     if (answer != (void *)-1 && address && answer != address) {
534         /* It is dangerous to try mmap() with MAP_FIXED since it does not
535            always detect conflicts or non-allocation and chaos ensues after
536            a successful call but an overlapping or non-allocated region.  */
537         munmap(answer, size);
538         answer = (void *) -1;
539         errno = EINVAL;
540         //printf(" VirtualAlloc(...) cannot satisfy requested address but address=NULL would work.\n");
541     }
542     if(answer==(void*)-1)
543     {
544         /*printf(" VirtualAlloc(...) mmap(0x%08X, %u, ...) failed with errno=%d (\"%s\")\n",
545                (unsigned)address, size, errno, strerror(errno));*/
546         return NULL;
547     }
548     else
549     {
550         virt_alloc *new_vm = (virt_alloc*) malloc(sizeof(virt_alloc));
551         new_vm->mapping_size=size;
552         new_vm->address=(char*)answer;
553         new_vm->prev=vm;
554         if(type == MEM_RESERVE)
555             new_vm->state=0;
556         else
557             new_vm->state=1;
558         if(vm)
559             vm->next=new_vm;
560         vm=new_vm;
561         vm->next=0;
562         //if(va_size!=0)
563         //    printf("Multiple VirtualAlloc!\n");
564         //printf(" VirtualAlloc(...) provides (0x%08X, %u)\n", (unsigned)answer, size);
565         return answer;
566     }
567 }
568
569 WIN_BOOL WINAPI VirtualFree(LPVOID  address, SIZE_T dwSize, DWORD dwFreeType)//not sure
570 {
571     virt_alloc* str=vm;
572     int answer;
573
574     //printf("VirtualFree(0x%08X, %d, 0x%08X)\n", (unsigned)address, dwSize, dwFreeType);
575     while(str)
576     {
577         if(address!=str->address)
578         {
579             str=str->prev;
580             continue;
581         }
582         //printf(" VirtualFree(...) munmap(0x%08X, %d)\n", (unsigned)str->address, str->mapping_size);
583         answer=munmap(str->address, str->mapping_size);
584         if(str->next)str->next->prev=str->prev;
585         if(str->prev)str->prev->next=str->next;
586         if(vm==str)vm=str->prev;
587         free(str);
588         return 0;
589     }
590     return -1;
591 }
592
593 INT WINAPI WideCharToMultiByte(UINT codepage, DWORD flags, LPCWSTR src,
594      INT srclen,LPSTR dest, INT destlen, LPCSTR defch, WIN_BOOL* used_defch)
595 {
596     int i;
597     if(src==0)
598         return 0;
599     if ((srclen==-1)&&(dest==0)) return 0;
600     if(srclen==-1){srclen=0; while(src[srclen++]);}
601 //    for(i=0; i<srclen; i++)
602 //      printf("%c", src[i]);
603 //    printf("\n");
604     if(dest==0)
605     {
606     for(i=0; i<srclen; i++)
607     {
608         src++;
609         if(*src==0)
610             return i+1;
611     }
612         return srclen+1;
613     }
614     if(used_defch)
615         *used_defch=0;
616     for(i=0; i<min(srclen, destlen); i++)
617     {
618         *dest=(char)*src;
619         dest++;
620         src++;
621         if(*src==0)
622             return i+1;
623     }
624     return min(srclen, destlen);
625 }
626 INT WINAPI MultiByteToWideChar(UINT codepage,DWORD flags, LPCSTR src, INT srclen,
627     LPWSTR dest, INT destlen)
628 {
629     return 0;
630 }
631 HANDLE WINAPI OpenFileMappingA(DWORD access, WIN_BOOL prot, LPCSTR name)
632 {
633     file_mapping* p;
634     if(fm==0)
635         return (HANDLE)0;
636     if(name==0)
637         return (HANDLE)0;
638     for(p=fm; p; p=p->prev)
639     {
640         if(p->name==0)
641             continue;
642         if(strcmp(p->name, name)==0)
643             return (HANDLE)p->handle;
644     }
645     return 0;
646 }