]> Savannah Git Hosting - gnulib.git/commitdiff
mountlist: Improve implementation on native Windows.
authorBruno Haible <bruno@clisp.org>
Wed, 19 Mar 2025 11:10:05 +0000 (12:10 +0100)
committerBruno Haible <bruno@clisp.org>
Wed, 19 Mar 2025 11:10:05 +0000 (12:10 +0100)
* lib/mountlist.c (read_file_system_list) [_WIN32 && !__CYGWIN__]:
Return the mntroot of drives mapped by SUBST or NET USE.

ChangeLog
lib/mountlist.c

index eb80449b85698645dd9525c30ca1dfdbb480f596..c33496dec9890b16262d23715e7883bf959ff12d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2025-03-19  Bruno Haible  <bruno@clisp.org>
 
+       mountlist: Improve implementation on native Windows.
+       * lib/mountlist.c (read_file_system_list) [_WIN32 && !__CYGWIN__]:
+       Return the mntroot of drives mapped by SUBST or NET USE.
+
        mountlist: Improve implementation on native Windows.
        * lib/mountlist.c (read_file_system_list) [_WIN32 && !__CYGWIN__]:
        Filter out those volumes for which GetVolumeInformation fails.
index 1385db43fddc0a4530c7e19e6f30baf859692ff3..23ebdf675068419e95e9840cc0b37df9fd8e820c 100644 (file)
@@ -1131,8 +1131,58 @@ read_file_system_list (bool need_fs_type)
                 /* Check if drive is remote.  See:
                    <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdrivetypea>.  */
                 me->me_remote = GetDriveType (mountdir) == DRIVE_REMOTE;
+                /* Here we could use
+                   QueryDosDeviceW -> returns something like '\Device\HarddiskVolume2'
+                   GetVolumeNameForVolumeMountPointW -> return something like '\\?\Volume{...}'
+                 */
                 me->me_devname = NULL;
-                me->me_mntroot = NULL;
+                {
+                  /* Find the SUBST or NET USE mapping of the given drive.
+                     <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-querydosdevicew>
+                     For testing of SUBST:   <https://ss64.com/nt/subst.html>
+                     For testing of NET USE: <https://ss64.com/nt/net-use.html>  */
+                  wchar_t drive[3];
+                  wchar_t mapping[MAX_PATH + 1];
+                  drive[0] = L'A' + i;
+                  drive[1] = L':';
+                  drive[2] = L'\0';
+                  DWORD mapping_len = QueryDosDeviceW (drive, mapping, sizeof (mapping) / sizeof (mapping[0]));
+                  if (mapping_len > 4 && wcsncmp (mapping, L"\\??\\", 4) == 0)
+                    {
+                      /* It's a SUBSTed drive.  */
+                      char subst_dir[MAX_PATH + 1];
+                      size_t subst_dir_len = wcstombs (subst_dir, mapping + 4, sizeof (subst_dir));
+                      if (subst_dir_len > 0 && subst_dir_len <= MAX_PATH)
+                        me->me_mntroot = xstrdup (subst_dir);
+                      else
+                        /* mapping is too long or not convertible to the
+                           locale encoding.  */
+                        me->me_mntroot = NULL;
+                    }
+                  else if (mapping_len > 26
+                           && wcsncmp (mapping, L"\\Device\\LanmanRedirector\\;", 26) == 0)
+                    {
+                      wchar_t *next_backslash = wcschr (mapping + 26, L'\\');
+                      if (next_backslash != NULL)
+                        {
+                          *--next_backslash = L'\\';
+                          char share_dir[MAX_PATH + 1];
+                          size_t share_dir_len = wcstombs (share_dir, next_backslash, sizeof (share_dir));
+                          if (share_dir_len > 0 && share_dir_len <= MAX_PATH)
+                            me->me_mntroot = xstrdup (share_dir);
+                          else
+                            /* mapping is too long or not convertible to the
+                               locale encoding.  */
+                            me->me_mntroot = NULL;
+                        }
+                      else
+                        /* mapping does not have the expected form.  */
+                        me->me_mntroot = NULL;
+                    }
+                  else
+                    /* It's neither a SUBSTed nor a NET USEd drive.  */
+                    me->me_mntroot = NULL;
+                }
                 me->me_dev = (dev_t) -1;
                 me->me_dummy = 0;
                 me->me_type = xstrdup (fs_name);