USB Device Removal Notifications

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • tristanlbailey
    New Member
    • Apr 2007
    • 30

    USB Device Removal Notifications

    Hello.

    I'm trying to create a program in Visual Basic 6 that detects when a user is attempting to remove a USB drive, by using the "Safely Remove Hardware" icon on the taskbar. There is supposed to be a message (DBT_DEVICEQUER YREMOVE) that the Windows Operating System broadcasts to applications that are "listening" for it. I'm trying to utilise this message to prevent the removal of the device.

    It has been stated on the MSDN site, that you need to use the DEV_BROADCAST_H ANDLE structure, open a file on the USB drive, and insert the file's handle into the structure; followed by a call to the system's RegisterDeviceN otification function.

    I have successfully received the DBT_DEVICEARRIV AL and DBT_DEVICEREMOV ECOMPLETE messages by using the DEV_BROADCAST_D EVICEINTERFACE structure, but I'm having troubles using the DEV_BROADCAST_H ANDLE structure. It fails at the RegisterDeviceN otification line, returning a standard error code of 0, and a DLL error code of 1066.

    Declarations:
    [CODE=VB]Public Declare Function CallWindowProcA Lib "user32" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Declare Function CreateFileA Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttri butes As Long, ByVal dwCreationDispo sition As Long, ByVal dwFlagsAndAttri butes As Long, ByVal hTemplateFile As Long) As Long
    Public Declare Function RegisterDeviceN otificationA Lib "user32" (ByVal hRecipient As Long, NotificationFil ter As DEV_BROADCAST_H ANDLE, ByVal Flags As Long) As Long
    Public Declare Function SetWindowLongA Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

    Public Type GUID
    D1(3) As Byte
    D2(1) As Byte
    D3(1) As Byte
    D4(7) As Byte
    End Type

    Public Type DEV_BROADCAST_D EVICEINTERFACE
    dbcc_size As Long
    dbcc_devicetype As Long
    dbcc_reserved As Long
    dbcc_classguid As GUID
    dbcc_name As String
    End Type

    Public Type DEV_BROADCAST_H ANDLE
    dbch_size As Long
    dbch_devicetype As Long
    dbch_reserved As Long
    dbch_handle As Long
    dbch_devnotify As Long
    dbch_eventguid As GUID
    dbch_nameoffset As Long
    dbch_data(1023) As Byte
    End Type

    Public Const DBT_DEVICEQUERY REMOVE As Long = 32769
    Public Const DBT_DEVTYP_DEVI CEINTERFACE As Long = 5
    Public Const DBT_DEVTYP_HAND LE As Long = 6
    Public Const DEVICE_NOTIFY_W INDOW_HANDLE As Long = 0
    Public Const DEVICE_NOTIFY_A LL_INTERFACE_CL ASSES As Long = 4
    Public Const FILE_ATTRIBUTE_ NORMAL As Long = 128
    Public Const FILE_SHARE_READ As Long = 1
    Public Const GENERIC_READ As Long = &H80000000
    Public Const GWL_WNDPROC As Long = -4
    Public Const WM_DEVICECHANGE As Long = &H219
    [/CODE]

    General Code:
    [CODE=VB]
    Function WindowProc(ByVa l hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

    If uMsg = WM_DEVICECHANGE Then
    MsgBox "DeviceChan ge message received. " & wParam & " " & lParam
    If wParam = DBT_DEVICEQUERY REMOVE Then
    MsgBox "DeviceQueryRem ove message received."
    End If
    End If

    WindowProc = CallWindowProcA (hUSBProc, hWnd, uMsg, wParam, lParam)

    End Function

    Sub Main

    Form1.Hide
    hFile = CreateFileA("E: \MYFILE.TXT", GENERIC_READ, FILE_SHARE_READ , 0, OPEN_EXISTING, FILE_ATTRIBUTE_ NORMAL, 0)
    With USBNotify
    .dbch_size = Len(USBNotify)
    .dbch_devicetyp e = DBT_DEVTYPE_HAN DLE
    .dbch_reserved = 0
    .dbch_handle = hFile
    End With
    I = RegisterDeviceN otificationA(Fo rm1.hWnd, USBNotify, DEVICE_NOTIFY_W INDOW_HANDLE Or DEVICE_NOTIFY_A LL_INTERFACE_CL ASSES)
    hUSBProc = SetWindowLongA( Form1.hWnd, GWL_WNDPROC, AddressOf WindowProc)

    End Sub
    [/CODE]
  • daniel aristidou
    Contributor
    • Aug 2007
    • 494

    #2
    Originally posted by tristanlbailey
    Hello.

    I'm trying to create a program in Visual Basic 6 that detects when a user is attempting to remove a USB drive, by using the "Safely Remove Hardware" icon on the taskbar. There is supposed to be a message (DBT_DEVICEQUER YREMOVE) that the Windows Operating System broadcasts to applications that are "listening" for it. I'm trying to utilise this message to prevent the removal of the device.

    It has been stated on the MSDN site, that you need to use the DEV_BROADCAST_H ANDLE structure, open a file on the USB drive, and insert the file's handle into the structure; followed by a call to the system's RegisterDeviceN otification function.

    I have successfully received the DBT_DEVICEARRIV AL and DBT_DEVICEREMOV ECOMPLETE messages by using the DEV_BROADCAST_D EVICEINTERFACE structure, but I'm having troubles using the DEV_BROADCAST_H ANDLE structure. It fails at the RegisterDeviceN otification line, returning a standard error code of 0, and a DLL error code of 1066.
    hmmm not sure if its relevant but might be...
    Have you checked the program on a different pc or with a different operating system.
    it might be the os that is to blame

    Comment

    • tristanlbailey
      New Member
      • Apr 2007
      • 30

      #3
      The main Windows Operating System that I use to test programs on is Windows XP. I don't see why this sort of code shouldn't work on Windows XP.

      I plan to use the program on multiple Windows Operating System platform versions (i.e. Windows 98, Me, NT, 2000, etc.), however. I believe all of the necessary API functions exist within each of these versions.

      Comment

      • tristanlbailey
        New Member
        • Apr 2007
        • 30

        #4
        I'm still looking for a way of getting the program to pick up the DBT_DEVICEQUERY REMOVE message. I have satisfied the RegisterDeviceN otification function by providing a handle to the USB device, but still can't get the message.

        Here's the updated version:

        Declarations:
        Code:
        Public Declare Function CallWindowProcA Lib "user32" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Public Declare Function CreateFileA Lib "kernel32" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
        Public Declare Function RegisterDeviceNotificationA Lib "user32" (ByVal hRecipient As Long, NotificationFilter As DEV_BROADCAST_HANDLE, ByVal Flags As Long) As Long
        Public Declare Function SetWindowLongA Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
        
        Public Type GUID
            D1 As Long
            D2 As Integer
            D3 As Integer
            D4(7) As Byte
        End Type
        
        Public Type DEV_BROADCAST_HANDLE
            dbch_size As Long
            dbch_devicetype As Long
            dbch_reserved As Long
            dbch_handle As Long
            dbch_devnotify As Long
            dbch_eventguid As GUID
            dbch_nameoffset As Long
            dbch_data As Byte
        End Type
        
        Public Const DBT_DEVICEQUERYREMOVE As Long = 32769
        Public Const DBT_DEVTYP_HANDLE As Long = 6
        Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Long = 0
        Public Const FILE_SHARE_READ As Long = 1
        Public Const FILE_SHARE_WRITE As Long = 2
        Public Const GENERIC_READ As Long = &H80000000
        Public Const GWL_WNDPROC As Long = -4
        Public Const WM_DEVICECHANGE As Long = 537
        
        Public hFile As Long, hUSBProc As Long
        Public USBNotify As DEV_BROADCAST_HANDLE
        General Code:
        Code:
        Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        
            If uMsg = WM_DEVICECHANGE Then
                MsgBox "DeviceChange message received. " & wParam & " " & lParam
                If wParam = DBT_DEVICEQUERYREMOVE Then
        		'Still not working!
        		MsgBox "DeviceQueryRemove message received."
                End If
            End If
            
            WindowProc = CallWindowProcA(hUSBProc, hWnd, uMsg, wParam, lParam)
        
        End Function
        
        Sub Main
        
            Form1.Hide
            hFile = CreateFileA("USB Mass Storage Device", GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0)
            With USBNotify
                .dbch_size = LenB(USBNotify)
                .dbch_devicetype = DBT_DEVTYPE_HANDLE
                .dbch_handle = hFile
            End With
            I = RegisterDeviceNotificationA(Form1.hWnd, USBNotify, DEVICE_NOTIFY_WINDOW_HANDLE)
            hUSBProc = SetWindowLongA(Form1.hWnd, GWL_WNDPROC, AddressOf WindowProc)
        
        End Sub
        If anyone has the answer, your help would be greatly appreciated.

        Comment

        Working...