Erreur DeviceIOControl : Fonction Incorrecte [Résolu]

tuxama 6 Messages postés lundi 28 janvier 2008Date d'inscription 18 février 2008 Dernière intervention - 9 févr. 2008 à 20:45 - Dernière réponse : Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention
- 19 févr. 2008 à 06:34
Bonsoir,

Je tente de récupérer quelques caractéristiques de mon disque physique principal.
DeviceIOControl me retourne une erreur '1' : Fonction Incorrecte
Malgrès différents essais je ne parviens pas à trouver de solution.

Quelqu'un a t-il une idée, voir même LA solution ?
Merci de votre aide.

        private void getPhysicalDrive( ) {
            IntPtr handle = IntPtr.Zero;
            uint ndevice = 0;

            Win32Functions.CHANGER_PRODUCT_DATA cpd = new Win32Functions.CHANGER_PRODUCT_DATA( );
            IntPtr pcpd = Marshal.AllocHGlobal( Marshal.SizeOf( cpd ) );
            Marshal.StructureToPtr( cpd, pcpd, true );

            do {
                string s = "\\\\.\\PHYSICALDRIVE" + ndevice.ToString( );
                Console.WriteLine( s );

                handle = Win32Functions.CreateFile( s,
                                                    0,
                                                    Win32Functions.FILE_SHARE_WRITE,
                                                    IntPtr.Zero,
                                                    Win32Functions.OPEN_EXISTING,
                                                    0,
                                                    IntPtr.Zero );
                if ( handle == IntPtr.Zero ) {
                    Console.WriteLine( "not Found" );
                }
                else {
                    uint nBytes = 0;
                    if ( Win32Functions.DeviceIoControl( handle,
                                                         Win32Functions.IOCTL_CHANGER_GET_PRODUCT_DATA,
                                                         IntPtr.Zero, 0,
                                                         pcpd, ( uint )Marshal.SizeOf( pcpd ),
                                                         ref nBytes,
                                                         IntPtr.Zero )
                                                         > 0 ) {

                        Console.WriteLine( cpd.ProductId );
                        Console.WriteLine( cpd.DeviceType );
                    }
                    else {
                        Int32 err = Marshal.GetLastWin32Error( );
                        Console.WriteLine( "The last Win32 Error was: " + err );
                        Console.WriteLine( GetLastWin32ErrorMessage( Marshal.GetLastWin32Error( ) ) );

                    }
                    Marshal.FreeHGlobal( pcpd );
                    if ( !Win32Functions.CloseHandle( handle ) ) {
                        Console.WriteLine( "CloseHandle code erreur: {0}", Marshal.GetLastWin32Error( ) );
                    }
                    ndevice++;
                }
            } while ( handle == IntPtr.Zero );
        }

        static void Main( string[ ] args ) {
            RawDiskAccess ld = new RawDiskAccess( );
            ld.getPhysicalDrive( );
        }
    }

////////////////////////////////////////////////////////////////

namespace RawDeviceAccess.Disk {
    /// <summary>
    /// Classe Wrapper pour des fonctions Win32 et les structures associées.
    /// </summary>
    internal class Win32Functions {
        // Types d'accès
        public const uint GENERIC_READ = 0x80000000;
        public const uint GENERIC_WRITE = 0x40000000;
        public const uint GENERIC_EXECUTE = 0x20000000;
        public const uint GENERIC_ALL = 0x10000000;

        // Partages
        public const uint FILE_SHARE_READ = 0x00000001;
        public const uint FILE_SHARE_WRITE = 0x00000002;
        public const uint FILE_SHARE_DELETE = 0x00000004;

        // Dispositions
        public const uint CREATE_NEW = 1;
        public const uint CREATE_ALWAYS = 2;
        public const uint OPEN_EXISTING = 3;
        public const uint OPEN_ALWAYS = 4;
        public const uint TRUNCATE_EXISTING = 5;

        //
        public const uint IOCTL_CHANGER_GET_PRODUCT_DATA = 0x00000002; //0x0002;

        [DllImport( "kernel32.dll", SetLastError = true, CharSet = CharSet.Auto )]
        public extern static IntPtr CreateFile(
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile
        );

        [System.Runtime.InteropServices.DllImport( "kernel32", SetLastError = true, CharSet = CharSet.Auto )]
        public extern static bool CloseHandle( IntPtr handle );

        [System.Runtime.InteropServices.DllImport( "Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto )]
        public extern static int DeviceIoControl(
            IntPtr hDevice,
            uint IoControlCode,
            IntPtr lpInBuffer,
            uint InBufferSize,
            IntPtr lpOutBuffer,
            uint nOutBufferSize,
            ref uint lpBytesReturned,
            IntPtr lpOverlapped
        );

        [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )]
        public struct CHANGER_PRODUCT_DATA {
            [MarshalAs( UnmanagedType.ByValArray, SizeConst = 255 )]
            public byte[ ] VendorId;
            [MarshalAs( UnmanagedType.ByValArray, SizeConst = 255 )]
            public byte[ ] ProductId;
            [MarshalAs( UnmanagedType.ByValArray, SizeConst = 255 )]
            public byte[ ] Revision;
            [MarshalAs( UnmanagedType.ByValArray, SizeConst = 255 )]
            public byte[ ] SerialNumber;
            [MarshalAs( UnmanagedType.ByValArray, SizeConst = 255 )]
            public byte[ ] DeviceType;
        };
    }
}

L'éternité c'est long surtout vers la fin...[Insert_Emoticon%28%27/imgs2/smile_wink.gif%27%29; ]
Afficher la suite 

11 réponses

Répondre au sujet
cs_coq 6366 Messages postés samedi 1 juin 2002Date d'inscription 2 août 2014 Dernière intervention - 10 févr. 2008 à 01:29
+3
Utile
Salut,

A vue de nez ta définition de la valeur de IOCTL_CHANGER_GET_PRODUCT_DATA me parait louche.

/*
coq
MVP Visual C#
CoqBlog
*/
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_coq
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 10 févr. 2008 à 13:31
+3
Utile
Salut, DeviceIoControl renvoie un bool sur 32 bits, et 1 c'est TRUE.
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 10 févr. 2008 à 18:38
+3
Utile
Oui je pense que c'est ça, les disques ne doivent pas être considérés comme des "changer". J'arrive à obtenir les réultats des codes DISK mais pas avec les code CHANGER.

( Exécuter en tant qu'administrateur ).

using System;
using System.Runtime.InteropServices;


namespace DeviceIO // compile with -unsafe
{
    internal class Program /*** Run as Administrator !! ***/
    {
        //[ StructLayout( LayoutKind.Sequential ) ]
        //private unsafe struct CHANGER_PRODUCT_DATA
        //{
        //    public fixed byte VendorId8;
        //    public fixed byte ProductId16;
        //    public fixed byte Revision4;
        //    public fixed byte SerialNumber32;
        //    byte DeviceType;
        //}


        [ DllImport( "kernel32.dll", CharSet = CharSet.Auto, SetLastError = true ) ]
        private static extern IntPtr CreateFile
        (
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile
        );


        [ DllImport( "kernel32.dll", SetLastError = true ) ]
        [ return: MarshalAs( UnmanagedType.Bool ) ]
        private static extern bool CloseHandle( IntPtr hObject );


        [ DllImport( "kernel32", SetLastError = true ) ]
        [ return: MarshalAs( UnmanagedType.Bool ) ]
        private static extern bool DeviceIoControl
        (
            IntPtr hDevice,
            uint dwIoControlCode,
            IntPtr lpInBuffer,
            uint nInBufferSize,
            IntPtr lpOutBuffer,
            uint nOutBufferSize,
            out uint lpBytesReturned,
            IntPtr lpOverlapped
        );


        [ DllImport( "kernel32.dll", CharSet = CharSet.Auto/*, SetLastError = true */ ) ]
        private static extern uint FormatMessage
        (
            uint dwFlags,
            IntPtr lpSource,
            uint dwMessageId,
            uint dwLanguageId,
            ref IntPtr lpBuffer,
            uint nSize,
            IntPtr Arguments
        );


        public static string GetLastWin32ErrorMessage( int errorCode )
        {
            IntPtr buffer = IntPtr.Zero;


            uint cnt = FormatMessage
            (
                0x00000100 |
                0x00000200 |
                0x00001000,
                IntPtr.Zero,
                ( uint )errorCode,
                0,
                ref buffer,
                0,
                IntPtr.Zero
            );


            if ( cnt 0 || buffer IntPtr.Zero )
                return String.Format( "Unknown error: {0}.", errorCode );


            string errorMessage = Marshal.PtrToStringAuto( buffer, ( int )cnt );
            Marshal.FreeHGlobal( buffer ); // LocalFree.


            return errorMessage;
        }


        private const string DISK_NAME = @"[file://\\.\PhysicalDrive0 \\.\PhysicalDrive0]"; // @"[file://\\.\C \\.\C]:"
        private const uint GENERIC_READ = 0x80000000;
        private const uint OPEN_EXISTING = 3;
        private const uint FILE_SHARE_READ = 0x00000001;
        private const uint FILE_SHARE_WRITE = 0x00000002;
        //private const uint IOCTL_CHANGER_GET_PRODUCT_DATA =
        //    ( ( 0x00000030 ) << 16 ) | ( ( 0x0001 ) << 14 ) | ( ( 0x0002  ) << 2 ) | ( 0x00 );
        private const uint IOCTL_DISK_GET_LENGTH_INFO =
            ( ( 0x00000007 ) << 16 ) | ( ( 0x0001 ) << 14 ) | ( ( 0x0017  ) << 2 ) | ( 0x00 );


        private static readonly IntPtr INVALID_HANDLE_VALUE = ( IntPtr )( -1 );


        private static unsafe void Main( )
        {
            IntPtr hDevice = CreateFile( DISK_NAME, GENERIC_READ,
                FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero );


            if ( hDevice == INVALID_HANDLE_VALUE )
            {
                Console.WriteLine( GetLastWin32ErrorMessage( Marshal.GetLastWin32Error( ) ) );
                goto exit;
            }


            Console.WriteLine( "Disk Handle: OK ..\r\n" );


            uint lpBytesReturned = 0U;
            long length  = 0L; // GET_LENGTH_INFORMATION.Length


            bool res = DeviceIoControl( hDevice, IOCTL_DISK_GET_LENGTH_INFO,
                IntPtr.Zero, 0, ( IntPtr )( &length ), sizeof( long ), out lpBytesReturned, IntPtr.Zero );


            if ( !res )
            {
                Console.WriteLine( GetLastWin32ErrorMessage( Marshal.GetLastWin32Error( ) ) );
                goto exit;
            }


            Console.WriteLine( "Disk Length: {0}Go / {1}Gio",
                ( uint )( length / Math.Pow( 1000, 3 ) ), ( uint )( length / Math.Pow( 1024, 3 ) )  );


            exit:


            Console.ReadLine( ); // Wait.


            if ( hDevice != IntPtr.Zero )
            {
                CloseHandle( hDevice );
                //hDevice = IntPtr.Zero;
            }
        }
    }
}
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Lutinore
cs_wizad 356 Messages postés samedi 30 octobre 2004Date d'inscription 14 avril 2009 Dernière intervention - 9 févr. 2008 à 22:41
0
Utile
A vu de nez (oui un nez peut voire suffit de bien l'éduquer) je dirais que tu te complique beaucoup <strike>trop</strike> la vie. A priori tu devrais plutôt passer par la couche WMI qui est faite pour ça (entre autre) et qui est accéssible en C# sans devoir wrapper divers couche native.

Pour info :
http://www.geekpedia.com/tutorial233_Getting-Disk-Drive-Information-using-WMI-and-Csharp.html
Commenter la réponse de cs_wizad
tuxama 6 Messages postés lundi 28 janvier 2008Date d'inscription 18 février 2008 Dernière intervention - 10 févr. 2008 à 11:24
0
Utile
L'objectif n'est pas ici de répondre à une problématique projet, mais à me former.
Je tente donc de découvrir l'utilisation des DLL natives.

L'éternité c'est long surtout vers la fin...[Insert_Emoticon%28%27/imgs2/smile_wink.gif%27%29; ]
Commenter la réponse de tuxama
tuxama 6 Messages postés lundi 28 janvier 2008Date d'inscription 18 février 2008 Dernière intervention - 10 févr. 2008 à 11:28
0
Utile
J'ai revu la définition de IOCTL_CHANGER_GET_PRODUCT_DATA c'était une des erreurs. Mais il doit en rester d'autre...

// CHANGER
ChangerBase = EFileDevice.Changer,
ChangerGetParameters = ( ChangerBase << 16 ) | ( 0x0000 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerGetStatus = ( ChangerBase << 16 ) | ( 0x0001 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerGetProductData = ( ChangerBase << 16 ) | ( 0x0002 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerSetAccess = ( ChangerBase << 16 ) | ( 0x0004 << 2 ) | EMethod.Buffered | ( ( FileAccess.Read | FileAccess.Write ) << 14 ),
ChangerGetElementStatus = ( ChangerBase << 16 ) | ( 0x0005 << 2 ) | EMethod.Buffered | ( ( FileAccess.Read | FileAccess.Write ) << 14 ),
ChangerInitializeElementStatus = ( ChangerBase << 16 ) | ( 0x0006 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerSetPosition = ( ChangerBase << 16 ) | ( 0x0007 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerExchangeMedium = ( ChangerBase << 16 ) | ( 0x0008 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerMoveMedium = ( ChangerBase << 16 ) | ( 0x0009 << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerReinitializeTarget = ( ChangerBase << 16 ) | ( 0x000A << 2 ) | EMethod.Buffered | ( FileAccess.Read << 14 ),
ChangerQueryVolumeTags = ( ChangerBase << 16 ) | ( 0x000B << 2 ) | EMethod.Buffered | ( ( FileAccess.Read | FileAccess.Write ) << 14 ),

public string GetLastWin32ErrorMessage( int errorCode ) {
    IntPtr buffer = IntPtr.Zero;

    uint cnt = FormatMessage
    (
        0x00000100 |    // FORMAT_MESSAGE_ALLOCATE_BUFFER
        0x00000200 |    // FORMAT_MESSAGE_IGNORE_INSERTS
        0x00001000,     // FORMAT_MESSAGE_FROM_SYSTEM
        IntPtr.Zero,
        ( uint )errorCode,
        0,              // LANGIDs : Neutral, Thread, User, System, en-US
        ref buffer,
        0,
        IntPtr.Zero
    );
    if ( cnt 0 || buffer IntPtr.Zero )
        return String.Format( "Unknown error: {0}.", errorCode );

    string errorMessage = Marshal.PtrToStringAuto( buffer, ( int )cnt );
    Marshal.FreeHGlobal( buffer ); // LocalFree.

    return errorMessage;
}

private void getPhysicalDrive( ) {
    IntPtr handle = IntPtr.Zero;
    uint ndevice = 0;

    Win32Functions.CHANGER_PRODUCT_DATA cpd = new Win32Functions.CHANGER_PRODUCT_DATA( );
    IntPtr pcpd = Marshal.AllocHGlobal( Marshal.SizeOf( cpd ) );
    Marshal.StructureToPtr( cpd, pcpd, true );

    do {
        string s = "\\\\.\\PHYSICALDRIVE" + ndevice.ToString( );
        Console.WriteLine( s );

        handle = Win32Functions.CreateFile( s,
                                            0,
                                            Win32Functions.FILE_SHARE_READ | Win32Functions.FILE_SHARE_WRITE,
                                            IntPtr.Zero,
                                            Win32Functions.OPEN_EXISTING,
                                            0,
                                            IntPtr.Zero );
        if ( handle == IntPtr.Zero ) {
            Console.WriteLine( "not Found" );
        }
        else {
            uint nBytes = 0;
            if ( Win32Functions.DeviceIoControl( handle,
                                                 (uint) EIOControlCode.ChangerGetProductData,
                                                 IntPtr.Zero, 0,
                                                 pcpd, ( uint )Marshal.SizeOf( pcpd ),
                                                 ref nBytes,
                                                 IntPtr.Zero )
                                                 > 0 ) {

                Console.WriteLine( cpd.ProductId );
                Console.WriteLine( cpd.DeviceType );
            }
            else {
                Int32 err = Marshal.GetLastWin32Error( );
                Console.WriteLine( "The last Win32 Error was: " + err );
                Console.WriteLine( GetLastWin32ErrorMessage( Marshal.GetLastWin32Error( ) ) );

            }
            Marshal.FreeHGlobal( pcpd );
            if ( !Win32Functions.CloseHandle( handle ) ) {
                Console.WriteLine( "CloseHandle code erreur: {0}", Marshal.GetLastWin32Error( ) );
            }
            ndevice++;
        }
    } while ( handle == IntPtr.Zero );
}

static void Main( string[ ] args ) {
    RawDiskAccess ld = new RawDiskAccess( );
    ld.getPhysicalDrive( );
}

L'éternité c'est long surtout vers la fin...[Insert_Emoticon%28%27/imgs2/smile_wink.gif%27%29; ]
Commenter la réponse de tuxama
tuxama 6 Messages postés lundi 28 janvier 2008Date d'inscription 18 février 2008 Dernière intervention - 10 févr. 2008 à 13:47
0
Utile
Merci de ton aide. DeviceIOControl retourne effectivmeent un bool et je viens de modifier l'appel et la définition ainsi :

if ( Win32Functions.DeviceIoControl( handle,
                                                         (uint) EIOControlCode.ChangerGetProductData,
                                                         IntPtr.Zero, 0,
                                                         pcpd, ( uint )Marshal.SizeOf( pcpd ),
                                                         ref nBytes,
                                                         IntPtr.Zero ) ) {
                                                        
                        Console.WriteLine( cpd.ProductId );
                        Console.WriteLine( cpd.DeviceType );
                    }

[System.Runtime.InteropServices.DllImport( "Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto )]
public extern static bool DeviceIoControl(
    IntPtr hDevice,
    uint IoControlCode,
    IntPtr lpInBuffer,
    uint InBufferSize,
    IntPtr lpOutBuffer,
    uint nOutBufferSize,
    ref uint lpBytesReturned,
    IntPtr lpOverlapped
    );

Mais j'ai toujous une erreur "Accès refusé"...

L'éternité c'est long surtout vers la fin...[Insert_Emoticon%28%27/imgs2/smile_wink.gif%27%29; ]
Commenter la réponse de tuxama
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 10 févr. 2008 à 15:07
0
Utile
Es-tu sûr que IOCTL_CHANGER_GET_PRODUCT_DATA s'applique aux disques et pas aux autres péréiphériques, les codes disque me semblent réunis dans "Disk Management Control Codes" ( IOCTL_DISK_* ).
Commenter la réponse de Lutinore
tuxama 6 Messages postés lundi 28 janvier 2008Date d'inscription 18 février 2008 Dernière intervention - 18 févr. 2008 à 22:32
0
Utile
Bonsoir Lutinore,

Ta réponse est me semble t-il à la fois juste et imcomplète. Car en effet s'il ne faut pas confondre les DISK et les CHANGER il n'en demeure pas moins que la possibilité nous est offerte (dans la doc msdn) de récupérer des infos uniquement accessiblent par IOCTL_GET_CHANGER_PRODUCT_DATA.

Pour récupérer comme dans les exemples MS la géométrie du disque pas de problème (en C# et C++ non managé sous VS 2008).
En revanche (pas d'exemple MS, j'en trouve pas) je prends un code retour 5, accès refusé, dès lors que je tente de récupérer les infos CHANGER_PRODUCT_DATA (en C# et C++ non managé sous VS 2008).

la doc msdn
The following control codes are used with changer devices.

Value |Meaning |----
[Insert_Emoticon%28%27/imgs2/smile_wink.gif%27%29; ]
Commenter la réponse de tuxama
tuxama 6 Messages postés lundi 28 janvier 2008Date d'inscription 18 février 2008 Dernière intervention - 18 févr. 2008 à 23:12
0
Utile
Après re-lecture de ton post j'ai voulu vérifier quelque chose (parfois je suis un peu borné )

Lors du createfile( DEVICE_NAME, ....
l'on précise le "nom de device". ET LA OUI TU AS RAISON il faut indiquer @"\\.\Changer0" dès lors que l'on indique un code de controle IOCTL_CHANGER !!

C'est en clair dans la doc :
Changer Device
The IOCTL_CHANGER_* control codes accept a handle to a changer device. To
open a changer device, use a file name of the following form:
\\.\Changerx where x is a number that indicates which device to
open, starting with zero (0). To open changer device zero (0) in an application
that is written in C or C++, use the following file name: "\\\\.\\Changer0".

Merci de m'avoir ouvert les yeux !

L'éternité c'est long surtout vers la fin...[Insert_Emoticon%28%27/imgs2/smile_wink.gif%27%29; ]
Commenter la réponse de tuxama
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 19 févr. 2008 à 06:34
0
Utile
lu.
Commenter la réponse de Lutinore

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.