Fixed GetShortPathNameA.
[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 "winbase.h"
11 #include "wine/winbase16.h"
12 #include "wine/winestring.h"
13 #include "builtin16.h"
14 #include "builtin32.h"
15 #include "global.h"
16 #include "heap.h"
17 #include "module.h"
18 #include "miscemu.h"
19 #include "neexe.h"
20 #include "stackframe.h"
21 #include "user.h"
22 #include "process.h"
23 #include "task.h"
24 #include "debugtools.h"
25 #include "toolhelp.h"
26
27 DEFAULT_DEBUG_CHANNEL(module)
28
29 typedef struct
30 {
31     LPVOID  res_start;          /* address of resource data */
32     DWORD   nr_res;
33     DWORD   res_size;           /* size of resource data */
34 } BUILTIN16_RESOURCE;
35
36 typedef struct
37 {
38     const WIN16_DESCRIPTOR *descr;     /* DLL descriptor */
39     int                     flags;     /* flags (see below) */
40     const BUILTIN16_RESOURCE *res;     /* resource descriptor */
41 } BUILTIN16_DLL;
42
43 /* DLL flags */
44 #define DLL_FLAG_NOT_USED    0x01  /* Use original Windows DLL if possible */
45 #define DLL_FLAG_ALWAYS_USED 0x02  /* Always use built-in DLL */
46
47 /* 16-bit DLLs */
48
49 extern const WIN16_DESCRIPTOR AVIFILE_Descriptor;
50 extern const WIN16_DESCRIPTOR COMM_Descriptor;
51 extern const WIN16_DESCRIPTOR COMMDLG_Descriptor;
52 extern const WIN16_DESCRIPTOR COMPOBJ_Descriptor;
53 extern const WIN16_DESCRIPTOR DDEML_Descriptor;
54 extern const WIN16_DESCRIPTOR DISPDIB_Descriptor;
55 extern const WIN16_DESCRIPTOR DISPLAY_Descriptor;
56 extern const WIN16_DESCRIPTOR GDI_Descriptor;
57 extern const WIN16_DESCRIPTOR KERNEL_Descriptor;
58 extern const WIN16_DESCRIPTOR KEYBOARD_Descriptor;
59 extern const WIN16_DESCRIPTOR LZEXPAND_Descriptor;
60 extern const WIN16_DESCRIPTOR MMSYSTEM_Descriptor;
61 extern const WIN16_DESCRIPTOR MOUSE_Descriptor;
62 extern const WIN16_DESCRIPTOR MSACM_Descriptor;
63 extern const WIN16_DESCRIPTOR MSVIDEO_Descriptor;
64 extern const WIN16_DESCRIPTOR OLE2CONV_Descriptor;
65 extern const WIN16_DESCRIPTOR OLE2DISP_Descriptor;
66 extern const WIN16_DESCRIPTOR OLE2NLS_Descriptor;
67 extern const WIN16_DESCRIPTOR OLE2PROX_Descriptor;
68 extern const WIN16_DESCRIPTOR OLE2THK_Descriptor;
69 extern const WIN16_DESCRIPTOR OLE2_Descriptor;
70 extern const WIN16_DESCRIPTOR OLECLI_Descriptor;
71 extern const WIN16_DESCRIPTOR OLESVR_Descriptor;
72 extern const WIN16_DESCRIPTOR RASAPI16_Descriptor;
73 extern const WIN16_DESCRIPTOR SHELL_Descriptor;
74 extern const WIN16_DESCRIPTOR SOUND_Descriptor;
75 extern const WIN16_DESCRIPTOR STORAGE_Descriptor;
76 extern const WIN16_DESCRIPTOR STRESS_Descriptor;
77 extern const WIN16_DESCRIPTOR SYSTEM_Descriptor;
78 extern const WIN16_DESCRIPTOR TOOLHELP_Descriptor;
79 extern const WIN16_DESCRIPTOR TYPELIB_Descriptor;
80 extern const WIN16_DESCRIPTOR USER_Descriptor;
81 extern const WIN16_DESCRIPTOR VER_Descriptor;
82 extern const WIN16_DESCRIPTOR W32SYS_Descriptor;
83 extern const WIN16_DESCRIPTOR WIN32S16_Descriptor;
84 extern const WIN16_DESCRIPTOR WIN87EM_Descriptor;
85 extern const WIN16_DESCRIPTOR WINASPI_Descriptor;
86 extern const WIN16_DESCRIPTOR WINDEBUG_Descriptor;
87 extern const WIN16_DESCRIPTOR WINEPS_Descriptor;
88 extern const WIN16_DESCRIPTOR WING_Descriptor;
89 extern const WIN16_DESCRIPTOR WINSOCK_Descriptor;
90 extern const WIN16_DESCRIPTOR WPROCS_Descriptor;
91
92 extern const BUILTIN16_RESOURCE display_ResourceDescriptor;
93 extern const BUILTIN16_RESOURCE mouse_ResourceDescriptor;
94
95 /* Table of all built-in DLLs */
96
97 static BUILTIN16_DLL BuiltinDLLs[] =
98 {
99     { &KERNEL_Descriptor,   0, NULL },
100     { &USER_Descriptor,     0, NULL },
101     { &GDI_Descriptor,      0, NULL },
102     { &SYSTEM_Descriptor,   DLL_FLAG_ALWAYS_USED, NULL },
103     { &DISPLAY_Descriptor,  DLL_FLAG_ALWAYS_USED, &display_ResourceDescriptor },
104     { &WPROCS_Descriptor,   DLL_FLAG_ALWAYS_USED, NULL },
105     { &WINDEBUG_Descriptor, DLL_FLAG_NOT_USED, NULL },
106     { &AVIFILE_Descriptor,  DLL_FLAG_NOT_USED, NULL },
107     { &COMMDLG_Descriptor,  DLL_FLAG_NOT_USED, NULL },
108     { &COMPOBJ_Descriptor,  DLL_FLAG_NOT_USED, NULL },
109     { &DDEML_Descriptor,    DLL_FLAG_NOT_USED, NULL },
110     { &DISPDIB_Descriptor,  0, NULL },
111     { &KEYBOARD_Descriptor, 0, NULL },
112     { &COMM_Descriptor,     0, NULL },
113     { &LZEXPAND_Descriptor, 0, NULL },
114     { &MMSYSTEM_Descriptor, 0, NULL },
115     { &MOUSE_Descriptor,    0, &mouse_ResourceDescriptor },
116     { &MSACM_Descriptor,    0, NULL },
117     { &MSVIDEO_Descriptor,  0, NULL },
118     { &OLE2CONV_Descriptor, DLL_FLAG_NOT_USED, NULL },
119     { &OLE2DISP_Descriptor, DLL_FLAG_NOT_USED, NULL },
120     { &OLE2NLS_Descriptor,  DLL_FLAG_NOT_USED, NULL },
121     { &OLE2PROX_Descriptor, DLL_FLAG_NOT_USED, NULL },
122     { &OLE2THK_Descriptor,  DLL_FLAG_NOT_USED, NULL },
123     { &OLE2_Descriptor,     DLL_FLAG_NOT_USED, NULL },
124     { &OLECLI_Descriptor,   DLL_FLAG_NOT_USED, NULL },
125     { &OLESVR_Descriptor,   DLL_FLAG_NOT_USED, NULL },
126     { &RASAPI16_Descriptor, 0, NULL },
127     { &SHELL_Descriptor,    0, NULL },
128     { &SOUND_Descriptor,    0, NULL },
129     { &STORAGE_Descriptor,  DLL_FLAG_NOT_USED, NULL },
130     { &STRESS_Descriptor,   0, NULL },
131     { &TOOLHELP_Descriptor, 0, NULL },
132     { &TYPELIB_Descriptor,  DLL_FLAG_NOT_USED, NULL },
133     { &VER_Descriptor,      0, NULL },
134     { &W32SYS_Descriptor,   DLL_FLAG_NOT_USED, NULL },
135     { &WIN32S16_Descriptor, DLL_FLAG_NOT_USED, NULL },
136     { &WIN87EM_Descriptor,  DLL_FLAG_NOT_USED, NULL },
137     { &WINASPI_Descriptor,  0, NULL },
138     { &WINEPS_Descriptor,   DLL_FLAG_ALWAYS_USED, NULL },
139     { &WING_Descriptor,     0, NULL },
140     { &WINSOCK_Descriptor,  0, NULL },
141     /* Last entry */
142     { NULL, 0, NULL }
143 };
144
145   /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
146 #define FIRST_INTERRUPT_ORDINAL 100
147
148
149 /***********************************************************************
150  *           BUILTIN_DoLoadModule16
151  *
152  * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule
153  * and BUILTIN_Init.
154  */
155 static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DLL *dll )
156 {
157     NE_MODULE *pModule;
158     int minsize, res_off;
159     SEGTABLEENTRY *pSegTable;
160     HMODULE16 hModule;
161
162     if ( !dll->res )
163     {
164         hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, dll->descr->module_start,
165                                       dll->descr->module_size, 0,
166                                             FALSE, FALSE, FALSE, NULL );
167     if (!hModule) return 0;
168     FarSetOwner16( hModule, hModule );
169
170     pModule = (NE_MODULE *)GlobalLock16( hModule );
171     }
172     else
173     {
174         ET_BUNDLE *bundle;
175
176         hModule = GLOBAL_Alloc( GMEM_MOVEABLE, 
177                                 dll->descr->module_size + dll->res->res_size, 
178                                 0, FALSE, FALSE, FALSE );
179         if (!hModule) return 0;
180         FarSetOwner16( hModule, hModule );
181
182         pModule = (NE_MODULE *)GlobalLock16( hModule );
183         res_off = ((NE_MODULE *)dll->descr->module_start)->res_table;
184
185         memcpy( (LPBYTE)pModule, dll->descr->module_start, res_off );
186         memcpy( (LPBYTE)pModule + res_off, dll->res->res_start, dll->res->res_size );
187         memcpy( (LPBYTE)pModule + res_off + dll->res->res_size, 
188                 dll->descr->module_start + res_off, dll->descr->module_size - res_off );
189
190         /* Have to fix up various pModule-based near pointers.  Ugh! */
191         pModule->name_table   += dll->res->res_size;
192         pModule->modref_table += dll->res->res_size;
193         pModule->import_table += dll->res->res_size;
194         pModule->entry_table  += dll->res->res_size;
195
196         for ( bundle = (ET_BUNDLE *)((LPBYTE)pModule + pModule->entry_table);
197               bundle->next;
198               bundle = (ET_BUNDLE *)((LPBYTE)pModule + bundle->next) )
199             bundle->next += dll->res->res_size;
200
201         /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
202         pModule->hRsrcMap = dll->res->res_start;
203     }
204     pModule->self = hModule;
205
206     TRACE( "Built-in %s: hmodule=%04x\n", dll->descr->name, hModule );
207
208     /* Allocate the code segment */
209
210     pSegTable = NE_SEG_TABLE( pModule );
211     pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, dll->descr->code_start,
212                                               pSegTable->minsize, hModule,
213                                               TRUE, TRUE, FALSE, NULL );
214     if (!pSegTable->hSeg) return 0;
215     pSegTable++;
216
217     /* Allocate the data segment */
218
219     minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
220     minsize += pModule->heap_size;
221     if (minsize > 0x10000) minsize = 0x10000;
222     pSegTable->hSeg = GLOBAL_Alloc( GMEM_FIXED, minsize,
223                                         hModule, FALSE, FALSE, FALSE );
224     if (!pSegTable->hSeg) return 0;
225     if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
226                                     dll->descr->data_start, pSegTable->minsize);
227     if (pModule->heap_size)
228         LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
229                 pSegTable->minsize, minsize );
230
231         if (dll->res)
232                 NE_InitResourceHandler(hModule);
233
234     NE_RegisterModule( pModule );
235     return hModule;
236 }
237
238
239 /***********************************************************************
240  *           BUILTIN_Init
241  *
242  * Load all built-in modules marked as 'always used'.
243  */
244 BOOL BUILTIN_Init(void)
245 {
246     BUILTIN16_DLL *dll;
247     WORD vector;
248     HMODULE16 hModule;
249
250     for (dll = BuiltinDLLs; dll->descr; dll++)
251     {
252         if (dll->flags & DLL_FLAG_ALWAYS_USED)
253             if (!BUILTIN_DoLoadModule16( dll )) return FALSE;
254     }
255
256     /* Set interrupt vectors from entry points in WPROCS.DLL */
257
258     hModule = GetModuleHandle16( "WPROCS" );
259     for (vector = 0; vector < 256; vector++)
260     {
261         FARPROC16 proc = NE_GetEntryPoint( hModule,
262                                            FIRST_INTERRUPT_ORDINAL + vector );
263         assert(proc);
264         INT_SetPMHandler( vector, proc );
265     }
266
267     return TRUE;
268 }
269
270
271 /***********************************************************************
272  *           BUILTIN_LoadModule
273  *
274  * Load a built-in module. If the 'force' parameter is FALSE, we only
275  * load the module if it has not been disabled via the -dll option.
276  */
277 HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force )
278 {
279     BUILTIN16_DLL *table;
280     char dllname[16], *p;
281
282     /* Fix the name in case we have a full path and extension */
283
284     if ((p = strrchr( name, '\\' ))) name = p + 1;
285     lstrcpynA( dllname, name, sizeof(dllname) );
286     p = strrchr( dllname, '.' );
287          
288     if (!p) strcat( dllname, ".dll" );
289
290     for (table = BuiltinDLLs; table->descr; table++)
291     {
292        NE_MODULE *pModule = (NE_MODULE *)table->descr->module_start;
293        OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
294        if (!lstrcmpiA( pOfs->szPathName, dllname )) break;
295     }
296
297     if (!table->descr) return (HMODULE16)2;
298
299     if ((table->flags & DLL_FLAG_NOT_USED) && !force) return (HMODULE16)2;
300
301     return BUILTIN_DoLoadModule16( table );
302 }
303
304
305 /***********************************************************************
306  *           BUILTIN_GetEntryPoint16
307  *
308  * Return the ordinal, name, and type info corresponding to a CS:IP address.
309  * This is used only by relay debugging.
310  */
311 LPCSTR BUILTIN_GetEntryPoint16( STACK16FRAME *frame, LPSTR name, WORD *pOrd )
312 {
313     WORD i, max_offset;
314     register BYTE *p;
315     NE_MODULE *pModule;
316     ET_BUNDLE *bundle;
317     ET_ENTRY *entry;
318
319     if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) ))))
320         return NULL;
321
322     max_offset = 0;
323     *pOrd = 0;
324     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
325     do 
326     {
327         entry = (ET_ENTRY *)((BYTE *)bundle+6);
328         for (i = bundle->first + 1; i <= bundle->last; i++)
329         {
330             if ((entry->offs < frame->entry_ip)
331             && (entry->segnum == 1) /* code segment ? */
332             && (entry->offs >= max_offset))
333             {
334                 max_offset = entry->offs;
335                 *pOrd = i;
336             }
337             entry++;
338         }
339     } while ( (bundle->next)
340            && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
341
342     /* Search for the name in the resident names table */
343     /* (built-in modules have no non-resident table)   */
344     
345     p = (BYTE *)pModule + pModule->name_table;
346     while (*p)
347     {
348         p += *p + 1 + sizeof(WORD);
349         if (*(WORD *)(p + *p + 1) == *pOrd) break;
350     }
351
352     sprintf( name, "%.*s.%d: %.*s",
353              *((BYTE *)pModule + pModule->name_table),
354              (char *)pModule + pModule->name_table + 1,
355              *pOrd, *p, (char *)(p + 1) );
356
357     /* Retrieve type info string */
358     return *(LPCSTR *)((LPBYTE)PTR_SEG_OFF_TO_LIN( frame->module_cs, frame->callfrom_ip ) + 4);
359 }
360
361
362 /**********************************************************************
363  *          BUILTIN_DefaultIntHandler
364  *
365  * Default interrupt handler.
366  */
367 void WINAPI BUILTIN_DefaultIntHandler( CONTEXT86 *context )
368 {
369     WORD ordinal;
370     char name[80];
371     BUILTIN_GetEntryPoint16( CURRENT_STACK16, name, &ordinal );
372     INT_BARF( context, ordinal - FIRST_INTERRUPT_ORDINAL );
373 }
374