驱动开发之五 --- TDI之十 【译文】

驱动开发之五 --- TDI之十 【译文】

转自 http://hi.baidu.com/combojiang/blog/item/c5920d2aab63bc28d42af1c8.html

/**/ /********************************************************************** 



* HandleIrp_RemoveNextIrp 



*    This function removes the next valid IRP. 



*********************************************************************
*/
 

PIRP HandleIrp_RemoveNextIrp(PIRPLISTHEAD pIrpListHead) 



    PIRP pIrp 
= NULL; 

    KIRQL kOldIrql; 

    PDRIVER_CANCEL pCancelRoutine; 

    PIRPLIST pIrpListCurrent; 


    KeAcquireSpinLock(
&pIrpListHead->kspIrpListLock, &kOldIrql); 

     

    pIrpListCurrent 
= pIrpListHead->pListFront; 


    
while(pIrpListCurrent && pIrp == NULL) 

    


        
/**//* 

         * To remove an IRP from the Queue we first want to 

       * reset the cancel routine. 

         
*/
 

        pCancelRoutine 
= IoSetCancelRoutine(pIrpListCurrent->pIrp, NULL); 


        
/**//* 

         * The next phase is to determine if this IRP has been canceled 

         
*/
 


        
if(pIrpListCurrent->pIrp->Cancel) 

        


            
/**//* 

             * We have been canceled so we need to determine if our 

             * cancel routine has already been called. pCancelRoutine 

             * will be NULL if our cancel routine has been called.   

             * If will not be NULL if our cancel routine has not been 

             * called. However, we don't care in either case and we 

             * will simply complete the IRP here since we have to implement at 

             * least that case anyway. 

             * 

             * Remove the IRP from the list. 

             
*/
 


            pIrpListHead
->pListFront = pIrpListCurrent->pNextIrp; 


            
if(pIrpListHead->pListFront == NULL) 

            


                pIrpListHead
->pListBack = NULL; 

            }
 


            KeReleaseSpinLock(
&pIrpListHead->kspIrpListLock, kOldIrql); 

             

            pIrpListCurrent
->pfnCleanUpIrp(pIrpListCurrent->pIrp, 

                                            pIrpListCurrent
->pContext); 


            DbgPrint(
"HandleIrp_RemoveNextIrp Complete Free Memory = 

                                               0x
%0x \r\n", pIrpListCurrent); 

            KMem_FreeNonPagedMemory(pIrpListCurrent); 

            pIrpListCurrent 
= NULL; 


            KeAcquireSpinLock(
&pIrpListHead->kspIrpListLock, 

                                                    
&kOldIrql); 

             

            pIrpListCurrent 
= pIrpListHead->pListFront; 


        }
 

        
else 

        


            pIrpListHead
->pListFront = pIrpListCurrent->pNextIrp; 


            
if(pIrpListHead->pListFront == NULL) 

            


                pIrpListHead
->pListBack = NULL; 

            }
 


            pIrp 
= pIrpListCurrent->pIrp; 


            KeReleaseSpinLock(
&pIrpListHead->kspIrpListLock, kOldIrql); 


            DbgPrint(
"HandleIrp_RemoveNextIrp Complete Free Memory = 0x%0x \r\n"

                                                          pIrpListCurrent); 

            KMem_FreeNonPagedMemory(pIrpListCurrent); 

            pIrpListCurrent 
= NULL; 


            KeAcquireSpinLock(
&pIrpListHead->kspIrpListLock, 

                                                      
&kOldIrql); 

             

        }
 

    }
 



    KeReleaseSpinLock(
&pIrpListHead->kspIrpListLock, kOldIrql); 


    
return pIrp; 

}
 



/**/ /********************************************************************** 



* HandleIrp_PerformCancel 



*    This function removes the specified IRP from the list. 



*********************************************************************
*/
 

NTSTATUS HandleIrp_PerformCancel(PIRPLISTHEAD pIrpListHead, PIRP pIrp) 



    NTSTATUS NtStatus 
= STATUS_UNSUCCESSFUL; 

    KIRQL kOldIrql; 

    PIRPLIST pIrpListCurrent, pIrpListPrevious; 


    KeAcquireSpinLock(
&pIrpListHead->kspIrpListLock, 

                                             
&kOldIrql); 

     

    pIrpListPrevious 
= NULL; 

    pIrpListCurrent 
= pIrpListHead->pListFront; 


    
while(pIrpListCurrent && NtStatus == STATUS_UNSUCCESSFUL) 

    


        
if(pIrpListCurrent->pIrp == pIrp) 

        


            
if(pIrpListPrevious) 

            


               pIrpListPrevious
->pNextIrp = pIrpListCurrent->pNextIrp; 

            }
 


            
if(pIrpListHead->pListFront == pIrpListCurrent) 

            


               pIrpListHead
->pListFront = pIrpListCurrent->pNextIrp; 

            }
 


            
if(pIrpListHead->pListBack == pIrpListCurrent) 

            


                pIrpListHead
->pListBack = pIrpListPrevious; 

            }
 


            KeReleaseSpinLock(
&pIrpListHead->kspIrpListLock, kOldIrql); 

             

            NtStatus 
= STATUS_SUCCESS; 


            
/**//* 

             * We are going to allow the clean up function to complete the IRP. 

             
*/
 

            pIrpListCurrent
->pfnCleanUpIrp(pIrpListCurrent->pIrp, 

                                              pIrpListCurrent
->pContext); 


            DbgPrint(
"HandleIrp_PerformCancel Complete Free Memory = 0x%0x \r\n"

                                                              pIrpListCurrent); 


            KMem_FreeNonPagedMemory(pIrpListCurrent); 


            pIrpListCurrent 
= NULL; 


            KeAcquireSpinLock(
&pIrpListHead->kspIrpListLock, 

                                                     
&kOldIrql); 


       }
 

        
else 

        


            pIrpListPrevious 
= pIrpListCurrent; 

            pIrpListCurrent 
= pIrpListCurrent->pNextIrp; 

        }
 

    }
 



    KeReleaseSpinLock(
&pIrpListHead->kspIrpListLock, kOldIrql); 


    
return NtStatus; 

}
 

/**/ /********************************************************************** 



* TdiExample_CancelRoutine 



*    This function is called if the IRP is ever canceled 



*    CancelIo() from user mode, IoCancelIrp() from the Kernel 



*********************************************************************
*/
 

VOID TdiExample_CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP pIrp) 



    PIRPLISTHEAD pIrpListHead 
= NULL; 


    
/**//* 

     * We must release the cancel spin lock 

     
*/
 


    IoReleaseCancelSpinLock(pIrp
->CancelIrql); 

     

    DbgPrint(
"TdiExample_CancelRoutine Called IRP = 0x%0x \r\n", pIrp); 


    
/**//* 

     * We stored the IRPLISTHEAD context in our DriverContext on the IRP 

     * before adding it to the queue so it should not be NULL here. 

     
*/
 


    pIrpListHead 
= (PIRPLISTHEAD)pIrp->Tail.Overlay.DriverContext[0]; 

    pIrp
->Tail.Overlay.DriverContext[0= NULL; 

     

    
/**//* 

     * We can then just throw the IRP to the PerformCancel 

     * routine since it will find it in the queue, remove it and 

     * then call our clean up routine. Our clean up routine 

     * will then complete the IRP. If this does not occur then 

     * our completion of the IRP will occur in another context 

     * since it is not in the list. 

     
*/
 

    HandleIrp_PerformCancel(pIrpListHead, pIrp); 


}
 


/**/ /********************************************************************** 



* TdiExample_IrpCleanUp 



*    This function is called to clean up the IRP if it is ever 

*    canceled after we have given it to the queueing routines. 



*********************************************************************
*/
 

VOID TdiExample_IrpCleanUp(PIRP pIrp, PVOID pContext) 



    pIrp
->IoStatus.Status      = STATUS_CANCELLED; 

    pIrp
->IoStatus.Information = 0

    pIrp
->Tail.Overlay.DriverContext[0= NULL; 

    DbgPrint(
"TdiExample_IrpCleanUp Called IRP = 0x%0x \r\n", pIrp); 


    IoCompleteRequest(pIrp, IO_NO_INCREMENT); 

}
 

你可能感兴趣的:(驱动开发之五 --- TDI之十 【译文】)