|
|
 |
 |
 |
 |
How to use the DataBuffer of SCSI_PASS_THROUGH_DIRECT in c# ?
Hi All; I need to send a READ command to CD-ROM drive by SCSI_PASS_THROUGH_DIRECT. int inputSize = Marshal.SizeOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS)); IntPtr input = Marshal.AllocHGlobal(inputSize); Marshal.StructureToPtr(sptdwb, input, true) In my code, the Marshal.StructureToPtr(sptdwb, input, true) will return error, because the sptdwb and input size are not equal, then the PVOID DataBuffer can't be access. Do you have any ideas ?
Sorry, modify some message. I need to send a READ command to CD-ROM drive by SCSI_PASS_THROUGH_DIRECT. As SCSI_PASS_THROUGH_DIRECT struct: typedef struct _SCSI_PASS_THROUGH_DIRECT { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; ULONG SenseInfoOffset; UCHAR Cdb[16]; }SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
int inputSize = Marshal.SizeOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS)); IntPtr input = Marshal.AllocHGlobal(inputSize); Marshal.StructureToPtr(sptdwb, input, true) In my code, the Marshal.StructureToPtr(sptdwb, input, true) will return error, because I need to modify the DataBuffer size for each command, the sptdwb and input size will not equal, then the PVOID DataBuffer can't be access. Do you have any ideas ? Thank you for your help !!
-----------------------------------------------Reply-----------------------------------------------
"Marce" <u34601@uwe> wrote in message news:72e367ac5a552@uwe... > Sorry, modify some message. > I need to send a READ command to CD-ROM drive by > SCSI_PASS_THROUGH_DIRECT. > As SCSI_PASS_THROUGH_DIRECT struct: > typedef struct _SCSI_PASS_THROUGH_DIRECT { > USHORT Length; > UCHAR ScsiStatus; > UCHAR PathId; > UCHAR TargetId; > UCHAR Lun; > UCHAR CdbLength; > UCHAR SenseInfoLength; > UCHAR DataIn; > ULONG DataTransferLength; > ULONG TimeOutValue; > PVOID DataBuffer; > ULONG SenseInfoOffset; > UCHAR Cdb[16]; > }SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; > int inputSize = Marshal.SizeOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS)); > IntPtr input = Marshal.AllocHGlobal(inputSize); > Marshal.StructureToPtr(sptdwb, input, true) > In my code, the Marshal.StructureToPtr(sptdwb, input, true) will return > error, because I need to modify the DataBuffer size for each command, the > sptdwb and input size will not equal, then the PVOID DataBuffer can't be > access. > Do you have any ideas ? > Thank you for your help !!
We need your SCSI_PASS_THROUGH_DIRECT structure declaration in C# to help you with this. Willy.
-----------------------------------------------Reply-----------------------------------------------
Willy Denoyette [MVP] wrote: >> Sorry, modify some message. >[quoted text clipped - 30 lines] >> Thank you for your help !! >We need your SCSI_PASS_THROUGH_DIRECT structure declaration in C# to help >you with this. >Willy.
Thank you Willy! [StructLayout(LayoutKind.Sequential)] class SCSI_PASS_THROUGH_DIRECT { public UInt16 Length = (UInt16)Marshal.SizeOf(typeof (SCSI_PASS_THROUGH_DIRECT)); public byte ScsiStatus = 0; public byte PathId= 0; public byte TargetId= 0; public byte Lun = 0; public byte CdbLength = 12; public byte SenseInfoLength = 24; public byte DataIn ; public Int32 DataTransferLength; public Int32 TimeOutValue= 30; public IntPtr DataBuffer; public UInt32 SenseInfoOffset = (UInt32)Marshal.OffsetOf(typeof (SCSI_PASS_THROUGH_WITH_BUFFERS), "ucSenseBuf"); [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] public byte[] Cdb = new byte[16]; } FYI. -- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1
-----------------------------------------------Reply-----------------------------------------------
Marce wrote: >>> Sorry, modify some message. >[quoted text clipped - 6 lines] >>Willy. >Thank you Willy! >[StructLayout(LayoutKind.Sequential)] > class SCSI_PASS_THROUGH_DIRECT > { > public UInt16 Length = (UInt16)Marshal.SizeOf(typeof >(SCSI_PASS_THROUGH_DIRECT)); > public byte ScsiStatus = 0; > public byte PathId= 0; > public byte TargetId= 0; > public byte Lun = 0; > public byte CdbLength = 12; > public byte SenseInfoLength = 24; > public byte DataIn ; > public Int32 DataTransferLength; > public Int32 TimeOutValue= 30; > public IntPtr DataBuffer; > public UInt32 SenseInfoOffset = (UInt32)Marshal.OffsetOf(typeof >(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS), "ucSenseBuf"); > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] > public byte[] Cdb = new byte[16]; > } >FYI.
-- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1 -----------------------------------------------Reply-----------------------------------------------
Sorry, modify some error message ! [StructLayout(LayoutKind.Sequential)] class SCSI_PASS_THROUGH_DIRECT { public UInt16 Length = (UInt16)Marshal.SizeOf(typeof (SCSI_PASS_THROUGH_DIRECT)); public byte ScsiStatus = 0; public byte PathId= 0; public byte TargetId= 0; public byte Lun = 0; public byte CdbLength = 12; public byte SenseInfoLength = 24; public byte DataIn ; public Int32 DataTransferLength; public Int32 TimeOutValue= 30; public IntPtr DataBuffer; public UInt32 SenseInfoOffset = (UInt32)Marshal.OffsetOf(typeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS), "ucSenseBuf"); [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] public byte[] Cdb = new byte[16]; } -- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1
-----------------------------------------------Reply-----------------------------------------------
"Marce via DotNetMonster.com" <u34601@uwe> wrote in message news:72e5d0179de3d@uwe...
> Sorry, modify some error message ! > [StructLayout(LayoutKind.Sequential)] > class SCSI_PASS_THROUGH_DIRECT > { > public UInt16 Length = (UInt16)Marshal.SizeOf(typeof > (SCSI_PASS_THROUGH_DIRECT)); > public byte ScsiStatus = 0; > public byte PathId= 0; > public byte TargetId= 0; > public byte Lun = 0; > public byte CdbLength = 12; > public byte SenseInfoLength = 24; > public byte DataIn ; > public Int32 DataTransferLength; > public Int32 TimeOutValue= 30; > public IntPtr DataBuffer; > public UInt32 SenseInfoOffset = (UInt32)Marshal.OffsetOf(typeof > (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS), "ucSenseBuf"); > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] > public byte[] Cdb = new byte[16]; > } > -- > Message posted via DotNetMonster.com > http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1
You have to take care that you pass a correctly filled and aligned structure, the buffers need to be fields in the same marshaled structure (here SCSI_PASS_THROUGH_WITH_BUFFERS). Here is how you could declare the structure and the SCSI_PASS_THROUGH_WITH_BUFFERS class. [StructLayout(LayoutKind.Sequential)] struct SCSI_PASS_THROUGH_DIRECT { public short Length; public byte ScsiStatus; public byte PathId; public byte TargetId; public byte Lun; public byte CdbLength; public byte SenseInfoLength; public byte DataIn ; public int DataTransferLength; public int TimeOutValue; public IntPtr DataBufferOffset; public uint SenseInfoOffset; [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] public byte[] Cdb; }; [StructLayout(LayoutKind.Sequential)] class SCSI_PASS_THROUGH_WITH_BUFFERS { internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT(); // // adapt size to suit your needs!!!!!! [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)] internal byte[] sense ; // adapt to suit your needs!!!!!!! [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)] internal byte[] data ; }; // usage ... SCSI_PASS_THROUGH_WITH_BUFFERS info = new SCSI_PASS_THROUGH_WITH_BUFFERS(); info.sptd.Cdb = new byte[16]; info.sense = new byte[18]; // adapt to suit your needs!!!!!! info.data = new byte[36]; // adapt to suit your needs!!!!!! info.sptd.Length = (short)Marshal.SizeOf(info.sptd); info.sptd.SenseInfoOffset = (uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "sense"); info.sptd.SenseInfoLength = (byte)info.sense.Length; info.sptd.DataTransferLength = info.data.Length; info.sptd.DataBufferOffset = Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "data"); info.sptd.TimeOutValue = 30; info.sptd.DataIn = SCSI_IOCTL_DATA_IN; // initilalize the cdb info.sptd.CdbLength = x; // length of CDB info.sptd.Cdb[0] = ...; .... IntPtr inpBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(info)); Marshal.StructureToPtr(info, inpBuffer, false); // call DeviceIoControl passing the buffer inpBuffer as inp buffer and/or output buffer depending on the command. int ret = DeviceIoControl(...., inpBuffer, Marshal.SizeOf(info), ...); ... Willy.
-----------------------------------------------Reply-----------------------------------------------
Willy Denoyette [MVP] wrote: >> Sorry, modify some error message ! >[quoted text clipped - 19 lines] >> public byte[] Cdb = new byte[16]; >> } >You have to take care that you pass a correctly filled and aligned >structure, the buffers need to be fields in the same marshaled structure >(here SCSI_PASS_THROUGH_WITH_BUFFERS). >Here is how you could declare the structure and the >SCSI_PASS_THROUGH_WITH_BUFFERS class. > [StructLayout(LayoutKind.Sequential)] > struct SCSI_PASS_THROUGH_DIRECT > { > public short Length; > public byte ScsiStatus; > public byte PathId; > public byte TargetId; > public byte Lun; > public byte CdbLength; > public byte SenseInfoLength; > public byte DataIn ; > public int DataTransferLength; > public int TimeOutValue; > public IntPtr DataBufferOffset; > public uint SenseInfoOffset; > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] > public byte[] Cdb; > }; > [StructLayout(LayoutKind.Sequential)] > class SCSI_PASS_THROUGH_WITH_BUFFERS > { > internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT(); > // // adapt size to suit your needs!!!!!! > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)] > internal byte[] sense ; > // adapt to suit your needs!!!!!!! > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)] > internal byte[] data ; > }; >// usage ... > SCSI_PASS_THROUGH_WITH_BUFFERS info = new >SCSI_PASS_THROUGH_WITH_BUFFERS(); > info.sptd.Cdb = new byte[16]; > info.sense = new byte[18]; // adapt to suit your needs!!!!!! > info.data = new byte[36]; // adapt to suit your needs!!!!!! > info.sptd.Length = (short)Marshal.SizeOf(info.sptd); > info.sptd.SenseInfoOffset = >(uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "sense"); > info.sptd.SenseInfoLength = (byte)info.sense.Length; > info.sptd.DataTransferLength = info.data.Length; > info.sptd.DataBufferOffset = >Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "data"); > info.sptd.TimeOutValue = 30; > info.sptd.DataIn = SCSI_IOCTL_DATA_IN; >// initilalize the cdb > info.sptd.CdbLength = x; // length of CDB > info.sptd.Cdb[0] = ...; > .... > IntPtr inpBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(info)); > Marshal.StructureToPtr(info, inpBuffer, false); > // call DeviceIoControl passing the buffer inpBuffer as inp buffer >and/or output buffer depending on the command. > int ret = DeviceIoControl(...., inpBuffer, Marshal.SizeOf(info), ...); >... >Willy.
Thanks Willy. It works ok by SCSI_PASS_THROUGH_WITH_BUFFERS, and the data buffer size need to fixed. As this: [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30*2048)] public byte[] ucDataBuf = new byte[30 * 2048]; But In the SCSI_PASS_THROUGH_DIRECT_BUFFERS structure, the DataBuffer is IntPtr point. How can I send a ATAPI cmd with databuffer by SCSI_PASS_THROUGH_DIRECT_BUFFERS ? -- Message posted via http://www.dotnetmonster.com
-----------------------------------------------Reply-----------------------------------------------
"Marce via DotNetMonster.com" <u34601@uwe> wrote in message news:72f0129368a0e@uwe...
> Willy Denoyette [MVP] wrote: >>> Sorry, modify some error message ! >>[quoted text clipped - 19 lines] >>> public byte[] Cdb = new byte[16]; >>> } >>You have to take care that you pass a correctly filled and aligned >>structure, the buffers need to be fields in the same marshaled structure >>(here SCSI_PASS_THROUGH_WITH_BUFFERS). >>Here is how you could declare the structure and the >>SCSI_PASS_THROUGH_WITH_BUFFERS class. >> [StructLayout(LayoutKind.Sequential)] >> struct SCSI_PASS_THROUGH_DIRECT >> { >> public short Length; >> public byte ScsiStatus; >> public byte PathId; >> public byte TargetId; >> public byte Lun; >> public byte CdbLength; >> public byte SenseInfoLength; >> public byte DataIn ; >> public int DataTransferLength; >> public int TimeOutValue; >> public IntPtr DataBufferOffset; >> public uint SenseInfoOffset; >> [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] >> public byte[] Cdb; >> }; >> [StructLayout(LayoutKind.Sequential)] >> class SCSI_PASS_THROUGH_WITH_BUFFERS >> { >> internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT(); >> // // adapt size to suit your needs!!!!!! >> [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)] >> internal byte[] sense ; >> // adapt to suit your needs!!!!!!! >> [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)] >> internal byte[] data ; >> }; >>// usage ... >> SCSI_PASS_THROUGH_WITH_BUFFERS info = new >>SCSI_PASS_THROUGH_WITH_BUFFERS(); >> info.sptd.Cdb = new byte[16]; >> info.sense = new byte[18]; // adapt to suit your needs!!!!!! >> info.data = new byte[36]; // adapt to suit your needs!!!!!! >> info.sptd.Length = (short)Marshal.SizeOf(info.sptd); >> info.sptd.SenseInfoOffset = >>(uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "sense"); >> info.sptd.SenseInfoLength = (byte)info.sense.Length; >> info.sptd.DataTransferLength = info.data.Length; >> info.sptd.DataBufferOffset = >>Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "data"); >> info.sptd.TimeOutValue = 30; >> info.sptd.DataIn = SCSI_IOCTL_DATA_IN; >>// initilalize the cdb >> info.sptd.CdbLength = x; // length of CDB >> info.sptd.Cdb[0] = ...; >> .... >> IntPtr inpBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(info)); >> Marshal.StructureToPtr(info, inpBuffer, false); >> // call DeviceIoControl passing the buffer inpBuffer as inp buffer >>and/or output buffer depending on the command. >> int ret = DeviceIoControl(...., inpBuffer, Marshal.SizeOf(info), ...); >>... >>Willy. > Thanks Willy. > It works ok by SCSI_PASS_THROUGH_WITH_BUFFERS, and the data buffer size > need > to fixed. > As this: > [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30*2048)] > public byte[] ucDataBuf = new byte[30 * 2048]; > But In the SCSI_PASS_THROUGH_DIRECT_BUFFERS structure, the DataBuffer is > IntPtr point. > How can I send a ATAPI cmd with databuffer by > SCSI_PASS_THROUGH_DIRECT_BUFFERS ? > -- > Message posted via http://www.dotnetmonster.com
Ok, if you need to pass such large buffers you will have to use the IOCTL_SCSI_PASS_THROUGH_DIRECT ioctl command and define your structures as follows: [StructLayout(LayoutKind.Sequential)] struct SCSI_PASS_THROUGH_DIRECT { public short Length; public byte ScsiStatus; public byte PathId; public byte TargetId; public byte Lun; public byte CdbLength; public byte SenseInfoLength; public byte DataIn ; public int DataTransferLength; public int TimeOutValue; public IntPtr DataBuffer; // note this is now interpreted as a pointer, not an offset!! public uint SenseInfoOffset; [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] public byte[] Cdb; }; [StructLayout(LayoutKind.Sequential)] class SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS { internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT(); [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)] internal byte[] sense ; }; in your code, you'll have to allocate the data buffer like this: SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS info = new SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS(); ... info.sptd.DataBuffer = Marshal.AllocHGlobal(30 * 2048); // allocate correctly aligned buffer marshal the data to/from the buffer using Marshal.Copy, and... use the IOCTL_SCSI_PASS_THROUGH_DIRECT command in the call to the DeviceIOControl API like this: const int IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014; // IOCTL cmd ... DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH_DIRECT,.... don't forget to Marshal.FreeHGlobal when done with the unmanaged buffer!! Willy.
-----------------------------------------------Reply-----------------------------------------------
Dear Willy: Thank you for your help! This help me more !
Willy Denoyette [MVP] wrote: >>>> Sorry, modify some error message ! >[quoted text clipped - 83 lines] >> How can I send a ATAPI cmd with databuffer by >> SCSI_PASS_THROUGH_DIRECT_BUFFERS ? >Ok, if you need to pass such large buffers you will have to use the >IOCTL_SCSI_PASS_THROUGH_DIRECT ioctl command and define your structures as >follows: > [StructLayout(LayoutKind.Sequential)] > struct SCSI_PASS_THROUGH_DIRECT > { > public short Length; > public byte ScsiStatus; > public byte PathId; > public byte TargetId; > public byte Lun; > public byte CdbLength; > public byte SenseInfoLength; > public byte DataIn ; > public int DataTransferLength; > public int TimeOutValue; > public IntPtr DataBuffer; // note this is now interpreted as a >pointer, not an offset!! > public uint SenseInfoOffset; > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)] > public byte[] Cdb; > }; > [StructLayout(LayoutKind.Sequential)] > class SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS > { > internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT(); > [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)] > internal byte[] sense ; > }; >in your code, you'll have to allocate the data buffer like this: >SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS info = new >SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS(); >... >info.sptd.DataBuffer = Marshal.AllocHGlobal(30 * 2048); // allocate >correctly aligned buffer >marshal the data to/from the buffer using Marshal.Copy, and... >use the IOCTL_SCSI_PASS_THROUGH_DIRECT command in the call to the >DeviceIOControl API like this: >const int IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014; // IOCTL cmd >... >DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH_DIRECT,.... >don't forget to Marshal.FreeHGlobal when done with the unmanaged buffer!! >Willy.
-- Message posted via DotNetMonster.com http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1
|
 |
 |
 |
 |
|