Blog. Just Blog

Обработка подключения и отключения съемного накопителя

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
С расширением рынка переносных устройств и USB-накопителей становится актуальной задача по обработке их взаимодействия с компьютером. Сегодня разберем обработку подключения и отключения съемных накопителей, таких как Flash-диски, карты памяти и USB-диски. Начинаем с теории. При подключении или отключении съемного накопителя система посылает всем окнам (через глобальный хэндл HWND_BROADCAST) сообщение WM_DEVICECHANGE. Но это сообщение всего лишь о самом факте изменения состояния съемного накопителя, а более подробные значения содержатся в параметрах lParam и wParam этого сообщения. В wParam приходит расшифровка произошедшего события: подключение, отключение, изменения состояния, отмена отключения и т.п. Нас пока интересует только два: DBT_DEVICEARRIVAL - подключение сменного накопителя и DBT_DEVICEREMOVECOMPLETE - извлечение накопителя. Основной обработчик событий приложения ничем не отличается от обычных обработчиков. Нам также понадобятся несколько констант, которые по умолчанию не определены в FASM:
  1. DBT_DEVICEARRIVAL        = 0x8000
  2. DBT_DEVICEREMOVECOMPLETE = 0x8004
  3.  
  4. DBT_DEVTYP_VOLUME        = 0x00000002
И, собственно, сам обработчик. Я оставил только нужные фрагменты кода:
  1. proc DialogProc hwnddlg,msg,wparam,lparam
  2.         push    ebx esi edi
  3.         ...
  4.         ; Пришло сообщение об изменении состояния съемного накопителя
  5.         cmp     [msg],WM_DEVICECHANGE
  6.         je      update_usb
  7.         ...
  8. update_usb:
  9.         ; Устройство подключено?
  10.         cmp     [wparam],DBT_DEVICEARRIVAL
  11.         je      usb_connected
  12.  
  13.         ; Устройство извлечено?
  14.         cmp     [wparam],DBT_DEVICEREMOVECOMPLETE
  15.         je      usb_disconnected
  16.  
  17.         jmp     processed
  18.  
  19. usb_connected:
  20.         ; Обработка подключения устройства
  21.         ...
  22.         jmp     processed
  23.  
  24. usb_disconnected:
  25.         ; Обработка отключения устройства
  26.         ...
  27.         jmp     processed
  28.         ...
  29. processed:
  30.         mov     eax,1
  31. finish:
  32.         pop     edi esi ebx
  33.         ret
  34. endp
Для полноты картины осталось узнать, какой именно диск был подключен или извлечен. В параметре lParam сообщения WM_DEVICECHANGE передается указатель на структуру, которая содержит подробную информацию о случившемся событии. FASM про нее тоже ничего не знает, поэтому придется и ее описать самостоятельно.

Структура состоит из двух частей: заголовка и информационной части. В заголовке содержится общая информация, а информационная часть может различаться в зависимости от типа устройства, на котором произошло событие. Для съемных дисков она будет следующая:
  1. struct DEV_BROADCAST
  2.         ; Заголовок структуры
  3.         dbch_size       dd ?
  4.         dbch_devicetype dd ?
  5.         dbch_reserved   dd ?
  6.  
  7.         ; Информационная часть структуры
  8.         dbcv_unitmask   dd ?
  9.         dbcv_flags      dd ?
  10. ends
Поскольку сообщения могут приходить от разных устройств, а нас интересуют только съемные накопители, то в обработчики придется добавить фильтр. Поле заголовка dbch_devicetype содержит значение типа устройства, в нашем случае это должно быть DBT_DEVTYP_VOLUME, оно описано выше. Все остальные сообщения мы должны пропускать без обработки. Также имейте в виду, что некоторые устройства, например, флоппи-дисководы или CD-ROM могут вообще не инициировать никаких событий, и смену носителей в них отследить не получится.

Чтобы узнать букву диска, которую система присвоила съемному носителю, надо разобрать значение dbcv_unitmask из информационной части структуры. Это битовая маска, где каждый отдельный бит соответствует определенной букве: бит 0 соответствует диску A, бит 1 - диску B, бит 2 - диску C и так далее. Я нашел несколько вариантов преобразования такой маски в человеко-понятную букву, но решил сделать свой, обойдясь двумя ассемблерными командами:
  1.         ; Получить букву диска из битовой маски (маска в регистре EAX)
  2.         bsr     eax,eax
  3.         ; В регистре AL буква диска
  4.         add     al,'A'
Теперь у нас есть все данные для обработки подключения и отключения съемных накопителей. Вот некоторые варианты применения таких обработчиков: резервное сохранение важных данных при неожиданном отключении накопителя, антивирусный мониторинг подключаемых USB-дисков, незаметное фоновое копирование данных с флешек или запись на них какой-либо информации, и многое-многое другое. Все зависит только от вашей фантазии и порядочности.

В приложении пример программы, записывающей в свой лог все сообщения о подключении и отключении съемных носителей с указанием букв дисков.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

USB.Plug.n.Play.Demo.zip (2,824 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 7224 | Комментариев: 19

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
джонни (05.12.2017 в 14:45):
Message-Only Window вот такое не работает. WindowProc принимает штук 5 сообщений и всё.
invoke  CreateWindowEx, 0,_class,0,0,0,0,0,0,HWND_MESSAGE,0,0,0
а вот так работает
invoke  CreateWindowEx, 0,_class,0,0,0,0,0,0,0,0,0,0
в msdn написано A message-only window ... does not receive broadcast messages
https://msdn.microsoft.com/en-...message_only
ManHunter (04.05.2016 в 12:11):
Да мне и спасибо достаточно :) Рад, что пригодилось.
вадя (03.05.2016 в 01:47):
спасибо очень помогло перепрограммировали свой вейп спасибо еще раз как скинуть вам на пиво
X (07.02.2013 в 19:20):
Спасибо. Буду разбираться.
ManHunter (07.02.2013 в 19:00):
Потрудись хотя бы открыть приведенную ссылку и внимательно там все прочитать.
1. RegisterClassEx -> WNDCLASSEX -> lpfnWndProc
2. CreateWindowEx с зарегистрированным классом
X (07.02.2013 в 18:48):
В примере программы создается модальное окно с помощью DialogBoxParam и ведется обработка всех сообщений в DialogProc функции. Если использовать CreateWindowEx для создания невидимого окна, то как указать функцию для обработки сообщений?
ManHunter (07.02.2013 в 18:45):
CreateWindowEx в MSDN
X (07.02.2013 в 18:42):
Где посмотреть пример создания невидимого окна-перехватчика на FASMe?
ManHunter (07.02.2013 в 18:36):
А что мешает консольной программе создать невидимое окно-перехватчик (Message-Only Window), как это делают все нормальные приложения?
http://msdn.microsoft.com/en-u...message_only
X (07.02.2013 в 18:34):
Возможно ли осуществить обработку подключения/отключения съемного накопителя в консольном приложении без создания окна?
Евлампий (26.09.2011 в 19:39):
респект
спс за инфу
zummenix (18.04.2011 в 17:18):
:) Насчет
   bsr     eax,eax
   add     al,'A'
Красивое и элегантное решение, мне нравится!
ManHunter (18.04.2011 в 16:47):
zummenix, http://lurkmore.ru/%D0%9D%D0%95%D0%A5 детектед :)
zummenix (18.04.2011 в 16:46):
Странно, сегодня у меня тоже нормально работает.
ManHunter (18.04.2011 в 11:09):
Проверил на чистой WinXP, тоже все прекрасно появляется.
ManHunter (17.04.2011 в 16:06):
Я проверял на Win7 - появляется. Завтра на работе проверю на WinXP.
zummenix (17.04.2011 в 15:50):
Видимо нужно возвращать 0 после обработки usb_connected, иначе не появляется безопасное извлечение устройства в трее.
ManHunter (17.04.2011 в 11:26):
На PHP решение заняло бы пару мегабайт, на JavaScript и SQL такие задачи не решаются, а на других языках я не пишу. А вообще толсто :)
Gideon Vi (17.04.2011 в 07:47):
Пардон, а асм в решении подобных задач - реальная необходимость или разминка для извилин?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.09 сек. / MySQL: 2 (0.0046 сек.) / Память: 4.5 Mb
Наверх