Widen the "About" dialog to prevent wrapping of text.
[wine/multimedia.git] / loader / module.c
blob07204fe59fc5466f606218606fe7e032796ed519
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34 #include "wine/winbase16.h"
35 #include "winerror.h"
36 #include "ntstatus.h"
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winreg.h"
40 #include "winternl.h"
41 #include "heap.h"
42 #include "thread.h"
43 #include "file.h"
44 #include "module.h"
46 #include "wine/debug.h"
47 #include "wine/unicode.h"
48 #include "wine/server.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(module);
51 WINE_DECLARE_DEBUG_CHANNEL(win32);
52 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
55 /****************************************************************************
56 * DisableThreadLibraryCalls (KERNEL32.@)
58 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
60 BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
62 NTSTATUS nts = LdrDisableThreadCalloutsForDll( hModule );
63 if (nts == STATUS_SUCCESS) return TRUE;
65 SetLastError( RtlNtStatusToDosError( nts ) );
66 return FALSE;
70 /* Check whether a file is an OS/2 or a very old Windows executable
71 * by testing on import of KERNEL.
73 * FIXME: is reading the module imports the only way of discerning
74 * old Windows binaries from OS/2 ones ? At least it seems so...
76 static enum binary_type MODULE_Decide_OS2_OldWin(HANDLE hfile, const IMAGE_DOS_HEADER *mz,
77 const IMAGE_OS2_HEADER *ne)
79 DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
80 enum binary_type ret = BINARY_OS216;
81 LPWORD modtab = NULL;
82 LPSTR nametab = NULL;
83 DWORD len;
84 int i;
86 /* read modref table */
87 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_modtab, NULL, SEEK_SET ) == -1)
88 || (!(modtab = HeapAlloc( GetProcessHeap(), 0, ne->ne_cmod*sizeof(WORD))))
89 || (!(ReadFile(hfile, modtab, ne->ne_cmod*sizeof(WORD), &len, NULL)))
90 || (len != ne->ne_cmod*sizeof(WORD)) )
91 goto broken;
93 /* read imported names table */
94 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_imptab, NULL, SEEK_SET ) == -1)
95 || (!(nametab = HeapAlloc( GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab)))
96 || (!(ReadFile(hfile, nametab, ne->ne_enttab - ne->ne_imptab, &len, NULL)))
97 || (len != ne->ne_enttab - ne->ne_imptab) )
98 goto broken;
100 for (i=0; i < ne->ne_cmod; i++)
102 LPSTR module = &nametab[modtab[i]];
103 TRACE("modref: %.*s\n", module[0], &module[1]);
104 if (!(strncmp(&module[1], "KERNEL", module[0])))
105 { /* very old Windows file */
106 MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
107 ret = BINARY_WIN16;
108 goto good;
112 broken:
113 ERR("Hmm, an error occurred. Is this binary file broken ?\n");
115 good:
116 HeapFree( GetProcessHeap(), 0, modtab);
117 HeapFree( GetProcessHeap(), 0, nametab);
118 SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
119 return ret;
122 /***********************************************************************
123 * MODULE_GetBinaryType
125 enum binary_type MODULE_GetBinaryType( HANDLE hfile )
127 union
129 struct
131 unsigned char magic[4];
132 unsigned char ignored[12];
133 unsigned short type;
134 } elf;
135 struct
137 unsigned long magic;
138 unsigned long cputype;
139 unsigned long cpusubtype;
140 unsigned long filetype;
141 } macho;
142 IMAGE_DOS_HEADER mz;
143 } header;
145 char magic[4];
146 DWORD len;
148 /* Seek to the start of the file and read the header information. */
149 if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1)
150 return BINARY_UNKNOWN;
151 if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
152 return BINARY_UNKNOWN;
154 if (!memcmp( header.elf.magic, "\177ELF", 4 ))
156 /* FIXME: we don't bother to check byte order, architecture, etc. */
157 switch(header.elf.type)
159 case 2: return BINARY_UNIX_EXE;
160 case 3: return BINARY_UNIX_LIB;
162 return BINARY_UNKNOWN;
165 /* Mach-o File with Endian set to Big Endian or Little Endian*/
166 if (header.macho.magic == 0xfeedface || header.macho.magic == 0xecafdeef)
168 switch(header.macho.filetype)
170 case 0x8: /* MH_BUNDLE */ return BINARY_UNIX_LIB;
172 return BINARY_UNKNOWN;
175 /* Not ELF, try DOS */
177 if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
179 /* We do have a DOS image so we will now try to seek into
180 * the file by the amount indicated by the field
181 * "Offset to extended header" and read in the
182 * "magic" field information at that location.
183 * This will tell us if there is more header information
184 * to read or not.
186 /* But before we do we will make sure that header
187 * structure encompasses the "Offset to extended header"
188 * field.
190 if (header.mz.e_lfanew < sizeof(IMAGE_DOS_HEADER))
191 return BINARY_DOS;
192 if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
193 return BINARY_DOS;
194 if (!ReadFile( hfile, magic, sizeof(magic), &len, NULL ) || len != sizeof(magic))
195 return BINARY_DOS;
197 /* Reading the magic field succeeded so
198 * we will try to determine what type it is.
200 if (!memcmp( magic, "PE\0\0", 4 ))
202 IMAGE_FILE_HEADER FileHeader;
204 if (ReadFile( hfile, &FileHeader, sizeof(FileHeader), &len, NULL ) && len == sizeof(FileHeader))
206 if (FileHeader.Characteristics & IMAGE_FILE_DLL) return BINARY_PE_DLL;
207 return BINARY_PE_EXE;
209 return BINARY_DOS;
212 if (!memcmp( magic, "NE", 2 ))
214 /* This is a Windows executable (NE) header. This can
215 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
216 * DOS program (running under a DOS extender). To decide
217 * which, we'll have to read the NE header.
219 IMAGE_OS2_HEADER ne;
220 if ( SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1
221 && ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
222 && len == sizeof(ne) )
224 switch ( ne.ne_exetyp )
226 case 2: return BINARY_WIN16;
227 case 5: return BINARY_DOS;
228 default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ne);
231 /* Couldn't read header, so abort. */
232 return BINARY_DOS;
235 /* Unknown extended header, but this file is nonetheless DOS-executable. */
236 return BINARY_DOS;
239 return BINARY_UNKNOWN;
242 /***********************************************************************
243 * GetBinaryTypeA [KERNEL32.@]
244 * GetBinaryType [KERNEL32.@]
246 * The GetBinaryType function determines whether a file is executable
247 * or not and if it is it returns what type of executable it is.
248 * The type of executable is a property that determines in which
249 * subsystem an executable file runs under.
251 * Binary types returned:
252 * SCS_32BIT_BINARY: A Win32 based application
253 * SCS_DOS_BINARY: An MS-Dos based application
254 * SCS_WOW_BINARY: A Win16 based application
255 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
256 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
257 * SCS_OS216_BINARY: A 16bit OS/2 based application
259 * Returns TRUE if the file is an executable in which case
260 * the value pointed by lpBinaryType is set.
261 * Returns FALSE if the file is not an executable or if the function fails.
263 * To do so it opens the file and reads in the header information
264 * if the extended header information is not present it will
265 * assume that the file is a DOS executable.
266 * If the extended header information is present it will
267 * determine if the file is a 16 or 32 bit Windows executable
268 * by check the flags in the header.
270 * Note that .COM and .PIF files are only recognized by their
271 * file name extension; but Windows does it the same way ...
273 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
275 BOOL ret = FALSE;
276 HANDLE hfile;
277 char *ptr;
279 TRACE_(win32)("%s\n", lpApplicationName );
281 /* Sanity check.
283 if ( lpApplicationName == NULL || lpBinaryType == NULL )
284 return FALSE;
286 /* Open the file indicated by lpApplicationName for reading.
288 hfile = CreateFileA( lpApplicationName, GENERIC_READ, FILE_SHARE_READ,
289 NULL, OPEN_EXISTING, 0, 0 );
290 if ( hfile == INVALID_HANDLE_VALUE )
291 return FALSE;
293 /* Check binary type
295 switch(MODULE_GetBinaryType( hfile ))
297 case BINARY_UNKNOWN:
298 /* try to determine from file name */
299 ptr = strrchr( lpApplicationName, '.' );
300 if (!ptr) break;
301 if (!FILE_strcasecmp( ptr, ".COM" ))
303 *lpBinaryType = SCS_DOS_BINARY;
304 ret = TRUE;
306 else if (!FILE_strcasecmp( ptr, ".PIF" ))
308 *lpBinaryType = SCS_PIF_BINARY;
309 ret = TRUE;
311 break;
312 case BINARY_PE_EXE:
313 case BINARY_PE_DLL:
314 *lpBinaryType = SCS_32BIT_BINARY;
315 ret = TRUE;
316 break;
317 case BINARY_WIN16:
318 *lpBinaryType = SCS_WOW_BINARY;
319 ret = TRUE;
320 break;
321 case BINARY_OS216:
322 *lpBinaryType = SCS_OS216_BINARY;
323 ret = TRUE;
324 break;
325 case BINARY_DOS:
326 *lpBinaryType = SCS_DOS_BINARY;
327 ret = TRUE;
328 break;
329 case BINARY_UNIX_EXE:
330 case BINARY_UNIX_LIB:
331 ret = FALSE;
332 break;
335 CloseHandle( hfile );
336 return ret;
339 /***********************************************************************
340 * GetBinaryTypeW [KERNEL32.@]
342 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
344 BOOL ret = FALSE;
345 LPSTR strNew = NULL;
347 TRACE_(win32)("%s\n", debugstr_w(lpApplicationName) );
349 /* Sanity check.
351 if ( lpApplicationName == NULL || lpBinaryType == NULL )
352 return FALSE;
354 /* Convert the wide string to a ascii string.
356 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
358 if ( strNew != NULL )
360 ret = GetBinaryTypeA( strNew, lpBinaryType );
362 /* Free the allocated string.
364 HeapFree( GetProcessHeap(), 0, strNew );
367 return ret;
371 /***********************************************************************
372 * GetModuleHandleA (KERNEL32.@)
373 * GetModuleHandle32 (KERNEL.488)
375 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
377 NTSTATUS nts;
378 HMODULE ret;
379 UNICODE_STRING wstr;
381 if (!module) return NtCurrentTeb()->Peb->ImageBaseAddress;
383 RtlCreateUnicodeStringFromAsciiz(&wstr, module);
384 nts = LdrGetDllHandle(0, 0, &wstr, &ret);
385 RtlFreeUnicodeString( &wstr );
386 if (nts != STATUS_SUCCESS)
388 ret = 0;
389 SetLastError( RtlNtStatusToDosError( nts ) );
391 return ret;
394 /***********************************************************************
395 * GetModuleHandleW (KERNEL32.@)
397 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
399 NTSTATUS nts;
400 HMODULE ret;
401 UNICODE_STRING wstr;
403 if (!module) return NtCurrentTeb()->Peb->ImageBaseAddress;
405 RtlInitUnicodeString( &wstr, module );
406 nts = LdrGetDllHandle( 0, 0, &wstr, &ret);
407 if (nts != STATUS_SUCCESS)
409 SetLastError( RtlNtStatusToDosError( nts ) );
410 ret = 0;
412 return ret;
416 /***********************************************************************
417 * GetModuleFileNameA (KERNEL32.@)
418 * GetModuleFileName32 (KERNEL.487)
420 * GetModuleFileNameA seems to *always* return the long path;
421 * it's only GetModuleFileName16 that decides between short/long path
422 * by checking if exe version >= 4.0.
423 * (SDK docu doesn't mention this)
425 DWORD WINAPI GetModuleFileNameA(
426 HMODULE hModule, /* [in] module handle (32bit) */
427 LPSTR lpFileName, /* [out] filenamebuffer */
428 DWORD size ) /* [in] size of filenamebuffer */
430 LPWSTR filenameW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
432 if (!filenameW)
434 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
435 return 0;
437 GetModuleFileNameW( hModule, filenameW, size );
438 WideCharToMultiByte( CP_ACP, 0, filenameW, -1, lpFileName, size, NULL, NULL );
439 HeapFree( GetProcessHeap(), 0, filenameW );
440 return strlen( lpFileName );
443 /***********************************************************************
444 * GetModuleFileNameW (KERNEL32.@)
446 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size )
448 ULONG magic;
450 lpFileName[0] = 0;
452 LdrLockLoaderLock( 0, NULL, &magic );
453 if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32))
455 /* 16-bit task - get current NE module name */
456 NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() );
457 if (pModule)
459 WCHAR path[MAX_PATH];
461 MultiByteToWideChar( CP_ACP, 0, NE_MODULE_NAME(pModule), -1, path, MAX_PATH );
462 GetLongPathNameW(path, lpFileName, size);
465 else
467 LDR_MODULE* pldr;
468 NTSTATUS nts;
470 if (!hModule) hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
471 nts = LdrFindEntryForAddress( hModule, &pldr );
472 if (nts == STATUS_SUCCESS) lstrcpynW(lpFileName, pldr->FullDllName.Buffer, size);
473 else SetLastError( RtlNtStatusToDosError( nts ) );
476 LdrUnlockLoaderLock( 0, magic );
478 TRACE( "%s\n", debugstr_w(lpFileName) );
479 return strlenW(lpFileName);
482 /******************************************************************
483 * load_library_as_datafile
485 static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
487 static const WCHAR dotDLL[] = {'.','d','l','l',0};
489 WCHAR filenameW[MAX_PATH];
490 HANDLE hFile = INVALID_HANDLE_VALUE;
491 HANDLE mapping;
492 HMODULE module;
494 *hmod = 0;
496 if (SearchPathW( NULL, (LPCWSTR)name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]),
497 filenameW, NULL ))
499 hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
500 NULL, OPEN_EXISTING, 0, 0 );
502 if (hFile == INVALID_HANDLE_VALUE) return FALSE;
504 mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
505 CloseHandle( hFile );
506 if (!mapping) return FALSE;
508 module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
509 CloseHandle( mapping );
510 if (!module) return FALSE;
512 /* make sure it's a valid PE file */
513 if (!RtlImageNtHeader(module))
515 UnmapViewOfFile( module );
516 return FALSE;
518 *hmod = (HMODULE)((char *)module + 1); /* set low bit of handle to indicate datafile module */
519 return TRUE;
522 /******************************************************************
523 * LoadLibraryExA (KERNEL32.@)
525 * The HFILE parameter is not used and marked reserved in the SDK. I can
526 * only guess that it should force a file to be mapped, but I rather
527 * ignore the parameter because it would be extremely difficult to
528 * integrate this with different types of module representations.
531 HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
533 UNICODE_STRING wstr;
534 NTSTATUS nts;
535 HMODULE hModule;
537 if (!libname)
539 SetLastError(ERROR_INVALID_PARAMETER);
540 return 0;
542 RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
544 if (flags & LOAD_LIBRARY_AS_DATAFILE)
546 /* The method in load_library_as_datafile allows searching for the
547 * 'native' libraries only
549 if (load_library_as_datafile( wstr.Buffer, &hModule))
551 RtlFreeUnicodeString( &wstr );
552 return hModule;
554 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
555 /* Fallback to normal behaviour */
558 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
559 if (nts != STATUS_SUCCESS)
561 hModule = 0;
562 SetLastError( RtlNtStatusToDosError( nts ) );
564 RtlFreeUnicodeString( &wstr );
566 return hModule;
569 /***********************************************************************
570 * LoadLibraryExW (KERNEL32.@)
572 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
574 UNICODE_STRING wstr;
575 NTSTATUS nts;
576 HMODULE hModule;
578 if (!libnameW)
580 SetLastError(ERROR_INVALID_PARAMETER);
581 return 0;
584 if (flags & LOAD_LIBRARY_AS_DATAFILE)
586 /* The method in load_library_as_datafile allows searching for the
587 * 'native' libraries only
589 if (load_library_as_datafile(libnameW, &hModule)) return hModule;
590 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
591 /* Fallback to normal behaviour */
594 RtlInitUnicodeString( &wstr, libnameW );
595 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
596 if (nts != STATUS_SUCCESS)
598 hModule = 0;
599 SetLastError( RtlNtStatusToDosError( nts ) );
601 return hModule;
604 /***********************************************************************
605 * LoadLibraryA (KERNEL32.@)
607 HMODULE WINAPI LoadLibraryA(LPCSTR libname)
609 return LoadLibraryExA(libname, 0, 0);
612 /***********************************************************************
613 * LoadLibraryW (KERNEL32.@)
615 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
617 return LoadLibraryExW(libnameW, 0, 0);
620 /***********************************************************************
621 * FreeLibrary (KERNEL32.@)
622 * FreeLibrary32 (KERNEL.486)
624 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
626 BOOL retv = FALSE;
627 NTSTATUS nts;
629 if (!hLibModule)
631 SetLastError( ERROR_INVALID_HANDLE );
632 return FALSE;
635 if ((ULONG_PTR)hLibModule & 1)
637 /* this is a LOAD_LIBRARY_AS_DATAFILE module */
638 char *ptr = (char *)hLibModule - 1;
639 UnmapViewOfFile( ptr );
640 return TRUE;
643 if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
644 else SetLastError( RtlNtStatusToDosError( nts ) );
646 return retv;
649 /***********************************************************************
650 * GetProcAddress (KERNEL32.@)
652 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
654 NTSTATUS nts;
655 FARPROC fp;
657 if (HIWORD(function))
659 ANSI_STRING str;
661 RtlInitAnsiString( &str, function );
662 nts = LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp );
664 else
665 nts = LdrGetProcedureAddress( hModule, NULL, (DWORD)function, (void**)&fp );
666 if (nts != STATUS_SUCCESS)
668 SetLastError( RtlNtStatusToDosError( nts ) );
669 fp = NULL;
671 return fp;
674 /***********************************************************************
675 * GetProcAddress32 (KERNEL.453)
677 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
679 /* FIXME: we used to disable snoop when returning proc for Win16 subsystem */
680 return GetProcAddress( hModule, function );