- Visual C++源码
- Visual Basic源码
- C++ Builder源码
- Java源码
- Delphi源码
- C/C++源码
- PHP源码
- Perl源码
- Python源码
- Asm源码
- Pascal源码
- Borland C++源码
- Others源码
- SQL源码
- VBScript源码
- JavaScript源码
- ASP/ASPX源码
- C#源码
- Flash/ActionScript源码
- matlab源码
- PowerBuilder源码
- LabView源码
- Flex源码
- MathCAD源码
- VBA源码
- IDL源码
- Lisp/Scheme源码
- VHDL源码
- Objective-C源码
- Fortran源码
- tcl/tk源码
- QT源码
send.c
资源名称:1336ndis.rar [点击查看]
上传用户:yanxuanwei
上传日期:2008-05-17
资源大小:53k
文件大小:13k
源码类别:
驱动编程
开发平台:
Visual C++
- /*++
- Copyright (c) 2000 Microsoft Corporation
- Module Name:
- send.c
- Abstract:
- NDIS protocol entry points and utility routines to handle sending
- data.
- Environment:
- Kernel mode only.
- Revision History:
- arvindm 4/10/2000 Created
- --*/
- #include "precomp.h"
- #define __FILENUMBER 'DNES'
- NTSTATUS
- NdisuioWrite(
- IN PDEVICE_OBJECT pDeviceObject,
- IN PIRP pIrp
- )
- /*++
- Routine Description:
- Dispatch routine to handle IRP_MJ_WRITE.
- Arguments:
- pDeviceObject - pointer to our device object
- pIrp - Pointer to request packet
- Return Value:
- NT status code.
- --*/
- {
- PIO_STACK_LOCATION pIrpSp;
- ULONG FunctionCode;
- ULONG DataLength;
- NTSTATUS NtStatus;
- NDIS_STATUS Status;
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- PNDIS_PACKET pNdisPacket;
- PNDIS_BUFFER pNdisBuffer;
- NDISUIO_ETH_HEADER UNALIGNED *pEthHeader;
- #ifdef NDIS51
- PVOID CancelId;
- #endif
- pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
- pOpenContext = pIrpSp->FileObject->FsContext;
- pNdisPacket = NULL;
- do
- {
- if (pOpenContext == NULL)
- {
- DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a devicen",
- pIrpSp->FileObject));
- NtStatus = STATUS_INVALID_HANDLE;
- break;
- }
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- //
- // Try to get a virtual address for the MDL.
- //
- #ifndef WIN9X
- pEthHeader = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
- if (pEthHeader == NULL)
- {
- DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for"
- " IRP %p, MDL %pn",
- pIrp, pIrp->MdlAddress));
- NtStatus = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- #else
- pEthHeader = MmGetSystemAddressForMdl(pIrp->MdlAddress); // for Win9X
- #endif
- //
- // Sanity-check the length.
- //
- DataLength = MmGetMdlByteCount(pIrp->MdlAddress);
- if (DataLength < sizeof(NDISUIO_ETH_HEADER))
- {
- DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)n",
- DataLength));
- NtStatus = STATUS_BUFFER_TOO_SMALL;
- break;
- }
- if (DataLength > (pOpenContext->MaxFrameSize + sizeof(NDISUIO_ETH_HEADER)))
- {
- DEBUGP(DL_WARN, ("Write: Open %p: data length (%d)"
- " larger than max frame size (%d)n",
- pOpenContext, DataLength, pOpenContext->MaxFrameSize));
- NtStatus = STATUS_INVALID_BUFFER_SIZE;
- break;
- }
- if (pEthHeader->EthType != Globals.EthType)
- {
- DEBUGP(DL_WARN, ("Write: Failing send with EthType %xn",
- pEthHeader->EthType));
- NtStatus = STATUS_INVALID_PARAMETER;
- break;
- }
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- if (!NUIO_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
- {
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- DEBUGP(DL_FATAL, ("Write: Open %p is not bound"
- " or in low power staten", pOpenContext));
- NtStatus = STATUS_INVALID_HANDLE;
- break;
- }
- //
- // Allocate a send packet.
- //
- NUIO_ASSERT(pOpenContext->SendPacketPool != NULL);
- NdisAllocatePacket(
- &Status,
- &pNdisPacket,
- pOpenContext->SendPacketPool);
- if (Status != NDIS_STATUS_SUCCESS)
- {
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send pktn",
- pOpenContext));
- NtStatus = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- //
- // Allocate a send buffer if necessary.
- //
- if (pOpenContext->bRunningOnWin9x)
- {
- NdisAllocateBuffer(
- &Status,
- &pNdisBuffer,
- pOpenContext->SendBufferPool,
- pEthHeader,
- DataLength);
- if (Status != NDIS_STATUS_SUCCESS)
- {
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- NdisFreePacket(pNdisPacket);
- DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send bufn",
- pOpenContext));
- NtStatus = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- }
- else
- {
- pNdisBuffer = pIrp->MdlAddress;
- }
- NdisInterlockedIncrement(&pOpenContext->PendedSendCount);
- NUIO_REF_OPEN(pOpenContext); // pended send
- IoMarkIrpPending(pIrp);
- //
- // Initialize the packet ref count. This packet will be freed
- // when this count goes to zero.
- //
- NUIO_SEND_PKT_RSVD(pNdisPacket)->RefCount = 1;
- #ifdef NDIS51
- //
- // NDIS 5.1 supports cancelling sends. We set up a cancel ID on
- // each send packet (which maps to a Write IRP), and save the
- // packet pointer in the IRP. If the IRP gets cancelled, we use
- // NdisCancelSendPackets() to cancel the packet.
- //
- CancelId = NUIO_GET_NEXT_CANCEL_ID();
- NDIS_SET_PACKET_CANCEL_ID(pNdisPacket, CancelId);
- pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pOpenContext;
- pIrp->Tail.Overlay.DriverContext[1] = (PVOID)pNdisPacket;
- NUIO_INSERT_TAIL_LIST(&pOpenContext->PendedWrites, &pIrp->Tail.Overlay.ListEntry);
- IoSetCancelRoutine(pIrp, NdisuioCancelWrite);
- #endif // NDIS51
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- //
- // Set a back pointer from the packet to the IRP.
- //
- NUIO_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp;
- NtStatus = STATUS_PENDING;
- pNdisBuffer->Next = NULL;
- NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
- #if SEND_DBG
- {
- PUCHAR pData;
- #ifndef WIN9X
- pData = MmGetSystemAddressForMdlSafe(pNdisBuffer, NormalPagePriority);
- NUIO_ASSERT(pEthHeader == pData);
- #else
- pData = MmGetSystemAddressForMdl(pNdisBuffer); // Win9x
- #endif
- DEBUGP(DL_VERY_LOUD,
- ("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytesn",
- pIrp->MdlAddress, pIrp->MdlAddress->MdlFlags, pData, DataLength));
- DEBUGPDUMP(DL_VERY_LOUD, pData, MIN(DataLength, 48));
- }
- #endif // SEND_DBG
- NdisSendPackets(pOpenContext->BindingHandle, &pNdisPacket, 1);
- }
- while (FALSE);
- if (NtStatus != STATUS_PENDING)
- {
- pIrp->IoStatus.Status = NtStatus;
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- }
- return (NtStatus);
- }
- #ifdef NDIS51
- VOID
- NdisuioCancelWrite(
- IN PDEVICE_OBJECT pDeviceObject,
- IN PIRP pIrp
- )
- /*++
- Routine Description:
- Cancel a pending write IRP. This routine attempt to cancel the NDIS send.
- Arguments:
- pDeviceObject - pointer to our device object
- pIrp - IRP to be cancelled
- Return Value:
- None
- --*/
- {
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- PLIST_ENTRY pIrpEntry;
- PNDIS_PACKET pNdisPacket;
- IoReleaseCancelSpinLock(pIrp->CancelIrql);
- //
- // The NDIS packet representing this Write IRP.
- //
- pNdisPacket = NULL;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT) pIrp->Tail.Overlay.DriverContext[0];
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- //
- // Try to locate the IRP in the pended write queue. The send completion
- // routine may be running and might have removed it from there.
- //
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- for (pIrpEntry = pOpenContext->PendedWrites.Flink;
- pIrpEntry != &pOpenContext->PendedWrites;
- pIrpEntry = pIrpEntry->Flink)
- {
- if (pIrp == CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry))
- {
- pNdisPacket = (PNDIS_PACKET) pIrp->Tail.Overlay.DriverContext[1];
- //
- // Place a reference on this packet so that it won't get
- // freed/reused until we are done with it.
- //
- NUIO_REF_SEND_PKT(pNdisPacket);
- break;
- }
- }
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- if (pNdisPacket != NULL)
- {
- //
- // Either the send completion routine hasn't run, or we got a peak
- // at the IRP/packet before it had a chance to take it out of the
- // pending IRP queue.
- //
- // We do not complete the IRP here - note that we didn't dequeue it
- // above. This is because we always want the send complete routine to
- // complete the IRP. And this in turn is because the packet that was
- // prepared from the IRP has a buffer chain pointing to data associated
- // with this IRP. Therefore we cannot complete the IRP before the driver
- // below us is done with the data it pointed to.
- //
- //
- // Request NDIS to cancel this send. The result of this call is that
- // our SendComplete handler will be called (if not already called).
- //
- DEBUGP(DL_INFO, ("CancelWrite: cancelling pkt %p on Open %pn",
- pNdisPacket, pOpenContext));
- NdisCancelSendPackets(
- pOpenContext->BindingHandle,
- NDIS_GET_PACKET_CANCEL_ID(pNdisPacket)
- );
- //
- // It is now safe to remove the reference we had placed on the packet.
- //
- NUIO_DEREF_SEND_PKT(pNdisPacket);
- }
- //
- // else the send completion routine has already picked up this IRP.
- //
- }
- #endif // NDIS51
- VOID
- NdisuioSendComplete(
- IN NDIS_HANDLE ProtocolBindingContext,
- IN PNDIS_PACKET pNdisPacket,
- IN NDIS_STATUS Status
- )
- /*++
- Routine Description:
- NDIS entry point called to signify completion of a packet send.
- We pick up and complete the Write IRP corresponding to this packet.
- NDIS 5.1:
- Arguments:
- ProtocolBindingContext - pointer to open context
- pNdisPacket - packet that completed send
- Status - status of send
- Return Value:
- None
- --*/
- {
- PIRP pIrp;
- PIO_STACK_LOCATION pIrpSp;
- PNDISUIO_OPEN_CONTEXT pOpenContext;
- pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
- NUIO_STRUCT_ASSERT(pOpenContext, oc);
- pIrp = NUIO_IRP_FROM_SEND_PKT(pNdisPacket);
- if (pOpenContext->bRunningOnWin9x)
- {
- //
- // We would have attached our own NDIS_BUFFER. Take it out
- // and free it.
- //
- PNDIS_BUFFER pNdisBuffer;
- PVOID VirtualAddr;
- UINT BufferLength;
- UINT TotalLength;
- #ifdef NDIS51
- NUIO_ASSERT(FALSE); // NDIS 5.1 not on Win9X!
- #else
- NdisGetFirstBufferFromPacket(
- pNdisPacket,
- &pNdisBuffer,
- &VirtualAddr,
- &BufferLength,
- &TotalLength);
- NUIO_ASSERT(pNdisBuffer != NULL);
- NdisFreeBuffer(pNdisBuffer);
- #endif
- }
- #ifdef NDIS51
- IoSetCancelRoutine(pIrp, NULL);
- NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
- NUIO_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry);
- NUIO_RELEASE_LOCK(&pOpenContext->Lock);
- #endif
- //
- // We are done with the NDIS_PACKET:
- //
- NUIO_DEREF_SEND_PKT(pNdisPacket);
- //
- // Complete the Write IRP with the right status.
- //
- pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
- if (Status == NDIS_STATUS_SUCCESS)
- {
- pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
- pIrp->IoStatus.Status = STATUS_SUCCESS;
- }
- else
- {
- pIrp->IoStatus.Information = 0;
- pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- }
- DEBUGP(DL_INFO, ("SendComplete: packet %p/IRP %p/Length %d "
- "completed with status %xn",
- pNdisPacket, pIrp, pIrp->IoStatus.Information, pIrp->IoStatus.Status));
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- NdisInterlockedDecrement(&pOpenContext->PendedSendCount);
- NUIO_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP
- }