diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2025-02-26 20:12:09 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2025-02-26 20:12:09 +0100 |
commit | 809c212093709d4f593fa301edbe2db119dd8afa (patch) | |
tree | 5d319c13a1bafd0dad79d58319a7a95defd1e414 | |
parent | 323729f654ae3524642115ed35330819f647a023 (diff) | |
download | newlib-809c212093709d4f593fa301edbe2db119dd8afa.zip newlib-809c212093709d4f593fa301edbe2db119dd8afa.tar.gz newlib-809c212093709d4f593fa301edbe2db119dd8afa.tar.bz2 |
Cygwin: fhandler_netdrive: try harder to find shares of weird providers
For some provider types, WNetGetResourceInformationW fails, namely
WNNC_NET_DAV. When that happens, try to find the server's provider
by enumerating all WNet containers from the top.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r-- | winsup/cygwin/fhandler/netdrive.cc | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/winsup/cygwin/fhandler/netdrive.cc b/winsup/cygwin/fhandler/netdrive.cc index 345ebdd..9fcbc82 100644 --- a/winsup/cygwin/fhandler/netdrive.cc +++ b/winsup/cygwin/fhandler/netdrive.cc @@ -266,6 +266,44 @@ out: return 0; } +#define NO_PROVIDER_FOUND 1 + +static DWORD +wnet_find_server (wchar_t *srv_name, LPNETRESOURCEW nro, bool start) +{ + DWORD wres, cnt, size; + DWORD provider = NO_PROVIDER_FOUND; + HANDLE dom; + + wres = WNetOpenEnumW (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, + RESOURCEUSAGE_CONTAINER, start ? NULL : nro, &dom); + if (wres != NO_ERROR) + return NO_PROVIDER_FOUND; + while ((wres = WNetEnumResourceW (dom, (cnt = 1, &cnt), nro, + (size = NT_MAX_PATH, &size))) == NO_ERROR) + { + NETINFOSTRUCT netinfo = { 0 }; + netinfo.cbStructure = sizeof netinfo; + wres = WNetGetNetworkInformationW (nro->lpProvider, &netinfo); + if (wres != NO_ERROR) + continue; + /* Do not even try to enumerate SMB servers! It takes 10 seconds just to + return with error 1208 ERROR_EXTENDED_ERROR, with extended error info + "The list of servers for this workgroup is not currently available". */ + if ((nro->dwDisplayType == RESOURCEDISPLAYTYPE_NETWORK + || nro->dwDisplayType == RESOURCEDISPLAYTYPE_DOMAIN) + && ((DWORD) netinfo.wNetType << 16) != WNNC_NET_SMB) + provider = wnet_find_server (srv_name, nro, false); + else if (nro->dwDisplayType == RESOURCEDISPLAYTYPE_SERVER + && !wcscasecmp (srv_name, nro->lpRemoteName)) + provider = ((DWORD) netinfo.wNetType << 16); + if (provider != NO_PROVIDER_FOUND) + break; + } + WNetCloseEnum (dom); + return provider; +} + static DWORD thread_netdrive_wnet (void *arg) { @@ -309,16 +347,16 @@ thread_netdrive_wnet (void *arg) (size = NT_MAX_PATH, &size), &dummy); if (wres != NO_ERROR) { - /* WNetGetResourceInformationW fails for WebDAV server names. - We don't want a "No such file or directory" in this case, but since - neither WNetGetResourceInformationW, nor WNetGetProviderNameW works - for them, we have to skip the error message heuristically... - FIXME: While WNetGetResourceInformationW fails, enumerating the - entire WNet namespace recursively down to the server level will - actually show the connected WebDAV servers. */ - if (wres != ERROR_BAD_NET_NAME || !wcschr (srv_name, L'@')) - ndi->err = geterrno_from_win_error (wres); - goto out; + /* WNetGetResourceInformationW fails for instance for WebDAV server + names, even if we have connected resources on the server. We don't + want a "No such file or directory" in this case, so try to find the + server by WNet enumerating from the top. */ + ndi->provider = wnet_find_server (srv_name, nro, true); + if (ndi->provider == NO_PROVIDER_FOUND) + { + ndi->err = geterrno_from_win_error (wres); + goto out; + } } if (ndi->provider) @@ -334,6 +372,10 @@ thread_netdrive_wnet (void *arg) /* More heuristics... */ switch (net_type) { + case 0: + case NO_PROVIDER_FOUND: + /* Nothing to enumerate. */ + goto out; case WNNC_NET_MS_NFS: /* If ndi->provider is 0 and the machine name contains dots, we already handled NFS. However, if the machine supports both, NFS and SMB, |