Функции для работы со ссылками на объекты
В некоторых ситуациях необходимо получать доступ к объектам режима ядра. В операционной системе Windows объектами представлены многие компоненты: программные потоки, объекты синхронизации, файловые объекты, драйверы, устройства, объекты DPC процедур, прерываний и т.п. Правильнее говорить, что эти явления представлены структурами данных для удобства ведения их учета. Структуры эти в полной мере (например, в смысле ООП) объектами не являются. У них нет конструкторов, деструкторов, виртуальных методов в привычном смысле С++. Тем не менее, понятие "объект" широко используется и, в некотором смысле, справедливо — оперировать этими структурами предпочтительнее специально для того предназначенными системными вызовами, которые и можно считать методами для данных объектов.
Рассмотрим пример, в котором объектом синхронизации является программный поток. Программные потоки могут своим окончанием сигнализировать другим программным потокам о том, что пора приступать к работе. В частности, программный поток может быть запущен вызовом 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 — для работы в режиме ядра • UserMode |
OUT PVOID *ppObject | Указатель на переменную типа PVOID, в которой будет возвращен указатель, соответствующий исходному дескриптору |
OUT POBJECT_HANDLE_INFORMATION Handlelnfо OPTIONAL | Указатель на структуру, в которой будет представлена дополнительная информация об объекте и правам доступа к нему |
Возвращаемое значение | • STATUS_SUCCESS • STATUS_OBJECT_TYPE_MISMATCH • STATUS_ACCESS_DENIED • STATUS_INVALID_HANDLE |
Следует отметить, что в результате выполнения системного вызова ObReferenceObjectByHandle, увеличивается на единицу счетчик ссылок на этот объект, который поддерживается операционной системой.
Общим правилом операционной системы является то, что счетчик ссылок поддерживается для каждого объекта режима ядра, и когда он уменьшается до нуля, происходит уничтожение объекта. В некоторых ситуациях, как раз необходимо произвести увеличение счетчика ссылок на объект, чтобы продлить ему жизнь. В режиме ядра более распространен способ работы с объектами через указатели на них. Поэтому, если необходимо увеличить счетчик ссылок на объект, но в распоряжении имеется только указатель на него — не беда. На этот случай существует системный вызов 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 — для работы в режиме ядра • UserMode |
Возвращаемое значение | • STATUS_SUCCESS • STATUS_OBJECT_TYPE_MISMATCH |
Таблица 7.43. Прототип вызова ObDereferenceObject
VOID ObDereferenceObject | IRQL == PASSIVE_LEVEL |
Параметры | Уменьшает счетчик ссылок на объект |
IN PVOID pObject | Указатель на объект |
Возвращаемое значение | void |