Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ДП.docx
Скачиваний:
11
Добавлен:
23.09.2019
Размер:
4.64 Mб
Скачать

2.4.3 Процедура AddDevice

В архитектуре WDM у драйвера имеется спе­циальная функция AddDevice, которую РnР Manager вызывает для каждого устройства. Данная процедура вызывается для создания и инициализации функционального объекта устройства (FDO). Для удобства и большей читабельности данная процедура разбита на три части. Первый вызов – AddDevice, из AddDevice вызывается CreateDeviceObject, а из CreateDeviceObject вызывается CreateSymbolicLink.

В AddDevice DriverObject – указатель на объект драйвера; PhysicalDeviceObject – указатель на объект устройства, созданного драйвером шины.

NTSTATUS AddDevice(

IN PDRIVER_OBJECT DriverObject,

IN PDEVICE_OBJECT PhysicalDeviceObject

)

{

NTSTATUS ntStatus = STATUS_SUCCESS;

PDEVICE_OBJECT deviceObject = NULL;

PDEVICE_EXTENSION deviceExtension;

USBD_VERSION_INFORMATION versionInformation;

ULONG i;

// Пытаемся создать функциональный объект устройства

ntStatus =

CreateDeviceObject(DriverObject, PhysicalDeviceObject, &deviceObject);

// В случае успеха

if (NT_SUCCESS(ntStatus)) {

deviceExtension = deviceObject->DeviceExtension;

deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

// Поддержка прямого (DIRECT IO) ввода/вывода для операций чтения/записи

deviceObject->Flags |= DO_DIRECT_IO;

// Устанавливаем флаг, так как во время запуска устройства вызов

// GetDescriptors() завершится неудачей

deviceObject->Flags |= DO_POWER_PAGABLE;

// Осуществляем инициализацию структуры расширения устройства

// Запоминаем физический объект устройства

deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;

// И присоединяем к стеку

deviceExtension->TopOfStackDeviceObject =

IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);

// Создаем копию структуры параметров устройства (DEVICE_CAPABILITIES) в

// нашей структуре расширения устройства

QueryCapabilities(PhysicalDeviceObject,

&deviceExtension->DeviceCapabilities);

// Настраиваем параметры энергопотребления

deviceExtension->PowerDownLevel = PowerDeviceUnspecified;

for (i=PowerSystemSleeping1; i<= PowerSystemSleeping3; i++)

{

if ( deviceExtension->DeviceCapabilities.DeviceState[i] < PowerDeviceD3 )

deviceExtension->PowerDownLevel = deviceExtension->DeviceCapabilities.

DeviceState[i];

}

// Сохраняем кол-во обрабатываемых пакетов ввода/вывода в расширении

// устройства. Впоследствии данный счетчик увеличивается для каждого нового // полученного IRP и уменьшается для каждого обработанного или пропущенного // IRP. Счетчик необходим для правильной обработки IRP_MN_REMOVE_DEVICE

IncrementIoCount(deviceObject);

}

USBD_GetUSBDIVersion(&versionInformation);

if( NT_SUCCESS( ntStatus ) )

{

NTSTATUS actStat;

// Повышаем уровень энергопотребления устройства

actStat = SelfSuspendOrActivate( deviceObject, FALSE );

}

return ntStatus;

}

// ========================================================================

// Именно в данной функции создаем FDO

NTSTATUS CreateDeviceObject(

IN PDRIVER_OBJECT DriverObject,

IN PDEVICE_OBJECT PhysicalDeviceObject,

IN PDEVICE_OBJECT *DeviceObject

)

{

NTSTATUS ntStatus;

UNICODE_STRING deviceLinkUnicodeString;

PDEVICE_EXTENSION deviceExtension;

USHORT i;

UNICODE_STRING pdoUniCodeName;

WCHAR pdoName[] = L"\\Device\\DACAL_DC_300";

UNICODE_STRING DeviceLinkUniCodeString;

WCHAR DeviceLinkName[] = L"\\DosDevices\\DACAL_DC_300";

RtlInitUnicodeString (&pdoUniCodeName, pdoName); // Создаем UNICODE-имя

ntStatus = CreateSymbolicLink( PhysicalDeviceObject, &deviceLinkUnicodeString );

if (NT_SUCCESS(ntStatus)) {

ntStatus = IoCreateDevice (DriverObject,

sizeof (DEVICE_EXTENSION),

&pdoUniCodeName,

FILE_DEVICE_UNKNOWN,

0,

FALSE,

DeviceObject);

if (NT_SUCCESS(ntStatus)) {

deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);

}

if (!NT_SUCCESS(ntStatus)) {

return ntStatus;

}

RtlInitUnicodeString (&DeviceLinkUniCodeString, DeviceLinkName);

ntStatus = IoCreateSymbolicLink(&DeviceLinkUniCodeString, &pdoUniCodeName);

// Максимальный размер пересылаемых данных за запрос вводы/

deviceExtension->MaximumTransferSize = ISO_MAX_TRANSFER_SIZE ;

// Копируем имя нашего устройства в структура расширения устройства

RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,

deviceLinkUnicodeString.Buffer,

deviceLinkUnicodeString.Length);

// Инициализируем события

KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);

KeInitializeEvent(&deviceExtension->SelfRequestedPowerIrpEvent, NotificationEvent, FALSE);

KeInitializeEvent(&deviceExtension->NoPendingIoEvent, NotificationEvent, FALSE);

// Освобождаем строковый буфер

RtlFreeUnicodeString( &deviceLinkUnicodeString );

}

return ntStatus;

}

// ========================================================================

// Данная функция вызывается для создания и инициализации GUID-

// символической ссылки на наше устройство, дабы из пользовательского

// режима можно было работать с манипулятором (handle) устройства

NTSTATUS CreateSymbolicLink(

IN PDEVICE_OBJECT DeviceObject,

IN OUT PUNICODE_STRING deviceLinkUnicodeString

)

{

NTSTATUS ntStatus = STATUS_SUCCESS;

// Создаем символическую ссылку

// Вызов IoRegisterDeviceInterface регистрирует интерфейс устройства и,

// таким образом, драйвер будет «доступен» для приложений пользовательского // режима или иных системных компонентов

ntStatus = IoRegisterDeviceInterface(

DeviceObject,

(LPGUID)& GUID_CLASS_DACAL_DC_300,

NULL,

deviceLinkUnicodeString);

if (NT_SUCCESS(ntStatus)) {

// Вызов IoSetDeviceInterfaceState активирует или деактивирует предыдущие

// зарегистрированные интерфейсы устройства. Приложения и системные

// компоненты могут открыть только активированный (доступный) интерфейс

ntStatus = IoSetDeviceInterfaceState(deviceLinkUnicodeString, TRUE);

}

return ntStatus;

}