' Removable Media Detection Demo
' By Brent D. Thorn, 2005
' This is a demo showing how to use WMLiberty.dll to make a program aware
' of insertions, ejections, etc. of removable media such as CD-ROMs.
' PUBLIC DOMAIN
NoMainWin
' Get Windows version.
Struct OSVERSIONINFO, _
dwOSVersionInfoSize As ULong, _
dwMajorVersion As ULong, _
dwMinorVersion As ULong, _
dwBuildNumber As ULong, _
dwPlatformId As ULong, _
szCSDVersion As Char[128]
OSVERSIONINFO.dwOSVersionInfoSize.struct = Len(OSVERSIONINFO.struct)
CallDLL #kernel32, "GetVersionExA", _
OSVERSIONINFO As Struct, _
r As Long
' Won't work on W95 nor NT4, both 4.0.
If OSVERSIONINFO.dwMajorVersion.struct = 4 Then
If OSVERSIONINFO.dwMinorVersion.struct = 0 Then
Notice "Program requires a more recent Windows version."
End
End If
End If
Open "WMLiberty" For DLL As #wmlib
Open "Removable Media Detection Demo" For Text As #demo
#demo "!TrapClose [quit]"
' Get top-level window's handle.
hWnd = HWnd(#demo)
CallDLL #user32, "GetParent", _
hWnd As ULong, _
hWnd As ULong
' Set up event handler.
Callback lpfn, OnDeviceChange(ULong,ULong,ULong,ULong),Long
CallDLL #wmlib, "SetWMHandler", _
hWnd As ULong, _
_WM_DEVICECHANGE As ULong, _
lpfn As ULong, _
-1 As Long, _
r As Long
' Let Windows know we're interested in "volume" changes.
Struct DEVBROADCASTVOLUME, _ 'DEV_BROADCAST_VOLUME
size As ULong, _
devicetype As ULong, _
reserved As ULong, _
unitmask As ULong, _
flags As Word
DEVBROADCASTVOLUME.size.struct = Len(DEVBROADCASTVOLUME.struct)
DEVBROADCASTVOLUME.devicetype.struct = 2 'DBT_DEVTYP_VOLUME
' unitmask member represents all drive letters with s
' respective bit: "A:" is 0, "C:" is 2, "D:" is 4, etc.
' For this demo, we'll select all drives, and then some.
DEVBROADCASTVOLUME.unitmask.struct = _INFINITE
DEVBROADCASTVOLUME.flags.struct = 1 'DBTF_MEDIA
' Register our window to be sent WM_DEVICECHANGE.
' Returns a handle identifying the notification.
CallDLL #user32, "RegisterDeviceNotificationA", _
hWnd As ULong, _
DEVBROADCASTVOLUME As Struct, _
0 As Long, _ 'DEVICE_NOTIFY_WINDOW_HANDLE
hDBT As ULong
[loop] ' WMLiberty requires a SCAN loop.
Scan
CallDLL #kernel32, "Sleep", _
1 As Long, r As void
GoTo [loop]
[quit]
' Unregister our window to free the notification handle.
CallDLL #user32, "UnregisterDeviceNotification", _
hDBT As ULong, _
r As Long
Close #demo
Close #wmlib
End
Function OnDeviceChange( hWnd, uMsg, wParam, lParam )
' wParam is the action type, i.e. what the device did.
' lParam is a pointer to a DEV_BROADCAST_VOLUME struct.
If lParam = 0 Then
Print #demo, "Unknown Event"
OnDeviceChange = 1
Exit Function
End If
DEVBROADCASTVOLUME.struct = lParam
' Just a single bit of unitmask is set to let us know
' for which drive the event occurred. We convert the
' set bit to a drive letter by using LOG2.
letter = Asc("A")
drive = DEVBROADCASTVOLUME.unitmask.struct
If drive Then letter = letter + Int(Log(drive) / Log(2))
Print #demo, "Drive ";Chr$(letter);": ";
' Not all actions are supported by all drives.
Select Case wParam
Case 32768 'DBT_DEVICEARRIVAL
Print #demo, "media inserted"
Case 32769 'DBT_DEVICEQUERYREMOVE
Print #demo, "user requested media removal"
Case 32770 'DBT_DEVICEQUERYREMOVEFAILED
Print #demo, "media removal failed"
Case 32771 'DBT_DEVICEREMOVEPENDING
Print #demo, "media removal pending"
Case 32772 'DBT_DEVICEREMOVECOMPLETE
Print #demo, "media removed"
Case 32773 'DBT_DEVICETYPESPECIFIC
Print #demo, "device-specific event"
Case 32774 'DBT_CUSTOMEVENT
Print #demo, "custom event"
Case Else
Print #demo, "unknown event"
End Select
' Return TRUE to allow the action. Not all actions can be cancelled.
OnDeviceChange = 1
End Function |