Problème Marshal.StructureToPtr [Résolu]

cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention - 24 mars 2008 à 03:47 - Dernière réponse : cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention
- 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
Afficher la suite 

Votre réponse

8 réponses

Meilleure réponse
cs_akim77 73 Messages postés lundi 12 avril 2004Date d'inscription 17 septembre 2008 Dernière intervention - 25 mars 2008 à 06:55
3
Merci
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

Merci cs_akim77 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 92 internautes ce mois-ci

Commenter la réponse de cs_akim77
Meilleure réponse
cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention - 31 mars 2008 à 15:21
3
Merci
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

Merci cs_Galain 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 92 internautes ce mois-ci

Commenter la réponse de cs_Galain
cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention - 24 mars 2008 à 04:10
0
Merci
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
Commenter la réponse de cs_Galain
cs_akim77 73 Messages postés lundi 12 avril 2004Date d'inscription 17 septembre 2008 Dernière intervention - 24 mars 2008 à 12:31
0
Merci
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
Commenter la réponse de cs_akim77
cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention - 24 mars 2008 à 14:06
0
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) ?

Avec mes remerciements

GRENIER Alain
Commenter la réponse de cs_Galain
cs_akim77 73 Messages postés lundi 12 avril 2004Date d'inscription 17 septembre 2008 Dernière intervention - 24 mars 2008 à 15:27
0
Merci
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
Commenter la réponse de cs_akim77
cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention - 24 mars 2008 à 21:39
0
Merci
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
Commenter la réponse de cs_Galain
cs_Galain 1270 Messages postés mardi 11 novembre 2003Date d'inscription 24 juillet 2013 Dernière intervention - 25 mars 2008 à 07:16
0
Merci
Merci Akim 77 pout ton aide

GRENIER Alain
Commenter la réponse de cs_Galain

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.