4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
13 #include "wine/winuser16.h"
14 #include "wine/winbase16.h"
27 #include "selectors.h"
28 #include "stackframe.h"
34 /*************************************************************************
35 * MODULE32_LookupHMODULE
36 * looks for the referenced HMODULE in the current process
38 WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
43 return PROCESS_Current()->exe_modref;
46 ERR(module,"tried to lookup 0x%04x in win32 module handler!\n",hmod);
49 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next )
50 if (wm->module == hmod)
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
73 static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
74 DWORD type, LPVOID lpReserved )
79 assert( wm && !(wm->flags & WINE_MODREF_MARKER) );
80 TRACE( module, "(%s,%08x,%ld,%p) - START\n",
81 wm->modname, wm->module, type, lpReserved );
83 /* Tag current MODREF to prevent recursive loop */
84 wm->flags |= WINE_MODREF_MARKER;
89 case DLL_PROCESS_ATTACH:
90 case DLL_THREAD_ATTACH:
91 /* Recursively attach all DLLs this one depends on */
92 for ( i = 0; i < wm->nDeps; i++ )
93 if ( wm->deps[i] && !(wm->deps[i]->flags & WINE_MODREF_MARKER) )
94 MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
97 case DLL_PROCESS_DETACH:
98 case DLL_THREAD_DETACH:
99 /* Recursively detach all DLLs that depend on this one */
100 for ( xwm = PROCESS_Current()->modref_list; xwm; xwm = xwm->next )
101 if ( !(xwm->flags & WINE_MODREF_MARKER) )
102 for ( i = 0; i < xwm->nDeps; i++ )
103 if ( xwm->deps[i] == wm )
105 MODULE_DoInitializeDLLs( xwm, type, lpReserved );
111 /* Evaluate module flags */
113 if ( ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
114 || ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
115 || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )
118 if ( type == DLL_PROCESS_ATTACH )
119 if ( wm->flags & WINE_MODREF_PROCESS_ATTACHED )
122 wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
124 if ( type == DLL_PROCESS_DETACH )
125 if ( wm->flags & WINE_MODREF_PROCESS_DETACHED )
128 wm->flags |= WINE_MODREF_PROCESS_DETACHED;
132 /* Now we can call the initialization routine */
133 TRACE( module, "(%s,%08x,%ld,%p) - CALL\n",
134 wm->modname, wm->module, type, lpReserved );
139 PE_InitDLL( wm, type, lpReserved );
143 /* no need to do that, dlopen() already does */
147 ERR(module, "wine_modref type %d not handled.\n", wm->type);
152 TRACE( module, "(%s,%08x,%ld,%p) - END\n",
153 wm->modname, wm->module, type, lpReserved );
156 void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
158 BOOL inProgress = FALSE;
161 /* Grab the process critical section to protect the recursion flags */
162 /* FIXME: This is probably overkill! */
163 EnterCriticalSection( &PROCESS_Current()->crit_section );
165 TRACE( module, "(%08x,%ld,%p) - START\n", root, type, lpReserved );
167 /* First, check whether initialization is currently in progress */
168 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
169 if ( wm->flags & WINE_MODREF_MARKER )
178 * If this a LoadLibrary call from within an initialization routine,
179 * treat it analogously to an implicitly referenced DLL.
180 * Anything else may not happen at this point!
184 wm = MODULE32_LookupHMODULE( root );
185 if ( wm && !(wm->flags & WINE_MODREF_MARKER) )
186 MODULE_DoInitializeDLLs( wm, type, lpReserved );
189 FIXME(module, "Invalid recursion!\n");
193 /* If we arrive here, this is the start of an initialization run */
196 /* If called for main EXE, initialize all DLLs */
200 case DLL_PROCESS_ATTACH:
201 case DLL_THREAD_ATTACH:
202 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
205 for ( ; wm; wm = wm->prev )
206 if ( !(wm->flags & WINE_MODREF_MARKER) )
207 MODULE_DoInitializeDLLs( wm, type, lpReserved );
210 case DLL_PROCESS_DETACH:
211 case DLL_THREAD_DETACH:
212 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
213 if ( !(wm->flags & WINE_MODREF_MARKER) )
214 MODULE_DoInitializeDLLs( wm, type, lpReserved );
220 /* If called for a specific DLL, initialize only it and its children */
221 wm = MODULE32_LookupHMODULE( root );
222 if (wm) MODULE_DoInitializeDLLs( wm, type, lpReserved );
225 /* We're finished, so we reset all recursion flags */
226 for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
227 wm->flags &= ~WINE_MODREF_MARKER;
230 TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
232 /* Release critical section */
233 LeaveCriticalSection( &PROCESS_Current()->crit_section );
236 /****************************************************************************
237 * DisableThreadLibraryCalls (KERNEL32.74)
239 * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
241 BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
243 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
244 if ( !wm ) return FALSE;
246 wm->flags |= WINE_MODREF_NO_DLL_CALLS;
250 /****************************************************************************
253 static void MODULE_IncRefCount( HMODULE hModule )
255 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
258 EnterCriticalSection( &PROCESS_Current()->crit_section );
260 LeaveCriticalSection( &PROCESS_Current()->crit_section );
263 /****************************************************************************
266 static int MODULE_DecRefCount( HMODULE hModule )
269 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
272 EnterCriticalSection( &PROCESS_Current()->crit_section );
273 if ( ( retv = wm->refCount ) > 0 ) wm->refCount--;
274 LeaveCriticalSection( &PROCESS_Current()->crit_section );
280 /***********************************************************************
281 * MODULE_CreateDummyModule
283 * Create a dummy NE module for Win32 or Winelib.
285 HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
289 SEGTABLEENTRY *pSegment;
292 const char* basename;
294 INT of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
295 + strlen(ofs->szPathName) + 1;
296 INT size = sizeof(NE_MODULE) +
297 /* loaded file info */
299 /* segment table: DS,CS */
300 2 * sizeof(SEGTABLEENTRY) +
303 /* several empty tables */
306 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
307 if (!hModule) return (HMODULE)11; /* invalid exe */
309 FarSetOwner16( hModule, hModule );
310 pModule = (NE_MODULE *)GlobalLock16( hModule );
312 /* Set all used entries */
313 pModule->magic = IMAGE_OS2_SIGNATURE;
320 pModule->heap_size = 0;
321 pModule->stack_size = 0;
322 pModule->seg_count = 2;
323 pModule->modref_count = 0;
324 pModule->nrname_size = 0;
325 pModule->fileinfo = sizeof(NE_MODULE);
326 pModule->os_flags = NE_OSFLAGS_WINDOWS;
327 pModule->expected_version = 0x030a;
328 pModule->self = hModule;
330 /* Set loaded file information */
331 memcpy( pModule + 1, ofs, of_size );
332 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
334 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
335 pModule->seg_table = (int)pSegment - (int)pModule;
338 pSegment->flags = NE_SEGFLAGS_DATA;
339 pSegment->minsize = 0x1000;
346 pStr = (char *)pSegment;
347 pModule->name_table = (int)pStr - (int)pModule;
352 basename = strrchr(ofs->szPathName,'\\');
353 if (!basename) basename = ofs->szPathName;
356 len = strlen(basename);
357 if ((s = strchr(basename,'.'))) len = s - basename;
358 if (len > 8) len = 8;
360 strncpy( pStr+1, basename, len );
361 if (len < 8) pStr[len+1] = 0;
364 /* All tables zero terminated */
365 pModule->res_table = pModule->import_table = pModule->entry_table =
366 (int)pStr - (int)pModule;
368 NE_RegisterModule( pModule );
373 /***********************************************************************
374 * MODULE_GetWndProcEntry16 (not a Windows API function)
376 * Return an entry point from the WPROCS dll.
378 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
380 FARPROC16 ret = NULL;
384 /* FIXME: hack for Winelib */
385 extern LRESULT ColorDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
386 extern LRESULT FileOpenDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
387 extern LRESULT FileSaveDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
388 extern LRESULT FindTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
389 extern LRESULT PrintDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
390 extern LRESULT PrintSetupDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
391 extern LRESULT ReplaceTextDlgProc16(HWND16,UINT16,WPARAM16,LPARAM);
393 if (!strcmp(name,"ColorDlgProc"))
394 return (FARPROC16)ColorDlgProc16;
395 if (!strcmp(name,"FileOpenDlgProc"))
396 return (FARPROC16)FileOpenDlgProc16;
397 if (!strcmp(name,"FileSaveDlgProc"))
398 return (FARPROC16)FileSaveDlgProc16;
399 if (!strcmp(name,"FindTextDlgProc"))
400 return (FARPROC16)FindTextDlgProc16;
401 if (!strcmp(name,"PrintDlgProc"))
402 return (FARPROC16)PrintDlgProc16;
403 if (!strcmp(name,"PrintSetupDlgProc"))
404 return (FARPROC16)PrintSetupDlgProc16;
405 if (!strcmp(name,"ReplaceTextDlgProc"))
406 return (FARPROC16)ReplaceTextDlgProc16;
407 FIXME(module,"No mapping for %s(), add one in library/miscstubs.c\n",name);
414 static HMODULE hModule = 0;
416 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
417 ordinal = NE_GetOrdinal( hModule, name );
418 if (!(ret = NE_GetEntryPoint( hModule, ordinal )))
420 WARN( module, "%s not found\n", name );
428 /**********************************************************************
429 * MODULE_FindModule32
431 * Find a (loaded) win32 module depending on path
432 * The handling of '.' is a bit weird, but we need it that way,
433 * for sometimes the programs use '<name>.exe' and '<name>.dll' and
434 * this is the only way to differentiate. (mainly hypertrm.exe)
437 * the module handle if found
440 HMODULE MODULE_FindModule(
441 LPCSTR path /* [in] pathname of module/library to be found */
447 if (!(filename = strrchr( path, '\\' )))
448 filename = HEAP_strdupA( GetProcessHeap(), 0, path );
450 filename = HEAP_strdupA( GetProcessHeap(), 0, filename+1 );
451 dotptr=strrchr(filename,'.');
453 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
454 LPSTR xmodname,xdotptr;
456 assert (wm->modname);
457 xmodname = HEAP_strdupA( GetProcessHeap(), 0, wm->modname );
458 xdotptr=strrchr(xmodname,'.');
459 if ( (xdotptr && !dotptr) ||
462 if (dotptr) *dotptr = '\0';
463 if (xdotptr) *xdotptr = '\0';
465 if (!strcasecmp( filename, xmodname)) {
466 HeapFree( GetProcessHeap(), 0, filename );
467 HeapFree( GetProcessHeap(), 0, xmodname );
470 if (dotptr) *dotptr='.';
471 /* FIXME: add paths, shortname */
472 HeapFree( GetProcessHeap(), 0, xmodname );
474 /* if that fails, try looking for the filename... */
475 for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next ) {
476 LPSTR xlname,xdotptr;
478 assert (wm->longname);
479 xlname = strrchr(wm->longname,'\\');
481 xlname = wm->longname;
484 xlname = HEAP_strdupA( GetProcessHeap(), 0, xlname );
485 xdotptr=strrchr(xlname,'.');
486 if ( (xdotptr && !dotptr) ||
489 if (dotptr) *dotptr = '\0';
490 if (xdotptr) *xdotptr = '\0';
492 if (!strcasecmp( filename, xlname)) {
493 HeapFree( GetProcessHeap(), 0, filename );
494 HeapFree( GetProcessHeap(), 0, xlname );
497 if (dotptr) *dotptr='.';
498 /* FIXME: add paths, shortname */
499 HeapFree( GetProcessHeap(), 0, xlname );
501 HeapFree( GetProcessHeap(), 0, filename );
505 /***********************************************************************
506 * MODULE_GetBinaryType
508 * The GetBinaryType function determines whether a file is executable
509 * or not and if it is it returns what type of executable it is.
510 * The type of executable is a property that determines in which
511 * subsystem an executable file runs under.
513 * Binary types returned:
514 * SCS_32BIT_BINARY: A Win32 based application
515 * SCS_DOS_BINARY: An MS-Dos based application
516 * SCS_WOW_BINARY: A Win16 based application
517 * SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
518 * SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
519 * SCS_OS216_BINARY: A 16bit OS/2 based application ( Not implemented )
521 * Returns TRUE if the file is an executable in which case
522 * the value pointed by lpBinaryType is set.
523 * Returns FALSE if the file is not an executable or if the function fails.
525 * To do so it opens the file and reads in the header information
526 * if the extended header information is not presend it will
527 * assume that that the file is a DOS executable.
528 * If the extended header information is present it will
529 * determine if the file is an 16 or 32 bit Windows executable
530 * by check the flags in the header.
532 * Note that .COM and .PIF files are only recognized by their
533 * file name extension; but Windows does it the same way ...
535 static BOOL MODULE_GetBinaryType( HFILE hfile, OFSTRUCT *ofs,
536 LPDWORD lpBinaryType )
538 IMAGE_DOS_HEADER mz_header;
541 /* Seek to the start of the file and read the DOS header information.
543 if ( _llseek( hfile, 0, SEEK_SET ) >= 0 &&
544 _lread( hfile, &mz_header, sizeof(mz_header) ) == sizeof(mz_header) )
546 /* Now that we have the header check the e_magic field
547 * to see if this is a dos image.
549 if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
551 BOOL lfanewValid = FALSE;
552 /* We do have a DOS image so we will now try to seek into
553 * the file by the amount indicated by the field
554 * "Offset to extended header" and read in the
555 * "magic" field information at that location.
556 * This will tell us if there is more header information
559 /* But before we do we will make sure that header
560 * structure encompasses the "Offset to extended header"
563 if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
564 if ( ( mz_header.e_crlc == 0 && mz_header.e_lfarlc == 0 ) ||
565 ( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
566 if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER) &&
567 _llseek( hfile, mz_header.e_lfanew, SEEK_SET ) >= 0 &&
568 _lread( hfile, magic, sizeof(magic) ) == sizeof(magic) )
573 /* If we cannot read this "extended header" we will
574 * assume that we have a simple DOS executable.
576 *lpBinaryType = SCS_DOS_BINARY;
581 /* Reading the magic field succeeded so
582 * we will try to determine what type it is.
584 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
586 /* This is an NT signature.
588 *lpBinaryType = SCS_32BIT_BINARY;
591 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
593 /* The IMAGE_OS2_SIGNATURE indicates that the
594 * "extended header is a Windows executable (NE)
595 * header. This is a bit misleading, but it is
596 * documented in the SDK. ( for more details see
599 *lpBinaryType = SCS_WOW_BINARY;
604 /* Unknown extended header, so abort.
612 /* If we get here, we don't even have a correct MZ header.
613 * Try to check the file extension for known types ...
615 ptr = strrchr( ofs->szPathName, '.' );
616 if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
618 if ( !lstrcmpiA( ptr, ".COM" ) )
620 *lpBinaryType = SCS_DOS_BINARY;
624 if ( !lstrcmpiA( ptr, ".PIF" ) )
626 *lpBinaryType = SCS_PIF_BINARY;
634 /***********************************************************************
635 * GetBinaryTypeA [KERNEL32.280]
637 BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
643 TRACE( win32, "%s\n", lpApplicationName );
647 if ( lpApplicationName == NULL || lpBinaryType == NULL )
650 /* Open the file indicated by lpApplicationName for reading.
652 if ( (hfile = OpenFile( lpApplicationName, &ofs, OF_READ )) == HFILE_ERROR )
657 ret = MODULE_GetBinaryType( hfile, &ofs, lpBinaryType );
661 CloseHandle( hfile );
666 /***********************************************************************
667 * GetBinaryTypeW [KERNEL32.281]
669 BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
674 TRACE( win32, "%s\n", debugstr_w(lpApplicationName) );
678 if ( lpApplicationName == NULL || lpBinaryType == NULL )
681 /* Convert the wide string to a ascii string.
683 strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
685 if ( strNew != NULL )
687 ret = GetBinaryTypeA( strNew, lpBinaryType );
689 /* Free the allocated string.
691 HeapFree( GetProcessHeap(), 0, strNew );
697 /**********************************************************************
698 * MODULE_CreateUnixProcess
700 static BOOL MODULE_CreateUnixProcess( LPCSTR filename, LPCSTR lpCmdLine,
701 LPSTARTUPINFOA lpStartupInfo,
702 LPPROCESS_INFORMATION lpProcessInfo,
705 DOS_FULL_NAME full_name;
706 const char *unixfilename = filename;
707 const char *argv[256], **argptr;
710 /* Get Unix file name and iconic flag */
712 if ( lpStartupInfo->dwFlags & STARTF_USESHOWWINDOW )
713 if ( lpStartupInfo->wShowWindow == SW_SHOWMINIMIZED
714 || lpStartupInfo->wShowWindow == SW_SHOWMINNOACTIVE )
717 if ( strchr(filename, '/')
718 || strchr(filename, ':')
719 || strchr(filename, '\\') )
721 if ( DOSFS_GetFullName( filename, TRUE, &full_name ) )
722 unixfilename = full_name.long_name;
727 SetLastError( ERROR_FILE_NOT_FOUND );
731 /* Build argument list */
736 char *p = strdup(lpCmdLine);
737 *argptr++ = unixfilename;
738 if (iconic) *argptr++ = "-iconic";
741 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
744 while (*p && *p != ' ' && *p != '\t') p++;
750 if (iconic) *argptr++ = "-iconic";
751 *argptr++ = lpCmdLine;
755 /* Fork and execute */
759 /* Note: don't use Wine routines here, as this process
760 has not been correctly initialized! */
762 execvp( argv[0], (char**)argv );
766 fprintf( stderr, "CreateProcess: can't exec 'wine %s'\n",
771 /* Fake success return value */
773 memset( lpProcessInfo, '\0', sizeof( *lpProcessInfo ) );
774 lpProcessInfo->hProcess = INVALID_HANDLE_VALUE;
775 lpProcessInfo->hThread = INVALID_HANDLE_VALUE;
777 SetLastError( ERROR_SUCCESS );
781 /***********************************************************************
782 * WinExec16 (KERNEL.166)
784 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
786 return WinExec( lpCmdLine, nCmdShow );
789 /***********************************************************************
790 * WinExec (KERNEL32.566)
792 HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
795 UINT16 paramCmdShow[2];
798 return 2; /* File not found */
800 /* Set up LOADPARAMS buffer for LoadModule */
802 memset( ¶ms, '\0', sizeof(params) );
803 params.lpCmdLine = (LPSTR)lpCmdLine;
804 params.lpCmdShow = paramCmdShow;
805 params.lpCmdShow[0] = 2;
806 params.lpCmdShow[1] = nCmdShow;
808 /* Now load the executable file */
810 return LoadModule( NULL, ¶ms );
813 /**********************************************************************
814 * LoadModule (KERNEL32.499)
816 HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
818 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
819 PROCESS_INFORMATION info;
820 STARTUPINFOA startup;
825 memset( &startup, '\0', sizeof(startup) );
826 startup.cb = sizeof(startup);
827 startup.dwFlags = STARTF_USESHOWWINDOW;
828 startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
830 if ( !CreateProcessA( name, params->lpCmdLine,
831 NULL, NULL, FALSE, 0, params->lpEnvAddress,
832 NULL, &startup, &info ) )
834 hInstance = GetLastError();
835 if ( hInstance < 32 ) return hInstance;
837 FIXME( module, "Strange error set by CreateProcess: %d\n", hInstance );
841 /* Get 16-bit hInstance/hTask from process */
842 pdb = PROCESS_IdToPDB( info.dwProcessId );
843 tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
844 hInstance = tdb && tdb->hInstance? tdb->hInstance : pdb? pdb->task : 0;
846 /* Close off the handles */
847 CloseHandle( info.hThread );
848 CloseHandle( info.hProcess );
854 static void get_executable_name( LPCSTR line, LPSTR name, int namelen,
855 LPCSTR *after, BOOL extension )
858 LPCSTR p = NULL, pcmd = NULL;
860 while ( *line == ' ' ) line++;
863 line++; /* skip '"' */
864 if ((pcmd = strchr(line, '"'))) /* closing '"' available, too ? */
869 if((p = strchr(line, ' ')))
879 if(len > (namelen - 4)) len = namelen - 4;
880 lstrcpynA(name, line, len);
881 if(extension && (strrchr(name, '.') <= strrchr(name, '\\')) )
882 strcat(name, ".exe");
883 if (after) *after = pcmd;
886 /**********************************************************************
887 * CreateProcessA (KERNEL32.171)
889 BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
890 LPSECURITY_ATTRIBUTES lpProcessAttributes,
891 LPSECURITY_ATTRIBUTES lpThreadAttributes,
892 BOOL bInheritHandles, DWORD dwCreationFlags,
893 LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
894 LPSTARTUPINFOA lpStartupInfo,
895 LPPROCESS_INFORMATION lpProcessInfo )
904 /* Get name and command line */
906 if (!lpApplicationName && !lpCommandLine)
908 SetLastError( ERROR_FILE_NOT_FOUND );
914 if (lpApplicationName) {
915 get_executable_name( lpApplicationName, name, sizeof(name), NULL, TRUE );
918 get_executable_name( lpCommandLine, name, sizeof ( name ), NULL, TRUE );
921 cmdline = lpApplicationName;
922 else cmdline = lpCommandLine;
924 /* Warn if unsupported features are used */
926 if (dwCreationFlags & DEBUG_PROCESS)
927 FIXME(module, "(%s,...): DEBUG_PROCESS ignored\n", name);
928 if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
929 FIXME(module, "(%s,...): DEBUG_ONLY_THIS_PROCESS ignored\n", name);
930 if (dwCreationFlags & CREATE_SUSPENDED)
931 FIXME(module, "(%s,...): CREATE_SUSPENDED ignored\n", name);
932 if (dwCreationFlags & DETACHED_PROCESS)
933 FIXME(module, "(%s,...): DETACHED_PROCESS ignored\n", name);
934 if (dwCreationFlags & CREATE_NEW_CONSOLE)
935 FIXME(module, "(%s,...): CREATE_NEW_CONSOLE ignored\n", name);
936 if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
937 FIXME(module, "(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
938 if (dwCreationFlags & IDLE_PRIORITY_CLASS)
939 FIXME(module, "(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
940 if (dwCreationFlags & HIGH_PRIORITY_CLASS)
941 FIXME(module, "(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
942 if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
943 FIXME(module, "(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
944 if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
945 FIXME(module, "(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
946 if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
947 FIXME(module, "(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
948 if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
949 FIXME(module, "(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
950 if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
951 FIXME(module, "(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
952 if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
953 FIXME(module, "(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
954 if (dwCreationFlags & CREATE_NO_WINDOW)
955 FIXME(module, "(%s,...): CREATE_NO_WINDOW ignored\n", name);
956 if (dwCreationFlags & PROFILE_USER)
957 FIXME(module, "(%s,...): PROFILE_USER ignored\n", name);
958 if (dwCreationFlags & PROFILE_KERNEL)
959 FIXME(module, "(%s,...): PROFILE_KERNEL ignored\n", name);
960 if (dwCreationFlags & PROFILE_SERVER)
961 FIXME(module, "(%s,...): PROFILE_SERVER ignored\n", name);
962 if (lpCurrentDirectory)
963 FIXME(module, "(%s,...): lpCurrentDirectory %s ignored\n",
964 name, lpCurrentDirectory);
965 if (lpStartupInfo->lpDesktop)
966 FIXME(module, "(%s,...): lpStartupInfo->lpDesktop %s ignored\n",
967 name, lpStartupInfo->lpDesktop);
968 if (lpStartupInfo->lpTitle)
969 FIXME(module, "(%s,...): lpStartupInfo->lpTitle %s ignored\n",
970 name, lpStartupInfo->lpTitle);
971 if (lpStartupInfo->dwFlags & STARTF_USECOUNTCHARS)
972 FIXME(module, "(%s,...): STARTF_USECOUNTCHARS (%ld,%ld) ignored\n",
973 name, lpStartupInfo->dwXCountChars, lpStartupInfo->dwYCountChars);
974 if (lpStartupInfo->dwFlags & STARTF_USEFILLATTRIBUTE)
975 FIXME(module, "(%s,...): STARTF_USEFILLATTRIBUTE %lx ignored\n",
976 name, lpStartupInfo->dwFillAttribute);
977 if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
978 FIXME(module, "(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
979 if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
980 FIXME(module, "(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
981 if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
982 FIXME(module, "(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
983 if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
984 FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
987 /* When in WineLib, always fork new Unix process */
990 return MODULE_CreateUnixProcess( name, cmdline,
991 lpStartupInfo, lpProcessInfo, TRUE );
993 /* Check for special case: second instance of NE module */
995 lstrcpynA( ofs.szPathName, name, sizeof( ofs.szPathName ) );
996 retv = NE_CreateProcess( HFILE_ERROR, &ofs, cmdline, lpEnvironment,
997 lpProcessAttributes, lpThreadAttributes,
998 bInheritHandles, lpStartupInfo, lpProcessInfo );
1000 /* Load file and create process */
1004 /* Open file and determine executable type */
1006 if ( (hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR )
1008 SetLastError( ERROR_FILE_NOT_FOUND );
1012 if ( !MODULE_GetBinaryType( hFile, &ofs, &type ) )
1014 CloseHandle( hFile );
1016 /* FIXME: Try Unix executable only when appropriate! */
1017 if ( MODULE_CreateUnixProcess( name, cmdline,
1018 lpStartupInfo, lpProcessInfo, FALSE ) )
1021 SetLastError( ERROR_BAD_FORMAT );
1026 /* Create process */
1030 case SCS_32BIT_BINARY:
1031 retv = PE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
1032 lpProcessAttributes, lpThreadAttributes,
1033 bInheritHandles, lpStartupInfo, lpProcessInfo );
1036 case SCS_DOS_BINARY:
1037 retv = MZ_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
1038 lpProcessAttributes, lpThreadAttributes,
1039 bInheritHandles, lpStartupInfo, lpProcessInfo );
1042 case SCS_WOW_BINARY:
1043 retv = NE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
1044 lpProcessAttributes, lpThreadAttributes,
1045 bInheritHandles, lpStartupInfo, lpProcessInfo );
1048 case SCS_PIF_BINARY:
1049 case SCS_POSIX_BINARY:
1050 case SCS_OS216_BINARY:
1051 FIXME( module, "Unsupported executable type: %ld\n", type );
1055 SetLastError( ERROR_BAD_FORMAT );
1060 CloseHandle( hFile );
1065 /**********************************************************************
1066 * CreateProcessW (KERNEL32.172)
1068 * lpReserved is not converted
1070 BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
1071 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1072 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1073 BOOL bInheritHandles, DWORD dwCreationFlags,
1074 LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
1075 LPSTARTUPINFOW lpStartupInfo,
1076 LPPROCESS_INFORMATION lpProcessInfo )
1078 STARTUPINFOA StartupInfoA;
1080 LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
1081 LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
1082 LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
1084 memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFOA));
1085 StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
1086 StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
1088 TRACE(win32, "(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
1090 if (lpStartupInfo->lpReserved)
1091 FIXME(win32,"StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
1093 ret = CreateProcessA( lpApplicationNameA, lpCommandLineA,
1094 lpProcessAttributes, lpThreadAttributes,
1095 bInheritHandles, dwCreationFlags,
1096 lpEnvironment, lpCurrentDirectoryA,
1097 &StartupInfoA, lpProcessInfo );
1099 HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
1100 HeapFree( GetProcessHeap(), 0, lpCommandLineA );
1101 HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
1102 HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
1107 /***********************************************************************
1108 * GetModuleHandle (KERNEL32.237)
1110 HMODULE WINAPI GetModuleHandleA(LPCSTR module)
1113 return PROCESS_Current()->exe_modref->module;
1115 return MODULE_FindModule( module );
1118 HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
1121 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1122 hModule = GetModuleHandleA( modulea );
1123 HeapFree( GetProcessHeap(), 0, modulea );
1128 /***********************************************************************
1129 * GetModuleFileName32A (KERNEL32.235)
1131 DWORD WINAPI GetModuleFileNameA(
1132 HMODULE hModule, /* [in] module handle (32bit) */
1133 LPSTR lpFileName, /* [out] filenamebuffer */
1134 DWORD size /* [in] size of filenamebuffer */
1136 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1138 if (!wm) /* can happen on start up or the like */
1141 if (PE_HEADER(wm->module)->OptionalHeader.MajorOperatingSystemVersion >= 4.0)
1142 lstrcpynA( lpFileName, wm->longname, size );
1144 lstrcpynA( lpFileName, wm->shortname, size );
1146 TRACE(module, "%s\n", lpFileName );
1147 return strlen(lpFileName);
1151 /***********************************************************************
1152 * GetModuleFileName32W (KERNEL32.236)
1154 DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName,
1157 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1158 DWORD res = GetModuleFileNameA( hModule, fnA, size );
1159 lstrcpynAtoW( lpFileName, fnA, size );
1160 HeapFree( GetProcessHeap(), 0, fnA );
1165 /***********************************************************************
1166 * LoadLibraryEx32W (KERNEL.513)
1169 HMODULE WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1172 TRACE(module,"(%s,%d,%08lx)\n",libname,hf,flags);
1173 return LoadLibraryExA(libname, hf,flags);
1176 /***********************************************************************
1177 * LoadLibraryEx32A (KERNEL32)
1179 HMODULE WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags)
1184 SetLastError(ERROR_INVALID_PARAMETER);
1187 hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
1191 /* Increment RefCount */
1192 MODULE_IncRefCount( hmod );
1194 /* Initialize DLL just loaded */
1195 MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL );
1196 /* FIXME: check for failure, SLE(ERROR_DLL_INIT_FAILED) */
1202 HMODULE MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
1206 hmod = ELF_LoadLibraryExA( libname, hfile, flags );
1207 if (hmod) return hmod;
1209 hmod = PE_LoadLibraryExA( libname, hfile, flags );
1213 /***********************************************************************
1214 * LoadLibraryA (KERNEL32)
1216 HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
1217 return LoadLibraryExA(libname,0,0);
1220 /***********************************************************************
1221 * LoadLibraryW (KERNEL32)
1223 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
1225 return LoadLibraryExW(libnameW,0,0);
1228 /***********************************************************************
1229 * LoadLibraryExW (KERNEL32)
1231 HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags)
1233 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1234 HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
1236 HeapFree( GetProcessHeap(), 0, libnameA );
1240 /***********************************************************************
1243 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
1245 if ( MODULE_DecRefCount( hLibModule ) != 1 ) return TRUE;
1247 FIXME(module,"(0x%08x): should unload now\n", hLibModule);
1248 return TRUE; /* FIXME */
1251 /***********************************************************************
1252 * FreeLibraryAndExitThread
1254 VOID WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
1256 FreeLibrary(hLibModule);
1257 ExitThread(dwExitCode);
1260 /***********************************************************************
1261 * PrivateLoadLibrary (KERNEL32)
1263 * FIXME: rough guesswork, don't know what "Private" means
1265 HINSTANCE WINAPI PrivateLoadLibrary(LPCSTR libname)
1267 return (HINSTANCE)LoadLibrary16(libname);
1272 /***********************************************************************
1273 * PrivateFreeLibrary (KERNEL32)
1275 * FIXME: rough guesswork, don't know what "Private" means
1277 void WINAPI PrivateFreeLibrary(HINSTANCE handle)
1279 FreeLibrary16((HINSTANCE16)handle);
1283 /***********************************************************************
1284 * WIN32_GetProcAddress16 (KERNEL32.36)
1285 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1287 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1293 WARN(module,"hModule may not be 0!\n");
1294 return (FARPROC16)0;
1296 if (HIWORD(hModule))
1298 WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
1299 return (FARPROC16)0;
1301 hModule = GetExePtr( hModule );
1303 ordinal = NE_GetOrdinal( hModule, name );
1304 TRACE(module, "%04x '%s'\n",
1307 ordinal = LOWORD(name);
1308 TRACE(module, "%04x %04x\n",
1311 if (!ordinal) return (FARPROC16)0;
1312 ret = NE_GetEntryPoint( hModule, ordinal );
1313 TRACE(module,"returning %08x\n",(UINT)ret);
1317 /***********************************************************************
1318 * GetProcAddress16 (KERNEL.50)
1320 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1325 if (!hModule) hModule = GetCurrentTask();
1326 hModule = GetExePtr( hModule );
1328 if (HIWORD(name) != 0)
1330 ordinal = NE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1331 TRACE(module, "%04x '%s'\n",
1332 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1336 ordinal = LOWORD(name);
1337 TRACE(module, "%04x %04x\n",
1340 if (!ordinal) return (FARPROC16)0;
1342 ret = NE_GetEntryPoint( hModule, ordinal );
1344 TRACE(module, "returning %08x\n", (UINT)ret );
1349 /***********************************************************************
1350 * GetProcAddress32 (KERNEL32.257)
1352 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
1354 return MODULE_GetProcAddress( hModule, function, TRUE );
1357 /***********************************************************************
1358 * WIN16_GetProcAddress32 (KERNEL.453)
1360 FARPROC WINAPI GetProcAddress32_16( HMODULE hModule, LPCSTR function )
1362 return MODULE_GetProcAddress( hModule, function, FALSE );
1365 /***********************************************************************
1366 * MODULE_GetProcAddress32 (internal)
1368 FARPROC MODULE_GetProcAddress(
1369 HMODULE hModule, /* [in] current module handle */
1370 LPCSTR function, /* [in] function to be looked up */
1373 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1376 if (HIWORD(function))
1377 TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1379 TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1381 SetLastError(ERROR_INVALID_HANDLE);
1387 retproc = PE_FindExportedFunction( wm, function, snoop );
1388 if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
1391 retproc = ELF_FindExportedFunction( wm, function);
1392 if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
1395 ERR(module,"wine_modref type %d not handled.\n",wm->type);
1396 SetLastError(ERROR_INVALID_HANDLE);
1402 /***********************************************************************
1403 * RtlImageNtHeaders (NTDLL)
1405 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1408 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1409 * but we could get HMODULE16 or the like (think builtin modules)
1412 WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
1413 if (!wm || (wm->type != MODULE32_PE)) return (PIMAGE_NT_HEADERS)0;
1414 return PE_HEADER(wm->module);
1418 /***************************************************************************
1419 * HasGPHandler (KERNEL.338)
1423 typedef struct _GPHANDLERDEF
1432 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1437 GPHANDLERDEF *gpHandler;
1439 if ( (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1440 && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1441 && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1442 && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1443 && (gpHandler = PTR_SEG_TO_LIN( gpPtr )) != NULL )
1445 while (gpHandler->selector)
1447 if ( SELECTOROF(address) == gpHandler->selector
1448 && OFFSETOF(address) >= gpHandler->rangeStart
1449 && OFFSETOF(address) < gpHandler->rangeEnd )
1450 return PTR_SEG_OFF_TO_SEGPTR( gpHandler->selector,
1451 gpHandler->handler );