Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / loader / module.c
blob590fa5c7dbb31195663040394b82540a2b1fc623
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 * wait_input_idle
58 * Wrapper to call WaitForInputIdle USER function
60 typedef DWORD (WINAPI *WaitForInputIdle_ptr)( HANDLE hProcess, DWORD dwTimeOut );
62 static DWORD wait_input_idle( HANDLE process, DWORD timeout )
64 HMODULE mod = GetModuleHandleA( "user32.dll" );
65 if (mod)
67 WaitForInputIdle_ptr ptr = (WaitForInputIdle_ptr)GetProcAddress( mod, "WaitForInputIdle" );
68 if (ptr) return ptr( process, timeout );
70 return 0;
74 /****************************************************************************
75 * DisableThreadLibraryCalls (KERNEL32.@)
77 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
79 BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
81 NTSTATUS nts = LdrDisableThreadCalloutsForDll( hModule );
82 if (nts == STATUS_SUCCESS) return TRUE;
84 SetLastError( RtlNtStatusToDosError( nts ) );
85 return FALSE;
89 /* Check whether a file is an OS/2 or a very old Windows executable
90 * by testing on import of KERNEL.
92 * FIXME: is reading the module imports the only way of discerning
93 * old Windows binaries from OS/2 ones ? At least it seems so...
95 static enum binary_type MODULE_Decide_OS2_OldWin(HANDLE hfile, const IMAGE_DOS_HEADER *mz,
96 const IMAGE_OS2_HEADER *ne)
98 DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
99 enum binary_type ret = BINARY_OS216;
100 LPWORD modtab = NULL;
101 LPSTR nametab = NULL;
102 DWORD len;
103 int i;
105 /* read modref table */
106 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_modtab, NULL, SEEK_SET ) == -1)
107 || (!(modtab = HeapAlloc( GetProcessHeap(), 0, ne->ne_cmod*sizeof(WORD))))
108 || (!(ReadFile(hfile, modtab, ne->ne_cmod*sizeof(WORD), &len, NULL)))
109 || (len != ne->ne_cmod*sizeof(WORD)) )
110 goto broken;
112 /* read imported names table */
113 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_imptab, NULL, SEEK_SET ) == -1)
114 || (!(nametab = HeapAlloc( GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab)))
115 || (!(ReadFile(hfile, nametab, ne->ne_enttab - ne->ne_imptab, &len, NULL)))
116 || (len != ne->ne_enttab - ne->ne_imptab) )
117 goto broken;
119 for (i=0; i < ne->ne_cmod; i++)
121 LPSTR module = &nametab[modtab[i]];
122 TRACE("modref: %.*s\n", module[0], &module[1]);
123 if (!(strncmp(&module[1], "KERNEL", module[0])))
124 { /* very old Windows file */
125 MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
126 ret = BINARY_WIN16;
127 goto good;
131 broken:
132 ERR("Hmm, an error occurred. Is this binary file broken ?\n");
134 good:
135 HeapFree( GetProcessHeap(), 0, modtab);
136 HeapFree( GetProcessHeap(), 0, nametab);
137 SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
138 return ret;
141 /***********************************************************************
142 * MODULE_GetBinaryType
144 enum binary_type MODULE_GetBinaryType( HANDLE hfile )
146 union
148 struct
150 unsigned char magic[4];
151 unsigned char ignored[12];
152 unsigned short type;
153 } elf;
154 struct
156 unsigned long magic;
157 unsigned long cputype;
158 unsigned long cpusubtype;
159 unsigned long filetype;
160 } macho;
161 IMAGE_DOS_HEADER mz;
162 } header;
164 char magic[4];
165 DWORD len;
167 /* Seek to the start of the file and read the header information. */
168 if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1)
169 return BINARY_UNKNOWN;
170 if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
171 return BINARY_UNKNOWN;
173 if (!memcmp( header.elf.magic, "\177ELF", 4 ))
175 /* FIXME: we don't bother to check byte order, architecture, etc. */
176 switch(header.elf.type)
178 case 2: return BINARY_UNIX_EXE;
179 case 3: return BINARY_UNIX_LIB;
181 return BINARY_UNKNOWN;
184 /* Mach-o File with Endian set to Big Endian or Little Endian*/
185 if (header.macho.magic == 0xfeedface || header.macho.magic == 0xecafdeef)
187 switch(header.macho.filetype)
189 case 0x8: /* MH_BUNDLE */ return BINARY_UNIX_LIB;
191 return BINARY_UNKNOWN;
194 /* Not ELF, try DOS */
196 if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
198 /* We do have a DOS image so we will now try to seek into
199 * the file by the amount indicated by the field
200 * "Offset to extended header" and read in the
201 * "magic" field information at that location.
202 * This will tell us if there is more header information
203 * to read or not.
205 /* But before we do we will make sure that header
206 * structure encompasses the "Offset to extended header"
207 * field.
209 if (header.mz.e_lfanew < sizeof(IMAGE_DOS_HEADER))
210 return BINARY_DOS;
211 if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
212 return BINARY_DOS;
213 if (!ReadFile( hfile, magic, sizeof(magic), &len, NULL ) || len != sizeof(magic))
214 return BINARY_DOS;
216 /* Reading the magic field succeeded so
217 * we will try to determine what type it is.
219 if (!memcmp( magic, "PE\0\0", 4 ))
221 IMAGE_FILE_HEADER FileHeader;
223 if (ReadFile( hfile, &FileHeader, sizeof(FileHeader), &len, NULL ) && len == sizeof(FileHeader))
225 if (FileHeader.Characteristics & IMAGE_FILE_DLL) return BINARY_PE_DLL;
226 return BINARY_PE_EXE;
228 return BINARY_DOS;
231 if (!memcmp( magic, "NE", 2 ))
233 /* This is a Windows executable (NE) header. This can
234 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
235 * DOS program (running under a DOS extender). To decide
236 * which, we'll have to read the NE header.
238 IMAGE_OS2_HEADER ne;
239 if ( SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1
240 && ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
241 && len == sizeof(ne) )
243 switch ( ne.ne_exetyp )
245 case 2: return BINARY_WIN16;
246 case 5: return BINARY_DOS;
247 default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ne);
250 /* Couldn't read header, so abort. */
251 return BINARY_DOS;
254 /* Unknown extended header, but this file is nonetheless DOS-executable. */
255 return BINARY_DOS;
258 return BINARY_UNKNOWN;
261 /***********************************************************************
262 * GetBinaryTypeA [KERNEL32.@]
263 * GetBinaryType [KERNEL32.@]
265 * The GetBinaryType function determines whether a file is executable
266 * or not and if it is it returns what type of executable it is.
267 * The type of executable is a property that determines in which
268 * subsystem an executable file runs under.
270 * Binary types returned:
271 * SCS_32BIT_BINARY: A Win32 based application
272 * SCS_DOS_BINARY: An MS-Dos based application
273 * SCS_WOW_BINARY: A Win16 based application
274 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
275 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
276 * SCS_OS216_BINARY: A 16bit OS/2 based application
278 * Returns TRUE if the file is an executable in which case
279 * the value pointed by lpBinaryType is set.
280 * Returns FALSE if the file is not an executable or if the function fails.
282 * To do so it opens the file and reads in the header information
283 * if the extended header information is not present it will
284 * assume that the file is a DOS executable.
285 * If the extended header information is present it will
286 * determine if the file is a 16 or 32 bit Windows executable
287 * by check the flags in the header.
289 * Note that .COM and .PIF files are only recognized by their
290 * file name extension; but Windows does it the same way ...
292 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
294 BOOL ret = FALSE;
295 HANDLE hfile;
296 char *ptr;
298 TRACE_(win32)("%s\n", lpApplicationName );
300 /* Sanity check.
302 if ( lpApplicationName == NULL || lpBinaryType == NULL )
303 return FALSE;
305 /* Open the file indicated by lpApplicationName for reading.
307 hfile = CreateFileA( lpApplicationName, GENERIC_READ, FILE_SHARE_READ,
308 NULL, OPEN_EXISTING, 0, 0 );
309 if ( hfile == INVALID_HANDLE_VALUE )
310 return FALSE;
312 /* Check binary type
314 switch(MODULE_GetBinaryType( hfile ))
316 case BINARY_UNKNOWN:
317 /* try to determine from file name */
318 ptr = strrchr( lpApplicationName, '.' );
319 if (!ptr) break;
320 if (!FILE_strcasecmp( ptr, ".COM" ))
322 *lpBinaryType = SCS_DOS_BINARY;
323 ret = TRUE;
325 else if (!FILE_strcasecmp( ptr, ".PIF" ))
327 *lpBinaryType = SCS_PIF_BINARY;
328 ret = TRUE;
330 break;
331 case BINARY_PE_EXE:
332 case BINARY_PE_DLL:
333 *lpBinaryType = SCS_32BIT_BINARY;
334 ret = TRUE;
335 break;
336 case BINARY_WIN16:
337 *lpBinaryType = SCS_WOW_BINARY;
338 ret = TRUE;
339 break;
340 case BINARY_OS216:
341 *lpBinaryType = SCS_OS216_BINARY;
342 ret = TRUE;
343 break;
344 case BINARY_DOS:
345 *lpBinaryType = SCS_DOS_BINARY;
346 ret = TRUE;
347 break;
348 case BINARY_UNIX_EXE:
349 case BINARY_UNIX_LIB:
350 ret = FALSE;
351 break;
354 CloseHandle( hfile );
355 return ret;
358 /***********************************************************************
359 * GetBinaryTypeW [KERNEL32.@]
361 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
363 BOOL ret = FALSE;
364 LPSTR strNew = NULL;
366 TRACE_(win32)("%s\n", debugstr_w(lpApplicationName) );
368 /* Sanity check.
370 if ( lpApplicationName == NULL || lpBinaryType == NULL )
371 return FALSE;
373 /* Convert the wide string to a ascii string.
375 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
377 if ( strNew != NULL )
379 ret = GetBinaryTypeA( strNew, lpBinaryType );
381 /* Free the allocated string.
383 HeapFree( GetProcessHeap(), 0, strNew );
386 return ret;
390 /***********************************************************************
391 * WinExec (KERNEL32.@)
393 UINT WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
395 PROCESS_INFORMATION info;
396 STARTUPINFOA startup;
397 char *cmdline;
398 UINT ret;
400 memset( &startup, 0, sizeof(startup) );
401 startup.cb = sizeof(startup);
402 startup.dwFlags = STARTF_USESHOWWINDOW;
403 startup.wShowWindow = nCmdShow;
405 /* cmdline needs to be writeable for CreateProcess */
406 if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(lpCmdLine)+1 ))) return 0;
407 strcpy( cmdline, lpCmdLine );
409 if (CreateProcessA( NULL, cmdline, NULL, NULL, FALSE,
410 0, NULL, NULL, &startup, &info ))
412 /* Give 30 seconds to the app to come up */
413 if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF)
414 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
415 ret = 33;
416 /* Close off the handles */
417 CloseHandle( info.hThread );
418 CloseHandle( info.hProcess );
420 else if ((ret = GetLastError()) >= 32)
422 FIXME("Strange error set by CreateProcess: %d\n", ret );
423 ret = 11;
425 HeapFree( GetProcessHeap(), 0, cmdline );
426 return ret;
429 /**********************************************************************
430 * LoadModule (KERNEL32.@)
432 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
434 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
435 PROCESS_INFORMATION info;
436 STARTUPINFOA startup;
437 HINSTANCE hInstance;
438 LPSTR cmdline, p;
439 char filename[MAX_PATH];
440 BYTE len;
442 if (!name) return (HINSTANCE)ERROR_FILE_NOT_FOUND;
444 if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
445 !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
446 return (HINSTANCE)GetLastError();
448 len = (BYTE)params->lpCmdLine[0];
449 if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
450 return (HINSTANCE)ERROR_NOT_ENOUGH_MEMORY;
452 strcpy( cmdline, filename );
453 p = cmdline + strlen(cmdline);
454 *p++ = ' ';
455 memcpy( p, params->lpCmdLine + 1, len );
456 p[len] = 0;
458 memset( &startup, 0, sizeof(startup) );
459 startup.cb = sizeof(startup);
460 if (params->lpCmdShow)
462 startup.dwFlags = STARTF_USESHOWWINDOW;
463 startup.wShowWindow = params->lpCmdShow[1];
466 if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
467 params->lpEnvAddress, NULL, &startup, &info ))
469 /* Give 30 seconds to the app to come up */
470 if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF )
471 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
472 hInstance = (HINSTANCE)33;
473 /* Close off the handles */
474 CloseHandle( info.hThread );
475 CloseHandle( info.hProcess );
477 else if ((hInstance = (HINSTANCE)GetLastError()) >= (HINSTANCE)32)
479 FIXME("Strange error set by CreateProcess: %p\n", hInstance );
480 hInstance = (HINSTANCE)11;
483 HeapFree( GetProcessHeap(), 0, cmdline );
484 return hInstance;
488 /***********************************************************************
489 * GetModuleHandleA (KERNEL32.@)
490 * GetModuleHandle32 (KERNEL.488)
492 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
494 NTSTATUS nts;
495 HMODULE ret;
496 UNICODE_STRING wstr;
498 if (!module) return NtCurrentTeb()->Peb->ImageBaseAddress;
500 RtlCreateUnicodeStringFromAsciiz(&wstr, module);
501 nts = LdrGetDllHandle(0, 0, &wstr, &ret);
502 RtlFreeUnicodeString( &wstr );
503 if (nts != STATUS_SUCCESS)
505 ret = 0;
506 SetLastError( RtlNtStatusToDosError( nts ) );
508 return ret;
511 /***********************************************************************
512 * GetModuleHandleW (KERNEL32.@)
514 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
516 NTSTATUS nts;
517 HMODULE ret;
518 UNICODE_STRING wstr;
520 if (!module) return NtCurrentTeb()->Peb->ImageBaseAddress;
522 RtlInitUnicodeString( &wstr, module );
523 nts = LdrGetDllHandle( 0, 0, &wstr, &ret);
524 if (nts != STATUS_SUCCESS)
526 SetLastError( RtlNtStatusToDosError( nts ) );
527 ret = 0;
529 return ret;
533 /***********************************************************************
534 * GetModuleFileNameA (KERNEL32.@)
535 * GetModuleFileName32 (KERNEL.487)
537 * GetModuleFileNameA seems to *always* return the long path;
538 * it's only GetModuleFileName16 that decides between short/long path
539 * by checking if exe version >= 4.0.
540 * (SDK docu doesn't mention this)
542 DWORD WINAPI GetModuleFileNameA(
543 HMODULE hModule, /* [in] module handle (32bit) */
544 LPSTR lpFileName, /* [out] filenamebuffer */
545 DWORD size ) /* [in] size of filenamebuffer */
547 LPWSTR filenameW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
549 if (!filenameW)
551 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
552 return 0;
554 GetModuleFileNameW( hModule, filenameW, size );
555 WideCharToMultiByte( CP_ACP, 0, filenameW, -1, lpFileName, size, NULL, NULL );
556 HeapFree( GetProcessHeap(), 0, filenameW );
557 return strlen( lpFileName );
560 /***********************************************************************
561 * GetModuleFileNameW (KERNEL32.@)
563 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size )
565 ULONG magic;
567 lpFileName[0] = 0;
569 LdrLockLoaderLock( 0, NULL, &magic );
570 if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32))
572 /* 16-bit task - get current NE module name */
573 NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() );
574 if (pModule)
576 WCHAR path[MAX_PATH];
578 MultiByteToWideChar( CP_ACP, 0, NE_MODULE_NAME(pModule), -1, path, MAX_PATH );
579 GetLongPathNameW(path, lpFileName, size);
582 else
584 LDR_MODULE* pldr;
585 NTSTATUS nts;
587 if (!hModule) hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
588 nts = LdrFindEntryForAddress( hModule, &pldr );
589 if (nts == STATUS_SUCCESS) lstrcpynW(lpFileName, pldr->FullDllName.Buffer, size);
590 else SetLastError( RtlNtStatusToDosError( nts ) );
593 LdrUnlockLoaderLock( 0, magic );
595 TRACE( "%s\n", debugstr_w(lpFileName) );
596 return strlenW(lpFileName);
599 /******************************************************************
600 * load_library_as_datafile
602 static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
604 static const WCHAR dotDLL[] = {'.','d','l','l',0};
606 WCHAR filenameW[MAX_PATH];
607 HANDLE hFile = INVALID_HANDLE_VALUE;
608 HANDLE mapping;
610 *hmod = 0;
612 if (SearchPathW( NULL, (LPCWSTR)name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]),
613 filenameW, NULL ))
615 hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
616 NULL, OPEN_EXISTING, 0, 0 );
618 if (hFile == INVALID_HANDLE_VALUE) return FALSE;
619 switch (MODULE_GetBinaryType( hFile ))
621 case BINARY_PE_EXE:
622 case BINARY_PE_DLL:
623 mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
624 if (mapping)
626 *hmod = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
627 CloseHandle( mapping );
629 break;
630 default:
631 break;
633 CloseHandle( hFile );
635 return *hmod != 0;
638 /******************************************************************
639 * LoadLibraryExA (KERNEL32.@)
641 * The HFILE parameter is not used and marked reserved in the SDK. I can
642 * only guess that it should force a file to be mapped, but I rather
643 * ignore the parameter because it would be extremely difficult to
644 * integrate this with different types of module representations.
647 HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
649 UNICODE_STRING wstr;
650 NTSTATUS nts;
651 HMODULE hModule;
653 if (!libname)
655 SetLastError(ERROR_INVALID_PARAMETER);
656 return 0;
658 RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
660 if (flags & LOAD_LIBRARY_AS_DATAFILE)
662 /* The method in load_library_as_datafile allows searching for the
663 * 'native' libraries only
665 if (load_library_as_datafile( wstr.Buffer, &hModule))
667 RtlFreeUnicodeString( &wstr );
668 return (HMODULE)((ULONG_PTR)hModule + 1);
670 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
671 /* Fallback to normal behaviour */
674 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
675 if (nts != STATUS_SUCCESS)
677 hModule = 0;
678 SetLastError( RtlNtStatusToDosError( nts ) );
680 RtlFreeUnicodeString( &wstr );
682 return hModule;
685 /***********************************************************************
686 * LoadLibraryExW (KERNEL32.@)
688 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
690 UNICODE_STRING wstr;
691 NTSTATUS nts;
692 HMODULE hModule;
694 if (!libnameW)
696 SetLastError(ERROR_INVALID_PARAMETER);
697 return 0;
700 if (flags & LOAD_LIBRARY_AS_DATAFILE)
702 /* The method in load_library_as_datafile allows searching for the
703 * 'native' libraries only
705 if (load_library_as_datafile(libnameW, &hModule))
706 return (HMODULE)((ULONG_PTR)hModule + 1);
707 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
708 /* Fallback to normal behaviour */
711 RtlInitUnicodeString( &wstr, libnameW );
712 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
713 if (nts != STATUS_SUCCESS)
715 hModule = 0;
716 SetLastError( RtlNtStatusToDosError( nts ) );
718 return hModule;
721 /***********************************************************************
722 * LoadLibraryA (KERNEL32.@)
724 HMODULE WINAPI LoadLibraryA(LPCSTR libname)
726 return LoadLibraryExA(libname, 0, 0);
729 /***********************************************************************
730 * LoadLibraryW (KERNEL32.@)
732 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
734 return LoadLibraryExW(libnameW, 0, 0);
737 /***********************************************************************
738 * LoadLibrary32 (KERNEL.452)
739 * LoadSystemLibrary32 (KERNEL.482)
741 HMODULE WINAPI LoadLibrary32_16( LPCSTR libname )
743 HMODULE hModule;
744 DWORD count;
746 ReleaseThunkLock( &count );
747 hModule = LoadLibraryA( libname );
748 RestoreThunkLock( count );
749 return hModule;
752 /***********************************************************************
753 * FreeLibrary (KERNEL32.@)
754 * FreeLibrary32 (KERNEL.486)
756 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
758 BOOL retv = FALSE;
759 NTSTATUS nts;
761 if (!hLibModule)
763 SetLastError( ERROR_INVALID_HANDLE );
764 return FALSE;
767 if ((ULONG_PTR)hLibModule & 1)
769 /* this is a LOAD_LIBRARY_AS_DATAFILE module */
770 char *ptr = (char *)hLibModule - 1;
771 UnmapViewOfFile( ptr );
772 return TRUE;
775 if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
776 else SetLastError( RtlNtStatusToDosError( nts ) );
778 return retv;
781 /***********************************************************************
782 * FreeLibraryAndExitThread (KERNEL32.@)
784 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
786 FreeLibrary(hLibModule);
787 ExitThread(dwExitCode);
790 /***********************************************************************
791 * GetProcAddress (KERNEL32.@)
793 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
795 NTSTATUS nts;
796 FARPROC fp;
798 if (HIWORD(function))
800 ANSI_STRING str;
802 RtlInitAnsiString( &str, function );
803 nts = LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp );
805 else
806 nts = LdrGetProcedureAddress( hModule, NULL, (DWORD)function, (void**)&fp );
807 if (nts != STATUS_SUCCESS)
809 SetLastError( RtlNtStatusToDosError( nts ) );
810 fp = NULL;
812 return fp;
815 /***********************************************************************
816 * GetProcAddress32 (KERNEL.453)
818 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
820 /* FIXME: we used to disable snoop when returning proc for Win16 subsystem */
821 return GetProcAddress( hModule, function );