From 619bd16e7a7486ca72cde1df01791629efb61341 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 3 Oct 2019 14:14:36 +0200 Subject: [PATCH] kernel32: Move dll path functions to ntdll. Signed-off-by: Alexandre Julliard --- dlls/kernel32/kernel32.spec | 6 +- dlls/kernel32/kernel_private.h | 3 - dlls/kernel32/module.c | 400 +------------------------------- dlls/kernel32/process.c | 5 +- dlls/kernel32/tests/path.c | 150 ++++++++++-- dlls/kernelbase/kernelbase.spec | 6 +- dlls/kernelbase/loader.c | 32 +++ dlls/ntdll/loader.c | 264 +++++++++++++++++++-- dlls/ntdll/ntdll.spec | 6 +- include/winternl.h | 4 + 10 files changed, 436 insertions(+), 440 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index f522429b767..eed3e668e59 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -140,7 +140,7 @@ @ stdcall AddAtomW(wstr) @ stdcall AddConsoleAliasA(str str str) @ stdcall AddConsoleAliasW(wstr wstr wstr) -@ stdcall AddDllDirectory(wstr) +@ stdcall -import AddDllDirectory(wstr) # @ stub AddIntegrityLabelToBoundaryDescriptor # @ stub AddLocalAlternateComputerNameA # @ stub AddLocalAlternateComputerNameW @@ -1274,7 +1274,7 @@ @ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr) # @ stub RemoveDirectoryTransactedA # @ stub RemoveDirectoryTransactedW -@ stdcall RemoveDllDirectory(ptr) +@ stdcall -import RemoveDllDirectory(ptr) # @ stub RemoveSecureMemoryCacheCallback # @ stub ReplacePartitionUnit @ stdcall RequestDeviceWakeup(long) @@ -1379,7 +1379,7 @@ @ stub SetDaylightFlag @ stdcall SetDefaultCommConfigA(str ptr long) @ stdcall SetDefaultCommConfigW(wstr ptr long) -@ stdcall SetDefaultDllDirectories(long) +@ stdcall -import SetDefaultDllDirectories(long) @ stdcall SetDllDirectoryA(str) @ stdcall SetDllDirectoryW(wstr) # @ stub SetDynamicTimeZoneInformation diff --git a/dlls/kernel32/kernel_private.h b/dlls/kernel32/kernel_private.h index fdfb7a3e83b..af85bee84df 100644 --- a/dlls/kernel32/kernel_private.h +++ b/dlls/kernel32/kernel_private.h @@ -65,9 +65,6 @@ extern void FILE_SetDosError(void) DECLSPEC_HIDDEN; extern WCHAR *FILE_name_AtoW( LPCSTR name, BOOL alloc ) DECLSPEC_HIDDEN; extern DWORD FILE_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen ) DECLSPEC_HIDDEN; -/* module.c */ -extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module, int safe_mode ) DECLSPEC_HIDDEN; - extern BOOL NLS_IsUnicodeOnlyLcid(LCID) DECLSPEC_HIDDEN; /* environ.c */ diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 131c2f96217..b87770eccfa 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -49,15 +49,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(module); #define NE_FFLAGS_LIBMODULE 0x8000 -struct dll_dir_entry -{ - struct list entry; - WCHAR dir[1]; -}; - -static struct list dll_dir_list = LIST_INIT( dll_dir_list ); /* extra dirs from AddDllDirectory */ -static DWORD default_search_flags; /* default flags set by SetDefaultDllDirectories */ - /* to keep track of LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE file handles */ struct exclusive_datafile { @@ -67,15 +58,6 @@ struct exclusive_datafile }; static struct list exclusive_datafile_list = LIST_INIT( exclusive_datafile_list ); -static CRITICAL_SECTION dlldir_section; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &dlldir_section, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": dlldir_section") } -}; -static CRITICAL_SECTION dlldir_section = { &critsect_debug, -1, 0, 0, 0, 0 }; - /**************************************************************************** * GetDllDirectoryA (KERNEL32.@) */ @@ -163,73 +145,6 @@ BOOL WINAPI SetDllDirectoryW( LPCWSTR dir ) } -/**************************************************************************** - * AddDllDirectory (KERNEL32.@) - */ -DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory( const WCHAR *dir ) -{ - WCHAR path[MAX_PATH]; - DWORD len; - struct dll_dir_entry *ptr; - DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U( dir ); - - if (type != ABSOLUTE_PATH && type != ABSOLUTE_DRIVE_PATH) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return NULL; - } - if (!(len = GetFullPathNameW( dir, MAX_PATH, path, NULL ))) return NULL; - if (GetFileAttributesW( path ) == INVALID_FILE_ATTRIBUTES) return NULL; - - if (!(ptr = HeapAlloc( GetProcessHeap(), 0, offsetof(struct dll_dir_entry, dir[++len] )))) return NULL; - memcpy( ptr->dir, path, len * sizeof(WCHAR) ); - TRACE( "%s\n", debugstr_w( ptr->dir )); - - RtlEnterCriticalSection( &dlldir_section ); - list_add_head( &dll_dir_list, &ptr->entry ); - RtlLeaveCriticalSection( &dlldir_section ); - return ptr; -} - - -/**************************************************************************** - * RemoveDllDirectory (KERNEL32.@) - */ -BOOL WINAPI RemoveDllDirectory( DLL_DIRECTORY_COOKIE cookie ) -{ - struct dll_dir_entry *ptr = cookie; - - TRACE( "%s\n", debugstr_w( ptr->dir )); - - RtlEnterCriticalSection( &dlldir_section ); - list_remove( &ptr->entry ); - HeapFree( GetProcessHeap(), 0, ptr ); - RtlLeaveCriticalSection( &dlldir_section ); - return TRUE; -} - - -/************************************************************************* - * SetDefaultDllDirectories (KERNEL32.@) - */ -BOOL WINAPI SetDefaultDllDirectories( DWORD flags ) -{ - /* LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR doesn't make sense in default dirs */ - const DWORD load_library_search_flags = (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | - LOAD_LIBRARY_SEARCH_USER_DIRS | - LOAD_LIBRARY_SEARCH_SYSTEM32 | - LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - - if (!flags || (flags & ~load_library_search_flags)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - default_search_flags = flags; - return TRUE; -} - - /*********************************************************************** * GetBinaryTypeW [KERNEL32.@] * @@ -368,293 +283,10 @@ BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType ) return GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType); } -/*********************************************************************** - * get_dll_system_path - */ -static const WCHAR *get_dll_system_path(void) -{ - static WCHAR *cached_path; - - if (!cached_path) - { - WCHAR *p, *path; - int len = 1; - - len += 2 * GetSystemDirectoryW( NULL, 0 ); - len += GetWindowsDirectoryW( NULL, 0 ); - p = path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - GetSystemDirectoryW( p, path + len - p); - p += strlenW(p); - /* if system directory ends in "32" add 16-bit version too */ - if (p[-2] == '3' && p[-1] == '2') - { - *p++ = ';'; - GetSystemDirectoryW( p, path + len - p); - p += strlenW(p) - 2; - } - *p++ = ';'; - GetWindowsDirectoryW( p, path + len - p); - cached_path = path; - } - return cached_path; -} - -/*********************************************************************** - * get_dll_safe_mode - */ -static BOOL get_dll_safe_mode(void) -{ - static const WCHAR keyW[] = {'\\','R','e','g','i','s','t','r','y','\\', - 'M','a','c','h','i','n','e','\\', - 'S','y','s','t','e','m','\\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0}; - static const WCHAR valueW[] = {'S','a','f','e','D','l','l','S','e','a','r','c','h','M','o','d','e',0}; - - static int safe_mode = -1; - - if (safe_mode == -1) - { - char buffer[offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[sizeof(DWORD)])]; - KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING nameW; - HANDLE hkey; - DWORD size = sizeof(buffer); - - attr.Length = sizeof(attr); - attr.RootDirectory = 0; - attr.ObjectName = &nameW; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - - safe_mode = 1; - RtlInitUnicodeString( &nameW, keyW ); - if (!NtOpenKey( &hkey, KEY_READ, &attr )) - { - RtlInitUnicodeString( &nameW, valueW ); - if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, buffer, size, &size ) && - info->Type == REG_DWORD && info->DataLength == sizeof(DWORD)) - safe_mode = !!*(DWORD *)info->Data; - NtClose( hkey ); - } - if (!safe_mode) TRACE( "SafeDllSearchMode disabled through the registry\n" ); - } - return safe_mode; -} - -/****************************************************************** - * get_module_path_end - * - * Returns the end of the directory component of the module path. - */ -static inline const WCHAR *get_module_path_end(const WCHAR *module) -{ - const WCHAR *p; - const WCHAR *mod_end = module; - if (!module) return mod_end; - - 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; - - return mod_end; -} - - -/****************************************************************** - * append_path_len - * - * Append a counted string to the load path. Helper for MODULE_get_dll_load_path. - */ -static inline WCHAR *append_path_len( WCHAR *p, const WCHAR *str, DWORD len ) -{ - if (!len) return p; - memcpy( p, str, len * sizeof(WCHAR) ); - p[len] = ';'; - return p + len + 1; -} - - -/****************************************************************** - * append_path - * - * Append a string to the load path. Helper for MODULE_get_dll_load_path. - */ -static inline WCHAR *append_path( WCHAR *p, const WCHAR *str ) -{ - return append_path_len( p, str, strlenW(str) ); -} - - -/****************************************************************** - * MODULE_get_dll_load_path - * - * Compute the load path to use for a given dll. - * Returned pointer must be freed by caller. - */ -WCHAR *MODULE_get_dll_load_path( LPCWSTR module, int safe_mode ) -{ - static const WCHAR pathW[] = {'P','A','T','H',0}; - static const WCHAR dotW[] = {'.',0}; - - const WCHAR *system_path = get_dll_system_path(); - const WCHAR *mod_end = NULL; - UNICODE_STRING name, value; - WCHAR *p, *ret; - int len = 0, path_len = 0, dlldir_len; - - /* adjust length for module name */ - - if (module) - mod_end = get_module_path_end( module ); - /* if module is NULL or doesn't contain a path, fall back to directory - * process was loaded from */ - if (module == mod_end) - { - module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; - mod_end = get_module_path_end( module ); - } - len += (mod_end - module) + 1; - - len += strlenW( system_path ) + 2; - - /* get the PATH variable */ - - 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; - - dlldir_len = GetDllDirectoryW( 0, NULL ); - - if (safe_mode == -1) safe_mode = get_dll_safe_mode(); - if (dlldir_len > 1) len += dlldir_len; - else len += 2; /* current directory */ - if ((p = ret = HeapAlloc( GetProcessHeap(), 0, path_len + len * sizeof(WCHAR) ))) - { - if (module) p = append_path_len( p, module, mod_end - module ); - - if (dlldir_len > 1) - { - GetDllDirectoryW( len - (p - ret), p ); - p += strlenW(p); - *p++ = ';'; - } - else if (!safe_mode) p = append_path( p, dotW ); - - p = append_path( p, system_path ); - - if (dlldir_len <= 1 && safe_mode) p = append_path( p, dotW ); - } - if (!ret) return NULL; - - value.Buffer = p; - 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 = HeapReAlloc( GetProcessHeap(), 0, ret, path_len + len * sizeof(WCHAR) ))) - { - HeapFree( GetProcessHeap(), 0, ret ); - return NULL; - } - value.Buffer = new_ptr + (value.Buffer - ret); - value.MaximumLength = path_len; - ret = new_ptr; - } - value.Buffer[value.Length / sizeof(WCHAR)] = 0; - return ret; -} - - -/****************************************************************** - * get_dll_load_path_search_flags - */ -static WCHAR *get_dll_load_path_search_flags( LPCWSTR module, DWORD flags ) -{ - const WCHAR *image = NULL, *mod_end, *image_end; - struct dll_dir_entry *dir; - WCHAR *p, *ret; - int len = 1; - - if (flags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) - flags |= (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | - LOAD_LIBRARY_SEARCH_USER_DIRS | - LOAD_LIBRARY_SEARCH_SYSTEM32); - - if (flags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) - { - DWORD type = RtlDetermineDosPathNameType_U( module ); - if (type != ABSOLUTE_DRIVE_PATH && type != ABSOLUTE_PATH) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return NULL; - } - mod_end = get_module_path_end( module ); - len += (mod_end - module) + 1; - } - else module = NULL; - - RtlEnterCriticalSection( &dlldir_section ); - - if (flags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) - { - image = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; - image_end = get_module_path_end( image ); - len += (image_end - image) + 1; - } - - if (flags & LOAD_LIBRARY_SEARCH_USER_DIRS) - { - LIST_FOR_EACH_ENTRY( dir, &dll_dir_list, struct dll_dir_entry, entry ) - len += strlenW( dir->dir ) + 1; - len += GetDllDirectoryW( 0, NULL ); - } - - if (flags & LOAD_LIBRARY_SEARCH_SYSTEM32) len += GetSystemDirectoryW( NULL, 0 ); - - if ((p = ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - { - if (module) p = append_path_len( p, module, mod_end - module ); - if (image) p = append_path_len( p, image, image_end - image ); - if (flags & LOAD_LIBRARY_SEARCH_USER_DIRS) - { - LIST_FOR_EACH_ENTRY( dir, &dll_dir_list, struct dll_dir_entry, entry ) - p = append_path( p, dir->dir ); - GetDllDirectoryW( ret + len - p, p ); - if (*p) - { - p += strlenW(p); - *p++ = ';'; - } - } - if (flags & LOAD_LIBRARY_SEARCH_SYSTEM32) GetSystemDirectoryW( p, ret + len - p ); - else - { - if (p > ret) p--; - *p = 0; - } - } - - RtlLeaveCriticalSection( &dlldir_section ); - return ret; -} - - /****************************************************************** * load_library_as_datafile */ -static BOOL load_library_as_datafile( LPCWSTR name, HMODULE *hmod, DWORD flags ) +static BOOL load_library_as_datafile( LPCWSTR load_path, DWORD flags, LPCWSTR name, HMODULE *hmod ) { static const WCHAR dotDLL[] = {'.','d','l','l',0}; @@ -669,7 +301,7 @@ static BOOL load_library_as_datafile( LPCWSTR name, HMODULE *hmod, DWORD flags ) if (flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) protect |= SEC_IMAGE; - if (SearchPathW( NULL, name, dotDLL, ARRAY_SIZE( filenameW ), filenameW, NULL )) + if (SearchPathW( load_path, name, dotDLL, ARRAY_SIZE( filenameW ), filenameW, NULL )) { hFile = CreateFileW( filenameW, GENERIC_READ, sharing, NULL, OPEN_EXISTING, 0, 0 ); } @@ -720,34 +352,14 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags ) { NTSTATUS nts; HMODULE hModule; - WCHAR *load_path; - const DWORD load_library_search_flags = (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | - LOAD_LIBRARY_SEARCH_APPLICATION_DIR | - LOAD_LIBRARY_SEARCH_USER_DIRS | - LOAD_LIBRARY_SEARCH_SYSTEM32 | - LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + WCHAR *load_path, *dummy; const DWORD unsupported_flags = (LOAD_IGNORE_CODE_AUTHZ_LEVEL | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET); if( flags & unsupported_flags) FIXME("unsupported flag(s) used (flags: 0x%08x)\n", flags); - if (flags & LOAD_WITH_ALTERED_SEARCH_PATH) - { - if (flags & load_library_search_flags) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - if (default_search_flags) flags |= default_search_flags | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR; - } - else if (!(flags & load_library_search_flags)) flags |= default_search_flags; - - if (flags & load_library_search_flags) - load_path = get_dll_load_path_search_flags( libname->Buffer, flags ); - else - load_path = MODULE_get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL, -1 ); - if (!load_path) return 0; + if (!set_ntstatus( LdrGetDllPath( libname->Buffer, flags, &load_path, &dummy ))) return 0; if (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)) { @@ -760,7 +372,7 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags ) LdrUnlockLoaderLock( 0, magic ); goto done; } - if (load_library_as_datafile( libname->Buffer, &hModule, flags )) + if (load_library_as_datafile( load_path, flags, libname->Buffer, &hModule )) { LdrUnlockLoaderLock( 0, magic ); goto done; @@ -780,7 +392,7 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags ) SetLastError( RtlNtStatusToDosError( nts ) ); } done: - HeapFree( GetProcessHeap(), 0, load_path ); + RtlReleasePath( load_path ); return hModule; } diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 008d89dc120..3aae3d129ec 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -1373,6 +1373,7 @@ void * CDECL __wine_kernel_init(void) RTL_USER_PROCESS_PARAMETERS *params = peb->ProcessParameters; HANDLE boot_events[2]; BOOL got_environment = TRUE; + WCHAR *load_path, *dummy; /* Initialize everything */ @@ -1429,8 +1430,8 @@ void * CDECL __wine_kernel_init(void) TRACE( "starting process name=%s argv[0]=%s\n", debugstr_w(main_exe_name), debugstr_w(__wine_main_wargv[0]) ); - RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath, - MODULE_get_dll_load_path( main_exe_name, -1 )); + LdrGetDllPath( main_exe_name, 0, &load_path, &dummy ); + RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath, load_path ); if (boot_events[0]) { diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c index 876ca743bc1..1610370064d 100644 --- a/dlls/kernel32/tests/path.c +++ b/dlls/kernel32/tests/path.c @@ -73,10 +73,14 @@ static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD); static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR); static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR); -static BOOL (WINAPI *pSetSearchPathMode)(DWORD); -static BOOL (WINAPI *pSetDllDirectoryA)(LPCSTR); +static DLL_DIRECTORY_COOKIE (WINAPI *pAddDllDirectory)(const WCHAR*); +static BOOL (WINAPI *pRemoveDllDirectory)(DLL_DIRECTORY_COOKIE); +static BOOL (WINAPI *pSetSearchPathMode)(DWORD); +static BOOL (WINAPI *pSetDllDirectoryW)(LPCWSTR); +static BOOL (WINAPI *pSetDefaultDllDirectories)(DWORD); static NTSTATUS (WINAPI *pRtlGetSearchPath)(LPWSTR*); -static void (WINAPI *pRtlReleasePath)(LPWSTR); +static void (WINAPI *pRtlReleasePath)(LPWSTR); +static NTSTATUS (WINAPI *pLdrGetDllPath)(LPCWSTR,ULONG,LPWSTR*,LPWSTR*); static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*); static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW); @@ -2201,7 +2205,10 @@ static void init_pointers(void) MAKEFUNC(NeedCurrentDirectoryForExePathA); MAKEFUNC(NeedCurrentDirectoryForExePathW); MAKEFUNC(SetSearchPathMode); - MAKEFUNC(SetDllDirectoryA); + MAKEFUNC(AddDllDirectory); + MAKEFUNC(RemoveDllDirectory); + MAKEFUNC(SetDllDirectoryW); + MAKEFUNC(SetDefaultDllDirectories); MAKEFUNC(ActivateActCtx); MAKEFUNC(CreateActCtxW); MAKEFUNC(DeactivateActCtx); @@ -2210,6 +2217,7 @@ static void init_pointers(void) MAKEFUNC(CheckNameLegalDOS8Dot3W); MAKEFUNC(CheckNameLegalDOS8Dot3A); mod = GetModuleHandleA("ntdll.dll"); + MAKEFUNC(LdrGetDllPath); MAKEFUNC(RtlGetSearchPath); MAKEFUNC(RtlReleasePath); #undef MAKEFUNC @@ -2470,12 +2478,23 @@ static void test_SetSearchPathMode(void) static const WCHAR pathW[] = {'P','A','T','H',0}; -static void build_search_path( WCHAR *buffer, UINT size, BOOL safe ) +static void build_search_path( WCHAR *buffer, UINT size, const WCHAR *dlldir, BOOL safe ) { WCHAR *p; GetModuleFileNameW( NULL, buffer, size ); if (!(p = wcsrchr( buffer, '\\' ))) return; *p++ = ';'; + if (dlldir) + { + lstrcpyW( p, dlldir ); + p += lstrlenW( p ); + if (*dlldir) *p++ = ';'; + } + else if (!safe) + { + *p++ = '.'; + *p++ = ';'; + } GetSystemDirectoryW( p, buffer + size - p ); p = buffer + lstrlenW(buffer); *p++ = ';'; @@ -2485,7 +2504,7 @@ static void build_search_path( WCHAR *buffer, UINT size, BOOL safe ) GetWindowsDirectoryW( p, buffer + size - p ); p = buffer + lstrlenW(buffer); *p++ = ';'; - if (!safe) + if (!dlldir && safe) { *p++ = '.'; *p++ = ';'; @@ -2501,7 +2520,7 @@ static BOOL path_equal( const WCHAR *path1, const WCHAR *path2 ) if (*path1 && *path1 != '\\' && *path1 != ';') return FALSE; while (*path1 && (*path1 == '\\' || *path1 == ';')) path1++; while (*path2 && (*path2 == '\\' || *path2 == ';')) path2++; - if (!*path1 && !*path2) return TRUE; + if (!*path1 || !*path2) return !*path1 && !*path2; } } @@ -2509,7 +2528,7 @@ static void test_RtlGetSearchPath(void) { NTSTATUS ret; WCHAR *path; - WCHAR buffer[2048], old_path[2048]; + WCHAR buffer[2048], old_path[2048], dlldir[4]; if (!pRtlGetSearchPath) { @@ -2518,8 +2537,10 @@ static void test_RtlGetSearchPath(void) } GetEnvironmentVariableW( pathW, old_path, ARRAY_SIZE(old_path) ); + GetWindowsDirectoryW( buffer, ARRAY_SIZE(buffer) ); + lstrcpynW( dlldir, buffer, ARRAY_SIZE(dlldir) ); - build_search_path( buffer, ARRAY_SIZE(buffer), FALSE ); + build_search_path( buffer, ARRAY_SIZE(buffer), NULL, TRUE ); path = (WCHAR *)0xdeadbeef; ret = pRtlGetSearchPath( &path ); ok( !ret, "RtlGetSearchPath failed %x\n", ret ); @@ -2527,23 +2548,123 @@ static void test_RtlGetSearchPath(void) pRtlReleasePath( path ); SetEnvironmentVariableA( "PATH", "foo" ); - build_search_path( buffer, ARRAY_SIZE(buffer), FALSE ); + build_search_path( buffer, ARRAY_SIZE(buffer), NULL, TRUE ); 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) + if (pSetDllDirectoryW) { - ok( pSetDllDirectoryA( "c:\\" ), "SetDllDirectoryA failed\n" ); - build_search_path( buffer, ARRAY_SIZE(buffer), FALSE ); + ok( pSetDllDirectoryW( dlldir ), "SetDllDirectoryW failed\n" ); + build_search_path( buffer, ARRAY_SIZE(buffer), NULL, TRUE ); 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 ); + pSetDllDirectoryW( NULL ); + } + + SetEnvironmentVariableW( pathW, old_path ); +} + +static void test_LdrGetDllPath(void) +{ + static const WCHAR fooW[] = {'f','o','o',0}; + NTSTATUS ret; + WCHAR *path, *unknown_ptr, *p; + WCHAR buffer[2048], old_path[2048], dlldir[4]; + + if (!pLdrGetDllPath) + { + win_skip( "LdrGetDllPath isn't available\n" ); + return; + } + GetEnvironmentVariableW( pathW, old_path, ARRAY_SIZE(old_path) ); + GetWindowsDirectoryW( buffer, ARRAY_SIZE(buffer) ); + lstrcpynW( dlldir, buffer, ARRAY_SIZE(dlldir) ); + + build_search_path( buffer, ARRAY_SIZE(buffer), NULL, TRUE ); + + path = unknown_ptr = (WCHAR *)0xdeadbeef; + ret = pLdrGetDllPath( 0, 0, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + 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), NULL, TRUE ); + ret = pLdrGetDllPath( 0, 0, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); + pRtlReleasePath( path ); + + if (pSetDllDirectoryW) + { + ok( pSetDllDirectoryW( dlldir ), "SetDllDirectoryW failed\n" ); + build_search_path( buffer, ARRAY_SIZE(buffer), dlldir, TRUE ); + ret = pLdrGetDllPath( 0, 0, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); + pRtlReleasePath( path ); + pSetDllDirectoryW( NULL ); + } + + ret = pLdrGetDllPath( 0, LOAD_LIBRARY_SEARCH_SYSTEM32, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + GetSystemDirectoryW( buffer, ARRAY_SIZE(buffer) ); + ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); + pRtlReleasePath( path ); + + ret = pLdrGetDllPath( 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + GetModuleFileNameW( NULL, buffer, ARRAY_SIZE(buffer) ); + if ((p = wcsrchr( buffer, '\\' ))) *p = 0; + ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); + pRtlReleasePath( path ); + + ret = pLdrGetDllPath( fooW, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR, &path, &unknown_ptr ); + ok( ret == STATUS_INVALID_PARAMETER, "LdrGetDllPath failed %x\n", ret ); + + lstrcpyW( buffer, dlldir ); + p = buffer + lstrlenW(buffer); + *p++ = '\\'; + lstrcpyW( p, fooW ); + ret = pLdrGetDllPath( buffer, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + ok( path_equal( path, dlldir ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(dlldir)); + pRtlReleasePath( path ); + + if (pAddDllDirectory) + { + DLL_DIRECTORY_COOKIE cookie = pAddDllDirectory( dlldir ); + ok( !!cookie, "AddDllDirectory failed\n" ); + ret = pLdrGetDllPath( 0, LOAD_LIBRARY_SEARCH_USER_DIRS, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + ok( path_equal( path, dlldir ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(dlldir)); + pRtlReleasePath( path ); + pRemoveDllDirectory( cookie ); + } + + if (pSetDefaultDllDirectories) + { + pSetDefaultDllDirectories( LOAD_LIBRARY_SEARCH_SYSTEM32 ); + ret = pLdrGetDllPath( 0, 0, &path, &unknown_ptr ); + ok( !ret, "LdrGetDllPath failed %x\n", ret ); + ok( !unknown_ptr, "unknown ptr %p\n", unknown_ptr ); + GetSystemDirectoryW( buffer, ARRAY_SIZE(buffer) ); + ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer)); + pRtlReleasePath( path ); + pSetDefaultDllDirectories( 0 ); } SetEnvironmentVariableW( pathW, old_path ); @@ -2584,4 +2705,5 @@ START_TEST(path) test_CheckNameLegalDOS8Dot3(); test_SetSearchPathMode(); test_RtlGetSearchPath(); + test_LdrGetDllPath(); } diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 7d86399af5f..dcd5bce6334 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -19,7 +19,7 @@ @ stdcall AddAuditAccessAce(ptr long long ptr long long) @ stdcall AddAuditAccessAceEx(ptr long long long ptr long long) @ stdcall AddAuditAccessObjectAce(ptr long long long ptr ptr ptr long long) -@ stdcall AddDllDirectory(wstr) kernel32.AddDllDirectory +@ stdcall AddDllDirectory(wstr) @ stdcall AddMandatoryAce(ptr long long long ptr) @ stdcall AddRefActCtx(ptr) # @ stub AddResourceAttributeAce @@ -1333,7 +1333,7 @@ @ stdcall RemapPredefinedHandleInternal(long long) @ stdcall RemoveDirectoryA(str) kernel32.RemoveDirectoryA @ stdcall RemoveDirectoryW(wstr) kernel32.RemoveDirectoryW -@ stdcall RemoveDllDirectory(ptr) kernel32.RemoveDllDirectory +@ stdcall RemoveDllDirectory(ptr) # @ stub RemovePackageStatus # @ stub RemovePackageStatusForUser @ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler @@ -1419,7 +1419,7 @@ @ stdcall SetCriticalSectionSpinCount(ptr long) ntdll.RtlSetCriticalSectionSpinCount @ stdcall SetCurrentDirectoryA(str) @ stdcall SetCurrentDirectoryW(wstr) -@ stdcall SetDefaultDllDirectories(long) kernel32.SetDefaultDllDirectories +@ stdcall SetDefaultDllDirectories(long) # @ stub SetDynamicTimeZoneInformation @ stdcall SetEndOfFile(long) @ stub SetEnvironmentStringsW diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index de46cc8c10d..992a9c9b293 100644 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -42,6 +42,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(module); ***********************************************************************/ +/**************************************************************************** + * AddDllDirectory (kernelbase.@) + */ +DLL_DIRECTORY_COOKIE WINAPI DECLSPEC_HOTPATCH AddDllDirectory( const WCHAR *dir ) +{ + UNICODE_STRING str; + void *cookie; + + RtlInitUnicodeString( &str, dir ); + if (!set_ntstatus( LdrAddDllDirectory( &str, &cookie ))) return NULL; + return cookie; +} + + /*********************************************************************** * DelayLoadFailureHook (kernelbase.@) */ @@ -225,6 +239,24 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetModuleHandleExW( DWORD flags, LPCWSTR name, HMO } +/**************************************************************************** + * RemoveDllDirectory (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH RemoveDllDirectory( DLL_DIRECTORY_COOKIE cookie ) +{ + return set_ntstatus( LdrRemoveDllDirectory( cookie )); +} + + +/************************************************************************* + * SetDefaultDllDirectories (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH SetDefaultDllDirectories( DWORD flags ) +{ + return set_ntstatus( LdrSetDefaultDllDirectories( flags )); +} + + /*********************************************************************** * Resources ***********************************************************************/ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 6606fa5aec5..4b528b5ea8b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -72,13 +72,25 @@ const WCHAR system_dir[] = {'C',':','\\','w','i','n','d','o','w','s','\\', 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}; + 'C',':','\\','w','i','n','d','o','w','s',0}; + +static const WCHAR dotW[] = {'.',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 */ static ULONG path_safe_mode; /* path mode set by RtlSetSearchPathMode */ +static ULONG dll_safe_mode = 1; /* dll search mode */ static UNICODE_STRING dll_directory; /* extra path for LdrSetDllDirectory */ +static DWORD default_search_flags; /* default flags set by LdrSetDefaultDllDirectories */ + +struct dll_dir_entry +{ + struct list entry; + WCHAR dir[1]; +}; + +static struct list dll_dir_list = LIST_INIT( dll_dir_list ); /* extra dirs from LdrAddDllDirectory */ struct ldr_notification { @@ -2078,25 +2090,54 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info ) } +/****************************************************************** + * get_module_path_end + * + * Returns the end of the directory component of the module path. + */ +static inline const WCHAR *get_module_path_end( const WCHAR *module ) +{ + const WCHAR *p; + const WCHAR *mod_end = 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; + return mod_end; +} + + +/****************************************************************** + * append_path + * + * Append a counted string to the load path. Helper for get_dll_load_path. + */ +static inline WCHAR *append_path( WCHAR *p, const WCHAR *str, int len ) +{ + if (len == -1) len = strlenW(str); + if (!len) return p; + memcpy( p, str, len * sizeof(WCHAR) ); + p[len] = ';'; + return p + len + 1; +} + + /****************************************************************** * get_dll_load_path */ -static NTSTATUS get_dll_load_path( LPCWSTR module, int safe_mode, WCHAR **path ) +static NTSTATUS get_dll_load_path( LPCWSTR module, LPCWSTR dll_dir, ULONG 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; + int len = ARRAY_SIZE(system_path) + 1, 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; + mod_end = get_module_path_end( module ); len += (mod_end - module) + 1; } @@ -2107,18 +2148,18 @@ static NTSTATUS get_dll_load_path( LPCWSTR module, int safe_mode, WCHAR **path ) 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) ))) + if (dll_dir) len += strlenW( dll_dir ) + 1; + else len += 2; /* current directory */ + if (!(p = 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); + p = append_path( p, module, mod_end - module ); + if (dll_dir) p = append_path( p, dll_dir, -1 ); + else if (!safe_mode) p = append_path( p, dotW, -1 ); + p = append_path( p, system_path, -1 ); + if (!dll_dir && safe_mode) p = append_path( p, dotW, -1 ); + + value.Buffer = p; value.MaximumLength = path_len; while (RtlQueryEnvironmentVariable_U( NULL, &name, &value ) == STATUS_BUFFER_TOO_SMALL) @@ -2142,6 +2183,69 @@ static NTSTATUS get_dll_load_path( LPCWSTR module, int safe_mode, WCHAR **path ) } +/****************************************************************** + * get_dll_load_path_search_flags + */ +static NTSTATUS get_dll_load_path_search_flags( LPCWSTR module, DWORD flags, WCHAR **path ) +{ + const WCHAR *image = NULL, *mod_end, *image_end; + struct dll_dir_entry *dir; + WCHAR *p, *ret; + int len = 1; + + if (flags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) + flags |= (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | + LOAD_LIBRARY_SEARCH_USER_DIRS | + LOAD_LIBRARY_SEARCH_SYSTEM32); + + if (flags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) + { + DWORD type = RtlDetermineDosPathNameType_U( module ); + if (type != ABSOLUTE_DRIVE_PATH && type != ABSOLUTE_PATH) + return STATUS_INVALID_PARAMETER; + mod_end = get_module_path_end( module ); + len += (mod_end - module) + 1; + } + else module = NULL; + + if (flags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) + { + image = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + image_end = get_module_path_end( image ); + len += (image_end - image) + 1; + } + + if (flags & LOAD_LIBRARY_SEARCH_USER_DIRS) + { + LIST_FOR_EACH_ENTRY( dir, &dll_dir_list, struct dll_dir_entry, entry ) + len += strlenW( dir->dir + 4 /* \??\ */ ) + 1; + if (dll_directory.Length) len += dll_directory.Length / sizeof(WCHAR) + 1; + } + + if (flags & LOAD_LIBRARY_SEARCH_SYSTEM32) len += strlenW( system_dir ); + + if ((p = ret = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + { + if (module) p = append_path( p, module, mod_end - module ); + if (image) p = append_path( p, image, image_end - image ); + if (flags & LOAD_LIBRARY_SEARCH_USER_DIRS) + { + LIST_FOR_EACH_ENTRY( dir, &dll_dir_list, struct dll_dir_entry, entry ) + p = append_path( p, dir->dir + 4 /* \??\ */, -1 ); + p = append_path( p, dll_directory.Buffer, dll_directory.Length / sizeof(WCHAR) ); + } + if (flags & LOAD_LIBRARY_SEARCH_SYSTEM32) strcpyW( p, system_dir ); + else + { + if (p > ret) p--; + *p = 0; + } + } + *path = ret; + return STATUS_SUCCESS; +} + + /*********************************************************************** * open_dll_file * @@ -3701,6 +3805,7 @@ static void load_global_options(void) 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0}; static const WCHAR globalflagW[] = {'G','l','o','b','a','l','F','l','a','g',0}; static const WCHAR safesearchW[] = {'S','a','f','e','P','r','o','c','e','s','s','S','e','a','r','c','h','M','o','d','e',0}; + static const WCHAR safedllmodeW[] = {'S','a','f','e','D','l','l','S','e','a','r','c','h','M','o','d','e',0}; static const WCHAR critsectW[] = {'C','r','i','t','i','c','a','l','S','e','c','t','i','o','n','T','i','m','e','o','u','t',0}; static const WCHAR heapresW[] = {'H','e','a','p','S','e','g','m','e','n','t','R','e','s','e','r','v','e',0}; static const WCHAR heapcommitW[] = {'H','e','a','p','S','e','g','m','e','n','t','C','o','m','m','i','t',0}; @@ -3724,6 +3829,7 @@ static void load_global_options(void) query_dword_option( hkey, globalflagW, &NtCurrentTeb()->Peb->NtGlobalFlag ); query_dword_option( hkey, safesearchW, &path_safe_mode ); + query_dword_option( hkey, safedllmodeW, &dll_safe_mode ); if (!query_dword_option( hkey, critsectW, &value )) NtCurrentTeb()->Peb->CriticalSectionTimeout.QuadPart = (ULONGLONG)value * -10000000; @@ -3876,6 +3982,124 @@ NTSTATUS WINAPI LdrSetDllDirectory( const UNICODE_STRING *dir ) } +/**************************************************************************** + * LdrAddDllDirectory (NTDLL.@) + */ +NTSTATUS WINAPI LdrAddDllDirectory( const UNICODE_STRING *dir, void **cookie ) +{ + FILE_BASIC_INFORMATION info; + UNICODE_STRING nt_name; + NTSTATUS status; + OBJECT_ATTRIBUTES attr; + DWORD len; + struct dll_dir_entry *ptr; + DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U( dir->Buffer ); + + if (type != ABSOLUTE_PATH && type != ABSOLUTE_DRIVE_PATH) + return STATUS_INVALID_PARAMETER; + + status = RtlDosPathNameToNtPathName_U_WithStatus( dir->Buffer, &nt_name, NULL, NULL ); + if (status) return status; + len = nt_name.Length / sizeof(WCHAR); + if (!(ptr = RtlAllocateHeap( GetProcessHeap(), 0, offsetof(struct dll_dir_entry, dir[++len] )))) + return STATUS_NO_MEMORY; + memcpy( ptr->dir, nt_name.Buffer, len * sizeof(WCHAR) ); + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &nt_name; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + status = NtQueryAttributesFile( &attr, &info ); + RtlFreeUnicodeString( &nt_name ); + + if (!status) + { + TRACE( "%s\n", debugstr_w( ptr->dir )); + RtlEnterCriticalSection( &dlldir_section ); + list_add_head( &dll_dir_list, &ptr->entry ); + RtlLeaveCriticalSection( &dlldir_section ); + *cookie = ptr; + } + else RtlFreeHeap( GetProcessHeap(), 0, ptr ); + return status; +} + + +/**************************************************************************** + * LdrRemoveDllDirectory (NTDLL.@) + */ +NTSTATUS WINAPI LdrRemoveDllDirectory( void *cookie ) +{ + struct dll_dir_entry *ptr = cookie; + + TRACE( "%s\n", debugstr_w( ptr->dir )); + + RtlEnterCriticalSection( &dlldir_section ); + list_remove( &ptr->entry ); + RtlFreeHeap( GetProcessHeap(), 0, ptr ); + RtlLeaveCriticalSection( &dlldir_section ); + return STATUS_SUCCESS; +} + + +/************************************************************************* + * LdrSetDefaultDllDirectories (NTDLL.@) + */ +NTSTATUS WINAPI LdrSetDefaultDllDirectories( ULONG flags ) +{ + /* LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR doesn't make sense in default dirs */ + const ULONG load_library_search_flags = (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | + LOAD_LIBRARY_SEARCH_USER_DIRS | + LOAD_LIBRARY_SEARCH_SYSTEM32 | + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + + if (!flags || (flags & ~load_library_search_flags)) return STATUS_INVALID_PARAMETER; + default_search_flags = flags; + return STATUS_SUCCESS; +} + + +/****************************************************************** + * LdrGetDllPath (NTDLL.@) + */ +NTSTATUS WINAPI LdrGetDllPath( PCWSTR module, ULONG flags, PWSTR *path, PWSTR *unknown ) +{ + NTSTATUS status; + const ULONG load_library_search_flags = (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | + LOAD_LIBRARY_SEARCH_APPLICATION_DIR | + LOAD_LIBRARY_SEARCH_USER_DIRS | + LOAD_LIBRARY_SEARCH_SYSTEM32 | + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + + if (flags & LOAD_WITH_ALTERED_SEARCH_PATH) + { + if (flags & load_library_search_flags) return STATUS_INVALID_PARAMETER; + if (default_search_flags) flags |= default_search_flags | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR; + } + else if (!(flags & load_library_search_flags)) flags |= default_search_flags; + + RtlEnterCriticalSection( &dlldir_section ); + + if (flags & load_library_search_flags) + { + status = get_dll_load_path_search_flags( module, flags, path ); + } + else + { + const WCHAR *dlldir = dll_directory.Length ? dll_directory.Buffer : NULL; + if (!(flags & LOAD_WITH_ALTERED_SEARCH_PATH)) + module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + status = get_dll_load_path( module, dlldir, dll_safe_mode, path ); + } + + RtlLeaveCriticalSection( &dlldir_section ); + *unknown = NULL; + return status; +} + + /************************************************************************* * RtlSetSearchPathMode (NTDLL.@) */ @@ -3913,8 +4137,8 @@ NTSTATUS WINAPI RtlSetSearchPathMode( ULONG flags ) */ NTSTATUS WINAPI RtlGetSearchPath( PWSTR *path ) { - WCHAR *module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; - return get_dll_load_path( module, path_safe_mode, path ); + const WCHAR *module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + return get_dll_load_path( module, NULL, path_safe_mode, path ); } diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 6a14d502534..c33f12121ba 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -71,6 +71,7 @@ @ stub KiUserExceptionDispatcher # @ stub LdrAccessOutOfProcessResource @ stdcall LdrAccessResource(long ptr ptr ptr) +@ stdcall LdrAddDllDirectory(ptr ptr) @ stdcall LdrAddRefDll(long ptr) # @ stub LdrAlternateResourcesEnabled # @ stub LdrCreateOutOfProcessImage @@ -84,9 +85,10 @@ # @ stub LdrFindResourceEx_U @ stdcall LdrFindResource_U(long ptr long ptr) @ stub LdrFlushAlternateResourceModules +@ stdcall LdrGetDllDirectory(ptr) @ stdcall LdrGetDllHandle(wstr long ptr ptr) # @ stub LdrGetDllHandleEx -@ stdcall LdrGetDllDirectory(ptr) +@ stdcall LdrGetDllPath(wstr long ptr ptr) @ stdcall LdrGetProcedureAddress(ptr ptr long ptr) # @ stub LdrHotPatchRoutine @ stub LdrInitShimEngineDynamic @@ -98,8 +100,10 @@ @ stdcall LdrQueryImageFileExecutionOptions(ptr wstr long ptr long ptr) @ stdcall LdrQueryProcessModuleInformation(ptr long ptr) @ stdcall LdrRegisterDllNotification(long ptr ptr ptr) +@ stdcall LdrRemoveDllDirectory(ptr) @ stdcall LdrResolveDelayLoadedAPI(ptr ptr ptr ptr ptr long) @ stub LdrSetAppCompatDllRedirectionCallback +@ stdcall LdrSetDefaultDllDirectories(long) @ stdcall LdrSetDllDirectory(ptr) @ stub LdrSetDllManifestProber @ stdcall LdrShutdownProcess() diff --git a/include/winternl.h b/include/winternl.h index cb0172c366f..95105c67b4c 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2309,6 +2309,7 @@ NTSYSAPI NTSTATUS WINAPI DbgUiIssueRemoteBreakin(HANDLE); NTSYSAPI void WINAPI DbgUiRemoteBreakin(void*); NTSYSAPI void WINAPI DbgUserBreakPoint(void); NTSYSAPI NTSTATUS WINAPI LdrAccessResource(HMODULE,const IMAGE_RESOURCE_DATA_ENTRY*,void**,PULONG); +NTSYSAPI NTSTATUS WINAPI LdrAddDllDirectory(const UNICODE_STRING*,void**); NTSYSAPI NTSTATUS WINAPI LdrAddRefDll(ULONG,HMODULE); NTSYSAPI NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE); NTSYSAPI NTSTATUS WINAPI LdrFindEntryForAddress(const void*, PLDR_MODULE*); @@ -2316,12 +2317,15 @@ NTSYSAPI NTSTATUS WINAPI LdrFindResourceDirectory_U(HMODULE,const LDR_RESOURCE_ NTSYSAPI NTSTATUS WINAPI LdrFindResource_U(HMODULE,const LDR_RESOURCE_INFO*,ULONG,const IMAGE_RESOURCE_DATA_ENTRY**); NTSYSAPI NTSTATUS WINAPI LdrGetDllDirectory(UNICODE_STRING*); NTSYSAPI NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*); +NTSYSAPI NTSTATUS WINAPI LdrGetDllPath(PCWSTR,ULONG,PWSTR*,PWSTR*); NTSYSAPI NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, const ANSI_STRING*, ULONG, void**); NTSYSAPI NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, const UNICODE_STRING*, HMODULE*); NTSYSAPI NTSTATUS WINAPI LdrLockLoaderLock(ULONG,ULONG*,ULONG_PTR*); IMAGE_BASE_RELOCATION * WINAPI LdrProcessRelocationBlock(void*,UINT,USHORT*,INT_PTR); NTSYSAPI NTSTATUS WINAPI LdrQueryImageFileExecutionOptions(const UNICODE_STRING*,LPCWSTR,ULONG,void*,ULONG,ULONG*); NTSYSAPI NTSTATUS WINAPI LdrQueryProcessModuleInformation(SYSTEM_MODULE_INFORMATION*, ULONG, ULONG*); +NTSYSAPI NTSTATUS WINAPI LdrRemoveDllDirectory(void*); +NTSYSAPI NTSTATUS WINAPI LdrSetDefaultDllDirectories(ULONG); NTSYSAPI NTSTATUS WINAPI LdrSetDllDirectory(const UNICODE_STRING*); NTSYSAPI void WINAPI LdrShutdownProcess(void); NTSYSAPI void WINAPI LdrShutdownThread(void);