blob: e2fade8b16474abfb070f474fa7a1586c949b60b [file] [log] [blame]
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001/*
2 * Built-in modules
3 *
4 * Copyright 1996 Alexandre Julliard
5 */
6
Alexandre Julliard9ea19e51997-01-01 17:29:55 +00007#include <assert.h>
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00008#include <ctype.h>
9#include <string.h>
Alexandre Julliard383da682000-02-10 22:15:21 +000010#include <stdio.h>
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000011#include "winbase.h"
12#include "wine/winbase16.h"
Huw D M Davies34acebc1999-02-19 16:03:19 +000013#include "wine/winestring.h"
Ulrich Weigandc50a1d01999-08-15 12:45:01 +000014#include "builtin16.h"
Alexandre Julliard44ed71f1997-12-21 19:17:50 +000015#include "builtin32.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000016#include "global.h"
Alexandre Julliard17216f51997-10-12 16:30:17 +000017#include "heap.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000018#include "module.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000019#include "miscemu.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000020#include "neexe.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000021#include "stackframe.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000022#include "user.h"
Alexandre Julliarde658d821997-11-30 17:45:40 +000023#include "process.h"
Alexandre Julliard642d3131998-07-12 19:29:36 +000024#include "task.h"
Alexandre Julliarda099a551999-06-12 15:45:58 +000025#include "debugtools.h"
Patrik Stridvallfdcfdb91999-06-12 14:55:11 +000026#include "toolhelp.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000027
Alexandre Julliard74e4a282000-01-09 04:20:31 +000028DEFAULT_DEBUG_CHANNEL(module);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000029
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000030typedef struct
31{
Andreas Mohra2da8681999-12-06 01:20:00 +000032 LPVOID res_start; /* address of resource data */
33 DWORD nr_res;
34 DWORD res_size; /* size of resource data */
35} BUILTIN16_RESOURCE;
36
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000037
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000038/* Table of all built-in DLLs */
39
Alexandre Julliard112d3072000-01-16 03:37:05 +000040#define MAX_DLLS 50
41
42static const BUILTIN16_DESCRIPTOR *builtin_dlls[MAX_DLLS];
43static int nb_dlls;
Alexandre Julliard74e4a282000-01-09 04:20:31 +000044
45/* list of DLLs that should always be loaded at startup */
46static const char * const always_load[] =
47{
48 "system", "display", "wprocs", "wineps", NULL
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000049};
50
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000051 /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
52#define FIRST_INTERRUPT_ORDINAL 100
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000053
Alexandre Julliard17216f51997-10-12 16:30:17 +000054
55/***********************************************************************
56 * BUILTIN_DoLoadModule16
57 *
58 * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule
59 * and BUILTIN_Init.
60 */
Alexandre Julliard112d3072000-01-16 03:37:05 +000061static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
Alexandre Julliard17216f51997-10-12 16:30:17 +000062{
63 NE_MODULE *pModule;
Andreas Mohra2da8681999-12-06 01:20:00 +000064 int minsize, res_off;
Alexandre Julliard17216f51997-10-12 16:30:17 +000065 SEGTABLEENTRY *pSegTable;
Andreas Mohra2da8681999-12-06 01:20:00 +000066 HMODULE16 hModule;
Alexandre Julliard74e4a282000-01-09 04:20:31 +000067 const BUILTIN16_RESOURCE *rsrc = descr->rsrc;
Alexandre Julliard17216f51997-10-12 16:30:17 +000068
Alexandre Julliard74e4a282000-01-09 04:20:31 +000069 if (!rsrc)
Andreas Mohra2da8681999-12-06 01:20:00 +000070 {
Alexandre Julliard74e4a282000-01-09 04:20:31 +000071 hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
72 descr->module_size, 0,
Alexandre Julliard17216f51997-10-12 16:30:17 +000073 FALSE, FALSE, FALSE, NULL );
Alexandre Julliard74e4a282000-01-09 04:20:31 +000074 if (!hModule) return 0;
75 FarSetOwner16( hModule, hModule );
Alexandre Julliard17216f51997-10-12 16:30:17 +000076
Alexandre Julliard74e4a282000-01-09 04:20:31 +000077 pModule = (NE_MODULE *)GlobalLock16( hModule );
Andreas Mohra2da8681999-12-06 01:20:00 +000078 }
79 else
80 {
81 ET_BUNDLE *bundle;
82
83 hModule = GLOBAL_Alloc( GMEM_MOVEABLE,
Alexandre Julliard74e4a282000-01-09 04:20:31 +000084 descr->module_size + rsrc->res_size,
Andreas Mohra2da8681999-12-06 01:20:00 +000085 0, FALSE, FALSE, FALSE );
86 if (!hModule) return 0;
87 FarSetOwner16( hModule, hModule );
88
89 pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliard74e4a282000-01-09 04:20:31 +000090 res_off = ((NE_MODULE *)descr->module_start)->res_table;
Andreas Mohra2da8681999-12-06 01:20:00 +000091
Alexandre Julliard74e4a282000-01-09 04:20:31 +000092 memcpy( (LPBYTE)pModule, descr->module_start, res_off );
93 memcpy( (LPBYTE)pModule + res_off, rsrc->res_start, rsrc->res_size );
94 memcpy( (LPBYTE)pModule + res_off + rsrc->res_size,
95 descr->module_start + res_off, descr->module_size - res_off );
Andreas Mohra2da8681999-12-06 01:20:00 +000096
97 /* Have to fix up various pModule-based near pointers. Ugh! */
Alexandre Julliard74e4a282000-01-09 04:20:31 +000098 pModule->name_table += rsrc->res_size;
99 pModule->modref_table += rsrc->res_size;
100 pModule->import_table += rsrc->res_size;
101 pModule->entry_table += rsrc->res_size;
Andreas Mohra2da8681999-12-06 01:20:00 +0000102
103 for ( bundle = (ET_BUNDLE *)((LPBYTE)pModule + pModule->entry_table);
104 bundle->next;
105 bundle = (ET_BUNDLE *)((LPBYTE)pModule + bundle->next) )
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000106 bundle->next += rsrc->res_size;
Andreas Mohra2da8681999-12-06 01:20:00 +0000107
108 /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000109 pModule->hRsrcMap = rsrc->res_start;
Andreas Mohra2da8681999-12-06 01:20:00 +0000110 }
Alexandre Julliard17216f51997-10-12 16:30:17 +0000111 pModule->self = hModule;
112
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000113 TRACE( "Built-in %s: hmodule=%04x\n", descr->name, hModule );
Andreas Mohra2da8681999-12-06 01:20:00 +0000114
Alexandre Julliard17216f51997-10-12 16:30:17 +0000115 /* Allocate the code segment */
116
117 pSegTable = NE_SEG_TABLE( pModule );
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000118 pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start,
Alexandre Julliard17216f51997-10-12 16:30:17 +0000119 pSegTable->minsize, hModule,
120 TRUE, TRUE, FALSE, NULL );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000121 if (!pSegTable->hSeg) return 0;
Alexandre Julliard17216f51997-10-12 16:30:17 +0000122 pSegTable++;
123
124 /* Allocate the data segment */
125
126 minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
127 minsize += pModule->heap_size;
128 if (minsize > 0x10000) minsize = 0x10000;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000129 pSegTable->hSeg = GLOBAL_Alloc( GMEM_FIXED, minsize,
Alexandre Julliard17216f51997-10-12 16:30:17 +0000130 hModule, FALSE, FALSE, FALSE );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000131 if (!pSegTable->hSeg) return 0;
132 if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000133 descr->data_start, pSegTable->minsize);
Alexandre Julliard17216f51997-10-12 16:30:17 +0000134 if (pModule->heap_size)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000135 LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000136 pSegTable->minsize, minsize );
Alexandre Julliard17216f51997-10-12 16:30:17 +0000137
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000138 if (rsrc)
Andreas Mohra2da8681999-12-06 01:20:00 +0000139 NE_InitResourceHandler(hModule);
140
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000141 NE_RegisterModule( pModule );
Alexandre Julliard17216f51997-10-12 16:30:17 +0000142 return hModule;
143}
144
145
146/***********************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000147 * BUILTIN_Init
148 *
149 * Load all built-in modules marked as 'always used'.
150 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000151BOOL BUILTIN_Init(void)
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000152{
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000153 WORD vector;
154 HMODULE16 hModule;
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000155 const char * const *ptr = always_load;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000156
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000157 while (*ptr)
Alexandre Julliard17216f51997-10-12 16:30:17 +0000158 {
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000159 if (!BUILTIN_LoadModule( *ptr )) return FALSE;
160 ptr++;
Alexandre Julliard17216f51997-10-12 16:30:17 +0000161 }
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000162
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000163 /* Set interrupt vectors from entry points in WPROCS.DLL */
164
Alexandre Julliard21979011997-03-05 08:22:35 +0000165 hModule = GetModuleHandle16( "WPROCS" );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000166 for (vector = 0; vector < 256; vector++)
167 {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000168 FARPROC16 proc = NE_GetEntryPoint( hModule,
169 FIRST_INTERRUPT_ORDINAL + vector );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000170 assert(proc);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000171 INT_SetPMHandler( vector, proc );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000172 }
173
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000174 return TRUE;
175}
176
177
178/***********************************************************************
179 * BUILTIN_LoadModule
180 *
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000181 * Load a built-in module.
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000182 */
Alexandre Julliard74e4a282000-01-09 04:20:31 +0000183HMODULE16 BUILTIN_LoadModule( LPCSTR name )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000184{
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000185 char dllname[16], *p;
Alexandre Julliard112d3072000-01-16 03:37:05 +0000186 int i;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000187
188 /* Fix the name in case we have a full path and extension */
189
190 if ((p = strrchr( name, '\\' ))) name = p + 1;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000191 lstrcpynA( dllname, name, sizeof(dllname) );
Eric Pouechd2344fb1999-10-13 15:59:26 +0000192 p = strrchr( dllname, '.' );
193
194 if (!p) strcat( dllname, ".dll" );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000195
Alexandre Julliard112d3072000-01-16 03:37:05 +0000196 for (i = 0; i < nb_dlls; i++)
Eric Pouechd2344fb1999-10-13 15:59:26 +0000197 {
Alexandre Julliard112d3072000-01-16 03:37:05 +0000198 const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
199 NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
200 OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
201 if (!lstrcmpiA( pOfs->szPathName, dllname ))
202 return BUILTIN_DoLoadModule16( descr );
Eric Pouechd2344fb1999-10-13 15:59:26 +0000203 }
Alexandre Julliard112d3072000-01-16 03:37:05 +0000204 return (HMODULE16)2;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000205}
206
207
208/***********************************************************************
Alexandre Julliardca22b331996-07-12 19:02:39 +0000209 * BUILTIN_GetEntryPoint16
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000210 *
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000211 * Return the ordinal, name, and type info corresponding to a CS:IP address.
Alexandre Julliardca22b331996-07-12 19:02:39 +0000212 * This is used only by relay debugging.
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000213 */
Ulrich Weigandc50a1d01999-08-15 12:45:01 +0000214LPCSTR BUILTIN_GetEntryPoint16( STACK16FRAME *frame, LPSTR name, WORD *pOrd )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000215{
Andreas Mohrdca5e561999-04-16 08:17:17 +0000216 WORD i, max_offset;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000217 register BYTE *p;
218 NE_MODULE *pModule;
Andreas Mohrdca5e561999-04-16 08:17:17 +0000219 ET_BUNDLE *bundle;
220 ET_ENTRY *entry;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000221
Ulrich Weigandc50a1d01999-08-15 12:45:01 +0000222 if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) ))))
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000223 return NULL;
224
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000225 max_offset = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000226 *pOrd = 0;
Andreas Mohrdca5e561999-04-16 08:17:17 +0000227 bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
Ulrich Weiganda7e6e811999-04-22 09:54:15 +0000228 do
229 {
230 entry = (ET_ENTRY *)((BYTE *)bundle+6);
231 for (i = bundle->first + 1; i <= bundle->last; i++)
232 {
Ulrich Weigandc50a1d01999-08-15 12:45:01 +0000233 if ((entry->offs < frame->entry_ip)
Ulrich Weiganda7e6e811999-04-22 09:54:15 +0000234 && (entry->segnum == 1) /* code segment ? */
Andreas Mohrdca5e561999-04-16 08:17:17 +0000235 && (entry->offs >= max_offset))
Ulrich Weiganda7e6e811999-04-22 09:54:15 +0000236 {
Andreas Mohrdca5e561999-04-16 08:17:17 +0000237 max_offset = entry->offs;
238 *pOrd = i;
Ulrich Weiganda7e6e811999-04-22 09:54:15 +0000239 }
Andreas Mohrdca5e561999-04-16 08:17:17 +0000240 entry++;
Ulrich Weiganda7e6e811999-04-22 09:54:15 +0000241 }
Andreas Mohrdca5e561999-04-16 08:17:17 +0000242 } while ( (bundle->next)
243 && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000244
245 /* Search for the name in the resident names table */
246 /* (built-in modules have no non-resident table) */
247
248 p = (BYTE *)pModule + pModule->name_table;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000249 while (*p)
250 {
251 p += *p + 1 + sizeof(WORD);
Alexandre Julliardca22b331996-07-12 19:02:39 +0000252 if (*(WORD *)(p + *p + 1) == *pOrd) break;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000253 }
254
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000255 sprintf( name, "%.*s.%d: %.*s",
Alexandre Julliardca22b331996-07-12 19:02:39 +0000256 *((BYTE *)pModule + pModule->name_table),
257 (char *)pModule + pModule->name_table + 1,
258 *pOrd, *p, (char *)(p + 1) );
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000259
260 /* Retrieve type info string */
Ulrich Weigandc50a1d01999-08-15 12:45:01 +0000261 return *(LPCSTR *)((LPBYTE)PTR_SEG_OFF_TO_LIN( frame->module_cs, frame->callfrom_ip ) + 4);
Alexandre Julliardca22b331996-07-12 19:02:39 +0000262}
263
264
Alexandre Julliard112d3072000-01-16 03:37:05 +0000265/***********************************************************************
266 * BUILTIN_RegisterDLL
267 *
268 * Register a built-in DLL descriptor.
269 */
270void BUILTIN_RegisterDLL( const BUILTIN16_DESCRIPTOR *descr )
271{
272 assert( nb_dlls < MAX_DLLS );
273 builtin_dlls[nb_dlls++] = descr;
274}
275
276
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000277/**********************************************************************
278 * BUILTIN_DefaultIntHandler
279 *
280 * Default interrupt handler.
281 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000282void WINAPI BUILTIN_DefaultIntHandler( CONTEXT86 *context )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000283{
284 WORD ordinal;
Ulrich Weigand3dff7bb1999-07-11 13:58:31 +0000285 char name[80];
Ulrich Weigandc50a1d01999-08-15 12:45:01 +0000286 BUILTIN_GetEntryPoint16( CURRENT_STACK16, name, &ordinal );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000287 INT_BARF( context, ordinal - FIRST_INTERRUPT_ORDINAL );
288}