⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.c

📁 使用NDIS协议完成的一个较为简单的驱动程序编程范例(windons驱动程序编程)
💻 C
📖 第 1 页 / 共 2 页
字号:
		NdisFreeMemory(VirtualAddress, TotalLength, 0);
		NdisFreePacket(pPacket);
		pPacket = NULL;
		goto ERROR;
	}



	NdisChainBufferAtFront(
		pPacket,
		pBuffer
		);

	//
	// Copy the ethernet header into the packet first.
	//
	NdisMoveMappedMemory(
	    (PUCHAR)VirtualAddress + TotalLength - ETHERNET_HEADER_LENGTH,
	    HeaderBuffer,
	    HeaderBufferSize
	    );

	//
	// Copy data received on the underlying NIC into the packet we have just built. 
	//
	NdisTransferData(
	        &status,
	        open->AdapterHandle,
	        MacReceiveContext,
	        0,
	        PacketSize,
	        pPacket,
	        &bytesTransfered
	);

	if (status == NDIS_STATUS_PENDING) {
        return NDIS_STATUS_SUCCESS;
    }
ERROR:
    //
    //  If it didn't pend, call the completion routine now.
    //
    PacketTransferDataComplete(
		open,
		pPacket,
		status,
		bytesTransfered
		);
    return NDIS_STATUS_SUCCESS;
}


VOID
PacketTransferDataComplete (
    IN NDIS_HANDLE   ProtocolBindingContext,
    IN PNDIS_PACKET  pPacket,
    IN NDIS_STATUS   Status,
    IN UINT          BytesTransfered
    )
/*++

Routine Description:

    This is a required function unless the protocol binds itself 
    exclusively to underlying NIC driver(s) that indicate packets 
    with NdisMIndicateReceivePacket. ProtocolTransferDataComplete 
    is called when a previous call to NdisTransferData returned 
    NDIS_STATUS_PENDING and the remaining data has been copied 
    into the protocol-supplied buffers chained to a given packet 
    descriptor. 

Arguments:


Return Value:


--*/

{
	POPEN_INSTANCE  open;
	PNDIS_BUFFER	pFirstBuffer;	
	PVOID		VirtualAddress;
	UINT		Length;
    PIRP        irp;
    PMDL        pMdl;
	PIO_STACK_LOCATION   irpSp;

	open = (POPEN_INSTANCE)ProtocolBindingContext;
	DebugPrint(("Packet: TransferDataComplete\n"));

	if(open->Buffer_Handin){
		irp=RESERVED(pPacket)->Irp;
		irpSp = IoGetCurrentIrpStackLocation(irp);
		pMdl=RESERVED(pPacket)->pMdl;
    //
    //  Free the partial MDL that we allocated
    //
    if(pMdl)
        IoFreeMdl(pMdl);
    //
    //  Put the packet on the free queue
    //
    NdisFreePacket(pPacket);

    if(Status == NDIS_STATUS_SUCCESS)
    {
        irp->IoStatus.Status = STATUS_SUCCESS;
        irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH;
    } else {
    
        irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        irp->IoStatus.Information = 0;
    }

    DebugPrint(("BytesTransfered:%d\n", irp->IoStatus.Information));

    IoCompleteRequest(irp, IO_NO_INCREMENT);

	}else{
		//
	//  Put this packet in the list of received packets if NdisTransferData returns NDIS_STATUS_SUCCESS.
	//  The PacketRead will attempt to remove packets from this list.
	//    
	if (Status == NDIS_STATUS_SUCCESS) {
		ExInterlockedInsertTailList(
			&open->RcvPackQList,
			&RESERVED(pPacket)->RcvPackQListElement,
			&open->RcvPackQSpinLock
			);
	} else {
	//
	// If control flow passes this branch, there are two possibilities for the pPacket:
	//	i. We call PacketTransferDataComplete immediately after the statement "goto ERROR".
	//	   We have nothing to do in this manner since we have released all the resources before "goto ERROR".
	//	ii.PacketTransferDataComplete is called automatically as the result that the preceding call to
	//	   NdisTransferData returns NDIS_STATUS_PENDING.
	//	   Since NdisTransferData failed eventually, we should release all the resources now.
	//
	if (pPacket != NULL) {
	NdisQueryPacket(pPacket, NULL, NULL, &pFirstBuffer, NULL);
	NdisQueryBuffer(pFirstBuffer, &VirtualAddress, &Length);	
	//
	// Free pPacket if failed during the transfer.
	//
	NdisFreeMemory(VirtualAddress, Length, 0);
	NdisFreeBuffer(pFirstBuffer);
			NdisFreePacket(pPacket);
		}
	}
  
	}
    IoDecrement(open);
    return;

}

VOID
PacketReceiveComplete(
    IN NDIS_HANDLE  ProtocolBindingContext
    )
/*++

Routine Description:

    This is a required function. PacketReceiveComplete 
    is called to indicate that any received packets previously 
    indicated to PacketReceivePacket can now be postprocessed. 
    
Arguments:


Return Value:


--*/
{
    return;
}

INT
PacketReceivePacket(
    IN    NDIS_HANDLE         ProtocolBindingContext,
    IN    PNDIS_PACKET        Packet
    )
/*++

Routine Description:

    ReceivePacket handler. Called up by the miniport below 
    when it supports NDIS 4.0 style receives.
    A ProtocolReceivePacket function should be provided if 
    the protocol driver might be bound to a NIC driver that 
    indicates an array of one or more packets by calling 
    NdisMIndicateReceivePacket. 

Arguments:

    ProtocolBindingContext    Pointer to our adapter structure.
    Packet - Pointer to the packet

Return Value:

    == 0 -> We are done with the packet
    != 0 -> We will keep the packet and call NdisReturnPackets() 
            this many times when done.
--*/
{
	return 0;
}


VOID
PacketCancelRoutine (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )

/*++

Routine Description:

    The cancel routine. It will remove the IRP from the queue 
    and will complete it. The cancel spin lock is already acquired 
    when this routine is called.

Arguments:

    DeviceObject - pointer to the device object.
    
    Irp - pointer to the IRP to be cancelled.
    
    
Return Value:

    VOID.

--*/
{

    POPEN_INSTANCE      open = DeviceObject->DeviceExtension; 
    KIRQL               oldIrql;
    PIRP                irpToComplete = NULL;
    PLIST_ENTRY         thisEntry, listHead;
    PIRP                pendingIrp;
    PNDIS_PACKET        myPacket = NULL;
    PPACKET_RESERVED    reserved;
    PMDL                mdl;

    //
    // Don't assume that the IRP being cancelled is in the queue.
    // Only complete the IRP if it IS in the queue.
    //
    //
    // Must acquire the local spinlock before releasing 
    // the global cancel spinlock
    //
    DebugPrint(("PacketCancelRoutine\n"));

    oldIrql = Irp->CancelIrql;

    //
    // One should not intermix KeAcquireSpinLock(AtDpcLevel) 
    // and ExInterlocked...List() functions on the same spinlock if the
    // routines that use the lock run at IRQL > DISPATCH_LEVEL.
    // After acquiring the lock using Ke function, if we got interrupted
    // and entered into an ISR and tried to manipulate the list using
    // ExInterlocked...List function with the same lock, we deadlock.
    // In this sample we can safely do that because none of our routines 
    // will be called at IRQL > DISPATCH_LEVEL.
    //
    
    KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock);

    IoReleaseCancelSpinLock( KeGetCurrentIrql() );

    //
    // Remove the IRP from the queue
    //
  
    listHead = &open->RcvList;
    
    for(thisEntry = listHead->Flink; 
        thisEntry != listHead;
        thisEntry = thisEntry->Flink)
    {

        reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
        myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);
        pendingIrp = RESERVED(myPacket)->Irp;

        if (pendingIrp == Irp) 
        {
                RemoveEntryList(thisEntry);
                irpToComplete = pendingIrp;
                break;
        }
      
    }
    
    //
    // Release the queue spinlock
    //

    KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql);

    //
    // Complete the IRP with status canclled
    //
    
    if(irpToComplete) {
    
        DebugPrint(("Cancelling IRP\n"));

        ASSERT(myPacket);       

        //
        //  Put the packet on the free queue
        //
        NdisFreePacket(myPacket);

        irpToComplete->IoStatus.Status = STATUS_CANCELLED;
        irpToComplete->IoStatus.Information = 0;
        IoCompleteRequest(irpToComplete, IO_NO_INCREMENT);
        IoDecrement(open);
    }

    return;
 
}


NTSTATUS
PacketCancelReadIrps(
    IN PDEVICE_OBJECT DeviceObject
)
{
    POPEN_INSTANCE      open = DeviceObject->DeviceExtension; 
    PLIST_ENTRY         thisEntry;
    PIRP                pendingIrp;
    PNDIS_PACKET        myPacket = NULL;
    PPACKET_RESERVED    reserved;
    PMDL                mdl;

    DebugPrint(("PacketCancelReadIrps\n"));

    //
    // Walk through the RcvList and cancel all read IRPs.
    //

    while(thisEntry=ExInterlockedRemoveHeadList(
                        &open->RcvList,
                        &open->RcvQSpinLock
                        ))
    {
        reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
        myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

        ASSERT(myPacket);

        pendingIrp = RESERVED(myPacket)->Irp;

        //
        //  Put the packet on the free queue
        //
        NdisFreePacket(myPacket);
        
        DebugPrint(("Cancelled : 0%0x\n", pendingIrp));
        
        IoSetCancelRoutine(pendingIrp, NULL);

        //
        // Cancel the Irp
        //
        pendingIrp->IoStatus.Information = 0;
        pendingIrp->IoStatus.Status = STATUS_CANCELLED;
        IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
        IoDecrement(open);
    }

    return STATUS_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -