Some fixes and additions.
[wine/multimedia.git] / loader / module.c
blob666d3c06a91dd401b04cd303116da8ca45d8c4ae
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include "wine/winuser16.h"
14 #include "wine/winbase16.h"
15 #include "windef.h"
16 #include "winerror.h"
17 #include "class.h"
18 #include "file.h"
19 #include "global.h"
20 #include "heap.h"
21 #include "module.h"
22 #include "neexe.h"
23 #include "pe_image.h"
24 #include "dosexe.h"
25 #include "process.h"
26 #include "thread.h"
27 #include "selectors.h"
28 #include "stackframe.h"
29 #include "task.h"
30 #include "debug.h"
31 #include "callback.h"
34 /*************************************************************************
35 * MODULE32_LookupHMODULE
36 * looks for the referenced HMODULE in the current process
38 WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
40 WINE_MODREF *wm;
42 if (!hmod)
43 return PROCESS_Current()->exe_modref;
45 if (!HIWORD(hmod)) {
46 ERR(module,"tried to lookup 0x%04x in win32 module handler!\n",hmod);
47 return NULL;
49 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next )
50 if (wm->module == hmod)
51 return wm;
52 return NULL;
55 /*************************************************************************
56 * MODULE_InitializeDLLs
58 * Call the initialization routines of all DLLs belonging to the
59 * current process. This is somewhat complicated due to the fact that
61 * - we have to respect the module dependencies, i.e. modules implicitly
62 * referenced by another module have to be initialized before the module
63 * itself can be initialized
65 * - the initialization routine of a DLL can itself call LoadLibrary,
66 * thereby introducing a whole new set of dependencies (even involving
67 * the 'old' modules) at any time during the whole process
69 * (Note that this routine can be recursively entered not only directly
70 * from itself, but also via LoadLibrary from one of the called initialization
71 * routines.)
73 static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
74 DWORD type, LPVOID lpReserved )
76 int i;
78 assert( wm && !wm->initDone );
79 TRACE( module, "(%08x,%ld,%p) - START\n",
80 wm->module, type, lpReserved );
82 /* Tag current MODREF to prevent recursive loop */
83 wm->initDone = TRUE;
85 /* Recursively initialize all child DLLs */
86 for ( i = 0; i < wm->nDeps; i++ )
87 if ( wm->deps[i] && !wm->deps[i]->initDone )
88 MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
90 /* Now we can call the initialization routine */
91 switch ( wm->type )
93 case MODULE32_PE:
94 PE_InitDLL( wm, type, lpReserved );
95 break;
97 case MODULE32_ELF:
98 /* no need to do that, dlopen() already does */
99 break;
100 default:
101 ERR(module, "wine_modref type %d not handled.\n", wm->type);
102 break;
105 TRACE( module, "(%08x,%ld,%p) - END\n",
106 wm->module, type, lpReserved );
109 void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
111 BOOL inProgress = FALSE;
112 WINE_MODREF *wm;
114 /* Grab the process critical section to protect the recursion flags */
115 /* FIXME: This is probably overkill! */
116 EnterCriticalSection( &PROCESS_Current()->crit_section );
118 TRACE( module, "(%08x,%ld,%p) - START\n", root, type, lpReserved );
120 /* First, check whether initialization is currently in progress */
121 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
122 if ( wm->initDone )
124 inProgress = TRUE;
125 break;
128 if ( inProgress )
131 * If this a LoadLibrary call from within an initialization routine,
132 * treat it analogously to an implicitly referenced DLL.
133 * Anything else may not happen at this point!
135 if ( root )
137 wm = MODULE32_LookupHMODULE( root );
138 if ( wm && !wm->initDone )
139 MODULE_DoInitializeDLLs( wm, type, lpReserved );
141 else
142 FIXME(module, "Invalid recursion!\n");
144 else
146 /* If we arrive here, this is the start of an initialization run */
147 if ( !root )
149 /* If called for main EXE, initialize all DLLs */
150 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
151 if ( !wm->initDone )
152 MODULE_DoInitializeDLLs( wm, type, lpReserved );
154 else
156 /* If called for a specific DLL, initialize only it and its children */
157 wm = MODULE32_LookupHMODULE( root );
158 if (wm) MODULE_DoInitializeDLLs( wm, type, lpReserved );
161 /* We're finished, so we reset all recursion flags */
162 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
163 wm->initDone = FALSE;
166 TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
168 /* Release critical section */
169 LeaveCriticalSection( &PROCESS_Current()->crit_section );
173 /***********************************************************************
174 * MODULE_CreateDummyModule
176 * Create a dummy NE module for Win32 or Winelib.
178 HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
180 HMODULE hModule;
181 NE_MODULE *pModule;
182 SEGTABLEENTRY *pSegment;
183 char *pStr,*s;
184 int len;
185 const char* basename;
187 INT of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
188 + strlen(ofs->szPathName) + 1;
189 INT size = sizeof(NE_MODULE) +
190 /* loaded file info */
191 of_size +
192 /* segment table: DS,CS */
193 2 * sizeof(SEGTABLEENTRY) +
194 /* name table */
196 /* several empty tables */
199 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
200 if (!hModule) return (HMODULE)11; /* invalid exe */
202 FarSetOwner16( hModule, hModule );
203 pModule = (NE_MODULE *)GlobalLock16( hModule );
205 /* Set all used entries */
206 pModule->magic = IMAGE_OS2_SIGNATURE;
207 pModule->count = 1;
208 pModule->next = 0;
209 pModule->flags = 0;
210 pModule->dgroup = 0;
211 pModule->ss = 1;
212 pModule->cs = 2;
213 pModule->heap_size = 0;
214 pModule->stack_size = 0;
215 pModule->seg_count = 2;
216 pModule->modref_count = 0;
217 pModule->nrname_size = 0;
218 pModule->fileinfo = sizeof(NE_MODULE);
219 pModule->os_flags = NE_OSFLAGS_WINDOWS;
220 pModule->expected_version = 0x030a;
221 pModule->self = hModule;
223 /* Set loaded file information */
224 memcpy( pModule + 1, ofs, of_size );
225 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
227 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
228 pModule->seg_table = (int)pSegment - (int)pModule;
229 /* Data segment */
230 pSegment->size = 0;
231 pSegment->flags = NE_SEGFLAGS_DATA;
232 pSegment->minsize = 0x1000;
233 pSegment++;
234 /* Code segment */
235 pSegment->flags = 0;
236 pSegment++;
238 /* Module name */
239 pStr = (char *)pSegment;
240 pModule->name_table = (int)pStr - (int)pModule;
241 if ( modName )
242 basename = modName;
243 else
245 basename = strrchr(ofs->szPathName,'\\');
246 if (!basename) basename = ofs->szPathName;
247 else basename++;
249 len = strlen(basename);
250 if ((s = strchr(basename,'.'))) len = s - basename;
251 if (len > 8) len = 8;
252 *pStr = len;
253 strncpy( pStr+1, basename, len );
254 if (len < 8) pStr[len+1] = 0;
255 pStr += 9;
257 /* All tables zero terminated */
258 pModule->res_table = pModule->import_table = pModule->entry_table =
259 (int)pStr - (int)pModule;
261 NE_RegisterModule( pModule );
262 return hModule;
266 /***********************************************************************
267 * MODULE_GetWndProcEntry16 (not a Windows API function)
269 * Return an entry point from the WPROCS dll.
271 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
273 FARPROC16 ret = NULL;
275 if (__winelib)
277 /* FIXME: hack for Winelib */
278 extern LRESULT ColorDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
279 extern LRESULT FileOpenDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
280 extern LRESULT FileSaveDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
281 extern LRESULT FindTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
282 extern LRESULT PrintDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
283 extern LRESULT PrintSetupDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
284 extern LRESULT ReplaceTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
286 if (!strcmp(name,"ColorDlgProc"))
287 return (FARPROC16)ColorDlgProc16;
288 if (!strcmp(name,"FileOpenDlgProc"))
289 return (FARPROC16)FileOpenDlgProc16;
290 if (!strcmp(name,"FileSaveDlgProc"))
291 return (FARPROC16)FileSaveDlgProc16;
292 if (!strcmp(name,"FindTextDlgProc"))
293 return (FARPROC16)FindTextDlgProc16;
294 if (!strcmp(name,"PrintDlgProc"))
295 return (FARPROC16)PrintDlgProc16;
296 if (!strcmp(name,"PrintSetupDlgProc"))
297 return (FARPROC16)PrintSetupDlgProc16;
298 if (!strcmp(name,"ReplaceTextDlgProc"))
299 return (FARPROC16)ReplaceTextDlgProc16;
300 if (!strcmp(name,"DefResourceHandler"))
301 return (FARPROC16)NE_DefResourceHandler;
302 FIXME(module,"No mapping for %s(), add one in library/miscstubs.c\n",name);
303 assert( FALSE );
304 return NULL;
306 else
308 WORD ordinal;
309 static HMODULE hModule = 0;
311 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
312 ordinal = NE_GetOrdinal( hModule, name );
313 if (!(ret = NE_GetEntryPoint( hModule, ordinal )))
315 WARN( module, "%s not found\n", name );
316 assert( FALSE );
319 return ret;
323 /**********************************************************************
324 * MODULE_FindModule32
326 * Find a (loaded) win32 module depending on path
327 * The handling of '.' is a bit weird, but we need it that way,
328 * for sometimes the programs use '<name>.exe' and '<name>.dll' and
329 * this is the only way to differentiate. (mainly hypertrm.exe)
331 * RETURNS
332 * the module handle if found
333 * 0 if not
335 HMODULE MODULE_FindModule(
336 LPCSTR path /* [in] pathname of module/library to be found */
338 LPSTR filename;
339 LPSTR dotptr;
340 WINE_MODREF *wm;
342 if (!(filename = strrchr( path, '\\' )))
343 filename = HEAP_strdupA( GetProcessHeap(), 0, path );
344 else
345 filename = HEAP_strdupA( GetProcessHeap(), 0, filename+1 );
346 dotptr=strrchr(filename,'.');
348 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
349 LPSTR xmodname,xdotptr;
351 assert (wm->modname);
352 xmodname = HEAP_strdupA( GetProcessHeap(), 0, wm->modname );
353 xdotptr=strrchr(xmodname,'.');
354 if ( (xdotptr && !dotptr) ||
355 (!xdotptr && dotptr)
357 if (dotptr) *dotptr = '\0';
358 if (xdotptr) *xdotptr = '\0';
360 if (!strcasecmp( filename, xmodname)) {
361 HeapFree( GetProcessHeap(), 0, filename );
362 HeapFree( GetProcessHeap(), 0, xmodname );
363 return wm->module;
365 if (dotptr) *dotptr='.';
366 /* FIXME: add paths, shortname */
367 HeapFree( GetProcessHeap(), 0, xmodname );
369 /* if that fails, try looking for the filename... */
370 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
371 LPSTR xlname,xdotptr;
373 assert (wm->longname);
374 xlname = strrchr(wm->longname,'\\');
375 if (!xlname)
376 xlname = wm->longname;
377 else
378 xlname++;
379 xlname = HEAP_strdupA( GetProcessHeap(), 0, xlname );
380 xdotptr=strrchr(xlname,'.');
381 if ( (xdotptr && !dotptr) ||
382 (!xdotptr && dotptr)
384 if (dotptr) *dotptr = '\0';
385 if (xdotptr) *xdotptr = '\0';
387 if (!strcasecmp( filename, xlname)) {
388 HeapFree( GetProcessHeap(), 0, filename );
389 HeapFree( GetProcessHeap(), 0, xlname );
390 return wm->module;
392 if (dotptr) *dotptr='.';
393 /* FIXME: add paths, shortname */
394 HeapFree( GetProcessHeap(), 0, xlname );
396 HeapFree( GetProcessHeap(), 0, filename );
397 return 0;
400 /***********************************************************************
401 * MODULE_GetBinaryType
403 * The GetBinaryType function determines whether a file is executable
404 * or not and if it is it returns what type of executable it is.
405 * The type of executable is a property that determines in which
406 * subsystem an executable file runs under.
408 * Binary types returned:
409 * SCS_32BIT_BINARY: A Win32 based application
410 * SCS_DOS_BINARY: An MS-Dos based application
411 * SCS_WOW_BINARY: A Win16 based application
412 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
413 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
414 * SCS_OS216_BINARY: A 16bit OS/2 based application ( Not implemented )
416 * Returns TRUE if the file is an executable in which case
417 * the value pointed by lpBinaryType is set.
418 * Returns FALSE if the file is not an executable or if the function fails.
420 * To do so it opens the file and reads in the header information
421 * if the extended header information is not presend it will
422 * assume that that the file is a DOS executable.
423 * If the extended header information is present it will
424 * determine if the file is an 16 or 32 bit Windows executable
425 * by check the flags in the header.
427 * Note that .COM and .PIF files are only recognized by their
428 * file name extension; but Windows does it the same way ...
430 static BOOL MODULE_GetBinaryType( HFILE hfile, OFSTRUCT *ofs,
431 LPDWORD lpBinaryType )
433 IMAGE_DOS_HEADER mz_header;
434 char magic[4], *ptr;
436 /* Seek to the start of the file and read the DOS header information.
438 if ( _llseek( hfile, 0, SEEK_SET ) >= 0 &&
439 _lread( hfile, &mz_header, sizeof(mz_header) ) == sizeof(mz_header) )
441 /* Now that we have the header check the e_magic field
442 * to see if this is a dos image.
444 if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
446 BOOL lfanewValid = FALSE;
447 /* We do have a DOS image so we will now try to seek into
448 * the file by the amount indicated by the field
449 * "Offset to extended header" and read in the
450 * "magic" field information at that location.
451 * This will tell us if there is more header information
452 * to read or not.
454 /* But before we do we will make sure that header
455 * structure encompasses the "Offset to extended header"
456 * field.
458 if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
459 if ( ( mz_header.e_crlc == 0 && mz_header.e_lfarlc == 0 ) ||
460 ( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
461 if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER) &&
462 _llseek( hfile, mz_header.e_lfanew, SEEK_SET ) >= 0 &&
463 _lread( hfile, magic, sizeof(magic) ) == sizeof(magic) )
464 lfanewValid = TRUE;
466 if ( !lfanewValid )
468 /* If we cannot read this "extended header" we will
469 * assume that we have a simple DOS executable.
471 *lpBinaryType = SCS_DOS_BINARY;
472 return TRUE;
474 else
476 /* Reading the magic field succeeded so
477 * we will try to determine what type it is.
479 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
481 /* This is an NT signature.
483 *lpBinaryType = SCS_32BIT_BINARY;
484 return TRUE;
486 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
488 /* The IMAGE_OS2_SIGNATURE indicates that the
489 * "extended header is a Windows executable (NE)
490 * header. This is a bit misleading, but it is
491 * documented in the SDK. ( for more details see
492 * the neexe.h file )
494 *lpBinaryType = SCS_WOW_BINARY;
495 return TRUE;
497 else
499 /* Unknown extended header, so abort.
501 return FALSE;
507 /* If we get here, we don't even have a correct MZ header.
508 * Try to check the file extension for known types ...
510 ptr = strrchr( ofs->szPathName, '.' );
511 if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
513 if ( !lstrcmpiA( ptr, ".COM" ) )
515 *lpBinaryType = SCS_DOS_BINARY;
516 return TRUE;
519 if ( !lstrcmpiA( ptr, ".PIF" ) )
521 *lpBinaryType = SCS_PIF_BINARY;
522 return TRUE;
526 return FALSE;
529 /***********************************************************************
530 * GetBinaryTypeA [KERNEL32.280]
532 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
534 BOOL ret = FALSE;
535 HFILE hfile;
536 OFSTRUCT ofs;
538 TRACE( win32, "%s\n", lpApplicationName );
540 /* Sanity check.
542 if ( lpApplicationName == NULL || lpBinaryType == NULL )
543 return FALSE;
545 /* Open the file indicated by lpApplicationName for reading.
547 if ( (hfile = OpenFile( lpApplicationName, &ofs, OF_READ )) == HFILE_ERROR )
548 return FALSE;
550 /* Check binary type
552 ret = MODULE_GetBinaryType( hfile, &ofs, lpBinaryType );
554 /* Close the file.
556 CloseHandle( hfile );
558 return ret;
561 /***********************************************************************
562 * GetBinaryTypeW [KERNEL32.281]
564 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
566 BOOL ret = FALSE;
567 LPSTR strNew = NULL;
569 TRACE( win32, "%s\n", debugstr_w(lpApplicationName) );
571 /* Sanity check.
573 if ( lpApplicationName == NULL || lpBinaryType == NULL )
574 return FALSE;
576 /* Convert the wide string to a ascii string.
578 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
580 if ( strNew != NULL )
582 ret = GetBinaryTypeA( strNew, lpBinaryType );
584 /* Free the allocated string.
586 HeapFree( GetProcessHeap(), 0, strNew );
589 return ret;
592 /**********************************************************************
593 * MODULE_CreateUnixProcess
595 static BOOL MODULE_CreateUnixProcess( LPCSTR filename, LPCSTR lpCmdLine,
596 LPSTARTUPINFOA lpStartupInfo,
597 LPPROCESS_INFORMATION lpProcessInfo,
598 BOOL useWine )
600 DOS_FULL_NAME full_name;
601 const char *unixfilename = filename;
602 const char *argv[256], **argptr;
603 BOOL iconic = FALSE;
605 /* Get Unix file name and iconic flag */
607 if ( lpStartupInfo->dwFlags & STARTF_USESHOWWINDOW )
608 if ( lpStartupInfo->wShowWindow == SW_SHOWMINIMIZED
609 || lpStartupInfo->wShowWindow == SW_SHOWMINNOACTIVE )
610 iconic = TRUE;
612 if ( strchr(filename, '/')
613 || strchr(filename, ':')
614 || strchr(filename, '\\') )
616 if ( DOSFS_GetFullName( filename, TRUE, &full_name ) )
617 unixfilename = full_name.long_name;
620 if ( !unixfilename )
622 SetLastError( ERROR_FILE_NOT_FOUND );
623 return FALSE;
626 /* Build argument list */
628 argptr = argv;
629 if ( !useWine )
631 char *p = strdup(lpCmdLine);
632 *argptr++ = unixfilename;
633 if (iconic) *argptr++ = "-iconic";
634 while (1)
636 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
637 if (!*p) break;
638 *argptr++ = p;
639 while (*p && *p != ' ' && *p != '\t') p++;
642 else
644 *argptr++ = "wine";
645 if (iconic) *argptr++ = "-iconic";
646 *argptr++ = lpCmdLine;
648 *argptr++ = 0;
650 /* Fork and execute */
652 if ( !fork() )
654 /* Note: don't use Wine routines here, as this process
655 has not been correctly initialized! */
657 execvp( argv[0], (char**)argv );
659 /* Failed ! */
660 if ( useWine )
661 fprintf( stderr, "CreateProcess: can't exec 'wine %s'\n",
662 lpCmdLine );
663 exit( 1 );
666 /* Fake success return value */
668 memset( lpProcessInfo, '\0', sizeof( *lpProcessInfo ) );
669 lpProcessInfo->hProcess = INVALID_HANDLE_VALUE;
670 lpProcessInfo->hThread = INVALID_HANDLE_VALUE;
672 SetLastError( ERROR_SUCCESS );
673 return TRUE;
676 /***********************************************************************
677 * WinExec16 (KERNEL.166)
679 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
681 return WinExec( lpCmdLine, nCmdShow );
684 /***********************************************************************
685 * WinExec (KERNEL32.566)
687 HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
689 LOADPARAMS params;
690 UINT16 paramCmdShow[2];
692 if (!lpCmdLine)
693 return 2; /* File not found */
695 /* Set up LOADPARAMS buffer for LoadModule */
697 memset( &params, '\0', sizeof(params) );
698 params.lpCmdLine = (LPSTR)lpCmdLine;
699 params.lpCmdShow = paramCmdShow;
700 params.lpCmdShow[0] = 2;
701 params.lpCmdShow[1] = nCmdShow;
703 /* Now load the executable file */
705 return LoadModule( NULL, &params );
708 /**********************************************************************
709 * LoadModule (KERNEL32.499)
711 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
713 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
714 PROCESS_INFORMATION info;
715 STARTUPINFOA startup;
716 HINSTANCE hInstance;
717 PDB *pdb;
718 TDB *tdb;
720 memset( &startup, '\0', sizeof(startup) );
721 startup.cb = sizeof(startup);
722 startup.dwFlags = STARTF_USESHOWWINDOW;
723 startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
725 if ( !CreateProcessA( name, params->lpCmdLine,
726 NULL, NULL, FALSE, 0, params->lpEnvAddress,
727 NULL, &startup, &info ) )
729 hInstance = GetLastError();
730 if ( hInstance < 32 ) return hInstance;
732 FIXME( module, "Strange error set by CreateProcess: %d\n", hInstance );
733 return 11;
736 /* Get 16-bit hInstance/hTask from process */
737 pdb = PROCESS_IdToPDB( info.dwProcessId );
738 tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
739 hInstance = tdb && tdb->hInstance? tdb->hInstance : pdb? pdb->task : 0;
741 /* Close off the handles */
742 CloseHandle( info.hThread );
743 CloseHandle( info.hProcess );
745 return hInstance;
749 static void get_executable_name( LPCSTR line, LPSTR name, int namelen,
750 LPCSTR *after, BOOL extension )
752 int len = 0;
753 LPCSTR p = NULL, pcmd = NULL;
755 if ((p = strchr(line, '"')))
757 p++; /* skip '"' */
758 line = p;
759 if ((pcmd = strchr(p, '"'))) { /* closing '"' available, too ? */
760 pcmd++;
761 len = (int)pcmd - (int)p;
765 if (!len)
767 p = strchr(line, ' ');
768 do {
769 len = (p? p-line : strlen(line)) + 1;
770 if (len > namelen - 4) len = namelen - 4;
771 lstrcpynA(name, line, len);
772 if (extension && !strchr(name, '\\') && !strchr(name, '.'))
773 strcat(name, ".exe");
774 if (GetFileAttributesA(name) != -1) {
775 pcmd = p ? p : line+strlen(line);
776 break;
778 /* if there is a space and no file found yet, include the word
779 * up to the next space too. If there is no next space, just
780 * use the first word.
782 if (p) {
783 p = strchr(p+1, ' ');
784 } else {
785 p = strchr(line, ' ');
786 len = (p? p-line : strlen(line)) + 1;
787 if (len > namelen - 4)
788 len = namelen - 4;
789 pcmd = p ? p + 1 : line+strlen(line);
790 break;
792 } while (1);
794 lstrcpynA(name, line, len);
795 if (after) *after = pcmd;
798 /**********************************************************************
799 * CreateProcessA (KERNEL32.171)
801 BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
802 LPSECURITY_ATTRIBUTES lpProcessAttributes,
803 LPSECURITY_ATTRIBUTES lpThreadAttributes,
804 BOOL bInheritHandles, DWORD dwCreationFlags,
805 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
806 LPSTARTUPINFOA lpStartupInfo,
807 LPPROCESS_INFORMATION lpProcessInfo )
809 BOOL retv = FALSE;
810 HFILE hFile;
811 OFSTRUCT ofs;
812 DWORD type;
813 char name[256];
814 LPCSTR cmdline;
815 #if 0
816 LPCSTR p = NULL;
817 #endif
819 /* Get name and command line */
821 if (!lpApplicationName && !lpCommandLine)
823 SetLastError( ERROR_FILE_NOT_FOUND );
824 return FALSE;
827 name[0] = '\0';
829 if (lpApplicationName) {
830 get_executable_name( lpApplicationName, name, sizeof(name), NULL, FALSE);
831 #if 0
832 p = strrchr(name, '.');
833 if (p >= name+strlen(name)-4) /* FIXME */
834 *p = '\0';
835 #endif
837 else {
838 get_executable_name ( lpCommandLine, name, sizeof ( name ), NULL, FALSE );
840 if (!lpCommandLine)
841 cmdline = lpApplicationName;
842 else cmdline = lpCommandLine;
844 if (!strchr(name, '\\') && !strchr(name, '.'))
845 strcat(name, ".exe");
848 /* Warn if unsupported features are used */
850 if (lpProcessAttributes)
851 FIXME(module, "(%s,...): lpProcessAttributes ignored\n", name);
852 if (lpThreadAttributes)
853 FIXME(module, "(%s,...): lpThreadAttributes ignored\n", name);
854 if (dwCreationFlags & DEBUG_PROCESS)
855 FIXME(module, "(%s,...): DEBUG_PROCESS ignored\n", name);
856 if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
857 FIXME(module, "(%s,...): DEBUG_ONLY_THIS_PROCESS ignored\n", name);
858 if (dwCreationFlags & CREATE_SUSPENDED)
859 FIXME(module, "(%s,...): CREATE_SUSPENDED ignored\n", name);
860 if (dwCreationFlags & DETACHED_PROCESS)
861 FIXME(module, "(%s,...): DETACHED_PROCESS ignored\n", name);
862 if (dwCreationFlags & CREATE_NEW_CONSOLE)
863 FIXME(module, "(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
864 if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
865 FIXME(module, "(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
866 if (dwCreationFlags & IDLE_PRIORITY_CLASS)
867 FIXME(module, "(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
868 if (dwCreationFlags & HIGH_PRIORITY_CLASS)
869 FIXME(module, "(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
870 if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
871 FIXME(module, "(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
872 if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
873 FIXME(module, "(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
874 if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
875 FIXME(module, "(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
876 if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
877 FIXME(module, "(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
878 if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
879 FIXME(module, "(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
880 if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
881 FIXME(module, "(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
882 if (dwCreationFlags & CREATE_NO_WINDOW)
883 FIXME(module, "(%s,...): CREATE_NO_WINDOW ignored\n", name);
884 if (dwCreationFlags & PROFILE_USER)
885 FIXME(module, "(%s,...): PROFILE_USER ignored\n", name);
886 if (dwCreationFlags & PROFILE_KERNEL)
887 FIXME(module, "(%s,...): PROFILE_KERNEL ignored\n", name);
888 if (dwCreationFlags & PROFILE_SERVER)
889 FIXME(module, "(%s,...): PROFILE_SERVER ignored\n", name);
890 if (lpCurrentDirectory)
891 FIXME(module, "(%s,...): lpCurrentDirectory %s ignored\n",
892 name, lpCurrentDirectory);
893 if (lpStartupInfo->lpDesktop)
894 FIXME(module, "(%s,...): lpStartupInfo->lpDesktop %s ignored\n",
895 name, lpStartupInfo->lpDesktop);
896 if (lpStartupInfo->lpTitle)
897 FIXME(module, "(%s,...): lpStartupInfo->lpTitle %s ignored\n",
898 name, lpStartupInfo->lpTitle);
899 if (lpStartupInfo->dwFlags & STARTF_USECOUNTCHARS)
900 FIXME(module, "(%s,...): STARTF_USECOUNTCHARS (%ld,%ld) ignored\n",
901 name, lpStartupInfo->dwXCountChars, lpStartupInfo->dwYCountChars);
902 if (lpStartupInfo->dwFlags & STARTF_USEFILLATTRIBUTE)
903 FIXME(module, "(%s,...): STARTF_USEFILLATTRIBUTE %lx ignored\n",
904 name, lpStartupInfo->dwFillAttribute);
905 if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
906 FIXME(module, "(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
907 if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
908 FIXME(module, "(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
909 if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
910 FIXME(module, "(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
911 if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
912 FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
915 /* When in WineLib, always fork new Unix process */
917 if ( __winelib )
918 return MODULE_CreateUnixProcess( name, cmdline,
919 lpStartupInfo, lpProcessInfo, TRUE );
921 /* Check for special case: second instance of NE module */
923 lstrcpynA( ofs.szPathName, name, sizeof( ofs.szPathName ) );
924 retv = NE_CreateProcess( HFILE_ERROR, &ofs, cmdline, lpEnvironment,
925 bInheritHandles, lpStartupInfo, lpProcessInfo );
927 /* Load file and create process */
929 if ( !retv )
931 /* Open file and determine executable type */
933 if ( (hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR )
935 SetLastError( ERROR_FILE_NOT_FOUND );
936 return FALSE;
939 if ( !MODULE_GetBinaryType( hFile, &ofs, &type ) )
941 CloseHandle( hFile );
943 /* FIXME: Try Unix executable only when appropriate! */
944 if ( MODULE_CreateUnixProcess( name, cmdline,
945 lpStartupInfo, lpProcessInfo, FALSE ) )
946 return TRUE;
948 SetLastError( ERROR_BAD_FORMAT );
949 return FALSE;
953 /* Create process */
955 switch ( type )
957 case SCS_32BIT_BINARY:
958 retv = PE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
959 bInheritHandles, lpStartupInfo, lpProcessInfo );
960 break;
962 case SCS_DOS_BINARY:
963 retv = MZ_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
964 bInheritHandles, lpStartupInfo, lpProcessInfo );
965 break;
967 case SCS_WOW_BINARY:
968 retv = NE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
969 bInheritHandles, lpStartupInfo, lpProcessInfo );
970 break;
972 case SCS_PIF_BINARY:
973 case SCS_POSIX_BINARY:
974 case SCS_OS216_BINARY:
975 FIXME( module, "Unsupported executable type: %ld\n", type );
976 /* fall through */
978 default:
979 SetLastError( ERROR_BAD_FORMAT );
980 retv = FALSE;
981 break;
984 CloseHandle( hFile );
987 /* Get hTask from process and start the task */
989 if ( retv )
991 PDB *pdb = PROCESS_IdToPDB( lpProcessInfo->dwProcessId );
992 if (pdb) TASK_StartTask( pdb->task );
995 return retv;
998 /**********************************************************************
999 * CreateProcessW (KERNEL32.172)
1000 * NOTES
1001 * lpReserved is not converted
1003 BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1004 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1005 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1006 BOOL bInheritHandles, DWORD dwCreationFlags,
1007 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
1008 LPSTARTUPINFOW lpStartupInfo,
1009 LPPROCESS_INFORMATION lpProcessInfo )
1010 { BOOL ret;
1011 STARTUPINFOA StartupInfoA;
1013 LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
1014 LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
1015 LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
1017 memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFOA));
1018 StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
1019 StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
1021 TRACE(win32, "(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
1023 if (lpStartupInfo->lpReserved)
1024 FIXME(win32,"StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
1026 ret = CreateProcessA( lpApplicationNameA, lpCommandLineA,
1027 lpProcessAttributes, lpThreadAttributes,
1028 bInheritHandles, dwCreationFlags,
1029 lpEnvironment, lpCurrentDirectoryA,
1030 &StartupInfoA, lpProcessInfo );
1032 HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
1033 HeapFree( GetProcessHeap(), 0, lpCommandLineA );
1034 HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
1035 HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
1037 return ret;
1040 /***********************************************************************
1041 * GetModuleHandle (KERNEL32.237)
1043 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
1045 if (module == NULL)
1046 return PROCESS_Current()->exe_modref->module;
1047 else
1048 return MODULE_FindModule( module );
1051 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
1053 HMODULE hModule;
1054 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1055 hModule = GetModuleHandleA( modulea );
1056 HeapFree( GetProcessHeap(), 0, modulea );
1057 return hModule;
1061 /***********************************************************************
1062 * GetModuleFileName32A (KERNEL32.235)
1064 DWORD WINAPI GetModuleFileNameA(
1065 HMODULE hModule, /* [in] module handle (32bit) */
1066 LPSTR lpFileName, /* [out] filenamebuffer */
1067 DWORD size /* [in] size of filenamebuffer */
1068 ) {
1069 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1071 if (!wm) /* can happen on start up or the like */
1072 return 0;
1074 if (PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion >= 4.0)
1075 lstrcpynA( lpFileName, wm->longname, size );
1076 else
1077 lstrcpynA( lpFileName, wm->shortname, size );
1079 TRACE(module, "%s\n", lpFileName );
1080 return strlen(lpFileName);
1084 /***********************************************************************
1085 * GetModuleFileName32W (KERNEL32.236)
1087 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName,
1088 DWORD size )
1090 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1091 DWORD res = GetModuleFileNameA( hModule, fnA, size );
1092 lstrcpynAtoW( lpFileName, fnA, size );
1093 HeapFree( GetProcessHeap(), 0, fnA );
1094 return res;
1098 /***********************************************************************
1099 * LoadLibraryEx32W (KERNEL.513)
1100 * FIXME
1102 HMODULE WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1103 DWORD flags )
1105 TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
1106 return LoadLibraryExA(libname, hf,flags);
1109 /***********************************************************************
1110 * LoadLibraryEx32A (KERNEL32)
1112 HMODULE WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags)
1114 HMODULE hmod;
1115 hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
1117 /* at least call not the dllmain...*/
1118 if ( DONT_RESOLVE_DLL_REFERENCES==flags || LOAD_LIBRARY_AS_DATAFILE==flags )
1119 { FIXME(module,"flag not properly supported %lx\n", flags);
1120 return hmod;
1123 /* initialize DLL just loaded */
1124 if ( hmod >= 32 )
1125 MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, (LPVOID)-1 );
1127 return hmod;
1130 HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
1132 HMODULE hmod;
1134 hmod = ELF_LoadLibraryExA( libname, hfile, flags );
1135 if (hmod) return hmod;
1137 hmod = PE_LoadLibraryExA( libname, hfile, flags );
1138 return hmod;
1141 /***********************************************************************
1142 * LoadLibraryA (KERNEL32)
1144 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
1145 return LoadLibraryExA(libname,0,0);
1148 /***********************************************************************
1149 * LoadLibraryW (KERNEL32)
1151 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
1153 return LoadLibraryExW(libnameW,0,0);
1156 /***********************************************************************
1157 * LoadLibraryExW (KERNEL32)
1159 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags)
1161 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1162 HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
1164 HeapFree( GetProcessHeap(), 0, libnameA );
1165 return ret;
1168 /***********************************************************************
1169 * FreeLibrary
1171 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
1173 FIXME(module,"(0x%08x): stub\n", hLibModule);
1174 return TRUE; /* FIXME */
1178 /***********************************************************************
1179 * PrivateLoadLibrary (KERNEL32)
1181 * FIXME: rough guesswork, don't know what "Private" means
1183 HINSTANCE WINAPI PrivateLoadLibrary(LPCSTR libname)
1185 return (HINSTANCE)LoadLibrary16(libname);
1190 /***********************************************************************
1191 * PrivateFreeLibrary (KERNEL32)
1193 * FIXME: rough guesswork, don't know what "Private" means
1195 void WINAPI PrivateFreeLibrary(HINSTANCE handle)
1197 FreeLibrary16((HINSTANCE16)handle);
1201 /***********************************************************************
1202 * WIN32_GetProcAddress16 (KERNEL32.36)
1203 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1205 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1207 WORD ordinal;
1208 FARPROC16 ret;
1210 if (!hModule) {
1211 WARN(module,"hModule may not be 0!\n");
1212 return (FARPROC16)0;
1214 if (HIWORD(hModule))
1216 WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
1217 return (FARPROC16)0;
1219 hModule = GetExePtr( hModule );
1220 if (HIWORD(name)) {
1221 ordinal = NE_GetOrdinal( hModule, name );
1222 TRACE(module, "%04x '%s'\n",
1223 hModule, name );
1224 } else {
1225 ordinal = LOWORD(name);
1226 TRACE(module, "%04x %04x\n",
1227 hModule, ordinal );
1229 if (!ordinal) return (FARPROC16)0;
1230 ret = NE_GetEntryPoint( hModule, ordinal );
1231 TRACE(module,"returning %08x\n",(UINT)ret);
1232 return ret;
1235 /***********************************************************************
1236 * GetProcAddress16 (KERNEL.50)
1238 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1240 WORD ordinal;
1241 FARPROC16 ret;
1243 if (!hModule) hModule = GetCurrentTask();
1244 hModule = GetExePtr( hModule );
1246 if (HIWORD(name) != 0)
1248 ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1249 TRACE(module, "%04x '%s'\n",
1250 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1252 else
1254 ordinal = LOWORD(name);
1255 TRACE(module, "%04x %04x\n",
1256 hModule, ordinal );
1258 if (!ordinal) return (FARPROC16)0;
1260 ret = NE_GetEntryPoint( hModule, ordinal );
1262 TRACE(module, "returning %08x\n", (UINT)ret );
1263 return ret;
1267 /***********************************************************************
1268 * GetProcAddress32 (KERNEL32.257)
1270 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
1272 return MODULE_GetProcAddress( hModule, function, TRUE );
1275 /***********************************************************************
1276 * WIN16_GetProcAddress32 (KERNEL.453)
1278 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
1280 return MODULE_GetProcAddress( hModule, function, FALSE );
1283 /***********************************************************************
1284 * MODULE_GetProcAddress32 (internal)
1286 FARPROC MODULE_GetProcAddress(
1287 HMODULE hModule, /* [in] current module handle */
1288 LPCSTR function, /* [in] function to be looked up */
1289 BOOL snoop )
1291 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1293 if (HIWORD(function))
1294 TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1295 else
1296 TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1297 if (!wm)
1298 return (FARPROC)0;
1299 switch (wm->type)
1301 case MODULE32_PE:
1302 return PE_FindExportedFunction( wm, function, snoop );
1303 case MODULE32_ELF:
1304 return ELF_FindExportedFunction( wm, function);
1305 default:
1306 ERR(module,"wine_modref type %d not handled.\n",wm->type);
1307 return (FARPROC)0;
1312 /***********************************************************************
1313 * RtlImageNtHeaders (NTDLL)
1315 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1317 /* basically:
1318 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1319 * but we could get HMODULE16 or the like (think builtin modules)
1322 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1323 if (!wm || (wm->type != MODULE32_PE)) return (PIMAGE_NT_HEADERS)0;
1324 return PE_HEADER(wm->module);
1328 /***************************************************************************
1329 * HasGPHandler (KERNEL.338)
1332 #pragma pack(1)
1333 typedef struct _GPHANDLERDEF
1335 WORD selector;
1336 WORD rangeStart;
1337 WORD rangeEnd;
1338 WORD handler;
1339 } GPHANDLERDEF;
1340 #pragma pack(4)
1342 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1344 HMODULE16 hModule;
1345 int gpOrdinal;
1346 SEGPTR gpPtr;
1347 GPHANDLERDEF *gpHandler;
1349 if ( (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1350 && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1351 && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1352 && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1353 && (gpHandler = PTR_SEG_TO_LIN( gpPtr )) != NULL )
1355 while (gpHandler->selector)
1357 if ( SELECTOROF(address) == gpHandler->selector
1358 && OFFSETOF(address) >= gpHandler->rangeStart
1359 && OFFSETOF(address) < gpHandler->rangeEnd )
1360 return PTR_SEG_OFF_TO_SEGPTR( gpHandler->selector,
1361 gpHandler->handler );
1362 gpHandler++;
1366 return 0;