Программирование драйверов Windows

       

Функции для работы со ссылками на объекты


В некоторых ситуациях необходимо получать доступ к объектам режима ядра. В операционной системе Windows объектами представлены многие компоненты: программные потоки, объекты синхронизации, файловые объекты, драйверы, устройства, объекты DPC процедур, прерываний и т.п. Правильнее говорить, что эти явления представлены структурами данных для удобства ведения их учета. Структуры эти в полной мере (например, в смысле ООП) объектами не являются. У них нет конструкторов, деструкторов, виртуальных методов в привычном смысле С++. Тем не менее, понятие "объект" широко используется и, в некотором смысле, справедливо &#8212 оперировать этими структурами предпочтительнее специально для того предназначенными системными вызовами, которые и можно считать методами для данных объектов.

Рассмотрим пример, в котором объектом синхронизации является программный поток. Программные потоки могут своим окончанием сигнализировать другим программным потокам о том, что пора приступать к работе. В частности, программный поток может быть запущен вызовом PsCreateSystemThread (см. главу 10). Другой поток может дожидаться его окончания, организовав ожидание при помощи одного из вызовов KeWaitForXxx. Возникает небольшое затруднение. Системный вызов PsCreateSystemThread, создавая поток, возвращает его дескриптор (HANDLE), a функции KeWaitForXxx принимают в качестве входного аргумента указатель на объект, по состоянию которого организуется ожидание.

Выход состоит в использовании вызова ObReferenceObjectByHandle, который в состоянии по корректному дескриптору возвратить указатель на соответствующий ему объект. Прототип ее вызова описан ниже.

Таблица 7.41. Прототип вызова ObReferenceObjectByHandle

NTSTATUS ObReferenceObjectByHandle IRQL == PASSIVE_LEVEL
Параметры Предоставляет указатель на объект режима ядра по открытому дескриптору
IN HANDLE Handle Исходный дескриптор объекта
IN ACCESS_MASK

DesiredAccess

Маска доступа, интерпретация которой зависит от типа рассматриваемого объекта
IN POBJECT_TYPE ObjectType

OPTIONAL

Можно установить NULL (если параметр AccessMode равен KernelMode) или одно из значений IoFileObjectType

or ExEventObjectType

IN KPROCESSOR_MODE

AccessMode

KernelMode &#8212 для работы в режиме ядра

UserMode

OUT PVOID *ppObject Указатель на переменную типа PVOID, в которой будет возвращен указатель, соответствующий исходному дескриптору
OUT POBJECT_HANDLE_INFORMATION Handlelnfо OPTIONAL Указатель на структуру, в которой будет представлена дополнительная информация об объекте и правам доступа к нему
Возвращаемое значение • STATUS_SUCCESS

• STATUS_OBJECT_TYPE_MISMATCH

• STATUS_ACCESS_DENIED

• STATUS_INVALID_HANDLE

<
Следует отметить, что в результате выполнения системного вызова ObReferenceObjectByHandle, увеличивается на единицу счетчик ссылок на этот объект, который поддерживается операционной системой.

Общим правилом операционной системы является то, что счетчик ссылок поддерживается для каждого объекта режима ядра, и когда он уменьшается до нуля, происходит уничтожение объекта. В некоторых ситуациях, как раз необходимо произвести увеличение счетчика ссылок на объект, чтобы продлить ему жизнь. В режиме ядра более распространен способ работы с объектами через указатели на них. Поэтому, если необходимо увеличить счетчик ссылок на объект, но в распоряжении имеется только указатель на него &#8212 не беда. На этот случай существует системный вызов ObReferenceObjectByPointer, который увеличивает ссылку на объект, используя в качестве исходных данных указатель, а не дескриптор.

Таблица 7.42. Прототип вызова ObReferenceObjectByPointer

NTSTATUS ObReferenceObjectByPointer IRQL == PASSIVE_LEVEL
Параметры Предоставляет указатель на объект режима ядра по открытому дескриптору
IN PVOID pObject Указатель на объект
IN ACCESS_MASK DesiredAccess Маска доступа, интерпретация которой зависит от типа рассматриваемого объекта
IN POBJECT_TYPE ObjectType

OPTIONAL
Можно установить NULL (если параметр AccessMode равен KernelMode) или одно из значений IoFileObjectType

or ExEventObjectType
IN KPROCESSOR_MODE AccessMode KernelMode &#8212 для работы в режиме ядра

UserMode
Возвращаемое значение • STATUS_SUCCESS

• STATUS_OBJECT_TYPE_MISMATCH
Вернемся к случаю с ожиданием, организованным по объекту программного потока одним из вызовов KeWaitForXxx. Когда поток завершился, ожидание прекращено. При этом объект потока еще не уничтожен, поскольку в результате вызова ObReferenceObjectByHandle получилось так, что число ссылок на него не равно нулю. Это положение можно изменить, если уменьшить число ссылок при помощи вызова ObDereferenceObject, что, вероятно, приведет и к удалению объекта потока из системы.



Таблица 7.43. Прототип вызова ObDereferenceObject

VOID ObDereferenceObject IRQL == PASSIVE_LEVEL
Параметры Уменьшает счетчик ссылок на объект
IN PVOID pObject Указатель на объект
Возвращаемое значение void
Заметим, что при выполнении вызова ZwClose происходит автоматическое уменьшение счетчика ссылок на объект и проверка, не пора ли его удалить из системы.


Содержание раздела