Reimplemented SearchPathW using ntdll functions.
This commit is contained in:
parent
df23d95476
commit
af16aac743
|
@ -62,6 +62,8 @@ extern VOID SYSLEVEL_CheckNotLevel( INT level );
|
||||||
extern DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context );
|
extern DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context );
|
||||||
extern void INSTR_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum );
|
extern void INSTR_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum );
|
||||||
|
|
||||||
|
extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module );
|
||||||
|
|
||||||
extern BOOL NLS_IsUnicodeOnlyLcid(LCID);
|
extern BOOL NLS_IsUnicodeOnlyLcid(LCID);
|
||||||
|
|
||||||
extern WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags );
|
extern WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags );
|
||||||
|
|
|
@ -507,42 +507,35 @@ DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size
|
||||||
*/
|
*/
|
||||||
static const WCHAR *get_dll_system_path(void)
|
static const WCHAR *get_dll_system_path(void)
|
||||||
{
|
{
|
||||||
static WCHAR *path;
|
static WCHAR *cached_path;
|
||||||
|
|
||||||
if (!path)
|
if (!cached_path)
|
||||||
{
|
{
|
||||||
WCHAR *p, *exe_name;
|
WCHAR *p, *path;
|
||||||
int len = 3;
|
int len = 3;
|
||||||
|
|
||||||
exe_name = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
|
|
||||||
if (!(p = strrchrW( exe_name, '\\' ))) p = exe_name;
|
|
||||||
/* include trailing backslash only on drive root */
|
|
||||||
if (p == exe_name + 2 && exe_name[1] == ':') p++;
|
|
||||||
len += p - exe_name;
|
|
||||||
len += GetSystemDirectoryW( NULL, 0 );
|
len += GetSystemDirectoryW( NULL, 0 );
|
||||||
len += GetWindowsDirectoryW( NULL, 0 );
|
len += GetWindowsDirectoryW( NULL, 0 );
|
||||||
path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
p = path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||||
memcpy( path, exe_name, (p - exe_name) * sizeof(WCHAR) );
|
|
||||||
p = path + (p - exe_name);
|
|
||||||
*p++ = ';';
|
|
||||||
*p++ = '.';
|
*p++ = '.';
|
||||||
*p++ = ';';
|
*p++ = ';';
|
||||||
GetSystemDirectoryW( p, path + len - p);
|
GetSystemDirectoryW( p, path + len - p);
|
||||||
p += strlenW(p);
|
p += strlenW(p);
|
||||||
*p++ = ';';
|
*p++ = ';';
|
||||||
GetWindowsDirectoryW( p, path + len - p);
|
GetWindowsDirectoryW( p, path + len - p);
|
||||||
|
cached_path = path;
|
||||||
}
|
}
|
||||||
return path;
|
return cached_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* get_dll_load_path
|
* MODULE_get_dll_load_path
|
||||||
*
|
*
|
||||||
* Compute the load path to use for a given dll.
|
* Compute the load path to use for a given dll.
|
||||||
* Returned pointer must be freed by caller.
|
* Returned pointer must be freed by caller.
|
||||||
*/
|
*/
|
||||||
static WCHAR *get_dll_load_path( LPCWSTR module )
|
WCHAR *MODULE_get_dll_load_path( LPCWSTR module )
|
||||||
{
|
{
|
||||||
static const WCHAR pathW[] = {'P','A','T','H',0};
|
static const WCHAR pathW[] = {'P','A','T','H',0};
|
||||||
|
|
||||||
|
@ -554,6 +547,7 @@ static WCHAR *get_dll_load_path( LPCWSTR module )
|
||||||
|
|
||||||
/* adjust length for module name */
|
/* adjust length for module name */
|
||||||
|
|
||||||
|
if (!module) module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
|
||||||
if (module)
|
if (module)
|
||||||
{
|
{
|
||||||
mod_end = module;
|
mod_end = module;
|
||||||
|
@ -561,8 +555,7 @@ static WCHAR *get_dll_load_path( LPCWSTR module )
|
||||||
if ((p = strrchrW( mod_end, '/' ))) mod_end = p;
|
if ((p = strrchrW( mod_end, '/' ))) mod_end = p;
|
||||||
if (mod_end == module + 2 && module[1] == ':') mod_end++;
|
if (mod_end == module + 2 && module[1] == ':') mod_end++;
|
||||||
if (mod_end == module && module[0] && module[1] == ':') mod_end += 2;
|
if (mod_end == module && module[0] && module[1] == ':') mod_end += 2;
|
||||||
len += (mod_end - module);
|
len += (mod_end - module) + 1;
|
||||||
system_path = strchrW( system_path, ';' );
|
|
||||||
}
|
}
|
||||||
len += strlenW( system_path ) + 2;
|
len += strlenW( system_path ) + 2;
|
||||||
|
|
||||||
|
@ -581,6 +574,7 @@ static WCHAR *get_dll_load_path( LPCWSTR module )
|
||||||
{
|
{
|
||||||
memcpy( ret, module, (mod_end - module) * sizeof(WCHAR) );
|
memcpy( ret, module, (mod_end - module) * sizeof(WCHAR) );
|
||||||
p += (mod_end - module);
|
p += (mod_end - module);
|
||||||
|
*p++ = ';';
|
||||||
}
|
}
|
||||||
strcpyW( p, system_path );
|
strcpyW( p, system_path );
|
||||||
p += strlenW(p);
|
p += strlenW(p);
|
||||||
|
@ -608,18 +602,6 @@ static WCHAR *get_dll_load_path( LPCWSTR module )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* MODULE_InitLoadPath
|
|
||||||
*
|
|
||||||
* Create the initial dll load path.
|
|
||||||
*/
|
|
||||||
void MODULE_InitLoadPath(void)
|
|
||||||
{
|
|
||||||
WCHAR *path = get_dll_load_path( NULL );
|
|
||||||
RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath, path );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* load_library_as_datafile
|
* load_library_as_datafile
|
||||||
*/
|
*/
|
||||||
|
@ -682,7 +664,7 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags )
|
||||||
/* Fallback to normal behaviour */
|
/* Fallback to normal behaviour */
|
||||||
}
|
}
|
||||||
|
|
||||||
load_path = get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL );
|
load_path = MODULE_get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL );
|
||||||
nts = LdrLoadDll( load_path, flags, libname, &hModule );
|
nts = LdrLoadDll( load_path, flags, libname, &hModule );
|
||||||
HeapFree( GetProcessHeap(), 0, load_path );
|
HeapFree( GetProcessHeap(), 0, load_path );
|
||||||
if (nts != STATUS_SUCCESS)
|
if (nts != STATUS_SUCCESS)
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
|
|
||||||
|
#include "kernel_private.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
@ -422,3 +423,156 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen
|
||||||
RtlFreeUnicodeString(&longpathW);
|
RtlFreeUnicodeString(&longpathW);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* contains_pathW
|
||||||
|
*
|
||||||
|
* Check if the file name contains a path; helper for SearchPathW.
|
||||||
|
* A relative path is not considered a path unless it starts with ./ or ../
|
||||||
|
*/
|
||||||
|
inline static BOOL contains_pathW (LPCWSTR name)
|
||||||
|
{
|
||||||
|
if (RtlDetermineDosPathNameType_U( name ) != RELATIVE_PATH) return TRUE;
|
||||||
|
if (name[0] != '.') return FALSE;
|
||||||
|
if (name[1] == '/' || name[1] == '\\') return TRUE;
|
||||||
|
return (name[1] == '.' && (name[2] == '/' || name[2] == '\\'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SearchPathW [KERNEL32.@]
|
||||||
|
*
|
||||||
|
* Searches for a specified file in the search path.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* path [I] Path to search
|
||||||
|
* name [I] Filename to search for.
|
||||||
|
* ext [I] File extension to append to file name. The first
|
||||||
|
* character must be a period. This parameter is
|
||||||
|
* specified only if the filename given does not
|
||||||
|
* contain an extension.
|
||||||
|
* buflen [I] size of buffer, in characters
|
||||||
|
* buffer [O] buffer for found filename
|
||||||
|
* lastpart [O] address of pointer to last used character in
|
||||||
|
* buffer (the final '\')
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: length of string copied into buffer, not including
|
||||||
|
* terminating null character. If the filename found is
|
||||||
|
* longer than the length of the buffer, the length of the
|
||||||
|
* filename is returned.
|
||||||
|
* Failure: Zero
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND)
|
||||||
|
* (tested on NT 4.0)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
|
||||||
|
LPWSTR buffer, LPWSTR *lastpart )
|
||||||
|
{
|
||||||
|
DWORD ret = 0;
|
||||||
|
|
||||||
|
/* If the name contains an explicit path, ignore the path */
|
||||||
|
|
||||||
|
if (contains_pathW(name))
|
||||||
|
{
|
||||||
|
/* try first without extension */
|
||||||
|
if (RtlDoesFileExists_U( name ))
|
||||||
|
return GetFullPathNameW( name, buflen, buffer, lastpart );
|
||||||
|
|
||||||
|
if (ext)
|
||||||
|
{
|
||||||
|
LPCWSTR p = strrchrW( name, '.' );
|
||||||
|
if (p && !strchrW( p, '/' ) && !strchrW( p, '\\' ))
|
||||||
|
ext = NULL; /* Ignore the specified extension */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer for the file name and extension */
|
||||||
|
if (ext)
|
||||||
|
{
|
||||||
|
LPWSTR tmp;
|
||||||
|
DWORD len = strlenW(name) + strlenW(ext);
|
||||||
|
|
||||||
|
if (!(tmp = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_OUTOFMEMORY );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strcpyW( tmp, name );
|
||||||
|
strcatW( tmp, ext );
|
||||||
|
if (RtlDoesFileExists_U( tmp ))
|
||||||
|
ret = GetFullPathNameW( tmp, buflen, buffer, lastpart );
|
||||||
|
HeapFree( GetProcessHeap(), 0, tmp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (path && path[0]) /* search in the specified path */
|
||||||
|
{
|
||||||
|
ret = RtlDosSearchPath_U( path, name, ext, buflen * sizeof(WCHAR),
|
||||||
|
buffer, lastpart ) / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else /* search in the default path */
|
||||||
|
{
|
||||||
|
WCHAR *dll_path = MODULE_get_dll_load_path( NULL );
|
||||||
|
|
||||||
|
if (dll_path)
|
||||||
|
{
|
||||||
|
ret = RtlDosSearchPath_U( dll_path, name, ext, buflen * sizeof(WCHAR),
|
||||||
|
buffer, lastpart ) / sizeof(WCHAR);
|
||||||
|
HeapFree( GetProcessHeap(), 0, dll_path );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_OUTOFMEMORY );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) SetLastError( ERROR_FILE_NOT_FOUND );
|
||||||
|
else TRACE( "found %s\n", debugstr_w(buffer) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SearchPathA (KERNEL32.@)
|
||||||
|
*/
|
||||||
|
DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
|
||||||
|
DWORD buflen, LPSTR buffer, LPSTR *lastpart )
|
||||||
|
{
|
||||||
|
UNICODE_STRING pathW, nameW, extW;
|
||||||
|
WCHAR bufferW[MAX_PATH];
|
||||||
|
DWORD ret, retW;
|
||||||
|
|
||||||
|
if (path) RtlCreateUnicodeStringFromAsciiz(&pathW, path);
|
||||||
|
else pathW.Buffer = NULL;
|
||||||
|
if (name) RtlCreateUnicodeStringFromAsciiz(&nameW, name);
|
||||||
|
else nameW.Buffer = NULL;
|
||||||
|
if (ext) RtlCreateUnicodeStringFromAsciiz(&extW, ext);
|
||||||
|
else extW.Buffer = NULL;
|
||||||
|
|
||||||
|
retW = SearchPathW(pathW.Buffer, nameW.Buffer, extW.Buffer, MAX_PATH, bufferW, NULL);
|
||||||
|
|
||||||
|
if (!retW)
|
||||||
|
ret = 0;
|
||||||
|
else if (retW > MAX_PATH)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (buflen >= ret)
|
||||||
|
{
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, buflen, NULL, NULL);
|
||||||
|
ret--; /* length without 0 */
|
||||||
|
if (lastpart) *lastpart = strrchr(buffer, '\\') + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlFreeUnicodeString(&pathW);
|
||||||
|
RtlFreeUnicodeString(&nameW);
|
||||||
|
RtlFreeUnicodeString(&extW);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -84,7 +84,6 @@ static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0};
|
||||||
|
|
||||||
extern void SHELL_LoadRegistry(void);
|
extern void SHELL_LoadRegistry(void);
|
||||||
extern void VERSION_Init( const WCHAR *appname );
|
extern void VERSION_Init( const WCHAR *appname );
|
||||||
extern void MODULE_InitLoadPath(void);
|
|
||||||
extern void LOCALE_Init(void);
|
extern void LOCALE_Init(void);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -835,7 +834,8 @@ void __wine_kernel_init(void)
|
||||||
TRACE( "starting process name=%s file=%p argv[0]=%s\n",
|
TRACE( "starting process name=%s file=%p argv[0]=%s\n",
|
||||||
debugstr_w(main_exe_name), main_exe_file, debugstr_a(__wine_main_argv[0]) );
|
debugstr_w(main_exe_name), main_exe_file, debugstr_a(__wine_main_argv[0]) );
|
||||||
|
|
||||||
MODULE_InitLoadPath();
|
RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath,
|
||||||
|
MODULE_get_dll_load_path(NULL) );
|
||||||
VERSION_Init( main_exe_name );
|
VERSION_Init( main_exe_name );
|
||||||
|
|
||||||
if (!main_exe_file) /* no file handle -> Winelib app */
|
if (!main_exe_file) /* no file handle -> Winelib app */
|
||||||
|
|
|
@ -54,15 +54,6 @@ WINE_DECLARE_DEBUG_CHANNEL(file);
|
||||||
static DOS_FULL_NAME DIR_Windows;
|
static DOS_FULL_NAME DIR_Windows;
|
||||||
static DOS_FULL_NAME DIR_System;
|
static DOS_FULL_NAME DIR_System;
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_contains_pathW
|
|
||||||
*/
|
|
||||||
inline static int FILE_contains_pathW (LPCWSTR name)
|
|
||||||
{
|
|
||||||
return ((*name && (name[1] == ':')) ||
|
|
||||||
strchrW (name, '/') || strchrW (name, '\\'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* DIR_GetPath
|
* DIR_GetPath
|
||||||
*
|
*
|
||||||
|
@ -613,321 +604,3 @@ BOOL WINAPI RemoveDirectoryA( LPCSTR path )
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* DIR_TryPath
|
|
||||||
*
|
|
||||||
* Helper function for DIR_SearchPath.
|
|
||||||
*/
|
|
||||||
static BOOL DIR_TryPath( const DOS_FULL_NAME *dir, LPCWSTR name,
|
|
||||||
DOS_FULL_NAME *full_name )
|
|
||||||
{
|
|
||||||
LPSTR p_l = full_name->long_name + strlen(dir->long_name) + 1;
|
|
||||||
LPWSTR p_s = full_name->short_name + strlenW(dir->short_name) + 1;
|
|
||||||
|
|
||||||
if ((p_s >= full_name->short_name + sizeof(full_name->short_name)/sizeof(full_name->short_name[0]) - 14) ||
|
|
||||||
(p_l >= full_name->long_name + sizeof(full_name->long_name) - 1))
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!DOSFS_FindUnixName( dir, name, p_l,
|
|
||||||
sizeof(full_name->long_name) - (p_l - full_name->long_name), p_s ))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
full_name->drive = dir->drive;
|
|
||||||
strcpy( full_name->long_name, dir->long_name );
|
|
||||||
p_l[-1] = '/';
|
|
||||||
strcpyW( full_name->short_name, dir->short_name );
|
|
||||||
p_s[-1] = '\\';
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL DIR_SearchSemicolonedPaths(LPCWSTR name, DOS_FULL_NAME *full_name, LPWSTR pathlist)
|
|
||||||
{
|
|
||||||
LPWSTR next, buffer = NULL;
|
|
||||||
INT len = strlenW(name), newlen, currlen = 0;
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
|
|
||||||
next = pathlist;
|
|
||||||
while (!ret && next)
|
|
||||||
{
|
|
||||||
static const WCHAR bkslashW[] = {'\\',0};
|
|
||||||
LPWSTR cur = next;
|
|
||||||
while (*cur == ';') cur++;
|
|
||||||
if (!*cur) break;
|
|
||||||
next = strchrW( cur, ';' );
|
|
||||||
if (next) *next++ = '\0';
|
|
||||||
newlen = strlenW(cur) + len + 2;
|
|
||||||
|
|
||||||
if (newlen > currlen)
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, newlen * sizeof(WCHAR));
|
|
||||||
else
|
|
||||||
buffer = HeapAlloc( GetProcessHeap(), 0, newlen * sizeof(WCHAR));
|
|
||||||
|
|
||||||
if(!buffer)
|
|
||||||
goto done;
|
|
||||||
currlen = newlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpyW( buffer, cur );
|
|
||||||
strcatW( buffer, bkslashW );
|
|
||||||
strcatW( buffer, name );
|
|
||||||
ret = DOSFS_GetFullName( buffer, TRUE, full_name );
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
HeapFree( GetProcessHeap(), 0, buffer );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* DIR_TryEnvironmentPath
|
|
||||||
*
|
|
||||||
* Helper function for DIR_SearchPath.
|
|
||||||
* Search in the specified path, or in $PATH if NULL.
|
|
||||||
*/
|
|
||||||
static BOOL DIR_TryEnvironmentPath( LPCWSTR name, DOS_FULL_NAME *full_name, LPCWSTR envpath )
|
|
||||||
{
|
|
||||||
LPWSTR path;
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
DWORD size;
|
|
||||||
static const WCHAR pathW[] = {'P','A','T','H',0};
|
|
||||||
|
|
||||||
size = envpath ? strlenW(envpath)+1 : GetEnvironmentVariableW( pathW, NULL, 0 );
|
|
||||||
if (!size) return FALSE;
|
|
||||||
if (!(path = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE;
|
|
||||||
if (envpath) strcpyW( path, envpath );
|
|
||||||
else if (!GetEnvironmentVariableW( pathW, path, size )) goto done;
|
|
||||||
|
|
||||||
ret = DIR_SearchSemicolonedPaths(name, full_name, path);
|
|
||||||
|
|
||||||
done:
|
|
||||||
HeapFree( GetProcessHeap(), 0, path );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* DIR_TryModulePath
|
|
||||||
*
|
|
||||||
* Helper function for DIR_SearchPath.
|
|
||||||
*/
|
|
||||||
static BOOL DIR_TryModulePath( LPCWSTR name, DOS_FULL_NAME *full_name, BOOL win32 )
|
|
||||||
{
|
|
||||||
WCHAR bufferW[MAX_PATH];
|
|
||||||
LPWSTR p;
|
|
||||||
|
|
||||||
if (!win32)
|
|
||||||
{
|
|
||||||
char buffer[OFS_MAXPATHNAME];
|
|
||||||
if (!GetCurrentTask()) return FALSE;
|
|
||||||
if (!GetModuleFileName16( GetCurrentTask(), buffer, sizeof(buffer) ))
|
|
||||||
return FALSE;
|
|
||||||
MultiByteToWideChar(CP_ACP, 0, buffer, -1, bufferW, MAX_PATH);
|
|
||||||
} else {
|
|
||||||
if (!GetModuleFileNameW( 0, bufferW, MAX_PATH ) )
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!(p = strrchrW( bufferW, '\\' ))) return FALSE;
|
|
||||||
if (MAX_PATH - (++p - bufferW) <= strlenW(name)) return FALSE;
|
|
||||||
strcpyW( p, name );
|
|
||||||
return DOSFS_GetFullName( bufferW, TRUE, full_name );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* DIR_SearchPath
|
|
||||||
*
|
|
||||||
* Implementation of SearchPathA. 'win32' specifies whether the search
|
|
||||||
* order is Win16 (module path last) or Win32 (module path first).
|
|
||||||
*
|
|
||||||
* FIXME: should return long path names.
|
|
||||||
*/
|
|
||||||
DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
|
|
||||||
DOS_FULL_NAME *full_name, BOOL win32 )
|
|
||||||
{
|
|
||||||
LPCWSTR p;
|
|
||||||
LPWSTR tmp = NULL;
|
|
||||||
BOOL ret = TRUE;
|
|
||||||
|
|
||||||
/* First check the supplied parameters */
|
|
||||||
|
|
||||||
p = strrchrW( name, '.' );
|
|
||||||
if (p && !strchrW( p, '/' ) && !strchrW( p, '\\' ))
|
|
||||||
ext = NULL; /* Ignore the specified extension */
|
|
||||||
if (FILE_contains_pathW (name))
|
|
||||||
path = NULL; /* Ignore path if name already contains a path */
|
|
||||||
if (path && !*path) path = NULL; /* Ignore empty path */
|
|
||||||
|
|
||||||
/* Allocate a buffer for the file name and extension */
|
|
||||||
|
|
||||||
if (ext)
|
|
||||||
{
|
|
||||||
DWORD len = strlenW(name) + strlenW(ext);
|
|
||||||
if (!(tmp = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_OUTOFMEMORY );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
strcpyW( tmp, name );
|
|
||||||
strcatW( tmp, ext );
|
|
||||||
name = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the name contains an explicit path, everything's easy */
|
|
||||||
|
|
||||||
if (FILE_contains_pathW(name))
|
|
||||||
{
|
|
||||||
ret = DOSFS_GetFullName( name, TRUE, full_name );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search in the specified path */
|
|
||||||
|
|
||||||
if (path)
|
|
||||||
{
|
|
||||||
ret = DIR_TryEnvironmentPath( name, full_name, path );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try the path of the current executable (for Win32 search order) */
|
|
||||||
|
|
||||||
if (win32 && DIR_TryModulePath( name, full_name, win32 )) goto done;
|
|
||||||
|
|
||||||
/* Try the current directory */
|
|
||||||
|
|
||||||
if (DOSFS_GetFullName( name, TRUE, full_name )) goto done;
|
|
||||||
|
|
||||||
/* Try the Windows system directory */
|
|
||||||
|
|
||||||
if (DIR_TryPath( &DIR_System, name, full_name ))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Try the Windows directory */
|
|
||||||
|
|
||||||
if (DIR_TryPath( &DIR_Windows, name, full_name ))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Try the path of the current executable (for Win16 search order) */
|
|
||||||
|
|
||||||
if (!win32 && DIR_TryModulePath( name, full_name, win32 )) goto done;
|
|
||||||
|
|
||||||
/* Try all directories in path */
|
|
||||||
|
|
||||||
ret = DIR_TryEnvironmentPath( name, full_name, NULL );
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* SearchPathW [KERNEL32.@]
|
|
||||||
*
|
|
||||||
* Searches for a specified file in the search path.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* path [I] Path to search
|
|
||||||
* name [I] Filename to search for.
|
|
||||||
* ext [I] File extension to append to file name. The first
|
|
||||||
* character must be a period. This parameter is
|
|
||||||
* specified only if the filename given does not
|
|
||||||
* contain an extension.
|
|
||||||
* buflen [I] size of buffer, in characters
|
|
||||||
* buffer [O] buffer for found filename
|
|
||||||
* lastpart [O] address of pointer to last used character in
|
|
||||||
* buffer (the final '\')
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: length of string copied into buffer, not including
|
|
||||||
* terminating null character. If the filename found is
|
|
||||||
* longer than the length of the buffer, the length of the
|
|
||||||
* filename is returned.
|
|
||||||
* Failure: Zero
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND)
|
|
||||||
* (tested on NT 4.0)
|
|
||||||
*/
|
|
||||||
DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
|
|
||||||
LPWSTR buffer, LPWSTR *lastpart )
|
|
||||||
{
|
|
||||||
LPSTR res;
|
|
||||||
DOS_FULL_NAME full_name;
|
|
||||||
|
|
||||||
if (!DIR_SearchPath( path, name, ext, &full_name, TRUE ))
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("found %s %s\n", full_name.long_name, debugstr_w(full_name.short_name));
|
|
||||||
TRACE("drive %c: root %s\n", 'A' + full_name.drive, DRIVE_GetRoot(full_name.drive));
|
|
||||||
|
|
||||||
lstrcpynW( buffer, full_name.short_name, buflen );
|
|
||||||
res = full_name.long_name +
|
|
||||||
strlen(DRIVE_GetRoot( full_name.drive ));
|
|
||||||
while (*res == '/') res++;
|
|
||||||
if (buflen)
|
|
||||||
{
|
|
||||||
LPWSTR p;
|
|
||||||
if (buflen > 3)
|
|
||||||
{
|
|
||||||
MultiByteToWideChar(CP_UNIXCP, 0, res, -1, buffer + 3, buflen - 3);
|
|
||||||
buffer[buflen - 1] = 0;
|
|
||||||
}
|
|
||||||
for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
|
|
||||||
if (lastpart) *lastpart = strrchrW( buffer, '\\' ) + 1;
|
|
||||||
}
|
|
||||||
TRACE("Returning %s\n", debugstr_w(buffer) );
|
|
||||||
return strlenW(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* SearchPathA (KERNEL32.@)
|
|
||||||
*/
|
|
||||||
DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
|
|
||||||
DWORD buflen, LPSTR buffer, LPSTR *lastpart )
|
|
||||||
{
|
|
||||||
UNICODE_STRING pathW, nameW, extW;
|
|
||||||
WCHAR bufferW[MAX_PATH];
|
|
||||||
DWORD ret, retW;
|
|
||||||
|
|
||||||
if (path) RtlCreateUnicodeStringFromAsciiz(&pathW, path);
|
|
||||||
else pathW.Buffer = NULL;
|
|
||||||
if (name) RtlCreateUnicodeStringFromAsciiz(&nameW, name);
|
|
||||||
else nameW.Buffer = NULL;
|
|
||||||
if (ext) RtlCreateUnicodeStringFromAsciiz(&extW, ext);
|
|
||||||
else extW.Buffer = NULL;
|
|
||||||
|
|
||||||
retW = SearchPathW(pathW.Buffer, nameW.Buffer, extW.Buffer, MAX_PATH, bufferW, NULL);
|
|
||||||
|
|
||||||
if (!retW)
|
|
||||||
ret = 0;
|
|
||||||
else if (retW > MAX_PATH)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
|
|
||||||
if (buflen >= ret)
|
|
||||||
{
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, buflen, NULL, NULL);
|
|
||||||
ret--; /* length without 0 */
|
|
||||||
if (lastpart) *lastpart = strrchr(buffer, '\\') + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlFreeUnicodeString(&pathW);
|
|
||||||
RtlFreeUnicodeString(&nameW);
|
|
||||||
RtlFreeUnicodeString(&extW);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
|
@ -46,8 +46,6 @@ extern HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
|
||||||
|
|
||||||
/* files/directory.c */
|
/* files/directory.c */
|
||||||
extern int DIR_Init(void);
|
extern int DIR_Init(void);
|
||||||
extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
|
|
||||||
DOS_FULL_NAME *full_name, BOOL win32 );
|
|
||||||
|
|
||||||
/* files/dos_fs.c */
|
/* files/dos_fs.c */
|
||||||
extern BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
|
extern BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
|
||||||
|
|
Loading…
Reference in New Issue