* fhandler.h (class fhandler_netdrive): Add method rewinddir.
* fhandler_netdrive.cc (struct netdriveinf): New structure to store thread arguments. (thread_netdrive): Thread handling all potentially blocking WNet... calls. (create_thread_and_wait): Start and wait for above thread. (fhandler_netdrive::exists): Change to call create_thread_and_wait instead of calling WNet... function. (fhandler_netdrive::readdir): Ditto. Fix error handling. (fhandler_netdrive::rewinddir): New method.
This commit is contained in:
		| @@ -1,3 +1,16 @@ | |||||||
|  | 2005-05-17  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* fhandler.h (class fhandler_netdrive): Add method rewinddir. | ||||||
|  | 	* fhandler_netdrive.cc (struct netdriveinf): New structure to | ||||||
|  | 	store thread arguments. | ||||||
|  | 	(thread_netdrive): Thread handling all potentially blocking | ||||||
|  | 	WNet... calls. | ||||||
|  | 	(create_thread_and_wait): Start and wait for above thread. | ||||||
|  | 	(fhandler_netdrive::exists): Change to call create_thread_and_wait | ||||||
|  | 	instead of calling WNet... function. | ||||||
|  | 	(fhandler_netdrive::readdir): Ditto.  Fix error handling. | ||||||
|  | 	(fhandler_netdrive::rewinddir): New method. | ||||||
|  |  | ||||||
| 2005-05-17  Corinna Vinschen  <corinna@vinschen.de> | 2005-05-17  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* external.cc (cygwin_internal): Avoid compiler warning. | 	* external.cc (cygwin_internal): Avoid compiler warning. | ||||||
|   | |||||||
| @@ -1222,6 +1222,7 @@ class fhandler_netdrive: public fhandler_virtual | |||||||
|   struct dirent *readdir (DIR *); |   struct dirent *readdir (DIR *); | ||||||
|   _off64_t telldir (DIR *); |   _off64_t telldir (DIR *); | ||||||
|   void seekdir (DIR *, _off64_t); |   void seekdir (DIR *, _off64_t); | ||||||
|  |   void rewinddir (DIR *); | ||||||
|   int closedir (DIR *); |   int closedir (DIR *); | ||||||
|   int open (int flags, mode_t mode = 0); |   int open (int flags, mode_t mode = 0); | ||||||
|   int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); |   int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); | ||||||
|   | |||||||
| @@ -18,11 +18,90 @@ details. */ | |||||||
| #include "fhandler.h" | #include "fhandler.h" | ||||||
| #include "dtable.h" | #include "dtable.h" | ||||||
| #include "cygheap.h" | #include "cygheap.h" | ||||||
|  | #include "sigproc.h" | ||||||
|  | #include "cygthread.h" | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <winnetwk.h> | #include <winnetwk.h> | ||||||
|  |  | ||||||
| #include <dirent.h> | #include <dirent.h> | ||||||
|  |  | ||||||
|  | enum | ||||||
|  |   { | ||||||
|  |     GET_RESOURCE_INFO = 0, | ||||||
|  |     GET_RESOURCE_OPENENUM = 1, | ||||||
|  |     GET_RESOURCE_OPENENUMTOP = 2, | ||||||
|  |     GET_RESOURCE_ENUM = 3 | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  | struct netdriveinf | ||||||
|  |   { | ||||||
|  |     int what; | ||||||
|  |     int ret; | ||||||
|  |     PVOID in; | ||||||
|  |     PVOID out; | ||||||
|  |     DWORD outsize; | ||||||
|  |     HANDLE sem; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  | static DWORD WINAPI | ||||||
|  | thread_netdrive (void *arg) | ||||||
|  | { | ||||||
|  |   netdriveinf *ndi = (netdriveinf *) arg; | ||||||
|  |   LPTSTR dummy = NULL; | ||||||
|  |   LPNETRESOURCE nro, nro2; | ||||||
|  |   DWORD size; | ||||||
|  |   HANDLE enumhdl; | ||||||
|  |  | ||||||
|  |   ReleaseSemaphore (ndi->sem, 1, NULL); | ||||||
|  |   switch (ndi->what) | ||||||
|  |     { | ||||||
|  |     case GET_RESOURCE_INFO: | ||||||
|  |       nro = (LPNETRESOURCE) alloca (size = 4096); | ||||||
|  |       ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in, | ||||||
|  | 					     nro, &size, &dummy); | ||||||
|  |       break; | ||||||
|  |     case GET_RESOURCE_OPENENUM: | ||||||
|  |     case GET_RESOURCE_OPENENUMTOP: | ||||||
|  |       nro = (LPNETRESOURCE) alloca (size = 4096); | ||||||
|  |       ndi->ret = WNetGetResourceInformation ((LPNETRESOURCE) ndi->in, | ||||||
|  | 					     nro, &size, &dummy); | ||||||
|  |       if (ndi->ret != NO_ERROR) | ||||||
|  |         break; | ||||||
|  |       if (ndi->what == GET_RESOURCE_OPENENUMTOP) | ||||||
|  |         { | ||||||
|  | 	  nro2 = nro; | ||||||
|  | 	  nro = (LPNETRESOURCE) alloca (size = 4096); | ||||||
|  | 	  ndi->ret = WNetGetResourceParent (nro2, nro, &size); | ||||||
|  | 	  if (ndi->ret != NO_ERROR) | ||||||
|  | 	    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; | ||||||
|  |     } | ||||||
|  |   ReleaseSemaphore (ndi->sem, 1, NULL); | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static DWORD | ||||||
|  | create_thread_and_wait (int what, PVOID in, PVOID out, DWORD outsize, | ||||||
|  | 			const char *name) | ||||||
|  | { | ||||||
|  |   netdriveinf ndi = { what, 0, in, out, outsize, | ||||||
|  | 		      CreateSemaphore (&sec_none_nih, 0, 2, NULL) }; | ||||||
|  |   cygthread *thr = new cygthread (thread_netdrive, (LPVOID) &ndi, name); | ||||||
|  |   if (thr->detach (ndi.sem)) | ||||||
|  |     ndi.ret = ERROR_OPERATION_ABORTED; | ||||||
|  |   CloseHandle (ndi.sem); | ||||||
|  |   return ndi.ret; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Returns 0 if path doesn't exist, >0 if path is a directory, | /* Returns 0 if path doesn't exist, >0 if path is a directory, | ||||||
|    -1 if path is a file, -2 if it's a symlink.  */ |    -1 if path is a file, -2 if it's a symlink.  */ | ||||||
| int | int | ||||||
| @@ -43,11 +122,9 @@ fhandler_netdrive::exists () | |||||||
|   nr.dwType = RESOURCETYPE_DISK; |   nr.dwType = RESOURCETYPE_DISK; | ||||||
|   nr.lpLocalName = NULL; |   nr.lpLocalName = NULL; | ||||||
|   nr.lpRemoteName = namebuf; |   nr.lpRemoteName = namebuf; | ||||||
|   LPTSTR sys = NULL; |   DWORD ret = create_thread_and_wait (GET_RESOURCE_INFO, &nr, NULL, 0, | ||||||
|   char buf[8192]; | 				      "WnetGetResourceInformation"); | ||||||
|   DWORD n = sizeof (buf); |   if (ret != ERROR_MORE_DATA && ret != NO_ERROR) | ||||||
|   DWORD rc = WNetGetResourceInformation (&nr, &buf, &n, &sys); |  | ||||||
|   if (rc != ERROR_MORE_DATA && rc != NO_ERROR) |  | ||||||
|     return 0; |     return 0; | ||||||
|   return 1; |   return 1; | ||||||
| } | } | ||||||
| @@ -80,8 +157,8 @@ fhandler_netdrive::readdir (DIR *dir) | |||||||
|   if (!dir->__d_position) |   if (!dir->__d_position) | ||||||
|     { |     { | ||||||
|       size_t len = strlen (get_name ()); |       size_t len = strlen (get_name ()); | ||||||
|       char *namebuf, *dummy; |       char *namebuf; | ||||||
|       NETRESOURCE nr = { 0 }, *nro2; |       NETRESOURCE nr = { 0 }; | ||||||
|  |  | ||||||
|       if (len == 2)	/* // */ |       if (len == 2)	/* // */ | ||||||
|         { |         { | ||||||
| @@ -106,44 +183,24 @@ fhandler_netdrive::readdir (DIR *dir) | |||||||
|  |  | ||||||
|       nr.lpRemoteName = namebuf; |       nr.lpRemoteName = namebuf; | ||||||
|       nr.dwType = RESOURCETYPE_DISK; |       nr.dwType = RESOURCETYPE_DISK; | ||||||
|       size = 4096; |       nro = (NETRESOURCE *) alloca (4096); | ||||||
|       nro = (NETRESOURCE *) alloca (size); |       ret = create_thread_and_wait (len == 2 ? GET_RESOURCE_OPENENUMTOP | ||||||
|       ret = WNetGetResourceInformation (&nr, nro, &size, &dummy); | 					     : GET_RESOURCE_OPENENUM, | ||||||
|  | 				    &nr, &dir->__handle, 0, "WNetOpenEnum"); | ||||||
|       if (ret != NO_ERROR) |       if (ret != NO_ERROR) | ||||||
| 	{ | 	{ | ||||||
| 	  __seterrno (); | 	  __seterrno_from_win_error (ret); | ||||||
| 	  return NULL; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|       if (len == 2) |  | ||||||
|         { |  | ||||||
| 	  nro2 = nro; |  | ||||||
| 	  size = 4096; |  | ||||||
| 	  nro = (NETRESOURCE *) alloca (size); |  | ||||||
| 	  ret = WNetGetResourceParent (nro2, nro, &size); |  | ||||||
| 	  if (ret != NO_ERROR) |  | ||||||
| 	    { |  | ||||||
| 	      __seterrno (); |  | ||||||
| 	      return NULL; |  | ||||||
| 	    } |  | ||||||
| 	} |  | ||||||
|       ret = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, |  | ||||||
|       			 nro, &dir->__handle); |  | ||||||
|       if (ret != NO_ERROR) |  | ||||||
| 	{ |  | ||||||
| 	  __seterrno (); |  | ||||||
| 	  dir->__handle = INVALID_HANDLE_VALUE; | 	  dir->__handle = INVALID_HANDLE_VALUE; | ||||||
| 	  return NULL; | 	  return NULL; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|   DWORD cnt = 1; |   ret = create_thread_and_wait (GET_RESOURCE_ENUM, dir->__handle, | ||||||
|   size = 16384;	/* As documented in MSDN. */ |   				nro = (LPNETRESOURCE) alloca (16384), | ||||||
|   nro = (NETRESOURCE *) alloca (size); | 				16384, "WnetEnumResource"); | ||||||
|   ret = WNetEnumResource (dir->__handle, &cnt, nro, &size); |  | ||||||
|   if (ret != NO_ERROR) |   if (ret != NO_ERROR) | ||||||
|     { |     { | ||||||
|       if (ret != ERROR_NO_MORE_ITEMS) |       if (ret != ERROR_NO_MORE_ITEMS) | ||||||
| 	__seterrno (); | 	__seterrno_from_win_error (ret); | ||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
|   dir->__d_position++; |   dir->__d_position++; | ||||||
| @@ -163,6 +220,15 @@ fhandler_netdrive::seekdir (DIR *, _off64_t) | |||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | fhandler_netdrive::rewinddir (DIR *dir) | ||||||
|  | { | ||||||
|  |   if (dir->__handle != INVALID_HANDLE_VALUE) | ||||||
|  |     WNetCloseEnum (dir->__handle); | ||||||
|  |   dir->__handle = INVALID_HANDLE_VALUE; | ||||||
|  |   return fhandler_virtual::rewinddir (dir); | ||||||
|  | } | ||||||
|  |  | ||||||
| int | int | ||||||
| fhandler_netdrive::closedir (DIR *dir) | fhandler_netdrive::closedir (DIR *dir) | ||||||
| { | { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user