Does this patch cover global mounts, i.e. SMB mounted by user
LocalSystem on a driver letter are visible to ALL users. Local users
logons can override the same drive letter via per-user net use

Example:
LocalSystem mounts H: to \\homeserver\disk4\users, this is visible to
all users in a system
User "lionel" mounts H: to \\lionelsserver\data\homedir, this is
visible to the current Logon session

Lionel

On Tue, 18 Feb 2025 at 22:25, Jeremy Drake via Cygwin-patches
<cygwin-patches@cygwin.com> wrote:
>
> After migrating from GetLogicalDrives to Find(First|Next)VolumeW, mapped
> network drives no longer showed up in getmntent output.  To fix that,
> also iterate GetLogicalDriveStringsW when builing dos_drive_mappings,
> and merge with volume mounts (skipping any volume mounts that are just
> mounted on the root of a drive, and replacing the dos mounts in the
> mapping for a volume which is mounted on both a drive root and a
> directory).
>
> Fixes: 04a5b072940cc ("Cygwin: expose all windows volume mount points.")
> Addresses: https://cygwin.com/pipermail/cygwin/2025-February/257384.html
> Signed-off-by: Jeremy Drake <cyg...@jdrake.com>
> ---
>
> This was generated on top of the patch
> https://cygwin.com/pipermail/cygwin-patches/2025q1/013390.html but should
> be able to be applied without it.
>
>  winsup/cygwin/mount.cc | 145 ++++++++++++++++++++++++++++++++---------
>  1 file changed, 113 insertions(+), 32 deletions(-)
>
> diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
> index a3d9e5bd0f..68414f13af 100644
> --- a/winsup/cygwin/mount.cc
> +++ b/winsup/cygwin/mount.cc
> @@ -1995,6 +1995,40 @@ endmntent (FILE *)
>    return 1;
>  }
>
> +static bool
> +resolve_dos_device (const wchar_t *dosname, wchar_t *devpath)
> +{
> +  if (QueryDosDeviceW (dosname, devpath, NT_MAX_PATH))
> +    {
> +      /* The DOS drive mapping can be another symbolic link.  If so,
> +        the mapping won't work since the section name is the name
> +        after resolving all symlinks.  Resolve symlinks here, too. */
> +      for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
> +       {
> +         UNICODE_STRING upath;
> +         OBJECT_ATTRIBUTES attr;
> +         NTSTATUS status;
> +         HANDLE h;
> +
> +         RtlInitUnicodeString (&upath, devpath);
> +         InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
> +                                     NULL, NULL);
> +         status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY, &attr);
> +         if (!NT_SUCCESS (status))
> +           break;
> +         RtlInitEmptyUnicodeString (&upath, devpath, (NT_MAX_PATH - 1)
> +                                                     * sizeof (WCHAR));
> +         status = NtQuerySymbolicLinkObject (h, &upath, NULL);
> +         NtClose (h);
> +         if (!NT_SUCCESS (status))
> +           break;
> +         devpath[upath.Length / sizeof (WCHAR)] = L'\0';
> +       }
> +      return true;
> +    }
> +  return false;
> +}
> +
>  dos_drive_mappings::dos_drive_mappings ()
>  : mappings(0)
>  , cur_mapping(0)
> @@ -2004,6 +2038,44 @@ dos_drive_mappings::dos_drive_mappings ()
>    wchar_t vol[64]; /* Long enough for Volume GUID string */
>    wchar_t *devpath = tp.w_get ();
>    wchar_t *mounts = tp.w_get ();
> +  mapping **nextm = &mappings;
> +  mapping *endfirstloop = NULL;
> +  DWORD len;
> +
> +  /* Iterate over all drive letters, fetch the DOS device path */
> +  if (!(len = GetLogicalDriveStringsW (NT_MAX_PATH - 1, mounts)) ||
> +      len >= NT_MAX_PATH)
> +    debug_printf ("GetLogicalDriveStringsW, %E");
> +  else {
> +    for (wchar_t *mount = mounts; *mount; mount += len + 2)
> +      {
> +       len = wcslen (mount);
> +       mount[--len] = L'\0'; /* Drop trailing backslash */
> +       if (resolve_dos_device (mount, devpath))
> +         {
> +           mapping *m = new mapping ();
> +           if (m)
> +             {
> +               m->dos.path = wcsdup (mount);
> +               m->ntdevpath = wcsdup (devpath);
> +               if (!m->dos.path || !m->ntdevpath)
> +                 {
> +                   free (m->dos.path);
> +                   free (m->ntdevpath);
> +                   delete m;
> +                   continue;
> +                 }
> +               m->dos.len = len;
> +               m->ntlen = wcslen (m->ntdevpath);
> +               *nextm = endfirstloop = m;
> +               nextm = &m->next;
> +             }
> +         }
> +       else
> +         debug_printf ("Unable to determine the native mapping for %ls "
> +                       "(error %E)", mount);
> +      }
> +  }
>
>    /* Iterate over all volumes, fetch the list of DOS paths the volume is
>       mounted to. */
> @@ -2011,43 +2083,22 @@ dos_drive_mappings::dos_drive_mappings ()
>    if (sh == INVALID_HANDLE_VALUE)
>      debug_printf ("FindFirstVolumeW, %E");
>    else {
> -    mapping **nextm = &mappings;
>      do
>        {
> -       /* Skip drives which are not mounted. */
> -       DWORD len;
> +       /* Skip volumes which are not mounted. */
>         if (!GetVolumePathNamesForVolumeNameW (vol, mounts, NT_MAX_PATH, &len)
>             || mounts[0] == L'\0')
>           continue;
> +       /* Skip volumes which are only mounted to the root of a drive letter:
> +          they were handled in the loop above */
> +       if (len == 5 && mounts[1] == L':' && mounts[2] == L'\\' && !mounts[3])
> +         continue;
> +
>         *wcsrchr (vol, L'\\') = L'\0';
> -       if (QueryDosDeviceW (vol + 4, devpath, NT_MAX_PATH))
> +       if (resolve_dos_device (vol + 4, devpath))
>           {
> -           /* The DOS drive mapping can be another symbolic link.  If so,
> -              the mapping won't work since the section name is the name
> -              after resolving all symlinks.  Resolve symlinks here, too. */
> -           for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
> -             {
> -               UNICODE_STRING upath;
> -               OBJECT_ATTRIBUTES attr;
> -               NTSTATUS status;
> -               HANDLE h;
> -
> -               RtlInitUnicodeString (&upath, devpath);
> -               InitializeObjectAttributes (&attr, &upath,
> -                                           OBJ_CASE_INSENSITIVE, NULL, NULL);
> -               status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY,
> -                                                  &attr);
> -               if (!NT_SUCCESS (status))
> -                 break;
> -               RtlInitEmptyUnicodeString (&upath, devpath, (NT_MAX_PATH - 1)
> -                                                           * sizeof (WCHAR));
> -               status = NtQuerySymbolicLinkObject (h, &upath, NULL);
> -               NtClose (h);
> -               if (!NT_SUCCESS (status))
> -                 break;
> -               devpath[upath.Length / sizeof (WCHAR)] = L'\0';
> -             }
>             mapping *m = new mapping ();
> +           bool hadrootmount = false;
>             if (m)
>               {
>                 /* store mount point list */
> @@ -2072,15 +2123,45 @@ dos_drive_mappings::dos_drive_mappings ()
>                     dos->path = mount;
>                     dos->len = wcslen (dos->path);
>                     dos->path[--dos->len] = L'\0'; /* Drop trailing backslash 
> */
> +                   if (dos->len == 2 && dos->path[1] == L':')
> +                     hadrootmount = true;
>                   }
>                 m->ntlen = wcslen (m->ntdevpath);
> -               *nextm = m;
> -               nextm = &m->next;
> +               if (hadrootmount)
> +               {
> +                 /* This device has already been added to the mappings list
> +                    in the first loop above, but with only the drive root
> +                    mount.  Find that entry and replace it with the complete
> +                    list of mounts. */
> +                 hadrootmount = false;
> +                 for (mapping *m2 = mappings;
> +                      endfirstloop && m2 != endfirstloop->next;
> +                      m2 = m2->next)
> +                   {
> +                     if (m->ntlen == m2->ntlen &&
> +                         !wcscmp (m->ntdevpath, m2->ntdevpath))
> +                       {
> +                         free (m2->dos.path);
> +                         m2->dos.next = m->dos.next;
> +                         m2->dos.path = m->dos.path;
> +                         m2->dos.len = m->dos.len;
> +                         free (m->ntdevpath);
> +                         delete m;
> +                         hadrootmount = true;
> +                         break;
> +                       }
> +                   }
> +               }
> +               if (!hadrootmount)
> +                 {
> +                   *nextm = m;
> +                   nextm = &m->next;
> +                 }
>               }
>           }
>         else
>           debug_printf ("Unable to determine the native mapping for %ls "
> -                       "(error %u)", vol, GetLastError ());
> +                       "(error %E)", vol);
>        }
>      while (FindNextVolumeW (sh, vol, 64));
>      FindVolumeClose (sh);
> --
> 2.48.1.windows.1
>


-- 
Lionel

Reply via email to