diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2a9ccfe8d..ed94c4534 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2006-03-09 Corinna Vinschen + + * autoload.cc (NtClose): Define. + (NtOpenDirectoryObject): Define. + (NtQueryDirectoryObject): Define. + * fhandler_proc.cc: Include ctype.h and wchar.h. + (format_proc_partitions): Revamp loop over existing harddisks by + scanning the NT native \Device object directory and looking for + Harddisk entries. + * ntdll.h: Rearrange system call declarations alphabetically. + (DIRECTORY_QUERY): Define. + (struct _DIRECTORY_BASIC_INFORMATION): Define. + (NtOpenDirectoryObject): Declare. + (NtQueryDirectoryObject): Declare. + 2006-03-08 Christopher Faylor * cygtls.h (_cygtls::retaddr): New method. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 548b4ab13..6b889a946 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -378,13 +378,16 @@ LoadDLLfunc (NetUserGetGroups, 28, netapi32) LoadDLLfunc (NetUserGetInfo, 16, netapi32) LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) +LoadDLLfuncEx (NtClose, 4, ntdll, 1) LoadDLLfuncEx (NtCreateFile, 44, ntdll, 1) LoadDLLfuncEx (NtCreateSection, 28, ntdll, 1) LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) LoadDLLfuncEx (NtLockVirtualMemory, 16, ntdll, 1) LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) +LoadDLLfuncEx (NtOpenDirectoryObject, 12, ntdll, 1) LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1) +LoadDLLfuncEx (NtQueryDirectoryObject, 28, ntdll, 1) LoadDLLfuncEx2 (NtQueryDirectoryFile, 44, ntdll, 1, 1) LoadDLLfuncEx2 (NtQueryInformationFile, 20, ntdll, 1, 1) LoadDLLfuncEx (NtQueryInformationProcess, 20, ntdll, 1) diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc index 0f3171116..7a67cf0b1 100644 --- a/winsup/cygwin/fhandler_proc.cc +++ b/winsup/cygwin/fhandler_proc.cc @@ -26,7 +26,9 @@ details. */ #include #include #include "ntdll.h" +#include #include +#include #include "cpuid.h" #define _COMPILING_NEWLIB @@ -952,118 +954,149 @@ format_proc_partitions (char *destbuf, size_t maxsize) char *bufptr = destbuf; print ("major minor #blocks name\n\n"); - if (wincap.is_winnt ()) + if (!wincap.is_winnt ()) + return bufptr - destbuf; + + char devname[CYG_MAX_PATH]; + OBJECT_ATTRIBUTES attr; + HANDLE dirhdl, devhdl; + IO_STATUS_BLOCK io; + NTSTATUS status; + + /* Open \Device object directory. */ + wchar_t wpath[CYG_MAX_PATH] = L"\\Device"; + UNICODE_STRING upath = {14, 16, wpath}; + InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL); + status = NtOpenDirectoryObject (&dirhdl, DIRECTORY_QUERY, &attr); + if (!NT_SUCCESS (status)) { - for (int drive_number=0; ; drive_number++) + debug_printf ("NtOpenDirectoryObject %x", status); + return bufptr - destbuf; + } + + /* Traverse \Device directory ... */ + PDIRECTORY_BASIC_INFORMATION dbi = (PDIRECTORY_BASIC_INFORMATION) + alloca (640); + BOOLEAN restart = TRUE; + ULONG context = 0; + while (NT_SUCCESS (NtQueryDirectoryObject (dirhdl, dbi, 640, TRUE, restart, + &context, NULL))) + { + restart = FALSE; + sys_wcstombs (devname, CYG_MAX_PATH - 1, dbi->ObjectName.Buffer, + dbi->ObjectName.Length / 2); + /* ... and check for a "Harddisk[0-9]*" entry. */ + if (!strncasematch (devname, "Harddisk", 8) + || dbi->ObjectName.Length < 18 + || !isdigit (devname[8])) + continue; + /* Construct path name for partition 0, which is the whole disk, + and try to open. */ + wcscpy (wpath, dbi->ObjectName.Buffer); + wcscpy (wpath + dbi->ObjectName.Length / 2, L"\\Partition0"); + upath.Length = 22 + dbi->ObjectName.Length; + upath.MaximumLength = upath.Length + 2; + InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, + dirhdl, NULL); + status = NtOpenFile (&devhdl, READ_CONTROL | FILE_READ_DATA, &attr, &io, + wincap.shared (), 0); + if (!NT_SUCCESS (status)) { - CHAR szDriveName[CYG_MAX_PATH]; - __small_sprintf (szDriveName, "\\\\.\\PHYSICALDRIVE%d", drive_number); - HANDLE hDevice; - hDevice = CreateFile (szDriveName, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) + /* Retry with READ_CONTROL only for non-privileged users. This + at least prints the Partition0 info, but it doesn't allow access + to the drive's layout information. It beats me, though, why + a non-privileged user shouldn't get read access to the drive + layout information. */ + status = NtOpenFile (&devhdl, READ_CONTROL, &attr, &io, + wincap.shared (), 0); + if (!NT_SUCCESS (status)) { - if (GetLastError () == ERROR_PATH_NOT_FOUND) - break; - __seterrno (); - debug_printf ("CreateFile %d %E", GetLastError ()); - break; + debug_printf ("NtOpenFile(%s) %x", devname, status); + continue; + } + } + + /* Use a buffer since some ioctl buffers aren't fixed size. */ + char buf[256]; + PARTITION_INFORMATION *pi = NULL; + PARTITION_INFORMATION_EX *pix = NULL; + DISK_GEOMETRY *dg = NULL; + DWORD bytes; + unsigned long drive_number = strtoul (devname + 8, NULL, 10); + unsigned long long size; + + if (wincap.has_disk_ex_ioctls () + && DeviceIoControl (devhdl, IOCTL_DISK_GET_PARTITION_INFO_EX, + NULL, 0, buf, 256, &bytes, NULL)) + { + pix = (PARTITION_INFORMATION_EX *) buf; + size = pix->PartitionLength.QuadPart; + } + else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_PARTITION_INFO, + NULL, 0, buf, 256, &bytes, NULL)) + { + pi = (PARTITION_INFORMATION *) buf; + size = pi->PartitionLength.QuadPart; + } + else if (DeviceIoControl (devhdl, IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, 0, buf, 256, &bytes, NULL)) + { + dg = (DISK_GEOMETRY *) buf; + size = (unsigned long long) dg->Cylinders.QuadPart + * dg->TracksPerCylinder + * dg->SectorsPerTrack + * dg->BytesPerSector; + } + else + size = 0; + if (!pi && !pix && !dg) + debug_printf ("DeviceIoControl %E"); + else + { + device dev; + dev.parsedisk (drive_number, 0); + bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n", + dev.major, dev.minor, + size >> 10, dev.name + 5); + } + size_t buf_size = 8192; + while (true) + { + char buf[buf_size]; + if (DeviceIoControl (devhdl, IOCTL_DISK_GET_DRIVE_LAYOUT, + NULL, 0, (DRIVE_LAYOUT_INFORMATION *) buf, + buf_size, &bytes, NULL)) + /* fall through */; + else if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) + { + buf_size *= 2; + continue; } else { - DWORD dwBytesReturned; - /* Use a buffer since some ioctl buffers aren't fixed size. */ - char buf[256]; - PARTITION_INFORMATION *pi = NULL; - PARTITION_INFORMATION_EX *pix = NULL; - DISK_GEOMETRY *dg = NULL; - unsigned long long drive_size; - - if (wincap.has_disk_ex_ioctls () - && DeviceIoControl (hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, - NULL, 0, buf, 256, &dwBytesReturned, - NULL)) - { - pix = (PARTITION_INFORMATION_EX *) buf; - drive_size = pix->PartitionLength.QuadPart; - } - else if (DeviceIoControl (hDevice, IOCTL_DISK_GET_PARTITION_INFO, - NULL, 0, buf, 256, &dwBytesReturned, - NULL)) - { - pi = (PARTITION_INFORMATION *) buf; - drive_size = pi->PartitionLength.QuadPart; - } - else if (DeviceIoControl (hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, 0, buf, 256, &dwBytesReturned, - NULL)) - { - dg = (DISK_GEOMETRY *) buf; - drive_size = (unsigned long long) dg->Cylinders.QuadPart - * dg->TracksPerCylinder - * dg->SectorsPerTrack - * dg->BytesPerSector; - } - else - drive_size = 0; - if (!pi && !pix && !dg) - debug_printf ("DeviceIoControl %E"); - else - { - device dev; - dev.parsedisk (drive_number, 0); - bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n", - dev.major, dev.minor, - drive_size >> 10, - dev.name + 5); - } - size_t buf_size = 8192; - DWORD rc; - while (1) - { - char buf[buf_size]; - memset (buf, 0, buf_size); - rc = DeviceIoControl (hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT, - NULL, 0, (DRIVE_LAYOUT_INFORMATION *) buf, - buf_size, &dwBytesReturned, NULL); - if (rc) - /* fall through */; - else if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) - { - buf_size *= 2; - continue; - } - else - { - debug_printf ("DeviceIoControl %E"); - break; - } - DRIVE_LAYOUT_INFORMATION *dli = (DRIVE_LAYOUT_INFORMATION *) buf; - for (unsigned partition = 0; partition < dli->PartitionCount; partition++) - { - if (!dli->PartitionEntry[partition].PartitionLength.QuadPart - || !dli->PartitionEntry[partition].RecognizedPartition) - continue; - device dev; - dev.parsedisk (drive_number, dli->PartitionEntry[partition].PartitionNumber); - bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n", - dev.major, dev.minor, - (long long)(dli->PartitionEntry[partition].PartitionLength.QuadPart >> 10), - dev.name + 5); - } - break; - } - CloseHandle (hDevice); + debug_printf ("DeviceIoControl %E"); + break; } + DRIVE_LAYOUT_INFORMATION *dli = (DRIVE_LAYOUT_INFORMATION *) buf; + for (unsigned part = 0; part < dli->PartitionCount; part++) + { + if (!dli->PartitionEntry[part].PartitionLength.QuadPart + || !dli->PartitionEntry[part].RecognizedPartition) + continue; + device dev; + dev.parsedisk (drive_number, + dli->PartitionEntry[part].PartitionNumber); + size = dli->PartitionEntry[part].PartitionLength.QuadPart >> 10; + bufptr += __small_sprintf (bufptr, "%5d %5d %9U %s\n", + dev.major, dev.minor, + size, dev.name + 5); + } + break; } + NtClose (devhdl); } - else - { - // not worth the effort - // you need a 16 bit thunk DLL to access the partition table on Win9x - // and then you have to decode it yourself - } + NtClose (dirhdl); + return bufptr - destbuf; } diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 1e1bd1145..3f5035c17 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -116,6 +116,8 @@ typedef struct _FILE_ID_BOTH_DIR_INFORMATION #define LOCK_VM_IN_WSL 1 #define LOCK_VM_IN_RAM 2 +#define DIRECTORY_QUERY 1 + typedef ULONG KAFFINITY; typedef enum _SYSTEM_INFORMATION_CLASS @@ -552,10 +554,17 @@ typedef struct _OBJECT_NAME_INFORMATION UNICODE_STRING Name; } OBJECT_NAME_INFORMATION; +typedef struct _DIRECTORY_BASIC_INFORMATION +{ + UNICODE_STRING ObjectName; + UNICODE_STRING ObjectTypeName; +} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION; + /* Function declarations for ntdll.dll. These don't appear in any standard Win32 header. */ extern "C" { + NTSTATUS NTAPI NtClose (HANDLE); NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG); @@ -570,9 +579,17 @@ extern "C" NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG, PLARGE_INTEGER, PULONG, SECTION_INHERIT, ULONG, ULONG); + NTSTATUS NTAPI NtOpenDirectoryObject (PHANDLE, ACCESS_MASK, + POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG); NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); + NTSTATUS NTAPI NtQueryDirectoryFile(HANDLE, HANDLE, PVOID, PVOID, + PIO_STATUS_BLOCK, PVOID, ULONG, + FILE_INFORMATION_CLASS, BOOLEAN, + PUNICODE_STRING, BOOLEAN); + NTSTATUS NTAPI NtQueryDirectoryObject (HANDLE, PVOID, ULONG, BOOLEAN, + BOOLEAN, PULONG, PULONG); NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS, @@ -593,10 +610,6 @@ extern "C" NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG); NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID); VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR); + ULONG NTAPI RtlIsDosDeviceName_U (PCWSTR); ULONG NTAPI RtlNtStatusToDosError (NTSTATUS); - ULONG WINAPI RtlIsDosDeviceName_U (PCWSTR); - NTSTATUS NTAPI NtQueryDirectoryFile(HANDLE, HANDLE, PVOID, PVOID, PIO_STATUS_BLOCK, - PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, - PUNICODE_STRING, BOOLEAN); - NTSTATUS NTAPI NtClose (HANDLE); }