The following is a list of precautions that developers should avoid when using the Windows NT Device Driver:
1. Do not return status_pending through the scheduling routine without marking the iomarkirppending.
2. Do not call kesynchronizeexecution through the interrupt service routine (ISR. It causes a system deadlock.
3. Do not set deviceobject-> flags to do_buffered_io and do_direct_io. It will disrupt the system and eventually lead to fatal errors. In addition, do not set method_buffered, method_neither, method_in_direct, or method_out_direct in deviceobject-> flags, because these values are only used when IOCTL is defined.
4. Do not assign scheduling program objects through the page buffer pool. If this is done, it will occasionally lead to system fault detection (bugcheck ).
5. When running on IRQL> = dispatch_level, do not allocate memory through the page buffer pool or access the memory in the page buffer pool. This is a fatal error.
6. Do not wait for the non-zero interval of the core scheduler object on IRQL> = dispatch_level. This is a fatal error.
7. When executing on IRQL> = dispatch_level, do not call any function that causes the calling thread to wait directly or indirectly. This is a fatal error.
8. Do not reduce the interrupt request level (IRQL) to a level lower than that called by your top-level routine.
9. If keraiseirql () has not been called, do not call kelowerirql ().
10. Do not stop the processor for more than 50 microseconds.
11. Do not keep the spin lock locked for more time than you need. To improve the overall performance of the system, do not lock effective rotation locks in any system range for more than 25 microseconds.
12. When IRQL is greater than dispatch_level, do not call keacquirespinlock and kereleasespinlock, or keacquirespinlockatdpclevel and kereleasespinlockfromdpclevel.
13. Do not call kereleasespinlockfromdpclevel to release the rotation lock obtained by keacquirespinlock because it will make the original IRQL unrecoverable.
14. Do not call keacquirespinlock and kereleasespinlock in ISR or synchcritsection routines or any other routine that uses the executable rotation lock.
15. When you create a device object in a routine instead of in DriverEntry, do not forget to clear the do_device_initializing tag.
16. Do not add the delayed Procedure Call (DPC) object to the queue (using keinsertqueuedpc) in multiple threads of different processors at the same time ). This can cause fatal errors.
17. Do not release the cycle timer through the cutomertimerdpc routine. You can release a non-cyclic timer through the DPC routine.
18. Do not pass the same DPC pointer to the kesettimer, or the kesettimerex (customtimerdpc) and keinsertqueuedpc (customdpc), because this will lead to competition.
19. Do not call iostartnextpacket when rotating the lock. This will cause a system deadlock.
20. Do not call iocompleterequest when rotating the lock. This will cause a system deadlock.
21. If your driver has set the completion routine, do not call iocompleterequest without setting the completion routine to null.
22. Before calling iocompleterequest, do not forget to set the I/O status zone in the IRP.
23. Do not call iomarkpending after adding IRP to the queue or sending it to another driver (iocalldriver. Before the driver calls iomarkpending, the IRP may have been completed, and fault detection may occur. For drivers that contain completion routines, if IRP-> pendingreturned is set, the completion routine must call iomarkpending.
24. Do not access a certain IRP after calling iocompleterequest.
25. Do not call iocancelirp for IRPs that do not belong to your driver unless you know that the IRP has not been completed.
26. Before your scheduling routine returns to the caller, do not perform IRP calls that are being processed by your scheduling routine.
55. Do not use iobuildsynchronousfsdrequest/iobuilddeviceiocontrolrequest in any thread context to allocate IRP, because the IRP is still associated with the thread (IRP-> threadlistentry) until it is released.
56. If ioallocateirp has been used to allocate an IRP when the chargequota parameter is set to true, do not call ioinitializeirp for this IRP. If an IRP is assigned when chargequota is set to true, the I/O manager saves the information about the buffer pool used when it allocates memory for the IRP in the internal tag of the IRP.
If ioinitializeirp is called for such IRPs, the allocation pool information will be lost when the function blindly clears the entire IRPs. When you release the IRP, the memory will be damaged. At the same time, do not reuse IRP from the IO manager. To reuse IRP, you should use ioallocateirp to allocate your own IRP.
57. If an object is assigned to the stack of the call thread, do not specify waitmode as usermode in kewaitforsingleobject/kewaitformultipleobjects. The result is that if the waiting object is created in the function stack, you must specify waitmode as kernelmode to prevent the thread from being scheduled by the page.
58. do not obtain resources such as eresources and fastmutex (unsafe) in the context of the user mode thread without protecting the code in key sections.
Because obtaining these resources does not increase IRQL to apc_level, if the thread is suspended after obtaining the resources (implemented by adding APC to the queue), it may lead to a deadlock, and reduce system security. Therefore, IRQL should be explicitly raised to apc_level, or keentercriticalregion should be called to enter key segments, and then these resources can be obtained.