Make sure dllname doesn't get optimized out (spotted by Marcus
[wine/multimedia.git] / loader / module.c
bloba54e87207427fec8dad58037039943c2682a7088
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 <stdio.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include "wine/winbase16.h"
34 #include "winerror.h"
35 #include "winternl.h"
36 #include "heap.h"
37 #include "file.h"
38 #include "module.h"
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
42 #include "wine/server.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(module);
45 WINE_DECLARE_DEBUG_CHANNEL(win32);
46 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
49 /***********************************************************************
50 * wait_input_idle
52 * Wrapper to call WaitForInputIdle USER function
54 typedef DWORD (WINAPI *WaitForInputIdle_ptr)( HANDLE hProcess, DWORD dwTimeOut );
56 static DWORD wait_input_idle( HANDLE process, DWORD timeout )
58 HMODULE mod = GetModuleHandleA( "user32.dll" );
59 if (mod)
61 WaitForInputIdle_ptr ptr = (WaitForInputIdle_ptr)GetProcAddress( mod, "WaitForInputIdle" );
62 if (ptr) return ptr( process, timeout );
64 return 0;
68 /****************************************************************************
69 * DisableThreadLibraryCalls (KERNEL32.@)
71 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
73 BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
75 NTSTATUS nts = LdrDisableThreadCalloutsForDll( hModule );
76 if (nts == STATUS_SUCCESS) return TRUE;
78 SetLastError( RtlNtStatusToDosError( nts ) );
79 return FALSE;
83 /* Check whether a file is an OS/2 or a very old Windows executable
84 * by testing on import of KERNEL.
86 * FIXME: is reading the module imports the only way of discerning
87 * old Windows binaries from OS/2 ones ? At least it seems so...
89 static enum binary_type MODULE_Decide_OS2_OldWin(HANDLE hfile, const IMAGE_DOS_HEADER *mz,
90 const IMAGE_OS2_HEADER *ne)
92 DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
93 enum binary_type ret = BINARY_OS216;
94 LPWORD modtab = NULL;
95 LPSTR nametab = NULL;
96 DWORD len;
97 int i;
99 /* read modref table */
100 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_modtab, NULL, SEEK_SET ) == -1)
101 || (!(modtab = HeapAlloc( GetProcessHeap(), 0, ne->ne_cmod*sizeof(WORD))))
102 || (!(ReadFile(hfile, modtab, ne->ne_cmod*sizeof(WORD), &len, NULL)))
103 || (len != ne->ne_cmod*sizeof(WORD)) )
104 goto broken;
106 /* read imported names table */
107 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_imptab, NULL, SEEK_SET ) == -1)
108 || (!(nametab = HeapAlloc( GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab)))
109 || (!(ReadFile(hfile, nametab, ne->ne_enttab - ne->ne_imptab, &len, NULL)))
110 || (len != ne->ne_enttab - ne->ne_imptab) )
111 goto broken;
113 for (i=0; i < ne->ne_cmod; i++)
115 LPSTR module = &nametab[modtab[i]];
116 TRACE("modref: %.*s\n", module[0], &module[1]);
117 if (!(strncmp(&module[1], "KERNEL", module[0])))
118 { /* very old Windows file */
119 MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
120 ret = BINARY_WIN16;
121 goto good;
125 broken:
126 ERR("Hmm, an error occurred. Is this binary file broken ?\n");
128 good:
129 HeapFree( GetProcessHeap(), 0, modtab);
130 HeapFree( GetProcessHeap(), 0, nametab);
131 SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
132 return ret;
135 /***********************************************************************
136 * MODULE_GetBinaryType
138 enum binary_type MODULE_GetBinaryType( HANDLE hfile )
140 union
142 struct
144 unsigned char magic[4];
145 unsigned char ignored[12];
146 unsigned short type;
147 } elf;
148 struct
150 unsigned long magic;
151 unsigned long cputype;
152 unsigned long cpusubtype;
153 unsigned long filetype;
154 } macho;
155 IMAGE_DOS_HEADER mz;
156 } header;
158 char magic[4];
159 DWORD len;
161 /* Seek to the start of the file and read the header information. */
162 if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1)
163 return BINARY_UNKNOWN;
164 if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
165 return BINARY_UNKNOWN;
167 if (!memcmp( header.elf.magic, "\177ELF", 4 ))
169 /* FIXME: we don't bother to check byte order, architecture, etc. */
170 switch(header.elf.type)
172 case 2: return BINARY_UNIX_EXE;
173 case 3: return BINARY_UNIX_LIB;
175 return BINARY_UNKNOWN;
178 /* Mach-o File with Endian set to Big Endian or Little Endian*/
179 if (header.macho.magic == 0xfeedface || header.macho.magic == 0xecafdeef)
181 switch(header.macho.filetype)
183 case 0x8: /* MH_BUNDLE */ return BINARY_UNIX_LIB;
185 return BINARY_UNKNOWN;
188 /* Not ELF, try DOS */
190 if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
192 /* We do have a DOS image so we will now try to seek into
193 * the file by the amount indicated by the field
194 * "Offset to extended header" and read in the
195 * "magic" field information at that location.
196 * This will tell us if there is more header information
197 * to read or not.
199 /* But before we do we will make sure that header
200 * structure encompasses the "Offset to extended header"
201 * field.
203 if ((header.mz.e_cparhdr << 4) < sizeof(IMAGE_DOS_HEADER))
204 return BINARY_DOS;
205 if (header.mz.e_crlc && (header.mz.e_lfarlc < sizeof(IMAGE_DOS_HEADER)))
206 return BINARY_DOS;
207 if (header.mz.e_lfanew < sizeof(IMAGE_DOS_HEADER))
208 return BINARY_DOS;
209 if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
210 return BINARY_DOS;
211 if (!ReadFile( hfile, magic, sizeof(magic), &len, NULL ) || len != sizeof(magic))
212 return BINARY_DOS;
214 /* Reading the magic field succeeded so
215 * we will try to determine what type it is.
217 if (!memcmp( magic, "PE\0\0", 4 ))
219 IMAGE_FILE_HEADER FileHeader;
221 if (ReadFile( hfile, &FileHeader, sizeof(FileHeader), &len, NULL ) && len == sizeof(FileHeader))
223 if (FileHeader.Characteristics & IMAGE_FILE_DLL) return BINARY_PE_DLL;
224 return BINARY_PE_EXE;
226 return BINARY_DOS;
229 if (!memcmp( magic, "NE", 2 ))
231 /* This is a Windows executable (NE) header. This can
232 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
233 * DOS program (running under a DOS extender). To decide
234 * which, we'll have to read the NE header.
236 IMAGE_OS2_HEADER ne;
237 if ( SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1
238 && ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
239 && len == sizeof(ne) )
241 switch ( ne.ne_exetyp )
243 case 2: return BINARY_WIN16;
244 case 5: return BINARY_DOS;
245 default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ne);
248 /* Couldn't read header, so abort. */
249 return BINARY_DOS;
252 /* Unknown extended header, but this file is nonetheless DOS-executable. */
253 return BINARY_DOS;
256 return BINARY_UNKNOWN;
259 /***********************************************************************
260 * GetBinaryTypeA [KERNEL32.@]
261 * GetBinaryType [KERNEL32.@]
263 * The GetBinaryType function determines whether a file is executable
264 * or not and if it is it returns what type of executable it is.
265 * The type of executable is a property that determines in which
266 * subsystem an executable file runs under.
268 * Binary types returned:
269 * SCS_32BIT_BINARY: A Win32 based application
270 * SCS_DOS_BINARY: An MS-Dos based application
271 * SCS_WOW_BINARY: A Win16 based application
272 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
273 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
274 * SCS_OS216_BINARY: A 16bit OS/2 based application
276 * Returns TRUE if the file is an executable in which case
277 * the value pointed by lpBinaryType is set.
278 * Returns FALSE if the file is not an executable or if the function fails.
280 * To do so it opens the file and reads in the header information
281 * if the extended header information is not present it will
282 * assume that the file is a DOS executable.
283 * If the extended header information is present it will
284 * determine if the file is a 16 or 32 bit Windows executable
285 * by check the flags in the header.
287 * Note that .COM and .PIF files are only recognized by their
288 * file name extension; but Windows does it the same way ...
290 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
292 BOOL ret = FALSE;
293 HANDLE hfile;
294 char *ptr;
296 TRACE_(win32)("%s\n", lpApplicationName );
298 /* Sanity check.
300 if ( lpApplicationName == NULL || lpBinaryType == NULL )
301 return FALSE;
303 /* Open the file indicated by lpApplicationName for reading.
305 hfile = CreateFileA( lpApplicationName, GENERIC_READ, FILE_SHARE_READ,
306 NULL, OPEN_EXISTING, 0, 0 );
307 if ( hfile == INVALID_HANDLE_VALUE )
308 return FALSE;
310 /* Check binary type
312 switch(MODULE_GetBinaryType( hfile ))
314 case BINARY_UNKNOWN:
315 /* try to determine from file name */
316 ptr = strrchr( lpApplicationName, '.' );
317 if (!ptr) break;
318 if (!FILE_strcasecmp( ptr, ".COM" ))
320 *lpBinaryType = SCS_DOS_BINARY;
321 ret = TRUE;
323 else if (!FILE_strcasecmp( ptr, ".PIF" ))
325 *lpBinaryType = SCS_PIF_BINARY;
326 ret = TRUE;
328 break;
329 case BINARY_PE_EXE:
330 case BINARY_PE_DLL:
331 *lpBinaryType = SCS_32BIT_BINARY;
332 ret = TRUE;
333 break;
334 case BINARY_WIN16:
335 *lpBinaryType = SCS_WOW_BINARY;
336 ret = TRUE;
337 break;
338 case BINARY_OS216:
339 *lpBinaryType = SCS_OS216_BINARY;
340 ret = TRUE;
341 break;
342 case BINARY_DOS:
343 *lpBinaryType = SCS_DOS_BINARY;
344 ret = TRUE;
345 break;
346 case BINARY_UNIX_EXE:
347 case BINARY_UNIX_LIB:
348 ret = FALSE;
349 break;
352 CloseHandle( hfile );
353 return ret;
356 /***********************************************************************
357 * GetBinaryTypeW [KERNEL32.@]
359 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
361 BOOL ret = FALSE;
362 LPSTR strNew = NULL;
364 TRACE_(win32)("%s\n", debugstr_w(lpApplicationName) );
366 /* Sanity check.
368 if ( lpApplicationName == NULL || lpBinaryType == NULL )
369 return FALSE;
371 /* Convert the wide string to a ascii string.
373 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
375 if ( strNew != NULL )
377 ret = GetBinaryTypeA( strNew, lpBinaryType );
379 /* Free the allocated string.
381 HeapFree( GetProcessHeap(), 0, strNew );
384 return ret;
388 /***********************************************************************
389 * WinExec (KERNEL32.@)
391 UINT WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
393 PROCESS_INFORMATION info;
394 STARTUPINFOA startup;
395 char *cmdline;
396 UINT ret;
398 memset( &startup, 0, sizeof(startup) );
399 startup.cb = sizeof(startup);
400 startup.dwFlags = STARTF_USESHOWWINDOW;
401 startup.wShowWindow = nCmdShow;
403 /* cmdline needs to be writeable for CreateProcess */
404 if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(lpCmdLine)+1 ))) return 0;
405 strcpy( cmdline, lpCmdLine );
407 if (CreateProcessA( NULL, cmdline, NULL, NULL, FALSE,
408 0, NULL, NULL, &startup, &info ))
410 /* Give 30 seconds to the app to come up */
411 if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF)
412 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
413 ret = 33;
414 /* Close off the handles */
415 CloseHandle( info.hThread );
416 CloseHandle( info.hProcess );
418 else if ((ret = GetLastError()) >= 32)
420 FIXME("Strange error set by CreateProcess: %d\n", ret );
421 ret = 11;
423 HeapFree( GetProcessHeap(), 0, cmdline );
424 return ret;
427 /**********************************************************************
428 * LoadModule (KERNEL32.@)
430 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
432 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
433 PROCESS_INFORMATION info;
434 STARTUPINFOA startup;
435 HINSTANCE hInstance;
436 LPSTR cmdline, p;
437 char filename[MAX_PATH];
438 BYTE len;
440 if (!name) return (HINSTANCE)ERROR_FILE_NOT_FOUND;
442 if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
443 !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
444 return (HINSTANCE)GetLastError();
446 len = (BYTE)params->lpCmdLine[0];
447 if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
448 return (HINSTANCE)ERROR_NOT_ENOUGH_MEMORY;
450 strcpy( cmdline, filename );
451 p = cmdline + strlen(cmdline);
452 *p++ = ' ';
453 memcpy( p, params->lpCmdLine + 1, len );
454 p[len] = 0;
456 memset( &startup, 0, sizeof(startup) );
457 startup.cb = sizeof(startup);
458 if (params->lpCmdShow)
460 startup.dwFlags = STARTF_USESHOWWINDOW;
461 startup.wShowWindow = params->lpCmdShow[1];
464 if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
465 params->lpEnvAddress, NULL, &startup, &info ))
467 /* Give 30 seconds to the app to come up */
468 if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF )
469 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
470 hInstance = (HINSTANCE)33;
471 /* Close off the handles */
472 CloseHandle( info.hThread );
473 CloseHandle( info.hProcess );
475 else if ((hInstance = (HINSTANCE)GetLastError()) >= (HINSTANCE)32)
477 FIXME("Strange error set by CreateProcess: %p\n", hInstance );
478 hInstance = (HINSTANCE)11;
481 HeapFree( GetProcessHeap(), 0, cmdline );
482 return hInstance;
486 /***********************************************************************
487 * GetModuleHandleA (KERNEL32.@)
488 * GetModuleHandle32 (KERNEL.488)
490 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
492 NTSTATUS nts;
493 HMODULE ret;
494 UNICODE_STRING wstr;
496 if (!module) return NtCurrentTeb()->Peb->ImageBaseAddress;
498 RtlCreateUnicodeStringFromAsciiz(&wstr, module);
499 nts = LdrGetDllHandle(0, 0, &wstr, &ret);
500 RtlFreeUnicodeString( &wstr );
501 if (nts != STATUS_SUCCESS)
503 ret = 0;
504 SetLastError( RtlNtStatusToDosError( nts ) );
506 return ret;
509 /***********************************************************************
510 * GetModuleHandleW (KERNEL32.@)
512 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
514 NTSTATUS nts;
515 HMODULE ret;
516 UNICODE_STRING wstr;
518 if (!module) return NtCurrentTeb()->Peb->ImageBaseAddress;
520 RtlInitUnicodeString( &wstr, module );
521 nts = LdrGetDllHandle( 0, 0, &wstr, &ret);
522 if (nts != STATUS_SUCCESS)
524 SetLastError( RtlNtStatusToDosError( nts ) );
525 ret = 0;
527 return ret;
531 /***********************************************************************
532 * GetModuleFileNameA (KERNEL32.@)
533 * GetModuleFileName32 (KERNEL.487)
535 * GetModuleFileNameA seems to *always* return the long path;
536 * it's only GetModuleFileName16 that decides between short/long path
537 * by checking if exe version >= 4.0.
538 * (SDK docu doesn't mention this)
540 DWORD WINAPI GetModuleFileNameA(
541 HMODULE hModule, /* [in] module handle (32bit) */
542 LPSTR lpFileName, /* [out] filenamebuffer */
543 DWORD size ) /* [in] size of filenamebuffer */
545 LPWSTR filenameW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
547 if (!filenameW)
549 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
550 return 0;
552 GetModuleFileNameW( hModule, filenameW, size );
553 WideCharToMultiByte( CP_ACP, 0, filenameW, -1, lpFileName, size, NULL, NULL );
554 HeapFree( GetProcessHeap(), 0, filenameW );
555 return strlen( lpFileName );
558 /***********************************************************************
559 * GetModuleFileNameW (KERNEL32.@)
561 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size )
563 ULONG magic;
565 lpFileName[0] = 0;
567 LdrLockLoaderLock( 0, NULL, &magic );
568 if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32))
570 /* 16-bit task - get current NE module name */
571 NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() );
572 if (pModule)
574 WCHAR path[MAX_PATH];
576 MultiByteToWideChar( CP_ACP, 0, NE_MODULE_NAME(pModule), -1, path, MAX_PATH );
577 GetLongPathNameW(path, lpFileName, size);
580 else
582 LDR_MODULE* pldr;
583 NTSTATUS nts;
585 if (!hModule) hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
586 nts = LdrFindEntryForAddress( hModule, &pldr );
587 if (nts == STATUS_SUCCESS) lstrcpynW(lpFileName, pldr->FullDllName.Buffer, size);
588 else SetLastError( RtlNtStatusToDosError( nts ) );
591 LdrUnlockLoaderLock( 0, magic );
593 TRACE( "%s\n", debugstr_w(lpFileName) );
594 return strlenW(lpFileName);
597 /******************************************************************
598 * load_library_as_datafile
600 static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
602 static const WCHAR dotDLL[] = {'.','d','l','l',0};
604 WCHAR filenameW[MAX_PATH];
605 HANDLE hFile = INVALID_HANDLE_VALUE;
606 HANDLE mapping;
608 *hmod = 0;
610 if (SearchPathW( NULL, (LPCWSTR)name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]),
611 filenameW, NULL ))
613 hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
614 NULL, OPEN_EXISTING, 0, 0 );
616 if (hFile == INVALID_HANDLE_VALUE) return FALSE;
617 switch (MODULE_GetBinaryType( hFile ))
619 case BINARY_PE_EXE:
620 case BINARY_PE_DLL:
621 mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
622 if (mapping)
624 *hmod = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
625 CloseHandle( mapping );
627 break;
628 default:
629 break;
631 CloseHandle( hFile );
633 return *hmod != 0;
636 /******************************************************************
637 * LoadLibraryExA (KERNEL32.@)
639 * The HFILE parameter is not used and marked reserved in the SDK. I can
640 * only guess that it should force a file to be mapped, but I rather
641 * ignore the parameter because it would be extremely difficult to
642 * integrate this with different types of module representations.
645 HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
647 UNICODE_STRING wstr;
648 NTSTATUS nts;
649 HMODULE hModule;
651 if (!libname)
653 SetLastError(ERROR_INVALID_PARAMETER);
654 return 0;
656 RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
658 if (flags & LOAD_LIBRARY_AS_DATAFILE)
660 /* The method in load_library_as_datafile allows searching for the
661 * 'native' libraries only
663 if (load_library_as_datafile( wstr.Buffer, &hModule))
665 RtlFreeUnicodeString( &wstr );
666 return (HMODULE)((ULONG_PTR)hModule + 1);
668 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
669 /* Fallback to normal behaviour */
672 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
673 if (nts != STATUS_SUCCESS)
675 hModule = 0;
676 SetLastError( RtlNtStatusToDosError( nts ) );
678 RtlFreeUnicodeString( &wstr );
680 return hModule;
683 /***********************************************************************
684 * LoadLibraryExW (KERNEL32.@)
686 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
688 UNICODE_STRING wstr;
689 NTSTATUS nts;
690 HMODULE hModule;
692 if (!libnameW)
694 SetLastError(ERROR_INVALID_PARAMETER);
695 return 0;
698 if (flags & LOAD_LIBRARY_AS_DATAFILE)
700 /* The method in load_library_as_datafile allows searching for the
701 * 'native' libraries only
703 if (load_library_as_datafile(libnameW, &hModule))
704 return (HMODULE)((ULONG_PTR)hModule + 1);
705 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
706 /* Fallback to normal behaviour */
709 RtlInitUnicodeString( &wstr, libnameW );
710 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
711 if (nts != STATUS_SUCCESS)
713 hModule = 0;
714 SetLastError( RtlNtStatusToDosError( nts ) );
716 return hModule;
719 /***********************************************************************
720 * LoadLibraryA (KERNEL32.@)
722 HMODULE WINAPI LoadLibraryA(LPCSTR libname)
724 return LoadLibraryExA(libname, 0, 0);
727 /***********************************************************************
728 * LoadLibraryW (KERNEL32.@)
730 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
732 return LoadLibraryExW(libnameW, 0, 0);
735 /***********************************************************************
736 * LoadLibrary32 (KERNEL.452)
737 * LoadSystemLibrary32 (KERNEL.482)
739 HMODULE WINAPI LoadLibrary32_16( LPCSTR libname )
741 HMODULE hModule;
742 DWORD count;
744 ReleaseThunkLock( &count );
745 hModule = LoadLibraryA( libname );
746 RestoreThunkLock( count );
747 return hModule;
750 /***********************************************************************
751 * FreeLibrary (KERNEL32.@)
752 * FreeLibrary32 (KERNEL.486)
754 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
756 BOOL retv = FALSE;
757 NTSTATUS nts;
759 if (!hLibModule)
761 SetLastError( ERROR_INVALID_HANDLE );
762 return FALSE;
765 if ((ULONG_PTR)hLibModule & 1)
767 /* this is a LOAD_LIBRARY_AS_DATAFILE module */
768 char *ptr = (char *)hLibModule - 1;
769 UnmapViewOfFile( ptr );
770 return TRUE;
773 if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
774 else SetLastError( RtlNtStatusToDosError( nts ) );
776 return retv;
779 /***********************************************************************
780 * FreeLibraryAndExitThread (KERNEL32.@)
782 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
784 FreeLibrary(hLibModule);
785 ExitThread(dwExitCode);
788 /***********************************************************************
789 * PrivateLoadLibrary (KERNEL32.@)
791 * FIXME: rough guesswork, don't know what "Private" means
793 HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
795 return LoadLibrary16(libname);
798 /***********************************************************************
799 * PrivateFreeLibrary (KERNEL32.@)
801 * FIXME: rough guesswork, don't know what "Private" means
803 void WINAPI PrivateFreeLibrary(HINSTANCE16 handle)
805 FreeLibrary16(handle);
809 /***********************************************************************
810 * GetProcAddress (KERNEL32.@)
812 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
814 NTSTATUS nts;
815 FARPROC fp;
817 if (HIWORD(function))
819 ANSI_STRING str;
821 RtlInitAnsiString( &str, function );
822 nts = LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp );
824 else
825 nts = LdrGetProcedureAddress( hModule, NULL, (DWORD)function, (void**)&fp );
826 if (nts != STATUS_SUCCESS)
828 SetLastError( RtlNtStatusToDosError( nts ) );
829 fp = NULL;
831 return fp;
834 /***********************************************************************
835 * GetProcAddress32 (KERNEL.453)
837 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
839 /* FIXME: we used to disable snoop when returning proc for Win16 subsystem */
840 return GetProcAddress( hModule, function );