Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Win32 builtin functions |
| 3 | * |
| 4 | * Copyright 1997 Alexandre Julliard |
| 5 | */ |
| 6 | |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 7 | #include "config.h" |
| 8 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 9 | #include <assert.h> |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 10 | #include <string.h> |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 11 | #include <stdio.h> |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 12 | #include <ctype.h> |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 13 | #ifdef HAVE_DL_API |
| 14 | #include <dlfcn.h> |
| 15 | #endif |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 16 | #ifdef HAVE_SYS_MMAN_H |
| 17 | #include <sys/mman.h> |
| 18 | #endif |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 19 | |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 20 | #include "windef.h" |
Alexandre Julliard | 680919c | 2000-05-07 18:39:28 +0000 | [diff] [blame] | 21 | #include "wine/winbase16.h" |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 22 | #include "wingdi.h" |
Michael Veksler | f935c59 | 1999-02-09 15:49:39 +0000 | [diff] [blame] | 23 | #include "winuser.h" |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 24 | #include "builtin32.h" |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 25 | #include "elfdll.h" |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 26 | #include "file.h" |
| 27 | #include "global.h" |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 28 | #include "neexe.h" |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 29 | #include "heap.h" |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 30 | #include "main.h" |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 31 | #include "snoop.h" |
| 32 | #include "winerror.h" |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 33 | #include "server.h" |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 34 | #include "debugtools.h" |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 35 | #include "options.h" /* for argv0 */ |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 36 | |
Alexandre Julliard | 74e4a28 | 2000-01-09 04:20:31 +0000 | [diff] [blame] | 37 | DEFAULT_DEBUG_CHANNEL(module); |
| 38 | DECLARE_DEBUG_CHANNEL(relay); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 39 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 40 | typedef struct |
| 41 | { |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 42 | BYTE *restab; |
| 43 | DWORD nresources; |
| 44 | DWORD restabsize; |
| 45 | IMAGE_RESOURCE_DATA_ENTRY *entries; |
Bertho Stultiens | d1895a7 | 1999-04-25 18:31:35 +0000 | [diff] [blame] | 46 | } BUILTIN32_RESOURCE; |
| 47 | |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 48 | #define MAX_DLLS 60 |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 49 | |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 50 | static const BUILTIN32_DESCRIPTOR *builtin_dlls[MAX_DLLS]; |
| 51 | static HMODULE dll_modules[MAX_DLLS]; |
| 52 | static int nb_dlls; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 53 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 54 | |
Alexandre Julliard | 74e4a28 | 2000-01-09 04:20:31 +0000 | [diff] [blame] | 55 | /*********************************************************************** |
| 56 | * BUILTIN32_WarnSecondInstance |
| 57 | * |
| 58 | * Emit a warning when we are creating a second instance for a DLL |
| 59 | * that is known to not support this. |
| 60 | */ |
| 61 | static void BUILTIN32_WarnSecondInstance( const char *name ) |
| 62 | { |
| 63 | static const char * const warning_list[] = |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 64 | { "comctl32.dll", "comdlg32.dll", "crtdll.dll", |
| 65 | "imagehlp.dll", "msacm32.dll", "shell32.dll", NULL }; |
Alexandre Julliard | 74e4a28 | 2000-01-09 04:20:31 +0000 | [diff] [blame] | 66 | |
| 67 | const char * const *ptr = warning_list; |
| 68 | |
| 69 | while (*ptr) |
| 70 | { |
| 71 | if (!strcasecmp( *ptr, name )) |
| 72 | { |
| 73 | ERR( "Attempt to instantiate built-in dll '%s' twice " |
| 74 | "in the same address space. Expect trouble!\n", name ); |
| 75 | return; |
| 76 | } |
| 77 | ptr++; |
| 78 | } |
| 79 | } |
| 80 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 81 | /*********************************************************************** |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 82 | * BUILTIN32_dlopen |
| 83 | */ |
| 84 | void *BUILTIN32_dlopen( const char *name ) |
| 85 | { |
| 86 | #ifdef HAVE_DL_API |
| 87 | void *handle; |
| 88 | char buffer[128], *p; |
| 89 | if ((p = strrchr( name, '/' ))) name = p + 1; |
| 90 | if ((p = strrchr( name, '\\' ))) name = p + 1; |
| 91 | sprintf( buffer, "lib%s", name ); |
| 92 | for (p = buffer; *p; p++) *p = tolower(*p); |
| 93 | if ((p = strrchr( buffer, '.' )) && (!strcmp( p, ".dll" ) || !strcmp( p, ".exe" ))) *p = 0; |
| 94 | strcat( buffer, ".so" ); |
| 95 | |
| 96 | if (!(handle = ELFDLL_dlopen( buffer, RTLD_NOW ))) |
| 97 | ERR( "failed to load %s: %s\n", buffer, dlerror() ); |
| 98 | return handle; |
| 99 | #else |
| 100 | return NULL; |
| 101 | #endif |
| 102 | } |
| 103 | |
| 104 | /*********************************************************************** |
| 105 | * BUILTIN32_dlclose |
| 106 | */ |
| 107 | int BUILTIN32_dlclose( void *handle ) |
| 108 | { |
| 109 | #ifdef HAVE_DL_API |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 110 | /* FIXME: should unregister descriptors first */ |
| 111 | /* return dlclose( handle ); */ |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 112 | #endif |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 113 | return 0; |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 114 | } |
| 115 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 116 | |
| 117 | /*********************************************************************** |
| 118 | * fixup_rva_ptrs |
| 119 | * |
| 120 | * Adjust an array of pointers to make them into RVAs. |
| 121 | */ |
| 122 | static inline void fixup_rva_ptrs( void *array, void *base, int count ) |
| 123 | { |
| 124 | void **ptr = (void **)array; |
| 125 | while (count--) |
| 126 | { |
| 127 | if (*ptr) *ptr = (void *)((char *)*ptr - (char *)base); |
| 128 | ptr++; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 133 | /*********************************************************************** |
Ulrich Weigand | ffa2c6f | 1998-12-18 15:38:15 +0000 | [diff] [blame] | 134 | * BUILTIN32_DoLoadImage |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 135 | * |
Ulrich Weigand | ffa2c6f | 1998-12-18 15:38:15 +0000 | [diff] [blame] | 136 | * Load a built-in Win32 module. Helper function for BUILTIN32_LoadImage. |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 137 | */ |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 138 | static HMODULE BUILTIN32_DoLoadImage( const BUILTIN32_DESCRIPTOR *descr ) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 139 | { |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 140 | IMAGE_DATA_DIRECTORY *dir; |
| 141 | IMAGE_DOS_HEADER *dos; |
| 142 | IMAGE_NT_HEADERS *nt; |
| 143 | IMAGE_SECTION_HEADER *sec; |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 144 | IMAGE_IMPORT_DESCRIPTOR *imp; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 145 | IMAGE_EXPORT_DIRECTORY *exports = descr->exports; |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 146 | INT i, size, nb_sections; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 147 | BYTE *addr, *code_start, *data_start; |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 148 | BYTE* xcnlnk; |
| 149 | DWORD xcnsize = 0; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 150 | int page_size = VIRTUAL_GetPageSize(); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 151 | |
| 152 | /* Allocate the module */ |
| 153 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 154 | nb_sections = 2; /* code + data */ |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 155 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 156 | if (!strcmp(descr->filename, "kernel32.dll")) { |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 157 | nb_sections++; |
| 158 | xcnsize = sizeof(DWORD); |
| 159 | } |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 160 | size = (sizeof(IMAGE_DOS_HEADER) |
| 161 | + sizeof(IMAGE_NT_HEADERS) |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 162 | + nb_sections * sizeof(IMAGE_SECTION_HEADER) |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 163 | + (descr->nb_imports+1) * sizeof(IMAGE_IMPORT_DESCRIPTOR) |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 164 | + xcnsize); |
| 165 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 166 | assert( size <= page_size ); |
| 167 | |
| 168 | if (descr->pe_header) |
| 169 | { |
| 170 | if ((addr = FILE_dommap( -1, descr->pe_header, 0, page_size, 0, 0, |
| 171 | PROT_READ|PROT_WRITE, MAP_FIXED )) != descr->pe_header) |
| 172 | { |
| 173 | ERR("failed to map over PE header for %s at %p\n", descr->filename, descr->pe_header ); |
| 174 | return 0; |
| 175 | } |
| 176 | } |
| 177 | else |
| 178 | { |
| 179 | if (!(addr = VirtualAlloc( NULL, page_size, MEM_COMMIT, PAGE_READWRITE ))) return 0; |
| 180 | } |
| 181 | |
| 182 | dos = (IMAGE_DOS_HEADER *)addr; |
| 183 | nt = (IMAGE_NT_HEADERS *)(dos + 1); |
| 184 | sec = (IMAGE_SECTION_HEADER *)(nt + 1); |
| 185 | imp = (IMAGE_IMPORT_DESCRIPTOR *)(sec + nb_sections); |
| 186 | xcnlnk = (char *)(imp + descr->nb_imports + 1); |
| 187 | code_start = addr + page_size; |
| 188 | |
| 189 | /* HACK! */ |
| 190 | data_start = code_start + page_size; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 191 | |
| 192 | /* Build the DOS and NT headers */ |
| 193 | |
| 194 | dos->e_magic = IMAGE_DOS_SIGNATURE; |
| 195 | dos->e_lfanew = sizeof(*dos); |
| 196 | |
| 197 | nt->Signature = IMAGE_NT_SIGNATURE; |
| 198 | nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386; |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 199 | nt->FileHeader.NumberOfSections = nb_sections; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 200 | nt->FileHeader.SizeOfOptionalHeader = sizeof(nt->OptionalHeader); |
Ulrich Weigand | 9ffd403 | 2000-02-03 01:33:48 +0000 | [diff] [blame] | 201 | nt->FileHeader.Characteristics = descr->characteristics; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 202 | |
| 203 | nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 204 | nt->OptionalHeader.SizeOfCode = data_start - code_start; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 205 | nt->OptionalHeader.SizeOfInitializedData = 0; |
| 206 | nt->OptionalHeader.SizeOfUninitializedData = 0; |
| 207 | nt->OptionalHeader.ImageBase = (DWORD)addr; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 208 | nt->OptionalHeader.SectionAlignment = page_size; |
| 209 | nt->OptionalHeader.FileAlignment = page_size; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 210 | nt->OptionalHeader.MajorOperatingSystemVersion = 1; |
| 211 | nt->OptionalHeader.MinorOperatingSystemVersion = 0; |
| 212 | nt->OptionalHeader.MajorSubsystemVersion = 4; |
| 213 | nt->OptionalHeader.MinorSubsystemVersion = 0; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 214 | nt->OptionalHeader.SizeOfImage = page_size; |
| 215 | nt->OptionalHeader.SizeOfHeaders = page_size; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 216 | nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 217 | if (descr->dllentrypoint) |
| 218 | nt->OptionalHeader.AddressOfEntryPoint = (DWORD)descr->dllentrypoint - (DWORD)addr; |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 219 | |
Alexandre Julliard | 936d663 | 1999-05-12 16:10:53 +0000 | [diff] [blame] | 220 | /* Build the code section */ |
| 221 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 222 | strcpy( sec->Name, ".text" ); |
| 223 | sec->SizeOfRawData = data_start - code_start; |
Alexandre Julliard | 936d663 | 1999-05-12 16:10:53 +0000 | [diff] [blame] | 224 | sec->Misc.VirtualSize = sec->SizeOfRawData; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 225 | sec->VirtualAddress = code_start - addr; |
| 226 | sec->PointerToRawData = code_start - addr; |
| 227 | sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); |
| 228 | sec++; |
| 229 | |
| 230 | /* Build the data section */ |
| 231 | |
| 232 | strcpy( sec->Name, ".data" ); |
| 233 | sec->SizeOfRawData = 0; |
| 234 | sec->Misc.VirtualSize = sec->SizeOfRawData; |
| 235 | sec->VirtualAddress = data_start - addr; |
| 236 | sec->PointerToRawData = data_start - addr; |
Alexandre Julliard | 936d663 | 1999-05-12 16:10:53 +0000 | [diff] [blame] | 237 | sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 238 | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ); |
Alexandre Julliard | 936d663 | 1999-05-12 16:10:53 +0000 | [diff] [blame] | 239 | sec++; |
| 240 | |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 241 | /* Build the import directory */ |
| 242 | |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 243 | if (descr->nb_imports) |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 244 | { |
| 245 | dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY]; |
| 246 | dir->VirtualAddress = (BYTE *)imp - addr; |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 247 | dir->Size = sizeof(*imp) * (descr->nb_imports + 1); |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 248 | |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 249 | /* Build the imports */ |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 250 | for (i = 0; i < descr->nb_imports; i++) |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 251 | { |
| 252 | imp[i].u.Characteristics = 0; |
| 253 | imp[i].ForwarderChain = -1; |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 254 | imp[i].Name = (BYTE *)descr->imports[i] - addr; |
Alexandre Julliard | e4177e6 | 1999-05-12 09:57:37 +0000 | [diff] [blame] | 255 | /* hack: make first thunk point to some zero value */ |
| 256 | imp[i].FirstThunk = (PIMAGE_THUNK_DATA)((BYTE *)&imp[i].u.Characteristics - addr); |
| 257 | } |
| 258 | } |
| 259 | |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 260 | /* Build Wine's .so link section. Those sections are used by the wine debugger to |
| 261 | * link a builtin PE header with the corresponding ELF module (from either a |
| 262 | * shared library, or the main executable - wine emulator or any winelib program |
| 263 | */ |
| 264 | if (xcnsize) |
| 265 | { |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 266 | strcpy( sec->Name, ".xcnlnk" ); |
| 267 | sec->Misc.VirtualSize = xcnsize; |
| 268 | sec->VirtualAddress = (BYTE *)xcnlnk - addr; |
| 269 | sec->SizeOfRawData = sec->Misc.VirtualSize; |
| 270 | sec->PointerToRawData = (BYTE *)xcnlnk - addr; |
| 271 | sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ); |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 272 | sec++; |
Eric Pouech | 87031a4 | 2000-04-13 19:27:52 +0000 | [diff] [blame] | 273 | |
| 274 | *(const char**)xcnlnk = argv0; |
| 275 | } |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 276 | |
Bertho Stultiens | d1895a7 | 1999-04-25 18:31:35 +0000 | [diff] [blame] | 277 | /* Build the resource directory */ |
Bertho Stultiens | d1895a7 | 1999-04-25 18:31:35 +0000 | [diff] [blame] | 278 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 279 | if (descr->rsrc) |
Alexandre Julliard | aabef02 | 2000-03-17 15:12:06 +0000 | [diff] [blame] | 280 | { |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 281 | BUILTIN32_RESOURCE *rsrc = descr->rsrc; |
Alexandre Julliard | aabef02 | 2000-03-17 15:12:06 +0000 | [diff] [blame] | 282 | IMAGE_RESOURCE_DATA_ENTRY *rdep; |
Bertho Stultiens | d1895a7 | 1999-04-25 18:31:35 +0000 | [diff] [blame] | 283 | dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY]; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 284 | dir->VirtualAddress = (BYTE *)rsrc->restab - addr; |
Alexandre Julliard | 74e4a28 | 2000-01-09 04:20:31 +0000 | [diff] [blame] | 285 | dir->Size = rsrc->restabsize; |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 286 | rdep = rsrc->entries; |
| 287 | for (i = 0; i < rsrc->nresources; i++) rdep[i].OffsetToData += dir->VirtualAddress; |
Bertho Stultiens | d1895a7 | 1999-04-25 18:31:35 +0000 | [diff] [blame] | 288 | } |
| 289 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 290 | /* Build the export directory */ |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 291 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 292 | if (exports) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 293 | { |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 294 | dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; |
| 295 | dir->VirtualAddress = (BYTE *)exports - addr; |
| 296 | dir->Size = descr->exports_size; |
Marcus Meissner | 30c112e | 1998-11-14 17:06:55 +0000 | [diff] [blame] | 297 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 298 | fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions ); |
| 299 | fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames ); |
| 300 | fixup_rva_ptrs( &exports->Name, addr, 1 ); |
| 301 | fixup_rva_ptrs( &exports->AddressOfFunctions, addr, 1 ); |
| 302 | fixup_rva_ptrs( &exports->AddressOfNames, addr, 1 ); |
| 303 | fixup_rva_ptrs( &exports->AddressOfNameOrdinals, addr, 1 ); |
Alexandre Julliard | 3eb441c | 1999-05-10 14:44:47 +0000 | [diff] [blame] | 304 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 305 | /* Setup relay debugging entry points */ |
| 306 | if (WARN_ON(relay) || TRACE_ON(relay)) RELAY_SetupDLL( addr ); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 307 | } |
| 308 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 309 | return (HMODULE)addr; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 310 | } |
| 311 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 312 | /*********************************************************************** |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 313 | * BUILTIN32_LoadLibraryExA |
| 314 | * |
| 315 | * Partly copied from the original PE_ version. |
| 316 | * |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 317 | */ |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 318 | WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 319 | { |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 320 | struct load_dll_request *req = get_req_buffer(); |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 321 | HMODULE16 hModule16; |
| 322 | NE_MODULE *pModule; |
| 323 | WINE_MODREF *wm; |
Francois Gouget | baa9bf9 | 1999-12-27 05:24:06 +0000 | [diff] [blame] | 324 | char dllname[MAX_PATH], *p; |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 325 | void *handle; |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 326 | int i; |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 327 | |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 328 | /* Fix the name in case we have a full path and extension */ |
| 329 | if ((p = strrchr( path, '\\' ))) path = p + 1; |
| 330 | lstrcpynA( dllname, path, sizeof(dllname) ); |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 331 | |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 332 | p = strrchr( dllname, '.' ); |
| 333 | if (!p) strcat( dllname, ".dll" ); |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 334 | |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 335 | /* Search built-in descriptor */ |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 336 | for (i = 0; i < nb_dlls; i++) |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 337 | if (!strcasecmp( builtin_dlls[i]->filename, dllname )) goto found; |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 338 | |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 339 | if ((handle = BUILTIN32_dlopen( dllname ))) |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 340 | { |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 341 | for (i = 0; i < nb_dlls; i++) |
| 342 | if (!strcasecmp( builtin_dlls[i]->filename, dllname )) goto found; |
| 343 | ERR( "loaded .so but dll %s still not found\n", dllname ); |
| 344 | BUILTIN32_dlclose( handle ); |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 345 | } |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 346 | |
Alexandre Julliard | e1e7537 | 2000-04-24 17:17:49 +0000 | [diff] [blame] | 347 | SetLastError( ERROR_FILE_NOT_FOUND ); |
| 348 | return NULL; |
| 349 | |
| 350 | found: |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 351 | /* Load built-in module */ |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 352 | if (!dll_modules[i]) |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 353 | { |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 354 | if (!(dll_modules[i] = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL; |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 355 | } |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 356 | else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->filename ); |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 357 | |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 358 | /* Create 16-bit dummy module */ |
Alexandre Julliard | b445952 | 2000-04-15 21:00:55 +0000 | [diff] [blame] | 359 | if ((hModule16 = MODULE_CreateDummyModule( dllname, dll_modules[i] )) < 32) |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 360 | { |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 361 | SetLastError( (DWORD)hModule16 ); |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 362 | return NULL; /* FIXME: Should unload the builtin module */ |
| 363 | } |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 364 | pModule = (NE_MODULE *)GlobalLock16( hModule16 ); |
| 365 | pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32 | NE_FFLAGS_BUILTIN; |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 366 | |
| 367 | /* Create 32-bit MODREF */ |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 368 | if ( !(wm = PE_CreateModule( pModule->module32, dllname, flags, TRUE )) ) |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 369 | { |
Alexandre Julliard | 74e4a28 | 2000-01-09 04:20:31 +0000 | [diff] [blame] | 370 | ERR( "can't load %s\n", path ); |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 371 | FreeLibrary16( hModule16 ); /* FIXME: Should unload the builtin module */ |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 372 | SetLastError( ERROR_OUTOFMEMORY ); |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 373 | return NULL; |
| 374 | } |
| 375 | |
| 376 | if (wm->binfmt.pe.pe_export) |
| 377 | SNOOP_RegisterDLL(wm->module,wm->modname,wm->binfmt.pe.pe_export->NumberOfFunctions); |
| 378 | |
Alexandre Julliard | 05f0b71 | 2000-03-09 18:18:41 +0000 | [diff] [blame] | 379 | req->handle = -1; |
| 380 | req->base = (void *)pModule->module32; |
| 381 | req->dbg_offset = 0; |
| 382 | req->dbg_size = 0; |
| 383 | req->name = &wm->modname; |
| 384 | server_call_noerr( REQ_LOAD_DLL ); |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 385 | return wm; |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 386 | } |
| 387 | |
Ulrich Weigand | 9ffd403 | 2000-02-03 01:33:48 +0000 | [diff] [blame] | 388 | /*********************************************************************** |
| 389 | * BUILTIN32_LoadExeModule |
| 390 | */ |
Alexandre Julliard | b445952 | 2000-04-15 21:00:55 +0000 | [diff] [blame] | 391 | HMODULE BUILTIN32_LoadExeModule( LPCSTR *filename ) |
Ulrich Weigand | 9ffd403 | 2000-02-03 01:33:48 +0000 | [diff] [blame] | 392 | { |
Ulrich Weigand | 9ffd403 | 2000-02-03 01:33:48 +0000 | [diff] [blame] | 393 | int i, exe = -1; |
| 394 | |
| 395 | /* Search built-in EXE descriptor */ |
| 396 | for ( i = 0; i < nb_dlls; i++ ) |
| 397 | if ( !(builtin_dlls[i]->characteristics & IMAGE_FILE_DLL) ) |
| 398 | { |
| 399 | if ( exe != -1 ) |
| 400 | { |
| 401 | MESSAGE( "More than one built-in EXE module loaded!\n" ); |
| 402 | break; |
| 403 | } |
| 404 | |
| 405 | exe = i; |
| 406 | } |
| 407 | |
| 408 | if ( exe == -1 ) |
| 409 | { |
| 410 | MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" ); |
| 411 | return 0; |
| 412 | } |
| 413 | |
| 414 | /* Load built-in module */ |
| 415 | if ( !dll_modules[exe] ) |
| 416 | if ( !(dll_modules[exe] = BUILTIN32_DoLoadImage( builtin_dlls[exe] )) ) |
| 417 | return 0; |
| 418 | |
Alexandre Julliard | b445952 | 2000-04-15 21:00:55 +0000 | [diff] [blame] | 419 | *filename = builtin_dlls[exe]->filename; |
| 420 | return dll_modules[exe]; |
Ulrich Weigand | 9ffd403 | 2000-02-03 01:33:48 +0000 | [diff] [blame] | 421 | } |
| 422 | |
Bertho Stultiens | c1d1cfe | 1999-04-18 12:14:06 +0000 | [diff] [blame] | 423 | |
| 424 | /*********************************************************************** |
| 425 | * BUILTIN32_UnloadLibrary |
| 426 | * |
| 427 | * Unload the built-in library and free the modref. |
| 428 | */ |
| 429 | void BUILTIN32_UnloadLibrary(WINE_MODREF *wm) |
| 430 | { |
| 431 | /* FIXME: do something here */ |
| 432 | } |
| 433 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 434 | /*********************************************************************** |
Alexandre Julliard | 112d307 | 2000-01-16 03:37:05 +0000 | [diff] [blame] | 435 | * BUILTIN32_RegisterDLL |
| 436 | * |
| 437 | * Register a built-in DLL descriptor. |
| 438 | */ |
| 439 | void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr ) |
| 440 | { |
| 441 | assert( nb_dlls < MAX_DLLS ); |
| 442 | builtin_dlls[nb_dlls++] = descr; |
| 443 | } |
| 444 | |
| 445 | /*********************************************************************** |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 446 | * BUILTIN32_Unimplemented |
| 447 | * |
| 448 | * This function is called for unimplemented 32-bit entry points (declared |
| 449 | * as 'stub' in the spec file). |
| 450 | */ |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 451 | void BUILTIN32_Unimplemented( const char *dllname, const char *funcname ) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 452 | { |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 453 | __RESTORE_ES; /* Just in case */ |
| 454 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 455 | MESSAGE( "No handler for Win32 routine %s.%s", dllname, funcname ); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 456 | #ifdef __GNUC__ |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 457 | MESSAGE( " (called from %p)", __builtin_return_address(1) ); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 458 | #endif |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 459 | MESSAGE( "\n" ); |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 460 | ExitProcess(1); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 461 | } |