Создание VxD на Visual C++ без ассемблерных модулей - Некоторые функции-обертки, определенные в VXDWRAPS

ОГЛАВЛЕНИЕ

 

Некоторые функции-обертки, определенные в VXDWRAPS

Out_Debug_String - вывод отладочного сообщения void Out_Debug_String (char *String);

  • String — указатель строки, выводимой в отладочный поток. Для перехода на новую строку используется символ '\n".

Системный отладочный поток можно просматривать отладчиками WDEB386, SoftICE, а также любым отладочным монитором.

_Sprintf - форматирование строки ULONG _Sprintf (char *Buffer, char *Format, ...);Функция аналогична стандартной функции sprintf языка C.

К сожалению, VMM не предоставляет функции, аналогичной vsprintf, поэтому для реализации функций целевого назначения, в основе которых лежит спецификация формата и список аргументов переменной длины (например, функций отладочного вывода или формирования строк специального вида), приходится использовать _Sprintf, копируя переменную часть списка аргументов (например, 10-20 двойных слов) из стекового кадра целевой функции.

Пример построения функции-обертки

Поскольку сервисная функция VMM _SelectorMapFlat не имеет стандартной обертки, возможная функция-обертка для нее могла бы выглядеть следующим образом:

#pragma warning (disable: 4035) // Блокировка предупреждения о невозврате

_declspec (naked)
void *SelectorMapFlat (DWORD VM, DWORD Sel, DWORD Rsv = 0) {

VMMJmp (_SelectorMapFlat) // Передача управления VMM

(void)(VM, Sel, Rsv); // Имитация использования параметров

}

#pragma warning (default: 4035) // Восстановление предупреждений о невозврате

Квалификатор _declspec (naked) подавляет генерацию пролога/эпилога, так что от функции остается лишь конструкция VMMJmp. При вызове этой функции-обертки параметры VM, Sel и Rsv помещаются в стек, затем туда же помещается адрес возврата, управление передается в функцию-обертку, при этом VMMJmp передает управление сервисной функции VMM _SelectorMapFlat, не запоминая нового адреса возврата в стеке. VMM использует значения параметров из стека, затем выполняет возврат по адресу, находящемуся на верхушке стека, при этом управление сразу возвращается в точку за вызовом функции-обертки, где находится код, удаляющий из стека параметры и использующий значение, возвращенное VMM в EAX.

Такая схема типична для построения функций-оберток, так как в полной мере использует особенности создания стекового кадра в языках C, а также возможности компилятора Visual C++ по оформлению функций. Без использования VMMJmp пришлось бы делать возврат дважды, а без использования квалификатора naked — дважды помещать в стек список параметров.