![]() |
Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply |
![]() ![]() ![]() |
|
ama_kid |
|
||||||||||||||||||||||||||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
1. Введение
Данная статья является, по своей сути, продолжением известной статьи Геннадия Порева "Создание драйверов режима ядра в среде Borland Delphi". Все моё дальнейшее повествование будет предполагать, что читатель по крайней мере ознакомился с представленным в ней материалом, поэтому если это еще не сделано - то сейчас самое время. К статье прилагается архив со всеми исходными текстами, описанными и разобранными здесь, при этом хотелось бы упомянуть, что некоторые вещи, которые можно найти в исходниках - здесь не описаны, например логирование действий драйвера в файл на диске, которая мало чем отличается от работы с логами в user-mode, или найденная мной в интернете ручная приближенная реализация cdecl-формата вызова функции DbgPrint, которая на языке С++ имеет переменное число параметров с возможностью вставлять управляющие символы для вывода значений переменных (Delphi этого не умеет). Не описано это просто потому, что нет желания останавливаться на этом, при необходимости - это можно самому посмотреть и понять. Также, при цитировании кода в тексте статьи я буду опускать те участки или параллельные вызовы функций (в основном, конечно, отладочный вывод), которые не нужны для понимания той части, о которой говорю в данный момент, поэтому не стоит удивляться, если обнаружите, что исходном коде наличествует еще какой-то "мусор" по сравнению со статьей. 2. Инструментарий Прежде всего, хочу немного времени уделить описанию инструментария, который я использую у себя. В принципе, в изначальной статье он был достаточно подробно описан, так что я не буду повторяться, просто на всякий случай пошагово опишу его применение. Средой разработки является любой текстовый редактор (кстати, почитателям компоненто-на-форму-кидательства дальнейшее не рекомендуется к прочтению). Лично я пользуюсь встроенным редактором Far'а, но можно использовать любой удобный и привычный инструмент. В принципе, впоследствии я нашел на просторах интернета "Delphi Driver Development Kit" (где вроде как используется компилятор от 7-й версии дельфи), но к тому моменту уже привык к изначальной среде окружения, поэтому не стал его особо изучать (кроме того на него тявкает мой антивирус, а после замены инфицированных компилятора и линкера на рабочие варианты - мне так и не удалось заставить его работать). Кому надо - может погуглить: Как правило, для разработки драйвера я копирую целиком папку, содержащую нижеописанные файлы и работаю уже в ней: а) Файл ntoskrnl.lib - самый главный файл, содержащий все импортируемые ядром Windows функции. Данный файл не только жизненно необходим для работы линковщика, но также может помочь узнать формат вызова конкретной необходимой функции, о чем я расскажу ниже. б) dcc32.exe, rlink32.dll, system.dcu и sysinit.dcu - собственно компилятор Delphi3 с сопутствующими файлами. в) link.exe, mspdb71.dll - линковщик от мелкомягких с необходимой для его работы библиотекой г) DrvInst.exe - инсталлятор\деинсталлятор драйвера. Исходник данного приложения на языке Delphi можно найти в прилагающемся архиве и в нем мной реализованы два способа установки драйвера: моментальный (по умолчанию) и с перезагрузкой (во многих случаях может потребоваться и это). Второй способ в исходнике закомментирован, но рекомендуется его проверить для того, чтобы понимать, как это делается. д) Пакетные файлы: _clear.bat (очистка папки), _copy.bat (копирование драйвера в системную папку), _Inst.bat (запуск драйвера), Make.bat и _make.bat (компилирование и сборка драйвера) и _Uninst.bat (очистка системы от следов драйвера) - собственно представляют из себя управление циклом жизни драйвера. Каждый из них вызывает соответствующие команды и исполняемые файлы для реализации своей задачи. Для корректной работы перед началом использования надо в них заменить все названия драйвера на своё собственное (заменив, естесственно, и соответствующие названия файлов). Затем, при наличии в этой же папке файла-исходника драйвера, запускать надо в следующем порядке: - _make.bat (если все прошло успешно - в папке появится sys-файл драйвера) - _copy.bat (этот файл скопируется в системную папку) - (в данном месте я обычно запускаю утилиту DbgView.exe) - _Inst.bat (драйвер запустится и начнет свою работу) - _UnInst.bat (драйвер выгрузится и удалится из системы и текущей папки) е) Ну и не могу не упомянуть скрытых игроков нашей команды - это предустановленный DDK, MSDN и интернет. 99% информации - оттуда. Естественно, этот способ организации процесса не является истиной в последней инстанции и можно его оптимизировать, но для того, чтобы дальнейшие описания были понятны и, самое главное, вопроизводимы - примем такую среду за отправную точку. 3. Первые шаги В данной главе я постараюсь показать, как можно работать в kernel-mode и что делать с доставшимся правом "делать все, что захочется". Исходный код тестового драйвера, рассмотренный здесь, а также user-mode'ного приложения для его тестирования, доступен в прилагающемся архиве в папке под именем MyDrv. 3.1 Перевод функций DDK Итак, автор первоначальной статьи оставил нас наедине с "голым" драйвером tiny, который может только загружаться и выгружаться. Куда двигаться дальше? Надо сказать, что несмотря на использовании компилятора дельфи, все его RTTL-вкусности типа функций trunc, sqrt, random, равно как классов, объектов и других полезностей в ООП, остаются за бортом. Да что там функции - даже банальное сложение двух строковых переменных недопустимо, потому что для этой несложной с точки зрения программиста операции компилятору приходится генерировать вызовы нескольких функций, которых просто нет в режиме ядра! Ну и особую грусть вызывает невозможность использования стандартных обработчиков исключений try...except...finally... по той же самой причине. Поэтому необходимо посмотреть в сторону того, что разрешено. Здесь на помощь приходят файлы ntddk.h, ntdef.h (файлы описаний из WinDDK) и ntoskrnl.lib (описанный выше). Этих файлов конечно недостаточно для того, чтобы написать какой-то навороченный драйвер файловой системы низкого уровня, но для написания более-менее полезного драйвера в учебных целях их хватит (при этом h-файлы используются только как справочный материал по объявлениям констант и необходимых нам функций). Для начала работы необходимо явно указать компилятору, какие функции режима ядра можно использовать - делается это путем статической линковки функций файла ntoskrnl.lib. Для тех, кто не очень четко представляет себе этот механизм - поясню сказанное: возьмем, к примеру, функцию IoCreateDevice, которая впоследствие нам еще пригодится. Объявление этой функции в файле ntddk.h выглядит следующим образом:
3.2. Создание объекта "устройство" Сам по себе драйвер, который умеет только загружаться и выгружаться - бесполезен. Как правило, все драйверы работают с какими-либо устройствами (но не обязательно, и впоследствии я покажу пример этого), поэтому самое первое, что необходимо сделать для того, чтобы труд не был напрасным - создать объект "устройство", к которому можно будет впоследствии обращаться из приложения. Создание устройства в принципе может происходить на любом этапе работы драйвера, но как правило это делают при начальной инициализации в функции DriverEnry:
3.3. Общение с приложением user-mode Но просто создать\удалить устройство - это еще полдела. Зачастую требуется получить некоторую информацию от процесса, исполняющегося в режиме ядра или передать туда порцию своей информации. Для начала рассмотрим самый простой способ - организацию функций-диспетчеров запросов IRP_MJ_READ ($03) и IRP_MJ_WRITE ($04), которые приходят драйверу при выполнении команд ReadFile и WriteFile соответственно. Для начала - необходимо назначить эти самые диспетчеры в функции DriverEntry:
Теперь рассмотрим методы приема\передачи буфера данных. При создании устройства можно выбрать тип метода передачи этого буфера: буферизированный (DO_BUFFERED_IO = $00000004) или прямой (DO_DIRECT_IO = $00000010) путем установки поля Flags объекта-устройств:
а) Запрос чтения (ReadFile): Сам запрос от приложения-инициатора выглядит следующим образом:
Теперь рассмотрим обработку этого запроса в нашем тестовом драйвере:
б) Запрос записи (WriteFile): Запрос от приложения-инициатора:
В драйвере:
Это сообщение отредактировал(а) ama_kid - 8.9.2008, 22:24 Присоединённый файл ( Кол-во скачиваний: 453 ) ![]() -------------------- самурай без меча подобен самураю с мечом, но только без меча |
||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||
ama_kid |
|
||||||||||||||||||||||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
3.4 Продвинутое общение
Рассмотренный нами в предыдущей главе метод общения драйвера с внешним миром, конечно, прост и понятен, но что делать, если задача требует не просто считать\записать данные, а произвести несколько более сложные действия, например, передать управляющие команды, обеспечить диалог драйвер-приложение или выполнить что-либо ещё специфическое для данного драйвера? Можно, конечно, при желании все организовать через ReadFile\WriteFile, но есть более универсальное решение - функция DeviceIoControl. Для примера, рассмотрим следующие функции:
![]() Расшифровка полей управляющего слова следующая: 1. Поле DeviceType определяет тип объекта-устройства, которому предназначен запрос. Это тот самый тип устройства, который передается функции IoCreateDevice() при создании устройства. 2. Поле Function идентифицирует конкретные действия, которые должно предпринять устройство при получении запроса. Значения поля Function должны быть уникальны внутри устройства. 3. Поле Method указывает метод передачи буферов данных. Для задания этого поля можно использовать константы: METHOD_BUFFERED = 0; METHOD_IN_DIRECT = 1; METHOD_OUT_DIRECT = 2; METHOD_NEITHER = 3; 4. Поле Access указывает тип доступа, который должен был быть запрошен (и предоставлен) при открытии объекта-файла, для которого передается данный код Управления вводом/выводом. Возможные значения: FILE_ANY_ACCESS = $0000, FILE_READ_ACCESS = $0001 и FILE_WRITE_ACCESS = $0002. Для нас самое важное значение имеют биты 0-2 (в которых указывается метод передачи буфера) и 3-12 (в которых указывается передаваемый код управления драйвером). Остальные байты можно формировать по желанию и необходимости, в нашем случае такой необходимости нет. Теперь рассмотрим обработку этого запроса со стороны драйвера: Для начала необходимо назначить функцию-обработчик данного запроса. Это выполняется, как обычно, в DriverEntry:
4. Из жизни Предыдущая глава была посвящена решению проблем, выдуманных нами фактически на пустом месте. Это не сильно интересно, поэтому в данной главе я хотел бы разобрать пару примеров, основа которых была мной написана для реальных проектов. Надеюсь, они помогут в более быстром освоении темы. Оба примера будут рассмотрены, естественно, на языке Delphi, но если кому интересно - то в соответствующих папках в архиве можно найти и C++ - варианты этих драйверов, которые собираются из-под DDKXP. 4.1 Пример №1: Перехват клавиатуры Рассмотрим частный пример распространенной проблемы глобального перехвата клавиатуры - отлов сочетания CAD. В операционных системах семейства NT это сочетание является единственным, которое не отлавливается из user-mode (исключение составляет способ отлова через MSGINA.dll, но он обладает своими недостатками), поэтому я и взял его для примера, но в принципе данный подход применим для отлова любого требуемого сочетания клавиш. Основной идеей является установка драйвера-фильтра клавиатуры верхнего уровня. Что такое драйвер-фильтр и чем верхний уровень отличается от нижнего я объяснять не буду, об этом можно почитать в соответствующих источниках, но суть сводится к тому, что мы "посадим" наш драйвер поверх устройства основного драйвера клавиатуры, оставляя всю рутинную работу по работе с портами ввода-вывода и первичной обработке результатов ему, а сами будем только фильтровать запросы, проходящие между режимом пользователя и этим драйвером. Данный пример был написан мною по мотивам и на основе широко известного примера Ctrl2Cap, но с некоторыми изменениями, на которых я остановлюсь подробнее. Исходный код драйвера находится в прилагающемся архиве в папке под названием KbdIntcpt. Итак, рассмотрим функцию DriverEntry: первым делом мы создаем объект "устройство", как было показано ранее, с помощью функций IoCreateDevice и IoCreateSymbolicLink.
Затем идёт кусок кода по созданию объекта-евента:
а) Дело в том, что в обработке драйвера клавиатуры всегда находится как минимум один IRP-пакет, поэтому когда мы присоединяемся в цепочку фильтров - то неизбежно пропустим тот пакет, который уже сидит в обработке, потому что на него еще не была установлена наша функция возврата. Фактически это означает что первое после загрузки драйвера нажатие клавиши не будет отловлено. б) Опять же, благодаря тому, что в обработке всегда наличествует как минимум один пакет, в момент выгрузки драйвера в этом пакете сидит привязанная к нему наша callback-функция ReadCompleteCallback (если, конечно, между загрузкой и выгрузкой драйвера происходили нажатия клавиш, что должно было привести к вызову IoSetCompletionRoutine) и если мы выгрузимся до того, как драйвер клавиатуры вызовет эту функцию, мы неизбежно получим BSOD. Для того, чтобы этого избежать - я и использовал евент, сигнализирующий о получении очередного пакета и не дающий выгрузиться драйверу, если он не сработал. Этой же цели служит булевская переменная UnloadProcess, которая не дает установить процедуру завершения, если пошел процесс выгрузки драйвера. Но все это приводит к небольшому неудобству - при выгрузке драйвера необходимо нажать клавишу. Упомянутый мной пример Ctrl2Cap этот момент обходит другим способом - он для своей установки\выгрузки требует перезагрузки компьютера, кому интересно - может погуглить и посмотреть, как это реализовано. в) Ну и еще один достаточно тонкий момент, который не относится именно к данному драйверу, но который я впервые испытал на своей шкуре именно в этом месте, поэтому упомяну здесь. Дело в том, что callback-функция ReadCompleteCallback вызывается на уровне DISPATCH_LEVEL, в то время как остальной код драйвера по умолчанию работает на самом низкоприоритетном уровне PASSIVE_LEVEL. Это различие аукнулось тем, что попытка записи в лог-файл внутри этой функции приводила к BSOD, потому что работа с файлами производится тоже на уровне PASSIVE_LEVEL. Поэтому при разработке механизмов взаимодействия рекомендую не забывать о таких вещах, как приоритет выполнения. Ну а что же собственно выполняет функция ReadCompleteCallback? Её код выглядит следующим образом:
4.2 Пример №2: Перехват системных функций ядра Ну и еще один пример, который я хотел бы рассмотреть - это пример осуществления перехвата функций ядра на примере функции ZwQueryDirectoryFile для обеспечения "невидимости" требуемого файла\папки. Делается это путем модификации системной таблицы служебных дескрипторов (SSDT). Данный метод зачастую называют "грязным", но иногда приходится прибегать и к таким способам, благо из режима ядра это разрешено. Этот пример тоже был написан под большим влиянием найденного в сети драйвера, осуществляющего какую-то работу с таблицей дескрипторов, но, к сожалению, я уже не помню что это был за драйвер, поэтому авторство идеи оставляю за "неизвестным героем". Исходный код находится в прилагающемся архиве в папке под названием FileHider и полный код я приводить здесь не буду, просто поясню основные моменты. Итак, хук устанавливается в функции DriverEntry с помощью экспортируемой недокументированной глобальной переменной KeServiceDescriptorTable (со скачиваемыми примерами рекомендую проявлять осторожность - антивирус ругается на скомпилированные файлы, принимая rootkit-технологии за зверьё). Тонким моментом здесь является использование бита WP системного регистра cr0 при установке\снятии хука. Этот бит управляет защитой от записи системных страниц памяти. Если у вас на машине стоит физической памяти больше 256 Мб (WinXP) или 128 Мб (Win2k), тогда данный код никак не влияет на функциональность (т.е. если его убрать - никаких отличий не найти). Но! Если на машине стоит памяти меньше чем указано - тогда система осуществляет защиту системных страниц памяти от записи и при попытке что-то записать в область системного кода будет генерироваться исключение и это вызовет BSOD (подробнее об этом можно прочитать в журнале Хакер, глава "Типы атак на ядро"). Именно для того, чтобы это учесть, и сделан сброс бита WP перед записью в область системного кода - тогда системные страницы с любом случае будут доступны для модификации. После установки хука - остальное дело техники. Все запросы, благодаря наличию в SSDT адреса нашей функции, перенаправляются ей, затем она тут же вызывает оригинальную системную процедуру по сохраненному указателю, а возвращаемый результат анализирует на предмет соответствия требуемым условиям. В примере я сделал проверку по соответствии имени файла\папки определенному шаблону, а также закомментировал проверку по атрибутам файла. Анализ осуществляется путем перебора всего списка элементов типа FILE_BOTH_DIRECTORY_INFORMATION, который возвращается оригнальной функцией ZwQueryDirectoryFile. В случае выполнения условий проверки - проверяемый элемент удаляется из списка путем перенаправления указателя предыдущего элемента списка на следующий. При завершении работы драйвера - в функции DriverUnload адрес оригинальной процедуры возвращается на место : Конечно, для того, чтобы полностью "спрятать" требуемый файл - просто перехвата ZwQueryDirectoryFile недостаточно, даже если спрятать папку таким образом - в неё все равно можно будет зайти путем ввода команды "cd". Но это уже вопрос наращивания функциональности. 5. Заключение Данная статья не охватывает многие и многие аспекты темы разработки драйверов. Например, не были рассмотрены вопросы обмена с реальными устройствами, не приведено примеров работы с файловой системой на низком уровне, даже не рассмотрен вопрос построения inf-файлов, необходимых для полноценной установки устройства в систему, или других узкоспециализированных моментов. Но и не в этом её цель. Целью является дать дополнительный импульс для тех, кто хочет осилить эту необъятную тему, с тем, чтобы дальше можно было двигаться самостоятельно, дать начальные познания при помощи привычной "среды", а также дать своеобразные "направляющие" для правильного составления конкретных вопросов на соответствующих форумах. Если не получилось - прошу строго не судить P.S. Выражаю огромную благодарность Snowy за помощь в подготовке и оформлении статьи. Это сообщение отредактировал(а) ama_kid - 8.9.2008, 22:11 Присоединённый файл ( Кол-во скачиваний: 483 ) ![]() -------------------- самурай без меча подобен самураю с мечом, но только без меча |
||||||||||||||||||||||
|
|||||||||||||||||||||||
THandle |
|
|||
![]() Хранитель Клуба ![]() Награды: 1 Профиль Группа: Админ Сообщений: 3639 Регистрация: 31.7.2007 Где: Moscow, Dubai Репутация: 7 Всего: 372 |
||||
|
||||
MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
ama_kid, сам написал?! ну ты
![]() -------------------- There are always someone smarter than you... |
|||
|
||||
ama_kid |
|
|||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
THandle, MetalFan, спасибо
![]() Это сообщение отредактировал(а) ama_kid - 5.12.2008, 23:26 -------------------- самурай без меча подобен самураю с мечом, но только без меча |
|||
|
||||
Riply |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Комодератор Сообщений: 572 Регистрация: 27.3.2007 Где: St. Petersburg Репутация: 21 Всего: 32 |
ama_kid,
Спасибо. Когда при решении задач мне стало довольно сильно мешать мое неумение писать драйвера, я решила обратиться к С, считая что в родной и любимой Delphi это будет "не естественно" ![]() Еще раз спасибо, за избавление от столь пагубного заблуждения ![]() |
|||
|
||||
ne0n |
|
|||
PlayBoy ![]() ![]() Профиль Группа: Участник Сообщений: 733 Регистрация: 5.8.2005 Где: Н.Новгород Репутация: 4 Всего: 11 |
Riply, ну на самом деле - это не такое пагубное заблуждение...переводить ddk на паскаль, никто не будет...а самому эту задачу не осилить, хотя может и найдуться интузиасты
![]() ничего нового не узнал, но за стотью в любом случаи респек и + |
|||
|
||||
Riply |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Комодератор Сообщений: 572 Регистрация: 27.3.2007 Где: St. Petersburg Репутация: 21 Всего: 32 |
ama_kid,
Наконец-то выдалось свободное время и можно заняться всякими вкусностями ![]() Начала смотреть код (Delphi версия) и у меня сразу появилась куча вопросов: 1. STRSIZE = 115; Что это за число (115) и откуда оно взялось ? 2. NTSTATUS спецально объявлен как ULong ? Если да, то почему ? 3. Вытекает из второго Реализация ф-ии NT_Success ( Result := (NTS=STATUS_SUCCESS) ) обусловлена именно таким объявлением NTSTATUS ? 4. Почему, после вызовов BCAnsiStringAllocate не всегда вызывается BCAnsiStringFree (например в WriteDispatch) ? 5. Rtl-кие функции для работы со строками валидны в нашем случае ? (Имеется ввиду совместимость способов выделения и освобождения памяти Rtl-кими функциями и BC-функциями) ? P.S. При ответах, просьба учесть нулевой уровень вопрошающей в данной области ![]() |
|||
|
||||
ama_kid |
|
|||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
115 - это "магическое число" и взялось оно мной практически с потолка, дабы ограничить размер статического массива
![]() Я не совсем понял вопрос. А как он должен быть объявлен? В принципе, в DDK он объявлен знаковым (long), но в изначальной статье (на которую я ссылаюсь вначале) он был объявлен как cardinal (и в принципе, я нигде не видел использования знаковых особенностей этого дефайна), поэтому перенес все один в один. ![]()
![]() ![]() Не понял, что ты имеешь ввиду под выделением\освобождением памяти Rtl-кими функциями? Память выделяется\освобождается функциями MmAllocateNonCachedMemory\MmFreeNonCachedMemory, а Rtl-кие функции как раз и предназначены для работы со строками (ну и для многого другого). BC-функции, как я говорил, это просто обертки над ними (посмотри их код в модуле BCore.inc - там они как раз и вызывают Rtl-функции) -------------------- самурай без меча подобен самураю с мечом, но только без меча |
|||
|
||||
Riply |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Комодератор Сообщений: 572 Регистрация: 27.3.2007 Где: St. Petersburg Репутация: 21 Всего: 32 |
Я только начала разбираться, но мне кажется, что можно работать с блоками размером до MAXWORD shr 1. Я пыталась исходить из размерности полей. К сожалению не знаю как обстоят дела в мире драйверов, но в обычном приложении, работающем с Nt-функциями знаковость NTSTATUS очень важна. А NT_SUCCESS должна иметь такой вид:
Дело в том, что некоторые (если не многие) функции могут в случае успеха возвращать не STATUS_SUCCESS а "некий код", содержащий STATUS_SEVERITY_INFORMATIONAL. В этом случае фунция выполнена успешно, а в ее результате дается дополнительная информация. Как правило это используется в Query функциях (например STATUS_MORE_ENTRIES говорит, что все удачно записано, но меня можно вызвать еще раз для дозаписи). Но встречается и в другин. Например я сталкивалась с STATUS_PREDEFINED_HANDLE, STATUS_EVENT_PENDING или при работе с секциями (мутантами) STATUS_OBJECT_NAME_EXISTS а вот здесь это становится довольно важно.
Ой. Прошу маленький тай-аут. Еще чуть поразбираюсь и сформулирую вопрос более точно. Но пока мне не понятно, чем обусловлен выбор MmAllocateNonCachedMemory вместо Rtl - Heap - функций ? (Они кстати "совместимы" с такими как RtlFreeUnicodeString) |
||||||
|
|||||||
ama_kid |
|
||||||||||||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
![]() Вот как это дело расписано в DDK:
![]() Я наконец понял, что ты имеешь ввиду. ![]()
![]()
-------------------- самурай без меча подобен самураю с мечом, но только без меча |
||||||||||||
|
|||||||||||||
Riply |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Комодератор Сообщений: 572 Регистрация: 27.3.2007 Где: St. Petersburg Репутация: 21 Всего: 32 |
IMHO, довольно опасный способ проверки. Например при создании секции такая проверка может показать неудачу, в то время как все успешно и мы получили на руки открытый Handle. Который еще и закрыть надо ![]() Я почему спрашиваю. Мы ведь в наших Dispatch функциях предполагаем многократное выделение/освобождение. Соответственно меня и интересует какой из способов работы с памятью лучше всего подходит для этого случая. С MmAllocateNonCachedMemory я еще не окончательно разобралась, но меня сильно смущает следующая фраза из MSDN: "A device driver that must use noncached memory should allocate only what it needs during driver initialization because nonpaged pool is likely to become fragmented as the system runs." Насчет же функций типа RtlAnsiStringToUnicodeString (а они предназначены для частого использования) , мое копательство в них показало, что они работают именно через Rtl-Heap. Поэтому я и говорила о "совместимости". Если бы BC функции тоже работали через Heap, то их можно было бы использовать "вперемежку" с Rtl-скими (проверяла в юзер-моде). P.S. Я ни в коем случае не спорю, а просто пытаюсь понять что к чему и с чем едят. Соответственно многие мои утверждения приведены не как контр-аргументы, а для того, чтобы мне показали ошибку в моих рассуждениях и пояснили "как надо на самом деле" ![]() Где еще найдешь бесплатное образование, кроме как не на таких форумах ![]() Это сообщение отредактировал(а) Riply - 9.9.2008, 17:26 |
|||
|
||||
ama_kid |
|
|||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
Ну вот сначала закрываем, а потом отлаживаем и разбираемся, что же мы получили ![]()
![]() Но вообще, режим ядра предоставляет гораздо большие возможности для работы с памятью, чем user-mode и на эту тему есть интересные статьи на Wasm.ru (главы "Работа с памятью"). Можешь почитать, если интересно... -------------------- самурай без меча подобен самураю с мечом, но только без меча |
|||
|
||||
Riply |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Комодератор Сообщений: 572 Регистрация: 27.3.2007 Где: St. Petersburg Репутация: 21 Всего: 32 |
||||
|
||||
ama_kid |
|
|||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 19 Всего: 95 |
-------------------- самурай без меча подобен самураю с мечом, но только без меча |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: WinAPI и системное программирование" | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |