Added code to retrieve NT device path (will be needed later).

This commit is contained in:
2017-12-06 13:46:35 +00:00
parent e3b97c123d
commit df076b5e0f
5 changed files with 227 additions and 9 deletions

View File

@@ -33,6 +33,8 @@
using System; using System;
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.Console;
using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.ATA;
namespace DiscImageChef.Devices namespace DiscImageChef.Devices
@@ -100,6 +102,7 @@ namespace DiscImageChef.Devices
throw new SystemException(string.Format("Error {0} trying device.", lastError)); throw new SystemException(string.Format("Error {0} trying device.", lastError));
bool scsiSense = true; bool scsiSense = true;
string ntDevicePath = null;
// Windows is answering SCSI INQUIRY for all device types so it needs to be detected first // Windows is answering SCSI INQUIRY for all device types so it needs to be detected first
if(platformID == Interop.PlatformID.Win32NT) if(platformID == Interop.PlatformID.Win32NT)
@@ -126,7 +129,20 @@ namespace DiscImageChef.Devices
{ {
Windows.StorageDeviceDescriptor descriptor = new Windows.StorageDeviceDescriptor(); Windows.StorageDeviceDescriptor descriptor = new Windows.StorageDeviceDescriptor();
descriptor.Version = BitConverter.ToUInt32(descriptor_b, 0);
descriptor.Size = BitConverter.ToUInt32(descriptor_b, 4);
descriptor.DeviceType = descriptor_b[8];
descriptor.DeviceTypeModifier= descriptor_b[9];
descriptor.RemovableMedia = descriptor_b[10] > 0;
descriptor.CommandQueueing = descriptor_b[11] > 0;
descriptor.VendorIdOffset = BitConverter.ToUInt32(descriptor_b, 12);
descriptor.ProductIdOffset = BitConverter.ToUInt32(descriptor_b, 16);
descriptor.ProductRevisionOffset = BitConverter.ToUInt32(descriptor_b, 20);
descriptor.SerialNumberOffset = BitConverter.ToUInt32(descriptor_b, 24);
descriptor.BusType = (Windows.StorageBusType)BitConverter.ToUInt32(descriptor_b, 28); descriptor.BusType = (Windows.StorageBusType)BitConverter.ToUInt32(descriptor_b, 28);
descriptor.RawPropertiesLength = BitConverter.ToUInt32(descriptor_b, 32);
descriptor.RawDeviceProperties = new byte[descriptor.RawPropertiesLength];
Array.Copy(descriptor_b, 36, descriptor.RawDeviceProperties, 0, descriptor.RawPropertiesLength);
switch(descriptor.BusType) switch(descriptor.BusType)
{ {
@@ -180,9 +196,12 @@ namespace DiscImageChef.Devices
else else
manufacturer = "ATA"; manufacturer = "ATA";
} }
// TODO: Get cached CID, CSD and SCR from kernel space // TODO: Get cached CID, CSD and SCR from kernel space
} }
ntDevicePath = Windows.Command.GetDevicePath((SafeFileHandle)fd);
DicConsole.DebugWriteLine("Windows devices", "NT device path: {0}", ntDevicePath);
Marshal.FreeHGlobal(descriptorPtr); Marshal.FreeHGlobal(descriptorPtr);
} }
else else
@@ -246,9 +265,12 @@ namespace DiscImageChef.Devices
} }
#region USB #region USB
if (platformID == Interop.PlatformID.Linux)
if(platformID == Interop.PlatformID.Linux)
{ {
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) || devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) || devicePath.StartsWith("/dev/st", StringComparison.Ordinal)) if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
{ {
string devPath = devicePath.Substring(5); string devPath = devicePath.Substring(5);
if(System.IO.Directory.Exists("/sys/block/" + devPath)) if(System.IO.Directory.Exists("/sys/block/" + devPath))
@@ -268,7 +290,8 @@ namespace DiscImageChef.Devices
System.IO.StreamReader usbSr; System.IO.StreamReader usbSr;
string usbTemp; string usbTemp;
usbFs = new System.IO.FileStream(resolvedLink + "/descriptors", System.IO.FileMode.Open, System.IO.FileAccess.Read); usbFs = new System.IO.FileStream(resolvedLink + "/descriptors",
System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte[] usbBuf = new byte[65536]; byte[] usbBuf = new byte[65536];
int usbCount = usbFs.Read(usbBuf, 0, 65536); int usbCount = usbFs.Read(usbBuf, 0, 65536);
usbDescriptors = new byte[usbCount]; usbDescriptors = new byte[usbCount];
@@ -277,12 +300,14 @@ namespace DiscImageChef.Devices
usbSr = new System.IO.StreamReader(resolvedLink + "/idProduct"); usbSr = new System.IO.StreamReader(resolvedLink + "/idProduct");
usbTemp = usbSr.ReadToEnd(); usbTemp = usbSr.ReadToEnd();
ushort.TryParse(usbTemp, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out usbProduct); ushort.TryParse(usbTemp, System.Globalization.NumberStyles.HexNumber,
System.Globalization.CultureInfo.InvariantCulture, out usbProduct);
usbSr.Close(); usbSr.Close();
usbSr = new System.IO.StreamReader(resolvedLink + "/idVendor"); usbSr = new System.IO.StreamReader(resolvedLink + "/idVendor");
usbTemp = usbSr.ReadToEnd(); usbTemp = usbSr.ReadToEnd();
ushort.TryParse(usbTemp, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out usbVendor); ushort.TryParse(usbTemp, System.Globalization.NumberStyles.HexNumber,
System.Globalization.CultureInfo.InvariantCulture, out usbVendor);
usbSr.Close(); usbSr.Close();
if(System.IO.File.Exists(resolvedLink + "/manufacturer")) if(System.IO.File.Exists(resolvedLink + "/manufacturer"))
@@ -313,6 +338,10 @@ namespace DiscImageChef.Devices
} }
} }
} }
}
else if(platformID == Interop.PlatformID.Win32NT)
{
} }
// TODO: Implement for other operating systems // TODO: Implement for other operating systems
else else

View File

@@ -32,8 +32,10 @@
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Net.NetworkInformation;
using Microsoft.Win32.SafeHandles; using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.ATA;
namespace DiscImageChef.Devices.Windows namespace DiscImageChef.Devices.Windows
@@ -481,6 +483,93 @@ namespace DiscImageChef.Devices.Windows
return error; return error;
} }
internal static uint GetDeviceNumber(SafeFileHandle deviceHandle)
{
StorageDeviceNumber sdn = new StorageDeviceNumber();
sdn.deviceNumber = - 1;
uint k = 0;
if(!Extern.DeviceIoControlGetDeviceNumber(deviceHandle, WindowsIoctl.IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero,
0, ref sdn, (uint)Marshal.SizeOf(sdn), ref k, IntPtr.Zero))
{
return uint.MaxValue;
}
return (uint)sdn.deviceNumber;
}
internal static string GetDevicePath(SafeFileHandle fd)
{
uint devNumber = GetDeviceNumber(fd);
if(devNumber == uint.MaxValue)
return null;
SafeFileHandle hDevInfo = Extern.SetupDiGetClassDevs(ref Consts.GUID_DEVINTERFACE_DISK, IntPtr.Zero,
IntPtr.Zero, DeviceGetClassFlags.Present | DeviceGetClassFlags.DeviceInterface);
if(hDevInfo.IsInvalid)
return null;
uint index = 0;
DeviceInterfaceData spdid = new DeviceInterfaceData();
spdid.cbSize = Marshal.SizeOf(spdid);
byte[] buffer;
while(true)
{
buffer = new byte[2048];
if(!Extern.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref Consts.GUID_DEVINTERFACE_DISK, index,
ref spdid))
break;
uint size = 0;
Extern.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref spdid, IntPtr.Zero, 0, ref size, IntPtr.Zero);
if(size > 0 && size < buffer.Length)
{
buffer[0] = (byte)(IntPtr.Size == 8 ? IntPtr.Size : IntPtr.Size + Marshal.SystemDefaultCharSize); // Funny...
IntPtr pspdidd = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, pspdidd, buffer.Length);
bool result =
Extern.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref spdid, pspdidd, size, ref size, IntPtr.Zero);
buffer = new byte[size];
Marshal.Copy(pspdidd, buffer, 0, buffer.Length);
Marshal.FreeHGlobal(pspdidd);
if(result)
{
string devicePath = Encoding.Unicode.GetString(buffer, 4, (int)size - 4);
SafeFileHandle hDrive = Extern.CreateFile(devicePath, 0, FileShare.Read | FileShare.Write,
IntPtr.Zero, FileMode.OpenExisting, 0, IntPtr.Zero);
if(!hDrive.IsInvalid)
{
uint newDeviceNumber = GetDeviceNumber(hDrive);
if(newDeviceNumber == devNumber)
{
Extern.CloseHandle(hDrive);
return devicePath;
}
}
Extern.CloseHandle(hDrive);
}
}
index++;
}
Extern.SetupDiDestroyDeviceInfoList(hDevInfo);
return null;
}
} }
} }

View File

@@ -105,7 +105,7 @@ namespace DiscImageChef.Devices.Windows
/// <summary> /// <summary>
/// FILE_ATTRIBUTE_VIRTUAL /// FILE_ATTRIBUTE_VIRTUAL
/// </summary> /// </summary>
Virtual = 0x10000 Virtual = 0x10000,
} }
[Flags] [Flags]
@@ -271,6 +271,7 @@ namespace DiscImageChef.Devices.Windows
IOCTL_SCSI_GET_ADDRESS = 0x41018, IOCTL_SCSI_GET_ADDRESS = 0x41018,
IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400, IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400,
IOCTL_IDE_PASS_THROUGH = 0x4D028, IOCTL_IDE_PASS_THROUGH = 0x4D028,
IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080,
} }
[Flags] [Flags]
@@ -349,4 +350,34 @@ namespace DiscImageChef.Devices.Windows
FileBackedVirtual = 0xF, FileBackedVirtual = 0xF,
NVMe = 0x11, NVMe = 0x11,
} }
[Flags]
enum DeviceGetClassFlags : uint
{
/// <summary>
/// DIGCF_DEFAULT
/// </summary>
Default = 0x01,
/// <summary>
/// DIGCF_PRESENT
/// </summary>
Present = 0x02,
/// <summary>
/// DIGCF_ALLCLASSES
/// </summary>
AllClasses = 0x04,
/// <summary>
/// DIGCF_PROFILE
/// </summary>
Profile = 0x08,
/// <summary>
/// DIGCF_DEVICEINTERFACE
/// </summary>
DeviceInterface = 0x10,
}
static class Consts
{
public static Guid GUID_DEVINTERFACE_DISK = new Guid(0x53F56307, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
}
} }

View File

@@ -98,6 +98,49 @@ namespace DiscImageChef.Devices.Windows
IntPtr Overlapped IntPtr Overlapped
); );
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "DeviceIoControl", CharSet = CharSet.Auto)]
internal static extern bool DeviceIoControlGetDeviceNumber(
SafeFileHandle hDevice,
WindowsIoctl IoControlCode,
IntPtr InBuffer,
uint nInBufferSize,
ref StorageDeviceNumber OutBuffer,
uint nOutBufferSize,
ref uint pBytesReturned,
IntPtr Overlapped
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
internal static extern SafeFileHandle SetupDiGetClassDevs(
ref Guid ClassGuid,
IntPtr Enumerator,
IntPtr hwndParent,
DeviceGetClassFlags Flags
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiEnumDeviceInterfaces(
SafeFileHandle hDevInfo,
IntPtr devInfo,
ref Guid interfaceClassGuid,
uint memberIndex,
ref DeviceInterfaceData deviceInterfaceData
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiGetDeviceInterfaceDetail(
SafeFileHandle hDevInfo,
ref DeviceInterfaceData deviceInterfaceData,
IntPtr deviceInterfaceDetailData,
UInt32 deviceInterfaceDetailDataSize,
ref UInt32 requiredSize,
IntPtr deviceInfoData
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList(SafeFileHandle hDevInfo);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern bool CloseHandle(SafeFileHandle hDevice); internal static extern bool CloseHandle(SafeFileHandle hDevice);
} }

View File

@@ -212,5 +212,31 @@ namespace DiscImageChef.Devices.Windows
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
public byte[] DataBuffer; public byte[] DataBuffer;
} }
[StructLayout(LayoutKind.Sequential)]
struct StorageDeviceNumber
{
public int deviceType;
public int deviceNumber;
public int partitionNumber;
}
[StructLayout(LayoutKind.Sequential)]
struct DeviceInfoData
{
public int cbSize;
public Guid classGuid;
public uint devInst;
public IntPtr reserved;
}
[StructLayout(LayoutKind.Sequential)]
struct DeviceInterfaceData
{
public int cbSize;
public Guid interfaceClassGuid;
public uint flags;
private IntPtr reserved;
}
} }