Использование NuMega DriverStudio для написания WDM-драйверов | страница 34



>VOID XDSPdrvDevice::StartIo(KIrp I) {

> t << "Entering StartIo, " << I << EOL;

> // Здесь надо проверить, отменен этот запрос или нет. Это производится при помощи вызова

> //метода TestAndSetCancelRoutine. Также этот метод устанавливает новую функцию отмены

> //пакетов, если это необходимо. Адрес новой функции передается вторым параметром. Если

> //он равен NULL,то вызывается старая функция. Если пакет должен быть отменен, функция

> //вернет FALSE.

> if (!I.TestAndSetCancelRoutine(LinkTo(CancelQueuedIrp), NULL, CurrentIrp())) {

>  //Пакет отменен.

>  return;

> }

> // Начать обработку запроса.

> // Выбрать необходимую функцию

> switch (I.MajorFunction()) {

> case IRP_MJ_READ:

>  //Чтение

>  SerialRead(I);

>  break;

> case IRP_MJ_WRITE:

>  //Запись

>  SerialWrite(I);

>  break;

> case IRP_MJ_DEVICE_CONTROL:

>  //IOCTL

>  switch (I.IoctlCode()) {

>  default:

>   //Мы обрабатываем пакет, который не должен быть обработан.

>   //Поэтому просто выходим.

>   ASSERT(FALSE);

>   break;

>  }

>  break;

> default:

>  // Драйвер занес в очередь какой-то непонятный пакет,

>  //он не должен быть обработан.

>  ASSERT(FALSE);

>  PnpNextIrp(I);

>  break;

> }

>}

Метод Create вызывается, когда пользовательское приложение пытается установить связь с драйвером при помощи вызова API CreateFile(). Обычно этот запрос обрабатывается в нашем объекте устройства и нет смысла пересылать запрос устройству нижнего уровня.

>NTSTATUS XDSPdrvDevice::Create(KIrp I) {

> NTSTATUS status;

> t << "Entering XDSPdrvDevice::Create, " << I << EOL;

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

> //приложением связи с устройством.

> status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);

> t << "XDSPdrvDevice::Create Status " << (ULONG)status << EOL;

> return status;

>}

Аналогично метод Close вызывается при разрыве связи приложения с драйвером.

>NTSTATUS XDSPdrvDevice::Close(KIrp I) {

> NTSTATUS status;

> t << "Entering XDSPdrvDevice::Close, " << I << EOL;

> //Здесь можно вставить код пользователя, который должен быть вызван при разрыве

> //приложением связи с устройством.

> status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);

> t << "XDSPdrvDevice::Close Status " << (ULONG)status << EOL;

> return status;

>}

В этих методах можно ввести проверки каких-либо условий. Отвлечемся на секунду от нашей PCI-карточки и обратим внимание на другой хороший пример — тот же программатор микроконтроллеров. Предположим, пользователь подключил программатор к компьютеру и начинает записывать в память микроконтроллера разработанную им программу. В принципе, ничто не помешает ему открыть еще одну копию программы и писать в ту же микросхему что-то совсем другое. В результате, в эту несчастную микросхему запишется невообразимая каша. Для того, чтобы избежать такой ситуации, в объекте драйвера надо установить флаг, который будет показывать, свободно ли это устройство, или оно уже кем-то используется. Это может выглядеть так: