diff --git a/include/module.h b/include/module.h index 748fbe6fa79..c953a9fce77 100644 --- a/include/module.h +++ b/include/module.h @@ -259,6 +259,7 @@ extern BOOL PE_InitDLL( HMODULE module, DWORD type, LPVOID lpReserved ); extern DWORD PE_fixup_imports(WINE_MODREF *wm); /* loader/loadorder.c */ +extern BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename, UINT size ); extern void MODULE_GetLoadOrder( enum loadorder_type plo[], const char *path, BOOL win32 ); extern void MODULE_AddLoadOrderOption( const char *option ); diff --git a/loader/loadorder.c b/loader/loadorder.c index a08a13411e7..2f1107ac0e8 100644 --- a/loader/loadorder.c +++ b/loader/loadorder.c @@ -417,6 +417,62 @@ static BOOL get_registry_value( HKEY hkey, const char *module, enum loadorder_ty } +/*************************************************************************** + * MODULE_GetBuiltinPath + * + * Get the path of a builtin module when the native file does not exist. + */ +BOOL MODULE_GetBuiltinPath( const char *libname, const char *ext, char *filename, UINT size ) +{ + char *p; + BOOL ret = FALSE; + UINT len = GetSystemDirectoryA( filename, size ); + + if (FILE_contains_path( libname )) + { + char *tmp; + + /* if the library name contains a path and can not be found, + * return an error. + * exception: if the path is the system directory, proceed, + * so that modules which are not PE modules can be loaded. + * If the library name does not contain a path and can not + * be found, assume the system directory is meant */ + + if (strlen(libname) >= size) return FALSE; /* too long */ + if (strchr( libname, '/' )) /* need to convert slashes */ + { + if (!(tmp = HeapAlloc( GetProcessHeap(), 0, strlen(libname)+1 ))) return FALSE; + strcpy( tmp, libname ); + for (p = tmp; *p; p++) if (*p == '/') *p = '\\'; + } + else tmp = (char *)libname; + + if (!FILE_strncasecmp( filename, tmp, len ) && tmp[len] == '\\') + { + strcpy( filename, tmp ); + ret = TRUE; + } + if (tmp != libname) HeapFree( GetProcessHeap(), 0, tmp ); + if (!ret) return FALSE; + } + else + { + if (strlen(libname) >= size - len - 1) return FALSE; + filename[len] = '\\'; + strcpy( filename+len+1, libname ); + } + + /* if the filename doesn't have an extension, append the default */ + if (!(p = strrchr( filename, '.')) || strchr( p, '/' ) || strchr( p, '\\')) + { + if (strlen(filename) + strlen(ext) >= size) return FALSE; + strcat( filename, ext ); + } + return TRUE; +} + + /*************************************************************************** * MODULE_GetLoadOrder (internal) * diff --git a/loader/module.c b/loader/module.c index 19a7a8e9236..637c69373f7 100644 --- a/loader/module.c +++ b/loader/module.c @@ -1194,7 +1194,7 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags ) WINE_MODREF *pwm; int i; enum loadorder_type loadorder[LOADORDER_NTYPES]; - LPSTR filename, p; + LPSTR filename; const char *filetype = ""; DWORD found; BOOL allocated_libdir = FALSE; @@ -1222,28 +1222,7 @@ WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags ) /* build the modules filename */ if (!found) { - if ( ! GetSystemDirectoryA ( filename, MAX_PATH ) ) - goto error; - - /* if the library name contains a path and can not be found, - * return an error. - * exception: if the path is the system directory, proceed, - * so that modules which are not PE modules can be loaded. - * If the library name does not contain a path and can not - * be found, assume the system directory is meant */ - - if ( ! FILE_strncasecmp ( filename, libname, strlen ( filename ) )) - strcpy ( filename, libname ); - else - { - if (FILE_contains_path(libname)) goto error; - strcat ( filename, "\\" ); - strcat ( filename, libname ); - } - - /* if the filename doesn't have an extension, append .DLL */ - if (!(p = strrchr( filename, '.')) || strchr( p, '/' ) || strchr( p, '\\')) - strcat( filename, ".dll" ); + if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH )) goto error; } /* Check for already loaded module */ diff --git a/scheduler/process.c b/scheduler/process.c index 3d351419807..2aacce8d3bd 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -254,19 +254,47 @@ inline static const char *get_basename( const char *name ) } +/*********************************************************************** + * open_builtin_exe_file + * + * Open an exe file for a builtin exe. + */ +static void *open_builtin_exe_file( const char *name, char *error, int error_size, int test_only ) +{ + char exename[MAX_PATH], *p; + const char *basename = get_basename(name); + + if (strlen(basename) >= sizeof(exename)) return NULL; + strcpy( exename, basename ); + for (p = exename; *p; p++) *p = FILE_tolower(*p); + return wine_dll_load_main_exe( exename, error, error_size, test_only ); +} + + /*********************************************************************** * open_exe_file * - * Open an exe file, taking load order into account. + * Open a specific exe file, taking load order into account. * Returns the file handle or 0 for a builtin exe. */ static HANDLE open_exe_file( const char *name ) { enum loadorder_type loadorder[LOADORDER_NTYPES]; + char buffer[MAX_PATH]; HANDLE handle; int i; - SetLastError( ERROR_FILE_NOT_FOUND ); + TRACE("looking for %s\n", debugstr_a(name) ); + + if ((handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE) + { + /* file doesn't exist, check for builtin */ + if (!FILE_contains_path( name )) goto error; + if (!MODULE_GetBuiltinPath( name, "", buffer, sizeof(buffer) )) goto error; + name = buffer; + } + MODULE_GetLoadOrder( loadorder, name, TRUE ); for(i = 0; i < LOADORDER_NTYPES; i++) @@ -276,19 +304,23 @@ static HANDLE open_exe_file( const char *name ) { case LOADORDER_DLL: TRACE( "Trying native exe %s\n", debugstr_a(name) ); - if ((handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE) - return handle; - if (GetLastError() != ERROR_FILE_NOT_FOUND) return INVALID_HANDLE_VALUE; + if (handle != INVALID_HANDLE_VALUE) return handle; break; case LOADORDER_BI: TRACE( "Trying built-in exe %s\n", debugstr_a(name) ); - if (wine_dll_load_main_exe( get_basename(name), NULL, 0, 1 )) return 0; - break; + if (open_builtin_exe_file( name, NULL, 0, 1 )) + { + if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); + return 0; + } default: break; } } + if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); + + error: + SetLastError( ERROR_FILE_NOT_FOUND ); return INVALID_HANDLE_VALUE; } @@ -308,46 +340,48 @@ static BOOL find_exe_file( const char *name, char *buffer, int buflen, HANDLE *h TRACE("looking for %s\n", debugstr_a(name) ); - if (SearchPathA( NULL, name, ".exe", buflen, buffer, NULL )) + if (!SearchPathA( NULL, name, ".exe", buflen, buffer, NULL ) && + !MODULE_GetBuiltinPath( name, ".exe", buffer, buflen )) { - *handle = open_exe_file( buffer ); - return TRUE; - } + /* no builtin found, try native without extension in case it is a Unix app */ - /* no such file in path, try builtin with .exe extension */ - - lstrcpynA( buffer, get_basename(name), buflen ); - if (!strchr( buffer, '.' )) - { - char *p = buffer + strlen(buffer); - lstrcpynA( p, ".exe", buflen - (p - buffer) ); + if (SearchPathA( NULL, name, NULL, buflen, buffer, NULL )) + { + TRACE( "Trying native/Unix binary %s\n", debugstr_a(buffer) ); + if ((*handle = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE) + return TRUE; + } + return FALSE; } MODULE_GetLoadOrder( loadorder, buffer, TRUE ); - for (i = 0; i < LOADORDER_NTYPES; i++) + + for(i = 0; i < LOADORDER_NTYPES; i++) { - if (loadorder[i] == LOADORDER_BI) + if (loadorder[i] == LOADORDER_INVALID) break; + switch(loadorder[i]) { + case LOADORDER_DLL: + TRACE( "Trying native exe %s\n", debugstr_a(buffer) ); + if ((*handle = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE) + return TRUE; + if (GetLastError() != ERROR_FILE_NOT_FOUND) return TRUE; + break; + case LOADORDER_BI: TRACE( "Trying built-in exe %s\n", debugstr_a(buffer) ); - if (wine_dll_load_main_exe( buffer, NULL, 0, 1 )) + if (open_builtin_exe_file( buffer, NULL, 0, 1 )) { *handle = 0; return TRUE; } break; + default: + break; } - if (loadorder[i] == LOADORDER_INVALID) break; - } - - /* no builtin found, try native without extension in case it is a Unix app */ - - if (SearchPathA( NULL, name, NULL, buflen, buffer, NULL )) - { - TRACE( "Trying native/Unix binary %s\n", debugstr_a(buffer) ); - if ((*handle = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE) - return TRUE; } + SetLastError( ERROR_FILE_NOT_FOUND ); return FALSE; } @@ -569,7 +603,7 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win if (!main_exe_file) /* no file handle -> Winelib app */ { TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) ); - if (wine_dll_load_main_exe( get_basename(main_exe_name), error, sizeof(error), 0 )) + if (open_builtin_exe_file( main_exe_name, error, sizeof(error), 0 )) goto found; MESSAGE( "%s: cannot open builtin library for '%s': %s\n", argv0, main_exe_name, error ); ExitProcess(1);