Replaced PTR_SEG_TO_LIN macro by exported MapSL function.
[wine] / if1632 / builtin.c
1 /*
2  * Built-in modules
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include "winbase.h"
12 #include "wine/winbase16.h"
13 #include "builtin16.h"
14 #include "global.h"
15 #include "heap.h"
16 #include "file.h"
17 #include "module.h"
18 #include "miscemu.h"
19 #include "stackframe.h"
20 #include "task.h"
21 #include "debugtools.h"
22 #include "toolhelp.h"
23
24 DEFAULT_DEBUG_CHANNEL(module);
25
26 /* Table of all built-in DLLs */
27
28 #define MAX_DLLS 50
29
30 static const BUILTIN16_DESCRIPTOR *builtin_dlls[MAX_DLLS];
31 static int nb_dlls;
32
33
34 /* patch all the flat cs references of the code segment if necessary */
35 inline static void patch_code_segment( void *code_segment )
36 {
37 #ifdef __i386__
38     CALLFROM16 *call = code_segment;
39     if (call->flatcs == __get_cs()) return;  /* nothing to patch */
40     while (call->pushl == 0x68)
41     {
42         call->flatcs = __get_cs();
43         call++;
44     }
45 #endif
46 }
47
48
49 /***********************************************************************
50  *           BUILTIN_DoLoadModule16
51  *
52  * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule.
53  */
54 static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
55 {
56     NE_MODULE *pModule;
57     int minsize;
58     SEGTABLEENTRY *pSegTable;
59     HMODULE16 hModule;
60
61     hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
62                                   descr->module_size, 0, WINE_LDT_FLAGS_DATA );
63     if (!hModule) return 0;
64     FarSetOwner16( hModule, hModule );
65
66     pModule = (NE_MODULE *)GlobalLock16( hModule );
67     pModule->self = hModule;
68     /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
69     pModule->hRsrcMap = (void *)descr->rsrc;
70
71     TRACE( "Built-in %s: hmodule=%04x\n", descr->name, hModule );
72
73     /* Allocate the code segment */
74
75     pSegTable = NE_SEG_TABLE( pModule );
76     pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start,
77                                           pSegTable->minsize, hModule,
78                                           WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT );
79     if (!pSegTable->hSeg) return 0;
80     patch_code_segment( descr->code_start );
81     pSegTable++;
82
83     /* Allocate the data segment */
84
85     minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
86     minsize += pModule->heap_size;
87     if (minsize > 0x10000) minsize = 0x10000;
88     pSegTable->hSeg = GLOBAL_Alloc( GMEM_FIXED, minsize, hModule, WINE_LDT_FLAGS_DATA );
89     if (!pSegTable->hSeg) return 0;
90     if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
91                                     descr->data_start, pSegTable->minsize);
92     if (pModule->heap_size)
93         LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
94                 pSegTable->minsize, minsize );
95
96     if (descr->rsrc) NE_InitResourceHandler(hModule);
97
98     NE_RegisterModule( pModule );
99     return hModule;
100 }
101
102
103 /***********************************************************************
104  *           BUILTIN_LoadModule
105  *
106  * Load a built-in module.
107  */
108 HMODULE16 BUILTIN_LoadModule( LPCSTR name )
109 {
110     char dllname[20], *p;
111     void *handle;
112     int i;
113
114     /* Fix the name in case we have a full path and extension */
115
116     if ((p = strrchr( name, '\\' ))) name = p + 1;
117     if ((p = strrchr( name, '/' ))) name = p + 1;
118
119     if (strlen(name) >= sizeof(dllname)-4) return (HMODULE16)2;
120
121     strcpy( dllname, name );
122     p = strrchr( dllname, '.' );
123     if (!p) strcat( dllname, ".dll" );
124     for (p = dllname; *p; p++) *p = FILE_tolower(*p);
125
126     for (i = 0; i < nb_dlls; i++)
127     {
128         const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
129         NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
130         OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
131         if (!FILE_strcasecmp( pOfs->szPathName, dllname ))
132             return BUILTIN_DoLoadModule16( descr );
133     }
134
135     if ((handle = BUILTIN32_dlopen( dllname )))
136     {
137         for (i = 0; i < nb_dlls; i++)
138         {
139             const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
140             NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
141             OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
142             if (!FILE_strcasecmp( pOfs->szPathName, dllname ))
143                 return BUILTIN_DoLoadModule16( descr );
144         }
145         ERR( "loaded .so but dll %s still not found\n", dllname );
146         BUILTIN32_dlclose( handle );
147     }
148
149     return (HMODULE16)2;
150 }
151
152
153 /***********************************************************************
154  *           BUILTIN_GetEntryPoint16
155  *
156  * Return the ordinal, name, and type info corresponding to a CS:IP address.
157  * This is used only by relay debugging.
158  */
159 LPCSTR BUILTIN_GetEntryPoint16( STACK16FRAME *frame, LPSTR name, WORD *pOrd )
160 {
161     WORD i, max_offset;
162     register BYTE *p;
163     NE_MODULE *pModule;
164     ET_BUNDLE *bundle;
165     ET_ENTRY *entry;
166
167     if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) ))))
168         return NULL;
169
170     max_offset = 0;
171     *pOrd = 0;
172     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
173     do 
174     {
175         entry = (ET_ENTRY *)((BYTE *)bundle+6);
176         for (i = bundle->first + 1; i <= bundle->last; i++)
177         {
178             if ((entry->offs < frame->entry_ip)
179             && (entry->segnum == 1) /* code segment ? */
180             && (entry->offs >= max_offset))
181             {
182                 max_offset = entry->offs;
183                 *pOrd = i;
184             }
185             entry++;
186         }
187     } while ( (bundle->next)
188            && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
189
190     /* Search for the name in the resident names table */
191     /* (built-in modules have no non-resident table)   */
192     
193     p = (BYTE *)pModule + pModule->name_table;
194     while (*p)
195     {
196         p += *p + 1 + sizeof(WORD);
197         if (*(WORD *)(p + *p + 1) == *pOrd) break;
198     }
199
200     sprintf( name, "%.*s.%d: %.*s",
201              *((BYTE *)pModule + pModule->name_table),
202              (char *)pModule + pModule->name_table + 1,
203              *pOrd, *p, (char *)(p + 1) );
204
205     /* Retrieve type info string */
206     return *(LPCSTR *)((LPBYTE)MapSL( MAKESEGPTR( frame->module_cs, frame->callfrom_ip )) + 4);
207 }
208
209
210 /***********************************************************************
211  *           __wine_register_dll_16
212  *
213  * Register a built-in DLL descriptor.
214  */
215 void __wine_register_dll_16( const BUILTIN16_DESCRIPTOR *descr )
216 {
217     assert( nb_dlls < MAX_DLLS );
218     builtin_dlls[nb_dlls++] = descr;
219 }