2 * Win32 builtin functions
4 * Copyright 1997 Alexandre Julliard
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_MMAN_H
22 #include "wine/winbase16.h"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(module
);
33 DECLARE_DEBUG_CHANNEL(relay
);
40 IMAGE_RESOURCE_DATA_ENTRY
*entries
;
47 const IMAGE_NT_HEADERS
*nt
; /* NT header */
48 const char *filename
; /* DLL file name */
49 } BUILTIN32_DESCRIPTOR
;
51 extern void RELAY_SetupDLL( const char *module
);
53 static BUILTIN32_DESCRIPTOR builtin_dlls
[MAX_DLLS
];
57 /***********************************************************************
60 void *BUILTIN32_dlopen( const char *name
)
65 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
66 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
67 sprintf( buffer
, "lib%s", name
);
68 for (p
= buffer
; *p
; p
++) *p
= tolower(*p
);
69 if ((p
= strrchr( buffer
, '.' )) && (!strcmp( p
, ".dll" ) || !strcmp( p
, ".exe" ))) *p
= 0;
70 strcat( buffer
, ".so" );
72 if (!(handle
= ELFDLL_dlopen( buffer
, RTLD_NOW
)))
76 p
= strchr(pErr
, ':');
78 (!strncmp(p
, ": undefined symbol", 18))) /* undef symbol -> ERR() */
79 ERR("failed to load %s: %s\n", buffer
, pErr
);
80 else /* WARN() for libraries that are supposed to be native */
81 WARN("failed to load %s: %s\n", buffer
, pErr
);
89 /***********************************************************************
92 int BUILTIN32_dlclose( void *handle
)
95 /* FIXME: should unregister descriptors first */
96 /* return dlclose( handle ); */
102 /***********************************************************************
105 * Adjust an array of pointers to make them into RVAs.
107 static inline void fixup_rva_ptrs( void *array
, void *base
, int count
)
109 void **ptr
= (void **)array
;
112 if (*ptr
) *ptr
= (void *)((char *)*ptr
- (char *)base
);
118 /***********************************************************************
119 * BUILTIN32_DoLoadImage
121 * Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage.
123 static HMODULE
BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR
*descr
)
125 IMAGE_DATA_DIRECTORY
*dir
;
126 IMAGE_DOS_HEADER
*dos
;
127 IMAGE_NT_HEADERS
*nt
;
128 IMAGE_SECTION_HEADER
*sec
;
129 INT i
, size
, nb_sections
;
130 BYTE
*addr
, *code_start
, *data_start
;
131 int page_size
= VIRTUAL_GetPageSize();
133 /* Allocate the module */
135 nb_sections
= 2; /* code + data */
137 size
= (sizeof(IMAGE_DOS_HEADER
)
138 + sizeof(IMAGE_NT_HEADERS
)
139 + nb_sections
* sizeof(IMAGE_SECTION_HEADER
));
141 assert( size
<= page_size
);
143 if (descr
->nt
->OptionalHeader
.ImageBase
)
145 void *base
= (void *)descr
->nt
->OptionalHeader
.ImageBase
;
146 if ((addr
= VIRTUAL_mmap( -1, base
, page_size
, 0,
147 PROT_READ
|PROT_WRITE
, MAP_FIXED
)) != base
)
149 ERR("failed to map over PE header for %s at %p\n", descr
->filename
, base
);
155 if (!(addr
= VirtualAlloc( NULL
, page_size
, MEM_COMMIT
, PAGE_READWRITE
))) return 0;
158 dos
= (IMAGE_DOS_HEADER
*)addr
;
159 nt
= (IMAGE_NT_HEADERS
*)(dos
+ 1);
160 sec
= (IMAGE_SECTION_HEADER
*)(nt
+ 1);
161 code_start
= addr
+ page_size
;
164 data_start
= code_start
+ page_size
;
166 /* Build the DOS and NT headers */
168 dos
->e_magic
= IMAGE_DOS_SIGNATURE
;
169 dos
->e_lfanew
= sizeof(*dos
);
173 nt
->FileHeader
.NumberOfSections
= nb_sections
;
174 nt
->OptionalHeader
.SizeOfCode
= data_start
- code_start
;
175 nt
->OptionalHeader
.SizeOfInitializedData
= 0;
176 nt
->OptionalHeader
.SizeOfUninitializedData
= 0;
177 nt
->OptionalHeader
.ImageBase
= (DWORD
)addr
;
179 fixup_rva_ptrs( &nt
->OptionalHeader
.AddressOfEntryPoint
, addr
, 1 );
181 /* Build the code section */
183 strcpy( sec
->Name
, ".text" );
184 sec
->SizeOfRawData
= data_start
- code_start
;
185 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
186 sec
->VirtualAddress
= code_start
- addr
;
187 sec
->PointerToRawData
= code_start
- addr
;
188 sec
->Characteristics
= (IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_MEM_READ
);
191 /* Build the data section */
193 strcpy( sec
->Name
, ".data" );
194 sec
->SizeOfRawData
= 0;
195 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
196 sec
->VirtualAddress
= data_start
- addr
;
197 sec
->PointerToRawData
= data_start
- addr
;
198 sec
->Characteristics
= (IMAGE_SCN_CNT_INITIALIZED_DATA
|
199 IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_READ
);
202 /* Build the import directory */
204 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
];
207 IMAGE_IMPORT_DESCRIPTOR
*imports
= (void *)dir
->VirtualAddress
;
208 fixup_rva_ptrs( &dir
->VirtualAddress
, addr
, 1 );
209 /* we can fixup everything at once since we only have pointers and 0 values */
210 fixup_rva_ptrs( imports
, addr
, dir
->Size
/ sizeof(void*) );
213 /* Build the resource directory */
215 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_RESOURCE_DIRECTORY
];
216 if (dir
->VirtualAddress
)
218 BUILTIN32_RESOURCE
*rsrc
= (BUILTIN32_RESOURCE
*)dir
->VirtualAddress
;
219 IMAGE_RESOURCE_DATA_ENTRY
*rdep
= rsrc
->entries
;
220 dir
->VirtualAddress
= (BYTE
*)rsrc
->restab
- addr
;
221 dir
->Size
= rsrc
->restabsize
;
222 for (i
= 0; i
< rsrc
->nresources
; i
++) rdep
[i
].OffsetToData
+= dir
->VirtualAddress
;
225 /* Build the export directory */
227 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
230 IMAGE_EXPORT_DIRECTORY
*exports
= (void *)dir
->VirtualAddress
;
231 fixup_rva_ptrs( &dir
->VirtualAddress
, addr
, 1 );
232 fixup_rva_ptrs( (void *)exports
->AddressOfFunctions
, addr
, exports
->NumberOfFunctions
);
233 fixup_rva_ptrs( (void *)exports
->AddressOfNames
, addr
, exports
->NumberOfNames
);
234 fixup_rva_ptrs( &exports
->Name
, addr
, 1 );
235 fixup_rva_ptrs( &exports
->AddressOfFunctions
, addr
, 1 );
236 fixup_rva_ptrs( &exports
->AddressOfNames
, addr
, 1 );
237 fixup_rva_ptrs( &exports
->AddressOfNameOrdinals
, addr
, 1 );
239 /* Setup relay debugging entry points */
240 if (WARN_ON(relay
) || TRACE_ON(relay
)) RELAY_SetupDLL( addr
);
243 return (HMODULE
)addr
;
246 /***********************************************************************
247 * BUILTIN32_LoadLibraryExA
249 * Partly copied from the original PE_ version.
252 WINE_MODREF
*BUILTIN32_LoadLibraryExA(LPCSTR path
, DWORD flags
)
256 char dllname
[20], *p
;
261 /* Fix the name in case we have a full path and extension */
263 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
264 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
266 if (strlen(name
) >= sizeof(dllname
)-4) goto error
;
268 strcpy( dllname
, name
);
269 p
= strrchr( dllname
, '.' );
270 if (!p
) strcat( dllname
, ".dll" );
272 /* Search built-in descriptor */
273 for (i
= 0; i
< nb_dlls
; i
++)
274 if (!strcasecmp( builtin_dlls
[i
].filename
, dllname
)) goto found
;
276 if ((handle
= BUILTIN32_dlopen( dllname
)))
278 for (i
= 0; i
< nb_dlls
; i
++)
279 if (!strcasecmp( builtin_dlls
[i
].filename
, dllname
)) goto found
;
280 ERR( "loaded .so but dll %s still not found\n", dllname
);
281 BUILTIN32_dlclose( handle
);
285 SetLastError( ERROR_FILE_NOT_FOUND
);
289 /* Load built-in module */
290 if (!(module
= BUILTIN32_DoLoadImage( &builtin_dlls
[i
] ))) return NULL
;
292 /* Create 32-bit MODREF */
293 if ( !(wm
= PE_CreateModule( module
, path
, flags
, -1, TRUE
)) )
295 ERR( "can't load %s\n", path
);
296 SetLastError( ERROR_OUTOFMEMORY
);
300 wm
->refCount
++; /* we don't support freeing builtin dlls (FIXME)*/
304 /***********************************************************************
305 * BUILTIN32_LoadExeModule
307 HMODULE
BUILTIN32_LoadExeModule(void)
311 /* Search built-in EXE descriptor */
312 for ( i
= 0; i
< nb_dlls
; i
++ )
313 if ( !(builtin_dlls
[i
].nt
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
) )
317 MESSAGE( "More than one built-in EXE module loaded!\n" );
326 MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" );
330 /* Load built-in module */
331 return BUILTIN32_DoLoadImage( &builtin_dlls
[exe
] );
335 /***********************************************************************
336 * BUILTIN32_RegisterDLL
338 * Register a built-in DLL descriptor.
340 void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS
*header
, const char *filename
)
342 assert( nb_dlls
< MAX_DLLS
);
343 builtin_dlls
[nb_dlls
].nt
= header
;
344 builtin_dlls
[nb_dlls
].filename
= filename
;
348 /***********************************************************************
349 * BUILTIN32_Unimplemented
351 * This function is called for unimplemented 32-bit entry points (declared
352 * as 'stub' in the spec file).
354 void BUILTIN32_Unimplemented( const char *dllname
, const char *funcname
)
356 __RESTORE_ES
; /* Just in case */
358 MESSAGE( "FATAL: No handler for Win32 routine %s.%s", dllname
, funcname
);
360 MESSAGE( " (called from %p)", __builtin_return_address(1) );