Alexandre Julliard : kernel32: Implement safe search mode for SearchPath.

Alexandre Julliard julliard at winehq.org
Tue Aug 29 14:48:24 CDT 2017


Module: wine
Branch: master
Commit: a8d291c0c01ec9696e14417ade7c30d8f2056366
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a8d291c0c01ec9696e14417ade7c30d8f2056366

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Aug 29 15:46:50 2017 +0200

kernel32: Implement safe search mode for SearchPath.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/kernel_private.h |  2 +-
 dlls/kernel32/module.c         |  7 ++--
 dlls/kernel32/path.c           | 77 +++++++++++++++++++++++++++++++++++++++---
 dlls/kernel32/process.c        |  2 +-
 include/winbase.h              |  7 ++++
 5 files changed, 85 insertions(+), 10 deletions(-)

diff --git a/dlls/kernel32/kernel_private.h b/dlls/kernel32/kernel_private.h
index 76611d7..7382956 100644
--- a/dlls/kernel32/kernel_private.h
+++ b/dlls/kernel32/kernel_private.h
@@ -89,7 +89,7 @@ struct binary_info
 };
 
 /* module.c */
-extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module ) DECLSPEC_HIDDEN;
+extern WCHAR *MODULE_get_dll_load_path( LPCWSTR module, int safe_mode ) DECLSPEC_HIDDEN;
 extern void MODULE_get_binary_info( HANDLE hfile, struct binary_info *info ) DECLSPEC_HIDDEN;
 
 extern BOOL NLS_IsUnicodeOnlyLcid(LCID) DECLSPEC_HIDDEN;
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c
index 9bd11c77..02c94c5 100644
--- a/dlls/kernel32/module.c
+++ b/dlls/kernel32/module.c
@@ -921,7 +921,7 @@ static inline WCHAR *append_path( WCHAR *p, const WCHAR *str )
  * 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 )
+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};
@@ -929,7 +929,6 @@ WCHAR *MODULE_get_dll_load_path( LPCWSTR module )
     const WCHAR *system_path = get_dll_system_path();
     const WCHAR *mod_end = NULL;
     UNICODE_STRING name, value;
-    BOOL safe_mode;
     WCHAR *p, *ret;
     int len = 0, path_len = 0;
 
@@ -958,7 +957,7 @@ WCHAR *MODULE_get_dll_load_path( LPCWSTR module )
         path_len = value.Length;
 
     RtlEnterCriticalSection( &dlldir_section );
-    safe_mode = get_dll_safe_mode();
+    if (safe_mode == -1) safe_mode = get_dll_safe_mode();
     if (dll_directory) len += strlenW(dll_directory) + 1;
     else len += 2;  /* current directory */
     if ((p = ret = HeapAlloc( GetProcessHeap(), 0, path_len + len * sizeof(WCHAR) )))
@@ -1137,7 +1136,7 @@ static HMODULE load_library( const UNICODE_STRING *libname, DWORD 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 );
+        load_path = MODULE_get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL, -1 );
     if (!load_path) return 0;
 
     if (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index ec7c53b..a389743 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -43,6 +43,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
 
 #define MAX_PATHNAME_LEN        1024
 
+static int path_safe_mode = -1;  /* path mode set by SetSearchPathMode */
 
 /* check if a file name is for an executable file (.exe or .com) */
 static inline BOOL is_executable( const WCHAR *name )
@@ -753,6 +754,51 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR
 
 
 /***********************************************************************
+ *           get_path_safe_mode
+ */
+static BOOL get_path_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','P','r','o','c','e','s','s','S','e','a','r','c','h','M','o','d','e',0};
+
+    if (path_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);
+        BOOL mode = FALSE;
+
+        attr.Length = sizeof(attr);
+        attr.RootDirectory = 0;
+        attr.ObjectName = &nameW;
+        attr.Attributes = 0;
+        attr.SecurityDescriptor = NULL;
+        attr.SecurityQualityOfService = NULL;
+
+        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))
+                mode = !!*(DWORD *)info->Data;
+            NtClose( hkey );
+        }
+        InterlockedCompareExchange( &path_safe_mode, mode, -1 );
+    }
+    return path_safe_mode != 0;
+}
+
+
+/***********************************************************************
  *           contains_pathW
  *
  * Check if the file name contains a path; helper for SearchPathW.
@@ -991,7 +1037,7 @@ DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
         }
         else
         {
-            if ((dll_path = MODULE_get_dll_load_path( NULL )))
+            if ((dll_path = MODULE_get_dll_load_path( NULL, get_path_safe_mode() )))
             {
                 ret = RtlDosSearchPath_U( dll_path, name, NULL, buflen * sizeof(WCHAR),
                                           buffer, lastpart ) / sizeof(WCHAR);
@@ -2075,9 +2121,32 @@ BOOL WINAPI CheckNameLegalDOS8Dot3W(const WCHAR *name, char *oemname, DWORD oemn
 /*************************************************************************
  *           SetSearchPathMode   (KERNEL32.@)
  */
-BOOL WINAPI SetSearchPathMode(DWORD flags)
+BOOL WINAPI SetSearchPathMode( DWORD flags )
 {
-    FIXME("(%x): stub\n", flags);
-    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    int val;
+
+    switch (flags)
+    {
+    case BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE:
+        val = 1;
+        break;
+    case BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE:
+        val = 0;
+        break;
+    case BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT:
+        InterlockedExchange( &path_safe_mode, 2 );
+        return TRUE;
+    default:
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    for (;;)
+    {
+        int prev = path_safe_mode;
+        if (prev == 2) break;  /* permanently set */
+        if (InterlockedCompareExchange( &path_safe_mode, val, prev ) == prev) return TRUE;
+    }
+    SetLastError( ERROR_ACCESS_DENIED );
     return FALSE;
 }
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 9097542..292317c 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -1258,7 +1258,7 @@ void CDECL __wine_kernel_init(void)
            debugstr_w(main_exe_name), debugstr_w(__wine_main_wargv[0]) );
 
     RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath,
-                          MODULE_get_dll_load_path(main_exe_name) );
+                          MODULE_get_dll_load_path( main_exe_name, -1 ));
 
     if (boot_events[0])
     {
diff --git a/include/winbase.h b/include/winbase.h
index f6a28c3..a4d545e 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1005,6 +1005,12 @@ DECL_WINELIB_TYPE_AW(ENUMRESLANGPROC)
 #define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT  2
 #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS        4
 
+/* flags for SetSearchPathMode */
+#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE  0x00001
+#define BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE 0x10000
+#define BASE_SEARCH_PATH_PERMANENT               0x08000
+#define BASE_SEARCH_PATH_INVALID_FLAGS         (~0x18001)
+
 typedef PLDT_ENTRY LPLDT_ENTRY;
 
 typedef enum _GET_FILEEX_INFO_LEVELS {
@@ -2551,6 +2557,7 @@ WINBASEAPI BOOL        WINAPI SetProcessAffinityMask(HANDLE,DWORD_PTR);
 WINBASEAPI BOOL        WINAPI SetProcessPriorityBoost(HANDLE,BOOL);
 WINBASEAPI BOOL        WINAPI SetProcessShutdownParameters(DWORD,DWORD);
 WINBASEAPI BOOL        WINAPI SetProcessWorkingSetSize(HANDLE,SIZE_T,SIZE_T);
+WINBASEAPI BOOL        WINAPI SetSearchPathMode(DWORD);
 WINADVAPI  BOOL        WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,SECURITY_DESCRIPTOR_CONTROL,SECURITY_DESCRIPTOR_CONTROL);
 WINADVAPI  BOOL        WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,BOOL,PACL,BOOL);
 WINADVAPI  BOOL        WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR,PSID,BOOL);




More information about the wine-cvs mailing list