Commit af16aac7 authored by Alexandre Julliard's avatar Alexandre Julliard

Reimplemented SearchPathW using ntdll functions.

parent df23d954
......@@ -62,6 +62,8 @@ extern VOID SYSLEVEL_CheckNotLevel( INT level );
extern DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context );
extern void INSTR_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum );
extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module );
extern BOOL NLS_IsUnicodeOnlyLcid(LCID);
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 WCHAR *path;
static WCHAR *cached_path;
if (!path)
if (!cached_path)
{
WCHAR *p, *exe_name;
WCHAR *p, *path;
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 += GetWindowsDirectoryW( NULL, 0 );
path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
memcpy( path, exe_name, (p - exe_name) * sizeof(WCHAR) );
p = path + (p - exe_name);
*p++ = ';';
p = path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
*p++ = '.';
*p++ = ';';
GetSystemDirectoryW( p, path + len - p);
p += strlenW(p);
*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.
* 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};
......@@ -554,6 +547,7 @@ static WCHAR *get_dll_load_path( LPCWSTR module )
/* adjust length for module name */
if (!module) module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
if (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 (mod_end == module + 2 && module[1] == ':') mod_end++;
if (mod_end == module && module[0] && module[1] == ':') mod_end += 2;
len += (mod_end - module);
system_path = strchrW( system_path, ';' );
len += (mod_end - module) + 1;
}
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) );
p += (mod_end - module);
*p++ = ';';
}
strcpyW( p, system_path );
p += strlenW(p);
......@@ -609,18 +603,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
*/
static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
......@@ -682,7 +664,7 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags )
/* 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 );
HeapFree( GetProcessHeap(), 0, load_path );
if (nts != STATUS_SUCCESS)
......
......@@ -35,6 +35,7 @@
#include "winreg.h"
#include "winternl.h"
#include "kernel_private.h"
#include "wine/unicode.h"
#include "wine/debug.h"
......@@ -422,3 +423,156 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen
RtlFreeUnicodeString(&longpathW);
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 VERSION_Init( const WCHAR *appname );
extern void MODULE_InitLoadPath(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",
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 );
if (!main_exe_file) /* no file handle -> Winelib app */
......
......@@ -46,8 +46,6 @@ extern HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
/* files/directory.c */
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 */
extern BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment