4 * Copyright 1996 Alexandre Julliard
17 #include "stackframe.h"
22 /* Built-in modules descriptors */
23 /* Don't change these structures! (see tools/build.c) */
27 const char *name
; /* DLL name */
28 void *module_start
; /* 32-bit address of the module data */
29 int module_size
; /* Size of the module data */
30 const BYTE
*code_start
; /* 32-bit address of DLL code */
31 const BYTE
*data_start
; /* 32-bit address of DLL data */
36 const char *name
; /* DLL name */
37 int base
; /* Ordinal base */
38 int nb_funcs
; /* Number of functions */
39 int nb_names
; /* Number of function names */
40 const void **functions
; /* Pointer to function table */
41 const char * const *names
; /* Pointer to names table */
42 const WORD
*ordinals
; /* Pointer to ordinals table */
43 const BYTE
*args
; /* Pointer to argument lengths */
48 const char *name
; /* DLL name */
49 WIN16_DESCRIPTOR win16
; /* Descriptor for Win16 DLL */
50 WIN32_DESCRIPTOR win32
; /* Descriptor for Win32 DLL */
55 BYTE call
; /* 0xe8 call callfrom32 (relative) */
56 DWORD callfrom32 WINE_PACKED
; /* RELAY_CallFrom32 relative addr */
57 BYTE ret
; /* 0xc2 ret $n or 0xc3 ret */
58 WORD args
; /* nb of args to remove from the stack */
63 const DLL_DESCRIPTOR
*descr
; /* DLL descriptor */
64 DEBUG_ENTRY_POINT
*dbg_funcs
; /* Relay debugging functions table */
65 int flags
; /* flags (see below) */
69 #define DLL_FLAG_NOT_USED 0x01 /* Use original Windows DLL if possible */
70 #define DLL_FLAG_ALWAYS_USED 0x02 /* Always use built-in DLL */
71 #define DLL_FLAG_WIN32 0x04 /* DLL is a Win32 DLL */
75 extern const DLL_DESCRIPTOR KERNEL_Descriptor
;
76 extern const DLL_DESCRIPTOR USER_Descriptor
;
77 extern const DLL_DESCRIPTOR GDI_Descriptor
;
78 extern const DLL_DESCRIPTOR WIN87EM_Descriptor
;
79 extern const DLL_DESCRIPTOR MMSYSTEM_Descriptor
;
80 extern const DLL_DESCRIPTOR SHELL_Descriptor
;
81 extern const DLL_DESCRIPTOR SOUND_Descriptor
;
82 extern const DLL_DESCRIPTOR KEYBOARD_Descriptor
;
83 extern const DLL_DESCRIPTOR WINSOCK_Descriptor
;
84 extern const DLL_DESCRIPTOR STRESS_Descriptor
;
85 extern const DLL_DESCRIPTOR SYSTEM_Descriptor
;
86 extern const DLL_DESCRIPTOR TOOLHELP_Descriptor
;
87 extern const DLL_DESCRIPTOR MOUSE_Descriptor
;
88 extern const DLL_DESCRIPTOR COMMDLG_Descriptor
;
89 extern const DLL_DESCRIPTOR OLE2_Descriptor
;
90 extern const DLL_DESCRIPTOR OLE2CONV_Descriptor
;
91 extern const DLL_DESCRIPTOR OLE2DISP_Descriptor
;
92 extern const DLL_DESCRIPTOR OLE2NLS_Descriptor
;
93 extern const DLL_DESCRIPTOR OLE2PROX_Descriptor
;
94 extern const DLL_DESCRIPTOR OLECLI_Descriptor
;
95 extern const DLL_DESCRIPTOR OLESVR_Descriptor
;
96 extern const DLL_DESCRIPTOR COMPOBJ_Descriptor
;
97 extern const DLL_DESCRIPTOR STORAGE_Descriptor
;
98 extern const DLL_DESCRIPTOR WPROCS_Descriptor
;
99 extern const DLL_DESCRIPTOR DDEML_Descriptor
;
100 extern const DLL_DESCRIPTOR LZEXPAND_Descriptor
;
101 extern const DLL_DESCRIPTOR VER_Descriptor
;
102 extern const DLL_DESCRIPTOR W32SYS_Descriptor
;
103 extern const DLL_DESCRIPTOR WING_Descriptor
;
107 extern const DLL_DESCRIPTOR ADVAPI32_Descriptor
;
108 extern const DLL_DESCRIPTOR COMCTL32_Descriptor
;
109 extern const DLL_DESCRIPTOR COMDLG32_Descriptor
;
110 extern const DLL_DESCRIPTOR CRTDLL_Descriptor
;
111 extern const DLL_DESCRIPTOR OLE32_Descriptor
;
112 extern const DLL_DESCRIPTOR GDI32_Descriptor
;
113 extern const DLL_DESCRIPTOR KERNEL32_Descriptor
;
114 extern const DLL_DESCRIPTOR LZ32_Descriptor
;
115 extern const DLL_DESCRIPTOR MPR_Descriptor
;
116 extern const DLL_DESCRIPTOR NTDLL_Descriptor
;
117 extern const DLL_DESCRIPTOR SHELL32_Descriptor
;
118 extern const DLL_DESCRIPTOR USER32_Descriptor
;
119 extern const DLL_DESCRIPTOR VERSION_Descriptor
;
120 extern const DLL_DESCRIPTOR WINMM_Descriptor
;
121 extern const DLL_DESCRIPTOR WINSPOOL_Descriptor
;
122 extern const DLL_DESCRIPTOR WSOCK32_Descriptor
;
124 /* Table of all built-in DLLs */
126 static BUILTIN_DLL BuiltinDLLs
[] =
129 { &KERNEL_Descriptor
, NULL
, DLL_FLAG_ALWAYS_USED
},
130 { &USER_Descriptor
, NULL
, DLL_FLAG_ALWAYS_USED
},
131 { &GDI_Descriptor
, NULL
, DLL_FLAG_ALWAYS_USED
},
132 { &SYSTEM_Descriptor
, NULL
, DLL_FLAG_ALWAYS_USED
},
133 { &WIN87EM_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
134 { &SHELL_Descriptor
, NULL
, 0 },
135 { &SOUND_Descriptor
, NULL
, 0 },
136 { &KEYBOARD_Descriptor
, NULL
, 0 },
137 { &WINSOCK_Descriptor
, NULL
, 0 },
138 { &STRESS_Descriptor
, NULL
, 0 },
139 { &MMSYSTEM_Descriptor
, NULL
, 0 },
140 { &TOOLHELP_Descriptor
, NULL
, 0 },
141 { &MOUSE_Descriptor
, NULL
, 0 },
142 { &COMMDLG_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
143 { &OLE2_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
144 { &OLE2CONV_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
145 { &OLE2DISP_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
146 { &OLE2NLS_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
147 { &OLE2PROX_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
148 { &OLECLI_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
149 { &OLESVR_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
150 { &COMPOBJ_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
151 { &STORAGE_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
152 { &WPROCS_Descriptor
, NULL
, DLL_FLAG_ALWAYS_USED
},
153 { &DDEML_Descriptor
, NULL
, DLL_FLAG_NOT_USED
},
154 { &LZEXPAND_Descriptor
, NULL
, 0 },
155 { &VER_Descriptor
, NULL
, 0 },
156 { &W32SYS_Descriptor
, NULL
, 0 },
157 { &WING_Descriptor
, NULL
, 0 },
159 { &ADVAPI32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
160 { &COMCTL32_Descriptor
, NULL
, DLL_FLAG_WIN32
| DLL_FLAG_NOT_USED
},
161 { &COMDLG32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
162 { &CRTDLL_Descriptor
, NULL
, DLL_FLAG_WIN32
},
163 { &OLE32_Descriptor
, NULL
, DLL_FLAG_WIN32
| DLL_FLAG_NOT_USED
},
164 { &GDI32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
165 { &KERNEL32_Descriptor
, NULL
, DLL_FLAG_WIN32
| DLL_FLAG_ALWAYS_USED
},
166 { &LZ32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
167 { &MPR_Descriptor
, NULL
, DLL_FLAG_WIN32
| DLL_FLAG_NOT_USED
},
168 { &NTDLL_Descriptor
, NULL
, DLL_FLAG_WIN32
},
169 { &SHELL32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
170 { &USER32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
171 { &VERSION_Descriptor
, NULL
, DLL_FLAG_WIN32
},
172 { &WINMM_Descriptor
, NULL
, DLL_FLAG_WIN32
},
173 { &WINSPOOL_Descriptor
, NULL
, DLL_FLAG_WIN32
},
174 { &WSOCK32_Descriptor
, NULL
, DLL_FLAG_WIN32
},
179 /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
180 #define FIRST_INTERRUPT_ORDINAL 100
182 /***********************************************************************
183 * BUILTIN_BuildDebugEntryPoints
185 * Build the table of relay-debugging entry points for a Win32 DLL.
187 static void BUILTIN_BuildDebugEntryPoints( BUILTIN_DLL
*dll
)
190 DEBUG_ENTRY_POINT
*entry
;
191 extern void RELAY_CallFrom32();
193 assert( !dll
->dbg_funcs
);
194 assert( dll
->flags
& DLL_FLAG_WIN32
);
195 dll
->dbg_funcs
= HeapAlloc( SystemHeap
, 0,
196 dll
->descr
->win32
.nb_funcs
* sizeof(DEBUG_ENTRY_POINT
) );
197 entry
= dll
->dbg_funcs
;
198 for (i
= 0; i
< dll
->descr
->win32
.nb_funcs
; i
++, entry
++)
200 BYTE args
= dll
->descr
->win32
.args
[i
];
201 entry
->call
= 0xe8; /* call */
204 case 0xfe: /* register func */
205 entry
->callfrom32
= (DWORD
)dll
->descr
->win32
.functions
[i
] -
207 entry
->ret
= 0x90; /* nop */
210 case 0xff: /* stub */
211 entry
->args
= 0xffff;
213 default: /* normal function (stdcall or cdecl) */
214 entry
->callfrom32
= (DWORD
)RELAY_CallFrom32
- (DWORD
)&entry
->ret
;
215 entry
->ret
= (args
& 0x80) ? 0xc3 : 0xc2; /* ret / ret $n */
216 entry
->args
= (args
& 0x7f) * sizeof(int);
223 /***********************************************************************
224 * BUILTIN_DoLoadModule16
226 * Load a built-in Win16 module. Helper function for BUILTIN_LoadModule
229 static HMODULE16
BUILTIN_DoLoadModule16( const WIN16_DESCRIPTOR
*descr
)
233 SEGTABLEENTRY
*pSegTable
;
235 HMODULE16 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, descr
->module_start
,
236 descr
->module_size
, 0,
237 FALSE
, FALSE
, FALSE
, NULL
);
238 if (!hModule
) return 0;
239 FarSetOwner( hModule
, hModule
);
241 dprintf_module( stddeb
, "Built-in %s: hmodule=%04x\n",
242 descr
->name
, hModule
);
243 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
244 pModule
->self
= hModule
;
246 /* Allocate the code segment */
248 pSegTable
= NE_SEG_TABLE( pModule
);
249 pSegTable
->selector
= GLOBAL_CreateBlock( GMEM_FIXED
, descr
->code_start
,
250 pSegTable
->minsize
, hModule
,
251 TRUE
, TRUE
, FALSE
, NULL
);
252 if (!pSegTable
->selector
) return 0;
255 /* Allocate the data segment */
257 minsize
= pSegTable
->minsize
? pSegTable
->minsize
: 0x10000;
258 minsize
+= pModule
->heap_size
;
259 if (minsize
> 0x10000) minsize
= 0x10000;
260 pSegTable
->selector
= GLOBAL_Alloc( GMEM_FIXED
, minsize
,
261 hModule
, FALSE
, FALSE
, FALSE
);
262 if (!pSegTable
->selector
) return 0;
263 if (pSegTable
->minsize
) memcpy( GlobalLock16( pSegTable
->selector
),
264 descr
->data_start
, pSegTable
->minsize
);
265 if (pModule
->heap_size
)
266 LocalInit( pSegTable
->selector
, pSegTable
->minsize
, minsize
);
268 MODULE_RegisterModule( pModule
);
273 /***********************************************************************
274 * BUILTIN_DoLoadModule32
276 * Load a built-in Win32 module. Helper function for BUILTIN_LoadModule
279 static HMODULE16
BUILTIN_DoLoadModule32( BUILTIN_DLL
*table
)
285 sprintf( ofs
.szPathName
, "%s.DLL", table
->descr
->name
);
286 hModule
= MODULE_CreateDummyModule( &ofs
);
287 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
288 pModule
->pe_module
= (PE_MODULE
*)table
;
289 pModule
->flags
= NE_FFLAGS_SINGLEDATA
| NE_FFLAGS_BUILTIN
|
290 NE_FFLAGS_LIBMODULE
| NE_FFLAGS_WIN32
;
291 if (debugging_relay
) BUILTIN_BuildDebugEntryPoints( table
);
296 /***********************************************************************
299 * Load all built-in modules marked as 'always used'.
301 BOOL32
BUILTIN_Init(void)
308 for (dll
= BuiltinDLLs
; dll
->descr
; dll
++)
310 if (!(dll
->flags
& DLL_FLAG_ALWAYS_USED
)) continue;
311 if (dll
->flags
& DLL_FLAG_WIN32
)
313 if (!BUILTIN_DoLoadModule32( dll
)) return FALSE
;
317 if (!BUILTIN_DoLoadModule16( &dll
->descr
->win16
)) return FALSE
;
321 /* Set the USER and GDI heap selectors */
323 pModule
= MODULE_GetPtr( GetModuleHandle16( "USER" ));
324 USER_HeapSel
= (NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1)->selector
;
325 pModule
= MODULE_GetPtr( GetModuleHandle16( "GDI" ));
326 GDI_HeapSel
= (NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1)->selector
;
328 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
330 hModule
= GetModuleHandle16( "KERNEL" );
331 MODULE_SetEntryPoint( hModule
, 178, GetWinFlags() );
333 /* Initialize the real-mode selector entry points */
335 DOSMEM_InitExports( hModule
);
337 /* Set interrupt vectors from entry points in WPROCS.DLL */
339 hModule
= GetModuleHandle16( "WPROCS" );
340 for (vector
= 0; vector
< 256; vector
++)
342 FARPROC16 proc
= MODULE_GetEntryPoint( hModule
,
343 FIRST_INTERRUPT_ORDINAL
+vector
);
345 INT_SetHandler( vector
, proc
);
352 /***********************************************************************
355 * Load a built-in module. If the 'force' parameter is FALSE, we only
356 * load the module if it has not been disabled via the -dll option.
358 HMODULE16
BUILTIN_LoadModule( LPCSTR name
, BOOL32 force
)
361 char dllname
[16], *p
;
363 /* Fix the name in case we have a full path and extension */
365 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
366 lstrcpyn32A( dllname
, name
, sizeof(dllname
) );
367 if ((p
= strrchr( dllname
, '.' ))) *p
= '\0';
369 for (table
= BuiltinDLLs
; table
->descr
; table
++)
370 if (!lstrcmpi32A( table
->descr
->name
, dllname
)) break;
371 if (!table
->descr
) return 0;
372 if ((table
->flags
& DLL_FLAG_NOT_USED
) && !force
) return 0;
374 if (table
->flags
& DLL_FLAG_WIN32
)
375 return BUILTIN_DoLoadModule32( table
);
377 return BUILTIN_DoLoadModule16( &table
->descr
->win16
);
381 /***********************************************************************
382 * BUILTIN_GetEntryPoint16
384 * Return the ordinal and name corresponding to a CS:IP address.
385 * This is used only by relay debugging.
387 LPCSTR
BUILTIN_GetEntryPoint16( WORD cs
, WORD ip
, WORD
*pOrd
)
389 static char buffer
[80];
390 WORD ordinal
, i
, max_offset
;
394 if (!(pModule
= MODULE_GetPtr( FarGetOwner( GlobalHandle16(cs
) ))))
397 /* Search for the ordinal */
399 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
411 case 1: /* code segment */
417 if ((*(WORD
*)p
<= ip
) && (*(WORD
*)p
>= max_offset
))
419 max_offset
= *(WORD
*)p
;
426 case 0xff: /* moveable (should not happen in built-in modules) */
427 fprintf( stderr
, "Built-in module has moveable entry\n" );
431 default: /* other segment */
438 /* Search for the name in the resident names table */
439 /* (built-in modules have no non-resident table) */
441 p
= (BYTE
*)pModule
+ pModule
->name_table
;
444 p
+= *p
+ 1 + sizeof(WORD
);
445 if (*(WORD
*)(p
+ *p
+ 1) == *pOrd
) break;
448 sprintf( buffer
, "%.*s.%d: %.*s",
449 *((BYTE
*)pModule
+ pModule
->name_table
),
450 (char *)pModule
+ pModule
->name_table
+ 1,
451 *pOrd
, *p
, (char *)(p
+ 1) );
456 /***********************************************************************
457 * BUILTIN_GetEntryPoint32
459 * Return the name of the DLL entry point corresponding
460 * to a relay entry point address. This is used only by relay debugging.
462 * This function _must_ return the real entry point to call
463 * after the debug info is printed.
465 FARPROC32
BUILTIN_GetEntryPoint32( char *buffer
, void *relay
)
469 const WIN32_DESCRIPTOR
*descr
;
471 /* First find the module */
473 for (dll
= BuiltinDLLs
; dll
->descr
; dll
++)
474 if ((dll
->flags
& DLL_FLAG_WIN32
) &&
475 ((void *)dll
->dbg_funcs
<= relay
) &&
476 ((void *)(dll
->dbg_funcs
+ dll
->descr
->win32
.nb_funcs
) > relay
))
479 descr
= &dll
->descr
->win32
;
481 /* Now find the function */
483 ordinal
= ((DWORD
)relay
-(DWORD
)dll
->dbg_funcs
) / sizeof(DEBUG_ENTRY_POINT
);
484 ordinal
+= descr
->base
;
485 for (i
= 0; i
< descr
->nb_names
; i
++)
486 if (descr
->ordinals
[i
] == ordinal
) break;
487 assert( i
< descr
->nb_names
);
489 sprintf( buffer
, "%s.%d: %s", descr
->name
, ordinal
, descr
->names
[i
] );
490 return (FARPROC32
)descr
->functions
[ordinal
- descr
->base
];
494 /***********************************************************************
495 * BUILTIN_GetProcAddress32
497 * Implementation of GetProcAddress() for built-in Win32 modules.
498 * FIXME: this should be unified with the real GetProcAddress32().
500 FARPROC32
BUILTIN_GetProcAddress32( NE_MODULE
*pModule
, LPCSTR function
)
502 BUILTIN_DLL
*dll
= (BUILTIN_DLL
*)pModule
->pe_module
;
503 const WIN32_DESCRIPTOR
*info
= &dll
->descr
->win32
;
506 if (!dll
) return NULL
;
508 if (HIWORD(function
)) /* Find function by name */
512 dprintf_module( stddeb
, "Looking for function %s in %s\n",
513 function
, dll
->descr
->name
);
514 for (i
= 0; i
< info
->nb_names
; i
++)
515 if (!strcmp( function
, info
->names
[i
] ))
517 ordinal
= info
->ordinals
[i
];
520 if (i
>= info
->nb_names
) return NULL
; /* not found */
522 else /* Find function by ordinal */
524 ordinal
= LOWORD(function
);
525 dprintf_module( stddeb
, "Looking for ordinal %d in %s\n",
526 ordinal
, dll
->descr
->name
);
527 if ((ordinal
< info
->base
) || (ordinal
>= info
->base
+ info
->nb_funcs
))
528 return NULL
; /* not found */
530 if (dll
->dbg_funcs
&& (dll
->dbg_funcs
[ordinal
-info
->base
].args
!= 0xffff))
531 return (FARPROC32
)&dll
->dbg_funcs
[ordinal
- info
->base
];
532 return (FARPROC32
)info
->functions
[ordinal
- info
->base
];
536 /**********************************************************************
537 * BUILTIN_DefaultIntHandler
539 * Default interrupt handler.
541 void BUILTIN_DefaultIntHandler( CONTEXT
*context
)
544 STACK16FRAME
*frame
= CURRENT_STACK16
;
545 BUILTIN_GetEntryPoint16( frame
->entry_cs
, frame
->entry_ip
, &ordinal
);
546 INT_BARF( context
, ordinal
- FIRST_INTERRUPT_ORDINAL
);
550 /***********************************************************************
551 * BUILTIN_ParseDLLOptions
553 * Set runtime DLL usage flags
555 BOOL32
BUILTIN_ParseDLLOptions( const char *str
)
562 while (*str
&& isspace(*str
)) str
++;
563 if (!*str
) return TRUE
;
564 if ((*str
!= '+') && (*str
!= '-')) return FALSE
;
566 if (!(p
= strchr( str
, ',' ))) p
= str
+ strlen(str
);
567 while ((p
> str
) && isspace(p
[-1])) p
--;
568 if (p
== str
) return FALSE
;
569 for (dll
= BuiltinDLLs
; dll
->descr
; dll
++)
571 if (!lstrncmpi32A( str
, dll
->descr
->name
, (int)(p
- str
) ))
575 if (dll
->flags
& DLL_FLAG_ALWAYS_USED
) return FALSE
;
576 dll
->flags
|= DLL_FLAG_NOT_USED
;
578 else dll
->flags
&= ~DLL_FLAG_NOT_USED
;
582 if (!dll
->descr
) return FALSE
;
584 while (*str
&& (isspace(*str
) || (*str
== ','))) str
++;
590 /***********************************************************************
593 * Print the list of built-in DLLs that can be disabled.
595 void BUILTIN_PrintDLLs(void)
600 for (i
= 0, dll
= BuiltinDLLs
; dll
->descr
; dll
++)
602 if (!(dll
->flags
& DLL_FLAG_ALWAYS_USED
))
603 fprintf( stderr
, "%-9s%c", dll
->descr
->name
,
604 ((++i
) % 8) ? ' ' : '\n' );
606 fprintf(stderr
,"\n");