Ejecting USB stick...

Share your advanced PureBasic knowledge/code with the community.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Ejecting USB stick...

Post by Michael Vogel »

As I want to remove an USB stick automatically, I wrote the following code (seems to work, everyone is welcome to improve the code)

Code: Select all

; Define

	#LOCK_TIMEOUT=10000; ms
	#LOCK_RETRIES=20
	#FSCTL_LOCK_VOLUME=$90018
	#FSCTL_UNLOCK_VOLUME=$9001C
	#FSCTL_DISMOUNT_VOLUME=$90020
	#IOCTL_STORAGE_MEDIA_REMOVAL=$2D4804
	#IOCTL_STORAGE_EJECT_MEDIA=$2D4808

	Structure PREVENT_MEDIA_REMOVAL
		PreventMediaRemoval.b
	EndStructure
; EndDefine

Procedure.l OpenVolume(DriveLetter.s)
	Protected AccessFlags.l
	Protected Volume.l

	DriveType.l=GetDriveType_(DriveLetter+":\")
	Debug "Drivetyp: "+Str(DriveType)

	Select DriveType
	Case #DRIVE_REMOVABLE
		AccessFlags = #GENERIC_READ|#GENERIC_WRITE
	Case #DRIVE_CDROM
		AccessFlags = #GENERIC_READ
	Default
		ProcedureReturn #INVALID_HANDLE_VALUE
	EndSelect

	ProcedureReturn CreateFile_("\\.\"+DriveLetter+":",AccessFlags,#FILE_SHARE_READ|#FILE_SHARE_WRITE,#Null,#OPEN_EXISTING,0,#Null)
EndProcedure
Procedure.b CloseVolume(Handle)
	ProcedureReturn CloseHandle_(Handle)
EndProcedure
Procedure.b LockVolume(Handle.l)
	Protected i.w=0
	Protected Buffer.l

	Debug "Lock..."
	While i<#LOCK_RETRIES
		i+1
		If DeviceIoControl_(Handle,#FSCTL_LOCK_VOLUME,#Null,0,#Null,0,@Buffer,#Null)
			Debug "...ed"
			ProcedureReturn #True
		EndIf
		Sleep_(#LOCK_TIMEOUT / #LOCK_RETRIES)
	Wend

	Debug "...failed"
	ProcedureReturn #False
EndProcedure
Procedure.b DismountVolume(Handle.l)
	Protected Buffer.l
	ProcedureReturn DeviceIoControl_(Handle,#FSCTL_DISMOUNT_VOLUME,#Null,0,#Null,0,@Buffer,#Null)
EndProcedure
Procedure.b PreventRemovalOfVolume(Handle.l,Flag.b)
	Protected Buffer.l
	Protected MediaBuffer.PREVENT_MEDIA_REMOVAL
	MediaBuffer\PreventMediaRemoval = Flag
	ProcedureReturn DeviceIoControl_(Handle,#IOCTL_STORAGE_MEDIA_REMOVAL,@MediaBuffer,SizeOf(PREVENT_MEDIA_REMOVAL),#Null,0,@Buffer,#Null)
EndProcedure
Procedure.b AutoEjectVolume(Handle)
	Protected Buffer.l
	ProcedureReturn DeviceIoControl_(Handle,#IOCTL_STORAGE_EJECT_MEDIA,#Null,0,#Null,0,@Buffer,#Null)
EndProcedure
Procedure EjectVolume(DriveLetter.s)
	Protected Handle.l
	Protected Success.l=0

	; [ 1 ] Volume "\\.\X:" öffnen...
	Handle=OpenVolume(DriveLetter)
	If Handle=#INVALID_HANDLE_VALUE
		ProcedureReturn #False
	Else
		; [ 2 ] Lock and Dismount...
		If LockVolume(Handle)&DismountVolume(Handle)
			Success=1
			; [ 3 ] Check removal and Eject...
			If PreventRemovalOfVolume(Handle,#False)&AutoEjectVolume(Handle)
				Success=2
			EndIf
		EndIf
		; [ 4 ] Close Volume...
		If CloseVolume(Handle)
			ProcedureReturn #False
		EndIf

		Debug "Ergebnis:"+Str(Success)

	EndIf
EndProcedure

Debug EjectVolume("D");
Last edited by Michael Vogel on Mon Mar 27, 2006 12:13 pm, edited 1 time in total.
User avatar
HeX0R
Addict
Addict
Posts: 1189
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Post by HeX0R »

I guess something went wrong here, as i see anything twice ;)
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

HeX0R wrote:I guess something went wrong here, as i see anything twice ;)
Not only you - must haven drunken some beer...
User avatar
Droopy
Enthusiast
Enthusiast
Posts: 658
Joined: Thu Sep 16, 2004 9:50 pm
Location: France
Contact:

Post by Droopy »

Thanks i try this code this evening :D
User avatar
bingo
Enthusiast
Enthusiast
Posts: 210
Joined: Fri Apr 02, 2004 12:21 pm
Location: germany/thueringen
Contact:

Post by bingo »

removes all USBSTORs :lol:

PB4 code !

Code: Select all

#DIGCF_PRESENT                     =   2 
#DIGCF_ALLCLASSES                  =   4 

hDeviceInfoSet = SetupDiGetClassDevs_(0,0,0,#DIGCF_PRESENT|#DIGCF_ALLCLASSES) 

Structure SP_DEVINFO_DATA 
  cbSize.l 
  ClassGuid.GUID 
  DevInst.l 
  Reserved.l 
EndStructure 

Global DeviceInfoData.SP_DEVINFO_DATA ;global für funktion
DeviceInfoData\cbSize=SizeOf(DeviceInfoData) 

#SPDRP_SERVICE = 4

*MemoryID = AllocateMemory(500)

i.l

OpenLibrary(1,"setupapi.dll")

*F1 = GetFunction(1, "SetupDiGetDeviceInstanceIdA") 
*F2 = GetFunction(1, "SetupDiGetDeviceRegistryPropertyA") 
*F3 = GetFunction(1, "CM_Locate_DevNodeA") 
*F4 = GetFunction(1, "CM_Request_Device_Eject_ExA") 

While SetupDiEnumDeviceInfo_(hDeviceInfoSet,i,@DeviceInfoData)
i+1 
CallFunctionFast(*F2,hDeviceInfoSet,DeviceInfoData,#SPDRP_SERVICE,0,*MemoryID,500,0)

If UCase(PeekS(*MemoryID)) = "USBSTOR"
CallFunctionFast(*F1,hDeviceInfoSet,DeviceInfoData,*MemoryID,500,0)
If CallFunctionFast(*F3,@devinst.l,PeekS(*MemoryID),0) = 0
CallFunctionFast(*F4,devinst,0,0,0,0,0) 
EndIf 
EndIf

Wend

SetupDiDestroyDeviceInfoList_(hDeviceInfoSet) 

CloseLibrary(1) 

FreeMemory(*MemoryID)
["1:0>1"]
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

bingo wrote:removes all USBSTORs :lol:
Cool :shock:

do you also know how to get also rid from the (windows-) message that all devices can now be removed? That would be superb!
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

Cool indeed, thanks!
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Post by SimpleMind »

This is a snippet from the above code. In the code the type GUID is used. Where is the structure type GUID declared?

[...]
Structure SP_DEVINFO_DATA
cbSize.l
ClassGuid.GUID
DevInst.l
Reserved.l
EndStructure
[...]
Give me books, fruit, french wine, fine weather and a little music.
John Keats
User avatar
bingo
Enthusiast
Enthusiast
Posts: 210
Joined: Fri Apr 02, 2004 12:21 pm
Location: germany/thueringen
Contact:

Post by bingo »

in pb4 with :

Code: Select all

Structure GUID
  Data1.l
  Data2.w
  Data3.w
  Data4.b[8]
EndStructure
8)
["1:0>1"]
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Post by SimpleMind »

Thanks, I tested it and it is standard present. I do not have to explicitely declare it.
Give me books, fruit, french wine, fine weather and a little music.
John Keats
User avatar
Le Soldat Inconnu
Enthusiast
Enthusiast
Posts: 306
Joined: Wed Jul 09, 2003 11:33 am
Location: France

Post by Le Soldat Inconnu »

i need to know drive letter of USB device

I look your code, it's find USB device, so great, but i need to find drive letter

I want do this :
I have list of all drive on my computer, by right click, i want can eject USB Device.


I try to get this information but nothing

Code: Select all

#DIGCF_PRESENT                     =  2 
#DIGCF_ALLCLASSES                  =  4 

hDeviceInfoSet = SetupDiGetClassDevs_(0,0,0,#DIGCF_PRESENT|#DIGCF_ALLCLASSES) 

Structure SP_DEVINFO_DATA 
  cbSize.l 
  ClassGuid.GUID 
  DevInst.l 
  reserved.l 
EndStructure 

Global DeviceInfoData.SP_DEVINFO_DATA ;global für funktion 
DeviceInfoData\cbSize=SizeOf(DeviceInfoData) 

#SPDRP_SERVICE = 4 

*MemoryID = AllocateMemory(500) 

i.l 

OpenLibrary(1,"setupapi.dll") 

*F1 = GetFunction(1, "SetupDiGetDeviceInstanceIdA") 
*F2 = GetFunction(1, "SetupDiGetDeviceRegistryPropertyA") 
*F3 = GetFunction(1, "CM_Locate_DevNodeA") 
*F4 = GetFunction(1, "CM_Request_Device_Eject_ExA") 

While SetupDiEnumDeviceInfo_(hDeviceInfoSet,i,@DeviceInfoData) 
  i+1 
  CallFunctionFast(*F2,hDeviceInfoSet,DeviceInfoData,#SPDRP_SERVICE,0,*MemoryID,500,0) 
  
  If UCase(PeekS(*MemoryID)) = "USBSTOR" 
    For n = 0 To 63
      CallFunctionFast(*F2,hDeviceInfoSet,DeviceInfoData,n,0,*MemoryID,500,0)
      Debug PeekS(*MemoryID)
    Next
    ; CallFunctionFast(*F1,hDeviceInfoSet,DeviceInfoData,*MemoryID,500,0) 
    ; If CallFunctionFast(*F3,@DevInst.l,PeekS(*MemoryID),0) = 0 
      ; CallFunctionFast(*F4,DevInst,0,0,0,0,0) 
    ; EndIf 
  EndIf 
  
Wend 

SetupDiDestroyDeviceInfoList_(hDeviceInfoSet) 

CloseLibrary(1) 

FreeMemory(*MemoryID) 
LSI
User avatar
graves
Enthusiast
Enthusiast
Posts: 160
Joined: Wed Oct 03, 2007 2:38 pm
Location: To the deal with a pepper

Post by graves »

You can unmount using the USB device name:

Code: Select all

#DIGCF_PRESENT    = 2
#DIGCF_ALLCLASSES = 4
#SPDRP_SERVICE    = 4

Structure SP_DEVINFO_DATA
  cbSize.l
  ClassGuid.GUID
  DevInst.l
  Reserved.l
EndStructure

Global DeviceInfoData.SP_DEVINFO_DATA, hDeviceInfoSet, *F1, *F2, *F3, *F4, *MemoryID, devinst, devname.s

*MemoryID = AllocateMemory(500)
hDeviceInfoSet = SetupDiGetClassDevs_(0,0,0,#DIGCF_PRESENT|#DIGCF_ALLCLASSES)
DeviceInfoData\cbSize=SizeOf(DeviceInfoData)
i.l=0

OpenLibrary(1,"setupapi.dll")
device.s = ProgramParameter()

*F1 = GetFunction(1, "SetupDiGetDeviceInstanceIdA")
*F2 = GetFunction(1, "SetupDiGetDeviceRegistryPropertyA")
*F3 = GetFunction(1, "CM_Locate_DevNodeA")
*F4 = GetFunction(1, "CM_Request_Device_Eject_ExA")

OpenConsole()
While SetupDiEnumDeviceInfo_(hDeviceInfoSet,i,@DeviceInfoData)
  i+1
  CallFunctionFast(*F2,hDeviceInfoSet,DeviceInfoData,#SPDRP_SERVICE,0,*MemoryID,500,0)
  if UCase(PeekS(*MemoryID)) = "USBSTOR"
    CallFunctionFast(*F2,hDeviceInfoSet,DeviceInfoData,13,0,*MemoryID,500,0)
    devname = PeekS(*MemoryID)
    if len(device)
      if ucase(device) = "*ALL" OR ucase(device) = ucase(left(devname,len(device)))
        CallFunctionFast(*F1,hDeviceInfoSet,DeviceInfoData,*MemoryID,500,0)
        If CallFunctionFast(*F3,@devinst,PeekS(*MemoryID),0) = 0
          CallFunctionFast(*F4,devinst,0,0,0,0,0)
          printn(devname+" unmounted")
        EndIf
      endif
    else
      printn(devname)
    endif
  endif
Wend

SetupDiDestroyDeviceInfoList_(hDeviceInfoSet)
CloseLibrary(1)
FreeMemory(*MemoryID)
printn("END")
input()
CloseConsole()
END
Last edited by graves on Thu Jan 22, 2009 12:14 pm, edited 1 time in total.
User avatar
Le Soldat Inconnu
Enthusiast
Enthusiast
Posts: 306
Joined: Wed Jul 09, 2003 11:33 am
Location: France

Post by Le Soldat Inconnu »

Thanks but i need with drive letter, like E:\, not name
LSI
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Damn, I was looking for some code to eject a USB stick physically :lol:
I like logic, hence I dislike humans but love computers.
User avatar
graves
Enthusiast
Enthusiast
Posts: 160
Joined: Wed Oct 03, 2007 2:38 pm
Location: To the deal with a pepper

Post by graves »

Joakim Christiansen wrote:Damn, I was looking for some code to eject a USB stick physically :lol:
:shock:
¿Launching it as a cannonball? :?:
Post Reply