4 * Copyright 1996 Alexandre Julliard
11 #include "wine/winbase16.h"
12 #include "wine/winestring.h"
13 #include "builtin16.h"
14 #include "builtin32.h"
20 #include "stackframe.h"
24 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(module
)
31 LPVOID res_start
; /* address of resource data */
33 DWORD res_size
; /* size of resource data */
38 const WIN16_DESCRIPTOR
*descr
; /* DLL descriptor */
39 int flags
; /* flags (see below) */
40 const BUILTIN16_RESOURCE
*res
; /* resource descriptor */
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 */
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
;
92 extern const BUILTIN16_RESOURCE display_ResourceDescriptor
;
93 extern const BUILTIN16_RESOURCE mouse_ResourceDescriptor
;
95 /* Table of all built-in DLLs */
97 static BUILTIN16_DLL BuiltinDLLs
[] =
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
},
145 /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
146 #define FIRST_INTERRUPT_ORDINAL 100
149 /***********************************************************************
150 * BUILTIN_DoLoadModule16
152 * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule
155 static HMODULE16
BUILTIN_DoLoadModule16( const BUILTIN16_DLL
*dll
)
158 int minsize
, res_off
;
159 SEGTABLEENTRY
*pSegTable
;
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
);
170 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
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
);
182 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
183 res_off
= ((NE_MODULE
*)dll
->descr
->module_start
)->res_table
;
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
);
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
;
196 for ( bundle
= (ET_BUNDLE
*)((LPBYTE
)pModule
+ pModule
->entry_table
);
198 bundle
= (ET_BUNDLE
*)((LPBYTE
)pModule
+ bundle
->next
) )
199 bundle
->next
+= dll
->res
->res_size
;
201 /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
202 pModule
->hRsrcMap
= dll
->res
->res_start
;
204 pModule
->self
= hModule
;
206 TRACE( "Built-in %s: hmodule=%04x\n", dll
->descr
->name
, hModule
);
208 /* Allocate the code segment */
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;
217 /* Allocate the data segment */
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
);
232 NE_InitResourceHandler(hModule
);
234 NE_RegisterModule( pModule
);
239 /***********************************************************************
242 * Load all built-in modules marked as 'always used'.
244 BOOL
BUILTIN_Init(void)
250 for (dll
= BuiltinDLLs
; dll
->descr
; dll
++)
252 if (dll
->flags
& DLL_FLAG_ALWAYS_USED
)
253 if (!BUILTIN_DoLoadModule16( dll
)) return FALSE
;
256 /* Set interrupt vectors from entry points in WPROCS.DLL */
258 hModule
= GetModuleHandle16( "WPROCS" );
259 for (vector
= 0; vector
< 256; vector
++)
261 FARPROC16 proc
= NE_GetEntryPoint( hModule
,
262 FIRST_INTERRUPT_ORDINAL
+ vector
);
264 INT_SetPMHandler( vector
, proc
);
271 /***********************************************************************
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.
277 HMODULE16
BUILTIN_LoadModule( LPCSTR name
, BOOL force
)
279 BUILTIN16_DLL
*table
;
280 char dllname
[16], *p
;
282 /* Fix the name in case we have a full path and extension */
284 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
285 lstrcpynA( dllname
, name
, sizeof(dllname
) );
286 p
= strrchr( dllname
, '.' );
288 if (!p
) strcat( dllname
, ".dll" );
290 for (table
= BuiltinDLLs
; table
->descr
; table
++)
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;
297 if (!table
->descr
) return (HMODULE16
)2;
299 if ((table
->flags
& DLL_FLAG_NOT_USED
) && !force
) return (HMODULE16
)2;
301 return BUILTIN_DoLoadModule16( table
);
305 /***********************************************************************
306 * BUILTIN_GetEntryPoint16
308 * Return the ordinal, name, and type info corresponding to a CS:IP address.
309 * This is used only by relay debugging.
311 LPCSTR
BUILTIN_GetEntryPoint16( STACK16FRAME
*frame
, LPSTR name
, WORD
*pOrd
)
319 if (!(pModule
= NE_GetPtr( FarGetOwner16( GlobalHandle16( frame
->module_cs
) ))))
324 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+ pModule
->entry_table
);
327 entry
= (ET_ENTRY
*)((BYTE
*)bundle
+6);
328 for (i
= bundle
->first
+ 1; i
<= bundle
->last
; i
++)
330 if ((entry
->offs
< frame
->entry_ip
)
331 && (entry
->segnum
== 1) /* code segment ? */
332 && (entry
->offs
>= max_offset
))
334 max_offset
= entry
->offs
;
339 } while ( (bundle
->next
)
340 && (bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+bundle
->next
)));
342 /* Search for the name in the resident names table */
343 /* (built-in modules have no non-resident table) */
345 p
= (BYTE
*)pModule
+ pModule
->name_table
;
348 p
+= *p
+ 1 + sizeof(WORD
);
349 if (*(WORD
*)(p
+ *p
+ 1) == *pOrd
) break;
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) );
357 /* Retrieve type info string */
358 return *(LPCSTR
*)((LPBYTE
)PTR_SEG_OFF_TO_LIN( frame
->module_cs
, frame
->callfrom_ip
) + 4);
362 /**********************************************************************
363 * BUILTIN_DefaultIntHandler
365 * Default interrupt handler.
367 void WINAPI
BUILTIN_DefaultIntHandler( CONTEXT86
*context
)
371 BUILTIN_GetEntryPoint16( CURRENT_STACK16
, name
, &ordinal
);
372 INT_BARF( context
, ordinal
- FIRST_INTERRUPT_ORDINAL
);