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

С расширением рынка переносных устройств и USB-накопителей становится актуальной задача по обработке их взаимодействия с компьютером. Сегодня разберем обработку подключения и отключения съемных накопителей, таких как Flash-диски, карты памяти и USB-диски. Начинаем с теории. При подключении или отключении съемного накопителя система посылает всем окнам (через глобальный хэндл HWND_BROADCAST) сообщение WM_DEVICECHANGE. Но это сообщение всего лишь о самом факте изменения состояния съемного накопителя, а более подробные значения содержатся в параметрах lParam и wParam этого сообщения. В wParam приходит расшифровка произошедшего события: подключение, отключение, изменения состояния, отмена отключения и т.п. Нас пока интересует только два: DBT_DEVICEARRIVAL - подключение сменного накопителя и DBT_DEVICEREMOVECOMPLETE - извлечение накопителя. Основной обработчик событий приложения ничем не отличается от обычных обработчиков. Нам также понадобятся несколько констант, которые по умолчанию не определены в FASM:
DBT_DEVICEARRIVAL        = 0x8000
DBT_DEVICEREMOVECOMPLETE = 0x8004
 
DBT_DEVTYP_VOLUME        = 0x00000002
И, собственно, сам обработчик. Я оставил только нужные фрагменты кода:
Code (Assembler) : Убрать нумерацию
proc DialogProc hwnddlg,msg,wparam,lparam
        push    ebx esi edi
        ...
        ; Пришло сообщение об изменении состояния съемного накопителя
        cmp     [msg],WM_DEVICECHANGE
        je      update_usb
        ...
update_usb:
        ; Устройство подключено?
        cmp     [wparam],DBT_DEVICEARRIVAL
        je      usb_connected
 
        ; Устройство извлечено?
        cmp     [wparam],DBT_DEVICEREMOVECOMPLETE
        je      usb_disconnected
 
        jmp     processed
 
usb_connected:
        ; Обработка подключения устройства
        ...
        jmp     processed
 
usb_disconnected:
        ; Обработка отключения устройства
        ...
        jmp     processed
        ...
processed:
        mov     eax,1
finish:
        pop     edi esi ebx
        ret
endp

Для полноты картины осталось узнать, какой именно диск был подключен или извлечен. В параметре lParam сообщения WM_DEVICECHANGE передается указатель на структуру, которая содержит подробную информацию о случившемся событии. FASM про нее тоже ничего не знает, поэтому придется и ее описать самостоятельно.

Структура состоит из двух частей: заголовка и информационной части. В заголовке содержится общая информация, а информационная часть может различаться в зависимости от типа устройства, на котором произошло событие. Для съемных дисков она будет следующая:
struct DEV_BROADCAST
        ; Заголовок структуры
        dbch_size       dd ?
        dbch_devicetype dd ?
        dbch_reserved   dd ?
 
        ; Информационная часть структуры
        dbcv_unitmask   dd ?
        dbcv_flags      dd ?
ends

Поскольку сообщения могут приходить от разных устройств, а нас интересуют только съемные накопители, то в обработчики придется добавить фильтр. Поле заголовка dbch_devicetypeсодержит значение типа устройства, в нашем случае это должно быть DBT_DEVTYP_VOLUME, оно описано выше. Все остальные сообщения мы должны пропускать без обработки. Также имейте в виду, что некоторые устройства, например, флоппи-дисководы или CD-ROM могут вообще не инициировать никаких событий, и смену носителей в них отследить не получится.

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

Теперь у нас есть все данные для обработки подключения и отключения съемных накопителей. Вот некоторые варианты применения таких обработчиков: резервное сохранение важных данных при неожиданном отключении накопителя, антивирусный мониторинг подключаемых USB-дисков, незаметное фоновое копирование данных с флешек или запись на них какой-либо информации, и многое-многое другое. Все зависит только от вашей фантазии и порядочности.

В приложении пример программы, записывающей в свой лог все сообщения о подключении и отключении съемных носителей с указанием букв дисков.
Теги:
подключение съемного носителя
Добавлено: 10 Апреля 2018 20:46:33 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...