Иллюстрированный самоучитель по Pogramming Sistem Security


Функции управления очередью низкого уровня - часть 2


KelnitializeSpinLock (& (pDeviceExtension->ListLock) ) ;

//после этого можно добавлять и удалять записи

PLIST_ENTRY pOldHead = ExInterlockedlnsertHeadList ( & (pDeviceExtension->ListHead) , pNewListEntry, & (pDeviceExte'nsion->ListLock) ) ;

Как видно из определения структуры LIST_ENTRY, она не содержит полей для хранения собственно данных (например, указателя на пакет IRP). Поэтому распространенный способ использования структуры LIST_ENTRY - включение ее экземпляра в состав более общей структуры.

Для организации очереди пакетов IRP, в каждом пакете IRP в поле Tail.Over-lay.ListEntry содержится экземпляр структуры LIST_ENTRY. При этом встает вопрос, как, зная указатель на структуру LIST_ENTRY, получить указатель на структуру IRP, в состав которой входит LIST_ENTRY. Для этого DDK предоставляет специальный макрос CONTAINING_RECORD:

#define CONTAINING_RECORD (address, type, field) \

((type *) ( (PCHAR) (address) - (ULONG_PTR) (&((type *) 0) ->f ield) ) )

Где: Address - Известный адрес некоторого поля структуры, адрес которой необходимо получить;

Туре - Тип структуры, адрес которой необходимо получить;

Field- Имя поля внутри искомой структуры, адрес этого поля передан в параметре address.

Применительно к IRP, мы должны будем написать что-то вроде:

PListEntry = ExInterlockedRemoveHeadList ( & (pDeviceExtension->ListHead) , & (pDeviceExtension->ListLock) ) ;

plrp = CONTAINING_RECORD(pListEntry, IRP, Tail. Overlay. ListEntry) ; //далее - обработка IRP

Организация очереди пакетов IRP показана на рис. 12.

Рис. 12




- Начало -  - Назад -  - Вперед -