ntdll: Implement RtlGetSearchPath().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-10-01 09:33:52 +02:00
parent 444933ae04
commit 5f938bb51b
4 changed files with 189 additions and 4 deletions

View File

@ -22,12 +22,15 @@
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include "wine/test.h"
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "winuser.h"
#include "winerror.h"
#include "winnls.h"
#include "wine/test.h"
#define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
@ -71,6 +74,9 @@ static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
static BOOL (WINAPI *pSetSearchPathMode)(DWORD);
static BOOL (WINAPI *pSetDllDirectoryA)(LPCSTR);
static NTSTATUS (WINAPI *pRtlGetSearchPath)(LPWSTR*);
static void (WINAPI *pRtlReleasePath)(LPWSTR);
static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
@ -2187,14 +2193,15 @@ static void test_GetFullPathNameW(void)
static void init_pointers(void)
{
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
HMODULE mod = GetModuleHandleA("kernel32.dll");
#define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
#define MAKEFUNC(f) (p##f = (void*)GetProcAddress(mod, #f))
MAKEFUNC(GetLongPathNameA);
MAKEFUNC(GetLongPathNameW);
MAKEFUNC(NeedCurrentDirectoryForExePathA);
MAKEFUNC(NeedCurrentDirectoryForExePathW);
MAKEFUNC(SetSearchPathMode);
MAKEFUNC(SetDllDirectoryA);
MAKEFUNC(ActivateActCtx);
MAKEFUNC(CreateActCtxW);
MAKEFUNC(DeactivateActCtx);
@ -2202,6 +2209,9 @@ static void init_pointers(void)
MAKEFUNC(ReleaseActCtx);
MAKEFUNC(CheckNameLegalDOS8Dot3W);
MAKEFUNC(CheckNameLegalDOS8Dot3A);
mod = GetModuleHandleA("ntdll.dll");
MAKEFUNC(RtlGetSearchPath);
MAKEFUNC(RtlReleasePath);
#undef MAKEFUNC
}
@ -2458,6 +2468,87 @@ static void test_SetSearchPathMode(void)
RemoveDirectoryA( dir );
}
static const WCHAR pathW[] = {'P','A','T','H',0};
static void build_search_path( WCHAR *buffer, UINT size, BOOL safe )
{
WCHAR *p;
GetModuleFileNameW( NULL, buffer, size );
if (!(p = wcsrchr( buffer, '\\' ))) return;
*p++ = ';';
GetSystemDirectoryW( p, buffer + size - p );
p = buffer + lstrlenW(buffer);
*p++ = ';';
GetSystemDirectoryW( p, buffer + size - p );
p = buffer + lstrlenW(buffer) - 2; /* remove "32" */
*p++ = ';';
GetWindowsDirectoryW( p, buffer + size - p );
p = buffer + lstrlenW(buffer);
*p++ = ';';
if (!safe)
{
*p++ = '.';
*p++ = ';';
}
GetEnvironmentVariableW( pathW, p, buffer + size - p );
}
static BOOL path_equal( const WCHAR *path1, const WCHAR *path2 )
{
for (;;)
{
while (*path1 && towlower(*path1) == towlower(*path2)) { path1++; path2++; }
if (*path1 && *path1 != '\\' && *path1 != ';') return FALSE;
while (*path1 && (*path1 == '\\' || *path1 == ';')) path1++;
while (*path2 && (*path2 == '\\' || *path2 == ';')) path2++;
if (!*path1 && !*path2) return TRUE;
}
}
static void test_RtlGetSearchPath(void)
{
NTSTATUS ret;
WCHAR *path;
WCHAR buffer[2048], old_path[2048];
if (!pRtlGetSearchPath)
{
win_skip( "RtlGetSearchPath isn't available\n" );
return;
}
GetEnvironmentVariableW( pathW, old_path, ARRAY_SIZE(old_path) );
build_search_path( buffer, ARRAY_SIZE(buffer), FALSE );
path = (WCHAR *)0xdeadbeef;
ret = pRtlGetSearchPath( &path );
ok( !ret, "RtlGetSearchPath failed %x\n", ret );
ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
pRtlReleasePath( path );
SetEnvironmentVariableA( "PATH", "foo" );
build_search_path( buffer, ARRAY_SIZE(buffer), FALSE );
path = (WCHAR *)0xdeadbeef;
ret = pRtlGetSearchPath( &path );
ok( !ret, "RtlGetSearchPath failed %x\n", ret );
ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
pRtlReleasePath( path );
if (pSetDllDirectoryA)
{
ok( pSetDllDirectoryA( "c:\\" ), "SetDllDirectoryA failed\n" );
build_search_path( buffer, ARRAY_SIZE(buffer), FALSE );
path = (WCHAR *)0xdeadbeef;
ret = pRtlGetSearchPath( &path );
ok( !ret, "RtlGetSearchPath failed %x\n", ret );
ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
pRtlReleasePath( path );
pSetDllDirectoryA( NULL );
}
SetEnvironmentVariableW( pathW, old_path );
}
START_TEST(path)
{
CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
@ -2492,4 +2583,5 @@ START_TEST(path)
test_GetFullPathNameW();
test_CheckNameLegalDOS8Dot3();
test_SetSearchPathMode();
test_RtlGetSearchPath();
}

View File

@ -68,6 +68,12 @@ typedef void (CALLBACK *LDRENUMPROC)(LDR_MODULE *, void *, BOOLEAN *);
const WCHAR system_dir[] = {'C',':','\\','w','i','n','d','o','w','s','\\',
's','y','s','t','e','m','3','2','\\',0};
/* system search path */
static const WCHAR system_path[] =
{'C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m','3','2',';',
'C',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m',';',
'C',':','\\','w','i','n','d','o','w','s',';',0};
static BOOL imports_fixup_done = FALSE; /* set once the imports have been fixed up, before attaching them */
static BOOL process_detaching = FALSE; /* set on process detach to avoid deadlocks with thread detach */
static int free_lib_count; /* recursion depth of LdrUnloadDll calls */
@ -2062,6 +2068,70 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info )
}
/******************************************************************
* get_dll_load_path
*/
static NTSTATUS get_dll_load_path( LPCWSTR module, int safe_mode, WCHAR **path )
{
static const WCHAR pathW[] = {'P','A','T','H',0};
static const WCHAR dotW[] = {'.',';',0};
const WCHAR *mod_end = module;
UNICODE_STRING name, value;
WCHAR *p, *ret;
int len = ARRAY_SIZE(system_path), path_len = 0;
if (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 && module[0] && module[1] == ':') mod_end += 2;
len += (mod_end - module) + 1;
}
RtlInitUnicodeString( &name, pathW );
value.Length = 0;
value.MaximumLength = 0;
value.Buffer = NULL;
if (RtlQueryEnvironmentVariable_U( NULL, &name, &value ) == STATUS_BUFFER_TOO_SMALL)
path_len = value.Length;
len += 2; /* current directory */
if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, path_len + len * sizeof(WCHAR) )))
return STATUS_NO_MEMORY;
memcpy( ret, module, (mod_end - module) * sizeof(WCHAR) );
p = ret + (mod_end - module);
if (p > ret) *p++ = ';';
*p = 0;
if (!safe_mode) strcatW( ret, dotW );
strcatW( ret, system_path );
if (safe_mode) strcatW( ret, dotW );
value.Buffer = ret + strlenW(ret);
value.MaximumLength = path_len;
while (RtlQueryEnvironmentVariable_U( NULL, &name, &value ) == STATUS_BUFFER_TOO_SMALL)
{
WCHAR *new_ptr;
/* grow the buffer and retry */
path_len = value.Length;
if (!(new_ptr = RtlReAllocateHeap( GetProcessHeap(), 0, ret, path_len + len * sizeof(WCHAR) )))
{
RtlFreeHeap( GetProcessHeap(), 0, ret );
return STATUS_NO_MEMORY;
}
value.Buffer = new_ptr + (value.Buffer - ret);
value.MaximumLength = path_len;
ret = new_ptr;
}
value.Buffer[value.Length / sizeof(WCHAR)] = 0;
*path = ret;
return STATUS_SUCCESS;
}
/***********************************************************************
* open_dll_file
*
@ -3789,6 +3859,25 @@ NTSTATUS WINAPI RtlSetSearchPathMode( ULONG flags )
}
/******************************************************************
* RtlGetSearchPath (NTDLL.@)
*/
NTSTATUS WINAPI RtlGetSearchPath( PWSTR *path )
{
WCHAR *module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
return get_dll_load_path( module, path_safe_mode, path );
}
/******************************************************************
* RtlReleasePath (NTDLL.@)
*/
void WINAPI RtlReleasePath( PWSTR path )
{
RtlFreeHeap( GetProcessHeap(), 0, path );
}
/***********************************************************************
* NtLoadDriver (NTDLL.@)
* ZwLoadDriver (NTDLL.@)

View File

@ -700,6 +700,7 @@
@ stdcall RtlGetProductInfo(long long long long ptr)
@ stdcall RtlGetProcessHeaps(long ptr)
@ stdcall RtlGetSaclSecurityDescriptor(ptr ptr ptr ptr)
@ stdcall RtlGetSearchPath(ptr)
# @ stub RtlGetSecurityDescriptorRMControl
# @ stub RtlGetSetBootStatusData
@ stdcall -ret64 RtlGetSystemTimePrecise()
@ -879,6 +880,7 @@
@ stdcall RtlRegisterWait(ptr ptr ptr ptr long long)
@ stdcall RtlReleaseActivationContext(ptr)
@ stub RtlReleaseMemoryStream
@ stdcall RtlReleasePath(ptr)
@ stdcall RtlReleasePebLock()
@ stdcall RtlReleaseRelativeName(ptr)
@ stdcall RtlReleaseResource(ptr)

View File

@ -2728,9 +2728,10 @@ NTSYSAPI ULONG WINAPI RtlGetNtGlobalFlags(void);
NTSYSAPI BOOLEAN WINAPI RtlGetNtProductType(LPDWORD);
NTSYSAPI NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID *,PBOOLEAN);
NTSYSAPI ULONG WINAPI RtlGetProcessHeaps(ULONG,HANDLE*);
NTSYSAPI DWORD WINAPI RtlGetThreadErrorMode(void);
NTSYSAPI NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,PBOOLEAN,PACL *,PBOOLEAN);
NTSYSAPI NTSTATUS WINAPI RtlGetSearchPath(PWSTR*);
NTSYSAPI LONGLONG WINAPI RtlGetSystemTimePrecise(void);
NTSYSAPI DWORD WINAPI RtlGetThreadErrorMode(void);
NTSYSAPI NTSTATUS WINAPI RtlGetVersion(RTL_OSVERSIONINFOEXW*);
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING,GUID*);
NTSYSAPI PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid(PSID);
@ -2812,6 +2813,7 @@ NTSYSAPI ULONG WINAPI RtlRandom(PULONG);
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE,ULONG,PVOID,SIZE_T);
NTSYSAPI NTSTATUS WINAPI RtlRegisterWait(PHANDLE,HANDLE,RTL_WAITORTIMERCALLBACKFUNC,PVOID,ULONG,ULONG);
NTSYSAPI void WINAPI RtlReleaseActivationContext(HANDLE);
NTSYSAPI void WINAPI RtlReleasePath(PWSTR);
NTSYSAPI void WINAPI RtlReleasePebLock(void);
NTSYSAPI void WINAPI RtlReleaseResource(LPRTL_RWLOCK);
NTSYSAPI void WINAPI RtlReleaseSRWLockExclusive(RTL_SRWLOCK*);