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