Problème Marshal.StructureToPtr

Résolu
Profil bloqué - 24 mars 2008 à 03:47
 Profil bloqué - 31 mars 2008 à 15:21
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.

        ' opération disque
        status = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, pbuffout, Lengthpswb, pbuffout, Lengthpswb, returned, IntPtr.Zero)

        ' 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

Merci pour l'aide et bonne prog à tous

GRENIER Alain

8 réponses

cs_akim77 Messages postés 73 Date d'inscription lundi 12 avril 2004 Statut Membre Dernière intervention 17 septembre 2008 4
25 mars 2008 à 06:55
Avec VB.NET il n'y a pas moyen de se passer de la documentation sur MSDN
ici: http://msdn2.microsoft.com/en-us/library/4ca6d5z7.aspx

Il suffit de copier l'exemple et ça donne:

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)

@+

Akim
3
Profil bloqué
31 mars 2008 à 15:21
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_FLAGS
        RCD_SYNC = &H80                                   ' sync pattern
        RCD_HDR_4BT = &H20                                ' 4-Bytes Header
        RCD_HDR_8BT = &H40                                ' 8-Bytes Header
        RCD_USRDATA = &H10                                ' userdata
        RCD_EDC_ECC = &H8                                 ' EDC+ECC correction
        RCD_RAW = &HF8                                    ' full sector
    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

        CDRomReadCD = ExecCMD(cmd, 12, False, e_AspiDirection.SRB_DIR_IN, 40)

    End Function

    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)

        'SPTD
        status = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, pointerpswb, Lengthpswb, pointerpswb, Lengthpswb, returned, IntPtr.Zero)

        'success?
        pswb.ScsiStatus = Marshal.ReadByte(pointerpswb, 2)        SPTICmd (status 1) And (pswb.ScsiStatus = 0)        If SPTICmd False Then dskerr True
        Marshal.Copy(pointerdata, buffer, 0, buffer.Length)
        Marshal.FreeHGlobal(pointerdata)
        Marshal.FreeHGlobal(pointerpswb)

    End Function

End Module

Un grand merci à Akim77 qui m'a bien aidé ainsi quàWilli (je lui ai pris un bout de code pour l'analyse des partitions NTFS)
bonne prog à tous et A+

GRENIER Alain
3
Profil bloqué
24 mars 2008 à 04:10
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

GRENIER Alain
0
cs_akim77 Messages postés 73 Date d'inscription lundi 12 avril 2004 Statut Membre Dernière intervention 17 septembre 2008 4
24 mars 2008 à 12:31
Bonjour,

Difficile de trouver ton problème, sans savoir comment est declaré t_SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER

le calcul de uiSpace semble compliqué, as-tu essayé :
Marshal.AllocHGlobal(Marshal.SizeOf(pswb))

Akim
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Profil bloqué
24 mars 2008 à 14:06
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) ?

Avec mes remerciements

GRENIER Alain
0
cs_akim77 Messages postés 73 Date d'inscription lundi 12 avril 2004 Statut Membre Dernière intervention 17 septembre 2008 4
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.

@+

Akim
0
Profil bloqué
24 mars 2008 à 21:39
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

Merci à tous et bonne prog
GRENIER Alain
0
Profil bloqué
25 mars 2008 à 07:16
Merci Akim 77 pout ton aide

GRENIER Alain
0
Rejoignez-nous