Здравствуйте, x64, Вы писали:
A_>>1. IOCTL_MOUSE_QUERY_ATTRIBUTES прилетает, только в случае успешного завершения обработчика IRP_MJ_CREATE. То есть последовательность при подключении устройства такая: IOCTL_INTERNAL_MOUSE_CONNECT -> IRP_MJ_CREATE -> IOCTL_MOUSE_QUERY_ATTRIBUTES. После этого можно вызывать callback. Если же обработчика IRP_MJ_CREATE в драйвере нет или он ошибку возвращает, то IOCTL_MOUSE_QUERY_ATTRIBUTES запроса не будет и смысла вызывать callback нет.
x64>Если бы ты был чуть более внимателен, ты бы заметил вызов MouEnableDisablePort() в mouclass'е, который для PnP-портов выливается в IoGetDeviceObjectPointer(), а эта функция внутри себя вызывает ZwOpenFile(), т.е. посылает IRP_MJ_CREATE. Кроме этого, большинство запросов device control, переданных тебе, это не mouclass шлёт, а подсистема Win32, а тебе попадают как нижнему по стеку. Ну это так, на заметку.
То есть в моем случае судя по исходникам IOCTL_INTERNAL_MOUSE_CONNECT создается с нуля mouclass`ом, а IOCTL_MOUSE_QUERY_ATTRIBUTES "транслируется" им нижестоящему драйверу (то есть моему).
A_>>2. При отключении устройства срабатывает только IRP_MJ_CLOSE. IOCTL_INTERNAL_MOUSE_DISCONNECT почему-то не прилетает, что мне кажется странным. По идее этот запрос комплементарный к IOCTL_INTERNAL_MOUSE_CONNECT.
x64>А это вообще нормальное поведение для компонентов ядра, хотя соглашусь, что не совсем логичное. Например, TDI-клиенты тоже не шлют TDI_DISCONNECT и TDI_DISASSOCIATE_ADDRESS и так далее, вместо этого сразу ZwClose(). Полагаю, это всё сделано в целях оптимизации производительности, так что ничего страшного.
На мой взгляд передача указателей, тем более callback`ов между компонентами — не безопасная операция, и интерфейс должен быть логичным в этом случае, чтобы точно знать, когда адрес валидный и его можно использовать, а когда нет. Пока не прочитал в MSDN, что IOCTL_INTERNAL_MOUSE_DISCONNECT не реализован, подсознательно думал, что что-то не так в моем коде. Сейчас получается, что адрес валидный на период между обработками IOCTL_INTERNAL_MOUSE_CONNECT и IRP_MJ_CLOSE. В обработчике IRP_MJ_CLOSE структуру CONNECT_DATA забиваю нулями через memset, чтобы наверняка в указателе NULL был.
A_>>3. Проверил так же на нескольких подключенных устройствах — для каждого в отдельности выполняется такая цепочка. То есть несколько устройств работают вместе без проблем.
x64>Ну кто бы сомневался.