this slowpoke moves

Get all USB Devices and Eject

Der folgende Code ist ein Beispiel dafür, wie eine USB-HUB-Schnittstelle auf jedem Windows-System angesprochen werden kann.

Es spielt keine Rolle, ob der HUB Onboard oder über einen HUB-Slot oder eine USB-PCI-Karte Daten versendet.

Ein Beispiel für das Auswerfen eines USB-Sticks über jeden der genannten Eingänge ist kein Problem. Doch lassen sich auch andere aller Art Geräte auflisten und entfernen.

Unit EjectUSB.pas
unit EjectUSB;

interface

uses
    Windows, SysUtils, Classes, Dialogs, ShlObj;

const
{    BusTypeUnknown                      = $0000;
    BusTypeScsi                         = $0001;}
    BusTypeAtapi                        = $0002;
    BusTypeAta                          = $0003;
    BusType1394                         = $0004;
{    BusTypeSsa                          = $0005;
    BusTypeFibre                        = $0006;}
    BusTypeUsb                          = $0007;
{    BusTypeRAID                         = $0008;
    BusTypeiSCSI                        = $0009;
    BusTypeSas                          = $000A;
    BusTypeSata                         = $000B;
    BusTypeSd                           = $000C;
    BusTypeMmc                          = $000D;
    BusTypeMax                          = $000E;
    BusTypeMaxReserved                  = $007F;}

    PNP_VetoTypeUnknown                 = $0000;
{    PNP_VetoLegacyDevice                = $0001;
    PNP_VetoPendingClose                = $0002;
    PNP_VetoWindowsApp                  = $0003;
    PNP_VetoWindowsService              = $0004;
    PNP_VetoOutstandingOpen             = $0005;
    PNP_VetoDevice                      = $0006;
    PNP_VetoDriver                      = $0007;
    PNP_VetoIllegalDeviceRequest        = $0008;
    PNP_VetoInsufficientPower           = $0009;
    PNP_VetoNonDisableable              = $000A;
    PNP_VetoLegacyDriver                = $000B;
    PNP_VetoInsufficientRights          = $000C;}

    CR_SUCCESS                  = $00000000;
{    CR_DEFAULT                  = $00000001;
    CR_OUT_OF_MEMORY            = $00000002;
    CR_INVALID_POINTER          = $00000003;
    CR_INVALID_FLAG             = $00000004;
    CR_INVALID_DEVNODE          = $00000005;
    CR_INVALID_DEVINST          = CR_INVALID_DEVNODE;
    CR_INVALID_RES_DES          = $00000006;
    CR_INVALID_LOG_CONF         = $00000007;
    CR_INVALID_ARBITRATOR       = $00000008;
    CR_INVALID_NODELIST         = $00000009;
    CR_DEVNODE_HAS_REQS         = $0000000A;
    CR_DEVINST_HAS_REQS         = CR_DEVNODE_HAS_REQS;
    CR_INVALID_RESOURCEID       = $0000000B;
    CR_DLVXD_NOT_FOUND          = $0000000C;   // WIN 95 ONLY
    CR_NO_SUCH_DEVNODE          = $0000000D;
    CR_NO_SUCH_DEVINST          = CR_NO_SUCH_DEVNODE;
    CR_NO_MORE_LOG_CONF         = $0000000E;
    CR_NO_MORE_RES_DES          = $0000000F;
    CR_ALREADY_SUCH_DEVNODE     = $00000010;
    CR_ALREADY_SUCH_DEVINST     = CR_ALREADY_SUCH_DEVNODE;
    CR_INVALID_RANGE_LIST       = $00000011;
    CR_INVALID_RANGE            = $00000012;
    CR_FAILURE                  = $00000013;
    CR_NO_SUCH_LOGICAL_DEV      = $00000014;
    CR_CREATE_BLOCKED           = $00000015;
    CR_NOT_SYSTEM_VM            = $00000016;   // WIN 95 ONLY
    CR_REMOVE_VETOED            = $00000017;
    CR_APM_VETOED               = $00000018;
    CR_INVALID_LOAD_TYPE        = $00000019;
    CR_BUFFER_SMALL             = $0000001A;
    CR_NO_ARBITRATOR            = $0000001B;
    CR_NO_REGISTRY_HANDLE       = $0000001C;
    CR_REGISTRY_ERROR           = $0000001D;
    CR_INVALID_DEVICE_ID        = $0000001E;
    CR_INVALID_DATA             = $0000001F;
    CR_INVALID_API              = $00000020;
    CR_DEVLOADER_NOT_READY      = $00000021;
    CR_NEED_RESTART             = $00000022;
    CR_NO_MORE_HW_PROFILES      = $00000023;
    CR_DEVICE_NOT_THERE         = $00000024;
    CR_NO_SUCH_VALUE            = $00000025;
    CR_WRONG_TYPE               = $00000026;
    CR_INVALID_PRIORITY         = $00000027;
    CR_NOT_DISABLEABLE          = $00000028;
    CR_FREE_RESOURCES           = $00000029;
    CR_QUERY_VETOED             = $0000002A;
    CR_CANT_SHARE_IRQ           = $0000002B;
    CR_NO_DEPENDENT             = $0000002C;
    CR_SAME_RESOURCES           = $0000002D;
    CR_NO_SUCH_REGISTRY_KEY     = $0000002E;
    CR_INVALID_MACHINENAME      = $0000002F;   // NT ONLY
    CR_REMOTE_COMM_FAILURE      = $00000030;   // NT ONLY
    CR_MACHINE_UNAVAILABLE      = $00000031;   // NT ONLY
    CR_NO_CM_SERVICES           = $00000032;   // NT ONLY
    CR_ACCESS_DENIED            = $00000033;   // NT ONLY
    CR_CALL_NOT_IMPLEMENTED     = $00000034;
    CR_INVALID_PROPERTY         = $00000035;
    CR_DEVICE_INTERFACE_ACTIVE  = $00000036;
    CR_NO_SUCH_DEVICE_INTERFACE = $00000037;
    CR_INVALID_REFERENCE_STRING = $00000038;
    CR_INVALID_CONFLICT_LIST    = $00000039;
    CR_INVALID_INDEX            = $0000003A;
    CR_INVALID_STRUCTURE_SIZE   = $0000003B;
    NUM_CR_RESULTS              = $0000003C;}

{    FILE_DEVICE_BEEP                = $00000001;
    FILE_DEVICE_CD_ROM              = $00000002;
    FILE_DEVICE_CD_ROM_FILE_SYSTEM  = $00000003;
    FILE_DEVICE_CONTROLLER          = $00000004;
    FILE_DEVICE_DATALINK            = $00000005;
    FILE_DEVICE_DFS                 = $00000006;
    FILE_DEVICE_DISK                = $00000007;
    FILE_DEVICE_DISK_FILE_SYSTEM    = $00000008;
    FILE_DEVICE_FILE_SYSTEM         = $00000009;
    FILE_DEVICE_INPORT_PORT         = $0000000a;
    FILE_DEVICE_KEYBOARD            = $0000000b;
    FILE_DEVICE_MAILSLOT            = $0000000c;
    FILE_DEVICE_MIDI_IN             = $0000000d;
    FILE_DEVICE_MIDI_OUT            = $0000000e;
    FILE_DEVICE_MOUSE               = $0000000f;
    FILE_DEVICE_MULTI_UNC_PROVIDER  = $00000010;
    FILE_DEVICE_NAMED_PIPE          = $00000011;
    FILE_DEVICE_NETWORK             = $00000012;
    FILE_DEVICE_NETWORK_BROWSER     = $00000013;
    FILE_DEVICE_NETWORK_FILE_SYSTEM = $00000014;
    FILE_DEVICE_NULL                = $00000015;
    FILE_DEVICE_PARALLEL_PORT       = $00000016;
    FILE_DEVICE_PHYSICAL_NETCARD    = $00000017;
    FILE_DEVICE_PRINTER             = $00000018;
    FILE_DEVICE_SCANNER             = $00000019;
    FILE_DEVICE_SERIAL_MOUSE_PORT   = $0000001a;
    FILE_DEVICE_SERIAL_PORT         = $0000001b;
    FILE_DEVICE_SCREEN              = $0000001c;
    FILE_DEVICE_SOUND               = $0000001d;
    FILE_DEVICE_STREAMS             = $0000001e;
    FILE_DEVICE_TAPE                = $0000001f;
    FILE_DEVICE_TAPE_FILE_SYSTEM    = $00000020;
    FILE_DEVICE_TRANSPORT           = $00000021;
    FILE_DEVICE_UNKNOWN             = $00000022;
    FILE_DEVICE_VIDEO               = $00000023;
    FILE_DEVICE_VIRTUAL_DISK        = $00000024;
    FILE_DEVICE_WAVE_IN             = $00000025;
    FILE_DEVICE_WAVE_OUT            = $00000026;
    FILE_DEVICE_8042_PORT           = $00000027;
    FILE_DEVICE_NETWORK_REDIRECTOR  = $00000028;
    FILE_DEVICE_BATTERY             = $00000029;
    FILE_DEVICE_BUS_EXTENDER        = $0000002a;
    FILE_DEVICE_MODEM               = $0000002b;
    FILE_DEVICE_VDM                 = $0000002c;
    FILE_DEVICE_MASS_STORAGE        = $0000002d;
    FILE_DEVICE_SMB                 = $0000002e;
    FILE_DEVICE_KS                  = $0000002f;
    FILE_DEVICE_CHANGER             = $00000030;
    FILE_DEVICE_SMARTCARD           = $00000031;
    FILE_DEVICE_ACPI                = $00000032;
    FILE_DEVICE_DVD                 = $00000033;
    FILE_DEVICE_FULLSCREEN_VIDEO    = $00000034;
    FILE_DEVICE_DFS_FILE_SYSTEM     = $00000035;
    FILE_DEVICE_DFS_VOLUME          = $00000036;}

    DIGCF_PRESENT                       = $00000002;
    DIGCF_DEVICEINTERFACE               = $00000010;

    GUID_DEVINTERFACE_FLOPPY    : TGUID = (D1:$53f56311;D2:$b6bf;D3:$11d0;D4:($94,$f2,$00,$a0,$c9,$1e,$fb,$8b));
    GUID_DEVINTERFACE_DISK      : TGUID = (D1:$53f56307;D2:$b6bf;D3:$11d0;D4:($94,$f2,$00,$a0,$c9,$1e,$fb,$8b));
    GUID_DEVINTERFACE_CDROM     : TGUID = (D1:$53f56308;D2:$b6bf;D3:$11d0;D4:($94,$f2,$00,$a0,$c9,$1e,$fb,$8b));

    IOCTL_STORAGE_GET_DEVICE_NUMBER     = (($0000002d shl 16) or ($0000 shl 14) or ($0420 shl 2) or 0);
    IOCTL_STORAGE_GET_HOTPLUG_INFO      = (($0000002d shl 16) or ($0000 shl 14) or ($0305 shl 2) or 0);
    IOCTL_STORAGE_MEDIA_REMOVAL         = (($0000002d shl 16) or ($0001 shl 14) or ($0201 shl 2) or 0);
    IOCTL_STORAGE_EJECT_MEDIA           = (($0000002d shl 16) or ($0001 shl 14) or ($0202 shl 2) or 0);
    IOCTL_STORAGE_CHECK_VERIFY          = (($0000002d shl 16) or ($0001 shl 14) or ($0200 shl 2) or 0);
    IOCTL_STORAGE_EJECTION_CONTROL      = (($0000002d shl 16) or ($0000 shl 14) or ($0250 shl 2) or 0);
    IOCTL_STORAGE_QUERY_PROPERTY        = (($0000002d shl 16) or ($0000 shl 14) or ($0500 shl 2) or 0);
{    IOCTL_STORAGE_SET_HOTPLUG_INFO      = (($0000002d shl 16) or (($0001 or $0002) shl 14) or ($0306 shl 2) or 0);
    IOCTL_STORAGE_LOAD_MEDIA            = (($0000002d shl 16) or ($0001 shl 14) or ($0203 shl 2) or 0);
    IOCTL_STORAGE_RESERVE               = (($0000002d shl 16) or ($0001 shl 14) or ($0204 shl 2) or 0);
    IOCTL_STORAGE_RELEASE               = (($0000002d shl 16) or ($0001 shl 14) or ($0205 shl 2) or 0);
    IOCTL_STORAGE_FIND_NEW_DEVICES      = (($0000002d shl 16) or ($0001 shl 14) or ($0206 shl 2) or 0);
    IOCTL_STORAGE_GET_MEDIA_TYPES       = (($0000002d shl 16) or ($0000 shl 14) or ($0300 shl 2) or 0);
    IOCTL_STORAGE_GET_MEDIA_TYPES_EX    = (($0000002d shl 16) or ($0000 shl 14) or ($0301 shl 2) or 0);
    IOCTL_STORAGE_RESET_BUS             = (($0000002d shl 16) or ($0001 shl 14) or ($0400 shl 2) or 0);
    IOCTL_STORAGE_RESET_DEVICE          = (($0000002d shl 16) or ($0001 shl 14) or ($0401 shl 2) or 0);}

    FSCTL_LOCK_VOLUME                   = (($00000009 shl 16) or ($0000 shl 14) or (00006 shl 2) or 0);
    FSCTL_DISMOUNT_VOLUME               = (($00000009 shl 16) or ($0000 shl 14) or (00008 shl 2) or 0);
    FSCTL_UNLOCK_VOLUME                 = (($00000009 shl 16) or ($0000 shl 14) or (00007 shl 2) or 0);

type
    PPNP_VETO_TYPE      = ^PNP_VETO_TYPE;
    PNP_VETO_TYPE       = DWORD;

    PDEVINST            = ^DEVINST;
    DEVINST             = DWORD;

    PRETURN_TYPE        = ^RETURN_TYPE;
    RETURN_TYPE         = DWORD;

    PCONFIGRET          = ^CONFIGRET;
    CONFIGRET           = RETURN_TYPE;

    PHDEVINFO           = ^HDEVINFO;
    HDEVINFO            = Pointer;

    PDEVICE_TYPE        = ^DEVICE_TYPE;
    DEVICE_TYPE         = DWORD;

    PSTORAGE_BUS_TYPE   = ^STORAGE_BUS_TYPE;
    STORAGE_BUS_TYPE    = DWORD;

    PULONG_PTR          = ^ULONG_PTR;
    ULONG_PTR           = LONGWORD;

    PPTSTR              = ^LPWSTR;
    PTSTR               = LPWSTR;

    PSPDeviceInterfaceData = ^TSPDeviceInterfaceData;
    SP_DEVICE_INTERFACE_DATA = packed record
        cbSize              : DWORD;
        InterfaceClassGuid  : TGUID;
        Flags               : DWORD;
        Reserved            : ULONG_PTR;
    end;
    TSPDeviceInterfaceData = SP_DEVICE_INTERFACE_DATA;

    PSPDevInfoData = ^TSPDevInfoData;
    SP_DEVINFO_DATA = packed record
        cbSize    : DWORD;
        ClassGuid : TGUID;
        DevInst   : DWORD;
        Reserved  : ULONG_PTR;
    end;
    TSPDevInfoData = SP_DEVINFO_DATA;

    PSPDeviceInterfaceDetailDataA = ^TSPDeviceInterfaceDetailDataA;
    PSPDeviceInterfaceDetailDataW = ^TSPDeviceInterfaceDetailDataW;
    SP_DEVICE_INTERFACE_DETAIL_DATA_A = packed record
        cbSize      : DWORD;
        DevicePath  : array [0..0] of AnsiChar;
    end;
    SP_DEVICE_INTERFACE_DETAIL_DATA_W = packed record
        cbSize      : DWORD;
        DevicePath  : array [0..0] of WideChar;
    end;
    TSPDeviceInterfaceDetailDataA = SP_DEVICE_INTERFACE_DETAIL_DATA_A;
    TSPDeviceInterfaceDetailDataW = SP_DEVICE_INTERFACE_DETAIL_DATA_W;
    {$IFDEF UNICODE}
        TSPDeviceInterfaceDetailData = TSPDeviceInterfaceDetailDataW;
        PSPDeviceInterfaceDetailData = PSPDeviceInterfaceDetailDataW;
    {$ELSE}
        TSPDeviceInterfaceDetailData = TSPDeviceInterfaceDetailDataA;
        PSPDeviceInterfaceDetailData = PSPDeviceInterfaceDetailDataA;
    {$ENDIF UNICODE}
    
    PSTORAGE_DEVICE_NUMBER = ^TSTORAGE_DEVICE_NUMBER;
        STORAGE_DEVICE_NUMBER = record
            DeviceType      : DEVICE_TYPE;
            DeviceNumber    : DWORD;
            PartitionNumber : DWORD;
        end;
    TSTORAGE_DEVICE_NUMBER = STORAGE_DEVICE_NUMBER;

    DEV_BROADCAST_HDR = ^PDEV_BROADCAST_HDR;
        PDEV_BROADCAST_HDR  = packed record
            dbch_size         : DWORD;
            dbch_devicetype   : DWORD;
            dbch_reserved     : DWORD;
        end;

    DEV_BROADCAST_VOLUME = ^PDEV_BROADCAST_VOLUME;
        PDEV_BROADCAST_VOLUME = packed record
            dbcv_size           : DWORD;
            dbcv_devicetype     : DWORD;
            dbcv_reserved       : DWORD;
            dbcv_unitmask       : DWORD;
            dbcv_flags          : WORD;
        end;

    PSTORAGE_HOTPLUG_INFO = ^TSTORAGE_HOTPLUG_INFO;
        STORAGE_HOTPLUG_INFO = packed record
            Size                        : DWORD;
            MediaRemovable              : BOOLEAN;
            MediaHotplug                : BOOLEAN;
            DeviceHotplug               : BOOLEAN;
            WriteCacheEnableOverride    : BOOLEAN;
        end;
    TSTORAGE_HOTPLUG_INFO = STORAGE_HOTPLUG_INFO;

    PSTORAGE_PROPERTY_QUERY = ^TSTORAGE_PROPERTY_QUERY;
        STORAGE_PROPERTY_QUERY = packed record
            PropertyId          : DWORD;
            QueryType           : DWORD;
            AdditionalParameters: array[0..3] of Byte;
        end;
     TSTORAGE_PROPERTY_QUERY = STORAGE_PROPERTY_QUERY;

    PSTORAGE_DEVICE_DESCRIPTOR = ^TSTORAGE_DEVICE_DESCRIPTOR;
        STORAGE_DEVICE_DESCRIPTOR = packed record
            Version                 : ULONG;
            Size                    : ULONG;
            DeviceType              : Byte;
            DeviceTypeModifier      : Byte;
            RemovableMedia          : Boolean;
            CommandQueueing         : Boolean;
            VendorIdOffset          : ULONG;
            ProductIdOffset         : ULONG;
            ProductRevisionOffset   : ULONG;
            SerialNumberOffset      : ULONG;
            BusType                 : STORAGE_BUS_TYPE;
            RawPropertiesLength     : ULONG;
            RawDeviceProperties     : array [0..MAX_PATH] of Byte;
        end;
    TSTORAGE_DEVICE_DESCRIPTOR = STORAGE_DEVICE_DESCRIPTOR;

{    PSTORAGE_BUS_RESET_REQUEST = ^TSTORAGE_BUS_RESET_REQUEST;
        STORAGE_BUS_RESET_REQUEST = packed record
            PathId : Byte;
        end;
    TSTORAGE_BUS_RESET_REQUEST = STORAGE_BUS_RESET_REQUEST;

    STORAGE_MEDIA_TYPE = DWORD;
    PDEVICE_MEDIA_INFO = ^TDEVICE_MEDIA_INFO;
        DEVICE_MEDIA_INFO = packed record
            DeviceSpecific : packed record
            case BYTE of
                0 :(DiskInfo : packed record
                        Cylinders           : LARGE_INTEGER;
                        MediaType           : STORAGE_MEDIA_TYPE;
                        TracksPerCylinder   : DWORD;//ULONG
                        SectorsPerTrack     : DWORD;
                        BytesPerSector      : DWORD;
                        NumberMediaSides    : DWORD;
                        MediaCharacteristics: DWORD;
                    end );
                1 :(RemovableDiskInfo : packed record
                        Cylinders           : LARGE_INTEGER;
                        MediaType           : STORAGE_MEDIA_TYPE;
                        TracksPerCylinder   : DWORD;
                        SectorsPerTrack     : DWORD;
                        BytesPerSector      : DWORD;
                        NumberMediaSides    : DWORD;
                        MediaCharacteristics: DWORD;
                    end );
                2 :(TapeInfo : packed record
                        MediaType           : STORAGE_MEDIA_TYPE;
                        MediaCharacteristics: DWORD;
                        CurrentBlockSize    : DWORD;
                        BusType             : STORAGE_BUS_TYPE;
                        BusSpecificData : packed record
                        case INTEGER of
                        0 :(ScsiInformation : packed record
                                MediumType  : BYTE;//UCHAR
                                DensityCode : BYTE;
                            end );
                        end;
                    end );
            end;
    end;
    TDEVICE_MEDIA_INFO = DEVICE_MEDIA_INFO;

    PGET_MEDIA_TYPES = ^TGET_MEDIA_TYPES;
        GET_MEDIA_TYPES = packed record
            DeviceType      : DWORD;
            MediaInfoCount  : DWORD;
            MediaInfo       : array [0..0] of DEVICE_MEDIA_INFO;
        end;
    TGET_MEDIA_TYPES = GET_MEDIA_TYPES;}

    TDrive = packed record
        Volume          : String;
        VolumeName      : String;
        TailleLib       : String;
        TailleTot       : String;
        SystFich        : String;
        Properties      : String;
        DeviceType      : DWORD;
        BusType         : STORAGE_BUS_TYPE;
        MediaRemovable  : BOOLEAN;
        MediaHotplug    : BOOLEAN;
        DeviceHotplug   : BOOLEAN;
        Partition       : Integer;
    end;

    TPREVENT_MEDIA_REMOVAL = record
        PreventMediaRemoval : ByteBool;
    end;

    function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall;external 'SetupApi.dll';
    function SetupDiEnumDeviceInterfaces(DeviceInfoSet:HDEVINFO;DeviceInfoData:PSPDevInfoData;
        const InterfaceClassGuid:TGUID;MemberIndex:DWORD;var DeviceInterfaceData:TSPDeviceInterfaceData):BOOL;stdcall;external 'SetupApi.dll';
    function CM_Get_Parent(var dnDevInstParent:DEVINST;dnDevInst:DEVINST;ulFlags:ULONG):CONFIGRET;stdcall;external 'CfgMgr32.dll';

    function CM_Query_And_Remove_SubTreeW(dnAncestor: DEVINST;pVetoType: PPNP_VETO_TYPE; pszVetoName: PWideChar;
        ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall;
    function CM_Query_And_Remove_SubTreeA(dnAncestor: DEVINST;pVetoType: PPNP_VETO_TYPE; pszVetoName: PAnsiChar;
        ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall;
    function CM_Query_And_Remove_SubTree(dnAncestor: DEVINST;pVetoType: PPNP_VETO_TYPE; pszVetoName: PTSTR;
        ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall;

    function CM_Request_Device_EjectW(dnDevInst:DEVINST;pVetoType:PPNP_VETO_TYPE;pszVetoName:PWideChar;
        ulNameLength:ULONG;ulFlags: ULONG):CONFIGRET; stdcall;
    function CM_Request_Device_EjectA(dnDevInst:DEVINST;pVetoType:PPNP_VETO_TYPE;pszVetoName:PAnsiChar;
        ulNameLength:ULONG;ulFlags: ULONG):CONFIGRET; stdcall;
    function CM_Request_Device_Eject(dnDevInst:DEVINST;pVetoType:PPNP_VETO_TYPE;pszVetoName:PTSTR;
        ulNameLength:ULONG;ulFlags: ULONG):CONFIGRET; stdcall;

    function SetupDiGetClassDevsW(ClassGuid:PGUID;const Enumerator:PWideChar;hwndParent:HWND;Flags:DWORD):HDEVINFO;stdcall;
    function SetupDiGetClassDevsA(ClassGuid:PGUID;const Enumerator:PAnsiChar;hwndParent:HWND;Flags:DWORD):HDEVINFO;stdcall;
    function SetupDiGetClassDevs(ClassGuid:PGUID;const Enumerator:PTSTR;hwndParent:HWND;Flags:DWORD):HDEVINFO;stdcall;

    function SetupDiGetDeviceInterfaceDetailW(DeviceInfoSet:HDEVINFO;DeviceInterfaceData:PSPDeviceInterfaceData;
        DeviceInterfaceDetailData:PSPDeviceInterfaceDetailData;DeviceInterfaceDetailDataSize:DWORD;
        var RequiredSize:DWORD;Device:PSPDevInfoData):BOOL;stdcall;
    function SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet:HDEVINFO;DeviceInterfaceData:PSPDeviceInterfaceData;
        DeviceInterfaceDetailData:PSPDeviceInterfaceDetailData;DeviceInterfaceDetailDataSize:DWORD;
        var RequiredSize:DWORD;Device:PSPDevInfoData):BOOL;stdcall;
    function SetupDiGetDeviceInterfaceDetail(DeviceInfoSet:HDEVINFO;DeviceInterfaceData:PSPDeviceInterfaceData;
        DeviceInterfaceDetailData:PSPDeviceInterfaceDetailData;DeviceInterfaceDetailDataSize:DWORD;
        var RequiredSize:DWORD;Device:PSPDevInfoData):BOOL;stdcall;

{    function CM_Reenumerate_DevNode(dnDevInst: DEVINST;ulFlags: ULONG): CONFIGRET; stdcall;external 'CfgMgr32.dll';
    function GetVolumeNameForVolumeMountPointW(lpszVolumeMountPoint: LPCWSTR;
        lpszVolumeName: LPWSTR; cchBufferLength: DWORD): BOOL; stdcall;external 'kernel32.dll';
    function SetupDiGetInterfaceDeviceDetailW(DeviceInfoSet:HDEVINFO;DeviceInterfaceData:PSPDeviceInterfaceData;
        DeviceInterfaceDetailData:PSPDeviceInterfaceDetailDataW;DeviceInterfaceDetailDataSize:DWORD;RequiredSize:PDWORD;
        Device:PSPDevInfoData):BOOL;stdcall;external 'SetupApi.dll';}

    function DeviceNumberDrive(DeviceNumber:Integer;DriveType:UINT;szDosDeviceName:PCHAR):DEVINST;
    function Eject_USB(LetVol:Char;Rep,TempRep:Integer;MessageEject,MultiSupport:Boolean):Boolean;stdcall;
    function Eject_DevHotPlugMedia(LetVol:Char;Rep,TempRep:Integer;MessageEject,MediaRemove:Boolean):Boolean;
    function Eject_DevHotPlug(LetVol:Char;Rep,TempRep:Integer;MessageEject,RemoveMediaHotPlug:Boolean):Boolean;

    Procedure Liste_USB(Lecteurs:TStrings;DriveRemovable,DriveFixed,DriveCDRom:Boolean);stdcall;

implementation

const
    {$IFDEF UNICODE}
        LettreFin = 'W';
    {$ELSE}
        LettreFin = 'A';
    {$ENDIF UNICODE}

Var
    Drive : TDrive;

function DeviceNumberDrive(DeviceNumber:Integer;DriveType:UINT;szDosDeviceName:PCHAR):DEVINST;
var
    IsFloppy                            : Boolean;
    BoucWh                              : Boolean;
    ValGUID                             : TGUID;
    ValHDevInfo                         : HDEVINFO;
    hDrive                              : THandle;
    dwIndex, dwSize, dwBytesReturned    : DWORD;
    FunctionResult                      : Boolean;
    SPDeviceInterfaceDetailData         : PSPDeviceInterfaceDetailData;
    SPDeviceInterfaceData               : SP_DEVICE_INTERFACE_DATA;
    SPDevInfoData                       : SP_DEVINFO_DATA;
    StorageDeviceNumber                 : STORAGE_DEVICE_NUMBER;
begin
    Result:=0;
    IsFloppy:=true;
    if StrPos(szDosDeviceName, '\Floppy') = nil then
        IsFloppy:=false;
    case (DriveType)  of
        DRIVE_REMOVABLE :   if ( IsFloppy ) then
                            begin
                                ValGUID := GUID_DEVINTERFACE_FLOPPY;
                            end
                            else
                            begin
                                ValGUID := GUID_DEVINTERFACE_DISK;
                            end;
        DRIVE_FIXED :       ValGUID := GUID_DEVINTERFACE_DISK;
        DRIVE_CDROM :       ValGUID := GUID_DEVINTERFACE_CDROM;
    else
        exit;
    end;

    ValHDevInfo := SetupDiGetClassDevs(@ValGUID,nil,0,DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
    if (Cardinal(ValHDevInfo)=INVALID_HANDLE_VALUE) then
        exit;

    dwIndex := 0;
    ZeroMemory(@SPDevInfoData,SizeOf(SPDevInfoData));
    SPDeviceInterfaceData.cbSize:=SizeOf(SPDeviceInterfaceData);

    BoucWh:=True;
    while (BoucWh=true) do
    begin
        FunctionResult:=SetupDiEnumDeviceInterfaces(ValHDevInfo,nil,ValGUID,dwIndex,SPDeviceInterfaceData);
        if FunctionResult=False then
            break;
        dwSize:=0;
        SetupDiGetDeviceInterfaceDetail(ValHDevInfo,@SPDeviceInterfaceData,nil,0,dwSize,nil);
        if (dwSize<>0)and(dwSize<=1024)then
        begin
            GetMem(SPDeviceInterfaceDetailData,dwSize);
            try
                SPDeviceInterfaceDetailData.cbSize:=SizeOf(SPDeviceInterfaceDetailData^);
                ZeroMemory(@SPDevInfoData,SizeOf(SPDevInfoData));
                SPDevInfoData.cbSize:=SizeOf(SPDevInfoData);
                FunctionResult:=SetupDiGetDeviceInterfaceDetail(ValHDevInfo,@SPDeviceInterfaceData,SPDeviceInterfaceDetailData,dwSize,dwSize,@SPDevInfoData);
                if FunctionResult then
                begin
                    hDrive:=DWORD(-1);
                    try
                        hDrive := CreateFile(SPDeviceInterfaceDetailData.DevicePath,0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
                        if (hDrive<>INVALID_HANDLE_VALUE) then
                        begin
                            dwBytesReturned := 0;
                            FunctionResult := DeviceIoControl(hDrive,IOCTL_STORAGE_GET_DEVICE_NUMBER,nil,0,@StorageDeviceNumber,SizeOf(StorageDeviceNumber),dwBytesReturned, nil);
                            if FunctionResult  then
                            begin
                                if DeviceNumber = LongInt(StorageDeviceNumber.DeviceNumber) then
                                begin
                                    Result:= SPDevInfoData.DevInst;
                                    break;
                                end;
                            end;
                        end;
                    finally
                        CloseHandle(hDrive);
                    end;
                end;
            finally
                FreeMem(SPDeviceInterfaceDetailData);
            end;
        end;
        dwIndex:=dwIndex+1;
    end;
    SetupDiDestroyDeviceInfoList(ValHDevInfo);
end;

function Eject_DevHotPlug(LetVol:Char;Rep,TempRep:Integer;MessageEject,RemoveMediaHotPlug:Boolean):Boolean;
var
    DeviceNumber        : LongInt;
    dwBytesReturned     : DWord;
    DriveType           : UINT;
    hVolume             : THandle;
    StorageDeviceNumber : STORAGE_DEVICE_NUMBER;
    I                   : Integer;
    ResultInt           : DWORD;
    ResultIntNod        : DWORD;
    ResultBool          : Boolean;
    DeviceInst          : DEVINST;
    DevInstParent       : DEVINST;
    szDosDeviceName     : array[0..MAX_PATH] of Char;
    VetoType            : PNP_VETO_TYPE;
    VetoNameW           : array[0..MAX_PATH] of WChar;
begin
    Result:=False;
    DeviceNumber:=-1;
    hVolume:=INVALID_HANDLE_VALUE;
    try
        hVolume:=CreateFile(PChar('\\.\'+LetVol+':'),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if hVolume=INVALID_HANDLE_VALUE then
            exit;
        dwBytesReturned:=0;
        ResultBool:=DeviceIoControl(hVolume,IOCTL_STORAGE_GET_DEVICE_NUMBER,nil,0,@StorageDeviceNumber,SizeOf(StorageDeviceNumber),dwBytesReturned,nil);
        if ResultBool = True  then
            DeviceNumber:=StorageDeviceNumber.DeviceNumber;
    finally
        CloseHandle(hVolume);
    end;
    if DeviceNumber=-1 then
        exit;


    DriveType:=GetDriveType(PChar(String(LetVol+':')));
    szDosDeviceName[0]:=#0;
    ResultInt:=QueryDosDevice(PChar(String(LetVol+':')),szDosDeviceName,MAX_PATH);
    if ResultInt=0 then
        exit;

    DeviceInst:=DeviceNumberDrive(DeviceNumber,DriveType,szDosDeviceName);
    if DeviceInst = 0 then
        exit;

    VetoType := PNP_VetoTypeUnknown;
    VetoNameW[0] := #0;
    DevInstParent := 0;
//    http://msdn.microsoft.com/en-us/library/ms791198.aspx
    CM_Get_Parent(DevInstParent, DeviceInst, 0);

    if not RemoveMediaHotPlug then
    begin
        for I := 0 to Rep - 1 do
        begin
            VetoNameW[0] := #0;
//            http://msdn.microsoft.com/en-us/library/ms790831.aspx
            if MessageEject then
                ResultInt:=CM_Request_Device_Eject(DevInstParent,nil,nil,0,0)
            else
                ResultInt:=CM_Request_Device_Eject(DevInstParent,@VetoType,VetoNameW,MAX_PATH,0);
            if (ResultInt=CR_SUCCESS)and(VetoType=PNP_VetoTypeUnknown) then
            begin
                Result:=True;
                Break;
            end;
            Sleep(TempRep);
        end;
    end
    else
    begin  // if CM_Request_Device_Eject(DevInstParent,@VetoType,VetoNameW,MAX_PATH,0)=CR_REMOVE_VETOED then CM_Query_And_Remove_SubTree(DeviceInst,nil,nil,0,0);
        for I := 0 to Rep - 1 do
        begin
            VetoNameW[0] := #0;
//            http://msdn.microsoft.com/en-us/library/ms790877.aspx
            if MessageEject then
                ResultIntNod:=CM_Query_And_Remove_SubTree(DeviceInst,nil,nil,0,0)
            else
                ResultIntNod:=CM_Query_And_Remove_SubTree(DeviceInst,@VetoType,VetoNameW,MAX_PATH,0);
            if (ResultIntNod=CR_SUCCESS)and(VetoType=PNP_VetoTypeUnknown) then
            begin
                Result:=True;
                if MessageEject then
                    MessageDlg('The material can be removed safely !',mtInformation,[mbOK],0);
                Break;
            end;
            Sleep(TempRep);
        end;
    end;
end;

function Eject_DevHotPlugMedia(LetVol:Char;Rep,TempRep:Integer;MessageEject,MediaRemove: Boolean):Boolean;
var
    HVolume             : THandle;
    lpBytesReturned     : DWORD;
    PreventRemoval      : TPREVENT_MEDIA_REMOVAL;
    FormatLettreLecteur : String;
    I                   : Integer;
begin
    Result:=False;
    hVolume:=INVALID_HANDLE_VALUE;
    try
        hVolume:=CreateFile(PChar('\\.\'+LetVol+':'),FILE_SHARE_READ or FILE_SHARE_WRITE,0,nil,OPEN_EXISTING,0,0);
        if hVolume=INVALID_HANDLE_VALUE then
            hVolume:=CreateFile(PChar('\\.\'+LetVol+':'),GENERIC_READ,0,nil,OPEN_EXISTING,0,0);
        if hVolume=INVALID_HANDLE_VALUE then
            hVolume:=CreateFile(PChar('\\.\'+LetVol+':'),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if hVolume=INVALID_HANDLE_VALUE then
            exit;
        for I := 0 to Rep - 1 do
        begin
            PreventRemoval.PreventMediaRemoval:=False;
            if DeviceIoControl(hVolume,FSCTL_LOCK_VOLUME, nil,0,nil,0,lpBytesReturned,nil) then
                if DeviceIoControl(hVolume,FSCTL_DISMOUNT_VOLUME, nil,0,nil,0,lpBytesReturned,nil) then
                    if DeviceIoControl(hVolume,IOCTL_STORAGE_MEDIA_REMOVAL,@PreventRemoval,SizeOf(TPREVENT_MEDIA_REMOVAL),nil,0,lpBytesReturned,nil) then
                        if DeviceIoControl(hVolume,IOCTL_STORAGE_EJECT_MEDIA,nil,0,nil,0,lpBytesReturned,nil)then
                            if DeviceIoControl(hVolume,FSCTL_UNLOCK_VOLUME,nil,0,nil,0,lpBytesReturned,nil) then
                            begin
                                FormatLettreLecteur:=Format('%s:\',[Uppercase(LetVol)]);
                                ShChangeNotify(SHCNE_MEDIAREMOVED,SHCNF_PATH,PChar(FormatLettreLecteur),Nil);
                                Result:=True;
                                if (MessageEject) and (not MediaRemove) then
                                    MessageDlg('The material can be removed safely !',mtInformation,[mbOK],0);
                                if (MessageEject) and (MediaRemove) then
                                    MessageDlg('The drive is open !',mtInformation,[mbOK],0);
                                Break;
                            end;
            if not Result then
                Sleep(TempRep);
        end;
    finally
        CloseHandle(hVolume);
    end;

    if (not Result) and (MessageEject) and (MediaRemove) then
        MessageDlg('The drive is in use by another process !',mtWarning,[mbOK],0);
    if (not Result) and (not MediaRemove) then
        Eject_DevHotPlug(LetVol,Rep,TempRep,MessageEject,False);
end;

function Eject_USB(LetVol:Char;Rep,TempRep:Integer;MessageEject,MultiSupport:Boolean):Boolean;
var
    hVolume             : THandle;
    GetMediaTypes       : STORAGE_HOTPLUG_INFO;
    lpBytesReturned     : DWORD;
begin
    Result:=False;
    hVolume:=INVALID_HANDLE_VALUE;
    try
        hVolume:=CreateFile(PChar('\\.\'+LetVol+':'),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if hVolume=INVALID_HANDLE_VALUE then
            exit;
        DeviceIoControl(hVolume,IOCTL_STORAGE_GET_HOTPLUG_INFO,nil,0,@GetMediaTypes,sizeof(GetMediaTypes),lpBytesReturned,nil);
    finally
        CloseHandle(hVolume);
    end;
    if (GetMediaTypes.DeviceHotplug) and (GetMediaTypes.MediaRemovable) and (MultiSupport=False) then
    begin
        if Eject_DevHotPlugMedia(LetVol,Rep,TempRep,MessageEject,False) then
            Result:=True;
    end
    else
        if GetMediaTypes.DeviceHotplug then
        begin
            if Eject_DevHotPlug(LetVol,Rep,TempRep,MessageEject,False)then
                Result:=True;
        end
        else
            if (GetMediaTypes.MediaRemovable) and (GetMediaTypes.MediaHotplug) then
            begin
                if Eject_DevHotPlug(LetVol,Rep,TempRep,MessageEject,True)then
                    Result:=True;
            end
            else
                if GetMediaTypes.MediaRemovable then
                begin
                    if Eject_DevHotPlugMedia(LetVol,Rep,TempRep,MessageEject,True) then
                        Result:=True;
                end
                else
                    MessageDlg('It is impossible to eject an internal device !',mtWarning,[mbOK],0);
end;


{function GetVolumeNameForVolumeMountPointString(LetVol: Char): string;
var
    Volume: array [0..MAX_PATH] of Char;
begin
    if GetDriveType(PChar(Format('%s:\',[Uppercase(LetVol)])))=DRIVE_REMOVABLE then
    begin
        FillChar(Volume[0],SizeOf(Volume),0);
        GetVolumeNameForVolumeMountPointW(PChar(Format('%s:\',[Uppercase(LetVol)])),@Volume[0],SizeOf(Volume));
        Result:=Volume;
    end;
end;}

//Partie informations peripherique

Procedure StorageDeviceNumberString(Disque:String);
var
    HFile               : THandle;
    lpBytesReturned       : DWORD;
    StorageDeviceNumber : STORAGE_DEVICE_NUMBER;
begin
    Drive.DeviceType:=0;
    Drive.Partition:=0;
    HFile:=INVALID_HANDLE_VALUE;
    try
        HFile:=CreateFile(PChar('\\.\'+Disque),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if HFile<>INVALID_HANDLE_VALUE then
        begin
            DeviceIoControl(HFile,IOCTL_STORAGE_GET_DEVICE_NUMBER,nil,0,@StorageDeviceNumber,SizeOf(StorageDeviceNumber),lpBytesReturned, nil);
            Drive.DeviceType:=StorageDeviceNumber.DeviceType;
            Drive.Partition:=StorageDeviceNumber.PartitionNumber;
        end;
    finally
        CloseHandle(HFile);
    end;
end;

{Procedure StorageMediaTypeString(Disque:String);
var
    HFile               : THandle;
    lpBytesReturned     : DWORD;
    StorageMediaType    : GET_MEDIA_TYPES;
    MediaTypes          : PGET_MEDIA_TYPES;
    Buffer              : Array[0..2047] of Byte;
    Result              : String;
begin
    Result:='';
    HFile:=INVALID_HANDLE_VALUE;
    try
        HFile:=CreateFile(PChar('\\.\'+Disque),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if HFile<>INVALID_HANDLE_VALUE then
        begin
            DeviceIoControl(HFile,IOCTL_STORAGE_GET_MEDIA_TYPES_EX,nil,0,@StorageMediaType,SizeOf(StorageMediaType),lpBytesReturned, nil);
            if DeviceIoControl(HFile,IOCTL_STORAGE_GET_MEDIA_TYPES_EX,nil,0,@Buffer,SizeOf(Buffer),lpBytesReturned,nil) then
                MediaTypes := PGET_MEDIA_TYPES(@Buffer);
            Result:=IntTostr(MediaTypes.MediaInfo[0].DeviceSpecific.RemovableDiskInfo.MediaType);
        end;
    finally
        CloseHandle(HFile);
    end;
end;}

Procedure DeviceDescriptorString(Disque:String);
{type
  PCharArray = ^TCharArray;
  TCharArray = Array[0..MAX_PATH] of Char;}
var
    HFile                       : THandle;
    PropQuery                   : STORAGE_PROPERTY_QUERY;
    DeviceDescriptor            : STORAGE_DEVICE_DESCRIPTOR;
    lpBytesReturned             : DWORD;
    I                           : Integer;
    Value                       : Char;
    PosValue                    : Integer;
//    TestString                  : String;
//    TestChar                    : PChar;
begin
    Drive.Properties:='';
    HFile:=INVALID_HANDLE_VALUE;
    try
        HFile:=CreateFile(PChar('\\.\'+Disque),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if HFile<>INVALID_HANDLE_VALUE then
        begin
            ZeroMemory(@PropQuery, SizeOf(PropQuery));
            ZeroMemory(@DeviceDescriptor, SizeOf(DeviceDescriptor));
            DeviceDescriptor.Size := SizeOf(DeviceDescriptor);
            DeviceIoControl(HFile,IOCTL_STORAGE_QUERY_PROPERTY,@PropQuery,SizeOf(PropQuery),@DeviceDescriptor,DeviceDescriptor.Size,lpBytesReturned,nil);
{//            vendorid
            if DeviceDescriptor.VendorIdOffset<>0 then
            begin
                TestChar:=@PCharArray(@DeviceDescriptor)^[DeviceDescriptor.VendorIdOffset];
                TestString:=Trim(TestChar);
                TestString:= String(PChar(@DeviceDescriptor) + DeviceDescriptor.VendorIdOffset);
            end;
//            productid
            if DeviceDescriptor.ProductIdOffset<>0 then
            begin
                TestChar:=@PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductIdOffset];
                TestString:=Trim(TestChar);
                TestString:= String(PChar(@DeviceDescriptor) + DeviceDescriptor.ProductIdOffset);
            end;
//            product révision
            if DeviceDescriptor.ProductRevisionOffset<>0 then
            begin
                TestChar:=@PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductRevisionOffset];
                TestString:=Trim(TestChar);
                TestString:= String(PChar(@DeviceDescriptor) + DeviceDescriptor.ProductRevisionOffset);
            end;}
            Drive.Properties:='';
            PosValue:=0;
            for I := DeviceDescriptor.RawPropertiesLength-1 Downto 0 do
                if DeviceDescriptor.RawDeviceProperties[i]=0 then
                begin
                    PosValue:=I;
                    Break;
                end;
            Value:=#0;
            for I:=PosValue to DeviceDescriptor.RawPropertiesLength-1 do
            begin
                case DeviceDescriptor.RawDeviceProperties[i] of
                    32..126:    begin
                                    if Drive.Properties<>'' then
                                        Value:=Drive.Properties[Length(Drive.Properties)-1];
                                    if (Value<>' ')or(DeviceDescriptor.RawDeviceProperties[i]<>32)then
                                        Drive.Properties:=Drive.Properties+Chr(DeviceDescriptor.RawDeviceProperties[i]);
                                end;
                end;
            end;
        end;
    finally
        CloseHandle(HFile);
    end;
end;

function FormatTaille(Value: Extended): String;
var
    i   : Integer;
begin
    i:=0;
    while (Value>=1000) or (i=4) do
    begin
        Value:=Value / 1024;
        Inc(i);
    end;
    case i of
        0 : Result:=FloatToStrF(Value,ffFixed,18,2)+' octet(s)';
        1 : Result:=FloatToStrF(Value,ffFixed,18,2)+' Ko';
        2 : Result:=FloatToStrF(Value,ffFixed,18,2)+' Mo';
        3 : Result:=FloatToStrF(Value,ffFixed,18,2)+' Go';
        4 : Result:=FloatToStrF(Value,ffFixed,18,2)+' To';
    end;
end;

Procedure InfoDevice(Disque:String);
var
    Volume                  : THandle;
    Returned                : DWORD;
    VolName                 : Array[0..MAX_PATH]Of Char;
    FileSysName             : Array[0..MAX_PATH]Of Char;
    VolSerial               : DWord;
    FileMaxLen              : DWord;
    FileFlags               : DWord;
    FreeAvailable           : Int64;
    TotalSpace              : Int64;
    FreeAvailableString     : String;
    TotalSpaceString        : String;
    TempVolName             : String;
begin
    Drive.VolumeName:='';
    Drive.TailleLib:='0 Go';
    Drive.TailleTot:='0 Go';
    Drive.SystFich:='';
    if GetVolumeInformation(PChar(Disque+'\'),VolName,Max_Path,@VolSerial,FileMaxLen,FileFlags,FileSysName,MAX_PATH) then
    begin
        GetDiskFreeSpaceEx(PChar(Disque),FreeAvailable,TotalSpace,nil);
        FreeAvailableString:=FormatTaille(FreeAvailable);
        TotalSpaceString:=FormatTaille(TotalSpace);
        if VolName<>'' then
            TempVolName:=VolName
        else
            TempVolName:='';
        Drive.VolumeName:=TempVolName;
        Drive.SystFich:=FileSysName;
        Drive.TailleLib:=FreeAvailableString;
        Drive.TailleTot:=TotalSpaceString;
    end
    else
    begin
        TempVolName:='Empty Drive';
        Volume := CreateFile(PChar('\\.\' + Disque + ':'),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil, OPEN_EXISTING, 0, 0);
        try
            if not DeviceIoControl(Volume, IOCTL_STORAGE_CHECK_VERIFY, nil, 0, nil, 0, Returned, nil) then
            begin
                Drive.VolumeName:=TempVolName;
                Drive.SystFich:='';
                Drive.TailleLib:='0 Go';
                Drive.TailleTot:='0 Go';
            end;
        finally
            CloseHandle(Volume);
        end;
    end;
end;

function HotPlugInfo(Disque:String):Boolean;
var
    HFile                       : THandle;
    GetMediaTypes               : STORAGE_HOTPLUG_INFO;
    PropQuery                   : STORAGE_PROPERTY_QUERY;
    DeviceDescriptor            : STORAGE_DEVICE_DESCRIPTOR;
    lpBytesReturned             : DWORD;
begin
    Result:=False;
    HFile:=INVALID_HANDLE_VALUE;
    try
        HFile:=CreateFile(PChar('\\.\'+Disque),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
        if HFile<>INVALID_HANDLE_VALUE then
        begin
            DeviceIoControl(HFile,IOCTL_STORAGE_GET_HOTPLUG_INFO,nil,0,@GetMediaTypes,sizeof(GetMediaTypes),lpBytesReturned,nil);
            ZeroMemory(@PropQuery, SizeOf(PropQuery));
            ZeroMemory(@DeviceDescriptor, SizeOf(DeviceDescriptor));
            DeviceDescriptor.Size := SizeOf(DeviceDescriptor);
            DeviceIoControl(HFile,IOCTL_STORAGE_QUERY_PROPERTY,@PropQuery,SizeOf(PropQuery),@DeviceDescriptor,DeviceDescriptor.Size,lpBytesReturned,nil);
            if (DeviceDescriptor.BusType=BusTypeUsb)or(DeviceDescriptor.BusType=BusType1394)or(DeviceDescriptor.BusType=BusTypeAtapi)or
                ((GetMediaTypes.MediaRemovable)and(GetMediaTypes.MediaHotplug))or
                (GetMediaTypes.DeviceHotplug)or(GetMediaTypes.MediaRemovable) then
                Result:=True
            else
                Result:=False;
            Drive.Volume:=Disque+'\';
            Drive.MediaRemovable:=GetMediaTypes.MediaRemovable;
            Drive.MediaHotplug:=GetMediaTypes.MediaHotplug;
            Drive.DeviceHotplug:=GetMediaTypes.DeviceHotplug;
            Drive.BusType:=DeviceDescriptor.BusType;
            DeviceDescriptorString(Disque);
            InfoDevice(Disque);
            StorageDeviceNumberString(Disque);
        end;
    finally
        CloseHandle(HFile);
    end;
end;

Procedure Liste_USB(Lecteurs:TStrings;DriveRemovable,DriveFixed,DriveCDRom:Boolean);
var
    Num     : Integer;
    Bits    : set of 0..25;
    Disque  : String;
begin
    Integer(Bits):=GetLogicalDrives;
    for Num := 0 to 25 do
    begin
        if Num in Bits then
        begin
            Disque:=Char(Num+Ord('A'))+':';
            case GetDriveType(PChar(Disque)) of
                DRIVE_REMOVABLE :   if DriveRemovable then
                                        if HotPlugInfo(Disque) then
                                            Lecteurs.Append(Drive.Volume+' '+Drive.Properties+' Lecteur Amovible'+' '+Drive.SystFich+' ( '+Drive.TailleLib+' / '+Drive.TailleTot+' ) '+Drive.VolumeName);
                DRIVE_FIXED     :   if DriveFixed then
                                        if HotPlugInfo(Disque) then
                                            Lecteurs.Append(Drive.Volume+' '+Drive.Properties+' Disque Externe Amovible'+' '+Drive.SystFich+' ( '+Drive.TailleLib+' / '+Drive.TailleTot+' ) '+Drive.VolumeName)
                                        else
                                            Lecteurs.Append(Drive.Volume+' '+Drive.Properties+' Disque Dur'+' '+Drive.SystFich+' ( '+Drive.TailleLib+' / '+Drive.TailleTot+' ) '+Drive.VolumeName);
                DRIVE_CDROM     :   if DriveCDRom then
                                        if HotPlugInfo(Disque) then
                                            Lecteurs.Append(Drive.Volume+' '+Drive.Properties+' Lecteur CDRom / DVDRom'+' '+Drive.SystFich+' ( '+Drive.TailleLib+' / '+Drive.TailleTot+' ) '+Drive.VolumeName);
            end;
        end;
    end;
end;


function CM_Query_And_Remove_SubTreeW; external 'SetupApi.dll' name 'CM_Query_And_Remove_SubTreeW';
function CM_Query_And_Remove_SubTreeA; external 'SetupApi.dll' name 'CM_Query_And_Remove_SubTreeA';
function CM_Query_And_Remove_SubTree; external 'SetupApi.dll' name 'CM_Query_And_Remove_SubTree' + LettreFin;

function CM_Request_Device_EjectW; external 'SetupApi.dll' name 'CM_Request_Device_EjectW';
function CM_Request_Device_EjectA; external 'SetupApi.dll' name 'CM_Request_Device_EjectA';
function CM_Request_Device_Eject; external 'SetupApi.dll' name 'CM_Request_Device_Eject' + LettreFin;

function SetupDiGetClassDevsW; external 'SetupApi.dll' name 'SetupDiGetClassDevsW';
function SetupDiGetClassDevsA; external 'SetupApi.dll' name 'SetupDiGetClassDevsA';
function SetupDiGetClassDevs; external 'SetupApi.dll' name 'SetupDiGetClassDevs' + LettreFin;

function SetupDiGetDeviceInterfaceDetailW; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailW';
function SetupDiGetDeviceInterfaceDetailA; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailA';
function SetupDiGetDeviceInterfaceDetail; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetail' + LettreFin;

end.
Unit1 :
uses EjectUSB, CheckLst

private
    { Declarations privates }
    Procedure EtatConnectionUSB(var Msg: TMessage);Message WM_DEVICECHANGE;

var
  Form1 : TForm1;
  Eject : Boolean;
  
//

Procedure TForm1.EtatConnectionUSB(var Msg: TMessage);
begin
    if (Msg.wParam = $8004) or (Msg.wParam = $8000) then
        if DEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype=2 then
            if DEV_BROADCAST_VOLUME(Msg.LParam)^.dbcv_flags=0 then
                if not Eject then
                begin
                    CheckListBox1.Clear;
                    Liste_USB(CheckListBox1.Items,True,True,True);
                end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
    CheckListBox1.Clear;
//    Liste_USB(Lecteurs:TStrings;DriveRemovable,DriveFixed,DriveCDRom:Boolean);
//    Drives: Retrieving volumes from a TStrings
//    DriveRemovable : Recovery of devices other than disks and media USB
//    DriveFixed : Disk Recovery USB
//    DriveCDROM : Media Recovery USB
    Liste_USB(CheckListBox1.Items,True,True,True);
end;
Geräte auslesen :
procedure TForm1.Button2Click(Sender: TObject);
begin
    CheckListBox1.Clear;
    Liste_USB(CheckListBox1.Items,True,True,True);
end;
Gerät entfernen :
procedure TForm1.Button1Click(Sender: TObject);
var
  I     : Integer;
  Drive : String;
begin
    for I := 0 to CheckListBox1.Count - 1 do
        if CheckListBox1.Checked[I] then
        begin
            Eject:=True;
            Drive:=CheckListBox1.Items.Strings[i];
//            Eject_USB(LetVol: String;Rep,TempRep: Integer;MessageEject,MultiSupport: Boolean);
//            LetVol: Letter from the volume to Eject
//            Rep : Number of ejection attempts
//            TempRep : Time in ms between each ejection attempt
//            MessageEject : Display of ejection bubble and errors
//            MultiSupport : For MultiCard readers for example this removes the complete adapter
            if MessageDlg('Extract full media ?',mtConfirmation,[mbYes,mbNo],0)=mrYes then
            begin
                if Eject_USB(Drive[1],4,300,True,True) then
                    CheckListBox1.ItemEnabled[I]:=False;
            end
            else
            begin
                if Eject_USB(Drive[1],4,300,True,False) then
                    CheckListBox1.ItemEnabled[I]:=False;
            end;
        end;
    CheckListBox1.Clear;
    Liste_USB(CheckListBox1.Items,True,True,True);
    Eject:=False;
end;

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate