I'm aware that winecfg allows unlinking of symlinked folders, but this is very annoying when regularly recreating WINEPREFIXES. This change makes it easy to isolate those folders from the start.
-- v5: ntdll: Add environment variable to prevent symlinking dosdevices/z: shell32: Add environment variable to prevent symlinking home folders
From: Fabian Maurer dark.shadow4@web.de
--- dlls/shell32/shellpath.c | 44 +++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-)
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c index 015d7cdd4e2..63ce9cbd08e 100644 --- a/dlls/shell32/shellpath.c +++ b/dlls/shell32/shellpath.c @@ -2775,6 +2775,26 @@ done: CloseHandle( mgr ); }
+static BOOL isolate_folder(const char *folder) +{ + char buffer[200]; + char *current, *next; + const char *isolate = getenv("WINEISOLATE"); + + if (!isolate || strlen(isolate) > ARRAY_SIZE(buffer)) + return FALSE; + + strcpy(buffer, isolate); + current = strtok_s(buffer, ",", &next); + while (current) + { + if (!strcmp(current, folder)) + return TRUE; + current = strtok(NULL, ","); + } + return FALSE; +} + /****************************************************************************** * _SHCreateSymbolicLink [Internal] * @@ -2786,29 +2806,39 @@ done: */ static void _SHCreateSymbolicLink(int nFolder, const WCHAR *path) { + BOOL isolate_all = isolate_folder("home"); DWORD folder = nFolder & CSIDL_FOLDER_MASK;
+ if (isolate_all) return; + switch (folder) { case CSIDL_PERSONAL: - create_link( path, "XDG_DOCUMENTS_DIR", "$HOME/Documents" ); + if (!isolate_folder("documents")) + create_link( path, "XDG_DOCUMENTS_DIR", "$HOME/Documents" ); break; case CSIDL_DESKTOPDIRECTORY: - create_link( path, "XDG_DESKTOP_DIR", "$HOME/Desktop" ); + if (!isolate_folder("desktop")) + create_link( path, "XDG_DESKTOP_DIR", "$HOME/Desktop" ); break; case CSIDL_MYPICTURES: - create_link( path, "XDG_PICTURES_DIR", "$HOME/Pictures" ); + if (!isolate_folder("pictures")) + create_link( path, "XDG_PICTURES_DIR", "$HOME/Pictures" ); break; case CSIDL_MYVIDEO: - create_link( path, "XDG_VIDEOS_DIR", "$HOME/Movies" ); + if (!isolate_folder("movies")) + create_link( path, "XDG_VIDEOS_DIR", "$HOME/Movies" ); break; case CSIDL_MYMUSIC: - create_link( path, "XDG_MUSIC_DIR", "$HOME/Music" ); + if (!isolate_folder("music")) + create_link( path, "XDG_MUSIC_DIR", "$HOME/Music" ); break; case CSIDL_DOWNLOADS: - create_link( path, "XDG_DOWNLOAD_DIR", "$HOME/Downloads" ); + if (!isolate_folder("downloads")) + create_link( path, "XDG_DOWNLOAD_DIR", "$HOME/Downloads" ); break; case CSIDL_TEMPLATES: - create_link( path, "XDG_TEMPLATES_DIR", "$HOME/Templates" ); + if (!isolate_folder("templates")) + create_link( path, "XDG_TEMPLATES_DIR", "$HOME/Templates" ); break; } }
From: Fabian Maurer dark.shadow4@web.de
--- dlls/ntdll/unix/server.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 7211457387c..b6d7ad10eee 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1265,6 +1265,26 @@ static const char *init_server_dir( dev_t dev, ino_t ino ) return dir; }
+/* Copied from shell32/shellpath, changed to use strtok_r */ +static BOOL isolate_folder(const char *folder) +{ + char buffer[200]; + char *current, *next = NULL; + const char *isolate = getenv("WINEISOLATE"); + + if (!isolate || strlen(isolate) > ARRAY_SIZE(buffer)) + return FALSE; + + strcpy(buffer, isolate); + current = strtok_r(buffer, ",", &next); + while (current) + { + if (!strcmp(current, folder)) + return TRUE; + current = strtok_r(NULL, ",", &next); + } + return FALSE; +}
/*********************************************************************** * setup_config_dir @@ -1303,7 +1323,8 @@ static int setup_config_dir(void) { mkdir( "drive_c", 0777 ); symlink( "../drive_c", "dosdevices/c:" ); - symlink( "/", "dosdevices/z:" ); + if (!isolate_folder("root")) + symlink( "/", "dosdevices/z:" ); } else if (errno != EEXIST) fatal_perror( "cannot create %s/dosdevices", config_dir );