blob: f9b555dbea28d3c54d324021a2478cdceb4c3bb0 [file] [log] [blame]
Alexandre Julliard594997c1995-04-30 10:05:20 +00001/*
2 * Modules
3 *
4 * Copyright 1995 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
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.
10 *
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.
15 *
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
Alexandre Julliard594997c1995-04-30 10:05:20 +000019 */
20
Patrik Stridvalld016f812002-08-17 00:43:16 +000021#include "config.h"
Patrik Stridvall9aab47e2002-08-28 23:42:34 +000022#include "wine/port.h"
Patrik Stridvalld016f812002-08-17 00:43:16 +000023
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000024#include <assert.h>
Alexandre Julliard594997c1995-04-30 10:05:20 +000025#include <fcntl.h>
26#include <stdlib.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000027#include <stdio.h>
Alexandre Julliard594997c1995-04-30 10:05:20 +000028#include <string.h>
29#include <sys/types.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000030#ifdef HAVE_UNISTD_H
31# include <unistd.h>
32#endif
Jeremy Whited3e22d92000-02-10 19:03:02 +000033#include "wine/winbase16.h"
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000034#include "winerror.h"
Patrik Stridvall9c1de6d2002-09-12 22:07:02 +000035#include "winternl.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000036#include "heap.h"
Aric Stewarte4d09322000-12-03 03:14:29 +000037#include "file.h"
Alexandre Julliardbecb9a32000-12-11 03:48:15 +000038#include "module.h"
Patrik Stridvallcf07e102002-10-23 20:20:59 +000039
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000040#include "wine/debug.h"
Patrik Stridvallcf07e102002-10-23 20:20:59 +000041#include "wine/unicode.h"
Alexandre Julliard37e95032001-07-19 00:39:09 +000042#include "wine/server.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000043
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000044WINE_DEFAULT_DEBUG_CHANNEL(module);
45WINE_DECLARE_DEBUG_CHANNEL(win32);
46WINE_DECLARE_DEBUG_CHANNEL(loaddll);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000047
Alexandre Julliard03e4ea12003-03-18 20:07:12 +000048inline static HMODULE get_exe_module(void)
49{
Alexandre Julliard59804772003-04-05 05:13:33 +000050 HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
51 return pdb[0x08 / sizeof(HANDLE)]; /* get dword at offset 0x08 in pdb */
Alexandre Julliard03e4ea12003-03-18 20:07:12 +000052}
53
Alexandre Julliard5edf4e12001-07-26 20:12:54 +000054/***********************************************************************
55 * wait_input_idle
56 *
57 * Wrapper to call WaitForInputIdle USER function
58 */
59typedef DWORD (WINAPI *WaitForInputIdle_ptr)( HANDLE hProcess, DWORD dwTimeOut );
60
61static DWORD wait_input_idle( HANDLE process, DWORD timeout )
62{
63 HMODULE mod = GetModuleHandleA( "user32.dll" );
64 if (mod)
65 {
66 WaitForInputIdle_ptr ptr = (WaitForInputIdle_ptr)GetProcAddress( mod, "WaitForInputIdle" );
67 if (ptr) return ptr( process, timeout );
68 }
69 return 0;
70}
71
72
Ulrich Weigande469a581999-03-27 16:45:57 +000073/****************************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +000074 * DisableThreadLibraryCalls (KERNEL32.@)
Ulrich Weigande469a581999-03-27 16:45:57 +000075 *
76 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
77 */
78BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
79{
Eric Pouech7d609642003-03-04 04:36:56 +000080 NTSTATUS nts = LdrDisableThreadCalloutsForDll( hModule );
81 if (nts == STATUS_SUCCESS) return TRUE;
Ulrich Weigande469a581999-03-27 16:45:57 +000082
Eric Pouech7d609642003-03-04 04:36:56 +000083 SetLastError( RtlNtStatusToDosError( nts ) );
84 return FALSE;
Ulrich Weigande469a581999-03-27 16:45:57 +000085}
86
Alexandre Julliarda2f2e011995-06-06 16:40:35 +000087
88/***********************************************************************
Alexandre Julliard18f92e71996-07-17 20:02:21 +000089 * MODULE_CreateDummyModule
90 *
91 * Create a dummy NE module for Win32 or Winelib.
92 */
Alexandre Julliard8ff37b82001-06-06 20:24:12 +000093HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 )
Alexandre Julliard18f92e71996-07-17 20:02:21 +000094{
Alexandre Julliard8ff37b82001-06-06 20:24:12 +000095 HMODULE16 hModule;
Alexandre Julliard18f92e71996-07-17 20:02:21 +000096 NE_MODULE *pModule;
97 SEGTABLEENTRY *pSegment;
Alexandre Julliard77b99181997-09-14 17:17:23 +000098 char *pStr,*s;
Francois Gougetbaa9bf91999-12-27 05:24:06 +000099 unsigned int len;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000100 const char* basename;
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000101 OFSTRUCT *ofs;
102 int of_size, size;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000103
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000104 /* Extract base filename */
105 basename = strrchr(filename, '\\');
106 if (!basename) basename = filename;
107 else basename++;
108 len = strlen(basename);
109 if ((s = strchr(basename, '.'))) len = s - basename;
110
111 /* Allocate module */
112 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
113 + strlen(filename) + 1;
114 size = sizeof(NE_MODULE) +
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000115 /* loaded file info */
Vincent Béron9a624912002-05-31 23:06:46 +0000116 ((of_size + 3) & ~3) +
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000117 /* segment table: DS,CS */
118 2 * sizeof(SEGTABLEENTRY) +
119 /* name table */
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000120 len + 2 +
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000121 /* several empty tables */
122 8;
123
124 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000125 if (!hModule) return (HMODULE16)11; /* invalid exe */
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000126
Alexandre Julliarda3960291999-02-26 11:11:13 +0000127 FarSetOwner16( hModule, hModule );
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000128 pModule = (NE_MODULE *)GlobalLock16( hModule );
129
130 /* Set all used entries */
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000131 pModule->magic = IMAGE_OS2_SIGNATURE;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000132 pModule->count = 1;
133 pModule->next = 0;
134 pModule->flags = 0;
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000135 pModule->dgroup = 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000136 pModule->ss = 1;
137 pModule->cs = 2;
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000138 pModule->heap_size = 0;
139 pModule->stack_size = 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000140 pModule->seg_count = 2;
141 pModule->modref_count = 0;
142 pModule->nrname_size = 0;
143 pModule->fileinfo = sizeof(NE_MODULE);
144 pModule->os_flags = NE_OSFLAGS_WINDOWS;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000145 pModule->self = hModule;
Alexandre Julliardb4459522000-04-15 21:00:55 +0000146 pModule->module32 = module32;
147
148 /* Set version and flags */
149 if (module32)
150 {
Alexandre Julliarda5dea212002-08-09 19:57:38 +0000151 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module32 );
152 pModule->expected_version = ((nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
153 (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
Alexandre Julliardb4459522000-04-15 21:00:55 +0000154 pModule->flags |= NE_FFLAGS_WIN32;
Alexandre Julliarda5dea212002-08-09 19:57:38 +0000155 if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
Alexandre Julliardb4459522000-04-15 21:00:55 +0000156 pModule->flags |= NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA;
157 }
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000158
159 /* Set loaded file information */
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000160 ofs = (OFSTRUCT *)(pModule + 1);
161 memset( ofs, 0, of_size );
162 ofs->cBytes = of_size < 256 ? of_size : 255; /* FIXME */
163 strcpy( ofs->szPathName, filename );
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000164
Ulrich Weigandacefd162000-12-29 05:09:15 +0000165 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + ((of_size + 3) & ~3));
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000166 pModule->seg_table = (int)pSegment - (int)pModule;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000167 /* Data segment */
168 pSegment->size = 0;
169 pSegment->flags = NE_SEGFLAGS_DATA;
170 pSegment->minsize = 0x1000;
171 pSegment++;
172 /* Code segment */
173 pSegment->flags = 0;
174 pSegment++;
175
176 /* Module name */
177 pStr = (char *)pSegment;
178 pModule->name_table = (int)pStr - (int)pModule;
Francois Gougetbaa9bf91999-12-27 05:24:06 +0000179 assert(len<256);
Alexandre Julliard17216f51997-10-12 16:30:17 +0000180 *pStr = len;
Francois Gougetbaa9bf91999-12-27 05:24:06 +0000181 lstrcpynA( pStr+1, basename, len+1 );
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000182 pStr += len+2;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000183
184 /* All tables zero terminated */
185 pModule->res_table = pModule->import_table = pModule->entry_table =
186 (int)pStr - (int)pModule;
187
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000188 NE_RegisterModule( pModule );
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000189 return hModule;
190}
191
192
Andreas Mohrb021fe22000-07-26 18:02:28 +0000193/* Check whether a file is an OS/2 or a very old Windows executable
194 * by testing on import of KERNEL.
195 *
196 * FIXME: is reading the module imports the only way of discerning
197 * old Windows binaries from OS/2 ones ? At least it seems so...
198 */
Alexandre Julliard35363162002-05-22 21:32:49 +0000199static enum binary_type MODULE_Decide_OS2_OldWin(HANDLE hfile, const IMAGE_DOS_HEADER *mz,
200 const IMAGE_OS2_HEADER *ne)
Andreas Mohrb021fe22000-07-26 18:02:28 +0000201{
202 DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
Alexandre Julliard35363162002-05-22 21:32:49 +0000203 enum binary_type ret = BINARY_OS216;
Andreas Mohrb021fe22000-07-26 18:02:28 +0000204 LPWORD modtab = NULL;
205 LPSTR nametab = NULL;
206 DWORD len;
207 int i;
208
209 /* read modref table */
210 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_modtab, NULL, SEEK_SET ) == -1)
211 || (!(modtab = HeapAlloc( GetProcessHeap(), 0, ne->ne_cmod*sizeof(WORD))))
212 || (!(ReadFile(hfile, modtab, ne->ne_cmod*sizeof(WORD), &len, NULL)))
213 || (len != ne->ne_cmod*sizeof(WORD)) )
214 goto broken;
215
216 /* read imported names table */
217 if ( (SetFilePointer( hfile, mz->e_lfanew + ne->ne_imptab, NULL, SEEK_SET ) == -1)
218 || (!(nametab = HeapAlloc( GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab)))
219 || (!(ReadFile(hfile, nametab, ne->ne_enttab - ne->ne_imptab, &len, NULL)))
220 || (len != ne->ne_enttab - ne->ne_imptab) )
221 goto broken;
222
223 for (i=0; i < ne->ne_cmod; i++)
224 {
225 LPSTR module = &nametab[modtab[i]];
226 TRACE("modref: %.*s\n", module[0], &module[1]);
227 if (!(strncmp(&module[1], "KERNEL", module[0])))
228 { /* very old Windows file */
229 MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
Alexandre Julliard35363162002-05-22 21:32:49 +0000230 ret = BINARY_WIN16;
Andreas Mohrb021fe22000-07-26 18:02:28 +0000231 goto good;
232 }
233 }
234
235broken:
236 ERR("Hmm, an error occurred. Is this binary file broken ?\n");
237
238good:
239 HeapFree( GetProcessHeap(), 0, modtab);
240 HeapFree( GetProcessHeap(), 0, nametab);
241 SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
Alexandre Julliard35363162002-05-22 21:32:49 +0000242 return ret;
Andreas Mohrb021fe22000-07-26 18:02:28 +0000243}
244
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000245/***********************************************************************
246 * MODULE_GetBinaryType
Alexandre Julliard35363162002-05-22 21:32:49 +0000247 */
248enum binary_type MODULE_GetBinaryType( HANDLE hfile )
249{
250 union
251 {
252 struct
253 {
254 unsigned char magic[4];
255 unsigned char ignored[12];
256 unsigned short type;
257 } elf;
258 IMAGE_DOS_HEADER mz;
259 } header;
260
261 char magic[4];
262 DWORD len;
263
264 /* Seek to the start of the file and read the header information. */
265 if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1)
266 return BINARY_UNKNOWN;
267 if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
268 return BINARY_UNKNOWN;
269
270 if (!memcmp( header.elf.magic, "\177ELF", 4 ))
271 {
272 /* FIXME: we don't bother to check byte order, architecture, etc. */
273 switch(header.elf.type)
274 {
275 case 2: return BINARY_UNIX_EXE;
276 case 3: return BINARY_UNIX_LIB;
277 }
278 return BINARY_UNKNOWN;
279 }
280
281 /* Not ELF, try DOS */
282
283 if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
284 {
285 /* We do have a DOS image so we will now try to seek into
286 * the file by the amount indicated by the field
287 * "Offset to extended header" and read in the
288 * "magic" field information at that location.
289 * This will tell us if there is more header information
290 * to read or not.
291 */
292 /* But before we do we will make sure that header
293 * structure encompasses the "Offset to extended header"
294 * field.
295 */
296 if ((header.mz.e_cparhdr << 4) < sizeof(IMAGE_DOS_HEADER))
297 return BINARY_DOS;
298 if (header.mz.e_crlc && (header.mz.e_lfarlc < sizeof(IMAGE_DOS_HEADER)))
299 return BINARY_DOS;
300 if (header.mz.e_lfanew < sizeof(IMAGE_DOS_HEADER))
301 return BINARY_DOS;
302 if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
303 return BINARY_DOS;
304 if (!ReadFile( hfile, magic, sizeof(magic), &len, NULL ) || len != sizeof(magic))
305 return BINARY_DOS;
306
307 /* Reading the magic field succeeded so
308 * we will try to determine what type it is.
309 */
310 if (!memcmp( magic, "PE\0\0", 4 ))
311 {
Dmitry Timoshkov1467bbd2002-08-27 00:34:41 +0000312 IMAGE_FILE_HEADER FileHeader;
Alexandre Julliard35363162002-05-22 21:32:49 +0000313
Dmitry Timoshkov1467bbd2002-08-27 00:34:41 +0000314 if (ReadFile( hfile, &FileHeader, sizeof(FileHeader), &len, NULL ) && len == sizeof(FileHeader))
Alexandre Julliard35363162002-05-22 21:32:49 +0000315 {
Dmitry Timoshkov1467bbd2002-08-27 00:34:41 +0000316 if (FileHeader.Characteristics & IMAGE_FILE_DLL) return BINARY_PE_DLL;
Alexandre Julliard35363162002-05-22 21:32:49 +0000317 return BINARY_PE_EXE;
318 }
Dmitry Timoshkov1467bbd2002-08-27 00:34:41 +0000319 return BINARY_DOS;
Alexandre Julliard35363162002-05-22 21:32:49 +0000320 }
321
322 if (!memcmp( magic, "NE", 2 ))
323 {
324 /* This is a Windows executable (NE) header. This can
325 * mean either a 16-bit OS/2 or a 16-bit Windows or even a
326 * DOS program (running under a DOS extender). To decide
327 * which, we'll have to read the NE header.
328 */
329 IMAGE_OS2_HEADER ne;
330 if ( SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1
331 && ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
332 && len == sizeof(ne) )
333 {
334 switch ( ne.ne_exetyp )
335 {
336 case 2: return BINARY_WIN16;
337 case 5: return BINARY_DOS;
338 default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ne);
339 }
340 }
341 /* Couldn't read header, so abort. */
Dmitry Timoshkov1467bbd2002-08-27 00:34:41 +0000342 return BINARY_DOS;
Alexandre Julliard35363162002-05-22 21:32:49 +0000343 }
344
345 /* Unknown extended header, but this file is nonetheless DOS-executable. */
346 return BINARY_DOS;
347 }
348
349 return BINARY_UNKNOWN;
350}
351
352/***********************************************************************
353 * GetBinaryTypeA [KERNEL32.@]
354 * GetBinaryType [KERNEL32.@]
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000355 *
356 * The GetBinaryType function determines whether a file is executable
357 * or not and if it is it returns what type of executable it is.
358 * The type of executable is a property that determines in which
359 * subsystem an executable file runs under.
360 *
361 * Binary types returned:
362 * SCS_32BIT_BINARY: A Win32 based application
363 * SCS_DOS_BINARY: An MS-Dos based application
364 * SCS_WOW_BINARY: A Win16 based application
365 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
366 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
Ulrich Weigandd523e4d1999-06-07 17:37:43 +0000367 * SCS_OS216_BINARY: A 16bit OS/2 based application
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000368 *
369 * Returns TRUE if the file is an executable in which case
370 * the value pointed by lpBinaryType is set.
371 * Returns FALSE if the file is not an executable or if the function fails.
372 *
373 * To do so it opens the file and reads in the header information
Andreas Mohr8952dea1999-12-12 20:16:42 +0000374 * if the extended header information is not present it will
375 * assume that the file is a DOS executable.
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000376 * If the extended header information is present it will
Andreas Mohr8952dea1999-12-12 20:16:42 +0000377 * determine if the file is a 16 or 32 bit Windows executable
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000378 * by check the flags in the header.
379 *
380 * Note that .COM and .PIF files are only recognized by their
381 * file name extension; but Windows does it the same way ...
Alexandre Julliard594997c1995-04-30 10:05:20 +0000382 */
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000383BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
Alexandre Julliard01d63461997-01-20 19:43:45 +0000384{
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000385 BOOL ret = FALSE;
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000386 HANDLE hfile;
Alexandre Julliard35363162002-05-22 21:32:49 +0000387 char *ptr;
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000388
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000389 TRACE_(win32)("%s\n", lpApplicationName );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000390
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000391 /* Sanity check.
392 */
393 if ( lpApplicationName == NULL || lpBinaryType == NULL )
394 return FALSE;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000395
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000396 /* Open the file indicated by lpApplicationName for reading.
397 */
Alexandre Julliarde3332122000-06-08 01:00:16 +0000398 hfile = CreateFileA( lpApplicationName, GENERIC_READ, FILE_SHARE_READ,
François Gougetda2b6a92001-01-06 01:29:18 +0000399 NULL, OPEN_EXISTING, 0, 0 );
Ulrich Weigand237e8e91999-12-04 04:04:58 +0000400 if ( hfile == INVALID_HANDLE_VALUE )
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000401 return FALSE;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000402
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000403 /* Check binary type
404 */
Alexandre Julliard35363162002-05-22 21:32:49 +0000405 switch(MODULE_GetBinaryType( hfile ))
406 {
407 case BINARY_UNKNOWN:
408 /* try to determine from file name */
409 ptr = strrchr( lpApplicationName, '.' );
410 if (!ptr) break;
411 if (!FILE_strcasecmp( ptr, ".COM" ))
412 {
413 *lpBinaryType = SCS_DOS_BINARY;
414 ret = TRUE;
415 }
416 else if (!FILE_strcasecmp( ptr, ".PIF" ))
417 {
418 *lpBinaryType = SCS_PIF_BINARY;
419 ret = TRUE;
420 }
421 break;
422 case BINARY_PE_EXE:
423 case BINARY_PE_DLL:
424 *lpBinaryType = SCS_32BIT_BINARY;
425 ret = TRUE;
426 break;
427 case BINARY_WIN16:
428 *lpBinaryType = SCS_WOW_BINARY;
429 ret = TRUE;
430 break;
431 case BINARY_OS216:
432 *lpBinaryType = SCS_OS216_BINARY;
433 ret = TRUE;
434 break;
435 case BINARY_DOS:
436 *lpBinaryType = SCS_DOS_BINARY;
437 ret = TRUE;
438 break;
439 case BINARY_UNIX_EXE:
440 case BINARY_UNIX_LIB:
441 ret = FALSE;
442 break;
443 }
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000444
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000445 CloseHandle( hfile );
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000446 return ret;
447}
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000448
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000449/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000450 * GetBinaryTypeW [KERNEL32.@]
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000451 */
452BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
453{
454 BOOL ret = FALSE;
455 LPSTR strNew = NULL;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000456
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000457 TRACE_(win32)("%s\n", debugstr_w(lpApplicationName) );
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000458
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000459 /* Sanity check.
460 */
461 if ( lpApplicationName == NULL || lpBinaryType == NULL )
462 return FALSE;
463
464 /* Convert the wide string to a ascii string.
465 */
466 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
467
468 if ( strNew != NULL )
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000469 {
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000470 ret = GetBinaryTypeA( strNew, lpBinaryType );
471
472 /* Free the allocated string.
473 */
474 HeapFree( GetProcessHeap(), 0, strNew );
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000475 }
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000476
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000477 return ret;
Alexandre Julliard01d63461997-01-20 19:43:45 +0000478}
479
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000480
481/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000482 * WinExec (KERNEL.166)
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000483 */
484HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
485{
Andreas Mohr70963842000-09-22 22:08:28 +0000486 LPCSTR p, args = NULL;
487 LPCSTR name_beg, name_end;
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000488 LPSTR name, cmdline;
Andreas Mohr70963842000-09-22 22:08:28 +0000489 int arglen;
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000490 HINSTANCE16 ret;
491 char buffer[MAX_PATH];
Ulrich Weigand6ce40061999-05-03 09:22:55 +0000492
Andreas Mohr70963842000-09-22 22:08:28 +0000493 if (*lpCmdLine == '"') /* has to be only one and only at beginning ! */
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000494 {
Andreas Mohr70963842000-09-22 22:08:28 +0000495 name_beg = lpCmdLine+1;
496 p = strchr ( lpCmdLine+1, '"' );
497 if (p)
498 {
499 name_end = p;
500 args = strchr ( p, ' ' );
501 }
502 else /* yes, even valid with trailing '"' missing */
503 name_end = lpCmdLine+strlen(lpCmdLine);
504 }
Vincent Béron9a624912002-05-31 23:06:46 +0000505 else
Andreas Mohr70963842000-09-22 22:08:28 +0000506 {
507 name_beg = lpCmdLine;
508 args = strchr( lpCmdLine, ' ' );
509 name_end = args ? args : lpCmdLine+strlen(lpCmdLine);
510 }
511
512 if ((name_beg == lpCmdLine) && (!args))
513 { /* just use the original cmdline string as file name */
514 name = (LPSTR)lpCmdLine;
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000515 }
516 else
517 {
Andreas Mohr70963842000-09-22 22:08:28 +0000518 if (!(name = HeapAlloc( GetProcessHeap(), 0, name_end - name_beg + 1 )))
519 return ERROR_NOT_ENOUGH_MEMORY;
520 memcpy( name, name_beg, name_end - name_beg );
521 name[name_end - name_beg] = '\0';
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000522 }
Ulrich Weigand6ce40061999-05-03 09:22:55 +0000523
Andreas Mohr70963842000-09-22 22:08:28 +0000524 if (args)
525 {
526 args++;
527 arglen = strlen(args);
Alexandre Julliardd7b76822001-12-20 00:19:40 +0000528 cmdline = HeapAlloc( GetProcessHeap(), 0, 2 + arglen );
Andreas Mohr70963842000-09-22 22:08:28 +0000529 cmdline[0] = (BYTE)arglen;
530 strcpy( cmdline + 1, args );
531 }
532 else
533 {
Alexandre Julliardd7b76822001-12-20 00:19:40 +0000534 cmdline = HeapAlloc( GetProcessHeap(), 0, 2 );
Andreas Mohr70963842000-09-22 22:08:28 +0000535 cmdline[0] = cmdline[1] = 0;
536 }
537
Andreas Mohrcabee392000-10-25 21:22:27 +0000538 TRACE("name: '%s', cmdline: '%.*s'\n", name, cmdline[0], &cmdline[1]);
Andreas Mohr70963842000-09-22 22:08:28 +0000539
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000540 if (SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL ))
541 {
542 LOADPARAMS16 params;
Alexandre Julliardd7b76822001-12-20 00:19:40 +0000543 WORD showCmd[2];
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000544 showCmd[0] = 2;
545 showCmd[1] = nCmdShow;
546
547 params.hEnvironment = 0;
Alexandre Julliardd7b76822001-12-20 00:19:40 +0000548 params.cmdLine = MapLS( cmdline );
549 params.showCmd = MapLS( showCmd );
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000550 params.reserved = 0;
551
552 ret = LoadModule16( buffer, &params );
Alexandre Julliardd7b76822001-12-20 00:19:40 +0000553 UnMapLS( params.cmdLine );
554 UnMapLS( params.showCmd );
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000555 }
556 else ret = GetLastError();
557
Alexandre Julliardd7b76822001-12-20 00:19:40 +0000558 HeapFree( GetProcessHeap(), 0, cmdline );
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000559 if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
560
561 if (ret == 21) /* 32-bit module */
562 {
Alexandre Julliardab687972000-11-15 23:41:46 +0000563 DWORD count;
564 ReleaseThunkLock( &count );
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000565 ret = LOWORD( WinExec( lpCmdLine, nCmdShow ) );
Alexandre Julliardab687972000-11-15 23:41:46 +0000566 RestoreThunkLock( count );
Alexandre Julliardc192ba22000-05-29 21:25:10 +0000567 }
568 return ret;
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000569}
570
571/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000572 * WinExec (KERNEL32.@)
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000573 */
Francois Gouget2204b502002-05-19 22:21:45 +0000574UINT WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000575{
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000576 PROCESS_INFORMATION info;
577 STARTUPINFOA startup;
Alexandre Julliard596921d2000-06-24 20:53:47 +0000578 char *cmdline;
Alexandre Julliard267ca682002-07-31 17:20:00 +0000579 UINT ret;
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000580
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000581 memset( &startup, 0, sizeof(startup) );
582 startup.cb = sizeof(startup);
583 startup.dwFlags = STARTF_USESHOWWINDOW;
584 startup.wShowWindow = nCmdShow;
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000585
Alexandre Julliard596921d2000-06-24 20:53:47 +0000586 /* cmdline needs to be writeable for CreateProcess */
Alexandre Julliard5f728ca2001-07-24 21:45:22 +0000587 if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(lpCmdLine)+1 ))) return 0;
588 strcpy( cmdline, lpCmdLine );
Alexandre Julliard596921d2000-06-24 20:53:47 +0000589
590 if (CreateProcessA( NULL, cmdline, NULL, NULL, FALSE,
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000591 0, NULL, NULL, &startup, &info ))
592 {
593 /* Give 30 seconds to the app to come up */
Alexandre Julliard5edf4e12001-07-26 20:12:54 +0000594 if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF)
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000595 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
Alexandre Julliard267ca682002-07-31 17:20:00 +0000596 ret = 33;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000597 /* Close off the handles */
598 CloseHandle( info.hThread );
599 CloseHandle( info.hProcess );
600 }
Alexandre Julliard267ca682002-07-31 17:20:00 +0000601 else if ((ret = GetLastError()) >= 32)
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000602 {
Alexandre Julliard267ca682002-07-31 17:20:00 +0000603 FIXME("Strange error set by CreateProcess: %d\n", ret );
604 ret = 11;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000605 }
Alexandre Julliard596921d2000-06-24 20:53:47 +0000606 HeapFree( GetProcessHeap(), 0, cmdline );
Alexandre Julliard267ca682002-07-31 17:20:00 +0000607 return ret;
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000608}
609
610/**********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000611 * LoadModule (KERNEL32.@)
Alexandre Julliard491502b1997-11-01 19:08:16 +0000612 */
Vincent Béron9a624912002-05-31 23:06:46 +0000613HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
Alexandre Julliard491502b1997-11-01 19:08:16 +0000614{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000615 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000616 PROCESS_INFORMATION info;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000617 STARTUPINFOA startup;
618 HINSTANCE hInstance;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000619 LPSTR cmdline, p;
620 char filename[MAX_PATH];
621 BYTE len;
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000622
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000623 if (!name) return (HINSTANCE)ERROR_FILE_NOT_FOUND;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000624
625 if (!SearchPathA( NULL, name, ".exe", sizeof(filename), filename, NULL ) &&
626 !SearchPathA( NULL, name, NULL, sizeof(filename), filename, NULL ))
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000627 return (HINSTANCE)GetLastError();
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000628
629 len = (BYTE)params->lpCmdLine[0];
630 if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + len + 2 )))
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000631 return (HINSTANCE)ERROR_NOT_ENOUGH_MEMORY;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000632
633 strcpy( cmdline, filename );
634 p = cmdline + strlen(cmdline);
635 *p++ = ' ';
636 memcpy( p, params->lpCmdLine + 1, len );
637 p[len] = 0;
638
639 memset( &startup, 0, sizeof(startup) );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000640 startup.cb = sizeof(startup);
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000641 if (params->lpCmdShow)
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000642 {
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000643 startup.dwFlags = STARTF_USESHOWWINDOW;
644 startup.wShowWindow = params->lpCmdShow[1];
Ulrich Weigand6e0d3861999-02-28 11:14:32 +0000645 }
Vincent Béron9a624912002-05-31 23:06:46 +0000646
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000647 if (CreateProcessA( filename, cmdline, NULL, NULL, FALSE, 0,
648 params->lpEnvAddress, NULL, &startup, &info ))
649 {
650 /* Give 30 seconds to the app to come up */
Alexandre Julliard5edf4e12001-07-26 20:12:54 +0000651 if (wait_input_idle( info.hProcess, 30000 ) == 0xFFFFFFFF )
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000652 WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000653 hInstance = (HINSTANCE)33;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000654 /* Close off the handles */
655 CloseHandle( info.hThread );
656 CloseHandle( info.hProcess );
657 }
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000658 else if ((hInstance = (HINSTANCE)GetLastError()) >= (HINSTANCE)32)
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000659 {
Andrew John Hughesed800c62002-11-21 03:45:01 +0000660 FIXME("Strange error set by CreateProcess: %p\n", hInstance );
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000661 hInstance = (HINSTANCE)11;
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000662 }
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000663
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000664 HeapFree( GetProcessHeap(), 0, cmdline );
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000665 return hInstance;
Alexandre Julliard491502b1997-11-01 19:08:16 +0000666}
667
Alexandre Julliard8e8f0f52000-04-15 21:30:33 +0000668
Alexandre Julliard77b99181997-09-14 17:17:23 +0000669/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000670 * GetModuleHandleA (KERNEL32.@)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000671 * GetModuleHandle32 (KERNEL.488)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000672 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000673HMODULE WINAPI GetModuleHandleA(LPCSTR module)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000674{
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000675 NTSTATUS nts;
676 HMODULE ret;
Alexandre Julliard59804772003-04-05 05:13:33 +0000677 UNICODE_STRING wstr;
Bertho Stultiensc1d1cfe1999-04-18 12:14:06 +0000678
Alexandre Julliard59804772003-04-05 05:13:33 +0000679 if (!module) return get_exe_module();
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000680
Alexandre Julliard59804772003-04-05 05:13:33 +0000681 RtlCreateUnicodeStringFromAsciiz(&wstr, module);
682 nts = LdrGetDllHandle(0, 0, &wstr, &ret);
683 RtlFreeUnicodeString( &wstr );
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000684 if (nts != STATUS_SUCCESS)
685 {
686 ret = 0;
687 SetLastError( RtlNtStatusToDosError( nts ) );
688 }
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000689 return ret;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000690}
691
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000692/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000693 * GetModuleHandleW (KERNEL32.@)
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000694 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000695HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000696{
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000697 NTSTATUS nts;
698 HMODULE ret;
Alexandre Julliard59804772003-04-05 05:13:33 +0000699 UNICODE_STRING wstr;
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000700
Alexandre Julliard59804772003-04-05 05:13:33 +0000701 if (!module) return get_exe_module();
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000702
Alexandre Julliard59804772003-04-05 05:13:33 +0000703 RtlInitUnicodeString( &wstr, module );
704 nts = LdrGetDllHandle( 0, 0, &wstr, &ret);
Eric Pouechf3a73ef2003-03-06 23:41:37 +0000705 if (nts != STATUS_SUCCESS)
706 {
707 SetLastError( RtlNtStatusToDosError( nts ) );
708 ret = 0;
709 }
710 return ret;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000711}
712
Alexandre Julliard594997c1995-04-30 10:05:20 +0000713
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000714/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000715 * GetModuleFileNameA (KERNEL32.@)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000716 * GetModuleFileName32 (KERNEL.487)
Andreas Mohr4654c322000-02-20 19:15:34 +0000717 *
718 * GetModuleFileNameA seems to *always* return the long path;
719 * it's only GetModuleFileName16 that decides between short/long path
720 * by checking if exe version >= 4.0.
721 * (SDK docu doesn't mention this)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000722 */
Vincent Béron9a624912002-05-31 23:06:46 +0000723DWORD WINAPI GetModuleFileNameA(
Alexandre Julliarda3960291999-02-26 11:11:13 +0000724 HMODULE hModule, /* [in] module handle (32bit) */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000725 LPSTR lpFileName, /* [out] filenamebuffer */
Alexandre Julliard081ee942000-08-07 04:12:41 +0000726 DWORD size ) /* [in] size of filenamebuffer */
727{
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000728 LPWSTR filenameW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000729
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000730 if (!filenameW)
Joshua Thielen1cef2972002-07-05 00:16:41 +0000731 {
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000732 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
733 return 0;
Joshua Thielen1cef2972002-07-05 00:16:41 +0000734 }
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000735 GetModuleFileNameW( hModule, filenameW, size );
736 WideCharToMultiByte( CP_ACP, 0, filenameW, -1, lpFileName, size, NULL, NULL );
737 HeapFree( GetProcessHeap(), 0, filenameW );
738 return strlen( lpFileName );
Vincent Béron9a624912002-05-31 23:06:46 +0000739}
740
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000741/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +0000742 * GetModuleFileNameW (KERNEL32.@)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000743 */
Alexandre Julliard83886f22002-07-05 01:27:19 +0000744DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000745{
Alexandre Julliard500a2f92003-03-20 04:29:21 +0000746 ULONG magic;
747
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000748 lpFileName[0] = 0;
749
Alexandre Julliard500a2f92003-03-20 04:29:21 +0000750 LdrLockLoaderLock( 0, NULL, &magic );
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000751 if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32))
752 {
753 /* 16-bit task - get current NE module name */
754 NE_MODULE *pModule = NE_GetPtr( GetCurrentTask() );
755 if (pModule)
756 {
757 WCHAR path[MAX_PATH];
758
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000759 MultiByteToWideChar( CP_ACP, 0, NE_MODULE_NAME(pModule), -1, path, MAX_PATH );
760 GetLongPathNameW(path, lpFileName, size);
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000761 }
762 }
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000763 else
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000764 {
765 LDR_MODULE* pldr;
766 NTSTATUS nts;
767
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000768 if (!hModule) hModule = get_exe_module();
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000769 nts = LdrFindEntryForAddress( hModule, &pldr );
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000770 if (nts == STATUS_SUCCESS) lstrcpynW(lpFileName, pldr->FullDllName.Buffer, size);
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000771 else SetLastError( RtlNtStatusToDosError( nts ) );
772
773 }
Alexandre Julliard500a2f92003-03-20 04:29:21 +0000774 LdrUnlockLoaderLock( 0, magic );
Eric Pouech84d1a8f2003-03-18 18:29:13 +0000775
Alexandre Julliard03e4ea12003-03-18 20:07:12 +0000776 TRACE( "%s\n", debugstr_w(lpFileName) );
777 return strlenW(lpFileName);
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000778}
779
Eric Pouech32872b12003-03-14 05:01:20 +0000780/******************************************************************
781 * load_library_as_datafile
Bill Medland65fc1c92001-08-24 21:13:02 +0000782 */
Alexandre Julliard803b5682003-03-14 23:17:45 +0000783static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
Bill Medland65fc1c92001-08-24 21:13:02 +0000784{
Alexandre Julliard803b5682003-03-14 23:17:45 +0000785 static const WCHAR dotDLL[] = {'.','d','l','l',0};
786
787 WCHAR filenameW[MAX_PATH];
Eric Pouech32872b12003-03-14 05:01:20 +0000788 HANDLE hFile = INVALID_HANDLE_VALUE;
789 HANDLE mapping;
Alexandre Julliard803b5682003-03-14 23:17:45 +0000790
Eric Pouech32872b12003-03-14 05:01:20 +0000791 *hmod = 0;
Bill Medland65fc1c92001-08-24 21:13:02 +0000792
Alexandre Julliard803b5682003-03-14 23:17:45 +0000793 if (SearchPathW( NULL, (LPCWSTR)name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]),
794 filenameW, NULL ))
Bill Medland65fc1c92001-08-24 21:13:02 +0000795 {
Alexandre Julliard803b5682003-03-14 23:17:45 +0000796 hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
797 NULL, OPEN_EXISTING, 0, 0 );
Eric Pouech32872b12003-03-14 05:01:20 +0000798 }
Eric Pouech32872b12003-03-14 05:01:20 +0000799 if (hFile == INVALID_HANDLE_VALUE) return FALSE;
800 switch (MODULE_GetBinaryType( hFile ))
801 {
802 case BINARY_PE_EXE:
803 case BINARY_PE_DLL:
Alexandre Julliard803b5682003-03-14 23:17:45 +0000804 mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
Eric Pouech32872b12003-03-14 05:01:20 +0000805 if (mapping)
806 {
Alexandre Julliard803b5682003-03-14 23:17:45 +0000807 *hmod = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
Eric Pouech32872b12003-03-14 05:01:20 +0000808 CloseHandle( mapping );
809 }
810 break;
811 default:
812 break;
813 }
814 CloseHandle( hFile );
815
816 return *hmod != 0;
Bill Medland65fc1c92001-08-24 21:13:02 +0000817}
818
Eric Pouech32872b12003-03-14 05:01:20 +0000819/******************************************************************
820 * LoadLibraryExA (KERNEL32.@)
Bertho Stultiensc1d1cfe1999-04-18 12:14:06 +0000821 *
822 * The HFILE parameter is not used and marked reserved in the SDK. I can
823 * only guess that it should force a file to be mapped, but I rather
824 * ignore the parameter because it would be extremely difficult to
Andreas Mohr01c8ec32002-04-02 19:47:30 +0000825 * integrate this with different types of module representations.
Bertho Stultiensc1d1cfe1999-04-18 12:14:06 +0000826 *
827 */
Eric Pouech32872b12003-03-14 05:01:20 +0000828HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
Marcus Meissner8220bc91998-10-11 11:10:27 +0000829{
Eric Pouech32872b12003-03-14 05:01:20 +0000830 UNICODE_STRING wstr;
831 NTSTATUS nts;
832 HMODULE hModule;
Peter Gantenc7c42462000-08-28 21:33:28 +0000833
Eric Pouech32872b12003-03-14 05:01:20 +0000834 if (!libname)
835 {
836 SetLastError(ERROR_INVALID_PARAMETER);
837 return 0;
838 }
Alexandre Julliard803b5682003-03-14 23:17:45 +0000839 RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
Peter Gantenc7c42462000-08-28 21:33:28 +0000840
Eric Pouech32872b12003-03-14 05:01:20 +0000841 if (flags & LOAD_LIBRARY_AS_DATAFILE)
842 {
Alexandre Julliard803b5682003-03-14 23:17:45 +0000843 /* The method in load_library_as_datafile allows searching for the
844 * 'native' libraries only
Eric Pouech32872b12003-03-14 05:01:20 +0000845 */
Alexandre Julliard803b5682003-03-14 23:17:45 +0000846 if (load_library_as_datafile( wstr.Buffer, &hModule))
847 {
848 RtlFreeUnicodeString( &wstr );
Eric Pouech32872b12003-03-14 05:01:20 +0000849 return (HMODULE)((ULONG_PTR)hModule + 1);
Alexandre Julliard803b5682003-03-14 23:17:45 +0000850 }
Eric Pouech32872b12003-03-14 05:01:20 +0000851 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
852 /* Fallback to normal behaviour */
853 }
Peter Gantenc7c42462000-08-28 21:33:28 +0000854
Eric Pouech32872b12003-03-14 05:01:20 +0000855 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
856 if (nts != STATUS_SUCCESS)
857 {
858 hModule = 0;
859 SetLastError( RtlNtStatusToDosError( nts ) );
860 }
861 RtlFreeUnicodeString( &wstr );
Bill Medland65fc1c92001-08-24 21:13:02 +0000862
Eric Pouech32872b12003-03-14 05:01:20 +0000863 return hModule;
864}
Bill Medland65fc1c92001-08-24 21:13:02 +0000865
Eric Pouech32872b12003-03-14 05:01:20 +0000866/***********************************************************************
867 * LoadLibraryExW (KERNEL32.@)
868 */
869HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
870{
871 UNICODE_STRING wstr;
872 NTSTATUS nts;
873 HMODULE hModule;
Bill Medland65fc1c92001-08-24 21:13:02 +0000874
Eric Pouech32872b12003-03-14 05:01:20 +0000875 if (!libnameW)
876 {
877 SetLastError(ERROR_INVALID_PARAMETER);
878 return 0;
879 }
Marcus Meissner8220bc91998-10-11 11:10:27 +0000880
Eric Pouech32872b12003-03-14 05:01:20 +0000881 if (flags & LOAD_LIBRARY_AS_DATAFILE)
882 {
Alexandre Julliard803b5682003-03-14 23:17:45 +0000883 /* The method in load_library_as_datafile allows searching for the
884 * 'native' libraries only
Eric Pouech32872b12003-03-14 05:01:20 +0000885 */
Alexandre Julliard803b5682003-03-14 23:17:45 +0000886 if (load_library_as_datafile(libnameW, &hModule))
Eric Pouech32872b12003-03-14 05:01:20 +0000887 return (HMODULE)((ULONG_PTR)hModule + 1);
888 flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
889 /* Fallback to normal behaviour */
890 }
Alexandre Julliard081ee942000-08-07 04:12:41 +0000891
Eric Pouech32872b12003-03-14 05:01:20 +0000892 RtlInitUnicodeString( &wstr, libnameW );
893 nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
894 if (nts != STATUS_SUCCESS)
895 {
896 hModule = 0;
897 SetLastError( RtlNtStatusToDosError( nts ) );
898 }
899 return hModule;
Alexandre Julliard77b99181997-09-14 17:17:23 +0000900}
901
902/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000903 * LoadLibraryA (KERNEL32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000904 */
Eric Pouech32872b12003-03-14 05:01:20 +0000905HMODULE WINAPI LoadLibraryA(LPCSTR libname)
906{
907 return LoadLibraryExA(libname, 0, 0);
Alexandre Julliard77b99181997-09-14 17:17:23 +0000908}
909
910/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000911 * LoadLibraryW (KERNEL32.@)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000912 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000913HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000914{
Eric Pouech32872b12003-03-14 05:01:20 +0000915 return LoadLibraryExW(libnameW, 0, 0);
Alexandre Julliard77b99181997-09-14 17:17:23 +0000916}
917
918/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000919 * LoadLibrary32 (KERNEL.452)
920 * LoadSystemLibrary32 (KERNEL.482)
Ulrich Weigandc3d9f281999-08-18 18:31:26 +0000921 */
922HMODULE WINAPI LoadLibrary32_16( LPCSTR libname )
923{
924 HMODULE hModule;
Alexandre Julliardab687972000-11-15 23:41:46 +0000925 DWORD count;
Ulrich Weigandc3d9f281999-08-18 18:31:26 +0000926
Alexandre Julliardab687972000-11-15 23:41:46 +0000927 ReleaseThunkLock( &count );
Ulrich Weigandc3d9f281999-08-18 18:31:26 +0000928 hModule = LoadLibraryA( libname );
Alexandre Julliardab687972000-11-15 23:41:46 +0000929 RestoreThunkLock( count );
Ulrich Weigandc3d9f281999-08-18 18:31:26 +0000930 return hModule;
931}
932
933/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +0000934 * FreeLibrary (KERNEL32.@)
935 * FreeLibrary32 (KERNEL.486)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000936 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000937BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000938{
Eric Pouech1efa50e2003-03-14 04:00:52 +0000939 BOOL retv = FALSE;
940 NTSTATUS nts;
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000941
Eric Pouech32872b12003-03-14 05:01:20 +0000942 if (!hLibModule)
943 {
944 SetLastError( ERROR_INVALID_HANDLE );
945 return FALSE;
946 }
947
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000948 if ((ULONG_PTR)hLibModule & 1)
949 {
950 /* this is a LOAD_LIBRARY_AS_DATAFILE module */
951 char *ptr = (char *)hLibModule - 1;
952 UnmapViewOfFile( ptr );
953 return TRUE;
954 }
Bertho Stultiens1b346971999-04-11 14:52:24 +0000955
Eric Pouech1efa50e2003-03-14 04:00:52 +0000956 if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
957 else SetLastError( RtlNtStatusToDosError( nts ) );
Bertho Stultiens1b346971999-04-11 14:52:24 +0000958
Bertho Stultiensc1d1cfe1999-04-18 12:14:06 +0000959 return retv;
960}
961
962/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000963 * FreeLibraryAndExitThread (KERNEL32.@)
Sergey Turchanov5ffd2df1999-03-22 12:35:48 +0000964 */
965VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
966{
967 FreeLibrary(hLibModule);
968 ExitThread(dwExitCode);
969}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000970
971/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000972 * PrivateLoadLibrary (KERNEL32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000973 *
974 * FIXME: rough guesswork, don't know what "Private" means
975 */
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000976HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000977{
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000978 return LoadLibrary16(libname);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000979}
980
Alexandre Julliard2787be81995-05-22 18:23:01 +0000981/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000982 * PrivateFreeLibrary (KERNEL32.@)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000983 *
984 * FIXME: rough guesswork, don't know what "Private" means
985 */
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000986void WINAPI PrivateFreeLibrary(HINSTANCE16 handle)
Alexandre Julliarde658d821997-11-30 17:45:40 +0000987{
Alexandre Julliard8ff37b82001-06-06 20:24:12 +0000988 FreeLibrary16(handle);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000989}
990
991
992/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000993 * GetProcAddress16 (KERNEL32.37)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000994 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
995 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000996FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000997{
Alexandre Julliard641ee761997-08-04 16:34:36 +0000998 if (!hModule) {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000999 WARN("hModule may not be 0!\n");
Alexandre Julliard641ee761997-08-04 16:34:36 +00001000 return (FARPROC16)0;
1001 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001002 if (HIWORD(hModule))
1003 {
Andrew John Hughesed800c62002-11-21 03:45:01 +00001004 WARN("hModule is Win32 handle (%p)\n", hModule );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001005 return (FARPROC16)0;
1006 }
Alexandre Julliard8ff37b82001-06-06 20:24:12 +00001007 return GetProcAddress16( LOWORD(hModule), name );
Alexandre Julliard641ee761997-08-04 16:34:36 +00001008}
1009
1010/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001011 * GetProcAddress (KERNEL.50)
Alexandre Julliard2787be81995-05-22 18:23:01 +00001012 */
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001013FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, LPCSTR name )
Alexandre Julliard2787be81995-05-22 18:23:01 +00001014{
1015 WORD ordinal;
Alexandre Julliardca22b331996-07-12 19:02:39 +00001016 FARPROC16 ret;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001017
1018 if (!hModule) hModule = GetCurrentTask();
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001019 hModule = GetExePtr( hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001020
1021 if (HIWORD(name) != 0)
1022 {
Alexandre Julliardac7efef2000-11-27 21:54:01 +00001023 ordinal = NE_GetOrdinal( hModule, name );
1024 TRACE("%04x '%s'\n", hModule, name );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001025 }
1026 else
1027 {
1028 ordinal = LOWORD(name);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001029 TRACE("%04x %04x\n", hModule, ordinal );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001030 }
Alexandre Julliardca22b331996-07-12 19:02:39 +00001031 if (!ordinal) return (FARPROC16)0;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001032
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001033 ret = NE_GetEntryPoint( hModule, ordinal );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001034
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001035 TRACE("returning %08x\n", (UINT)ret );
Alexandre Julliardca22b331996-07-12 19:02:39 +00001036 return ret;
1037}
1038
1039
1040/***********************************************************************
Patrik Stridvalldae8de62001-06-13 20:13:18 +00001041 * GetProcAddress (KERNEL32.@)
Alexandre Julliardca22b331996-07-12 19:02:39 +00001042 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001043FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
Alexandre Julliardca22b331996-07-12 19:02:39 +00001044{
Eric Pouechf3a73ef2003-03-06 23:41:37 +00001045 NTSTATUS nts;
1046 FARPROC fp;
1047
1048 if (HIWORD(function))
1049 {
1050 ANSI_STRING str;
1051
1052 RtlInitAnsiString( &str, function );
1053 nts = LdrGetProcedureAddress( hModule, &str, 0, (void**)&fp );
1054 }
1055 else
1056 nts = LdrGetProcedureAddress( hModule, NULL, (DWORD)function, (void**)&fp );
1057 if (nts != STATUS_SUCCESS)
1058 {
1059 SetLastError( RtlNtStatusToDosError( nts ) );
1060 fp = NULL;
1061 }
1062 return fp;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001063}
1064
Ulrich Weiganda3527cf1998-10-11 19:31:10 +00001065/***********************************************************************
Patrik Stridvall54fe8382000-04-06 20:21:16 +00001066 * GetProcAddress32 (KERNEL.453)
Ulrich Weiganda3527cf1998-10-11 19:31:10 +00001067 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001068FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
Ulrich Weiganda3527cf1998-10-11 19:31:10 +00001069{
Eric Pouechf3a73ef2003-03-06 23:41:37 +00001070 /* FIXME: we used to disable snoop when returning proc for Win16 subsystem */
1071 return GetProcAddress( hModule, function );
Ulrich Weiganda3527cf1998-10-11 19:31:10 +00001072}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001073
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001074/***************************************************************************
1075 * HasGPHandler (KERNEL.338)
1076 */
1077
Patrik Stridvallc7a8dde1999-04-25 12:36:53 +00001078#include "pshpack1.h"
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001079typedef struct _GPHANDLERDEF
1080{
1081 WORD selector;
1082 WORD rangeStart;
1083 WORD rangeEnd;
1084 WORD handler;
1085} GPHANDLERDEF;
Patrik Stridvallc7a8dde1999-04-25 12:36:53 +00001086#include "poppack.h"
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001087
Alexandre Julliarda3960291999-02-26 11:11:13 +00001088SEGPTR WINAPI HasGPHandler16( SEGPTR address )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001089{
1090 HMODULE16 hModule;
Ulrich Weiganda3527cf1998-10-11 19:31:10 +00001091 int gpOrdinal;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001092 SEGPTR gpPtr;
1093 GPHANDLERDEF *gpHandler;
Vincent Béron9a624912002-05-31 23:06:46 +00001094
Alexandre Julliarda3960291999-02-26 11:11:13 +00001095 if ( (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
Ulrich Weiganda3527cf1998-10-11 19:31:10 +00001096 && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1097 && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001098 && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
Alexandre Julliard982a2232000-12-13 20:20:09 +00001099 && (gpHandler = MapSL( gpPtr )) != NULL )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001100 {
1101 while (gpHandler->selector)
1102 {
1103 if ( SELECTOROF(address) == gpHandler->selector
1104 && OFFSETOF(address) >= gpHandler->rangeStart
1105 && OFFSETOF(address) < gpHandler->rangeEnd )
Alexandre Julliard982a2232000-12-13 20:20:09 +00001106 return MAKESEGPTR( gpHandler->selector, gpHandler->handler );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +00001107 gpHandler++;
1108 }
1109 }
1110
1111 return 0;
1112}