Salut à tous
Cela fait 3 jours que je galère avec VB net et j'appelle au secours
'execute a command through the SPTI
Private Function SPTICmd(ByRef cmd() As Byte, ByVal CmdLen As Integer, ByVal WFE As Boolean, ByVal eDir As e_SPTIDirection, ByVal Pointer As Long, ByVal PointerLen As Long, Optional ByVal Timeout As Long = 5) As Boolean
Dim pswb As t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
Dim Lengthpswb As Int32, returned As Int32
Dim status As Int32, i As Byte
dskerr = False
ReDim pswb.spt.cdb(0 To 15)
ReDim pswb.spt.Fill(0 To 2)
ReDim pswb.SenseBuffer(0 To 35)
'check the timeout If WFE Then Timeout 9999 Else If Timeout 0 Then Timeout = 10
With pswb.spt
.Length = 44 ' size of the substructure
.DataIn = eDir ' data dir
.TimeOutValue = Timeout ' Timeout
.SenseInfoLength = (pswb.SenseBuffer.Length - 1) - 4 ' Sense Info size
.SenseInfoOffset = Marshal.SizeOf(pswb.spt) + 4 ' Sense Info Offset
.DataTransferLength = PointerLen ' data len
.DataBuffer = Pointer ' data buffer pointer
For i = 0 To CmdLen - 1
.cdb(i) = cmd(i) ' CDB from Array
Next i
.CdbLength = CmdLen ' CDB len
End With
Lengthpswb = pswb.spt.Length + pswb.SenseBuffer.Length ' size of the structure
' allocation mémoire por la structure
Dim uiSpace As Int32 = Convert.ToInt32(Lengthpswb) 'Représente la taille de la structure
Dim pbuffout As IntPtr = Marshal.AllocHGlobal(uiSpace) 'Alloue un espace mémoire
' Copie de la structure dans la zone mémoire allouée
Marshal.StructureToPtr(pswb, pbuffout, True) ' ICI erreur : Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée.
' Copie de la mémoire allouée dans la structure
Marshal.PtrToStructure(pbuffout, pswb)
' on libère la zone mémoire
Marshal.FreeHGlobal(pbuffout)
' on a réussi ? SPTICmd status 1 And pswb.spt.ScsiStatus = 0 If SPTICmd False Then dskerr True
End Function
On copie la structure pswb dans une zone mémoire allouée
On détermine le pointeur de cette zone mémoire
On copie la structure dans la zone mémoire
On appelle DeviceIoControl
On recopie la zone mémoire dans la structure
On teste si l'opération a réussie
Mon raisonnement est-il juste?
Que signifie l'erreur à ICI Erreur ?
Les paramètres de la structure pswb sont corrects car ceux-ci fonctionnent correctement à l'identique sur un projet VB 6.0. Mais en VB net c'est la cata
Dim pswb_bis As t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
pswb_bis = CType(Marshal.PtrToStructure(pbuffout, GetType(t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)), t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)
Pour ceux que cela intéresse voici le module qui permet l'accès bas niveau au CDROM ou DVDROM en vb Net
En exemple la fonction CDRomGetSectorMode donne le mode du support inséré( mode 0 = audio, mode 1 : data, etc....)
Ce module sera inclus dans la gestion des CDROMs etDVDROMs du projet "Accés Disques et Partions VB Net" qui est en chantier
Imports System.Runtime.InteropServices
Module Module3
Private Enum e_SPTIDirection
SCSI_IOCTL_DATA_OUT = 0 ' send data to the drive
SCSI_IOCTL_DATA_IN = 1 ' retrieve data from the drive
SCSI_IOCTL_DATA_UNSPECIFIED = 2 ' no transfer
End Enum
Public Enum e_AspiDirection
SRB_DIR_IN = &H8 ' retrieve data from the drive
SRB_DIR_OUT = &H10 ' send data to the drive
End Enum
Public Enum e_READCD_SUBCH_FLAGS
RCD_SUBCH_PW_RAW = &H1 ' Raw Channels P-W
RCD_SUBCH_Q = &H2 ' only Q channel
RCD_SUBCH_PW_CORRECTED = &H4 ' Channels P-W corrected
End Enum
<StructLayout(LayoutKind.Sequential)> _
Private Structure t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
Dim Lengthdata As Int16 ' data len
Dim ScsiStatus As Byte ' SCSI Status
Dim PathId As Byte ' Bus Number
Dim TargetId As Byte ' Target
Dim Lun As Byte ' Logical Unit Number
Dim CdbLength As Byte ' CDB (Command Descriptor Block)
Dim SenseInfoLength As Byte ' Sense Info len
Dim DataIn As Byte ' data direction
Dim DataTransferLength As Int32 ' data transfer length
Dim TimeOutValue As Int32 ' command timeout
Dim DataBuffer As Int32 ' Pointer to the data buffer
Dim SenseInfoOffset As Int32 ' Sense Info Offset
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=16)> Dim Cdb() As Byte ' commande SPTI
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Dim Fill() As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=36)> Dim SenseBuffer() As Byte ' Debugging-Info from the drive (0 to 35)
End Structure
Public SYNCPATTERN As String = "00FFFFFFFFFFFFFFFFFFFF00"
Private IOCTL_SCSI_PASS_THROUGH_DIRECT As UInt32 = &H4D014
Public buffer() As Byte
Public Function CDRomGetSectorMode(ByVal SectorLBA As Int32) As Int32 ' (fonction exemple)
Dim sync As String, cnt As Integer
'read sector raw
ReDim buffer(0 To 2351)
'read sector raw
If Not CDRomReadCD(SectorLBA, 1, e_READCD_FLAGS.RCD_RAW) Then
CDRomGetSectorMode = -1
dskerr = True
Exit Function
End If
'get the first 12 bytes and convert them to hex
sync = ""
For cnt = 0 To 11
sync = sync & buffer(cnt).ToString("X2")
Next
'is a sync pattern?
If sync = SYNCPATTERN Then
'Byte 16 is the mode
Select Case buffer(15)
Case 1
'Mode-1 Track (2048 Bytes data)
CDRomGetSectorMode = 1
Case 2
'compare pattern If (buffer(16) buffer(20)) And (buffer(17) buffer(21)) _ And (buffer(18) buffer(22)) And (buffer(19) buffer(23)) Then
If Not buffer(18) And &H20 = 0 Then
'Mode 2 Form 2 Track
CDRomGetSectorMode = 4
Else
'Mode 2 Form 1 Track
CDRomGetSectorMode = 3
End If
Else
'Mode-2 Track (2336 Bytes data)
CDRomGetSectorMode = 2
End If
End Select
Else
'Audio or Mode-0 (2352 Bytes data/2352 Bytes completely empty)
CDRomGetSectorMode = 0
End If
End Function
Public Function CDRomReadCD(ByVal LBA As Int32, ByVal NumSectors As Int32, ByVal ReadFlags As e_READCD_FLAGS, Optional ByVal SubchBits As e_READCD_SUBCH_FLAGS = 0) As Boolean
Dim cmd(11) As Byte
cmd(0) = &HBE ' READ CD OpCode
cmd(2) = (LBA >> 24) And &HFF ' LBA
cmd(3) = (LBA >> 16) And &HFF
cmd(4) = (LBA >> 8) And &HFF
cmd(5) = LBA And &HFF ' LBA
cmd(6) = (NumSectors >> 16) And &HFF ' num. sectors
cmd(7) = (NumSectors >> 8) And &HFF
cmd(8) = NumSectors And &HFF ' num. sectors
cmd(9) = ReadFlags ' read flags
cmd(10) = SubchBits ' Sub-Channel Flags
Private Function ExecCMD(ByRef cmd() As Byte, ByVal CmdLen As Int16, ByVal WFE As Boolean, ByVal eDir As e_AspiDirection, Optional ByVal Timeout As Int32 = 5) As Boolean
Dim DataDir As Int32
'SPTI
If eDir = e_AspiDirection.SRB_DIR_IN Then
DataDir = e_SPTIDirection.SCSI_IOCTL_DATA_IN
Else
DataDir = e_SPTIDirection.SCSI_IOCTL_DATA_OUT
End If
ExecCMD = SPTICmd(cmd, CmdLen, WFE, DataDir, Timeout)
End Function
'execute a command through the SPTI
Private Function SPTICmd(ByRef cmd() As Byte, ByVal CmdLen As Int16, ByVal WFE As Boolean, ByVal eDir As e_SPTIDirection, Optional ByVal Timeout As Int32 = 5) As Boolean
Dim pswb As t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
Dim Lengthpswb As UInt32, returned As UInt32
Dim status As Int32, i As Byte
Dim pointerdata As IntPtr, pointerpswb As IntPtr
dskerr = False
ReDim pswb.cdb(0 To 15)
ReDim pswb.Fill(0 To 2)
ReDim pswb.SenseBuffer(0 To 35)
' création du pointeur du buffer des Datas
pointerdata = Marshal.AllocHGlobal(Convert.ToInt32(buffer.Length))
' création du pointeur du buffer de la structure pswb
pointerpswb = Marshal.AllocHGlobal(80)
'check the timeout If WFE Then Timeout 9999 Else If Timeout 0 Then Timeout = 10
With pswb
.Lengthdata = 44 ' taille de la structure
.DataIn = eDir ' data dir
.TimeOutValue = Timeout ' Timeout
.SenseInfoLength = (pswb.SenseBuffer.Length - 1) - 4 ' Sense Info size
.SenseInfoOffset = (pswb.Lengthdata) + 4 ' Sense Info Offset
.DataTransferLength = buffer.Length ' data len
.DataBuffer = pointerdata ' data buffer pointer For i 0 To CmdLen - 1 : .cdb(i) cmd(i) : Next i ' CDB from Array
.CdbLength = CmdLen ' CDB len
Lengthpswb = .Lengthdata + .SenseBuffer.Length ' size of the structure
End With
Marshal.StructureToPtr(pswb, pointerpswb, False)
J'ai corrigé l'appel de la fonction : Pointer est un Intptr et 2 valeurs Long (VB 6.0) sont devenes Int32 (VB net) mais le problème reste entier
J'ai mis aussi le Imports System.Interopservices en debiut de module
Private Function SPTICmd(ByRef cmd() As Byte, ByVal CmdLen As Integer,
ByVal WFE As Boolean, ByVal eDir As e_SPTIDirection, ByVal Pointer As
Intptr, ByVal PointerLen As Int32, Optional ByVal Timeout As Int32 = 5) As
Boolean
Je cherche et j'attends une piste de votre part
Merci
Merci Akim 77 de t'intéresser au problème
voici la déclaration de la structure pswb as t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
Public Structure t_SPTD
Dim Length As Int16 ' data len
Dim ScsiStatus As Byte ' SCSI Status
Dim PathId As Byte ' Bus Number
Dim TargetId As Byte ' Target
Dim Lun As Byte ' Logical Unit Number
Dim CdbLength As Byte ' CDB (Command Descriptor Block)
Dim SenseInfoLength As Byte ' Sense Info len
Dim DataIn As Byte ' data direction
Dim DataTransferLength As Int32 ' data transfer length
Dim TimeOutValue As Int32 ' command timeout
Dim DataBuffer As Int32 ' Pointer to the data buffer
Dim SenseInfoOffset As Int32 ' Sense Info Offset
Dim cdb() As Byte ' Command Descriptor Block (0 to 15)
Dim Fill() As Byte ' (0 to 2)
End Structure
Public Structure t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
Dim spt As t_SPTD ' SPTD structure
Dim SenseBuffer() As Byte ' Debugging-Info from the drive (0 to 35)
End Structure
Dans le code on calcule 2 paramètres de cette structure
Voici les calculs en VB Net
.SenseInfoLength = (pswb.SenseBuffer.Length - 1) - 4 ' Sense Info size
.SenseInfoOffset = Marshal.SizeOf(pswb.spt) + 4 ' Sense Info Offset
et leus équivalents en VB 6.0
.SenseInfoLength = UBound(pswb.SenseBuffer) - 4 ' Sense Info size
.SenseInfoOffset = Len(pswb.spt) + 4 ' Sense Info Offset
Ceci vous donnera peut-être un début de piste
Autre chose en rapport
Lorsque l'on fait Dim pswb As t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER on réserve bien en mémoire une zone pour cette structure. Comment avoir son pointeur en Intptr ( c'est à dire son adresse mémoire si j'ai bien compris) ?
cs_akim77
Messages postés73Date d'inscriptionlundi 12 avril 2004StatutMembreDernière intervention17 septembre 20084 24 mars 2008 à 15:27
Ici http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshal.structuretoptr.aspx MSDN nous dit:
StructureToPtr copies the contents of structure to the pre-allocated block of memory pointed to by the ptr parameter.
If the fDeleteOld parameter is true, the buffer originally pointed to by ptr is deleted with the appropriate delete API
on the embedded pointer, but the buffer must contain valid data.
Notre pbuffout fraichement créé ne contient aucune donnée valide donc on doit utiliser:
Marshal.StructureToPtr(pswb, pbuffout, False)
Je n'ai plus d'erreur mais je ne pas être sûr que ça fonctionne.
Salut Akim77 et à tous les autres
Désolé de ne pas avoir pu répondre avant mais les connections internet sur ma région( Cergy et le Val d'Oise) sont très mauvaises
Je n'ai plus la première erreur et la commande DeviceIoControl ne renvoie un status correct prouvant qu'elle s'est bien déroulée.
par contre l'erreur se situe maintenant à la ligne suivante au Marshal.PtrToStructure qui renvoie la mémoire pointée vert la structure d'entrée de DeviceIoControl
' Copie de la mémoire allouée dans la structure
Marshal.PtrToStructure(pbuffout, pswb) <------- ICI Erreur
L'erreur est : La structure ne doit pas être une classe Valeur
Je t'envoie le message sur le forum et cherche de mon côté
Merci d'avoir solutionné à plus de 80% mon problème