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 нет.
Если бы ты был чуть более внимателен, ты бы заметил вызов MouEnableDisablePort() в mouclass'е, который для PnP-портов выливается в IoGetDeviceObjectPointer(), а эта функция внутри себя вызывает ZwOpenFile(), т.е. посылает IRP_MJ_CREATE. Кроме этого, большинство запросов device control, переданных тебе, это не mouclass шлёт, а подсистема Win32, а тебе попадают как нижнему по стеку. Ну это так, на заметку.
A_>2. При отключении устройства срабатывает только IRP_MJ_CLOSE. IOCTL_INTERNAL_MOUSE_DISCONNECT почему-то не прилетает, что мне кажется странным. По идее этот запрос комплементарный к IOCTL_INTERNAL_MOUSE_CONNECT.
А это вообще нормальное поведение для компонентов ядра, хотя соглашусь, что не совсем логичное. Например, TDI-клиенты тоже не шлют TDI_DISCONNECT и TDI_DISASSOCIATE_ADDRESS и так далее, вместо этого сразу ZwClose(). Полагаю, это всё сделано в целях оптимизации производительности, так что ничего страшного.
A_>3. Проверил так же на нескольких подключенных устройствах — для каждого в отдельности выполняется такая цепочка. То есть несколько устройств работают вместе без проблем.