Donc voici le code qui permet, a partir de la lettre du lecteur :
- Ejecter un lecteur CD (ou le fermer)
- Retirer un périphérique amovible.
Code testé avec clé USB U3, Clé USB classique
En attente de test pour disque dur USB, Graveur USB, et d'un test sous Vista
Code : Tout sélectionner
Procedure EjectCDRomDrive(DriveLetter.s, Test.l = 0) ; To eject CD, or close CD
Protected hDevice, Retour = 0, Temps
DriveLetter = Left(DriveLetter, 1)
If GetDriveType_(DriveLetter + ":\") = 5 ; Lecteur cd-rom
#IOCTL_STORAGE_EJECT_MEDIA = $D4808
#IOCTL_STORAGE_LOAD_MEDIA = $2D480C
hDevice = CreateFile_("\\.\" + DriveLetter + ":", #GENERIC_READ, #FILE_SHARE_READ, 0, #OPEN_EXISTING, 0, 0)
If hDevice <> #INVALID_HANDLE_VALUE
; Ejecter cd rom
If Test = 0
Temps = ElapsedMilliseconds()
DeviceIoControl_(hDevice, #IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, @Retour, 0)
If ElapsedMilliseconds() - Temps < 50
; rentrer cd rom
DeviceIoControl_(hDevice, #IOCTL_STORAGE_LOAD_MEDIA, 0, 0, 0, 0, @Retour, 0)
EndIf
EndIf
CloseHandle_(hDevice)
Retour = 1
EndIf
EndIf
ProcedureReturn Retour
EndProcedure
Procedure IsCDRomDrive(DriveLetter.s) ; To check if drive is CD
ProcedureReturn EjectCDRomDrive(DriveLetter, 1)
EndProcedure
Procedure RemoveDrive(DriveLetter.s, Test.l = 0) ; To disconnect USB drive
#SPDRP_SERVICE = $4
DataSection ; GUID
GUID_DEVINTERFACE_FLOPPY:
Data.l $53F56311
Data.w $B6BF, $11D0
Data.b $94, $F2, $00, $A0, $C9, $1E, $FB, $8B
GUID_DEVINTERFACE_DISK:
Data.l $53F56307
Data.w $B6BF, $11D0
Data.b $94, $F2, $00, $A0, $C9, $1E, $FB, $8B
GUID_DEVINTERFACE_CDROM:
Data.l $53F56308
Data.w $B6BF, $11D0
Data.b $94, $F2, $00, $A0, $C9, $1E, $FB, $8B
GUID_DEVINTERFACE_VOLUME:
Data.l $53F5630D
Data.w $B6BF, $11D0
Data.b $94, $F2, $00, $A0, $C9, $1E, $FB, $8B
EndDataSection
Structure PSP_DEVICE_INTERFACE_DETAIL_DATA
cbSize.l
DevicePath.s{255}
EndStructure
Structure SP_DEVINFO_DATA
cbSize.l
ClassGuid.GUID
DevInst.l
reserved.l
EndStructure
Protected Index, Retour, *VolumeName, *DeviceInstanceId, *DeviceService.l
Protected DevicePath_Length.l, DeviceLetter.s, DeviceVolume.s, DeviceInstance.l, DeviceID.s
Protected hDevice.l, *Guid.l, pspdidd.PSP_DEVICE_INTERFACE_DETAIL_DATA, spdid.SP_DEVICE_INTERFACE_DATA, spdd.SP_DEVINFO_DATA
Protected Removable_hDevice, Removable_Index, Removable_spdd.SP_DEVINFO_DATA, Removable_DeviceCapabilities.l, Removable_Service.s, RemovableDevice.l, Removable_DeviceID.s
Protected DriveVolume.s
; On ouvre les librairies et on charge les fonctions utiles
dll_Setupapi = OpenLibrary(#PB_Any, "setupapi.dll")
If dll_Setupapi
dll_Kernel32 = OpenLibrary(#PB_Any, "Kernel32.dll")
If dll_Kernel32
*CM_Locate_DevNode = GetFunction(dll_Setupapi, "CM_Locate_DevNodeA")
*CM_Request_Device_Eject = GetFunction(dll_Setupapi, "CM_Request_Device_Eject_ExA")
*CM_Get_Parent = GetFunction(dll_Setupapi, "CM_Get_Parent")
*CM_Get_Device_ID = GetFunction(dll_Setupapi, "CM_Get_Device_IDA")
*GetVolumeNameForVolumeMountPoint = GetFunction(dll_Kernel32, "GetVolumeNameForVolumeMountPointA")
; On récupère le nom de volume du lecteur
*VolumeName = AllocateMemory(255)
CallFunctionFast(*GetVolumeNameForVolumeMountPoint, DriveLetter + ":\", *VolumeName, 255)
DriveVolume= PeekS(*VolumeName)
FreeMemory(*VolumeName)
; On recherche le volume qui correspond a chaque lettre de lecteur
*Guid = ?GUID_DEVINTERFACE_VOLUME ; On recherche tous les volumes
hDevice = SetupDiGetClassDevs_(*Guid, 0, 0, #DIGCF_PRESENT|#DIGCF_DEVICEINTERFACE)
If hDevice <> #INVALID_HANDLE_VALUE
; Paramétrage
spdid\cbSize = SizeOf(SP_DEVICE_INTERFACE_DATA)
; On liste les interfaces
Index= 0
While SetupDiEnumDeviceInterfaces_(hDevice, 0, *Guid, Index, @spdid)
; Taille du buffer nécessaire pour lire l'information
SetupDiGetDeviceInterfaceDetail_(hDevice, @spdid, 0, 0, @DevicePath_Length, 0)
If DevicePath_Length <> 0 And DevicePath_Length < 255 ; On teste pour savoir si le texte n'est pas trop long
pspdidd\cbSize = 5 ; Unicode=6, ASCII=5
spdd\cbSize = SizeOf(SP_DEVINFO_DATA)
If SetupDiGetDeviceInterfaceDetail_(hDevice, @spdid, @pspdidd, DevicePath_Length, 0, @spdd)
*VolumeName = AllocateMemory(255)
CallFunctionFast(*GetVolumeNameForVolumeMountPoint, pspdidd\DevicePath + "\", *VolumeName, 255)
DeviceVolume = PeekS(*VolumeName)
FreeMemory(*VolumeName)
If DriveVolume = DeviceVolume
; On a trouvé le volume correspondant à la lettre de lecteur
DeviceInstance = spdd\DevInst
Repeat ; On parcourt la liste des parents à la recherche d'un périphérique amovible
If CallFunctionFast(*CM_Get_Parent, @DeviceParent, DeviceInstance, 0) = 0
DeviceInstance = DeviceParent
*DeviceInstanceId = AllocateMemory(255)
CallFunctionFast(*CM_Get_Device_ID, DeviceInstance, *DeviceInstanceId, 255, 0) ; On récupère l'ID du device
DeviceID = PeekS(*DeviceInstanceId)
FreeMemory(*DeviceInstanceId)
; On recherche si le device est amovible
RemovableDevice = 0
Removable_hDevice = SetupDiGetClassDevs_(0, 0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES)
If Removable_hDevice <> #INVALID_HANDLE_VALUE
Removable_spdd\cbSize = SizeOf(SP_DEVINFO_DATA)
Removable_Index = 0
While SetupDiEnumDeviceInfo_(Removable_hDevice, Removable_Index, @Removable_spdd)
*DeviceInstanceId = AllocateMemory(255)
SetupDiGetDeviceInstanceId_(Removable_hDevice, Removable_spdd, *DeviceInstanceId, 255, 0)
Removable_DeviceID = PeekS(*DeviceInstanceId)
FreeMemory(*DeviceInstanceId)
If Removable_DeviceID = DeviceID
*DeviceService = AllocateMemory(255)
SetupDiGetDeviceRegistryProperty_(Removable_hDevice, Removable_spdd, #SPDRP_SERVICE, 0, *DeviceService, 255, 0)
Removable_Service = LCase(PeekS(*DeviceService))
FreeMemory(*DeviceService)
If Removable_Service = "usbstor"
RemovableDevice = 1
Break
EndIf
EndIf
Removable_Index + 1
Wend
SetupDiDestroyDeviceInfoList_(Removable_hDevice)
EndIf
If RemovableDevice ; Si le lecteur est amovible
Retour = 1 ; On retourne une réponse positive
If Test = 0 ; Si on veut retirer le lecteur
If CallFunctionFast(*CM_Locate_DevNode, @DeviceInstance.l, DeviceID, 0) = 0 ; On va sur le noeud du device
CallFunctionFast(*CM_Request_Device_Eject, DeviceInstance, 0, 0, 0, 0, 0) ; On éjecte le device
EndIf
EndIf
Break 2 ; On s'arrête sur le premier périphérique amovible
EndIf
EndIf
Until DeviceInstance <> DeviceParent ; on a listé tous les parents
EndIf
EndIf
EndIf
; On passe à l'élément suivant
Index + 1
Wend
SetupDiDestroyDeviceInfoList_(hDevice) ; On ferme
EndIf
CloseLibrary(dll_Kernel32)
EndIf
CloseLibrary(dll_Setupapi)
EndIf
ProcedureReturn Retour
EndProcedure
Procedure IsRemovableDrive(DriveLetter.s) ; To check if drive is USB drive
ProcedureReturn RemoveDrive(DriveLetter, 1)
EndProcedure
;- Test
Lecteur.s = "i"
If IsCDRomDrive(Lecteur)
EjectCDRomDrive(Lecteur)
EndIf
If IsRemovableDrive(Lecteur)
RemoveDrive(Lecteur)
EndIf
Ancien sujet avant résolution
--------------------------------------------------------------------------------
Bon, voilà une belle galère
Pour éjecter le cd-rom, c'est ok, j'ai trouvé quelque chose de fonctionnel
A partir du code
http://www.purebasic.fr/english/viewtop ... highlight=
Par contre, pour les clés USB, c'est une autre galère
j'ai trouvé un code qui éjecte les clés usb mais ... (si si, un petit mais) ... ca éjecte toutes les clés usb alors que je cherche a éjecter un lecteur particulier à partir de sa lettre
http://www.purebasic.fr/english/viewtop ... highlight=
Donc je cherche, si vous avez une idée, merci