ntdll: Implement RtlGetSearchPath().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
444933ae04
commit
5f938bb51b
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.@)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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*);
|
||||
|
|
Loading…
Reference in New Issue