+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.
/* 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.
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;
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);
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.
fhandler_dev_floppy::fhandler_dev_floppy ()
: fhandler_dev_raw (), status ()
{
+ memset (partitions, 0, sizeof partitions);
}
int
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 ());
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.
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)) = {
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)) = {
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)) = {
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)) = {
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)) = {
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)) = {
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)) = {
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)) = {
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));
/* 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.
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
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
};