* fhandler.h (MAX_PARTITIONS): New definition.
(class fhandler_dev_floppy): Add partitions array member. Add close method. * fhandler_floppy.cc (fhandler_dev_floppy::fhandler_dev_floppy): Zero out partitions array. (fhandler_dev_floppy::open): Fix "entire disk" condition for call to DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO). When opening disks for writing, call DeviceIoControl (FSCTL_LOCK_VOLUME) on all affected disk partitions starting with Vista. (fhandler_dev_floppy::close): New method. (fhandler_dev_floppy::dup): Duplicate handles in partitions, if any. * wincap.h (wincaps::has_restricted_raw_disk_access): New element. * wincap.cc: Implement above element throughout.
This commit is contained in:
		| @@ -1,3 +1,19 @@ | |||||||
|  | 2011-01-11  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* fhandler.h (MAX_PARTITIONS): New definition. | ||||||
|  | 	(class fhandler_dev_floppy): Add partitions array member.  Add close | ||||||
|  | 	method. | ||||||
|  | 	* fhandler_floppy.cc (fhandler_dev_floppy::fhandler_dev_floppy): Zero | ||||||
|  | 	out partitions array. | ||||||
|  | 	(fhandler_dev_floppy::open): Fix "entire disk" condition for call to  | ||||||
|  | 	DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO). | ||||||
|  | 	When opening disks for writing, call DeviceIoControl (FSCTL_LOCK_VOLUME) | ||||||
|  | 	on all affected disk partitions starting with Vista. | ||||||
|  | 	(fhandler_dev_floppy::close): New method. | ||||||
|  | 	(fhandler_dev_floppy::dup): Duplicate handles in partitions, if any. | ||||||
|  | 	* wincap.h (wincaps::has_restricted_raw_disk_access): New element. | ||||||
|  | 	* wincap.cc: Implement above element throughout. | ||||||
|  |  | ||||||
| 2011-01-11  Yaakov Selkowitz  <yselkowitz@users.sourceforge.net> | 2011-01-11  Yaakov Selkowitz  <yselkowitz@users.sourceforge.net> | ||||||
|  |  | ||||||
| 	* termios.cc (cfgetospeed, cfgetispeed): Constify argument per POSIX. | 	* termios.cc (cfgetospeed, cfgetispeed): Constify argument per POSIX. | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| /* fhandler.h | /* fhandler.h | ||||||
|  |  | ||||||
|    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, | ||||||
|    2005, 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. |    2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. | ||||||
|  |  | ||||||
| This file is part of Cygwin. | This file is part of Cygwin. | ||||||
|  |  | ||||||
| @@ -687,11 +687,14 @@ class fhandler_dev_raw: public fhandler_base | |||||||
|   void fixup_after_exec (); |   void fixup_after_exec (); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #define MAX_PARTITIONS 15 | ||||||
|  |  | ||||||
| class fhandler_dev_floppy: public fhandler_dev_raw | class fhandler_dev_floppy: public fhandler_dev_raw | ||||||
| { | { | ||||||
|  private: |  private: | ||||||
|   _off64_t drive_size; |   _off64_t drive_size; | ||||||
|   unsigned long bytes_per_sector; |   unsigned long bytes_per_sector; | ||||||
|  |   HANDLE partitions[MAX_PARTITIONS]; | ||||||
|   struct status_flags |   struct status_flags | ||||||
|   { |   { | ||||||
|     unsigned eom_detected    : 1; |     unsigned eom_detected    : 1; | ||||||
| @@ -711,6 +714,7 @@ class fhandler_dev_floppy: public fhandler_dev_raw | |||||||
|   fhandler_dev_floppy (); |   fhandler_dev_floppy (); | ||||||
|  |  | ||||||
|   int open (int flags, mode_t mode = 0); |   int open (int flags, mode_t mode = 0); | ||||||
|  |   int close (); | ||||||
|   int dup (fhandler_base *child); |   int dup (fhandler_base *child); | ||||||
|   void __stdcall raw_read (void *ptr, size_t& ulen); |   void __stdcall raw_read (void *ptr, size_t& ulen); | ||||||
|   ssize_t __stdcall raw_write (const void *ptr, size_t ulen); |   ssize_t __stdcall raw_write (const void *ptr, size_t ulen); | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|    fhandler classes. |    fhandler classes. | ||||||
|  |  | ||||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | ||||||
|    2009 Red Hat, Inc. |    2009, 2011 Red Hat, Inc. | ||||||
|  |  | ||||||
| This file is part of Cygwin. | This file is part of Cygwin. | ||||||
|  |  | ||||||
| @@ -32,6 +32,7 @@ details. */ | |||||||
| fhandler_dev_floppy::fhandler_dev_floppy () | fhandler_dev_floppy::fhandler_dev_floppy () | ||||||
|   : fhandler_dev_raw (), status () |   : fhandler_dev_raw (), status () | ||||||
| { | { | ||||||
|  |   memset (partitions, 0, sizeof partitions); | ||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| @@ -221,12 +222,71 @@ fhandler_dev_floppy::open (int flags, mode_t) | |||||||
|          make sure we're actually allowed to read *all* of the device. |          make sure we're actually allowed to read *all* of the device. | ||||||
| 	 This is actually documented in the MSDN CreateFile man page. */ | 	 This is actually documented in the MSDN CreateFile man page. */ | ||||||
|       if (get_major () != DEV_FLOPPY_MAJOR |       if (get_major () != DEV_FLOPPY_MAJOR | ||||||
| 	  && (get_major () == DEV_CDROM_MAJOR || get_minor () == 0) | 	  && (get_major () == DEV_CDROM_MAJOR || get_minor () % 16 == 0) | ||||||
| 	  && !DeviceIoControl (get_handle (), FSCTL_ALLOW_EXTENDED_DASD_IO, | 	  && !DeviceIoControl (get_handle (), FSCTL_ALLOW_EXTENDED_DASD_IO, | ||||||
| 			       NULL, 0, NULL, 0, &bytes_read, NULL)) | 			       NULL, 0, NULL, 0, &bytes_read, NULL)) | ||||||
| 	debug_printf ("DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO) " | 	debug_printf ("DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO) " | ||||||
| 		      "failed, %E"); | 		      "failed, %E"); | ||||||
|  |       /* If we're trying to write to a disk partition, lock the partition, | ||||||
|  | 	 otherwise we will get "Access denied" starting with Vista. */ | ||||||
|  |       if (wincap.has_restricted_raw_disk_access () | ||||||
|  | 	  && get_major () != DEV_FLOPPY_MAJOR | ||||||
|  | 	  && get_major () != DEV_CDROM_MAJOR | ||||||
|  | 	  && (flags & O_ACCMODE) != O_RDONLY) | ||||||
|  | 	{ | ||||||
|  | 	  /* Special case: If we try to write to the entire disk, we have to | ||||||
|  | 	     lock all partitions, otherwise writing fails as soon as we cross | ||||||
|  | 	     a partition boundary. */ | ||||||
|  | 	  if (get_minor () % 16 == 0) | ||||||
|  | 	    { | ||||||
|  | 	      WCHAR part[MAX_PATH], *p; | ||||||
|  |  | ||||||
|  | 	      sys_mbstowcs (part, MAX_PATH, get_win32_name ()); | ||||||
|  | 	      p = wcschr (part, L'\0') - 1; | ||||||
|  | 	      for (int i = 0; i < MAX_PARTITIONS; ++i) | ||||||
|  | 	      	{ | ||||||
|  | 		  NTSTATUS status; | ||||||
|  | 		  UNICODE_STRING upart; | ||||||
|  | 		  OBJECT_ATTRIBUTES attr; | ||||||
|  | 		  IO_STATUS_BLOCK io; | ||||||
|  |  | ||||||
|  | 		  __small_swprintf (p, L"%d", i + 1); | ||||||
|  | 		  RtlInitUnicodeString (&upart, part); | ||||||
|  | 		  InitializeObjectAttributes (&attr, &upart, | ||||||
|  | 					      OBJ_INHERIT|OBJ_CASE_INSENSITIVE, | ||||||
|  | 					      NULL, NULL); | ||||||
|  | 		  status = NtOpenFile (&partitions[i], GENERIC_WRITE, &attr, | ||||||
|  | 				       &io, FILE_SHARE_VALID_FLAGS, 0); | ||||||
|  | 		  if (status == STATUS_OBJECT_NAME_NOT_FOUND || | ||||||
|  | 		      status == STATUS_OBJECT_PATH_NOT_FOUND) | ||||||
|  | 		    break; | ||||||
|  | 		  else if (!NT_SUCCESS (status)) | ||||||
|  | 		    debug_printf ("NtCreateFile(%W): status %p", part, status); | ||||||
|  | 		  else if (!DeviceIoControl (partitions[i], FSCTL_LOCK_VOLUME, | ||||||
|  | 					     NULL, 0, NULL, 0, | ||||||
|  | 					     &bytes_read, NULL)) | ||||||
|  | 		    debug_printf ("DeviceIoControl (%W, FSCTL_LOCK_VOLUME) " | ||||||
|  | 				  "failed, %E", part); | ||||||
| 		} | 		} | ||||||
|  | 	    } | ||||||
|  | 	  else if (!DeviceIoControl (get_handle (), FSCTL_LOCK_VOLUME, | ||||||
|  | 				     NULL, 0, NULL, 0, &bytes_read, NULL)) | ||||||
|  | 	    debug_printf ("DeviceIoControl (FSCTL_LOCK_VOLUME) failed, %E"); | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_dev_floppy::close () | ||||||
|  | { | ||||||
|  |   int ret = fhandler_dev_raw::close (); | ||||||
|  |  | ||||||
|  |   /* See "Special case" comment in fhandler_dev_floppy::open. */ | ||||||
|  |   if (wincap.has_restricted_raw_disk_access ()) | ||||||
|  |     for (int i = 0; i < MAX_PARTITIONS && partitions[i]; ++i) | ||||||
|  |       NtClose (partitions[i]); | ||||||
|  |  | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
| @@ -234,12 +294,26 @@ fhandler_dev_floppy::open (int flags, mode_t) | |||||||
| int | int | ||||||
| fhandler_dev_floppy::dup (fhandler_base *child) | fhandler_dev_floppy::dup (fhandler_base *child) | ||||||
| { | { | ||||||
|  |   fhandler_dev_floppy *fhc = (fhandler_dev_floppy *) child; | ||||||
|  |  | ||||||
|  |   /* See "Special case" comment in fhandler_dev_floppy::open. */ | ||||||
|  |   memset (fhc->partitions, 0, sizeof fhc->partitions); | ||||||
|  |   if (wincap.has_restricted_raw_disk_access ()) | ||||||
|  |     for (int i = 0; i < MAX_PARTITIONS && partitions[i]; ++i) | ||||||
|  |       if (!DuplicateHandle (GetCurrentProcess (), partitions[i], | ||||||
|  | 			    GetCurrentProcess (), &fhc->partitions[i], | ||||||
|  | 			    0, TRUE, DUPLICATE_SAME_ACCESS)) | ||||||
|  | 	{ | ||||||
|  | 	  __seterrno (); | ||||||
|  | 	  while (--i >= 0) | ||||||
|  | 	    NtClose (partitions[i]); | ||||||
|  | 	  return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|   int ret = fhandler_dev_raw::dup (child); |   int ret = fhandler_dev_raw::dup (child); | ||||||
|  |  | ||||||
|   if (!ret) |   if (!ret) | ||||||
|     { |     { | ||||||
|       fhandler_dev_floppy *fhc = (fhandler_dev_floppy *) child; |  | ||||||
|  |  | ||||||
|       fhc->drive_size = drive_size; |       fhc->drive_size = drive_size; | ||||||
|       fhc->bytes_per_sector = bytes_per_sector; |       fhc->bytes_per_sector = bytes_per_sector; | ||||||
|       fhc->eom_detected (eom_detected ()); |       fhc->eom_detected (eom_detected ()); | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| 		capability class to the appropriate values. | 		capability class to the appropriate values. | ||||||
|  |  | ||||||
|    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | ||||||
|    2009, 2010 Red Hat, Inc. |    2009, 2010, 2011 Red Hat, Inc. | ||||||
|  |  | ||||||
| This file is part of Cygwin. | This file is part of Cygwin. | ||||||
|  |  | ||||||
| @@ -61,6 +61,7 @@ wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|   has_mwmo_inputavailable:false, |   has_mwmo_inputavailable:false, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -101,6 +102,7 @@ wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -141,6 +143,7 @@ wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -181,6 +184,7 @@ wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -221,6 +225,7 @@ wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -261,6 +266,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -301,6 +307,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:false, |   has_fast_cwd:false, | ||||||
|  |   has_restricted_raw_disk_access:false, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -341,6 +348,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:true, |   has_buggy_thread_startup:true, | ||||||
|   has_fast_cwd:true, |   has_fast_cwd:true, | ||||||
|  |   has_restricted_raw_disk_access:true, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { | wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { | ||||||
| @@ -381,6 +389,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|   has_mwmo_inputavailable:true, |   has_mwmo_inputavailable:true, | ||||||
|   has_buggy_thread_startup:false, |   has_buggy_thread_startup:false, | ||||||
|   has_fast_cwd:true, |   has_fast_cwd:true, | ||||||
|  |   has_restricted_raw_disk_access:true, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); | wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| /* wincap.h: Header for OS capability class. | /* wincap.h: Header for OS capability class. | ||||||
|  |  | ||||||
|    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | ||||||
|    2009, 2010 Red Hat, Inc. |    2009, 2010, 2011 Red Hat, Inc. | ||||||
|  |  | ||||||
| This file is part of Cygwin. | This file is part of Cygwin. | ||||||
|  |  | ||||||
| @@ -51,6 +51,7 @@ struct wincaps | |||||||
|   unsigned has_mwmo_inputavailable			: 1; |   unsigned has_mwmo_inputavailable			: 1; | ||||||
|   unsigned has_buggy_thread_startup			: 1; |   unsigned has_buggy_thread_startup			: 1; | ||||||
|   unsigned has_fast_cwd					: 1; |   unsigned has_fast_cwd					: 1; | ||||||
|  |   unsigned has_restricted_raw_disk_access		: 1; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class wincapc | class wincapc | ||||||
| @@ -107,6 +108,7 @@ public: | |||||||
|   bool	IMPLEMENT (has_mwmo_inputavailable) |   bool	IMPLEMENT (has_mwmo_inputavailable) | ||||||
|   bool	IMPLEMENT (has_buggy_thread_startup) |   bool	IMPLEMENT (has_buggy_thread_startup) | ||||||
|   bool	IMPLEMENT (has_fast_cwd) |   bool	IMPLEMENT (has_fast_cwd) | ||||||
|  |   bool	IMPLEMENT (has_restricted_raw_disk_access) | ||||||
|  |  | ||||||
| #undef IMPLEMENT | #undef IMPLEMENT | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user