* 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:
Corinna Vinschen 2011-01-11 14:50:45 +00:00
parent 5837aa428f
commit 95a5c969ab
5 changed files with 112 additions and 7 deletions

View File

@ -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>
* termios.cc (cfgetospeed, cfgetispeed): Constify argument per POSIX.

View File

@ -1,7 +1,7 @@
/* fhandler.h
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.
@ -687,11 +687,14 @@ class fhandler_dev_raw: public fhandler_base
void fixup_after_exec ();
};
#define MAX_PARTITIONS 15
class fhandler_dev_floppy: public fhandler_dev_raw
{
private:
_off64_t drive_size;
unsigned long bytes_per_sector;
HANDLE partitions[MAX_PARTITIONS];
struct status_flags
{
unsigned eom_detected : 1;
@ -711,6 +714,7 @@ class fhandler_dev_floppy: public fhandler_dev_raw
fhandler_dev_floppy ();
int open (int flags, mode_t mode = 0);
int close ();
int dup (fhandler_base *child);
void __stdcall raw_read (void *ptr, size_t& ulen);
ssize_t __stdcall raw_write (const void *ptr, size_t ulen);

View File

@ -2,7 +2,7 @@
fhandler classes.
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.
@ -32,6 +32,7 @@ details. */
fhandler_dev_floppy::fhandler_dev_floppy ()
: fhandler_dev_raw (), status ()
{
memset (partitions, 0, sizeof partitions);
}
int
@ -221,25 +222,98 @@ fhandler_dev_floppy::open (int flags, mode_t)
make sure we're actually allowed to read *all* of the device.
This is actually documented in the MSDN CreateFile man page. */
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,
NULL, 0, NULL, 0, &bytes_read, NULL))
debug_printf ("DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO) "
"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;
}
int
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);
if (!ret)
{
fhandler_dev_floppy *fhc = (fhandler_dev_floppy *) child;
fhc->drive_size = drive_size;
fhc->bytes_per_sector = bytes_per_sector;
fhc->eom_detected (eom_detected ());

View File

@ -2,7 +2,7 @@
capability class to the appropriate values.
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.
@ -61,6 +61,7 @@ wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) =
has_mwmo_inputavailable:false,
has_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:false,
has_fast_cwd:false,
has_restricted_raw_disk_access:false,
};
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_buggy_thread_startup:true,
has_fast_cwd:true,
has_restricted_raw_disk_access:true,
};
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_buggy_thread_startup:false,
has_fast_cwd:true,
has_restricted_raw_disk_access:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));

View File

@ -1,7 +1,7 @@
/* wincap.h: Header for OS capability class.
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.
@ -51,6 +51,7 @@ struct wincaps
unsigned has_mwmo_inputavailable : 1;
unsigned has_buggy_thread_startup : 1;
unsigned has_fast_cwd : 1;
unsigned has_restricted_raw_disk_access : 1;
};
class wincapc
@ -107,6 +108,7 @@ public:
bool IMPLEMENT (has_mwmo_inputavailable)
bool IMPLEMENT (has_buggy_thread_startup)
bool IMPLEMENT (has_fast_cwd)
bool IMPLEMENT (has_restricted_raw_disk_access)
#undef IMPLEMENT
};