Implemented buffer management functions, a couple of workstation
[wine] / if1632 / builtin.c
1 /*
2  * Built-in modules
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include "winbase.h"
29 #include "wine/winbase16.h"
30 #include "builtin16.h"
31 #include "global.h"
32 #include "file.h"
33 #include "module.h"
34 #include "miscemu.h"
35 #include "stackframe.h"
36 #include "wine/library.h"
37 #include "wine/debug.h"
38 #include "toolhelp.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(module);
41
42 typedef struct
43 {
44     void       *module_start;      /* 32-bit address of the module data */
45     int         module_size;       /* Size of the module data */
46     void       *code_start;        /* 32-bit address of DLL code */
47     void       *data_start;        /* 32-bit address of DLL data */
48     const char *owner;             /* 32-bit dll that contains this dll */
49     const void *rsrc;              /* resources data */
50 } BUILTIN16_DESCRIPTOR;
51
52 /* Table of all built-in DLLs */
53
54 #define MAX_DLLS 50
55
56 static const BUILTIN16_DESCRIPTOR *builtin_dlls[MAX_DLLS];
57
58
59 /* patch all the flat cs references of the code segment if necessary */
60 inline static void patch_code_segment( void *code_segment )
61 {
62 #ifdef __i386__
63     CALLFROM16 *call = code_segment;
64     if (call->flatcs == wine_get_cs()) return;  /* nothing to patch */
65     while (call->pushl == 0x68)
66     {
67         call->flatcs = wine_get_cs();
68         call++;
69     }
70 #endif
71 }
72
73
74 /***********************************************************************
75  *           BUILTIN_DoLoadModule16
76  *
77  * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule.
78  */
79 static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
80 {
81     NE_MODULE *pModule;
82     int minsize;
83     SEGTABLEENTRY *pSegTable;
84     HMODULE16 hModule;
85
86     hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
87                                   descr->module_size, 0, WINE_LDT_FLAGS_DATA );
88     if (!hModule) return 0;
89     FarSetOwner16( hModule, hModule );
90
91     pModule = (NE_MODULE *)GlobalLock16( hModule );
92     pModule->self = hModule;
93     /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
94     pModule->hRsrcMap = (void *)descr->rsrc;
95
96     /* Allocate the code segment */
97
98     pSegTable = NE_SEG_TABLE( pModule );
99     pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start,
100                                           pSegTable->minsize, hModule,
101                                           WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT );
102     if (!pSegTable->hSeg) return 0;
103     patch_code_segment( descr->code_start );
104     pSegTable++;
105
106     /* Allocate the data segment */
107
108     minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
109     minsize += pModule->heap_size;
110     if (minsize > 0x10000) minsize = 0x10000;
111     pSegTable->hSeg = GlobalAlloc16( GMEM_FIXED, minsize );
112     if (!pSegTable->hSeg) return 0;
113     FarSetOwner16( pSegTable->hSeg, hModule );
114     if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
115                                     descr->data_start, pSegTable->minsize);
116     if (pModule->heap_size)
117         LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
118                 pSegTable->minsize, minsize );
119
120     if (descr->rsrc) NE_InitResourceHandler(hModule);
121
122     NE_RegisterModule( pModule );
123
124     /* make sure the 32-bit library containing this one is loaded too */
125     LoadLibraryA( descr->owner );
126
127     return hModule;
128 }
129
130
131 /***********************************************************************
132  *           find_dll_descr
133  *
134  * Find a descriptor in the list
135  */
136 static const BUILTIN16_DESCRIPTOR *find_dll_descr( const char *dllname )
137 {
138     int i;
139     for (i = 0; i < MAX_DLLS; i++)
140     {
141         const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
142         if (descr)
143         {
144             NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
145             OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
146             BYTE *name_table = (BYTE *)pModule + pModule->name_table;
147
148             /* check the dll file name */
149             if (!FILE_strcasecmp( pOfs->szPathName, dllname )) return descr;
150             /* check the dll module name (without extension) */
151             if (!FILE_strncasecmp( dllname, name_table+1, *name_table ) &&
152                 !strcmp( dllname + *name_table, ".dll" ))
153                 return descr;
154         }
155     }
156     return NULL;
157 }
158
159
160 /***********************************************************************
161  *           BUILTIN_IsPresent
162  *
163  * Check if a builtin dll descriptor is present (because we loaded its 32-bit counterpart).
164  */
165 BOOL BUILTIN_IsPresent( LPCSTR name )
166 {
167     char dllname[20], *p;
168
169     if (strlen(name) >= sizeof(dllname)-4) return FALSE;
170     strcpy( dllname, name );
171     p = strrchr( dllname, '.' );
172     if (!p) strcat( dllname, ".dll" );
173     for (p = dllname; *p; p++) *p = FILE_tolower(*p);
174
175     return (find_dll_descr( dllname ) != NULL);
176 }
177
178
179 /***********************************************************************
180  *           BUILTIN_LoadModule
181  *
182  * Load a built-in module.
183  */
184 HMODULE16 BUILTIN_LoadModule( LPCSTR name )
185 {
186     const BUILTIN16_DESCRIPTOR *descr;
187     char dllname[20], *p;
188     void *handle;
189
190     /* Fix the name in case we have a full path and extension */
191
192     if ((p = strrchr( name, '\\' ))) name = p + 1;
193     if ((p = strrchr( name, '/' ))) name = p + 1;
194
195     if (strlen(name) >= sizeof(dllname)-4) return (HMODULE16)2;
196
197     strcpy( dllname, name );
198     p = strrchr( dllname, '.' );
199     if (!p) strcat( dllname, ".dll" );
200     for (p = dllname; *p; p++) *p = FILE_tolower(*p);
201
202     if ((descr = find_dll_descr( dllname )))
203         return BUILTIN_DoLoadModule16( descr );
204
205     if ((handle = BUILTIN32_dlopen( dllname )))
206     {
207         if ((descr = find_dll_descr( dllname )))
208             return BUILTIN_DoLoadModule16( descr );
209
210         ERR( "loaded .so but dll %s still not found\n", dllname );
211         BUILTIN32_dlclose( handle );
212     }
213
214     return (HMODULE16)2;
215 }
216
217
218 /***********************************************************************
219  *           __wine_register_dll_16 (KERNEL32.@)
220  *
221  * Register a built-in DLL descriptor.
222  */
223 void __wine_register_dll_16( const BUILTIN16_DESCRIPTOR *descr )
224 {
225     int i;
226
227     for (i = 0; i < MAX_DLLS; i++)
228     {
229         if (builtin_dlls[i]) continue;
230         builtin_dlls[i] = descr;
231         break;
232     }
233     assert( i < MAX_DLLS );
234 }
235
236
237 /***********************************************************************
238  *           __wine_unregister_dll_16 (KERNEL32.@)
239  *
240  * Unregister a built-in DLL descriptor.
241  */
242 void __wine_unregister_dll_16( const BUILTIN16_DESCRIPTOR *descr )
243 {
244     int i;
245
246     for (i = 0; i < MAX_DLLS; i++)
247     {
248         if (builtin_dlls[i] != descr) continue;
249         builtin_dlls[i] = NULL;
250         break;
251     }
252 }