Книга: Writing Windows WDM Device Drivers

Processing Commands

Processing Commands

Critical Sections

The IOCTL_PHDIO_RUN_CMDS IOCTL is used to run a set of commands straightaway. Eventually the ProcessCmds routine is run to process the commands. ProcessCmds is fairly straightforward and so is not listed here. It is in DeviceIo.cpp on the book CD-ROM. Suffice to say, it is passed parameters to its input and output buffers, together with their length. It also has a CanTrace bool parameter that dictates whether its DebugPrint trace statements can be run safely.

However, there are a couple of hurdles to overcome before IOCTL_PHDIO_RUN_CMDS can call ProcessCmds.

The first hurdle is that the IOCTL input and output buffers use the same block of memory. While this is a jolly useful technique for saving memory in the first stage of IOCTL processing, it means that some nonpaged memory must be allocated for the output data. The output data is copied back to the shared buffer and the temporary memory freed. The RunCmds routine performs this task[39].

If WdmIo has not connected to a hardware interrupt, the IOCTL_PHDICLRUN_CMDS handler in Listing 16.2 simply calls RunCmds. However, if the device extension ConnectedToInterrupt field is true, an interrupt may occur that could scupper any command processing. This problem is overcome by calling RunCmds in the context of a Critical Section. To recap, a Critical Section routine runs at Device IRQL (DIRQL) and so cannot be interrupted (by our interrupt at least).

In this case, the IOCTL_PHDIO_RUN_CMDS handler calls KeSynchronizeExecution to run the RunCmdsSynch routine as a Critical Section. RunCmdsSynch just calls RunCmds with the CanTrace parameter set to false. Both RunCmdsSynch and RunCmds return FALSE if they can not allocate enough memory for the output buffer.

Listing 16.3 RunCmdsSynch and RunCmds

BOOLEAN RunCradsSynch(IN PDEVICE_OBJECT fdo) {
 return RunCmds(fdo, false);
}
BOOLEAN RunCmds(IN PDEVICE_OBJECT fdo, IN bool CanTrace) {
 PWDMIO_DEVICE_EXTENSION dx = (PWDMIO_DEVICE_EXTENSION)fdo->DeviceExtension;
 PIRP Irp = fdo->CurrentIrp;
 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
 ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
 ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
 PUCHAR Buffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
 PUCHAR OutBuffer = NULL;
 if (OutputLength>0) {
  OutBuffer = (PUCHAR)ExAllocatePool(NonPagedPool.OutputLength);
  if (OutBuffer==NULL) return FALSE;
 }
 ProcessCmds(dx, Buffer, InputLength, OutBuffer, OutputLength, CanTrace);
 if (OutBuffer!=NULL) {
  RtlMoveMemory(Buffer, OutBuffer, OutputLength);
  ExFreePool(OutBuffer);
 }
 return TRUE;
}

Оглавление книги


Генерация: 0.926. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз