Utiliser l'api IOCTL_DISK_GET_DRIVE_GEOMETRY_EX

Résolu
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008 - 12 août 2006 à 20:10
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008 - 14 août 2006 à 21:42
Bonjour a tous,

Voilà j'essaye d'utiliser l'api IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, pour obtenir la geométrie du disque, pour se faire j'ai suivi les instruction de msdn j'ai creer toutes les structutres nécéssaires, j'ai essayé de mettre les bon types donnée, mais rien a faire j'ai toujours cette erreur:
PInvokeStackImbalance a été détecté
Message: Un appel à la fonction PInvoke 'hddtools!WindowsApplication1.Form1::DeviceIoControl' a déséquilibré la pile. Cela peut se produire, car la signature PInvoke managée ne correspond pas à la signature cible non managée. Vérifiez que la convention d'appel et les paramètres de la signature PInvoke correspondent à la signature non managée cible.

Voici le code source de mon application (elle assez brouillon a cause des nombreux teste effectué, veuillez m'en excusé):

Imports Microsoft.VisualBasic
Public Class Form1

    'appel de CTL_CODE pour obtneir le code d'optention de la géométrie
    Private Function CTL_CODE(ByVal DeviceType As UInteger, ByVal Fct As UInteger, ByVal Method As UInteger, ByVal Access As UInteger) As UInteger
        Return ((DeviceType) << 16) Or ((Access) << 14) Or ((Fct) << 2) Or (Method)
    End Function

    'calul du code d'optention de la geométrie
    Private IOCTL_DISK_GET_DRIVE_GEOMETRY_EX As Long = CTL_CODE(IOCTL_DISK_BASE, &H28, METHOD_BUFFERED, FILE_ANY_ACCESS)

    'déclaration de l'api CreateFile de kernel32.dll
    Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As UInteger, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As UInteger, ByVal dwFlagsAndAttributes As UInteger, ByVal hTemplateFile As IntPtr) As IntPtr

    'declaration de l'api DeviceIoControl deKernel32.dll
    Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, ByVal lpInBuffer As Object, ByVal nInBufferSize As Long, ByVal lpOutBuffer As DISK_GEOMETRY_EX, ByVal nOutBufferSize As Long, ByVal lpBytesReturned As Long, ByVal lpOverlapped As Object) As Long

    'declaration des constante createfile
    Const GENERIC_READ = &H80000000
    Const GENERIC_WRITE = &H40000000
    Const FILE_SHARE_READ = &H1
    Const FILE_SHARE_WRITE = &H2
    Const OPEN_EXISTING = 3

    'déclaratiob des constante DeviceIoControl
    Const METHOD_BUFFERED = 0
    Const FILE_ANY_ACCESS = 0
    Const FILE_DEVICE_DISK = &H7
    Const IOCTL_DISK_BASE = FILE_DEVICE_DISK
    Enum MEDIA_TYPE
        Unknown
        F5_1Pt2_512
        F3_1Pt44_512
        F3_2Pt88_512
        F3_20Pt8_512
        F3_720_512
        F5_360_512
        F5_320_512
        F5_320_1024
        F5_180_512
        F5_160_512
        RemovableMedia
        FixedMedia
        F3_120M_512
        F3_640_512
        F5_640_512
        F5_720_512
        F3_1Pt2_512
        F3_1Pt23_1024
        F5_1Pt23_1024
        F3_128Mb_512
        F3_230Mb_512
        F8_256_128
        F3_200Mb_512
        F3_240M_512
        F3_32M_512
    End Enum

    Structure DISK_GEOMETRY
        Dim Cylinders As Int64
        Dim MediaType As MEDIA_TYPE
        Dim TracksPerCylinder As Int64
        Dim SectorsPerTrack As Int64
        Dim BytesPerSector As Int64
    End Structure
    Structure DISK_GEOMETRY_EX
        Dim Geometry As DISK_GEOMETRY
        Dim DiskSize As Int64
        Dim Data() As Byte
    End Structure

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'instruction pour plus tard
        'Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
        'Dim d As DriveInfo
        Dim dg As New DISK_GEOMETRY_EX
        Dim drive As String
        drive = "c:"

        Dim hwndDevice As Long = CreateFile("\\." & drive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)
        Dim result As Long

        result = DeviceIoControl(hwndDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, Nothing, System.Convert.ToByte(0), dg, System.Convert.ToByte(255), System.Convert.ToByte(255), Nothing)

    End Sub
End Class

J'aimerais que quelqu'un m'explique ce qu j'ai mal fait ou oublié de faire,

je remercie toutes les personne qui m'aiderons, je remerci aussi willi pour l'aide déjà approtée

14 réponses

cs_Willi Messages postés 2375 Date d'inscription jeudi 12 juillet 2001 Statut Modérateur Dernière intervention 15 décembre 2018 22
12 août 2006 à 22:07
Bonsoir,
J'ai commenté pour que tu comprennes un miminum ce que j'ai fais.
J'ai typé tes constantes également ! Pense y par la suite pour plus de clarté.
J'ai modifié quelque peu les déclarations API et y ai ajouté CloseHandle pour libérer le handle ouvert par CreateFile à la fin.
Dans ton bouton1 je n'ai laissé que le nécessaire pour récupérer les datas de ta structure DISK_GEOMETRY_EX.

8<-------------------------------------------------------------------
Imports Microsoft.VisualBasic

Imports System.Runtime.InteropServices

'.........

Declare
Function CreateFile
Lib
"kernel32.dll"
Alias
"CreateFileA" (
ByVal lpFileName
As
String,
ByVal dwDesiredAccess
As
Integer,
ByVal dwShareMode
As
UInteger,
ByVal lpSecurityAttributes
As IntPtr,
ByVal dwCreationDisposition
As
UInteger,
ByVal dwFlagsAndAttributes
As
UInteger,
ByVal hTemplateFile
As IntPtr)
As IntPtr

Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Boolean

Declare
Function DeviceIoControl
Lib
"kernel32.dll" (
ByVal hDevice
As IntPtr,
ByVal dwIoControlCode
As
UInteger,
ByVal lpInBuffer
As IntPtr,
ByVal nInBufferSize
As
UInteger,
ByVal lpOutBuffer
As IntPtr,
ByVal nOutBufferSize
As
UInteger,
ByRef lpBytesReturned
As
UInteger,
ByVal lpOverlapped
As IntPtr)
As
Boolean

'declaration des constantes
Const GENERIC_READ
As
Integer = &H80000000

Const FILE_SHARE_READ
As
Integer = &H1

Const FILE_SHARE_WRITE
As
Integer = &H2

Const OPEN_EXISTING
As
Integer = 3

'déclaratiob des constante DeviceIoControl
Const METHOD_BUFFERED As
Integer 
 = 0
Const FILE_ANY_ACCESS As
Integer 
 = 0
Const FILE_DEVICE_DISK As
Integer 
 = &H7
Const IOCTL_DISK_BASE = FILE_DEVICE_DISK

Enum MEDIA_TYPE
   Unknown
   F5_1Pt2_512
   F3_1Pt44_512
   F3_2Pt88_512
   F3_20Pt8_512
   F3_720_512
   F5_360_512
   F5_320_512
   F5_320_1024
   F5_180_512
   F5_160_512
   RemovableMedia
   FixedMedia
   F3_120M_512
   F3_640_512
   F5_640_512
   F5_720_512
   F3_1Pt2_512
   F3_1Pt23_1024
   F5_1Pt23_1024
   F3_128Mb_512
   F3_230Mb_512
   F8_256_128
   F3_200Mb_512
   F3_240M_512
   F3_32M_512

End
Enum

Structure DISK_GEOMETRY
   
Dim Cylinders
As Int64

   Dim MediaType
As MEDIA_TYPE

   Dim TracksPerCylinder
As Int64

   Dim SectorsPerTrack
As Int64

   Dim BytesPerSector
As Int64

End
Structure

Structure DISK_GEOMETRY_EX

   Dim Geometry
As DISK_GEOMETRY   

   Dim DiskSize
As Int64

   Dim Data()
As
Byte
End
Structure

Private
Sub Button1_Click(
ByVal sender
As System.Object,
ByVal e
As System.EventArgs)
Handles Button1.Click 

   
Dim dg
As
New DISK_GEOMETRY_EX

   Dim drive
As
String="c:"

   Dim hwndDevice
As IntPtr = CreateFile(
"\\." & drive, GENERIC_READ, FILE_SHARE_READ
Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)

   If hwndDevice <> -1
Then
'handle ok
      
      Dim gcHwnd
As GCHandle = GCHandle.Alloc(Marshal.SizeOf(dg), GCHandleType.Pinned)

      Dim pBuff
As IntPtr = gcHwnd.AddrOfPinnedObject  
'pointeur sur le buffer qui va contenir les datas de ta structure
      
      Dim uiRet
As
UInteger = 0
'octets retournés

      Dim bIO
As
Boolean = DeviceIoControl(hwndDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
Nothing, 0, pBuff, Marshal.SizeOf(dg), uiRet, IntPtr.Zero)

      'DeviceIoControl OK
      If bIO
Then
      
         'Récupération de ta structure DISK_GEOMETRY_EX
         dg = Marshal.PtrToStructure(pBuff, dg.GetType)

         'Libération du GCHandle et du handle ouvert par CreateFile
         CloseHandle(hwndDevice)
         gcHwnd.Free()

      End
If

   End
If

End
Sub

------------------------------------------------------------------------>8

Bon courage ++
3
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
13 août 2006 à 11:23
CloseHandle() doit être appelé inconditionnellement si CreateFile() a réussi, il faut le sortir du 'If bIO Then'.

ciao...
BruNews, MVP VC++
3
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
12 août 2006 à 22:15
Merci beaucoup pour cette reponse, c'est vraimment sympa...
0
cs_Willi Messages postés 2375 Date d'inscription jeudi 12 juillet 2001 Statut Modérateur Dernière intervention 15 décembre 2018 22
12 août 2006 à 22:19
Je ne sais plus si ton problème était de récupérer les datas dans ta structures ou bien utiliser correctement la méthode DeviceIoControl. Du coup je t'ai tout fais....

Tiens nous au courant si sa marche ou pas.
0

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

Posez votre question
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
12 août 2006 à 22:27
Je suis désolé mais le code que tu ma donné bloque mon pc... je comprend pas
0
cs_Willi Messages postés 2375 Date d'inscription jeudi 12 juillet 2001 Statut Modérateur Dernière intervention 15 décembre 2018 22
12 août 2006 à 22:30
Execute le en pas à pas (raccourci clavier F10) et donne nous l'erreur que tu obtiens.
(le code marche parfaitement j'ai testé avant quand meme)
0
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
12 août 2006 à 22:36
Maintenant elle fonctionne (je suis pas mito pourtant) mais parfois si on appuye trop vite sur le boutton ou parfois a la fermeture sa se plante merci quand même sans toi je serais toujours nul par
0
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
12 août 2006 à 22:41
Ne faudrais t'il pas ajouté une ligne qui stoppe les opérations de lecture?? enfin je dit sa mais j'ai encore des lacune en programmation

merci
0
cs_Willi Messages postés 2375 Date d'inscription jeudi 12 juillet 2001 Statut Modérateur Dernière intervention 15 décembre 2018 22
12 août 2006 à 23:01
Quelles opérations de lecture ?
Compile ton projet en mode release et execute l'exe généré à partir de l'explorer.
Très rarement j'ai des blocage de quelques secondes suivuis d'un message d'erreurs quand je travaille en debug pas à pas.
0
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
12 août 2006 à 23:04
moi j'ai sa:

AppName: hddtools.exe      AppVer: 1.0.0.0     AppStamp:44de420b
ModName: mscorwks.dll      ModVer: 2.0.50727.42      ModStamp:4333e7ec
fDebug: 0       Offset: 000a163b

désolé
0
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
12 août 2006 à 23:05
Parfois sa marche parfois pas désolé du "flood", mais c'est étrange maintenant sa marche... merci beaucoup
0
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
14 août 2006 à 18:39
Voila j'ai ecrit un petit programme qui devrait afficher les nombre de cylindre, de pistes... mais les résultat sont incohérent et l'application plante aléatoirement avec une preference pour la fermeture quand on a lancé l'application plus qu'une fois.

Est-ce que quelqu'un pourrait (encore) m'aider svp.

Code:
Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices

Public Class Form1

    'appel de CTL_CODE pour obtneir le code d'optention de la géométrie
    Private Function CTL_CODE(ByVal DeviceType As UInteger, ByVal Fct As UInteger, ByVal Method As UInteger, ByVal Access As UInteger) As UInteger
        Return ((DeviceType) << 16) Or ((Access) << 14) Or ((Fct) << 2) Or (Method)
    End Function

    'calul du code d'optention de la geométrie
    Private IOCTL_DISK_GET_DRIVE_GEOMETRY_EX As Long = CTL_CODE(IOCTL_DISK_BASE, &H28, METHOD_BUFFERED, FILE_ANY_ACCESS)

    Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As UInteger, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As UInteger, ByVal dwFlagsAndAttributes As UInteger, ByVal hTemplateFile As IntPtr) As IntPtr

    Declare Function CloseHandle Lib "kernel32" (ByVal hObject As IntPtr) As Boolean

    Declare Function DeviceIoControl Lib "kernel32.dll" (ByVal hDevice As IntPtr, ByVal dwIoControlCode As UInteger, ByVal lpInBuffer As IntPtr, ByVal nInBufferSize As UInteger, ByVal lpOutBuffer As IntPtr, ByVal nOutBufferSize As UInteger, ByRef lpBytesReturned As UInteger, ByVal lpOverlapped As IntPtr) As Boolean

    'declaration des constantes
    Const GENERIC_READ As Integer = &H80000000
    Const FILE_SHARE_READ As Integer = &H1
    Const FILE_SHARE_WRITE As Integer = &H2
    Const OPEN_EXISTING As Integer = 3

    'déclaratiob des constante DeviceIoControl
    Const METHOD_BUFFERED As Integer = 0
    Const FILE_ANY_ACCESS As Integer = 0
    Const FILE_DEVICE_DISK As Integer = &H7
    Const IOCTL_DISK_BASE = FILE_DEVICE_DISK

    Enum MEDIA_TYPE
        Unknown
        F5_1Pt2_512
        F3_1Pt44_512
        F3_2Pt88_512
        F3_20Pt8_512
        F3_720_512
        F5_360_512
        F5_320_512
        F5_320_1024
        F5_180_512
        F5_160_512
        RemovableMedia
        FixedMedia
        F3_120M_512
        F3_640_512
        F5_640_512
        F5_720_512
        F3_1Pt2_512
        F3_1Pt23_1024
        F5_1Pt23_1024
        F3_128Mb_512
        F3_230Mb_512
        F8_256_128
        F3_200Mb_512
        F3_240M_512
        F3_32M_512
    End Enum

    Structure DISK_GEOMETRY
        Dim Cylinders As Int64
        Dim MediaType As MEDIA_TYPE
        Dim TracksPerCylinder As Int64
        Dim SectorsPerTrack As Int64
        Dim BytesPerSector As Int64
    End Structure

    Structure DISK_GEOMETRY_EX
        Dim Geometry As DISK_GEOMETRY
        Dim DiskSize As Int64
        Dim Data() As Byte
    End Structure

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim dg As New DISK_GEOMETRY_EX
        Dim drive As String = "c:"

        Dim hwndDevice As IntPtr = CreateFile("\\." & drive, GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero)

        If hwndDevice <> -1 Then 'handle ok

            Dim gcHwnd As GCHandle = GCHandle.Alloc(Marshal.SizeOf(dg), GCHandleType.Pinned)
            Dim pBuff As IntPtr = gcHwnd.AddrOfPinnedObject   'pointeur sur le buffer qui va contenir les datas de ta structure

            Dim uiRet As UInteger = 0 'octets retournés

            Dim bIO As Boolean = DeviceIoControl(hwndDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, Nothing, 0, pBuff, Marshal.SizeOf(dg), uiRet, IntPtr.Zero)

            'DeviceIoControl OK
            If bIO Then

                'Récupération de ta structure DISK_GEOMETRY_EX
                dg = Marshal.PtrToStructure(pBuff, dg.GetType)
            End If
            'Libération du GCHandle et du handle ouvert par CreateFile
            gcHwnd.Free()
            CloseHandle(hwndDevice)
        End If

        'Affichage des resultats
        Me.ListBox1.Items.Add("Type de média:")
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add(dg.Geometry.MediaType)
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add("Nombre de cylindre:")
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add(dg.Geometry.Cylinders)
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add("Nombre de piste par cylindre:")
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add(dg.Geometry.TracksPerCylinder)
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add("Nombre de sercteur par piste:")
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add(dg.Geometry.SectorsPerTrack)
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add("Nombre de byte par secteur:")
        Me.ListBox1.Items.Add("")
        Me.ListBox1.Items.Add(dg.Geometry.BytesPerSector)

    End Sub

End Class
0
cs_Willi Messages postés 2375 Date d'inscription jeudi 12 juillet 2001 Statut Modérateur Dernière intervention 15 décembre 2018 22
14 août 2006 à 21:17
Si tu ne veux pas te faire chi** utilise le fonctions suivante de l'api, tu auras les infos que tu recherches.
Fais une recherche sur le site ou sur google si tu ne sais pas les appeler.



Private



Declare



Function
GetVolumeInformation

Lib



"kernel32"



Alias



"GetVolumeInformationA"
(

ByVal
lpRootPathName

As



String
,

ByVal
lpVolumeNameBuffer

As
StringBuilder,

ByVal
nVolumeNameSize

As



Integer
,

ByRef
lpVolumeSerialNumber

As



Integer
,

ByRef
lpMaximumComponentLength

As



Integer
,

ByRef
lpFileSystemFlags

As



Integer
,

ByVal
lpFileSystemNameBuffer

As
StringBuilder,

ByVal
nFileSystemNameSize

As



Integer
)

As



Boolean








Private



Declare



Function
GetDiskFreeSpace

Lib



"kernel32"



Alias



"GetDiskFreeSpaceA"
(

ByVal
lpRootPathName

As



String
,

ByRef
lpSectorsPerCluster

As



Integer
,

ByRef
lpBytesPerSector

As



Integer
,

ByRef
ByreflpNumberOfFreeClusters

As



Integer
,

ByRef
lpTotalNumberOfClusters

As



Integer
)

As



Boolean
0
DrThrax Messages postés 38 Date d'inscription dimanche 29 janvier 2006 Statut Membre Dernière intervention 17 août 2008
14 août 2006 à 21:42
OK merci je vais y regarder demain n'empeche j'ai trouvé une source en c++ qui utilise l'autre méthode mais je comprend pas pourquoi elle elle marche pas grave si cette méthode est plus simple je vais "oublier" l'autre

Merci pour tes bon conseils.
0
Rejoignez-nous