-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathEjectDevice.ahk
87 lines (67 loc) · 3.96 KB
/
EjectDevice.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
EjectDevice(RootPathName, Retract := FALSE) {
/* DESCRIPTION
Eject the specified device. It can be a CD / DVD drive or a removable device (USB).
Parameters:
RootPathName: The root directory of the unit.
Retract: If it is TRUE the CD / DVD drive closes (by default it opens).
Return:
-2 = The device could not be ejected.
-1 = The device is invalid.
0 = The device has been successfully ejected.
2 = ERROR_FILE_NOT_FOUND. The dispisitivo does not exist.
32 = ERROR_SHARING_VIOLATION. The device can not be ejected because another application prevents it.
X = Another error code.
*/
Local DriveType, Device, Size, R, STORAGE_DEVICE_NUMBER, BytesReturned, DeviceNumber, PNPDeviceID, hModule, VetoType, hDevInst, hParentDevInst, nVT, Obj
RootPathName := SubStr(RootPathName, 1, 1) . ':'
DriveType := DllCall('Kernel32.dll\GetDriveTypeW', 'Str', RootPathName . '\')
If (DriveType == 5)
{
DriveEject(RootPathName, Retract)
Return (ErrorLevel ? -1 : 0)
}
If (DriveType != 2)
Return (-1)
If (!(Device := FileOpen('\\.\' . RootPathName, 'rw')))
Return (A_LastError)
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216(v=vs.85).aspx
; https://msdn.microsoft.com/en-us/library/windows/desktop/bb968800(v=vs.85).aspx
Size := VarSetcapacity(STORAGE_DEVICE_NUMBER, 4 * 3, 0)
R := DllCall('Kernel32.dll\DeviceIoControl', 'Ptr' , Device.__Handle ;hDevice
, 'UInt' , 0x2D1080 ;dwIoControlCode --> IOCTL_STORAGE_GET_DEVICE_NUMBER
, 'Ptr' , 0 ;lpInBuffer
, 'UInt' , 0 ;nInBufferSize
, 'UPtr' , &STORAGE_DEVICE_NUMBER ;lpOutBuffer
, 'UInt' , Size ;nOutBufferSize
, 'UIntP', BytesReturned ;lpBytesReturned
, 'Ptr' , 0) ;lpOverlapped
Device := ''
; https://msdn.microsoft.com/en-us/library/windows/desktop/bb968801(v=vs.85).aspx
If (NumGet(&STORAGE_DEVICE_NUMBER, 'UInt') != 7) ;DeviceType --> FILE_DEVICE_DISK
Return (-1)
DeviceNumber := NumGet(&STORAGE_DEVICE_NUMBER + 4, 'UInt')
PNPDeviceID := ''
; https://msdn.microsoft.com/en-us/library/aa394132(v=vs.85).aspx
For Obj in ComObjGet('winmgmts:').ExecQuery('Select * from Win32_DiskDrive')
{
If (Obj.DeviceID == '\\.\PHYSICALDRIVE' . DeviceNumber && Obj.InterfaceType == 'USB')
{
PNPDeviceID := Obj.PNPDeviceID
Break
}
}
If (PNPDeviceID == '')
Return (-1)
hModule := DllCall('Kernel32.dll\LoadLibraryW', 'Str', 'SetupAPI.dll', 'Ptr')
; https://msdn.microsoft.com/en-us/library/windows/hardware/ff538742(v=vs.85).aspx
DllCall('SetupAPI.dll\CM_Locate_DevNodeW', 'PtrP', hDevInst, 'UPtr', &PNPDeviceID, 'UInt', 0)
; https://msdn.microsoft.com/en-us/library/windows/hardware/ff538610(v=vs.85).aspx
DllCall('SetupAPI.dll\CM_Get_Parent', 'PtrP', hParentDevInst, 'Ptr', hDevInst, 'UInt', 0, 'Cdecl')
; https://msdn.microsoft.com/en-us/library/windows/hardware/ff539806(v=vs.85).aspx
VetoType := 1
While (hParentDevInst && VetoType && A_Index < 4)
DllCall('SetupAPI.dll\CM_Request_Device_EjectW', 'Ptr', hParentDevInst, 'PtrP', VetoType, 'Ptr', 0, 'UInt', 0, 'UInt', 0)
DllCall('Kernel32.dll\FreeLibrary', 'Ptr', hModule)
Return (nVT ? -2 : 0)
} ;http://ahkscript.org/boards/viewtopic.php?f=6&t=4491