Moved PE header definitions to winnt.h where they belong.
[wine] / relay32 / builtin32.c
1 /*
2  * Win32 builtin functions
3  *
4  * Copyright 1997 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <ctype.h>
11 #include "windef.h"
12 #include "wingdi.h"
13 #include "winuser.h"
14 #include "builtin32.h"
15 #include "neexe.h"
16 #include "heap.h"
17 #include "main.h"
18 #include "snoop.h"
19 #include "winerror.h"
20 #include "server.h"
21 #include "debugtools.h"
22 #include "options.h" /* for argv0 */
23
24 DEFAULT_DEBUG_CHANNEL(module);
25 DECLARE_DEBUG_CHANNEL(relay);
26
27 typedef struct
28 {
29     BYTE  call;                    /* 0xe8 call callfrom32 (relative) */
30     DWORD callfrom32 WINE_PACKED;  /* RELAY_CallFrom32 relative addr */
31     BYTE  ret;                     /* 0xc2 ret $n  or  0xc3 ret */
32     WORD  args;                    /* nb of args to remove from the stack */
33 } DEBUG_ENTRY_POINT;
34
35 typedef struct
36 {
37         const BYTE                      *restab;
38         const DWORD                     nresources;
39         const DWORD                     restabsize;
40         const IMAGE_RESOURCE_DATA_ENTRY *entries;
41 } BUILTIN32_RESOURCE;
42
43 #define MAX_DLLS 60
44
45 static const BUILTIN32_DESCRIPTOR *builtin_dlls[MAX_DLLS];
46 static HMODULE dll_modules[MAX_DLLS];
47 static int nb_dlls;
48
49 extern void RELAY_CallFrom32();
50 extern void RELAY_CallFrom32Regs();
51
52 /***********************************************************************
53  *           BUILTIN32_WarnSecondInstance
54  *
55  * Emit a warning when we are creating a second instance for a DLL
56  * that is known to not support this.
57  */
58 static void BUILTIN32_WarnSecondInstance( const char *name )
59 {
60     static const char * const warning_list[] =
61     { "comctl32", "comdlg32", "crtdll", "imagehlp", "msacm32", "shell32", NULL };
62
63     const char * const *ptr = warning_list;
64
65     while (*ptr)
66     {
67         if (!strcasecmp( *ptr, name ))
68         {
69             ERR( "Attempt to instantiate built-in dll '%s' twice "
70                  "in the same address space. Expect trouble!\n", name );
71             return;
72         }
73         ptr++;
74     }
75 }
76
77 /***********************************************************************
78  *           BUILTIN32_DoLoadImage
79  *
80  * Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage.
81  */
82 static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr )
83 {
84
85     IMAGE_DATA_DIRECTORY *dir;
86     IMAGE_DOS_HEADER *dos;
87     IMAGE_NT_HEADERS *nt;
88     IMAGE_SECTION_HEADER *sec;
89     IMAGE_EXPORT_DIRECTORY *exp;
90     IMAGE_IMPORT_DESCRIPTOR *imp;
91     const BUILTIN32_RESOURCE *rsrc = descr->rsrc;
92     LPVOID *funcs;
93     LPSTR *names;
94     LPSTR pfwd, rtab;
95     DEBUG_ENTRY_POINT *debug;
96     INT i, size, nb_sections;
97     BYTE *addr;
98     BYTE* xcnlnk;
99     DWORD xcnsize = 0;
100
101     /* Allocate the module */
102
103     nb_sections = 2;  /* exports + code */
104     if (descr->nb_imports) nb_sections++;
105
106     if (!strcmp(descr->name, "KERNEL32")) {
107        nb_sections++;
108        xcnsize = sizeof(DWORD);
109     }
110     size = (sizeof(IMAGE_DOS_HEADER)
111             + sizeof(IMAGE_NT_HEADERS)
112             + nb_sections * sizeof(IMAGE_SECTION_HEADER)
113             + (descr->nb_imports+1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)
114             + sizeof(IMAGE_EXPORT_DIRECTORY)
115             + descr->nb_funcs * sizeof(LPVOID)
116             + descr->nb_names * sizeof(LPSTR)
117             + descr->fwd_size 
118             + xcnsize);
119
120 #ifdef __i386__
121     if (WARN_ON(relay) || TRACE_ON(relay))
122         size += descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
123 #endif
124     if (rsrc) size += rsrc->restabsize;
125     addr  = VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
126     if (!addr) return 0;
127     dos   = (IMAGE_DOS_HEADER *)addr;
128     nt    = (IMAGE_NT_HEADERS *)(dos + 1);
129     sec   = (IMAGE_SECTION_HEADER *)(nt + 1);
130     imp   = (IMAGE_IMPORT_DESCRIPTOR *)(sec + nb_sections);
131     exp   = (IMAGE_EXPORT_DIRECTORY *)(imp + descr->nb_imports + 1);
132     funcs = (LPVOID *)(exp + 1);
133     names = (LPSTR *)(funcs + descr->nb_funcs);
134     pfwd  = (LPSTR)(names + descr->nb_names);
135     xcnlnk= pfwd + descr->fwd_size;
136     rtab  = xcnlnk + xcnsize;
137     debug = (DEBUG_ENTRY_POINT *)(rtab + (rsrc ? rsrc->restabsize : 0));
138
139     /* Build the DOS and NT headers */
140
141     dos->e_magic  = IMAGE_DOS_SIGNATURE;
142     dos->e_lfanew = sizeof(*dos);
143
144     nt->Signature                       = IMAGE_NT_SIGNATURE;
145     nt->FileHeader.Machine              = IMAGE_FILE_MACHINE_I386;
146     nt->FileHeader.NumberOfSections     = nb_sections;
147     nt->FileHeader.SizeOfOptionalHeader = sizeof(nt->OptionalHeader);
148     nt->FileHeader.Characteristics      = descr->characteristics;
149
150     nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
151     nt->OptionalHeader.SizeOfCode                  = 0x1000;
152     nt->OptionalHeader.SizeOfInitializedData       = 0;
153     nt->OptionalHeader.SizeOfUninitializedData     = 0;
154     nt->OptionalHeader.ImageBase                   = (DWORD)addr;
155     nt->OptionalHeader.SectionAlignment            = 0x1000;
156     nt->OptionalHeader.FileAlignment               = 0x1000;
157     nt->OptionalHeader.MajorOperatingSystemVersion = 1;
158     nt->OptionalHeader.MinorOperatingSystemVersion = 0;
159     nt->OptionalHeader.MajorSubsystemVersion       = 4;
160     nt->OptionalHeader.MinorSubsystemVersion       = 0;
161     nt->OptionalHeader.SizeOfImage                 = size;
162     nt->OptionalHeader.SizeOfHeaders               = (BYTE *)exp - addr;
163     nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
164     if (descr->dllentrypoint) 
165         nt->OptionalHeader.AddressOfEntryPoint = (DWORD)descr->dllentrypoint - (DWORD)addr;
166     
167     /* Build the code section */
168
169     strcpy( sec->Name, ".code" );
170     sec->SizeOfRawData = 0;
171 #ifdef __i386__
172     if (WARN_ON(relay) || TRACE_ON(relay))
173         sec->SizeOfRawData += descr->nb_funcs * sizeof(DEBUG_ENTRY_POINT);
174 #endif
175     sec->Misc.VirtualSize = sec->SizeOfRawData;
176     sec->VirtualAddress   = (BYTE *)debug - addr;
177     sec->PointerToRawData = (BYTE *)debug - addr;
178     sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
179                              IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);
180     sec++;
181
182     /* Build the import directory */
183
184     if (descr->nb_imports)
185     {
186         dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
187         dir->VirtualAddress = (BYTE *)imp - addr;
188         dir->Size = sizeof(*imp) * (descr->nb_imports + 1);
189
190         /* Build the imports section */
191         strcpy( sec->Name, ".idata" );
192         sec->Misc.VirtualSize = dir->Size;
193         sec->VirtualAddress   = (BYTE *)imp - addr;
194         sec->SizeOfRawData    = dir->Size;
195         sec->PointerToRawData = (BYTE *)imp - addr;
196         sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
197                                  IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
198                                  IMAGE_SCN_MEM_WRITE);
199         sec++;
200
201         /* Build the imports */
202         for (i = 0; i < descr->nb_imports; i++)
203         {
204             imp[i].u.Characteristics = 0;
205             imp[i].ForwarderChain = -1;
206             imp[i].Name = (BYTE *)descr->imports[i] - addr;
207             /* hack: make first thunk point to some zero value */
208             imp[i].FirstThunk = (PIMAGE_THUNK_DATA)((BYTE *)&imp[i].u.Characteristics - addr);
209         }
210     }
211
212     /* Build the export directory */
213
214     dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
215     dir->VirtualAddress = (BYTE *)exp - addr;
216     dir->Size = sizeof(*exp)
217                 + descr->nb_funcs * sizeof(LPVOID)
218                 + descr->nb_names * sizeof(LPSTR)
219                 + descr->fwd_size;
220
221     /* Build the exports section */
222
223     strcpy( sec->Name, ".edata" );
224     sec->Misc.VirtualSize = dir->Size;
225     sec->VirtualAddress   = (BYTE *)exp - addr;
226     sec->SizeOfRawData    = dir->Size;
227     sec->PointerToRawData = (BYTE *)exp - addr;
228     sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA |
229                              IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ |
230                              IMAGE_SCN_MEM_WRITE);
231
232     /* Build Wine's .so link section. Those sections are used by the wine debugger to
233      * link a builtin PE header with the corresponding ELF module (from either a 
234      * shared library, or the main executable - wine emulator or any winelib program 
235      */
236     if (xcnsize) 
237     {
238        sec++;
239        strcpy( sec->Name, ".xcnlnk" );
240        sec->Misc.VirtualSize = xcnsize;
241        sec->VirtualAddress   = (BYTE *)xcnlnk - addr;
242        sec->SizeOfRawData    = sec->Misc.VirtualSize;
243        sec->PointerToRawData = (BYTE *)xcnlnk - addr;
244        sec->Characteristics  = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ);
245
246        *(const char**)xcnlnk = argv0;
247     }
248
249     /* Build the resource directory */
250
251     if (rsrc)
252     {
253         IMAGE_RESOURCE_DATA_ENTRY *rdep;
254
255         /*
256          * The resource directory has to be copied because it contains
257          * RVAs. These would be invalid if the dll is instantiated twice.
258          */
259         memcpy(rtab, rsrc->restab, rsrc->restabsize);
260
261         dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
262         dir->VirtualAddress = (BYTE *)rtab - addr;
263         dir->Size = rsrc->restabsize;
264         rdep = (IMAGE_RESOURCE_DATA_ENTRY *)((DWORD)rtab + (DWORD)rsrc->entries - (DWORD)rsrc->restab);
265         for(i = 0; i < rsrc->nresources; i++)
266         {
267                 rdep[i].OffsetToData += (DWORD)rsrc->restab - (DWORD)addr;
268         }
269     }
270
271     /* Build the exports section data */
272
273     exp->Name                  = ((BYTE *)descr->name) - addr;  /*??*/
274     exp->Base                  = descr->base;
275     exp->NumberOfFunctions     = descr->nb_funcs;
276     exp->NumberOfNames         = descr->nb_names;
277     exp->AddressOfFunctions    = (LPDWORD *)((BYTE *)funcs - addr);
278     exp->AddressOfNames        = (LPDWORD *)((BYTE *)names - addr);
279     exp->AddressOfNameOrdinals = (LPWORD *)((BYTE *)descr->ordinals - addr);
280
281     /* Build the funcs table */
282
283     for (i = 0; i < descr->nb_funcs; i++, funcs++, debug++)
284     {
285         BYTE args = descr->args[i];
286         int j;
287
288         if (!descr->functions[i]) continue;
289
290         if (args == 0xfd)  /* forward func */
291         {
292             strcpy( pfwd, (LPSTR)descr->functions[i] );
293             *funcs = (LPVOID)((BYTE *)pfwd - addr);
294             pfwd += strlen(pfwd) + 1;
295         }
296         else *funcs = (LPVOID)((BYTE *)descr->functions[i] - addr);
297
298 #ifdef __i386__
299         if (!(WARN_ON(relay) || TRACE_ON(relay))) continue;
300         for (j=0;j<descr->nb_names;j++)
301             if (descr->ordinals[j] == i)
302                 break;
303         if (j<descr->nb_names) {
304             if (descr->names[j]) {
305                 char buffer[200];
306                 sprintf(buffer,"%s.%d: %s",descr->name,i,descr->names[j]);
307                 if (!RELAY_ShowDebugmsgRelay(buffer))
308                     continue;
309             }
310         }
311         switch(args)
312         {
313         case 0xfd:  /* forward */
314         case 0xff:  /* stub or extern */
315             break;
316         default:  /* normal function (stdcall or cdecl or register) */
317             if (TRACE_ON(relay)) {
318                 debug->call       = 0xe8; /* lcall relative */
319                 if (args & 0x40)  /* register func */
320                     debug->callfrom32 = (DWORD)RELAY_CallFrom32Regs -
321                         (DWORD)&debug->ret;
322                 else
323                     debug->callfrom32 = (DWORD)RELAY_CallFrom32 -
324                         (DWORD)&debug->ret;
325             } else {
326                 debug->call       = 0xe9; /* ljmp relative */
327                 debug->callfrom32 = (DWORD)descr->functions[i] -
328                                     (DWORD)&debug->ret;
329             }
330             debug->ret        = (args & 0x80) ? 0xc3 : 0xc2; /*ret/ret $n*/
331             debug->args       = (args & 0x3f) * sizeof(int);
332             *funcs = (LPVOID)((BYTE *)debug - addr);
333             break;
334         }
335 #endif  /* __i386__ */
336     }
337
338     /* Build the names table */
339
340     for (i = 0; i < exp->NumberOfNames; i++, names++)
341         if (descr->names[i])
342             *names = (LPSTR)((BYTE *)descr->names[i] - addr);
343
344     return (HMODULE)addr;
345 }
346
347 /***********************************************************************
348  *           BUILTIN32_LoadLibraryExA
349  *
350  * Partly copied from the original PE_ version.
351  *
352  */
353 WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
354 {
355     struct load_dll_request *req = get_req_buffer();
356     HMODULE16      hModule16;
357     NE_MODULE     *pModule;
358     WINE_MODREF   *wm;
359     char           dllname[MAX_PATH], *p;
360     int i;
361
362     /* Fix the name in case we have a full path and extension */
363     if ((p = strrchr( path, '\\' ))) path = p + 1;
364     lstrcpynA( dllname, path, sizeof(dllname) );
365
366     p = strrchr( dllname, '.' );
367     if (!p) strcat( dllname, ".dll" );
368
369     /* Search built-in descriptor */
370     for (i = 0; i < nb_dlls; i++)
371         if (!lstrcmpiA( builtin_dlls[i]->filename, dllname )) break;
372
373     if (i == nb_dlls)
374     {
375         SetLastError( ERROR_FILE_NOT_FOUND );
376         return NULL;
377     }
378
379     /* Load built-in module */
380     if (!dll_modules[i])
381     {
382         if (!(dll_modules[i] = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL;
383     }
384     else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->name );
385
386     /* Create 16-bit dummy module */
387     if ((hModule16 = MODULE_CreateDummyModule( dllname, dll_modules[i] )) < 32)
388     {
389         SetLastError( (DWORD)hModule16 );
390         return NULL;    /* FIXME: Should unload the builtin module */
391     }
392     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
393     pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32 | NE_FFLAGS_BUILTIN;
394
395     /* Create 32-bit MODREF */
396     if ( !(wm = PE_CreateModule( pModule->module32, dllname, flags, TRUE )) )
397     {
398         ERR( "can't load %s\n", path );
399         FreeLibrary16( hModule16 );     /* FIXME: Should unload the builtin module */
400         SetLastError( ERROR_OUTOFMEMORY );
401         return NULL;
402     }
403
404     if (wm->binfmt.pe.pe_export)
405         SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions);
406
407     req->handle     = -1;
408     req->base       = (void *)pModule->module32;
409     req->dbg_offset = 0;
410     req->dbg_size   = 0;
411     req->name       = &wm->modname;
412     server_call_noerr( REQ_LOAD_DLL );
413     return wm;
414 }
415
416 /***********************************************************************
417  *           BUILTIN32_LoadExeModule
418  */
419 HMODULE BUILTIN32_LoadExeModule( LPCSTR *filename )
420 {
421     HMODULE16 hModule16;
422     NE_MODULE *pModule;
423     int i, exe = -1;
424
425     /* Search built-in EXE descriptor */
426     for ( i = 0; i < nb_dlls; i++ )
427         if ( !(builtin_dlls[i]->characteristics & IMAGE_FILE_DLL) ) 
428         {
429             if ( exe != -1 )
430             {
431                 MESSAGE( "More than one built-in EXE module loaded!\n" );
432                 break;
433             }
434
435             exe = i;
436         }
437
438     if ( exe == -1 ) 
439     {
440         MESSAGE( "No built-in EXE module loaded!  Did you create a .spec file?\n" );
441         return 0;
442     }
443
444     /* Load built-in module */
445     if ( !dll_modules[exe] )
446         if ( !(dll_modules[exe] = BUILTIN32_DoLoadImage( builtin_dlls[exe] )) )
447             return 0;
448
449     *filename = builtin_dlls[exe]->filename;
450     return dll_modules[exe];
451 }
452
453
454 /***********************************************************************
455  *      BUILTIN32_UnloadLibrary
456  *
457  * Unload the built-in library and free the modref.
458  */
459 void BUILTIN32_UnloadLibrary(WINE_MODREF *wm)
460 {
461         /* FIXME: do something here */
462 }
463
464
465 /***********************************************************************
466  *           BUILTIN32_GetEntryPoint
467  *
468  * Return the name of the DLL entry point corresponding
469  * to a relay entry point address. This is used only by relay debugging.
470  *
471  * This function _must_ return the real entry point to call
472  * after the debug info is printed.
473  */
474 ENTRYPOINT32 BUILTIN32_GetEntryPoint( char *buffer, void *relay,
475                                       unsigned int *typemask )
476 {
477     const BUILTIN32_DESCRIPTOR *descr = NULL;
478     int ordinal = 0, i;
479
480     /* First find the module */
481
482     for (i = 0; i < nb_dlls; i++)
483         if (dll_modules[i])
484         {
485             IMAGE_SECTION_HEADER *sec = PE_SECTIONS(dll_modules[i]);
486             DEBUG_ENTRY_POINT *debug = 
487                  (DEBUG_ENTRY_POINT *)((DWORD)dll_modules[i] + sec[0].VirtualAddress);
488             DEBUG_ENTRY_POINT *func = (DEBUG_ENTRY_POINT *)relay;
489             descr = builtin_dlls[i];
490             if (debug <= func && func < debug + descr->nb_funcs)
491             {
492                 ordinal = func - debug;
493                 break;
494             }
495         }
496     
497     if (!descr) return NULL;
498
499     /* Now find the function */
500
501     for (i = 0; i < descr->nb_names; i++)
502         if (descr->ordinals[i] == ordinal) break;
503
504     sprintf( buffer, "%s.%d: %s", descr->name, ordinal + descr->base,
505              (i < descr->nb_names) ? descr->names[i] : "@" );
506     *typemask = descr->argtypes[ordinal];
507     return descr->functions[ordinal];
508 }
509
510 /***********************************************************************
511  *           BUILTIN32_SwitchRelayDebug
512  *
513  * FIXME: enhance to do it module relative.
514  */
515 void BUILTIN32_SwitchRelayDebug(BOOL onoff)
516 {
517     const BUILTIN32_DESCRIPTOR *descr;
518     IMAGE_SECTION_HEADER *sec;
519     DEBUG_ENTRY_POINT *debug;
520     int i, j;
521
522 #ifdef __i386__
523     if (!(TRACE_ON(relay) || WARN_ON(relay)))
524         return;
525     for (j = 0; j < nb_dlls; j++)
526     {
527         if (!dll_modules[j]) continue;
528         sec = PE_SECTIONS(dll_modules[j]);
529         debug = (DEBUG_ENTRY_POINT *)((DWORD)dll_modules[j] + sec[1].VirtualAddress);
530         descr = builtin_dlls[j];
531         for (i = 0; i < descr->nb_funcs; i++,debug++) {
532             if (!descr->functions[i]) continue;
533             if ((descr->args[i]==0xff) || (descr->args[i]==0xfe))
534                 continue;
535             if (onoff) {
536                 debug->call       = 0xe8; /* lcall relative */
537                 debug->callfrom32 = (DWORD)RELAY_CallFrom32 -
538                                     (DWORD)&debug->ret;
539             } else {
540                 debug->call       = 0xe9; /* ljmp relative */
541                 debug->callfrom32 = (DWORD)descr->functions[i] -
542                                     (DWORD)&debug->ret;
543             }
544         }
545     }
546 #endif /* __i386__ */
547     return;
548 }
549
550 /***********************************************************************
551  *           BUILTIN32_RegisterDLL
552  *
553  * Register a built-in DLL descriptor.
554  */
555 void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr )
556 {
557     assert( nb_dlls < MAX_DLLS );
558     builtin_dlls[nb_dlls++] = descr;
559 }
560
561 /***********************************************************************
562  *           BUILTIN32_Unimplemented
563  *
564  * This function is called for unimplemented 32-bit entry points (declared
565  * as 'stub' in the spec file).
566  */
567 void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR *descr, int ordinal )
568 {
569     const char *func_name = "???";
570     int i;
571
572     __RESTORE_ES;  /* Just in case */
573
574     for (i = 0; i < descr->nb_names; i++)
575         if (descr->ordinals[i] + descr->base == ordinal) break;
576     if (i < descr->nb_names) func_name = descr->names[i];
577
578     MESSAGE( "No handler for Win32 routine %s.%d: %s",
579              descr->name, ordinal, func_name );
580 #ifdef __GNUC__
581     MESSAGE( " (called from %p)", __builtin_return_address(1) );
582 #endif
583     MESSAGE( "\n" );
584     ExitProcess(1);
585 }