By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,558 Members | 1,373 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,558 IT Pros & Developers. It's quick & easy.

USB Device Removal Notifications

P: 31
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_DEVICEQUERYREMOVE) 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_HANDLE 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 RegisterDeviceNotification function.

I have successfully received the DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE messages by using the DEV_BROADCAST_DEVICEINTERFACE structure, but I'm having troubles using the DEV_BROADCAST_HANDLE structure. It fails at the RegisterDeviceNotification line, returning a standard error code of 0, and a DLL error code of 1066.

Declarations:
Expand|Select|Wrap|Line Numbers
  1. 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
  2. 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
  3. Public Declare Function RegisterDeviceNotificationA Lib "user32" (ByVal hRecipient As Long, NotificationFilter As DEV_BROADCAST_HANDLE, ByVal Flags As Long) As Long
  4. Public Declare Function SetWindowLongA Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
  5.  
  6. Public Type GUID
  7.     D1(3) As Byte
  8.     D2(1) As Byte
  9.     D3(1) As Byte
  10.     D4(7) As Byte
  11. End Type
  12.  
  13. Public Type DEV_BROADCAST_DEVICEINTERFACE
  14.     dbcc_size As Long
  15.     dbcc_devicetype As Long
  16.     dbcc_reserved As Long
  17.     dbcc_classguid As GUID
  18.     dbcc_name As String
  19. End Type
  20.  
  21. Public Type DEV_BROADCAST_HANDLE
  22.     dbch_size As Long
  23.     dbch_devicetype As Long
  24.     dbch_reserved As Long
  25.     dbch_handle As Long
  26.     dbch_devnotify As Long
  27.     dbch_eventguid As GUID
  28.     dbch_nameoffset As Long
  29.     dbch_data(1023) As Byte
  30. End Type
  31.  
  32. Public Const DBT_DEVICEQUERYREMOVE As Long = 32769
  33. Public Const DBT_DEVTYP_DEVICEINTERFACE As Long = 5
  34. Public Const DBT_DEVTYP_HANDLE As Long = 6
  35. Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Long = 0
  36. Public Const DEVICE_NOTIFY_ALL_INTERFACE_CLASSES As Long = 4
  37. Public Const FILE_ATTRIBUTE_NORMAL As Long = 128
  38. Public Const FILE_SHARE_READ As Long = 1
  39. Public Const GENERIC_READ As Long = &H80000000
  40. Public Const GWL_WNDPROC As Long = -4
  41. Public Const WM_DEVICECHANGE As Long = &H219
  42.  
General Code:
Expand|Select|Wrap|Line Numbers
  1. Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  2.  
  3.     If uMsg = WM_DEVICECHANGE Then
  4.         MsgBox "DeviceChange message received. " & wParam & " " & lParam
  5.         If wParam = DBT_DEVICEQUERYREMOVE Then
  6.             MsgBox "DeviceQueryRemove message received."
  7.         End If
  8.     End If
  9.  
  10.     WindowProc = CallWindowProcA(hUSBProc, hWnd, uMsg, wParam, lParam)
  11.  
  12. End Function
  13.  
  14. Sub Main
  15.  
  16.     Form1.Hide
  17.     hFile = CreateFileA("E:\MYFILE.TXT", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
  18.     With USBNotify
  19.         .dbch_size = Len(USBNotify)
  20.         .dbch_devicetype = DBT_DEVTYPE_HANDLE
  21.         .dbch_reserved = 0
  22.         .dbch_handle = hFile
  23.     End With
  24.     I = RegisterDeviceNotificationA(Form1.hWnd, USBNotify, DEVICE_NOTIFY_WINDOW_HANDLE Or DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
  25.     hUSBProc = SetWindowLongA(Form1.hWnd, GWL_WNDPROC, AddressOf WindowProc)
  26.  
  27. End Sub
  28.  
May 29 '08 #1
Share this Question
Share on Google+
3 Replies


daniel aristidou
100+
P: 491
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_DEVICEQUERYREMOVE) 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_HANDLE 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 RegisterDeviceNotification function.

I have successfully received the DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE messages by using the DEV_BROADCAST_DEVICEINTERFACE structure, but I'm having troubles using the DEV_BROADCAST_HANDLE structure. It fails at the RegisterDeviceNotification 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
May 31 '08 #2

P: 31
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.
Jun 1 '08 #3

P: 31
I'm still looking for a way of getting the program to pick up the DBT_DEVICEQUERYREMOVE message. I have satisfied the RegisterDeviceNotification function by providing a handle to the USB device, but still can't get the message.

Here's the updated version:

Declarations:
Expand|Select|Wrap|Line Numbers
  1. 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
  2. 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
  3. Public Declare Function RegisterDeviceNotificationA Lib "user32" (ByVal hRecipient As Long, NotificationFilter As DEV_BROADCAST_HANDLE, ByVal Flags As Long) As Long
  4. Public Declare Function SetWindowLongA Lib "user32" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
  5.  
  6. Public Type GUID
  7.     D1 As Long
  8.     D2 As Integer
  9.     D3 As Integer
  10.     D4(7) As Byte
  11. End Type
  12.  
  13. Public Type DEV_BROADCAST_HANDLE
  14.     dbch_size As Long
  15.     dbch_devicetype As Long
  16.     dbch_reserved As Long
  17.     dbch_handle As Long
  18.     dbch_devnotify As Long
  19.     dbch_eventguid As GUID
  20.     dbch_nameoffset As Long
  21.     dbch_data As Byte
  22. End Type
  23.  
  24. Public Const DBT_DEVICEQUERYREMOVE As Long = 32769
  25. Public Const DBT_DEVTYP_HANDLE As Long = 6
  26. Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Long = 0
  27. Public Const FILE_SHARE_READ As Long = 1
  28. Public Const FILE_SHARE_WRITE As Long = 2
  29. Public Const GENERIC_READ As Long = &H80000000
  30. Public Const GWL_WNDPROC As Long = -4
  31. Public Const WM_DEVICECHANGE As Long = 537
  32.  
  33. Public hFile As Long, hUSBProc As Long
  34. Public USBNotify As DEV_BROADCAST_HANDLE
General Code:
Expand|Select|Wrap|Line Numbers
  1. Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  2.  
  3.     If uMsg = WM_DEVICECHANGE Then
  4.         MsgBox "DeviceChange message received. " & wParam & " " & lParam
  5.         If wParam = DBT_DEVICEQUERYREMOVE Then
  6.         'Still not working!
  7.         MsgBox "DeviceQueryRemove message received."
  8.         End If
  9.     End If
  10.  
  11.     WindowProc = CallWindowProcA(hUSBProc, hWnd, uMsg, wParam, lParam)
  12.  
  13. End Function
  14.  
  15. Sub Main
  16.  
  17.     Form1.Hide
  18.     hFile = CreateFileA("USB Mass Storage Device", GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0)
  19.     With USBNotify
  20.         .dbch_size = LenB(USBNotify)
  21.         .dbch_devicetype = DBT_DEVTYPE_HANDLE
  22.         .dbch_handle = hFile
  23.     End With
  24.     I = RegisterDeviceNotificationA(Form1.hWnd, USBNotify, DEVICE_NOTIFY_WINDOW_HANDLE)
  25.     hUSBProc = SetWindowLongA(Form1.hWnd, GWL_WNDPROC, AddressOf WindowProc)
  26.  
  27. End Sub
If anyone has the answer, your help would be greatly appreciated.
Sep 12 '08 #4

Post your reply

Sign in to post your reply or Sign up for a free account.