示例#1
0
        private SCSIStatusCodeName ReportLUNs(out byte[] response)
        {
            uint               bytesReturned;
            uint               outBufferLength = 4096;
            IntPtr             outBuffer       = Marshal.AllocHGlobal((int)outBufferLength);
            SCSIStatusCodeName status;

            if (!DeviceIoControl(m_handle, IOCTL_SCSI_GET_INQUIRY_DATA, IntPtr.Zero, 0, outBuffer, outBufferLength, out bytesReturned, IntPtr.Zero))
            {
                Win32Error lastError = (Win32Error)Marshal.GetLastWin32Error();
                Log(Severity.Error, "DeviceIoControl/IOCTL_SCSI_GET_INQUIRY_DATA error: {0}, Device path: {1}", lastError, m_path);
                response = VirtualSCSITarget.FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData());
                status   = SCSIStatusCodeName.CheckCondition;
            }
            else
            {
                List <SCSI_INQUIRY_DATA> devices   = SCSI_ADAPTER_BUS_INFO.GetInquiryDataForAllDevices(outBuffer);
                ReportLUNsParameter      parameter = new ReportLUNsParameter();
                foreach (SCSI_INQUIRY_DATA device in devices)
                {
                    // If the device has been claimed by a class driver then passthrough IOCTLs must go through the class driver
                    if (!device.DeviceClaimed)
                    {
                        PeripheralDeviceType deviceType = (PeripheralDeviceType)(device.InquiryData[0] & 0x1F);
                        if (deviceType == PeripheralDeviceType.DirectAccessBlockDevice |
                            deviceType == PeripheralDeviceType.SequentialAccessDevice |
                            deviceType == PeripheralDeviceType.CDRomDevice)
                        {
                            byte?associatedLUN = m_logicalUnitManager.FindAssociatedLUN(device.PathId, device.TargetId, device.Lun);
                            if (!associatedLUN.HasValue)
                            {
                                associatedLUN = m_logicalUnitManager.FindUnusedLUN();
                                LogicalUnit logicalUnit = new LogicalUnit();
                                logicalUnit.AssociatedLun = associatedLUN.Value;
                                logicalUnit.PathId        = device.PathId;
                                logicalUnit.TargetId      = device.TargetId;
                                logicalUnit.TargetLun     = device.Lun;
                                logicalUnit.DeviceType    = deviceType;
                                m_logicalUnitManager.AddLogicalUnit(logicalUnit);
                                Log(Severity.Verbose, "Assigned virtual LUN {0} to device PathId: {1}, TargetId: {2}, LUN: {3}", associatedLUN.Value, device.PathId, device.TargetId, device.Lun);
                            }

                            if (!associatedLUN.HasValue)
                            {
                                throw new NotImplementedException("The maximum number of LUNs supported has been reached");
                            }
                            parameter.LUNList.Add(associatedLUN.Value);
                        }
                    }
                }
                response = parameter.GetBytes();
                Log(Severity.Verbose, "DeviceIoControl/IOCTL_SCSI_GET_INQUIRY_DATA reported {0} usable devices", parameter.LUNList.Count);
                status = SCSIStatusCodeName.Good;
            }
            Marshal.FreeHGlobal(outBuffer);
            return(status);
        }
        public static SCSI_ADAPTER_BUS_INFO FromIntPtr(IntPtr ptr)
        {
            SCSI_ADAPTER_BUS_INFO busInfo = new SCSI_ADAPTER_BUS_INFO();
            byte numberOfBuses            = Marshal.ReadByte(ptr);

            ptr = new IntPtr(ptr.ToInt64() + 4);
            busInfo.NumberOfBuses = numberOfBuses;
            busInfo.BusData       = new SCSI_BUS_DATA[numberOfBuses];
            for (int index = 0; index < numberOfBuses; index++)
            {
                busInfo.BusData[index] = (SCSI_BUS_DATA)Marshal.PtrToStructure(ptr, typeof(SCSI_BUS_DATA));
                ptr = new IntPtr(ptr.ToInt64() + Marshal.SizeOf(typeof(SCSI_BUS_DATA)));
            }
            return(busInfo);
        }
        public static List <SCSI_INQUIRY_DATA> GetInquiryDataForAllDevices(IntPtr busInfoPtr)
        {
            SCSI_ADAPTER_BUS_INFO    busInfo = FromIntPtr(busInfoPtr);
            List <SCSI_INQUIRY_DATA> devices = new List <SCSI_INQUIRY_DATA>();

            foreach (SCSI_BUS_DATA busData in busInfo.BusData)
            {
                byte numberOfLuns      = busData.NumberOfLogicalUnits;
                uint inquiryDataOffset = busData.InquiryDataOffset;
                for (int lunIndex = 0; lunIndex < numberOfLuns; lunIndex++)
                {
                    IntPtr            inquiryDataPtr = new IntPtr(busInfoPtr.ToInt64() + inquiryDataOffset);
                    SCSI_INQUIRY_DATA inquiryData    = SCSI_INQUIRY_DATA.FromIntPtr(inquiryDataPtr);
                    devices.Add(inquiryData);
                    inquiryDataOffset = inquiryData.NextInquiryDataOffset;
                }
            }
            return(devices);
        }