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