…

 0004:00000492 ?PnpDefaultHandler@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z 00012512 f pnp.obj

 0004:00000591 ?ForwardAndWait@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z    00012611 f pnp.obj

Conclusion

Please test your driver well before releasing it. You must check that your driver works on a variety of computers. It must cope with user mode program aborts.

Debugging drivers is harder than user mode applications. In the worst case, a bugcheck occurs that tells you roughly what went wrong. Resource leaks and timing problems are more difficult to sort out.

The DebugPrint software lets you insert 'print' statements into your driver code. You can do source-level debugging between two computers using WinDbg, or on a single computer using the NuMega SoftICE product.

The next chapter looks at the dispatch routines in the Wdm1 device driver. 

Chapter 7

Dispatch Routines

This chapter looks at how to write driver dispatch routines that process I/O Request Packets (IRPs). Dispatch routines are used to handle requests from Win32 applications. It is crucial that you understand everything in this chapter clearly. If necessary, refer to Chapter 3 where IRPs are first introduced.

The dispatch routines for the Wdm1 driver are explained in full. These handle open, close, read, write, and IOCTL requests. The Wdm1 driver implements a global memory buffer that is shared by all Wdm1 devices.

This chapter takes a good hard look at I/O Request Packets (IRPs). It is worth reading this chapter carefully, as a good understanding of IRPs will ease your passage through the rest of the book.

Dispatch Routine IRPs

Table 7.1 lists the most common Win32 functions that are used to access devices. A CreateFile call to your device ends up as a Create IRP, an I/O Request Packet with a major function code of IRP_MJ_CREATE. The driver routine to handle this IRP can have any name. However, I use a generic name for the Create IRP handler of Create. In your driver, you would usually put a short name or acronym in front of this base name. The Wdm1 device driver's Create IRP handler is called Wdm1Create.

Table 7.1 is not an exhaustive list of Win32 functions and their matching IRPs. For example, ReadFile has several variants, such as ReadFileEx, but they all end up as IRP_MJ_READ requests. IRPs can also be issued by Windows on behalf of the user program. For example, if an application terminates unexpectedly, the operating system will try to tidy any open files by issuing an IRP_MJ_CLOSE IRP to each file.

Table 7.1 Common dispatch routines

Win32 Function IRP Major Code Base Driver routine name
CreateFile IRP_MJ_CREATE Create
CloseHandle IRP_MJ_CLOSE Close
ReadFile IRP_MJ_READ Read
WriteFile IRP_MJ_WRITE Write
DeviceIoControl IRP_MJ_DEVICE_CONTROL DeviceControl

A driver need not handle all these IRPs, though handling Create and Close IRPs is an obvious minimum. Its DriverEntry routine sets up the entry points that are valid. If an entry point is not set, then the I/O Manager fails the Win32 request and GetLastError returns 1.

The following line in DriverEntry sets the Wdm1Read routine as the handler for Read IRPs.

DriverObject->MajorFunction[IRP_MJ_READ] = Wdm1Read;

I/O Request Packets

Dispatch Routine Handling

All dispatch routines have the same function prototype. The function is passed a pointer to your device object and the IRP. The function must return a suitable NTSTATUS value (e.g., STATUS_SUCCESS).

NTSTATUS Wdm1Read( IN PDEVICE_OBJECT fdo. IN PIRP Irp)

A dispatch routine is usually called at PASSIVE_LEVEL IRQL. (This is a bit unexpected, as you might expect dispatch routines to run at DISPATCH_LEVEL IRQL.) Running at PASSIVE_ LEVEL means that a dispatch routine can very easily be interrupted by other parts of the kernel or even your own driver. However, a routine that runs at PASSIVE_LEVEL can issue most kernel calls, including writing to other files.

A dispatch routine can be called at DISPATCH_LEVEL if a higher level driver calls you at this IRQL level. This might happen if it calls you from a completion routine, as described in Chapter 9. If you think this might be happening, then assume that your driver dispatch routines are running at DISPATCH_LEVEL

Dispatch routines run in an arbitrary thread context. As well as standard user mode threads, the kernel has its own threads that run only in kernel mode. Although your IRP will have originated in one of these threads, you cannot guarantee that you arc running in its context. This means that a valid address in the originating thread may not be valid when your driver sees it. A later section in this chapter shows how to access user buffers correctly.

Reentrancy

A dispatch routine must be reentrant. This means that it may be called 'simultaneously' to process two separate IRPs. In a multiprocessor Windows 2000 system, one processor could call Wdm1Read with one IRP, and a second process on another CPU could also call Wdm1Read simultaneously with another IRP. However, do not dismiss reentrancy as some arcane requirement that your driver will never encounter. In Windows 98, the single processor could start running Wdm1Read to handle a first IRP.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×