Здравствуйте, Ignoramus, Вы писали:
I>Господа!
I>Хочу научиться правильно устанавливать WDM-драйверы. Речь идет о filter-драйвере.
I>Можете ли дать инструкцию по пунктам как это делается? Мне пару раз это магическим образом удалось сделать, но осознанно воспроизвести процедуру пока не могу.
I>Меня интересует 2 типа установки:
I>1) Установка для отладки. Т.е. я добавил в драйвер новую фичу, скомпилировал его и хочу установить поверх старого, и так итеративно много раз.
I>2) Установка для релиза. Как добавить процедуру установки драйвера в инсталлятор? (Я пользуюсь MSI). Какие дополнительные файлы (.inf, .cat etc.) для этого необходимы?
--
Для установки WDM драйвера-фильтра (F) "поверх" другого WDM драйвера (A) я пользуюсь следующей процедурой:
1. Регистрирую WDM драйвер-фильтр F в системе с помощью *.inf файла, в котором использую секцию [DefaultInstall]. Запускаю этот файл или по контекстному меню Install, или с помощью функции InstallHinfSection. В принципе, это можно сделать и "руками" в registry.
2. Определяю SP_DEVINFO_DATA WDM драйвера А, "поверх" которого будет установлен драйвер-фильтр.
В моем конкретном случае обычно это делает пользователь, выбирая драйвер из списка. Список драйверов я генерирую с помощью функции SetupDiGetClassDevs. Для каждого драйвера в списке с помощью функции SetupDiEnumDeviceInfo получаю SP_DEVINFO_DATA. Кроме того с помощью функции SetupDiGetDeviceRegistryProperty для каждого драйвера получаю кое-какую дополнительную информацию о нем (Hardware ID, имя сервиса и т.п.), она используется пользователем для осмысленного выбора необходимого драйвера; эту же информацию можно использовать и для автоматического выбора драйвера А.
3. Получаю, акуратно дописываю в конец и сохраняю (с помощью функций SetupDiGetDeviceRegistryProperty и SetupDiSetDeviceRegistryProperty, property SPDRP_UPPERFILTERS) в UpperFilter имя сервиса WDM драйвера-фильтра F.
4. Перезапускаю WDM драйвер А, в котором при повторном старте и будет запущен WDM драйвер-фильтр F; для этого использую функции SetupDiSetClassInstallParams, а затем SetupDiCallClassInstaller с параметром DIF_PROPERTYCHANGE.
Если нужно "снять" драйвер-фильтр F, то каким-то образом запрещаю запуск WDM драйвера А (например, вытаскиваю плату или что-то похожее, вплоть до запуска Windows recovery console), а затем вновь его переустанавливаю.
Несмотря на довольно трудоемкий процесс, это дает возможность поставить драйвер-фильтр (как upper filter, так и lower filter) для любого драйвера в системе.
Здравствуйте, Ignoramus, Вы писали:
I>Спасибо, буду дальше изучать матчасть :). "Успехи" уже есть — винду уже переставлял :)
--
Если есть необходимость — могу послать несколько классов для перечисления и инсталяции драйверов и пример их использования для установки драйвера ильтра. Но они относятся только к установке драйвера-фильтра для одного устройства, а не для класса устройств.
I>P.S. I>Правильно ли я понимаю Вашу терминологию — все драйверы Вы делите на Legacy и PNP? Я больше склонен делить их на Legacy и WDM, термин PNP меня несколько сбивает с толку, особенно для filter-драйвера, т.к. такой драйвер по сути представляет собой нечто искусственное, внедряемое в стек "насильно", а PNP предполагает, что система сама ищет драйвер для обнаруженного устройства.
--
Нет, я не все драйвера делю на две эти группы — есть еще и мини-драйвера, и streaming... Но когда речь идет о драйверах-фильтрах, то такое деление, по-моему, однозначно.
Да, наверное более корректным говорить о WDM-драйверах, чем о PNP-драйверах. Правда, драйвер-фильтр для PNP-драйвера также должен поддерживать корректную обработку всех системных IRP, включая и PNP IRP. Кроме того, в WDM явно включена возможность включения в стек драйверов, соответсвующий некоторому hardware ID, и драйверов-фильтров, поэтому их "искусственность" спорна.
Здравствуйте, Ignoramus, Вы писали:
I>Фух, кажется разобрался.
--
Прежде всего, это очень хорошо, что все в конце-концов получилось!
I>Чтобы установить фильтр-драйвер, действовать нужно так:
I>1) Перечислить все устройства функциями SetupDi*, найти то, у которого нужный Class GUID и прописать ему свойство UpperFilters.
I>2) Создать сервис для фильтра функцией CreateService.
I>3) Дальше возможны варианты. Если устройство, на которое устанавливается фильтр, позволяет перезапускать себя без перезагрузки, можно попробовать перезапустить драйвер функциями SetupDi*, как описывал Геннадий. В моем случае это не срабатывает — функция перезапуска драйвера по возвращении указывает на необходимость перезагрузки системы, а до тех пор ничего не происходит. Поэтому можно не пытаться перезапустить драйвер, а сразу перезагрузить машину.
--
Наверное, в программе просто стоит проверять флаг необходимости перезагрузки и, при необходимости, перезапустить машину автоматически или попросить это сделать пользователя.
I>Аналогично выглядит процедура удаления фильтр-драйвера.
I>Кроме того, я сделал следующие выводы:
I>Опыт 1. Параметр UpperFilters в реестре CurrentControlSet\Control\Class\{...}\ непонятно для чего нужен. Я не обнаружил никакого эффекта от его наличия/отсутствия. Реально влияет только UpperFilters в CurrentControlSet\Enum\..., т.е. там где реальные устройства описаны. Менять эти ключи в реестре можно только функциями SetupDi*, regedit матерится .
--
По умолчанию ветка registry ...\Enum "закрыта" для редактирования. Что бы ее можно изменять "руками", можно с помощью regedt32.exe разрешить для этой ветки "Full Control" (меню Security -> Permissions).
I>Опыт 2. Запускать функцией StartService можно только драйверы, которые ни к какому устройству не привязаны (т.е. которые служат просто программой, выполняемой в kernel mode). Фильтры в эту категорию не входят. Попытка запуска фильтра StartService выдает сообщение ERROR_SERVICE_DISABLED "The service cannot be started, either because it is disabled, or because it has no enabled devices associated with it."
I>Опыт 3. Аналогично, после перезагрузки системы, когда фильтр уже запущен, StopService не работает с сообщением что эта операция сервисом не поддерживается. Судя по всему, придется смириться с тем, что некоторые устройства, к которым подключается фильтр, не позволяют менять свои параметры и состояние без перезагрузки. Таким образом, "динамический" запуск фильтра превращается к сожалению в "статический". Хотя может это и к лучшему — меньше непредвиденных ситуаций в рантайме произойти может. А при правильной конструкции фильтра, он потреблять ресурсы не должен когда не используется...
--
Запускать драйвер-фильтр для WDM PNP device'ов самостоятельно, по-моему, нет никакого смысла! Насколько я понял архитектуру drivers layer для Windows 2K, драйверы фильтры должны принимать участие в "фильтрации" сообщений для фильтруемого драйвера уже на самых первых этапах его иницализации. Поэтому и требуется запускать драйвер-фильтр совместно с фильтруемым таким достаточно сложным способом.
I>Опыт 4. Фильтр, подключаемый к драйверу устройства, наследует права доступа последнего. Т.е. если получить хендл устройства через CreateFile было нельзя по причине access denied, то и для подключенного к нему фильтра будет access denied. Это в принципе соответствует концепции безопасности Windows, но затрудняет работу с фильтром — нельзя использовать DeviceIoControl.
--
Сообщения DeviceIoControl, которые приходят в драйвер-фильтр, "принадлежат", по сути, фильтруемому драйверу. Поэтому для управления состоянием драйвера-фильтра нужны другие механизмы (например, именованые device'ы, call-back функции и т.п.).
I>Остался еще один вопрос: Если я удаляю фильтр, то мне нужно сбросить соответствующую запись UpperFilters. Функции SetupDi* позволяют сделать эту запись пустой, но не удалить ее полностью. Однако, в случае пустой строки UpperFilters, драйвер устройства не грузится, сообщение что-то вроде — невозможно запустить устройство, т.к. не все драйверы удалось загрузить. Что делать?
--
Что такое "пустая строка"?
PropertyBuffer
The address of a buffer that contains the new data for the property. If the property is being cleared, then this pointer should be NULL and PropertyBufferSize must be zero.
Здравствуйте, Ignoramus, Вы писали:
I>Когда я говорил "поверх", я вообще-то имел в виду "вместо" , вместо своего же драйвера, который был установлен ранее. Установка "вместо" постоянно необходима в процессе разработки и отладки. Если же говорить о "поверх" в смысле "upper", то да, реальное устройство известно конечно же, драйвер для него в системе уже есть, и я не имею к нему никакого другого отношения.
--
Понятно.
Я везде подразумевал "поверх" в смысле "upper-filter".
Если же нужно "заменить" свой драйвер-фильтр, то я обычно просто переинсталлирую "драйвер того реального устройства".
ГМ>>Проблема в том, что, насколько я знаю, нет "документированого" способа определить описание драйвера в ветке CurrentControlSet\ENUM\... в registry и добавить туда UpperFilter (или LowerFilter) и поэтому-то и приходится работать так. ГМ>>Определить же "руками" это достаточно просто — проанализируй информацию из ветки ENUM для описания сервиса любого драйвера, там все достаточно прозрачно.
I>Т.е. Вы предлагаете единожды написать утилитку, которая будет ставить драйвер программно, я правильно Вас понял?
--
Ну, примерно так. Или написать отдельную утилиту, или просто встроить соответствующий код в основное приложение, работающее с фильтром.
И, кстати, можно сделать утилиту и для программного "снятия" драйвера-фильтра.
ГМ>>А какие проблемы с *.inf файлами?
I>Прочитал описание формата, посмотрел примеры из разных источников — они такие разные, что так и не понял какие секции мне нужны, а какие можно выбросить... К тому же вопрос — нужно ли мне действительно с ними разбираться, если я, скажем, буду при отладке устанавливать драйвер вручную (или программно с помощью утилитки), а в релизе включу драйвер в инсталлятор и он как-то по-другому (?) будет устанавливаться, без inf.
--
На мой взгляд, в Windows 2K/XP всегда лучше использовать *.inf файлы для установки драйверов. Информацию о структуре этих файлов можно найти в книге Walter Oney "Programming the Microsoft Windows Driver Model", 2nd edition, глава 15 "Distributing Device Drivers". Кстати, *.inf файл для драйвера-фильтра можно найти в примерах к главе 16 этой же книги (Powertrace).
I>Я извиняюсь за путаницу . Драйвер в окончательном варианте будет только один, WDM filter.
--
1. Программа инсталяции обязательно должна зарегистрировать WDM драйвер фильтр в системе как сервис (п.1 моего первого сообщения).
2. Если драйвер-фильтр нужно сразу же запустить, то уже в программе инсталяции необходимо выполнить и остальные пункты 2-4.
3. Если драйвер-фильтр должен запускаться только при старте определенного приложения (на мой взляд, это логичнее), то эти пункты можно выполнить при старте этого приложения. Кстати, а при окончании этого приложения вполне можно драйвер-фильтр "снять" из системы.
4. При деинсталяции программы так же необходимо "снять" драйвер-фильтр из системы (как из строки UpperFilter фильтруемого драйвера, так и как сервис).
Хочу научиться правильно устанавливать WDM-драйверы. Речь идет о filter-драйвере.
Можете ли дать инструкцию по пунктам как это делается? Мне пару раз это магическим образом удалось сделать, но осознанно воспроизвести процедуру пока не могу.
Меня интересует 2 типа установки:
1) Установка для отладки. Т.е. я добавил в драйвер новую фичу, скомпилировал его и хочу установить поверх старого, и так итеративно много раз.
2) Установка для релиза. Как добавить процедуру установки драйвера в инсталлятор? (Я пользуюсь MSI). Какие дополнительные файлы (.inf, .cat etc.) для этого необходимы?
Спасибо, за развернутый ответ!
Но так все сложно на первый взгляд!
Если можно, я уточню вопрос:
1. У меня пока нет необходимости выбирать драйвер из списка, тем более давать юзеру такую возможность.
2. Мне, в принципе, не нужно устанавливать драйвер программно. Вполне достаточно ручной установки. Разобраться с inf-файлами с разбега тоже оказалось не так просто...
3. С другой стороны, меня интересует установка драйвера вместе с инсталляцией программы. Как это обычно делается?
Здравствуйте, Ignoramus, Вы писали:
I>Если можно, я уточню вопрос:
I>1. У меня пока нет необходимости выбирать драйвер из списка, тем более давать юзеру такую возможность.
--
Но что-то о том драйвере, "поверх" которого ставится драйвер-фильтр, должно быть заранее известно, нет?(например, имя сервиса, hardware ID и т.п.). Очень детальную информацию о драйвере можно получить с помощью функции SetupDiGetDeviceRegistryProperty (см. п 2 в моем предыдущем сообщении). Поэтому, как я уже и писал там, можно автоматически находить SP_DEVINFO_DATA для нужного драйвера.
I>2. Мне, в принципе, не нужно устанавливать драйвер программно. Вполне достаточно ручной установки. Разобраться с inf-файлами с разбега тоже оказалось не так просто...
--
Проблема в том, что, насколько я знаю, нет "документированого" способа определить описание драйвера в ветке CurrentControlSet\ENUM\... в registry и добавить туда UpperFilter (или LowerFilter) и поэтому-то и приходится работать так.
Определить же "руками" это достаточно просто — проанализируй информацию из ветки ENUM для описания сервиса любого драйвера, там все достаточно прозрачно.
А какие проблемы с *.inf файлами?
I>3. С другой стороны, меня интересует установка драйвера вместе с инсталляцией программы. Как это обычно делается?
--
Правильно ли я понял, что при инсталяции программы устанавливаются все 2 драйвера? Или с этой программой должен быть установлен только драйвер-фильтр?
Здравствуйте, Геннадий Майко, Вы писали:
I>>1. У меня пока нет необходимости выбирать драйвер из списка, тем более давать юзеру такую возможность. ГМ>-- ГМ>Но что-то о том драйвере, "поверх" которого ставится драйвер-фильтр, должно быть заранее известно, нет?(например, имя сервиса, hardware ID и т.п.). Очень детальную информацию о драйвере можно получить с помощью функции SetupDiGetDeviceRegistryProperty (см. п 2 в моем предыдущем сообщении). Поэтому, как я уже и писал там, можно автоматически находить SP_DEVINFO_DATA для нужного драйвера.
Когда я говорил "поверх", я вообще-то имел в виду "вместо" , вместо своего же драйвера, который был установлен ранее. Установка "вместо" постоянно необходима в процессе разработки и отладки. Если же говорить о "поверх" в смысле "upper", то да, реальное устройство известно конечно же, драйвер для него в системе уже есть, и я не имею к нему никакого другого отношения.
I>>2. Мне, в принципе, не нужно устанавливать драйвер программно. Вполне достаточно ручной установки. Разобраться с inf-файлами с разбега тоже оказалось не так просто... ГМ>-- ГМ>Проблема в том, что, насколько я знаю, нет "документированого" способа определить описание драйвера в ветке CurrentControlSet\ENUM\... в registry и добавить туда UpperFilter (или LowerFilter) и поэтому-то и приходится работать так. ГМ>Определить же "руками" это достаточно просто — проанализируй информацию из ветки ENUM для описания сервиса любого драйвера, там все достаточно прозрачно.
Т.е. Вы предлагаете единожды написать утилитку, которая будет ставить драйвер программно, я правильно Вас понял?
ГМ>А какие проблемы с *.inf файлами?
Прочитал описание формата, посмотрел примеры из разных источников — они такие разные, что так и не понял какие секции мне нужны, а какие можно выбросить... К тому же вопрос — нужно ли мне действительно с ними разбираться, если я, скажем, буду при отладке устанавливать драйвер вручную (или программно с помощью утилитки), а в релизе включу драйвер в инсталлятор и он как-то по-другому (?) будет устанавливаться, без inf.
I>>3. С другой стороны, меня интересует установка драйвера вместе с инсталляцией программы. Как это обычно делается? ГМ>-- ГМ>Правильно ли я понял, что при инсталяции программы устанавливаются все 2 драйвера? Или с этой программой должен быть установлен только драйвер-фильтр?
Я извиняюсь за путаницу . Драйвер в окончательном варианте будет только один, WDM filter.
Здравствуйте, Геннадий Майко, Вы писали:
I>>Т.е. Вы предлагаете единожды написать утилитку, которая будет ставить драйвер программно, я правильно Вас понял? ГМ>-- ГМ>Ну, примерно так. Или написать отдельную утилиту, или просто встроить соответствующий код в основное приложение, работающее с фильтром. ГМ>И, кстати, можно сделать утилиту и для программного "снятия" драйвера-фильтра.
Уже пишу
Насколько я понял, функция SetupDiEnumDeviceInfo выдает только самые верхние устройства в стеке. Правильно? Вопрос: как мне идентифицировать "реальное устройство", upper которого я хочу установить свой фильтр? Например, это драйвер мыши. Я думаю, нужно по GUID, ведь он фиксированный? (у Oney почему-то по friendly name или description (filter.sys + filtject.dll) ).
ГМ>На мой взгляд, в Windows 2K/XP всегда лучше использовать *.inf файлы для установки драйверов. Информацию о структуре этих файлов можно найти в книге Walter Oney "Programming the Microsoft Windows Driver Model", 2nd edition, глава 15 "Distributing Device Drivers". Кстати, *.inf файл для драйвера-фильтра можно найти в примерах к главе 16 этой же книги (Powertrace).
Ок, почитаю еще. Дело в том, что я не собираюсь поставлять драйвер отдельно, а только как часть приложения. Поэтому, наверное, нужно будет включить в инсталлятор custom action, который будет устанавливать драйвер подобно этой утилите... Как в MSI можно по-другому драйвер и/или inf запихнуть, не представляю пока.
ГМ>1. Программа инсталяции обязательно должна зарегистрировать WDM драйвер фильтр в системе как сервис (п.1 моего первого сообщения). ГМ>2. Если драйвер-фильтр нужно сразу же запустить, то уже в программе инсталяции необходимо выполнить и остальные пункты 2-4. ГМ>3. Если драйвер-фильтр должен запускаться только при старте определенного приложения (на мой взляд, это логичнее), то эти пункты можно выполнить при старте этого приложения. Кстати, а при окончании этого приложения вполне можно драйвер-фильтр "снять" из системы. ГМ>4. При деинсталяции программы так же необходимо "снять" драйвер-фильтр из системы (как из строки UpperFilter фильтруемого драйвера, так и как сервис).
Означает ли это, что драйвер можно устанавливать/удалять при запуске/закрытии приложения? Я по наивности думал, что после инсталляции драйвера машину нужно перезапускать, и поэтому драйвер устанавливается единожды при инсталляции приложения и удаляется при деинсталляции... Или я путаю понятия "установить/удалить" и "запустить/остановить" драйвер? Не могли бы разъяснить плз?
Здравствуйте, Ignoramus, Вы писали:
I>Насколько я понял, функция SetupDiEnumDeviceInfo выдает только самые верхние устройства в стеке. Правильно?
--
Не знаю.
Она просто возвращает SP_DEVINFO_DATA одного из драйверов, попавших в device information set. Получить же этот device information set можно по разному.
Вопрос: как мне идентифицировать "реальное устройство", upper которого я хочу установить свой фильтр? Например, это драйвер мыши. Я думаю, нужно по GUID, ведь он фиксированный? (у Oney почему-то по friendly name или description (filter.sys + filtject.dll) ).
--
Можно, например, по GUID класса получить в device information set все драйверы, существующие в системе (с помощью функции SetupDiGetClassDevs). Затем для каждого драйвера из этого set'a получить, например, что-то, что уникально характеризует драйвер, и я думаю, Oney прав в своих рекомендациях.
Если имеется в виду GUID интерфейса, то в принципе нет взаимно-однозначного соответствия между device и интерфейсом, которые он (или они) может expose. Поэтому я бы не использовал интерфейс как признак выбора драйвера (посмотри картинку на страничке по ссылке вверху).
I>Означает ли это, что драйвер можно устанавливать/удалять при запуске/закрытии приложения?
--
Да. Я часто так делаю.
I> Я по наивности думал, что после инсталляции драйвера машину нужно перезапускать, и поэтому драйвер устанавливается единожды при инсталляции приложения и удаляется при деинсталляции... Или я путаю понятия "установить/удалить" и "запустить/остановить" драйвер? Не могли бы разъяснить плз?
--
Для PNP драйверов перезапускать машину обычно не нужно (исключения составляют boot-драйвера).
Попробую описать эти понятия, не претендуя на полноту изложения:
"установить" — install — это зарешистрировать и запустить драйвер в системе (т.е. будет вызвана его функция Driverentry), а затем AddDevice.
"удалить" — remove — де-инсталлировать устройство, будет вызвана его функция обработки IRP_MN_REMOVE_DEVICE и информация об устройстве исчезнет (как будто-бы из registry и машины.
"запустить" — start — это обработка IRP_MN_START_DEVICE.
"остановить" — stop — это обработка IRP_MN_STOP_DEVICE.
Все эти действия можно выполнить в своей программе.
Ну вот, начал писать утилиту для установки и появились более внятные вопросы .
1. С модификацией реестра с помощью функций SetupDiGetDeviceRegistryProperty уже понятно. Однако, если я правильно понял, изменить реестр – еще не значит запустить/остановить драйвер. Для этого нужно еще, как Вы писали, вызвать функции SetupDiSetClassInstallParams и SetupDiCallClassInstaller. Можете дать пример их использования? в MSDN не совсем понятно написано...
2. При чем здесь сервисы? Те ли это сервисы, которые отображаются в Computer Management->System Tools->Software Environment->Services? (я никаких сервисов драйверов там не обнаружил по крайней мере). К тому же на Win98 сервисов вообще нет, а WDM есть... Путаюсь я еще . Можете еще пару слов на эту тему?
3.
I>Означает ли это, что драйвер можно устанавливать/удалять при запуске/закрытии приложения?
--
Да. Я часто так делаю.
--
Это весьма заманчиво
Однако, возникает вопрос: нужны ли особые права для установки и запуска драйвера? Или только для установки? Как быть если юзер не админ, а хочет пользоваться программой + драйвером? Если я правильно понял, придется устанавливать драйвер перманентно, а при запуске программы только стартовать его. Так обычно решается эта проблема?
4. Если я все делаю "руками" с помощью SetupDi* функций, то нужны ли inf-файлы? Они ведь вроде то же самое делают...
5. "Если нужно "снять" драйвер-фильтр F, то каким-то образом запрещаю запуск WDM драйвера А (например, вытаскиваю плату или что-то похожее, вплоть до запуска Windows recovery console), а затем вновь его переустанавливаю."
Зачем так жестоко? А нельзя ли сделать удаление аналогично установке?
6. Обязательно ли копировать файл драйвера в Windows\System32?
7. Может ли юзер остановить/удалить драйвер в процессе его работы и что при этом произойдет?
Спасибо.
Надеюсь, я Вас еще не замучил
Re[9]: Как правильно устанавливать драйвер?
От:
Аноним
Дата:
21.11.03 17:04
Оценка:
Здравствуйте, Ignoramus, Вы писали:
I>1. С модификацией реестра с помощью функций SetupDiGetDeviceRegistryProperty уже понятно. Однако, если я правильно понял, изменить реестр – еще не значит запустить/остановить драйвер. Для этого нужно еще, как Вы писали, вызвать функции SetupDiSetClassInstallParams и SetupDiCallClassInstaller. Можете дать пример их использования? в MSDN не совсем понятно написано...
--
Мой код в офиссе, буду там только в воскресенье. Пример использования этих функций есть в исходных кодах к devcon из DDK (файл cmds.cpp, функция ControlCallback).
I>2. При чем здесь сервисы? Те ли это сервисы, которые отображаются в Computer Management->System Tools->Software Environment->Services? (я никаких сервисов драйверов там не обнаружил по крайней мере). К тому же на Win98 сервисов вообще нет, а WDM есть... Путаюсь я еще . Можете еще пару слов на эту тему?
--
Я имел ввиду, что под NT4/W2K/XP/NET инсталяции драйверов и сервисов в registry находятся в одном месте. Прошу прощения за некорректные термины
Откровенно говоря, я не очень хорошо знаю платформы Win9X/ME, не исключено, что все это там вообще работать не сможет...
I>3.
I>>Означает ли это, что драйвер можно устанавливать/удалять при запуске/закрытии приложения? I>-- I>Да. Я часто так делаю. I>-- I>Это весьма заманчиво I>Однако, возникает вопрос: нужны ли особые права для установки и запуска драйвера? Или только для установки? Как быть если юзер не админ, а хочет пользоваться программой + драйвером? Если я правильно понял, придется устанавливать драйвер перманентно, а при запуске программы только стартовать его. Так обычно решается эта проблема?
--
Да, это совершенно верно. User должен иметь соответствующие права для того, чтобы устанавливать и запускать драйвера. Если он таких прав не имеет, такой подход не приемлим.
В таком случае при инсталяции программы необходимо и установить, и, быть может, стартовать драйвер.
I>4. Если я все делаю "руками" с помощью SetupDi* функций, то нужны ли inf-файлы? Они ведь вроде то же самое делают...
--
Некоторые функции семейства Setup* работают с *.inf файлами. На мой взгляд, устанавливать драйвер все таки проще с помощью *.inf файла.
Как я уже упоминал, в таком подходе *.inf файл нужен только для регистрации драйвера-фильтра.
I>5. "Если нужно "снять" драйвер-фильтр F, то каким-то образом запрещаю запуск WDM драйвера А (например, вытаскиваю плату или что-то похожее, вплоть до запуска Windows recovery console), а затем вновь его переустанавливаю."
I>Зачем так жестоко? А нельзя ли сделать удаление аналогично установке?
--
Ну, был у меня однажды баг при удалении device-фильтра, так только таким "жестоким" способом удалось запретить запуск другого PNP-драйвера (этот драйвер был моего специального класса устройств, не связанных с hardware).
Да, конечно, стоило сделать утилиту удаления, просто тогда я запаниковал и воспользовался известным способом удаления драйвера.
I>6. Обязательно ли копировать файл драйвера в Windows\System32?
--
В принципе нет. Тогда нужно в *.inf файле в секции [AddService] прописать путь к драйверу в строке ServiceBinary=path-to-service.
Однако я так не делаю из-за возможных проблем с boot-драйверами, когда этот "путь" еще не существует во время загрузки.
I>7. Может ли юзер остановить/удалить драйвер в процессе его работы и что при этом произойдет?
--
Если имеет соответствующие права — то да, может попытаться.
Чтобы все работало нормально, я всегда пытаюсь корректно обрабатываю IRP_MN_QUERY_* сообщения и запрещаю отстановку или удаление device'a, если, согласно его внутреннему состоянию, этого делать нельзя (например, он занят чем-то полезным или у него есть необработанные запросы и т.п.).
I>Надеюсь, я Вас еще не замучил
--
Нет, у меня нет никаких проблем продолжать эти, как я считаю, полезные обсуждения.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Ignoramus, Вы писали:
I>>1. С модификацией реестра с помощью функций SetupDiGetDeviceRegistryProperty уже понятно. Однако, если я правильно понял, изменить реестр – еще не значит запустить/остановить драйвер. Для этого нужно еще, как Вы писали, вызвать функции SetupDiSetClassInstallParams и SetupDiCallClassInstaller. Можете дать пример их использования? в MSDN не совсем понятно написано... А>-- А>Мой код в офиссе, буду там только в воскресенье. Пример использования этих функций есть в исходных кодах к devcon из DDK (файл cmds.cpp, функция ControlCallback).
В моем DDK такого почему-то не обнаружилось...
I>>2. При чем здесь сервисы? Те ли это сервисы, которые отображаются в Computer Management->System Tools->Software Environment->Services? (я никаких сервисов драйверов там не обнаружил по крайней мере). К тому же на Win98 сервисов вообще нет, а WDM есть... Путаюсь я еще . Можете еще пару слов на эту тему? А>-- А>Я имел ввиду, что под NT4/W2K/XP/NET инсталяции драйверов и сервисов в registry находятся в одном месте. Прошу прощения за некорректные термины
Дело в том, что не только Вы используете термин "сервис" по отношению к драйверам. Я видел и в других постингах, у Oney, даже в реестре CurrentControlSet есть ключ "Services", там действительно есть и "сервисы драйверы" и "обычные сервисы". Я просто пытаюсь понять что это за "сервисы драйверов" и чем они отличаются от "обычных" сервисов NT.
А>Откровенно говоря, я не очень хорошо знаю платформы Win9X/ME, не исключено, что все это там вообще работать не сможет...
У Oney вся модель WDM рассматривается дуально: под Win2K и Win98, так что под последней должно работать, правда, с определенными отличиями и оговорками.
I>>Однако, возникает вопрос: нужны ли особые права для установки и запуска драйвера? Или только для установки? Как быть если юзер не админ, а хочет пользоваться программой + драйвером? Если я правильно понял, придется устанавливать драйвер перманентно, а при запуске программы только стартовать его. Так обычно решается эта проблема? А>-- А>Да, это совершенно верно. User должен иметь соответствующие права для того, чтобы устанавливать и запускать драйвера. Если он таких прав не имеет, такой подход не приемлим.
А>В таком случае при инсталяции программы необходимо и установить, и, быть может, стартовать драйвер.
Я бы все-таки предпочел его останавливать при закрытии приложения. Зачем лишнии ресурсы потреблять?
I>>4. Если я все делаю "руками" с помощью SetupDi* функций, то нужны ли inf-файлы? Они ведь вроде то же самое делают... А>-- А>Некоторые функции семейства Setup* работают с *.inf файлами. На мой взгляд, устанавливать драйвер все таки проще с помощью *.inf файла.
А>Как я уже упоминал, в таком подходе *.inf файл нужен только для регистрации драйвера-фильтра.
С этими inf-ами я определенно туплю . Что такое регистрация и чем она отличается от установки?
Здравствуйте, Ignoramus, Вы писали:
А>>... Пример использования этих функций есть в исходных кодах к devcon из DDK (файл cmds.cpp, функция ControlCallback). I>В моем DDK такого почему-то не обнаружилось...
---
Пример devcon должен быть в src\setup\devcon директории.
А>>-- А>>Я имел ввиду, что под NT4/W2K/XP/NET инсталяции драйверов и сервисов в registry находятся в одном месте. Прошу прощения за некорректные термины
I>Дело в том, что не только Вы используете термин "сервис" по отношению к драйверам. Я видел и в других постингах, у Oney, даже в реестре CurrentControlSet есть ключ "Services", там действительно есть и "сервисы драйверы" и "обычные сервисы". Я просто пытаюсь понять что это за "сервисы драйверов" и чем они отличаются от "обычных" сервисов NT.
--
"Сервисы драйверов" просто означает, что информация для запуска драйверов в registry находятся там же (CurrentControlSet->services), где и для запуска "обычных сервисов".
А>>Некоторые функции семейства Setup* работают с *.inf файлами. На мой взгляд, устанавливать драйвер все таки проще с помощью *.inf файла.
А>>Как я уже упоминал, в таком подходе *.inf файл нужен только для регистрации драйвера-фильтра.
I>С этими inf-ами я определенно туплю . Что такое регистрация и чем она отличается от установки?
--
Под термином "регистрация с помощью *.inf файла" я имел в виду только запись необходимой информации в registry и копирование файлов, запуск драйвера в этом случае не происходит. Это нужно для драйвера фильтра, так как он должен запускаться при запуске другого драйвера, а не по желанию пользователя.
С помощью (других) *.inf файлов для "установки" "обычных" PNP WDM драйверов можно не только регистрировать и копировать файлы драйвера, но и немедленно запускать его на выполнение.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Ignoramus, Вы писали:
I>>1. С модификацией реестра с помощью функций SetupDiGetDeviceRegistryProperty уже понятно. Однако, если я правильно понял, изменить реестр – еще не значит запустить/остановить драйвер. Для этого нужно еще, как Вы писали, вызвать функции SetupDiSetClassInstallParams и SetupDiCallClassInstaller. Можете дать пример их использования? в MSDN не совсем понятно написано... А>-- А>Мой код в офиссе, буду там только в воскресенье. Пример использования этих функций есть в исходных кодах к devcon из DDK (файл cmds.cpp, функция ControlCallback).
Не хочу показаться нескромным, , но очень хочется получить обещанный код . Застрял именно на этом...
Потому что в MSDN все равно непонятно . Мое наблюдение — весь DDK нацелен на драйверы реальных устройств, которые автоматически обнаруживаются PNP и дальше сами устанавливаются. Случай filter-драйверов видимо показался авторам DDK не практичным...
Здравствуйте, Ignoramus, Вы писали:
I>Не хочу показаться нескромным, :shuffle: , но очень хочется получить обещанный код :). Застрял именно на этом...
--
Вот обещанный код — метод класса, который перезапускает выбранный драйвер:
Функция GetHandle() возвращает HDEVINFO, полученный ранее, например, с помощью функции SetupDiGetClassDevs(); DevInfo — структура SP_DEVINFO_DATA, полученная с помощью функции SetupDiEnumDeviceInfo() для выбранного драйвера.
Функция использует только текущий hardware profile.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Вот обещанный код — метод класса, который перезапускает выбранный драйвер:
Спасибо! . А этот код нужно применять к моему драйверу или к тому, по отношению к которому мой драйвер "upper"?
ГМ>Функция использует только текущий hardware profile.
Здравствуйте, Ignoramus, Вы писали:
I>Спасибо! :). А этот код нужно применять к моему драйверу или к тому, по отношению к которому мой драйвер "upper"?
--
Этот код применяется для драйвера, "поверх" которого будет ставиться драйвер-фильтр. Так как до этого в registry для этого драйвера была изменена строка UpperFilter, то при его рестарте автоматически загрузится драйвер фильтр.
ГМ>>Функция использует только текущий hardware profile.
I>Ой... а что это значит/чем это чревато?
--
Вообще-то ничем, это просто означает, что изменения будут применяться к текущей конфигурации hardware.
Список hardware profile можно найти в System Properties диалоге (Start button->Settings->Control Panel->System), страница Hardware, Hardware Profiles. Обычно это используется для компьютеров, которые могут работать с различной hardware конфигурациями (например, laptop может работать автономно или в составе docking station и, соответственно, иметь разный набор перефирийных устройств).
Решил начать новую ветку, чтобы удобнее читать было .
Хотел Вас еще попросить скинуть мне все-таки исходники devcon, пригодится, я думаю. В DDK так и не нашел — то ли у меня DDK старый то ли я совсем туплю . В сети тоже нет исходников, только написано что входит в DDK.
Адрес:
krupnov(ухо)pworlds.com
Спасибо.
По поводу hardware конфигураций: наверное мне нужно, чтобы мой драйвер работал во всех конфигурациях. Какие могут быть проблемы с этим связанные?
Здравствуйте, Ignoramus, Вы писали:
I>Вопрос: нужно ли мне вызывать SetupDiCreateDeviceInfo и SetupDiRegisterDeviceInfo если это filter-driver? I>Если нужно, то какие параметры функции указывать?
--
Все, что нужно сделать для драйвера-фильтра — это зарегистрировать для него "сервис" в registry, в ветке currentcontrolset, и скопировать файл в нужное место. Это можно сделать многими способами, хоть "руками" прописать в registry нужные значения. Я это обычно делаю с помощью простого *.inf файла — или вручную, или с помощью функции InstallHinfSection.
Вот пример *.inf файла для одного моего драйвера-фильтра:
; Copyright...
;
; SpyFiltr.inf
; Inf file of the WDM Filter driver for Windows 2000 for the DVB "Spy" Board
;
[Version]
Signature=$CHICAGO$
Provider=%BRCM%
DriverVer= 11/12/2003, 1.0.0.0
;
; Files will be installed into the standard driver directory
;
[DestinationDirs]
DefaultDestDir = 12
;
; Name of the installations for the Ix86 CPU
;
[SourceDisksNames.x86]
0=%Desc_x860%
;
; Directory of the installation disk where files are located
;
[SourceDisksFiles.x86]
SpyFiltr.sys=0,bin\i386,
[SourceDisksFiles.ia64]
;------------------------------------------------------------------------------
; Windows 2000 Sections
;------------------------------------------------------------------------------
[DefaultInstall.ntx86]
CopyFiles=DriverCopyFiles
[DriverCopyFiles]
;SpyFiltr.sys,,,0x60 ; replace newer, suppress dialog
SpyFiltr.sys
[DefaultInstall.ntx86.services]
AddService=SpyFiltr,,SpyFiltrService
[SpyFiltrService]
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_IGNORE%
DisplayName = %SpyFiltrDesc_x860%
ServiceBinary = %12%\SpyFiltr.sys
AddReg = SpyFiltrService.AddReg
;
; Additional registry entries for the parameters
;
[SpyFiltrService.AddReg]
HKR,%PARAMS_A%,%DEBUG_VIEW_STR_A%,%REG_DWORD%,%BRCM_DEBUG_SHOW_ALL%
[Strings]
; *******Localizable Strings*******
Brcm= "Broadcom"
Desc_x860= "Dvb Spy Board WDM Drivers for Windows 2000"
SpyFiltrDesc_x860= "Filter WDM Driver for Windows 2000, used by Dvb Spy Board WDM Driver"
PARAMS_A= "Parameters"
DEBUG_VIEW_STR_A= "DebugView"
BRCM_DEBUG_SHOW_ALL = 0x2
BRCM_DEBUG_SHOW_ERRORS = 0x1
BRCM_DEBUG_SHOW_NOTHING = 0x0
; *******Non Localizable Strings*******
SERVICE_BOOT_START = 0x0
SERVICE_SYSTEM_START = 0x1
SERVICE_AUTO_START = 0x2
SERVICE_DEMAND_START = 0x3
SERVICE_DISABLED = 0x4
SERVICE_KERNEL_DRIVER = 0x1
SERVICE_ERROR_IGNORE = 0x0
SERVICE_ERROR_NORMAL = 0x1
SERVICE_ERROR_SEVERE = 0x2
SERVICE_ERROR_CRITICAL = 0x3
REG_DWORD = 0x00010001
Здравствуйте, Ignoramus, Вы писали:
I>И вообще: есть ли возможность установить и запустить драйвер ПОЛНОСТЬЮ программно, без использования inf-файлов? Если можно, то как? I>Все материалы, которые я до сих пор читал, ссылаются на inf-файлы... Мне это не нравится. :crash: В моем случае inf — это имхо "лишняя сущность".
--
Если это не PNP драйвер, то, скорее всего, это можно сделать.
Если это PNP драйвер, то, по моему, без *.inf файла не обойтись. Эти файлы дают PNP manager'у информацию о всех устройствах, которые система может автоматически распознать и установить для них корректный драйвер. У manager'a просто нет другой возможности получить информацию о том, какой драйвер соответствует вновь появившемуся PNP устройству.
Попробуйте разрешить Setup Logging на своем компьютере, вставить какое-то PNP устройство (PCI плату или USB device) и просмотреть в громадном setupapi.log файле, как PNP manager просматривает все *.inf и *.pnf файлы в системе и выбирает нужный.
I>Эх, увидеть бы готовый примерчик кода который регистрирует и запускает фильтр-драйверы! :shuffle:
--
Он есть в devcon.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Если это не PNP драйвер, то, скорее всего, это можно сделать. ГМ>Если это PNP драйвер, то, по моему, без *.inf файла не обойтись. Эти файлы дают PNP manager'у информацию о всех устройствах, которые система может автоматически распознать и установить для них корректный драйвер. У manager'a просто нет другой возможности получить информацию о том, какой драйвер соответствует вновь появившемуся PNP устройству. ГМ>Попробуйте разрешить Setup Logging на своем компьютере, вставить какое-то PNP устройство (PCI плату или USB device) и просмотреть в громадном setupapi.log файле, как PNP manager просматривает все *.inf и *.pnf файлы в системе и выбирает нужный.
У меня filter-driver, который не PNP в том смысле, что его никто не должен обнаруживать. Я сам его устанавливаю когда хочу и удаляю когда хочу, он никак на работу железа влиять не должен. Но это WDM драйвер. Так что я не знаю какой правильный ответ — PNP or not PNP.
Уточню еще раз: есть filter-драйвер мышки (class-driver, т.е. фильтровать хочу все мышки, а не только PS/2). Драйвер не поставляется отдельно, а в составе user-mode программы (поэтому имхо inf не нужен). Это задумывалось вроде kernel-mode хука на сообщения мышки, который должен работать только пока активно приложение.
Не понимаю — почему в DDK не описан такой простейший случай?..
Здравствуйте, Ignoramus, Вы писали:
I>У меня filter-driver, который не PNP в том смысле, что его никто не должен обнаруживать. Я сам его устанавливаю когда хочу и удаляю когда хочу, он никак на работу железа влиять не должен. Но это WDM драйвер. Так что я не знаю какой правильный ответ — PNP or not PNP.
I>Уточню еще раз: есть filter-драйвер мышки (class-driver, т.е. фильтровать хочу все мышки, а не только PS/2). Драйвер не поставляется отдельно, а в составе user-mode программы (поэтому имхо inf не нужен). Это задумывалось вроде kernel-mode хука на сообщения мышки, который должен работать только пока активно приложение.
--
Попробую еще раз пройти по этапам установки этого драйвера, как я бы это делал.
1. Зарегистрировал бы "сервис" для этого драйвера-фильтра и скопировал его бинарный файл в нужное место. (В паралельном моем сообщении есть пример *.inf файла для этого).
2. Нашел бы SP_DEVINFO_DATA драйвера(ов), к которым я бы хотел подключить мой драйвер-фильтр.
3. Для всех таких драйверов дописал бы имя "сервиса", соответствующего моему драйверу-фильтру, в их UpperFilter строку в registry.
4. Все такие драйвера перезапустил бы их.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Попробую еще раз пройти по этапам установки этого драйвера, как я бы это делал. ГМ>1. Зарегистрировал бы "сервис" для этого драйвера-фильтра и скопировал его бинарный файл в нужное место. (В паралельном моем сообщении есть пример *.inf файла для этого). ГМ>2. Нашел бы SP_DEVINFO_DATA драйвера(ов), к которым я бы хотел подключить мой драйвер-фильтр. ГМ>3. Для всех таких драйверов дописал бы имя "сервиса", соответствующего моему драйверу-фильтру, в их UpperFilter строку в registry. ГМ>4. Все такие драйвера перезапустил бы их.
Что я сделал:
1) Скопировал файл моего драйвера в System32\drivers
2) Вызвал функцию CreateService, указав SERVICE_KERNEL_DRIVER. В реестре CurrentControlSet\Services\ появился очень симпатичный ключ. Наверное, это то что нужно.
3) Вызвал StartService. Сервис не запустился с сообщением "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it."
4) Поскольку сервис не disabled, то решил устранить причину №2. Пробовал 2 варианта:
5) В реестре CurrentControlSet\Control\Classes\{4d36e96f-e325-11ce-bfc1-08002be10318} (класс устройств "Mouse") прописал UpperFilters. Этим я хотел сказать, что устанавливаю драйвер класса, а не конкретного устройства (кстати, вот еще интересно, если мышь USB, она по-прежнему входит в этот класс?) Не помогло , сервис все равно не запустился.
6) Вызвал SetupDiEnumDeviceInfo и потом SetupDiSetDeviceRegistryProperty для SPDRP_UPPERFILTERS. В реестре CurrentControlSet\Enum\PNP0F13\4&f29db88&0 (там где конкретное устройство "PS/2 Compatible Mouse", Service = i8042prt) появилась строка UpperFilters.
7) Пробовал StartService — не запускается с тем же сообщением
8) Пробовал SetupDiSetClassInstallParams и затем SetupDiCallClassInstaller. Компьютер подумал немного и сказал, что функции выполнены успешно. Но мой фильтр-драйвер не запустился
9) Опять пробовал StartService — не запускается с тем же сообщением
Что я делаю не так? Может, перезагрузиться надо?
P.S. Какова, кстати, роль драйвера mouclass во всем этом?
Здравствуйте, Ignoramus, Вы писали:
I>Что я сделал:
I>1) Скопировал файл моего драйвера в System32\drivers
--
Правильно, если имеется ввиду драйвер-фильтр.
I>2) Вызвал функцию CreateService, указав SERVICE_KERNEL_DRIVER. В реестре CurrentControlSet\Services\ появился очень симпатичный ключ. Наверное, это то что нужно.
--
Допустимо. Интересно, правда посмотреть все появившиеся строчки (ServiceType, StartType, ErrorControl, DisplayName, ServiceBinary, ??? )
I>3) Вызвал StartService. Сервис не запустился :( с сообщением "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it."
--
Не надо этого делать!
Этот "сервис" (т.е. драйвер-фильтр) должен запусаться автоматически, когда будет загружаться или перезагружаться тот драйвер мыши, для которого будет установлен драйвер-фильтр.
I>4) Поскольку сервис не disabled, то решил устранить причину №2. Пробовал 2 варианта: I>5) В реестре CurrentControlSet\Control\Classes\{4d36e96f-e325-11ce-bfc1-08002be10318} (класс устройств "Mouse") прописал UpperFilters. Этим я хотел сказать, что устанавливаю драйвер класса, а не конкретного устройства (кстати, вот еще интересно, если мышь USB, она по-прежнему входит в этот класс?) Не помогло :(, сервис все равно не запустился.
--
В принципе, это можно сделать так (для отладки).
Но "сервис" драйвера-фильтра опять не надо запускать!
I>6) Вызвал SetupDiEnumDeviceInfo и потом SetupDiSetDeviceRegistryProperty для SPDRP_UPPERFILTERS. В реестре CurrentControlSet\Enum\PNP0F13\4&f29db88&0 (там где конкретное устройство "PS/2 Compatible Mouse", Service = i8042prt) появилась строка UpperFilters.
--
Правильно. Это тот способ, который я предлагал делать.
I>7) Пробовал StartService — не запускается с тем же сообщением :xz:
--
Не надо этого делать (см. комментарии к п.3 выше).
I>8) Пробовал SetupDiSetClassInstallParams и затем SetupDiCallClassInstaller. Компьютер подумал немного и сказал, что функции выполнены успешно. Но мой фильтр-драйвер не запустился :(
--
Как проверялось то, что драйвер-фильтр не запустился?
I>9) Опять пробовал StartService — не запускается с тем же сообщением :xz:
--
Не надо этого делать (см. комментарии к п.3 выше).
I>Что я делаю не так? Может, перезагрузиться надо?
--
А вот это не исключено. Я не знаю, можно ли перезагружать драйвер мыши без перезагрузки компьютера. Вот что написано в комментариях к функции SetupDiCallClassInstaller:
After SetupDiCallClassInstaller returns, the setup application that called it should call SetupDiGetDeviceInstallParams, check the flags, and request a reboot if necessary.
Соответствующий пример есть в devcon (файл cmds.cpp, функция ControlCallback).
I>P.S. Какова, кстати, роль драйвера mouclass во всем этом?
--
У него нужно прописать в registry строку UpperFilter и перезагрузить.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Здравствуйте, Ignoramus, Вы писали:
I>>Что я сделал:
I>>1) Скопировал файл моего драйвера в System32\drivers ГМ>-- ГМ>Правильно, если имеется ввиду драйвер-фильтр.
Непонятно почему правильно именно если драйвер-фильтр...
I>>2) Вызвал функцию CreateService, указав SERVICE_KERNEL_DRIVER. В реестре CurrentControlSet\Services\ появился очень симпатичный ключ. Наверное, это то что нужно. ГМ>-- ГМ>Допустимо. Интересно, правда посмотреть все появившиеся строчки (ServiceType, StartType, ErrorControl, DisplayName, ServiceBinary, ??? )
Из перечисленных Вами нет ServiceBinary, зато появились подключи Enum и Security, и там еще какие-то строчки.
I>>3) Вызвал StartService. Сервис не запустился с сообщением "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it." ГМ>-- ГМ>Не надо этого делать! ГМ>Этот "сервис" (т.е. драйвер-фильтр) должен запусаться автоматически, когда будет загружаться или перезагружаться тот драйвер мыши, для которого будет установлен драйвер-фильтр.
Ок, больше не буду А почему кстати так нельзя? Это же сервис вроде тоже...
I>>4) Поскольку сервис не disabled, то решил устранить причину №2. Пробовал 2 варианта: I>>5) В реестре CurrentControlSet\Control\Classes\{4d36e96f-e325-11ce-bfc1-08002be10318} (класс устройств "Mouse") прописал UpperFilters. Этим я хотел сказать, что устанавливаю драйвер класса, а не конкретного устройства (кстати, вот еще интересно, если мышь USB, она по-прежнему входит в этот класс?) Не помогло , сервис все равно не запустился. ГМ>-- ГМ>В принципе, это можно сделать так (для отладки).
А как это можно использовать для отладки?
Меня терзают подозрения, что если я сделаю не так, а как описано ниже, то драйвер будет фильтровать только одну мышь, а я хочу все устройства класса (включая USB-мышей ) Есть же различие между драйвером устройства и драйвером класса?
I>>6) Вызвал SetupDiEnumDeviceInfo и потом SetupDiSetDeviceRegistryProperty для SPDRP_UPPERFILTERS. В реестре CurrentControlSet\Enum\PNP0F13\4&f29db88&0 (там где конкретное устройство "PS/2 Compatible Mouse", Service = i8042prt) появилась строка UpperFilters. ГМ>-- ГМ>Правильно. Это тот способ, который я предлагал делать.
Но не помогло .
I>>8) Пробовал SetupDiSetClassInstallParams и затем SetupDiCallClassInstaller. Компьютер подумал немного и сказал, что функции выполнены успешно. Но мой фильтр-драйвер не запустился ГМ>-- ГМ>Как проверялось то, что драйвер-фильтр не запустился?
В своем фильтре я выбрасываю в Debug отладочные строчки на каждое событие мыши. Последних не наблюдается (хотя раньше, когда я ставил свой драйвер вручную через панель управления, все работало).
ГМ>-- ГМ>А вот это не исключено. Я не знаю, можно ли перезагружать драйвер мыши без перезагрузки компьютера. Вот что написано в комментариях к функции SetupDiCallClassInstaller: ГМ>
ГМ>After SetupDiCallClassInstaller returns, the setup application that called it should call SetupDiGetDeviceInstallParams, check the flags, and request a reboot if necessary.
Т.е. я проверяю какой-то флаг и сам должен перезагружаться? Вот будет облом если для запуска/остановки драйвера нужно каждый раз перезагружаться...
I>>P.S. Какова, кстати, роль драйвера mouclass во всем этом? ГМ>-- ГМ>У него нужно прописать в registry строку UpperFilter и перезагрузить.
Здравствуйте, Ignoramus, Вы писали:
I>>>Что я сделал:
I>>>1) Скопировал файл моего драйвера в System32\drivers ГМ>>-- ГМ>>Правильно, если имеется ввиду драйвер-фильтр.
I>Непонятно почему правильно именно если драйвер-фильтр... :)
--
Да, здесь я погорячился... Просто правильно :)
I>>>3) Вызвал StartService. Сервис не запустился :( с сообщением "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it." ГМ>>-- ГМ>>Не надо этого делать! ГМ>>Этот "сервис" (т.е. драйвер-фильтр) должен запусаться автоматически, когда будет загружаться или перезагружаться тот драйвер мыши, для которого будет установлен драйвер-фильтр.
I>Ок, больше не буду :) А почему кстати так нельзя? Это же сервис вроде тоже...
--
:)
Ну а зачем запускать драйвер-фильтр просто так? Какой от него будет толк?
I>>>4) Поскольку сервис не disabled, то решил устранить причину №2. Пробовал 2 варианта: I>>>5) В реестре CurrentControlSet\Control\Classes\{4d36e96f-e325-11ce-bfc1-08002be10318} (класс устройств "Mouse") прописал UpperFilters. Этим я хотел сказать, что устанавливаю драйвер класса, а не конкретного устройства (кстати, вот еще интересно, если мышь USB, она по-прежнему входит в этот класс?) Не помогло :(, сервис все равно не запустился. ГМ>>-- ГМ>>В принципе, это можно сделать так (для отладки).
I>А как это можно использовать для отладки?
--
Я имел ввиду, что "для отладки прописать UpperFilters" и, как я понял, сделано это было "руками". Потом это лучше сделать в программе.
I>Меня терзают подозрения, что если я сделаю не так, а как описано ниже, то драйвер будет фильтровать только одну мышь, а я хочу все устройства класса (включая USB-мышей :) ) Есть же различие между драйвером устройства и драйвером класса?
--
Да, Вы правы, стоит прописать UpperFilters для класса устройств. Кстати, весь этот процесс описан здесь, и, похоже, Вы все делаете корректно.
ГМ>>-- ГМ>>А вот это не исключено. Я не знаю, можно ли перезагружать драйвер мыши без перезагрузки компьютера. Вот что написано в комментариях к функции SetupDiCallClassInstaller: ГМ>>
ГМ>>After SetupDiCallClassInstaller returns, the setup application that called it should call SetupDiGetDeviceInstallParams, check the flags, and request a reboot if necessary.
I>Т.е. я проверяю какой-то флаг и сам должен перезагружаться? Вот будет облом если для запуска/остановки драйвера нужно каждый раз перезагружаться... :(
--
Да, это так. После перезагрузки драйвера, необходимо вызвать функцию SetupDiGetDeviceInstallParams() и проверить возвращаемое значение (пример есть в devcon). Если нужно, лучше, наверное, попросить пользователя перезагрузится.
Так как Вы собираетесь ставить драйвер-фильтр для класса устройств (а не для конкретного устройства), то надо из своей программы перезапустить все драйвера, относящиеся к этому классу. Или сразу перезагрузится, при этом драйвер-фильтр или будет установлен, или Вы останетесь без мыши в этом сеансе работы :)
I>>>P.S. Какова, кстати, роль драйвера mouclass во всем этом? ГМ>>-- ГМ>>У него нужно прописать в registry строку UpperFilter и перезагрузить.
I>Как это соотносится с п. 8 ?
--
Прошу прощения, я не обратил внимание на mouclass :( Вычеркните мой ответ предыдуший ответ.
I>Сорри, что пропал — пришлось немного приостановить работы по фильтру. Пока не могу сказать, что все получилось.
Аналогично.
Пытался отменить динамичискую загрузку,остановившись на одноразовой перезагрузке и затем,при необходимсти, связываясь с драйвером (пользуясь исходниками ctrl2cap). Сначала все было отменно,но внезапно драйвер стал отрубать мышь при загрузке системы.
Причем даже установка вместо моего драйвера драйвера из ДДК не помогло. Чистка реестра тоже ничего не дала.
Сейчас ищу шамана — одолжить бубен 8)
I>Давайте сотрудничать и обмениваться опытом
Давайте...
I>Мое мыло и аська также в Вашем распоряжении.
Это как? 8)
При клике на ваш ник сайт ничего не показывает
Здравствуйте, SomeOne_TT, Вы писали:
SO_>Аналогично. SO_>Пытался отменить динамичискую загрузку,остановившись на одноразовой перезагрузке и затем,при необходимсти, связываясь с драйвером (пользуясь исходниками ctrl2cap). Сначала все было отменно,но внезапно драйвер стал отрубать мышь при загрузке системы.
Так Вам удалось установить/запустить драйвер программно? Можно подробнее?
Я также использовал исходники ctrl2cap, filter из Walter Oney (2nd Ed.), а также moufiltr из DDK На этапе создания самого драйвера было все равно как его устанавливать, и я устанавливал вручную — использовал либо inf, либо вообще через Control Panel. А теперь вот захотелось культурно устанавливать, программно... Но это оказалось не так просто
SO_>Причем даже установка вместо моего драйвера драйвера из ДДК не помогло. Чистка реестра тоже ничего не дала. SO_>Сейчас ищу шамана — одолжить бубен 8)
У меня кажется тоже было нечто подобное... Через Control Panel не пробовали переустановить прежний драйвер?
SO_>Это как? 8) SO_>При клике на ваш ник сайт ничего не показывает
Помните, Вы говорили, что запускать драйвер функцией StartService категорически не следует?
Как Вы тогда прокомментируете цитату из описания этой функции (MSDN):
[msdn]
When a driver service is started, the StartService function does not return until the device driver has finished initializing.
[/msdn]
Кроме того, в том же MSDN я нашел целую статью про то, как запускать драйверы динамичиески с помощью SCM API. Статья из раздела Periodicals March 1998, "Pop Open a Privileged Set of APIs with Windows NT Kernel Mode Drivers", параграф "Loading a Device Driver", там даже исходники есть как это делается (которые впрочем не работают — возвращается сообщение 0x0422 "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it."
BOOL InstallAndStartDriver(SC_HANDLE hSCManager, LPCTSTR DriverName,
LPCTSTR ServiceExe)
{
SC_HANDLE hService;
BOOL bReturn;
// Create the driver entry in the SC Manager.
hService = CreateService (hSCManager, DriverName, DriverName, SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,ServiceExe,NULL,NULL,NULL,NULL,NULL);
// This may fail because the service entry already exists. However,
// we've tried to load it earlier, so something clearly is wrong if
// we can't create it!
if(!hService)
return FALSE;
// Start the driver!
bReturn = StartService(hService, 0, NULL);
// Dispose of the handle...
CloseServiceHandle(hService);
// Return whatever the driver start returned...
return bReturn;
}
Здравствуйте, Ignoramus, Вы писали:
I>Помните, Вы говорили, что запускать драйвер функцией StartService категорически не следует?
--
Если я не ошибаюсь, речь шла о сервисе для PNP драйвера-фильтра.
В этом случае предлагалось только зарегистрировать сервис в registry (и еще найти "фильтруемый" PNP-драйвкр и для него него прописать UpperFilter). Сам драйвер-фильтр предлагалось не запускать, так как при перезагрузке "фильтруемого" драйвера он был бы запущен автоматически PNP-manager'ом.
I>Как Вы тогда прокомментируете цитату из описания этой функции (MSDN): I>[msdn] I>When a driver service is started, the StartService function does not return until the device driver has finished initializing. I>[/msdn]
--
Здесь все верно — при вызове этой функции будет вызвана функция DriverEntry соответствующего драйвера.
I>Кроме того, в том же MSDN я нашел целую статью про то, как запускать драйверы динамичиески с помощью SCM API. Статья из раздела Periodicals March 1998, "Pop Open a Privileged Set of APIs with Windows NT Kernel Mode Drivers", параграф "Loading a Device Driver", там даже исходники есть как это делается (которые впрочем не работают — возвращается сообщение 0x0422 "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it."
--
Да, я знаком с этим кодом и пользуюсь им тогда, когда мне нужно инсталировать или запустить Legacy NT 4.0 драйвер. Как отмечено выше, это приводит к вызову функции DriverEntry. Так как для PNP-драйверов этого не достаточно (kernel mode device object создается при вызове функции AddDevice, инициализируется при обработке IRP_MN_START и т.д.), то запускать PNP-драйвера таким способом не стоит. Legacy NT 4.0 всю инициализацию делают самостоятельно как раз в DriverEntry, поэтому такой способ для них подходит.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Если я не ошибаюсь, речь шла о сервисе для PNP драйвера-фильтра. ГМ>В этом случае предлагалось только зарегистрировать сервис в registry (и еще найти "фильтруемый" PNP-драйвкр и для него него прописать UpperFilter). Сам драйвер-фильтр предлагалось не запускать, так как при перезагрузке "фильтруемого" драйвера он был бы запущен автоматически PNP-manager'ом.
ГМ>Да, я знаком с этим кодом и пользуюсь им тогда, когда мне нужно инсталировать или запустить Legacy NT 4.0 драйвер. Как отмечено выше, это приводит к вызову функции DriverEntry. Так как для PNP-драйверов этого не достаточно (kernel mode device object создается при вызове функции AddDevice, инициализируется при обработке IRP_MN_START и т.д.), то запускать PNP-драйвера таким способом не стоит. Legacy NT 4.0 всю инициализацию делают самостоятельно как раз в DriverEntry, поэтому такой способ для них подходит.
Спасибо, буду дальше изучать матчасть . "Успехи" уже есть — винду уже переставлял
P.S.
Правильно ли я понимаю Вашу терминологию — все драйверы Вы делите на Legacy и PNP? Я больше склонен делить их на Legacy и WDM, термин PNP меня несколько сбивает с толку, особенно для filter-драйвера, т.к. такой драйвер по сути представляет собой нечто искусственное, внедряемое в стек "насильно", а PNP предполагает, что система сама ищет драйвер для обнаруженного устройства.
Здравствуйте, Геннадий Майко, Вы писали:
ГМ>Здравствуйте, Ignoramus, Вы писали:
I>>Спасибо, буду дальше изучать матчасть . "Успехи" уже есть — винду уже переставлял ГМ>-- ГМ>Если есть необходимость — могу послать несколько классов для перечисления и инсталяции драйверов и пример их использования для установки драйвера ильтра. Но они относятся только к установке драйвера-фильтра для одного устройства, а не для класса устройств.
Думаю, это было бы полезно Мой адрес: krupnov (собачка) pworlds.com
Спасибо.
Чтобы установить фильтр-драйвер, действовать нужно так:
1) Перечислить все устройства функциями SetupDi*, найти то, у которого нужный Class GUID и прописать ему свойство UpperFilters.
2) Создать сервис для фильтра функцией CreateService.
3) Дальше возможны варианты. Если устройство, на которое устанавливается фильтр, позволяет перезапускать себя без перезагрузки, можно попробовать перезапустить драйвер функциями SetupDi*, как описывал Геннадий. В моем случае это не срабатывает — функция перезапуска драйвера по возвращении указывает на необходимость перезагрузки системы, а до тех пор ничего не происходит. Поэтому можно не пытаться перезапустить драйвер, а сразу перезагрузить машину.
Опыт 1. Параметр UpperFilters в реестре CurrentControlSet\Control\Class\{...}\ непонятно для чего нужен. Я не обнаружил никакого эффекта от его наличия/отсутствия. Реально влияет только UpperFilters в CurrentControlSet\Enum\..., т.е. там где реальные устройства описаны. Менять эти ключи в реестре можно только функциями SetupDi*, regedit матерится .
Опыт 2. Запускать функцией StartService можно только драйверы, которые ни к какому устройству не привязаны (т.е. которые служат просто программой, выполняемой в kernel mode). Фильтры в эту категорию не входят. Попытка запуска фильтра StartService выдает сообщение ERROR_SERVICE_DISABLED "The service cannot be started, either because it is disabled, or because it has no enabled devices associated with it."
Опыт 3. Аналогично, после перезагрузки системы, когда фильтр уже запущен, StopService не работает с сообщением что эта операция сервисом не поддерживается. Судя по всему, придется смириться с тем, что некоторые устройства, к которым подключается фильтр, не позволяют менять свои параметры и состояние без перезагрузки. Таким образом, "динамический" запуск фильтра превращается к сожалению в "статический". Хотя может это и к лучшему — меньше непредвиденных ситуаций в рантайме произойти может. А при правильной конструкции фильтра, он потреблять ресурсы не должен когда не используется...
Опыт 4. Фильтр, подключаемый к драйверу устройства, наследует права доступа последнего. Т.е. если получить хендл устройства через CreateFile было нельзя по причине access denied, то и для подключенного к нему фильтра будет access denied. Это в принципе соответствует концепции безопасности Windows, но затрудняет работу с фильтром — нельзя использовать DeviceIoControl.
Остался еще один вопрос: Если я удаляю фильтр, то мне нужно сбросить соответствующую запись UpperFilters. Функции SetupDi* позволяют сделать эту запись пустой, но не удалить ее полностью. Однако, в случае пустой строки UpperFilters, драйвер устройства не грузится, сообщение что-то вроде — невозможно запустить устройство, т.к. не все драйверы удалось загрузить. Что делать?
2 Геннадий, был бы признателен если бы Вы также прокомментировали мои опыты и выводы .
Здравствуйте, Геннадий Майко, Вы писали:
I>>Остался еще один вопрос: Если я удаляю фильтр, то мне нужно сбросить соответствующую запись UpperFilters. Функции SetupDi* позволяют сделать эту запись пустой, но не удалить ее полностью. Однако, в случае пустой строки UpperFilters, драйвер устройства не грузится, сообщение что-то вроде — невозможно запустить устройство, т.к. не все драйверы удалось загрузить. Что делать? ГМ>-- ГМ>Что такое "пустая строка"?
ГМ>Из описания функции SetupDiSetDeviceRegistryProperty: ГМ>
ГМ>PropertyBuffer
ГМ>The address of a buffer that contains the new data for the property. If the property is being cleared, then this pointer should be NULL and PropertyBufferSize must be zero.
ГМ>Вы делаете также?
Как-то я на это не обратил внимания
Под пустой мульти-строкой я понимал два terminating NULL подряд. А ведь реально, можно передавать указатель NULL вместо буфера. Вопрос снимается.