Merged msacm and msacm32 dlls.
[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 "wine/winestring.h"
14 #include "builtin16.h"
15 #include "builtin32.h"
16 #include "global.h"
17 #include "heap.h"
18 #include "module.h"
19 #include "miscemu.h"
20 #include "stackframe.h"
21 #include "process.h"
22 #include "task.h"
23 #include "debugtools.h"
24 #include "toolhelp.h"
25
26 DEFAULT_DEBUG_CHANNEL(module);
27
28 typedef struct
29 {
30     LPVOID  res_start;          /* address of resource data */
31     DWORD   nr_res;
32     DWORD   res_size;           /* size of resource data */
33 } BUILTIN16_RESOURCE;
34
35
36 /* Table of all built-in DLLs */
37
38 #define MAX_DLLS 50
39
40 static const BUILTIN16_DESCRIPTOR *builtin_dlls[MAX_DLLS];
41 static int nb_dlls;
42
43
44 /***********************************************************************
45  *           BUILTIN_DoLoadModule16
46  *
47  * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule.
48  */
49 static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
50 {
51     NE_MODULE *pModule;
52     int minsize, res_off;
53     SEGTABLEENTRY *pSegTable;
54     HMODULE16 hModule;
55     const BUILTIN16_RESOURCE *rsrc = descr->rsrc;
56
57     if (!rsrc)
58     {
59         hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
60                                       descr->module_size, 0,
61                                             FALSE, FALSE, FALSE, NULL );
62         if (!hModule) return 0;
63         FarSetOwner16( hModule, hModule );
64
65         pModule = (NE_MODULE *)GlobalLock16( hModule );
66     }
67     else
68     {
69         ET_BUNDLE *bundle;
70
71         hModule = GLOBAL_Alloc( GMEM_MOVEABLE, 
72                                 descr->module_size + rsrc->res_size, 
73                                 0, FALSE, FALSE, FALSE );
74         if (!hModule) return 0;
75         FarSetOwner16( hModule, hModule );
76
77         pModule = (NE_MODULE *)GlobalLock16( hModule );
78         res_off = ((NE_MODULE *)descr->module_start)->res_table;
79
80         memcpy( (LPBYTE)pModule, descr->module_start, res_off );
81         memcpy( (LPBYTE)pModule + res_off, rsrc->res_start, rsrc->res_size );
82         memcpy( (LPBYTE)pModule + res_off + rsrc->res_size, 
83                 (LPBYTE)descr->module_start + res_off, descr->module_size - res_off );
84
85         /* Have to fix up various pModule-based near pointers.  Ugh! */
86         pModule->name_table   += rsrc->res_size;
87         pModule->modref_table += rsrc->res_size;
88         pModule->import_table += rsrc->res_size;
89         pModule->entry_table  += rsrc->res_size;
90
91         for ( bundle = (ET_BUNDLE *)((LPBYTE)pModule + pModule->entry_table);
92               bundle->next;
93               bundle = (ET_BUNDLE *)((LPBYTE)pModule + bundle->next) )
94             bundle->next += rsrc->res_size;
95
96         /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
97         pModule->hRsrcMap = rsrc->res_start;
98     }
99     pModule->self = hModule;
100
101     TRACE( "Built-in %s: hmodule=%04x\n", descr->name, hModule );
102
103     /* Allocate the code segment */
104
105     pSegTable = NE_SEG_TABLE( pModule );
106     pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start,
107                                               pSegTable->minsize, hModule,
108                                               TRUE, TRUE, FALSE, NULL );
109     if (!pSegTable->hSeg) return 0;
110     pSegTable++;
111
112     /* Allocate the data segment */
113
114     minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
115     minsize += pModule->heap_size;
116     if (minsize > 0x10000) minsize = 0x10000;
117     pSegTable->hSeg = GLOBAL_Alloc( GMEM_FIXED, minsize,
118                                         hModule, FALSE, FALSE, FALSE );
119     if (!pSegTable->hSeg) return 0;
120     if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
121                                     descr->data_start, pSegTable->minsize);
122     if (pModule->heap_size)
123         LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
124                 pSegTable->minsize, minsize );
125
126         if (rsrc)
127                 NE_InitResourceHandler(hModule);
128
129     NE_RegisterModule( pModule );
130     return hModule;
131 }
132
133
134 /***********************************************************************
135  *           BUILTIN_LoadModule
136  *
137  * Load a built-in module.
138  */
139 HMODULE16 BUILTIN_LoadModule( LPCSTR name )
140 {
141     char dllname[16], *p;
142     void *handle;
143     int i;
144
145     /* Fix the name in case we have a full path and extension */
146
147     if ((p = strrchr( name, '\\' ))) name = p + 1;
148     lstrcpynA( dllname, name, sizeof(dllname) );
149     p = strrchr( dllname, '.' );
150          
151     if (!p) strcat( dllname, ".dll" );
152
153     for (i = 0; i < nb_dlls; i++)
154     {
155         const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
156         NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
157         OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
158         if (!strcasecmp( pOfs->szPathName, dllname ))
159             return BUILTIN_DoLoadModule16( descr );
160     }
161
162     if ((handle = BUILTIN32_dlopen( dllname )))
163     {
164         for (i = 0; i < nb_dlls; i++)
165         {
166             const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
167             NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
168             OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
169             if (!strcasecmp( pOfs->szPathName, dllname ))
170                 return BUILTIN_DoLoadModule16( descr );
171         }
172         ERR( "loaded .so but dll %s still not found\n", dllname );
173         BUILTIN32_dlclose( handle );
174     }
175
176     return (HMODULE16)2;
177 }
178
179
180 /***********************************************************************
181  *           BUILTIN_GetEntryPoint16
182  *
183  * Return the ordinal, name, and type info corresponding to a CS:IP address.
184  * This is used only by relay debugging.
185  */
186 LPCSTR BUILTIN_GetEntryPoint16( STACK16FRAME *frame, LPSTR name, WORD *pOrd )
187 {
188     WORD i, max_offset;
189     register BYTE *p;
190     NE_MODULE *pModule;
191     ET_BUNDLE *bundle;
192     ET_ENTRY *entry;
193
194     if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) ))))
195         return NULL;
196
197     max_offset = 0;
198     *pOrd = 0;
199     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
200     do 
201     {
202         entry = (ET_ENTRY *)((BYTE *)bundle+6);
203         for (i = bundle->first + 1; i <= bundle->last; i++)
204         {
205             if ((entry->offs < frame->entry_ip)
206             && (entry->segnum == 1) /* code segment ? */
207             && (entry->offs >= max_offset))
208             {
209                 max_offset = entry->offs;
210                 *pOrd = i;
211             }
212             entry++;
213         }
214     } while ( (bundle->next)
215            && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
216
217     /* Search for the name in the resident names table */
218     /* (built-in modules have no non-resident table)   */
219     
220     p = (BYTE *)pModule + pModule->name_table;
221     while (*p)
222     {
223         p += *p + 1 + sizeof(WORD);
224         if (*(WORD *)(p + *p + 1) == *pOrd) break;
225     }
226
227     sprintf( name, "%.*s.%d: %.*s",
228              *((BYTE *)pModule + pModule->name_table),
229              (char *)pModule + pModule->name_table + 1,
230              *pOrd, *p, (char *)(p + 1) );
231
232     /* Retrieve type info string */
233     return *(LPCSTR *)((LPBYTE)PTR_SEG_OFF_TO_LIN( frame->module_cs, frame->callfrom_ip ) + 4);
234 }
235
236
237 /***********************************************************************
238  *           BUILTIN_RegisterDLL
239  *
240  * Register a built-in DLL descriptor.
241  */
242 void BUILTIN_RegisterDLL( const BUILTIN16_DESCRIPTOR *descr )
243 {
244     assert( nb_dlls < MAX_DLLS );
245     builtin_dlls[nb_dlls++] = descr;
246 }