2 * Win32 builtin functions
4 * Copyright 1997 Alexandre Julliard
11 #include "builtin32.h"
20 DECLARE_DEBUG_CHANNEL(relay
)
21 DECLARE_DEBUG_CHANNEL(win32
)
25 BYTE call
; /* 0xe8 call callfrom32 (relative) */
26 DWORD callfrom32 WINE_PACKED
; /* RELAY_CallFrom32 relative addr */
27 BYTE ret
; /* 0xc2 ret $n or 0xc3 ret */
28 WORD args
; /* nb of args to remove from the stack */
33 const BUILTIN32_DESCRIPTOR
*descr
; /* DLL descriptor */
34 BOOL used
; /* Used by default */
38 extern const BUILTIN32_DESCRIPTOR ADVAPI32_Descriptor
;
39 extern const BUILTIN32_DESCRIPTOR AVIFIL32_Descriptor
;
40 extern const BUILTIN32_DESCRIPTOR COMCTL32_Descriptor
;
41 extern const BUILTIN32_DESCRIPTOR COMDLG32_Descriptor
;
42 extern const BUILTIN32_DESCRIPTOR CRTDLL_Descriptor
;
43 extern const BUILTIN32_DESCRIPTOR DCIMAN32_Descriptor
;
44 extern const BUILTIN32_DESCRIPTOR DDRAW_Descriptor
;
45 extern const BUILTIN32_DESCRIPTOR DINPUT_Descriptor
;
46 extern const BUILTIN32_DESCRIPTOR DPLAY_Descriptor
;
47 extern const BUILTIN32_DESCRIPTOR DPLAYX_Descriptor
;
48 extern const BUILTIN32_DESCRIPTOR DSOUND_Descriptor
;
49 extern const BUILTIN32_DESCRIPTOR GDI32_Descriptor
;
50 extern const BUILTIN32_DESCRIPTOR IMAGEHLP_Descriptor
;
51 extern const BUILTIN32_DESCRIPTOR IMM32_Descriptor
;
52 extern const BUILTIN32_DESCRIPTOR KERNEL32_Descriptor
;
53 extern const BUILTIN32_DESCRIPTOR LZ32_Descriptor
;
54 extern const BUILTIN32_DESCRIPTOR MPR_Descriptor
;
55 extern const BUILTIN32_DESCRIPTOR MSACM32_Descriptor
;
56 extern const BUILTIN32_DESCRIPTOR MSNET32_Descriptor
;
57 extern const BUILTIN32_DESCRIPTOR MSVFW32_Descriptor
;
58 extern const BUILTIN32_DESCRIPTOR NTDLL_Descriptor
;
59 extern const BUILTIN32_DESCRIPTOR OLE32_Descriptor
;
60 extern const BUILTIN32_DESCRIPTOR OLEAUT32_Descriptor
;
61 extern const BUILTIN32_DESCRIPTOR OLECLI32_Descriptor
;
62 extern const BUILTIN32_DESCRIPTOR OLEDLG_Descriptor
;
63 extern const BUILTIN32_DESCRIPTOR OLESVR32_Descriptor
;
64 extern const BUILTIN32_DESCRIPTOR PSAPI_Descriptor
;
65 extern const BUILTIN32_DESCRIPTOR RASAPI32_Descriptor
;
66 extern const BUILTIN32_DESCRIPTOR SHELL32_Descriptor
;
67 extern const BUILTIN32_DESCRIPTOR TAPI32_Descriptor
;
68 extern const BUILTIN32_DESCRIPTOR USER32_Descriptor
;
69 extern const BUILTIN32_DESCRIPTOR VERSION_Descriptor
;
70 extern const BUILTIN32_DESCRIPTOR W32SKRNL_Descriptor
;
71 extern const BUILTIN32_DESCRIPTOR WINMM_Descriptor
;
72 extern const BUILTIN32_DESCRIPTOR WINSPOOL_Descriptor
;
73 extern const BUILTIN32_DESCRIPTOR WNASPI32_Descriptor
;
74 extern const BUILTIN32_DESCRIPTOR WOW32_Descriptor
;
75 extern const BUILTIN32_DESCRIPTOR WSOCK32_Descriptor
;
77 static BUILTIN32_DLL BuiltinDLLs
[] =
79 { &ADVAPI32_Descriptor
, TRUE
},
80 { &AVIFIL32_Descriptor
, FALSE
},
81 { &COMCTL32_Descriptor
, FALSE
},
82 { &COMDLG32_Descriptor
, TRUE
},
83 { &CRTDLL_Descriptor
, TRUE
},
84 { &DCIMAN32_Descriptor
, FALSE
},
85 { &DDRAW_Descriptor
, TRUE
},
86 { &DINPUT_Descriptor
, TRUE
},
87 { &DPLAY_Descriptor
, FALSE
},
88 { &DPLAYX_Descriptor
, FALSE
},
89 { &DSOUND_Descriptor
, TRUE
},
90 { &GDI32_Descriptor
, TRUE
},
91 { &IMAGEHLP_Descriptor
, FALSE
},
92 { &IMM32_Descriptor
, FALSE
},
93 { &KERNEL32_Descriptor
, TRUE
},
94 { &LZ32_Descriptor
, TRUE
},
95 { &MPR_Descriptor
, TRUE
},
96 { &MSACM32_Descriptor
, FALSE
},
97 { &MSNET32_Descriptor
, FALSE
},
98 { &MSVFW32_Descriptor
, TRUE
},
99 { &NTDLL_Descriptor
, TRUE
},
100 { &OLE32_Descriptor
, FALSE
},
101 { &OLEAUT32_Descriptor
, FALSE
},
102 { &OLECLI32_Descriptor
, FALSE
},
103 { &OLEDLG_Descriptor
, FALSE
},
104 { &OLESVR32_Descriptor
, FALSE
},
105 { &PSAPI_Descriptor
, FALSE
},
106 { &RASAPI32_Descriptor
, FALSE
},
107 { &SHELL32_Descriptor
, TRUE
},
108 { &TAPI32_Descriptor
, FALSE
},
109 { &USER32_Descriptor
, TRUE
},
110 { &VERSION_Descriptor
, TRUE
},
111 { &W32SKRNL_Descriptor
, TRUE
},
112 { &WINMM_Descriptor
, TRUE
},
113 { &WINSPOOL_Descriptor
, TRUE
},
114 { &WNASPI32_Descriptor
, TRUE
},
115 { &WOW32_Descriptor
, TRUE
},
116 { &WSOCK32_Descriptor
, TRUE
},
121 extern void RELAY_CallFrom32();
123 /***********************************************************************
124 * BUILTIN32_DoLoadImage
126 * Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage.
128 static HMODULE
BUILTIN32_DoLoadImage( BUILTIN32_DLL
*dll
)
131 IMAGE_DATA_DIRECTORY
*dir
;
132 IMAGE_DOS_HEADER
*dos
;
133 IMAGE_NT_HEADERS
*nt
;
134 IMAGE_SECTION_HEADER
*sec
;
135 IMAGE_EXPORT_DIRECTORY
*exp
;
138 DEBUG_ENTRY_POINT
*debug
;
142 /* Allocate the module */
144 size
= (sizeof(IMAGE_DOS_HEADER
)
145 + sizeof(IMAGE_NT_HEADERS
)
146 + 2 * sizeof(IMAGE_SECTION_HEADER
)
147 + sizeof(IMAGE_EXPORT_DIRECTORY
)
148 + dll
->descr
->nb_funcs
* sizeof(LPVOID
)
149 + dll
->descr
->nb_names
* sizeof(LPSTR
));
151 if (WARN_ON(relay
) || TRACE_ON(relay
))
152 size
+= dll
->descr
->nb_funcs
* sizeof(DEBUG_ENTRY_POINT
);
154 addr
= VirtualAlloc( NULL
, size
, MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
156 dos
= (IMAGE_DOS_HEADER
*)addr
;
157 nt
= (IMAGE_NT_HEADERS
*)(dos
+ 1);
158 sec
= (IMAGE_SECTION_HEADER
*)(nt
+ 1);
159 exp
= (IMAGE_EXPORT_DIRECTORY
*)(sec
+ 2);
160 funcs
= (LPVOID
*)(exp
+ 1);
161 names
= (LPSTR
*)(funcs
+ dll
->descr
->nb_funcs
);
162 debug
= (DEBUG_ENTRY_POINT
*)(names
+ dll
->descr
->nb_names
);
164 /* Build the DOS and NT headers */
166 dos
->e_magic
= IMAGE_DOS_SIGNATURE
;
167 dos
->e_lfanew
= sizeof(*dos
);
169 nt
->Signature
= IMAGE_NT_SIGNATURE
;
170 nt
->FileHeader
.Machine
= IMAGE_FILE_MACHINE_I386
;
171 nt
->FileHeader
.NumberOfSections
= 2; /* exports + code */
172 nt
->FileHeader
.SizeOfOptionalHeader
= sizeof(nt
->OptionalHeader
);
173 nt
->FileHeader
.Characteristics
= IMAGE_FILE_DLL
;
175 nt
->OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR_MAGIC
;
176 nt
->OptionalHeader
.SizeOfCode
= 0x1000;
177 nt
->OptionalHeader
.SizeOfInitializedData
= 0;
178 nt
->OptionalHeader
.SizeOfUninitializedData
= 0;
179 nt
->OptionalHeader
.ImageBase
= (DWORD
)addr
;
180 nt
->OptionalHeader
.SectionAlignment
= 0x1000;
181 nt
->OptionalHeader
.FileAlignment
= 0x1000;
182 nt
->OptionalHeader
.MajorOperatingSystemVersion
= 1;
183 nt
->OptionalHeader
.MinorOperatingSystemVersion
= 0;
184 nt
->OptionalHeader
.MajorSubsystemVersion
= 4;
185 nt
->OptionalHeader
.MinorSubsystemVersion
= 0;
186 nt
->OptionalHeader
.SizeOfImage
= size
;
187 nt
->OptionalHeader
.SizeOfHeaders
= (BYTE
*)exp
- addr
;
188 nt
->OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
189 if (dll
->descr
->dllentrypoint
)
190 nt
->OptionalHeader
.AddressOfEntryPoint
= (DWORD
)dll
->descr
->dllentrypoint
- (DWORD
)addr
;
192 /* Build the export directory */
194 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
195 dir
->VirtualAddress
= (BYTE
*)exp
- addr
;
196 dir
->Size
= sizeof(*exp
)
197 + dll
->descr
->nb_funcs
* sizeof(LPVOID
)
198 + dll
->descr
->nb_names
* sizeof(LPSTR
);
200 /* Build the exports section */
202 strcpy( sec
->Name
, ".edata" );
203 sec
->Misc
.VirtualSize
= dir
->Size
;
204 sec
->VirtualAddress
= (BYTE
*)exp
- addr
;
205 sec
->SizeOfRawData
= dir
->Size
;
206 sec
->PointerToRawData
= (BYTE
*)exp
- addr
;
207 sec
->Characteristics
= (IMAGE_SCN_CNT_INITIALIZED_DATA
|
208 IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_MEM_READ
|
209 IMAGE_SCN_MEM_WRITE
);
211 /* Build the code section */
214 strcpy( sec
->Name
, ".code" );
215 sec
->SizeOfRawData
= 0;
217 if (WARN_ON(relay
) || TRACE_ON(relay
))
218 sec
->SizeOfRawData
+= dll
->descr
->nb_funcs
* sizeof(DEBUG_ENTRY_POINT
);
220 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
221 sec
->VirtualAddress
= (BYTE
*)debug
- addr
;
222 sec
->PointerToRawData
= (BYTE
*)debug
- addr
;
223 sec
->Characteristics
= (IMAGE_SCN_CNT_INITIALIZED_DATA
|
224 IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_MEM_READ
);
226 /* Build the exports section data */
228 exp
->Name
= ((BYTE
*)dll
->descr
->name
) - addr
; /*??*/
229 exp
->Base
= dll
->descr
->base
;
230 exp
->NumberOfFunctions
= dll
->descr
->nb_funcs
;
231 exp
->NumberOfNames
= dll
->descr
->nb_names
;
232 exp
->AddressOfFunctions
= (LPDWORD
*)((BYTE
*)funcs
- addr
);
233 exp
->AddressOfNames
= (LPDWORD
*)((BYTE
*)names
- addr
);
234 exp
->AddressOfNameOrdinals
= (LPWORD
*)((BYTE
*)dll
->descr
->ordinals
- addr
);
236 /* Build the funcs table */
238 for (i
= 0; i
< dll
->descr
->nb_funcs
; i
++, funcs
++, debug
++)
240 BYTE args
= dll
->descr
->args
[i
];
243 if (!dll
->descr
->functions
[i
]) continue;
244 *funcs
= (LPVOID
)((BYTE
*)dll
->descr
->functions
[i
] - addr
);
246 if (!(WARN_ON(relay
) || TRACE_ON(relay
))) continue;
247 for (j
=0;j
<dll
->descr
->nb_names
;j
++)
248 if (dll
->descr
->ordinals
[j
] == i
)
250 if (j
<dll
->descr
->nb_names
) {
251 if (dll
->descr
->names
[j
]) {
253 sprintf(buffer
,"%s.%d: %s",dll
->descr
->name
,i
,dll
->descr
->names
[j
]);
254 if (!RELAY_ShowDebugmsgRelay(buffer
))
260 case 0xfe: /* register func */
262 debug
->callfrom32
= (DWORD
)dll
->descr
->functions
[i
] -
264 debug
->ret
= 0x90; /* nop */
266 *funcs
= (LPVOID
)((BYTE
*)debug
- addr
);
268 case 0xff: /* stub or extern */
270 default: /* normal function (stdcall or cdecl) */
271 if (TRACE_ON(relay
)) {
272 debug
->call
= 0xe8; /* lcall relative */
273 debug
->callfrom32
= (DWORD
)RELAY_CallFrom32
-
276 debug
->call
= 0xe9; /* ljmp relative */
277 debug
->callfrom32
= (DWORD
)dll
->descr
->functions
[i
] -
280 debug
->ret
= (args
& 0x80) ? 0xc3 : 0xc2; /*ret/ret $n*/
281 debug
->args
= (args
& 0x7f) * sizeof(int);
282 *funcs
= (LPVOID
)((BYTE
*)debug
- addr
);
285 #endif /* __i386__ */
288 /* Build the names table */
290 for (i
= 0; i
< exp
->NumberOfNames
; i
++, names
++)
291 if (dll
->descr
->names
[i
])
292 *names
= (LPSTR
)((BYTE
*)dll
->descr
->names
[i
] - addr
);
294 return (HMODULE
)addr
;
297 /***********************************************************************
298 * BUILTIN32_LoadImage
300 * Load a built-in module. If the 'force' parameter is FALSE, we only
301 * load the module if it has not been disabled via the -dll option.
303 HMODULE
BUILTIN32_LoadImage( LPCSTR name
, OFSTRUCT
*ofs
, BOOL force
)
305 BUILTIN32_DLL
*table
;
306 char dllname
[16], *p
;
308 /* Fix the name in case we have a full path and extension */
310 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
311 lstrcpynA( dllname
, name
, sizeof(dllname
) );
312 if ((p
= strrchr( dllname
, '.' ))) *p
= '\0';
314 for (table
= BuiltinDLLs
; table
->descr
; table
++)
315 if (!lstrcmpiA( table
->descr
->name
, dllname
)) break;
316 if (!table
->descr
) return 0;
319 if (!force
) return 0;
320 table
->used
= TRUE
; /* So next time we use it at once */
323 sprintf( ofs
->szPathName
, "%s.DLL", table
->descr
->name
);
324 return BUILTIN32_DoLoadImage( table
);
328 /***********************************************************************
329 * BUILTIN32_LoadLibraryExA
331 * Partly copied from the original PE_ version.
333 * Note: This implementation is not very nice and should be one with
334 * the BUILTIN32_LoadImage function. But, we don't care too much
335 * because this code will obsolete itself shortly when we get the
336 * modularization of wine implemented (BS 05-Mar-1999).
338 WINE_MODREF
*BUILTIN32_LoadLibraryExA(LPCSTR path
, DWORD flags
, DWORD
*err
)
340 LPCSTR modName
= NULL
;
346 char dllname
[256], *p
;
348 /* Append .DLL to name if no extension present */
349 strcpy( dllname
, path
);
350 if (!(p
= strrchr( dllname
, '.')) || strchr( p
, '/' ) || strchr( p
, '\\'))
351 strcat( dllname
, ".DLL" );
353 hModule32
= BUILTIN32_LoadImage( path
, &ofs
, TRUE
);
356 *err
= ERROR_FILE_NOT_FOUND
;
360 /* Create 16-bit dummy module */
361 if ((hModule16
= MODULE_CreateDummyModule( &ofs
, modName
)) < 32)
363 *err
= (DWORD
)hModule16
;
364 return NULL
; /* FIXME: Should unload the builtin module */
367 pModule
= (NE_MODULE
*)GlobalLock16( hModule16
);
368 pModule
->flags
= NE_FFLAGS_LIBMODULE
| NE_FFLAGS_SINGLEDATA
| NE_FFLAGS_WIN32
| NE_FFLAGS_BUILTIN
;
369 pModule
->module32
= hModule32
;
371 /* Create 32-bit MODREF */
372 if ( !(wm
= PE_CreateModule( hModule32
, &ofs
, flags
, TRUE
)) )
374 ERR(win32
,"can't load %s\n",ofs
.szPathName
);
375 FreeLibrary16( hModule16
); /* FIXME: Should unload the builtin module */
376 *err
= ERROR_OUTOFMEMORY
;
380 if (wm
->binfmt
.pe
.pe_export
)
381 SNOOP_RegisterDLL(wm
->module
,wm
->modname
,wm
->binfmt
.pe
.pe_export
->NumberOfFunctions
);
388 /***********************************************************************
389 * BUILTIN32_UnloadLibrary
391 * Unload the built-in library and free the modref.
393 void BUILTIN32_UnloadLibrary(WINE_MODREF
*wm
)
395 /* FIXME: do something here */
399 /***********************************************************************
400 * BUILTIN32_GetEntryPoint
402 * Return the name of the DLL entry point corresponding
403 * to a relay entry point address. This is used only by relay debugging.
405 * This function _must_ return the real entry point to call
406 * after the debug info is printed.
408 ENTRYPOINT32
BUILTIN32_GetEntryPoint( char *buffer
, void *relay
,
409 unsigned int *typemask
)
415 /* First find the module */
417 for (dll
= BuiltinDLLs
; dll
->descr
; dll
++)
419 && ((hModule
= GetModuleHandleA(dll
->descr
->name
)) != 0))
421 IMAGE_SECTION_HEADER
*sec
= PE_SECTIONS(hModule
);
422 DEBUG_ENTRY_POINT
*debug
=
423 (DEBUG_ENTRY_POINT
*)((DWORD
)hModule
+ sec
[1].VirtualAddress
);
424 DEBUG_ENTRY_POINT
*func
= (DEBUG_ENTRY_POINT
*)relay
;
426 if (debug
<= func
&& func
< debug
+ dll
->descr
->nb_funcs
)
428 ordinal
= func
- debug
;
434 return (ENTRYPOINT32
)NULL
;
436 /* Now find the function */
438 for (i
= 0; i
< dll
->descr
->nb_names
; i
++)
439 if (dll
->descr
->ordinals
[i
] == ordinal
) break;
440 assert( i
< dll
->descr
->nb_names
);
442 sprintf( buffer
, "%s.%d: %s", dll
->descr
->name
, ordinal
+ dll
->descr
->base
,
443 dll
->descr
->names
[i
] );
444 *typemask
= dll
->descr
->argtypes
[ordinal
];
445 return dll
->descr
->functions
[ordinal
];
448 /***********************************************************************
449 * BUILTIN32_SwitchRelayDebug
451 * FIXME: enhance to do it module relative.
453 void BUILTIN32_SwitchRelayDebug(BOOL onoff
) {
459 if (!(TRACE_ON(relay
) || WARN_ON(relay
)))
461 for (dll
= BuiltinDLLs
; dll
->descr
; dll
++) {
462 IMAGE_SECTION_HEADER
*sec
;
463 DEBUG_ENTRY_POINT
*debug
;
464 if (!dll
->used
|| !(hModule
= GetModuleHandleA(dll
->descr
->name
)))
467 sec
= PE_SECTIONS(hModule
);
468 debug
= (DEBUG_ENTRY_POINT
*)((DWORD
)hModule
+ sec
[1].VirtualAddress
);
469 for (i
= 0; i
< dll
->descr
->nb_funcs
; i
++,debug
++) {
470 if (!dll
->descr
->functions
[i
]) continue;
471 if ((dll
->descr
->args
[i
]==0xff) || (dll
->descr
->args
[i
]==0xfe))
474 debug
->call
= 0xe8; /* lcall relative */
475 debug
->callfrom32
= (DWORD
)RELAY_CallFrom32
-
478 debug
->call
= 0xe9; /* ljmp relative */
479 debug
->callfrom32
= (DWORD
)dll
->descr
->functions
[i
] -
484 #endif /* __i386__ */
488 /***********************************************************************
489 * BUILTIN32_Unimplemented
491 * This function is called for unimplemented 32-bit entry points (declared
492 * as 'stub' in the spec file).
494 void BUILTIN32_Unimplemented( const BUILTIN32_DESCRIPTOR
*descr
, int ordinal
)
496 const char *func_name
= "???";
499 __RESTORE_ES
; /* Just in case */
501 for (i
= 0; i
< descr
->nb_names
; i
++)
502 if (descr
->ordinals
[i
] + descr
->base
== ordinal
) break;
503 if (i
< descr
->nb_names
) func_name
= descr
->names
[i
];
505 MSG( "No handler for Win32 routine %s.%d: %s",
506 descr
->name
, ordinal
, func_name
);
508 MSG( " (called from %p)", __builtin_return_address(1) );