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