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"
23 #include "builtin32.h"
32 #include "debugtools.h"
34 DEFAULT_DEBUG_CHANNEL(module
);
35 DECLARE_DEBUG_CHANNEL(relay
);
42 IMAGE_RESOURCE_DATA_ENTRY
*entries
;
47 static const BUILTIN32_DESCRIPTOR
*builtin_dlls
[MAX_DLLS
];
51 /***********************************************************************
54 void *BUILTIN32_dlopen( const char *name
)
59 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
60 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
61 sprintf( buffer
, "lib%s", name
);
62 for (p
= buffer
; *p
; p
++) *p
= tolower(*p
);
63 if ((p
= strrchr( buffer
, '.' )) && (!strcmp( p
, ".dll" ) || !strcmp( p
, ".exe" ))) *p
= 0;
64 strcat( buffer
, ".so" );
66 if (!(handle
= ELFDLL_dlopen( buffer
, RTLD_NOW
)))
67 WARN( "failed to load %s: %s\n", buffer
, dlerror() );
74 /***********************************************************************
77 int BUILTIN32_dlclose( void *handle
)
80 /* FIXME: should unregister descriptors first */
81 /* return dlclose( handle ); */
87 /***********************************************************************
90 * Adjust an array of pointers to make them into RVAs.
92 static inline void fixup_rva_ptrs( void *array
, void *base
, int count
)
94 void **ptr
= (void **)array
;
97 if (*ptr
) *ptr
= (void *)((char *)*ptr
- (char *)base
);
103 /***********************************************************************
104 * BUILTIN32_DoLoadImage
106 * Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage.
108 static HMODULE
BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR
*descr
)
110 IMAGE_DATA_DIRECTORY
*dir
;
111 IMAGE_DOS_HEADER
*dos
;
112 IMAGE_NT_HEADERS
*nt
;
113 IMAGE_SECTION_HEADER
*sec
;
114 IMAGE_IMPORT_DESCRIPTOR
*imp
;
115 IMAGE_EXPORT_DIRECTORY
*exports
= descr
->exports
;
116 INT i
, size
, nb_sections
;
117 BYTE
*addr
, *code_start
, *data_start
;
118 int page_size
= VIRTUAL_GetPageSize();
120 /* Allocate the module */
122 nb_sections
= 2; /* code + data */
124 size
= (sizeof(IMAGE_DOS_HEADER
)
125 + sizeof(IMAGE_NT_HEADERS
)
126 + nb_sections
* sizeof(IMAGE_SECTION_HEADER
)
127 + (descr
->nb_imports
+1) * sizeof(IMAGE_IMPORT_DESCRIPTOR
));
129 assert( size
<= page_size
);
131 if (descr
->pe_header
)
133 if ((addr
= FILE_dommap( -1, descr
->pe_header
, 0, page_size
, 0, 0,
134 PROT_READ
|PROT_WRITE
, MAP_FIXED
)) != descr
->pe_header
)
136 ERR("failed to map over PE header for %s at %p\n", descr
->filename
, descr
->pe_header
);
142 if (!(addr
= VirtualAlloc( NULL
, page_size
, MEM_COMMIT
, PAGE_READWRITE
))) return 0;
145 dos
= (IMAGE_DOS_HEADER
*)addr
;
146 nt
= (IMAGE_NT_HEADERS
*)(dos
+ 1);
147 sec
= (IMAGE_SECTION_HEADER
*)(nt
+ 1);
148 imp
= (IMAGE_IMPORT_DESCRIPTOR
*)(sec
+ nb_sections
);
149 code_start
= addr
+ page_size
;
152 data_start
= code_start
+ page_size
;
154 /* Build the DOS and NT headers */
156 dos
->e_magic
= IMAGE_DOS_SIGNATURE
;
157 dos
->e_lfanew
= sizeof(*dos
);
159 nt
->Signature
= IMAGE_NT_SIGNATURE
;
160 nt
->FileHeader
.Machine
= IMAGE_FILE_MACHINE_I386
;
161 nt
->FileHeader
.NumberOfSections
= nb_sections
;
162 nt
->FileHeader
.SizeOfOptionalHeader
= sizeof(nt
->OptionalHeader
);
163 nt
->FileHeader
.Characteristics
= descr
->characteristics
;
165 nt
->OptionalHeader
.Magic
= IMAGE_NT_OPTIONAL_HDR_MAGIC
;
166 nt
->OptionalHeader
.SizeOfCode
= data_start
- code_start
;
167 nt
->OptionalHeader
.SizeOfInitializedData
= 0;
168 nt
->OptionalHeader
.SizeOfUninitializedData
= 0;
169 nt
->OptionalHeader
.ImageBase
= (DWORD
)addr
;
170 nt
->OptionalHeader
.SectionAlignment
= page_size
;
171 nt
->OptionalHeader
.FileAlignment
= page_size
;
172 nt
->OptionalHeader
.MajorOperatingSystemVersion
= 1;
173 nt
->OptionalHeader
.MinorOperatingSystemVersion
= 0;
174 nt
->OptionalHeader
.MajorSubsystemVersion
= 4;
175 nt
->OptionalHeader
.MinorSubsystemVersion
= 0;
176 nt
->OptionalHeader
.SizeOfImage
= page_size
;
177 nt
->OptionalHeader
.SizeOfHeaders
= page_size
;
178 nt
->OptionalHeader
.NumberOfRvaAndSizes
= IMAGE_NUMBEROF_DIRECTORY_ENTRIES
;
179 if (descr
->dllentrypoint
)
180 nt
->OptionalHeader
.AddressOfEntryPoint
= (DWORD
)descr
->dllentrypoint
- (DWORD
)addr
;
182 /* Build the code section */
184 strcpy( sec
->Name
, ".text" );
185 sec
->SizeOfRawData
= data_start
- code_start
;
186 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
187 sec
->VirtualAddress
= code_start
- addr
;
188 sec
->PointerToRawData
= code_start
- addr
;
189 sec
->Characteristics
= (IMAGE_SCN_CNT_CODE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_MEM_READ
);
192 /* Build the data section */
194 strcpy( sec
->Name
, ".data" );
195 sec
->SizeOfRawData
= 0;
196 sec
->Misc
.VirtualSize
= sec
->SizeOfRawData
;
197 sec
->VirtualAddress
= data_start
- addr
;
198 sec
->PointerToRawData
= data_start
- addr
;
199 sec
->Characteristics
= (IMAGE_SCN_CNT_INITIALIZED_DATA
|
200 IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_READ
);
203 /* Build the import directory */
205 if (descr
->nb_imports
)
207 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_IMPORT_DIRECTORY
];
208 dir
->VirtualAddress
= (BYTE
*)imp
- addr
;
209 dir
->Size
= sizeof(*imp
) * (descr
->nb_imports
+ 1);
211 /* Build the imports */
212 for (i
= 0; i
< descr
->nb_imports
; i
++)
214 imp
[i
].u
.Characteristics
= 0;
215 imp
[i
].ForwarderChain
= -1;
216 imp
[i
].Name
= (BYTE
*)descr
->imports
[i
] - addr
;
217 /* hack: make first thunk point to some zero value */
218 imp
[i
].FirstThunk
= (PIMAGE_THUNK_DATA
)((BYTE
*)&imp
[i
].u
.Characteristics
- addr
);
222 /* Build the resource directory */
226 BUILTIN32_RESOURCE
*rsrc
= descr
->rsrc
;
227 IMAGE_RESOURCE_DATA_ENTRY
*rdep
;
228 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_RESOURCE_DIRECTORY
];
229 dir
->VirtualAddress
= (BYTE
*)rsrc
->restab
- addr
;
230 dir
->Size
= rsrc
->restabsize
;
231 rdep
= rsrc
->entries
;
232 for (i
= 0; i
< rsrc
->nresources
; i
++) rdep
[i
].OffsetToData
+= dir
->VirtualAddress
;
235 /* Build the export directory */
239 dir
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_FILE_EXPORT_DIRECTORY
];
240 dir
->VirtualAddress
= (BYTE
*)exports
- addr
;
241 dir
->Size
= descr
->exports_size
;
243 fixup_rva_ptrs( (void *)exports
->AddressOfFunctions
, addr
, exports
->NumberOfFunctions
);
244 fixup_rva_ptrs( (void *)exports
->AddressOfNames
, addr
, exports
->NumberOfNames
);
245 fixup_rva_ptrs( &exports
->Name
, addr
, 1 );
246 fixup_rva_ptrs( &exports
->AddressOfFunctions
, addr
, 1 );
247 fixup_rva_ptrs( &exports
->AddressOfNames
, addr
, 1 );
248 fixup_rva_ptrs( &exports
->AddressOfNameOrdinals
, addr
, 1 );
250 /* Setup relay debugging entry points */
251 if (WARN_ON(relay
) || TRACE_ON(relay
)) RELAY_SetupDLL( addr
);
254 return (HMODULE
)addr
;
257 /***********************************************************************
258 * BUILTIN32_LoadLibraryExA
260 * Partly copied from the original PE_ version.
263 WINE_MODREF
*BUILTIN32_LoadLibraryExA(LPCSTR path
, DWORD flags
)
267 char dllname
[MAX_PATH
], *p
;
271 /* Fix the name in case we have a full path and extension */
272 if ((p
= strrchr( path
, '\\' ))) path
= p
+ 1;
273 lstrcpynA( dllname
, path
, sizeof(dllname
) );
275 p
= strrchr( dllname
, '.' );
276 if (!p
) strcat( dllname
, ".dll" );
278 /* Search built-in descriptor */
279 for (i
= 0; i
< nb_dlls
; i
++)
280 if (!strcasecmp( builtin_dlls
[i
]->filename
, dllname
)) goto found
;
282 if ((handle
= BUILTIN32_dlopen( dllname
)))
284 for (i
= 0; i
< nb_dlls
; i
++)
285 if (!strcasecmp( builtin_dlls
[i
]->filename
, dllname
)) goto found
;
286 ERR( "loaded .so but dll %s still not found\n", dllname
);
287 BUILTIN32_dlclose( handle
);
290 SetLastError( ERROR_FILE_NOT_FOUND
);
294 /* Load built-in module */
295 if (!(module
= BUILTIN32_DoLoadImage( builtin_dlls
[i
] ))) return NULL
;
297 /* Create 32-bit MODREF */
298 if ( !(wm
= PE_CreateModule( module
, dllname
, flags
, -1, TRUE
)) )
300 ERR( "can't load %s\n", path
);
301 SetLastError( ERROR_OUTOFMEMORY
);
305 wm
->refCount
++; /* we don't support freeing builtin dlls (FIXME)*/
309 /***********************************************************************
310 * BUILTIN32_LoadExeModule
312 HMODULE
BUILTIN32_LoadExeModule(void)
316 /* Search built-in EXE descriptor */
317 for ( i
= 0; i
< nb_dlls
; i
++ )
318 if ( !(builtin_dlls
[i
]->characteristics
& IMAGE_FILE_DLL
) )
322 MESSAGE( "More than one built-in EXE module loaded!\n" );
331 MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" );
335 /* Load built-in module */
336 return BUILTIN32_DoLoadImage( builtin_dlls
[exe
] );
340 /***********************************************************************
341 * BUILTIN32_RegisterDLL
343 * Register a built-in DLL descriptor.
345 void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR
*descr
)
347 assert( nb_dlls
< MAX_DLLS
);
348 builtin_dlls
[nb_dlls
++] = descr
;
351 /***********************************************************************
352 * BUILTIN32_Unimplemented
354 * This function is called for unimplemented 32-bit entry points (declared
355 * as 'stub' in the spec file).
357 void BUILTIN32_Unimplemented( const char *dllname
, const char *funcname
)
359 __RESTORE_ES
; /* Just in case */
361 MESSAGE( "FATAL: No handler for Win32 routine %s.%s", dllname
, funcname
);
363 MESSAGE( " (called from %p)", __builtin_return_address(1) );