* autoload.cc (WNetGetProviderNameA): Define.

(WNetGetResourceParentA): Remove.
	* fhandler_netdrive.cc (struct net_hdls): New structure to keep
	WNet handles.  Stored in dir->__handle throughout.
	(thread_netdrive): Rewrite to enumerate all servers in all accessible
	domains and workgroups.
	(fhandler_netdrive::readdir): Simplify toplevel code.  Lowercase all
	server names in toplevel.
	(fhandler_netdrive::rewinddir): Close all WNet handles and free
	net_hdls structure.
This commit is contained in:
Corinna Vinschen 2008-07-19 12:26:09 +00:00
parent b47d83c645
commit 5a3ed02610
3 changed files with 101 additions and 34 deletions

View File

@ -1,3 +1,16 @@
2008-07-19 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (WNetGetProviderNameA): Define.
(WNetGetResourceParentA): Remove.
* fhandler_netdrive.cc (struct net_hdls): New structure to keep
WNet handles. Stored in dir->__handle throughout.
(thread_netdrive): Rewrite to enumerate all servers in all accessible
domains and workgroups.
(fhandler_netdrive::readdir): Simplify toplevel code. Lowercase all
server names in toplevel.
(fhandler_netdrive::rewinddir): Close all WNet handles and free
net_hdls structure.
2008-07-18 Corinna Vinschen <corinna@vinschen.de> 2008-07-18 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_base::open): Rename x to fh. On Samba, always * fhandler.cc (fhandler_base::open): Rename x to fh. On Samba, always

View File

@ -438,8 +438,8 @@ LoadDLLfuncEx (waveInStart, 4, winmm, 1)
LoadDLLfuncEx (waveInReset, 4, winmm, 1) LoadDLLfuncEx (waveInReset, 4, winmm, 1)
LoadDLLfuncEx (waveInClose, 4, winmm, 1) LoadDLLfuncEx (waveInClose, 4, winmm, 1)
LoadDLLfunc (WNetGetProviderNameA, 12, mpr)
LoadDLLfunc (WNetGetResourceInformationA, 16, mpr) LoadDLLfunc (WNetGetResourceInformationA, 16, mpr)
LoadDLLfunc (WNetGetResourceParentA, 12, mpr)
LoadDLLfunc (WNetOpenEnumA, 20, mpr) LoadDLLfunc (WNetOpenEnumA, 20, mpr)
LoadDLLfunc (WNetEnumResourceA, 16, mpr) LoadDLLfunc (WNetEnumResourceA, 16, mpr)
LoadDLLfunc (WNetCloseEnum, 4, mpr) LoadDLLfunc (WNetCloseEnum, 4, mpr)

View File

@ -14,6 +14,8 @@ details. */
#include "security.h" #include "security.h"
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "cygthread.h" #include "cygthread.h"
#include <winnetwk.h> #include <winnetwk.h>
@ -37,14 +39,20 @@ struct netdriveinf
HANDLE sem; HANDLE sem;
}; };
struct net_hdls
{
HANDLE net;
HANDLE dom;
};
static DWORD WINAPI static DWORD WINAPI
thread_netdrive (void *arg) thread_netdrive (void *arg)
{ {
netdriveinf *ndi = (netdriveinf *) arg; netdriveinf *ndi = (netdriveinf *) arg;
LPTSTR dummy = NULL; char provider[256], *dummy = NULL;
LPNETRESOURCE nro, nro2; LPNETRESOURCE nro;
DWORD size; DWORD cnt, size;
HANDLE enumhdl; struct net_hdls *nh;
ReleaseSemaphore (ndi->sem, 1, NULL); ReleaseSemaphore (ndi->sem, 1, NULL);
switch (ndi->what) switch (ndi->what)
@ -54,29 +62,74 @@ thread_netdrive (void *arg)
ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in, ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in,
nro, &size, &dummy); nro, &size, &dummy);
break; break;
case GET_RESOURCE_OPENENUM:
case GET_RESOURCE_OPENENUMTOP: case GET_RESOURCE_OPENENUMTOP:
nro = (LPNETRESOURCE) alloca (size = 4096); nro = (LPNETRESOURCE) alloca (size = 4096);
nh = (struct net_hdls *) ndi->out;
ndi->ret = WNetGetProviderName (WNNC_NET_LANMAN, provider,
(size = 256, &size));
if (ndi->ret != NO_ERROR)
break;
memset (nro, 0, sizeof *nro);
nro->dwScope = RESOURCE_GLOBALNET;
nro->dwType = RESOURCETYPE_ANY;
nro->dwDisplayType = RESOURCEDISPLAYTYPE_GROUP;
nro->dwUsage = RESOURCEUSAGE_RESERVED | RESOURCEUSAGE_CONTAINER;
nro->lpRemoteName = provider;
nro->lpProvider = provider;
ndi->ret = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_ALL, nro, &nh->net);
if (ndi->ret != NO_ERROR)
break;
while ((ndi->ret = WNetEnumResource (nh->net, (cnt = 1, &cnt), nro,
(size = 4096, &size))) == NO_ERROR)
{
ndi->ret = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_ALL, nro, &nh->dom);
if (ndi->ret == NO_ERROR)
break;
}
break;
case GET_RESOURCE_OPENENUM:
nro = (LPNETRESOURCE) alloca (size = 4096);
nh = (struct net_hdls *) ndi->out;
ndi->ret = WNetGetProviderName (WNNC_NET_LANMAN, provider,
(size = 256, &size));
if (ndi->ret != NO_ERROR)
break;
((LPNETRESOURCE) ndi->in)->lpProvider = provider;
ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in, ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in,
nro, &size, &dummy); nro, &size, &dummy);
if (ndi->ret != NO_ERROR) if (ndi->ret != NO_ERROR)
break; break;
if (ndi->what == GET_RESOURCE_OPENENUMTOP) ndi->ret = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_ALL, nro, &nh->dom);
break;
case GET_RESOURCE_ENUM:
nh = (struct net_hdls *) ndi->in;
if (!nh->dom)
{
ndi->ret = ERROR_NO_MORE_ITEMS;
break;
}
while ((ndi->ret = WNetEnumResource (nh->dom, (cnt = 1, &cnt),
(LPNETRESOURCE) ndi->out,
&ndi->outsize)) != NO_ERROR
&& nh->net)
{ {
nro2 = nro; WNetCloseEnum (nh->dom);
nh->dom = NULL;
nro = (LPNETRESOURCE) alloca (size = 4096); nro = (LPNETRESOURCE) alloca (size = 4096);
ndi->ret = WNetGetResourceParent (nro2, nro, &size); while ((ndi->ret = WNetEnumResource (nh->net, (cnt = 1, &cnt), nro,
(size = 4096, &size))) == NO_ERROR)
{
ndi->ret = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
RESOURCEUSAGE_ALL, nro, &nh->dom);
if (ndi->ret == NO_ERROR)
break;
}
if (ndi->ret != NO_ERROR) if (ndi->ret != NO_ERROR)
break; break;
} }
ndi->ret = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, nro,
&enumhdl);
if (ndi->ret == NO_ERROR)
*(HANDLE *) ndi->out = enumhdl;
break;
case GET_RESOURCE_ENUM:
ndi->ret = WNetEnumResource ((HANDLE) ndi->in, (size = 1, &size),
(LPNETRESOURCE) ndi->out, &ndi->outsize);
break; break;
} }
ReleaseSemaphore (ndi->sem, 1, NULL); ReleaseSemaphore (ndi->sem, 1, NULL);
@ -145,7 +198,6 @@ fhandler_netdrive::fstat (struct __stat64 *buf)
int int
fhandler_netdrive::readdir (DIR *dir, dirent *de) fhandler_netdrive::readdir (DIR *dir, dirent *de)
{ {
DWORD size;
NETRESOURCE *nro; NETRESOURCE *nro;
DWORD ret; DWORD ret;
int res; int res;
@ -153,21 +205,11 @@ fhandler_netdrive::readdir (DIR *dir, dirent *de)
if (!dir->__d_position) if (!dir->__d_position)
{ {
size_t len = strlen (get_name ()); size_t len = strlen (get_name ());
char *namebuf; char *namebuf = NULL;
NETRESOURCE nr = { 0 }; NETRESOURCE nr = { 0 };
struct net_hdls *nh;
if (len == 2) /* // */ if (len != 2) /* // */
{
namebuf = (char *) alloca (MAX_COMPUTERNAME_LENGTH + 3);
strcpy (namebuf, "\\\\");
size = MAX_COMPUTERNAME_LENGTH + 1;
if (!GetComputerName (namebuf + 2, &size))
{
res = geterrno_from_win_error ();
goto out;
}
}
else
{ {
const char *from; const char *from;
char *to; char *to;
@ -180,15 +222,17 @@ fhandler_netdrive::readdir (DIR *dir, dirent *de)
nr.lpRemoteName = namebuf; nr.lpRemoteName = namebuf;
nr.dwType = RESOURCETYPE_DISK; nr.dwType = RESOURCETYPE_DISK;
nro = (NETRESOURCE *) alloca (4096); nro = (NETRESOURCE *) alloca (4096);
nh = (struct net_hdls *) ccalloc (HEAP_FHANDLER, 1, sizeof *nh);
ret = create_thread_and_wait (len == 2 ? GET_RESOURCE_OPENENUMTOP ret = create_thread_and_wait (len == 2 ? GET_RESOURCE_OPENENUMTOP
: GET_RESOURCE_OPENENUM, : GET_RESOURCE_OPENENUM,
&nr, &dir->__handle, 0, "WNetOpenEnum"); &nr, nh, 0, "WNetOpenEnum");
if (ret != NO_ERROR) if (ret != NO_ERROR)
{ {
dir->__handle = INVALID_HANDLE_VALUE; dir->__handle = INVALID_HANDLE_VALUE;
res = geterrno_from_win_error (ret); res = geterrno_from_win_error (ret);
goto out; goto out;
} }
dir->__handle = (HANDLE) nh;
} }
ret = create_thread_and_wait (GET_RESOURCE_ENUM, dir->__handle, ret = create_thread_and_wait (GET_RESOURCE_ENUM, dir->__handle,
nro = (LPNETRESOURCE) alloca (16384), nro = (LPNETRESOURCE) alloca (16384),
@ -201,7 +245,10 @@ fhandler_netdrive::readdir (DIR *dir, dirent *de)
char *bs = strrchr (nro->lpRemoteName, '\\'); char *bs = strrchr (nro->lpRemoteName, '\\');
strcpy (de->d_name, bs ? bs + 1 : nro->lpRemoteName); strcpy (de->d_name, bs ? bs + 1 : nro->lpRemoteName);
if (strlen (get_name ()) == 2) if (strlen (get_name ()) == 2)
de->d_ino = hash_path_name (get_ino (), de->d_name); {
strlwr (de->d_name);
de->d_ino = hash_path_name (get_ino (), de->d_name);
}
else else
{ {
de->d_ino = readdir_get_ino (nro->lpRemoteName, false); de->d_ino = readdir_get_ino (nro->lpRemoteName, false);
@ -234,7 +281,14 @@ void
fhandler_netdrive::rewinddir (DIR *dir) fhandler_netdrive::rewinddir (DIR *dir)
{ {
if (dir->__handle != INVALID_HANDLE_VALUE) if (dir->__handle != INVALID_HANDLE_VALUE)
WNetCloseEnum (dir->__handle); {
struct net_hdls *nh = (struct net_hdls *) dir->__handle;
if (nh->dom)
WNetCloseEnum (nh->dom);
if (nh->net)
WNetCloseEnum (nh->net);
cfree (nh);
}
dir->__handle = INVALID_HANDLE_VALUE; dir->__handle = INVALID_HANDLE_VALUE;
return fhandler_virtual::rewinddir (dir); return fhandler_virtual::rewinddir (dir);
} }