Привет всем. Жизнь заставляет писАть драйвер ком-порта, при этом возникает необходимость общения с user-mode приложением (для управления поведением драйвера, вызовом некоторых функций и т.п.).
Очевидно, для общения с драйвером посредством отложенного DeviceIoControl необходимо получить хандл драйвера. Также очевидно, что напрямую сделать ЭТО в случае с ком портом не представляется возможным, т.к. такой хандл должно мочь создать приложение пользователя. Очевидно, есть 2 решения.
1. Писать filter драйвер. Ну, или совмещать его функциональность в основном.
2. Использовать неизвестные мне недокументированные возможности и создавать таки хандл (точнее, его копию) из юзер моде.
Интересует следующее.
а) Возможно ли совместить функционал 2-х типов драйверов в одном, т.е. сначала сделать IoCreateDevice и IoAttachDeviceToDeviceStack для собственно драйвера последовательного порта, а потом сделать в нем же так называемый вторичный девайс, спеиально для общения с нашим управляющим user-mode приложением, и потом тоже его IoAttachDeviceToDeviceStack. Соотв., управляющее юзер-моде приложение будет создавать объект вторичного девайса, а приложение пользователя — первичного. (?) какие параметры передавать IoCreateDevice в этом случае для успешной работы вторичного девайса. Очевидно, в этом случае на функциях IOCTLххх и IRP_ххх прижется разбирать, какой именно драйвер вызывается.
б) Другие варианты.
Возможно, я что то недопонимаю, т.к. опыта написания таких драйверов немного.
Всем спасибо за советы.
Здравствуйте Andrew S, Вы писали:
AS>Привет всем. Жизнь заставляет писАть драйвер ком-порта, при этом возникает необходимость общения с user-mode приложением (для управления поведением драйвера, вызовом некоторых функций и т.п.). AS>Очевидно, для общения с драйвером посредством отложенного DeviceIoControl необходимо получить хандл драйвера. Также очевидно, что напрямую сделать ЭТО в случае с ком портом не представляется возможным, т.к. такой хандл должно мочь создать приложение пользователя. Очевидно, есть 2 решения. AS>1. Писать filter драйвер. Ну, или совмещать его функциональность в основном. AS>2. Использовать неизвестные мне недокументированные возможности и создавать таки хандл (точнее, его копию) из юзер моде. AS>Интересует следующее. AS>а) Возможно ли совместить функционал 2-х типов драйверов в одном, т.е. сначала сделать IoCreateDevice и IoAttachDeviceToDeviceStack для собственно драйвера последовательного порта, а потом сделать в нем же так называемый вторичный девайс, спеиально для общения с нашим управляющим user-mode приложением, и потом тоже его IoAttachDeviceToDeviceStack. Соотв., управляющее юзер-моде приложение будет создавать объект вторичного девайса, а приложение пользователя — первичного. (?) какие параметры передавать IoCreateDevice в этом случае для успешной работы вторичного девайса. Очевидно, в этом случае на функциях IOCTLххх и IRP_ххх прижется разбирать, какой именно драйвер вызывается. AS>б) Другие варианты.
AS>Возможно, я что то недопонимаю, т.к. опыта написания таких драйверов немного. AS>Всем спасибо за советы.
Просто создай для общения с приложением второй девайс (DEVICE_TYPE возьми какойнть начиная с 0x8000) и симболик линк для него создай, и все. Никуда его аттачить не надо
А IRP проще наверное стеково передавать? Дело в том, что многие из IRP будут нести данные, нужные lower level драйверу. Поэтому я и решил, чтобу не разводить копии IRP — проще аттачить его на стек драйверов. В этом случае функции filter части вторичного девайса драйвера сводятся просто к передачи запроса Lower level драйверу.
Или я неправ?
V>Просто создай для общения с приложением второй девайс (DEVICE_TYPE возьми какойнть начиная с 0x8000) и симболик линк для него создай, и все. Никуда его аттачить не надо
Да, и сразу же второй вопрос. Как лучшее — создавать один вторичный девайс, или для каждого первичного создавать свой вторичный. В смысле, как будет меньше оверхед при использовании?
Здравствуйте Andrew S, Вы писали:
AS>А IRP проще наверное стеково передавать? Дело в том, что многие из IRP будут нести данные, нужные lower level драйверу. Поэтому я и решил, чтобу не разводить копии IRP — проще аттачить его на стек драйверов. В этом случае функции filter части вторичного девайса драйвера сводятся просто к передачи запроса Lower level драйверу. AS>Или я неправ?
Ну здесь дело в том что устройство, которое аттачится наверх стека, по-хорошему должно сохранять флаги нижних устройств, в частности и флаг эксклюзивности, а так как сериалпорт должен быть эксклюзивным, то при такой архитектуре (устройство для общения с приложением сидит наверху стека) — не удастся открыть более одного хэндла. Поэтому твое приложение и какаянить другая програмка не смогут работать одновременно. Или же наоборот, если ты снимешь флаг экслюзивности, то 2 приложения смогут открыть сериалпорт, что тоже неправильно. Отсюда и необходимость "вторичного" устройства. Пробовать передавать оригинальный ИРП из девайса-сателлита прямо в девайс сериал порта — очень не рекомендую, даже если данные запроса менять не надо. Лучше иметь пул preallocated ирпов для девайса сериал порта, и брать из него при необходимости (ну и пополнять его соответвенно тоже). Отвечая на следующий пост — на мой взгляд, можно вообще пренебречь "оверхедом" от создания дополнительных девайсов, и действовать так, как будет архитектурно правильно. Если тебе кажется, что логичнее чтоб у каждого порта был свое устройство-"сателлит" — значит так и делай.
Удачи!
Слушай, извини, что мучаю, но больше никто, видимо, ответить не могет. Народа, общающегося с кернел, не так то много:)
Насчет эксклюзивности ты уверен абсолютно или все же стОит попробовать?
Насколько я знаю, filter драйверы пишутся именно так, и вроде все работает. Например, фильтер драйвер для ком порта.
И после этого юзерские приложения не могут открывать более одного раза ком порт, как и положено.
А если использовать IoAttachDevice для вторичного девайса вместо IoAttachDeviceToDeviceStack?
Тут то экслюзивность сохраняется? И можно ли после этого убить SourceDevice (см. IoAttachDevice), или они должны жить вместе с AttachedDevice долго и умереть в один день?
А оверхед... В принципе, всего 2 варианта:
1. Для каждого девайса — свой саттелит. При этом в DEVICE_EXTENSION саттелита хранится lower device настоящего девайса. Соотв, надо различать, запрос к чему идет. Можно для это цели выбрать первый элемент структуры в DEVICE_EXTENSION, который будет указывать, саттелит это или нет. Соотв., дальнейшие поля DEVICE_EXTENSION в зависимости от этого интерпретируются по-разному.
2. Для всех девайсов — один саттелит. При этом при первом вызове из юзер-моде приложения ему возвращается соотв. DEVICE_OBJECT настоящего девайса, который потом и используется при вызовах для роутинга между настоящими девайсами.
Для метода (2) наверное, каждый запрос к драйверу требует нового IRP. Или нет?
Очевидно, что для (1) все может быть проще — просто передаем запрос ниже по стеку драйверов и все.
Правда, если только насчет эксклюзивности ты ошибся :)
Мне просто интересно не как логичнее на мой взгляд, а как делают другие, т.к. у меня опыта пока немного и все кажется весьма сложным.
И еще. А почему рекомендуешь создавать пул IRP заранее (под пулом подразумевается LinkedList?)? Чем это удобно? Почему нельзя создавать IRP непосредственно при необходимости, в момент запроса?
Здравствуйте Andrew S, Вы писали:
AS>Слушай, извини, что мучаю, но больше никто, видимо, ответить не могет. Народа, общающегося с кернел, не так то много
AS>Насчет эксклюзивности ты уверен абсолютно или все же стОит попробовать? AS>Насколько я знаю, filter драйверы пишутся именно так, и вроде все работает. Например, фильтер драйвер для ком порта. AS>И после этого юзерские приложения не могут открывать более одного раза ком порт, как и положено.
По хорошему фильтры должны брать флаги нижележащих устройств (ну и модифицировать их по необходимости). Но здесь все равно имеется логическая проблема. Даже если ты уберешь флаг экслюзивности у устройства, какое-нить приложение может создать хэндл сериал порта для эксклюзивного доступа (передать 0 в dwShareMode при CreateFile), поэтому неприемлемо иметь устройство для общения с твоим приложением, сидящее наверху стека самого сериалпорта (если только действительно нужна работа этого приложения одновременно с другими, пользующимися портом)
AS>А если использовать IoAttachDevice для вторичного девайса вместо IoAttachDeviceToDeviceStack? AS>Тут то экслюзивность сохраняется?
Эксклюзивность задается при IoCreateDevice (флаг bExclusive) или позже, через DEVICE_OBJECT::Flags (DO_EXCLUSIVE)
AS>И можно ли после этого убить SourceDevice (см. IoAttachDevice), или они должны жить вместе с AttachedDevice долго и умереть в один день?
Какже ты его убъешь??? Ты ж его только что приаттачил сверху на стек???
AS>А оверхед... В принципе, всего 2 варианта: AS>1. Для каждого девайса — свой саттелит. При этом в DEVICE_EXTENSION саттелита хранится lower device настоящего девайса. Соотв, надо различать, запрос к чему идет. Можно для это цели выбрать первый элемент структуры в DEVICE_EXTENSION, который будет указывать, саттелит это или нет. Соотв., дальнейшие поля DEVICE_EXTENSION в зависимости от этого интерпретируются по-разному. AS>2. Для всех девайсов — один саттелит. При этом при первом вызове из юзер-моде приложения ему возвращается соотв. DEVICE_OBJECT настоящего девайса, который потом и используется при вызовах для роутинга между настоящими девайсами.
AS>Для метода (2) наверное, каждый запрос к драйверу требует нового IRP. Или нет? AS>Очевидно, что для (1) все может быть проще — просто передаем запрос ниже по стеку драйверов и все. AS>Правда, если только насчет эксклюзивности ты ошибся
AS>Мне просто интересно не как логичнее на мой взгляд, а как делают другие, т.к. у меня опыта пока немного и все кажется весьма сложным.
Ну все зависит от логики работы этого "вторичного" устройства. Если логично и удобно чтоб он был один, надо делать один. Если нужно много — можно сделать много, на "оверхед" можно не обращать внимания. Если сообщищь, что собирается делать приложение, можно чтонить поконкретнее сказать =)
AS>И еще. А почему рекомендуешь создавать пул IRP заранее (под пулом подразумевается LinkedList?)? Чем это удобно? Почему нельзя создавать IRP непосредственно при необходимости, в момент запроса?
Вообще-то это неудобно =) Но если нет гарантий, что dispatchentry будет вызвана при PASSIVE_LEVEL — это необходимо.
Если ты уверен, что будет PASSIVE_LEVEL (например если все запросы к твоему устройству идут от тебя же), можешь создавать новый ирп прям в момент запроса.
Нет, ну это понятно. А как же тогда пишутся фильтры для последовательных портов? Например, PortMon. Он одновременно общается и со своим юзер-може приложением, и одновременно дает открыть lower level драйвер ком-порта обычным приложениям. Ок. Я все же попробую, что получится — скажу.
Спасибо!
V>По хорошему фильтры должны брать флаги нижележащих устройств (ну и модифицировать их по необходимости). Но здесь все равно имеется логическая проблема. Даже если ты уберешь флаг экслюзивности у устройства, какое-нить приложение может создать хэндл сериал порта для эксклюзивного доступа (передать 0 в dwShareMode при CreateFile), поэтому неприемлемо иметь устройство для общения с твоим приложением, сидящее наверху стека самого сериалпорта (если только действительно нужна работа этого приложения одновременно с другими, пользующимися портом)
AS>>А если использовать IoAttachDevice для вторичного девайса вместо IoAttachDeviceToDeviceStack? AS>>Тут то экслюзивность сохраняется? V>Эксклюзивность задается при IoCreateDevice (флаг bExclusive) или позже, через DEVICE_OBJECT::Flags (DO_EXCLUSIVE)
AS>>И можно ли после этого убить SourceDevice (см. IoAttachDevice), или они должны жить вместе с AttachedDevice долго и умереть в один день? V>Какже ты его убъешь??? Ты ж его только что приаттачил сверху на стек???
AS>>А оверхед... В принципе, всего 2 варианта: AS>>1. Для каждого девайса — свой саттелит. При этом в DEVICE_EXTENSION саттелита хранится lower device настоящего девайса. Соотв, надо различать, запрос к чему идет. Можно для это цели выбрать первый элемент структуры в DEVICE_EXTENSION, который будет указывать, саттелит это или нет. Соотв., дальнейшие поля DEVICE_EXTENSION в зависимости от этого интерпретируются по-разному. AS>>2. Для всех девайсов — один саттелит. При этом при первом вызове из юзер-моде приложения ему возвращается соотв. DEVICE_OBJECT настоящего девайса, который потом и используется при вызовах для роутинга между настоящими девайсами.
AS>>Для метода (2) наверное, каждый запрос к драйверу требует нового IRP. Или нет? AS>>Очевидно, что для (1) все может быть проще — просто передаем запрос ниже по стеку драйверов и все. AS>>Правда, если только насчет эксклюзивности ты ошибся
AS>>Мне просто интересно не как логичнее на мой взгляд, а как делают другие, т.к. у меня опыта пока немного и все кажется весьма сложным. V>Ну все зависит от логики работы этого "вторичного" устройства. Если логично и удобно чтоб он был один, надо делать один. Если нужно много — можно сделать много, на "оверхед" можно не обращать внимания. Если сообщищь, что собирается делать приложение, можно чтонить поконкретнее сказать =)
AS>>И еще. А почему рекомендуешь создавать пул IRP заранее (под пулом подразумевается LinkedList?)? Чем это удобно? Почему нельзя создавать IRP непосредственно при необходимости, в момент запроса? V>Вообще-то это неудобно =) Но если нет гарантий, что dispatchentry будет вызвана при PASSIVE_LEVEL — это необходимо. V>Если ты уверен, что будет PASSIVE_LEVEL (например если все запросы к твоему устройству идут от тебя же), можешь создавать новый ирп прям в момент запроса.
Привет всем еще раз. Попробовал я сделать, как рекомендовалось. Т.е. просто создать саттелит-девайс без аттачинья его куда-либо (в том же драйвере, что и основной). И симболик линк на него. Это не заработало. Девайс создается, линк на него тоже. Но вот не окрывается из юзер-моде. Основной — открывается, а этот нет.
Итак, у кого еще есть какие мнения. Приложению управления нужно получать данные из последовательного порта, и отправлять ему тоже. При этом, естественно, порт открыт другим юзер-моде приложением пользователя, и открыть его еще раз приложения управления не может, т.к. порт уже открыт. Очевидно, что такая проблема на других устройствах решается filter-драйвером. Однако тут проскочило замечание, что с последовательным портом такое не пройдет, т.к. присутствует флаг эксклюзитвности.
К тому же задача осложняется (или упрощается?) тем, что это хорошо бы совместить в одном драйвере — т.е. и функционал драйвера com-порта, и фильтер-драйвера.
Т.е. создается устройство — саттелит (как?), с которым и общается юзер-моде приложение.
Илди может можно без дополнительного гемморая, получить каким то образом юзер-моде хандл на уже открытый другим юзер-моде приложением девайс и отдать его приложению управления (это, конечно, ересь — т.к. хандл привязан к процессу, его открывшему, но вдруг...)?
очевидно, проблема решаема, т.к. существуют подобные продукты. (Да взять хотя бы драйвера вин-модемов)
Буду всем признателен за любую помощь. К сожалению, в той литературе, что есть у меня, этот вопрос не освещен вообще.
Здравствуйте Andrew S, Вы писали:
AS>Привет всем. Жизнь заставляет писАть драйвер ком-порта, при этом возникает необходимость общения с user-mode приложением (для управления поведением драйвера, вызовом некоторых функций и т.п.). AS>Очевидно, для общения с драйвером посредством отложенного DeviceIoControl необходимо получить хандл драйвера. Также очевидно, что напрямую сделать ЭТО в случае с ком портом не представляется возможным, т.к. такой хандл должно мочь создать приложение пользователя. Очевидно, есть 2 решения. AS>1. Писать filter драйвер. Ну, или совмещать его функциональность в основном. AS>2. Использовать неизвестные мне недокументированные возможности и создавать таки хандл (точнее, его копию) из юзер моде. AS>Интересует следующее. AS>а) Возможно ли совместить функционал 2-х типов драйверов в одном, т.е. сначала сделать IoCreateDevice и IoAttachDeviceToDeviceStack для собственно драйвера последовательного порта, а потом сделать в нем же так называемый вторичный девайс, спеиально для общения с нашим управляющим user-mode приложением, и потом тоже его IoAttachDeviceToDeviceStack. Соотв., управляющее юзер-моде приложение будет создавать объект вторичного девайса, а приложение пользователя — первичного. (?) какие параметры передавать IoCreateDevice в этом случае для успешной работы вторичного девайса. Очевидно, в этом случае на функциях IOCTLххх и IRP_ххх прижется разбирать, какой именно драйвер вызывается. AS>б) Другие варианты.
AS>Возможно, я что то недопонимаю, т.к. опыта написания таких драйверов немного. AS>Всем спасибо за советы.
Хотелось бы узнать чем все это закончилось?
AS>Привет всем. Жизнь заставляет писАть драйвер ком-порта, при этом возникает необходимость общения с user-mode приложением (для управления поведением драйвера, вызовом некоторых функций и т.п.). AS>Очевидно, для общения с драйвером посредством отложенного DeviceIoControl необходимо получить хандл драйвера. Также очевидно, что напрямую сделать ЭТО в случае с ком портом не представляется возможным, т.к. такой хандл должно мочь создать приложение пользователя. Очевидно, есть 2 решения. AS>1. Писать filter драйвер. Ну, или совмещать его функциональность в основном. AS>2. Использовать неизвестные мне недокументированные возможности и создавать таки хандл (точнее, его копию) из юзер моде. AS>Интересует следующее. AS>а) Возможно ли совместить функционал 2-х типов драйверов в одном, т.е. сначала сделать IoCreateDevice и IoAttachDeviceToDeviceStack для собственно драйвера последовательного порта, а потом сделать в нем же так называемый вторичный девайс, спеиально для общения с нашим управляющим user-mode приложением, и потом тоже его IoAttachDeviceToDeviceStack. Соотв., управляющее юзер-моде приложение будет создавать объект вторичного девайса, а приложение пользователя — первичного. (?) какие параметры передавать IoCreateDevice в этом случае для успешной работы вторичного девайса. Очевидно, в этом случае на функциях IOCTLххх и IRP_ххх прижется разбирать, какой именно драйвер вызывается. AS>б) Другие варианты.
AS>Возможно, я что то недопонимаю, т.к. опыта написания таких драйверов немного. AS>Всем спасибо за советы.
Скелет драйвера был почти написан, а проект заброшен
Честно говоря, сейчас даже и не помню всех проблем, которые решали и которые еще предстояло решить.
Здравствуйте, Andrew S, Вы писали:
FiW>>Хотелось бы узнать чем все это закончилось?
AS>Скелет драйвера был почти написан, а проект заброшен AS>Честно говоря, сейчас даже и не помню всех проблем, которые решали и которые еще предстояло решить.
вот блин, я в таком же "тупике" сейчас... а исходников не осталось? может там были "крупицы истины"?
FiW>вот блин, я в таком же "тупике" сейчас... а исходников не осталось? может там были "крупицы истины"?
Все уже давно поксерено... Я думаю — самый правильный вариант — почитать форум хардваре, поспрашивать там — подобные темы там были и варианты решения тоже. Еще можно попробовать поискать иходники port mon.
Здравствуйте, Andrew S, Вы писали:
FiW>>вот блин, я в таком же "тупике" сейчас... а исходников не осталось? может там были "крупицы истины"?
AS>Все уже давно поксерено... Я думаю — самый правильный вариант — почитать форум хардваре, поспрашивать там — подобные темы там были и варианты решения тоже. Еще можно попробовать поискать иходники port mon.
Да фильтер-драйвер уже есть (который "слушает", как PortMon), а вот как реализовать передачу в порт от другой программы? Мне казалось что я вот-вот у цели... а теперь я в тупике
ps: у меня порт захвачен сервисом постоянно, а иногда нужно послать пару тройку команд туда...
FiW>>>вот блин, я в таком же "тупике" сейчас... а исходников не осталось? может там были "крупицы истины"?
AS>>Все уже давно поксерено... Я думаю — самый правильный вариант — почитать форум хардваре, поспрашивать там — подобные темы там были и варианты решения тоже. Еще можно попробовать поискать иходники port mon.
FiW>Да фильтер-драйвер уже есть (который "слушает", как PortMon), а вот как реализовать передачу в порт от другой программы? Мне казалось что я вот-вот у цели... а теперь я в тупике
FiW>ps: у меня порт захвачен сервисом постоянно, а иногда нужно послать пару тройку команд туда...
Насколько я помню, туда на стек аттачится дополнительный девайс, который собственно может как пропускать IRP (то бишь выполнять роль фильтра), так и формировать новые. Но это лучше в hardware спросить — я слишком давно всем этим занимался, а копаться в этом белье мне сейчас просто не когда...