Windows驱动编程关于IRP串行处理的一些函数的说明

typedef struct _KDEVICE_QUEUE {                                        //IRP队列来实现串行  
CSHORT Type;  
CSHORT Size;  
LIST_ENTRY devicelisthead;  
KSPIN_LOCK Lock;  
BOOLEAN Busy;  
} KDEVICE_QUEUE, *PKDEVICE_QUEUE, *RESTRICTED_POINTER PRKDEVICE_QUEUE;

typedef struct _KDEVICE_QUEUE_ENTRY{
    LIST_ENTRY DeviceListEntry;
    ULONG SortKey;
    BOOLEAN Inserted;
}KDEVICE_QUEUE_ENTRY, *PKDEVICE_QUEUE_ENTRY, *RESTRICTED_POINTER PRKDEVICE_QUEUE_ENTRY;

VOID IoStartPacket(IN PDEVICE_OBJECT DeviceObject, 
IN PIRP Irp, 
IN PULONG Key OPTIONAL, 
IN PDRIVER_CANCEL CancelFunction OPTIONAL)
 {     
    KIRQL oldIrql;     
    KIRQL cancelIrql = PASSIVE_LEVEL;     
    BOOLEAN i;  
    KeRaiseIrql( DISPATCH_LEVEL, &oldIrql );
    
    if (CancelFunction) 
    {         
        IoAcquireCancelSpinLock( &cancelIrql ); 
        Irp->CancelRoutine = CancelFunction;     
    }     
    
    i = KeInsertDeviceQueue(&DeviceObject->DeviceQueue, &Irp->Tail.Overlay.DeviceQueueEntry); 
    
    if (!i) 
    {         
        DeviceObject->CurrentIrp = Irp;
        if (CancelFunction) 
        {            
            IoReleaseCancelSpinLock( cancelIrql );
        } 
        
        DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);    
    } 
    else 
    {  
        if (CancelFunction) 
        {             
            if (Irp->Cancel) 
            {               
                Irp->CancelIrql = cancelIrql;   
                Irp->CancelRoutine = (PDRIVER_CANCEL) NULL;   
                CancelFunction( DeviceObject, Irp );     
            }
            else 
            {                 
                IoReleaseCancelSpinLock( cancelIrql );  
            }         
        }    
    } 
    
    KeLowerIrql( oldIrql ); 
}

BOOLEAN NTAPI KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,  
                               IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)  
{  
    KLOCK_QUEUE_HANDLE DeviceLock;  
    BOOLEAN Inserted;  
    ASSERT_DEVICE_QUEUE(DeviceQueue);  
 
    /* Lock the queue */  
    KiAcquireDeviceQueueLock(DeviceQueue, &DeviceLock);  
    /* Check if it's not busy */  
    if (!DeviceQueue->Busy)  
    {   //目标设备对象空闲,不需要挂入队列,可以直接执行启动函数  
        /* Set it as busy */  
        Inserted = FALSE;  
        DeviceQueue->Busy = TRUE;    //但是现在目标设备对象已经不再空闲  
    }  
    else  
    {   //目标设备对象已经执行过启动函数但尚未完成,需要挂入队列  
        /* Insert it into the list */  
        Inserted = TRUE;  
        InsertTailList(&DeviceQueue->DeviceListHead, &DeviceQueueEntry->DeviceListEntry);  
    }  
    /* Set the Insert state into the entry */  
    DeviceQueueEntry->Inserted = Inserted;  
    /* Release the lock */  
    KiReleaseDeviceQueueLock(&DeviceLock);  
    /* Return the state */  
    return Inserted;    //返回TRUE表示已排入队列,FALSE表示可以继续操作  

VOID IopStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN LOGICAL Cancelable)
{     
    KIRQL cancelIrql = PASSIVE_LEVEL;    
    PIRP irp;   
    PKDEVICE_QUEUE_ENTRY packet;
    
    if (Cancelable) 
    {       
        IoAcquireCancelSpinLock( &cancelIrql );  
    }  
    
    DeviceObject->CurrentIrp = (PIRP) NULL; 
    
    packet = KeRemoveDeviceQueue( &DeviceObject->DeviceQueue );    
    
    if (packet) 
    {        
        irp = CONTAINING_RECORD( packet, IRP, Tail.Overlay.DeviceQueueEntry );
        
        DeviceObject->CurrentIrp = irp;     
        if (Cancelable) 
        {                      
            IoReleaseCancelSpinLock( cancelIrql );   
        }  
        
        DeviceObject->DriverObject->DriverStartIo( DeviceObject, irp ); 
    }
    else
    {  
        if (Cancelable) 
        {      
            IoReleaseCancelSpinLock( cancelIrql );     
        }    
    } 
}

宏 CONTAINING_RECORD 的用处其实还是相当大的, 而且很是方便, 它的主要作用是:根据结构体中的某成员的地址来推算出该结构体整体的地址

#define CONTAINING_RECORD(addr,type,field) ((type*)((unsigned char*)addr - (unsigned long)&((type*)0)->field))
    // addr:  结构体中某个成员变量的地址
    // type:  结构体的原型
    // field: 结构体的某个成员(与前面相同)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值