Alexandre Julliard : winecfg: Use mountmgr to manage shell folders.

Alexandre Julliard julliard at winehq.org
Tue Sep 7 16:25:19 CDT 2021


Module: wine
Branch: master
Commit: 01a2b9c6282f9ff5480563cc5e4be12ce2f907a6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=01a2b9c6282f9ff5480563cc5e4be12ce2f907a6

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Sep  7 13:18:37 2021 +0200

winecfg: Use mountmgr to manage shell folders.

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

---

 programs/winecfg/drive.c   | 52 ++++++++++++++++++++++++++++++++
 programs/winecfg/theme.c   | 75 +++++-----------------------------------------
 programs/winecfg/winecfg.h |  2 ++
 3 files changed, 61 insertions(+), 68 deletions(-)

diff --git a/programs/winecfg/drive.c b/programs/winecfg/drive.c
index a5fc3bfd73a..bfe9a48e94d 100644
--- a/programs/winecfg/drive.c
+++ b/programs/winecfg/drive.c
@@ -370,3 +370,55 @@ void apply_drive_changes(void)
     }
     CloseHandle( mgr );
 }
+
+
+void query_shell_folder( const WCHAR *path, char *dest, unsigned int len )
+{
+    UNICODE_STRING nt_name;
+    HANDLE mgr;
+
+    if ((mgr = open_mountmgr()) == INVALID_HANDLE_VALUE) return;
+
+    if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL ))
+    {
+        CloseHandle( mgr );
+        return;
+    }
+    DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_SHELL_FOLDER, nt_name.Buffer, nt_name.Length,
+                     dest, len, NULL, NULL );
+    RtlFreeUnicodeString( &nt_name );
+}
+
+void set_shell_folder( const WCHAR *path, const char *dest )
+{
+    struct mountmgr_shell_folder *ioctl;
+    UNICODE_STRING nt_name;
+    HANDLE mgr;
+    DWORD len;
+
+    if ((mgr = open_mountmgr()) == INVALID_HANDLE_VALUE) return;
+
+    if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL ))
+    {
+        CloseHandle( mgr );
+        return;
+    }
+
+    len = sizeof(*ioctl) + nt_name.Length;
+    if (dest) len += strlen(dest) + 1;
+
+    if (!(ioctl = HeapAlloc( GetProcessHeap(), 0, len ))) return;
+    ioctl->folder_offset = sizeof(*ioctl);
+    ioctl->folder_size = nt_name.Length;
+    memcpy( (char *)ioctl + ioctl->folder_offset, nt_name.Buffer, nt_name.Length );
+    if (dest)
+    {
+        ioctl->symlink_offset = ioctl->folder_offset + ioctl->folder_size;
+        strcpy( (char *)ioctl + ioctl->symlink_offset, dest );
+    }
+    else ioctl->symlink_offset = 0;
+
+    DeviceIoControl( mgr, IOCTL_MOUNTMGR_DEFINE_SHELL_FOLDER, ioctl, len, NULL, 0, NULL, NULL );
+    HeapFree( GetProcessHeap(), 0, ioctl );
+    RtlFreeUnicodeString( &nt_name );
+}
diff --git a/programs/winecfg/theme.c b/programs/winecfg/theme.c
index b3a3eeed3ba..151dc486659 100644
--- a/programs/winecfg/theme.c
+++ b/programs/winecfg/theme.c
@@ -28,12 +28,6 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 
 #define COBJMACROS
 
@@ -765,25 +759,14 @@ static void init_shell_folder_listview_headers(HWND dialog) {
 /* Reads the currently set shell folder symbol link targets into asfiInfo. */
 static void read_shell_folder_link_targets(void) {
     WCHAR wszPath[MAX_PATH];
-    HRESULT hr;
     int i;
 
     for (i=0; i<ARRAY_SIZE(asfiInfo); i++) {
         asfiInfo[i].szLinkTarget[0] = '\0';
-        hr = SHGetFolderPathW(NULL, asfiInfo[i].nFolder|CSIDL_FLAG_DONT_VERIFY, NULL, 
-                              SHGFP_TYPE_CURRENT, wszPath);
-        if (SUCCEEDED(hr)) {
-            char *pszUnixPath = wine_get_unix_file_name(wszPath);
-            if (pszUnixPath) {
-                struct stat statPath;
-                if (!lstat(pszUnixPath, &statPath) && S_ISLNK(statPath.st_mode)) {
-                    int cLen = readlink(pszUnixPath, asfiInfo[i].szLinkTarget, FILENAME_MAX-1);
-                    if (cLen >= 0) asfiInfo[i].szLinkTarget[cLen] = '\0';
-                }
-                HeapFree(GetProcessHeap(), 0, pszUnixPath);
-            }
-        } 
-    }    
+        if (SUCCEEDED( SHGetFolderPathW( NULL, asfiInfo[i].nFolder | CSIDL_FLAG_DONT_VERIFY, NULL,
+                                         SHGFP_TYPE_CURRENT, wszPath )))
+            query_shell_folder( wszPath, asfiInfo[i].szLinkTarget, FILENAME_MAX );
+    }
 }
 
 static void update_shell_folder_listview(HWND dialog) {
@@ -904,56 +887,12 @@ static void on_shell_folder_edit_changed(HWND hDlg) {
 
 static void apply_shell_folder_changes(void) {
     WCHAR wszPath[MAX_PATH];
-    char szBackupPath[FILENAME_MAX], szUnixPath[FILENAME_MAX], *pszUnixPath = NULL;
     int i;
-    struct stat statPath;
-    HRESULT hr;
 
     for (i=0; i<ARRAY_SIZE(asfiInfo); i++) {
-        /* Ignore nonexistent link targets */
-        if (asfiInfo[i].szLinkTarget[0] && stat(asfiInfo[i].szLinkTarget, &statPath))
-            continue;
-        
-        hr = SHGetFolderPathW(NULL, asfiInfo[i].nFolder|CSIDL_FLAG_CREATE, NULL, 
-                              SHGFP_TYPE_CURRENT, wszPath);
-        if (FAILED(hr)) continue;
-
-        /* Retrieve the corresponding unix path. */
-        pszUnixPath = wine_get_unix_file_name(wszPath);
-        if (!pszUnixPath) continue;
-        lstrcpyA(szUnixPath, pszUnixPath);
-        HeapFree(GetProcessHeap(), 0, pszUnixPath);
-            
-        /* Derive name for folder backup. */
-        lstrcpyA(szBackupPath, szUnixPath);
-        lstrcatA(szBackupPath, ".winecfg");
-        
-        if (lstat(szUnixPath, &statPath)) continue;
-    
-        /* Move old folder/link out of the way. */
-        if (S_ISLNK(statPath.st_mode)) {
-            if (unlink(szUnixPath)) continue; /* Unable to remove link. */
-        } else { 
-            if (!*asfiInfo[i].szLinkTarget) {
-                continue; /* We are done. Old was real folder, as new shall be. */
-            } else { 
-                if (rename(szUnixPath, szBackupPath)) { /* Move folder out of the way. */
-                    continue; /* Unable to move old folder. */
-                }
-            }
-        }
-    
-        /* Create new link/folder. */
-        if (*asfiInfo[i].szLinkTarget) {
-            symlink(asfiInfo[i].szLinkTarget, szUnixPath);
-        } else {
-            /* If there's a backup folder, restore it. Else create new folder. */
-            if (!lstat(szBackupPath, &statPath) && S_ISDIR(statPath.st_mode)) {
-                rename(szBackupPath, szUnixPath);
-            } else {
-                mkdir(szUnixPath, 0777);
-            }
-        }
+        if (SUCCEEDED( SHGetFolderPathW( NULL, asfiInfo[i].nFolder | CSIDL_FLAG_CREATE, NULL,
+                                         SHGFP_TYPE_CURRENT, wszPath )))
+            set_shell_folder( wszPath, asfiInfo[i].szLinkTarget );
     }
 }
 
diff --git a/programs/winecfg/winecfg.h b/programs/winecfg/winecfg.h
index d022cd3d688..17516aa4a14 100644
--- a/programs/winecfg/winecfg.h
+++ b/programs/winecfg/winecfg.h
@@ -117,6 +117,8 @@ BOOL add_drive(char letter, const char *targetpath, const char *device,
                const WCHAR *label, DWORD serial, DWORD type);
 void delete_drive(struct drive *pDrive);
 void apply_drive_changes(void);
+void query_shell_folder( const WCHAR *path, char *dest, unsigned int len );
+void set_shell_folder( const WCHAR *path, const char *dest );
 BOOL browse_for_unix_folder(HWND dialog, WCHAR *pszPath);
 extern struct drive drives[26]; /* one for each drive letter */
 




More information about the wine-cvs mailing list