#include <sys/types.h> before <sys/mman.h>.
[wine] / relay32 / builtin32.c
1 /*
2  * Win32 builtin functions
3  *
4  * Copyright 1997 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <ctype.h>
13 #ifdef HAVE_DL_API
14 #include <dlfcn.h>
15 #endif
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_MMAN_H
18 #include <sys/mman.h>
19 #endif
20
21 #include "windef.h"
22 #include "wine/winbase16.h"
23 #include "wingdi.h"
24 #include "winuser.h"
25 #include "builtin32.h"
26 #include "elfdll.h"
27 #include "file.h"
28 #include "global.h"
29 #include "neexe.h"
30 #include "heap.h"
31 #include "main.h"
32 #include "snoop.h"
33 #include "winerror.h"
34 #include "server.h"
35 #include "debugtools.h"
36 #include "options.h" /* for argv0 */
37
38 DEFAULT_DEBUG_CHANNEL(module);
39 DECLARE_DEBUG_CHANNEL(relay);
40
41 typedef struct
42 {
43     BYTE                        *restab;
44     DWORD                       nresources;
45     DWORD                       restabsize;
46     IMAGE_RESOURCE_DATA_ENTRY   *entries;
47 } BUILTIN32_RESOURCE;
48
49 #define MAX_DLLS 60
50
51 static const BUILTIN32_DESCRIPTOR *builtin_dlls[MAX_DLLS];
52 static HMODULE dll_modules[MAX_DLLS];
53 static int nb_dlls;
54
55
56 /***********************************************************************
57  *           BUILTIN32_WarnSecondInstance
58  *
59  * Emit a warning when we are creating a second instance for a DLL
60  * that is known to not support this.
61  */
62 static void BUILTIN32_WarnSecondInstance( const char *name )
63 {
64     static const char * const warning_list[] =
65     { "comctl32.dll", "comdlg32.dll", "crtdll.dll",
66       "imagehlp.dll", "msacm32.dll", "shell32.dll", NULL };
67
68     const char * const *ptr = warning_list;
69
70     while (*ptr)
71     {
72         if (!strcasecmp( *ptr, name ))
73         {
74             ERR( "Attempt to instantiate built-in dll '%s' twice "
75                  "in the same address space. Expect trouble!\n", name );
76             return;
77         }
78         ptr++;
79     }
80 }
81
82 /***********************************************************************
83  *           BUILTIN32_dlopen
84  */
85 void *BUILTIN32_dlopen( const char *name )
86 {
87 #ifdef HAVE_DL_API
88     void *handle;
89     char buffer[128], *p;
90     if ((p = strrchr( name, '/' ))) name = p + 1;
91     if ((p = strrchr( name, '\\' ))) name = p + 1;
92     sprintf( buffer, "lib%s", name );
93     for (p = buffer; *p; p++) *p = tolower(*p);
94     if ((p = strrchr( buffer, '.' )) && (!strcmp( p, ".dll" ) || !strcmp( p, ".exe" ))) *p = 0;
95     strcat( buffer, ".so" );
96
97     if (!(handle = ELFDLL_dlopen( buffer, RTLD_NOW )))
98         ERR( "failed to load %s: %s\n", buffer, dlerror() );
99     return handle;
100 #else
101     return NULL;
102 #endif
103 }
104
105 /***********************************************************************
106  *           BUILTIN32_dlclose
107  */
108 int BUILTIN32_dlclose( void *handle )
109 {
110 #ifdef HAVE_DL_API
111     /* FIXME: should unregister descriptors first */
112     /* return dlclose( handle ); */
113 #endif
114     return 0;
115 }
116
117
118 /***********************************************************************
119  *           fixup_rva_ptrs
120  *
121  * Adjust an array of pointers to make them into RVAs.
122  */
123 static inline void fixup_rva_ptrs( void *array, void *base, int count )
124 {
125     void **ptr = (void **)array;
126     while (count--)
127     {
128         if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base);
129         ptr++;
130     }
131 }
132
133
134 /***********************************************************************
135  *           BUILTIN32_DoLoadImage
136  *
137  * Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage.
138  */
139 static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
140 {
141     IMAGE_DATA_DIRECTORY *dir;
142     IMAGE_DOS_HEADER *dos;
143     IMAGE_NT_HEADERS *nt;
144     IMAGE_SECTION_HEADER *sec;
145     IMAGE_IMPORT_DESCRIPTOR *imp;
146     IMAGE_EXPORT_DIRECTORY *exports = descr->exports;
147     INT i, size, nb_sections;
148     BYTE *addr, *code_start, *data_start;
149     BYTE* xcnlnk;
150     DWORD xcnsize = 0;
151     int page_size = VIRTUAL_GetPageSize();
152
153     /* Allocate the module */
154
155     nb_sections = 2;  /* code + data */
156
157     if (!strcmp(descr->filename, "kernel32.dll")) {
158        nb_sections++;
159        xcnsize = sizeof(DWORD);
160     }
161     size = (sizeof(IMAGE_DOS_HEADER)
162             + sizeof(IMAGE_NT_HEADERS)
163             + nb_sections * sizeof(IMAGE_SECTION_HEADER)
164             + (descr->nb_imports+1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)
165             + xcnsize);
166
167     assert( size <= page_size );
168
169     if (descr->pe_header)
170     {
171         if ((addr = FILE_dommap( -1, descr->pe_header, 0, page_size, 0, 0,
172                                  PROT_READ|PROT_WRITE, MAP_FIXED )) != descr->pe_header)
173         {
174             ERR("failed to map over PE header for %s at %p\n", descr->filename, descr->pe_header );
175             return 0;
176         }
177     }
178     else
179     {
180         if (!(addr = VirtualAlloc( NULL, page_size, MEM_COMMIT, PAGE_READWRITE ))) return 0;
181     }
182
183     dos    = (IMAGE_DOS_HEADER *)addr;
184     nt     = (IMAGE_NT_HEADERS *)(dos + 1);
185     sec    = (IMAGE_SECTION_HEADER *)(nt + 1);
186     imp    = (IMAGE_IMPORT_DESCRIPTOR *)(sec + nb_sections);
187     xcnlnk = (char *)(imp + descr->nb_imports + 1);
188     code_start = addr + page_size;
189
190     /* HACK! */
191     data_start = code_start + page_size;
192
193     /* Build the DOS and NT headers */
194
195     dos->e_magic  = IMAGE_DOS_SIGNATURE;
196     dos->e_lfanew = sizeof(*dos);
197
198     nt->Signature                       = IMAGE_NT_SIGNATURE;
199     nt->FileHeader.Machine              = IMAGE_FILE_MACHINE_I386;
200     nt->FileHeader.NumberOfSections     = nb_sections;
201     nt->FileHeader.SizeOfOptionalHeader = sizeof(nt->OptionalHeader);
202     nt->FileHeader.Characteristics      = descr->characteristics;
203
204     nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
205     nt->OptionalHeader.SizeOfCode                  = data_start - code_start;
206     nt->OptionalHeader.SizeOfInitializedData       = 0;
207     nt->OptionalHeader.SizeOfUninitializedData     = 0;
208     nt->OptionalHeader.ImageBase                   = (DWORD)addr;
209     nt->OptionalHeader.SectionAlignment            = page_size;
210     nt->OptionalHeader.FileAlignment               = page_size;
211     nt->OptionalHeader.MajorOperatingSystemVersion = 1;
212     nt->OptionalHeader.MinorOperatingSystemVersion = 0;
213     nt->OptionalHeader.MajorSubsystemVersion       = 4;
214     nt->OptionalHeader.MinorSubsystemVersion       = 0;
215     nt->OptionalHeader.SizeOfImage                 = page_size;
216     nt->OptionalHeader.SizeOfHeaders               = page_size;
217     nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
218     if (descr->dllentrypoint) 
219         nt->OptionalHeader.AddressOfEntryPoint = (DWORD)descr->dllentrypoint - (DWORD)addr;
220     
221     /* Build the code section */
222
223     strcpy( sec->Name, ".text" );
224     sec->SizeOfRawData = data_start - code_start;
225     sec->Misc.VirtualSize = sec->SizeOfRawData;
226     sec->VirtualAddress   = code_start - addr;
227     sec->PointerToRawData = code_start - addr;
228     sec->Characteristics  = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
229     sec++;
230
231     /* Build the data section */
232
233     strcpy( sec->Name, ".data" );
234     sec->SizeOfRawData = 0;
235     sec->Misc.VirtualSize = sec->SizeOfRawData;
236     sec->VirtualAddress   = data_start - addr;
237     sec->PointerToRawData = data_start - addr;
238     sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
239                              IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ);
240     sec++;
241
242     /* Build the import directory */
243
244     if (descr->nb_imports)
245     {
246         dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
247         dir->VirtualAddress = (BYTE *)imp - addr;
248         dir->Size = sizeof(*imp) * (descr->nb_imports + 1);
249
250         /* Build the imports */
251         for (i = 0; i < descr->nb_imports; i++)
252         {
253             imp[i].u.Characteristics = 0;
254             imp[i].ForwarderChain = -1;
255             imp[i].Name = (BYTE *)descr->imports[i] - addr;
256             /* hack: make first thunk point to some zero value */
257             imp[i].FirstThunk = (PIMAGE_THUNK_DATA)((BYTE *)&imp[i].u.Characteristics - addr);
258         }
259     }
260
261     /* Build Wine's .so link section. Those sections are used by the wine debugger to
262      * link a builtin PE header with the corresponding ELF module (from either a 
263      * shared library, or the main executable - wine emulator or any winelib program 
264      */
265     if (xcnsize) 
266     {
267        strcpy( sec->Name, ".xcnlnk" );
268        sec->Misc.VirtualSize = xcnsize;
269        sec->VirtualAddress   = (BYTE *)xcnlnk - addr;
270        sec->SizeOfRawData    = sec->Misc.VirtualSize;
271        sec->PointerToRawData = (BYTE *)xcnlnk - addr;
272        sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ);
273        sec++;
274
275        *(const char**)xcnlnk = argv0;
276     }
277
278     /* Build the resource directory */
279
280     if (descr->rsrc)
281     {
282         BUILTIN32_RESOURCE *rsrc = descr->rsrc;
283         IMAGE_RESOURCE_DATA_ENTRY *rdep;
284         dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
285         dir->VirtualAddress = (BYTE *)rsrc->restab - addr;
286         dir->Size = rsrc->restabsize;
287         rdep = rsrc->entries;
288         for (i = 0; i < rsrc->nresources; i++) rdep[i].OffsetToData += dir->VirtualAddress;
289     }
290
291     /* Build the export directory */
292
293     if (exports)
294     {
295         dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
296         dir->VirtualAddress = (BYTE *)exports - addr;
297         dir->Size = descr->exports_size;
298
299         fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
300         fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
301         fixup_rva_ptrs( &exports->Name, addr, 1 );
302         fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 );
303         fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 );
304         fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 );
305
306         /* Setup relay debugging entry points */
307         if (WARN_ON(relay) || TRACE_ON(relay)) RELAY_SetupDLL( addr );
308     }
309
310     return (HMODULE)addr;
311 }
312
313 /***********************************************************************
314  *           BUILTIN32_LoadLibraryExA
315  *
316  * Partly copied from the original PE_ version.
317  *
318  */
319 WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
320 {
321     struct load_dll_request *req = get_req_buffer();
322     HMODULE16      hModule16;
323     NE_MODULE     *pModule;
324     WINE_MODREF   *wm;
325     char           dllname[MAX_PATH], *p;
326     void *handle;
327     int i;
328
329     /* Fix the name in case we have a full path and extension */
330     if ((p = strrchr( path, '\\' ))) path = p + 1;
331     lstrcpynA( dllname, path, sizeof(dllname) );
332
333     p = strrchr( dllname, '.' );
334     if (!p) strcat( dllname, ".dll" );
335
336     /* Search built-in descriptor */
337     for (i = 0; i < nb_dlls; i++)
338         if (!strcasecmp( builtin_dlls[i]->filename, dllname )) goto found;
339
340     if ((handle = BUILTIN32_dlopen( dllname )))
341     {
342         for (i = 0; i < nb_dlls; i++)
343             if (!strcasecmp( builtin_dlls[i]->filename, dllname )) goto found;
344         ERR( "loaded .so but dll %s still not found\n", dllname );
345         BUILTIN32_dlclose( handle );
346     }
347
348     SetLastError( ERROR_FILE_NOT_FOUND );
349     return NULL;
350
351  found:
352     /* Load built-in module */
353     if (!dll_modules[i])
354     {
355         if (!(dll_modules[i] = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL;
356     }
357     else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->filename );
358
359     /* Create 16-bit dummy module */
360     if ((hModule16 = MODULE_CreateDummyModule( dllname, dll_modules[i] )) < 32)
361     {
362         SetLastError( (DWORD)hModule16 );
363         return NULL;    /* FIXME: Should unload the builtin module */
364     }
365     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
366     pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32 | NE_FFLAGS_BUILTIN;
367
368     /* Create 32-bit MODREF */
369     if ( !(wm = PE_CreateModule( pModule->module32, dllname, flags, TRUE )) )
370     {
371         ERR( "can't load %s\n", path );
372         FreeLibrary16( hModule16 );     /* FIXME: Should unload the builtin module */
373         SetLastError( ERROR_OUTOFMEMORY );
374         return NULL;
375     }
376
377     if (wm->binfmt.pe.pe_export)
378         SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions);
379
380     req->handle     = -1;
381     req->base       = (void *)pModule->module32;
382     req->dbg_offset = 0;
383     req->dbg_size   = 0;
384     req->name       = &wm->modname;
385     server_call_noerr( REQ_LOAD_DLL );
386     return wm;
387 }
388
389 /***********************************************************************
390  *           BUILTIN32_LoadExeModule
391  */
392 HMODULE BUILTIN32_LoadExeModule( LPCSTR *filename )
393 {
394     int i, exe = -1;
395
396     /* Search built-in EXE descriptor */
397     for ( i = 0; i < nb_dlls; i++ )
398         if ( !(builtin_dlls[i]->characteristics & IMAGE_FILE_DLL) ) 
399         {
400             if ( exe != -1 )
401             {
402                 MESSAGE( "More than one built-in EXE module loaded!\n" );
403                 break;
404             }
405
406             exe = i;
407         }
408
409     if ( exe == -1 ) 
410     {
411         MESSAGE( "No built-in EXE module loaded!  Did you create a .spec file?\n" );
412         return 0;
413     }
414
415     /* Load built-in module */
416     if ( !dll_modules[exe] )
417         if ( !(dll_modules[exe] = BUILTIN32_DoLoadImage( builtin_dlls[exe] )) )
418             return 0;
419
420     *filename = builtin_dlls[exe]->filename;
421     return dll_modules[exe];
422 }
423
424
425 /***********************************************************************
426  *      BUILTIN32_UnloadLibrary
427  *
428  * Unload the built-in library and free the modref.
429  */
430 void BUILTIN32_UnloadLibrary(WINE_MODREF *wm)
431 {
432         /* FIXME: do something here */
433 }
434
435 /***********************************************************************
436  *           BUILTIN32_RegisterDLL
437  *
438  * Register a built-in DLL descriptor.
439  */
440 void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr )
441 {
442     assert( nb_dlls < MAX_DLLS );
443     builtin_dlls[nb_dlls++] = descr;
444 }
445
446 /***********************************************************************
447  *           BUILTIN32_Unimplemented
448  *
449  * This function is called for unimplemented 32-bit entry points (declared
450  * as 'stub' in the spec file).
451  */
452 void BUILTIN32_Unimplemented( const char *dllname, const char *funcname )
453 {
454     __RESTORE_ES;  /* Just in case */
455
456     MESSAGE( "No handler for Win32 routine %s.%s", dllname, funcname );
457 #ifdef __GNUC__
458     MESSAGE( " (called from %p)", __builtin_return_address(1) );
459 #endif
460     MESSAGE( "\n" );
461     ExitProcess(1);
462 }