Ejemplo n.º 1
0
/**
* Adds a string to the data recorder.
* 
* \return NDIS_STATUS
*/
NDIS_STATUS SaveToDataRecorder(PMP_DATA_RECORDER_OBJ Recorder, __format_string __nullterminated CHAR *Format, ...)
{
    ULONG                       myIndex;
    va_list                     args;

    if (Recorder->RecordList)
    {
        myIndex = NdisInterlockedIncrement((PLONG)&(Recorder->CurrentIndex)) % Recorder->MaxLength;
        Recorder->RecordList[myIndex].DataType = MP_STRING;

        // Format the message        
        va_start(args, Format);
        if (NT_SUCCESS(RtlStringCchVPrintfA(
                            Recorder->RecordList[myIndex].Data.String, 
                            MAX_RECORDED_STRING_LENGTH, 
                            Format, 
                            args))
            )
        {
            Recorder->RecordList[myIndex].Data.String[MAX_RECORDED_STRING_LENGTH-1] = 0;
        }
        va_end (args);       
    }
    
    return NDIS_STATUS_SUCCESS;
}
Ejemplo n.º 2
0
NDIS_STATUS
TXNblReference(
    _In_  PMP_ADAPTER       Adapter,
    _In_  PNET_BUFFER_LIST  NetBufferList)
/*++

Routine Description:

    Adds a reference on a NBL that is being transmitted.
    The NBL won't be returned to the protocol until the last reference is
    released.

    Runs at IRQL <= DISPATCH_LEVEL.

Arguments:

    Adapter                     Pointer to our adapter
    NetBufferList               The NBL to reference

Return Value:

    NDIS_STATUS_SUCCESS if reference was acquired succesfully.
    NDIS_STATUS_ADAPTER_NOT_READY if the adapter state is such that we should not acquire new references to resources

--*/
{
    NdisInterlockedIncrement(&Adapter->nBusySend);

    //
    // Make sure the increment happens before ready state check
    //
    KeMemoryBarrier();

    //
    // If the adapter is not ready, undo the reference and fail the call
    //
    if(!MP_IS_READY(Adapter))
    {
        InterlockedDecrement(&Adapter->nBusySend);
        DEBUGP(MP_LOUD, "[%p] Could not acquire transmit reference, the adapter is not ready.\n", Adapter);
        return NDIS_STATUS_ADAPTER_NOT_READY;
    }

    NdisInterlockedIncrement(&SEND_REF_FROM_NBL(NetBufferList));
    return NDIS_STATUS_SUCCESS;

}
Ejemplo n.º 3
0
VOID tapWaitForReceiveNblInFlightCountZeroEvent(__in PTAP_ADAPTER_CONTEXT Adapter) {
  LONG nblCount;

  //
  // Wait until higher-level protocol has returned all NBLs
  // to the driver.
  //

  // Add one NBL "bias" to insure allow event to be reset safely.
  nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
  ASSERT(nblCount > 0);
  NdisResetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent);

  //
  // Now remove the bias and wait for the ReceiveNblInFlightCountZeroEvent
  // if the count returned is not zero.
  //
  nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount);
  ASSERT(nblCount >= 0);

  if (nblCount) {
    LARGE_INTEGER startTime, currentTime;

    NdisGetSystemUpTimeEx(&startTime);

    for (;;) {
      BOOLEAN waitResult =
          NdisWaitEvent(&Adapter->ReceiveNblInFlightCountZeroEvent, TAP_WAIT_POLL_LOOP_TIMEOUT);

      NdisGetSystemUpTimeEx(&currentTime);

      if (waitResult) {
        break;
      }

      DEBUGP(("[%s] Waiting for %d in-flight receive NBLs to be returned.\n",
              MINIPORT_INSTANCE_ID(Adapter), Adapter->ReceiveNblInFlightCount));
    }

    DEBUGP(("[%s] Waited %d ms for all in-flight NBLs to be returned.\n",
            MINIPORT_INSTANCE_ID(Adapter), (currentTime.LowPart - startTime.LowPart)));
  }
}
Ejemplo n.º 4
0
A_STATUS
CAR6KMini::WMISendControlPacket(
	IN PVOID            osbuf,
	IN HTC_ENDPOINT_ID  endPoint)
{
	A_STATUS    status = A_OK;

	if (WMI_CONTROL_MBOX != endPoint)
		NdisInterlockedIncrement(&m_TxPending);

	status = Ar6000SendPkt(endPoint,osbuf,AR6K_CONTROL_PKT_TAG);
	
	if (A_OK != status && A_PENDING != status && WMI_CONTROL_MBOX != endPoint) 
	{
		NDIS_DEBUG_PRINTF(DBG_ERR, " %s(), Ar6000SendPkt Fail, status = %d \r\n", __FUNCTION__,status);
		NdisInterlockedDecrement(&m_TxPending);
	}

	return status;
}
Ejemplo n.º 5
0
VOID
ndisprotRefOpen(
    IN PNDISPROT_OPEN_CONTEXT        pOpenContext
    )
/*++

Routine Description:

    Reference the given open context.

    NOTE: Can be called with or without holding the opencontext lock.

Arguments:

    pOpenContext - pointer to open context

Return Value:

    None

--*/
{
    NdisInterlockedIncrement((PLONG)&pOpenContext->RefCount);
}
//------------------------------------------------------------------------------
void signalKernelEvent(void)
{
    NdisInterlockedIncrement(&instance_l.kernelEventCount);
    NdisSetEvent(&instance_l.kernelWaitEvent);
}
//------------------------------------------------------------------------------
void signalUserEvent(void)
{
    NdisInterlockedIncrement(&instance_l.userEventCount);
    NdisSetEvent(&instance_l.userWaitEvent);
}
Ejemplo n.º 8
0
/*
 * --------------------------------------------------------------------------
 * Utility function to issue the specified OID to the NDIS stack. The OID is
 * directed towards the miniport edge of the extensible switch.
 * An OID that gets issued may not complete immediately, and in such cases, the
 * function waits for the OID to complete. Thus, this function must not be
 * called at the PASSIVE_LEVEL.
 * --------------------------------------------------------------------------
 */
static NDIS_STATUS
OvsIssueOidRequest(POVS_SWITCH_CONTEXT switchContext,
                   NDIS_REQUEST_TYPE oidType,
                   UINT32 oidRequestEnum,
                   PVOID oidInputBuffer,
                   UINT32 inputSize,
                   PVOID oidOutputBuffer,
                   UINT32 outputSize,
                   UINT32 *outputSizeNeeded)
{
    NDIS_STATUS status;
    PNDIS_OID_REQUEST oidRequest;
    POVS_OID_CONTEXT oidContext;
    ULONG OvsExtOidRequestId =          'ISVO';

    DBG_UNREFERENCED_PARAMETER(inputSize);
    DBG_UNREFERENCED_PARAMETER(oidInputBuffer);

    OVS_LOG_TRACE("Enter: switchContext: %p, oidType: %d",
                  switchContext, oidType);

    ASSERT(oidInputBuffer == NULL || inputSize != 0);
    ASSERT(oidOutputBuffer == NULL || outputSize != 0);
    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    oidRequest = OvsAllocateMemoryWithTag(sizeof *oidRequest,
                                          OVS_OID_POOL_TAG);
    if (!oidRequest) {
        status = NDIS_STATUS_RESOURCES;
        goto done;
    }

    oidContext = OvsAllocateMemoryWithTag(sizeof *oidContext,
                                          OVS_OID_POOL_TAG);
    if (!oidContext) {
        OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG);
        status = NDIS_STATUS_RESOURCES;
        goto done;
    }

    RtlZeroMemory(oidRequest, sizeof *oidRequest);
    RtlZeroMemory(oidContext, sizeof *oidContext);

    oidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
    oidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
    oidRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;

    oidRequest->RequestType = oidType;
    oidRequest->PortNumber = 0;
    oidRequest->Timeout = 0;
    oidRequest->RequestId = (PVOID)OvsExtOidRequestId;

    switch(oidType) {
    case NdisRequestQueryInformation:
        oidRequest->DATA.QUERY_INFORMATION.Oid = oidRequestEnum;
        oidRequest->DATA.QUERY_INFORMATION.InformationBuffer = oidOutputBuffer;
        oidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = outputSize;
        break;
    default:
        ASSERT(FALSE);
        status = NDIS_STATUS_INVALID_PARAMETER;
        break;
    }

    /*
     * We make use of the SourceReserved field in the OID request to store
     * pointers to the original OID (if any), and also context for completion
     * (if any).
     */
    oidContext->status = NDIS_STATUS_SUCCESS;
    NdisInitializeEvent(&oidContext->oidComplete);

    OvsOidSetOrigRequest(oidRequest, NULL);
    OvsOidSetContext(oidRequest, oidContext);

    NdisInterlockedIncrement(&(switchContext->pendingOidCount));
    status = NdisFOidRequest(switchContext->NdisFilterHandle, oidRequest);
    if (status == NDIS_STATUS_PENDING) {
        NdisWaitEvent(&oidContext->oidComplete, 0);
    } else {
        NdisInterlockedDecrement(&(switchContext->pendingOidCount));
    }

    if (status == NDIS_STATUS_INVALID_LENGTH ||
        oidContext->status == NDIS_STATUS_INVALID_LENGTH) {
        switch(oidType) {
        case NdisRequestQueryInformation:
            *outputSizeNeeded = oidRequest->DATA.QUERY_INFORMATION.BytesNeeded;
        }
    }

    status = oidContext->status;
    ASSERT(status != NDIS_STATUS_PENDING);

    OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG);
    OvsFreeMemoryWithTag(oidContext, OVS_OID_POOL_TAG);

done:
    OVS_LOG_TRACE("Exit: status %8x.", status);
    return status;
}
Ejemplo n.º 9
0
NDIS_STATUS
OvsExtOidRequest(NDIS_HANDLE filterModuleContext,
                 PNDIS_OID_REQUEST oidRequest)
{
    POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext;
    NDIS_STATUS status = NDIS_STATUS_SUCCESS;
    PNDIS_OID_REQUEST clonedOidRequest = NULL;
    struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);
    BOOLEAN completeOid = FALSE;
    ULONG bytesNeeded = 0;

    OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d",
                  oidRequest, oidRequest->RequestType);
    status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle,
                                         oidRequest, OVS_MEMORY_TAG,
                                         &clonedOidRequest);
    if (status != NDIS_STATUS_SUCCESS) {
        goto done;
    }

    NdisInterlockedIncrement(&(switchObject->pendingOidCount));

    /* set the original oid request in cloned one. */
    OvsOidSetOrigRequest(clonedOidRequest, oidRequest);
    OvsOidSetContext(clonedOidRequest, NULL);

    switch(clonedOidRequest->RequestType) {
    case NdisRequestSetInformation:
        status = OvsProcessSetOid(switchObject, clonedOidRequest,
                                                   &completeOid);
        break;
    case NdisRequestMethod:
        status = OvsProcessMethodOid(switchObject, clonedOidRequest,
                                     &completeOid, &bytesNeeded);
        break;
    default:
        /* We do not handle other request types as of now.
         * We are just a passthrough for those. */
        break;
    }

    if (completeOid == TRUE) {
        /* dont leave any reference back to original request,
         * even if we are freeing it up. */
        OVS_LOG_INFO("Complete True oidRequest %p.", oidRequest);
        OvsOidSetOrigRequest(clonedOidRequest, NULL);
        NdisFreeCloneOidRequest(switchObject->NdisFilterHandle,
                                             clonedOidRequest);
        methodInfo->BytesNeeded = bytesNeeded;
        NdisInterlockedDecrement(&switchObject->pendingOidCount);
        goto done;
    }

    /* pass the request down */
    status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedOidRequest);
    if (status != NDIS_STATUS_PENDING) {
        OvsExtOidRequestComplete(switchObject, clonedOidRequest, status);
        /* sample code says so */
        status = NDIS_STATUS_PENDING;
    }

done:
    OVS_LOG_TRACE("Exit: status %8x.", status);
    return status;
}
Ejemplo n.º 10
0
VOID
IndicateReceivePacket(
    __in PTAP_ADAPTER_CONTEXT  Adapter,
    __in PUCHAR packetData,
    __in const unsigned int packetLength
    )
{
    PUCHAR  injectBuffer;

    //
    // Handle miniport Pause
    // ---------------------
    // NDIS 6 miniports implement a temporary "Pause" state normally followed
    // by the Restart. While in the Pause state it is forbidden for the miniport
    // to indicate receive NBLs.
    //
    // That is: The device interface may be "up", but the NDIS miniport send/receive
    // interface may be temporarily "down".
    //
    // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas inject path
    // the code below will simply ignore inject packets passed to the driver while
    // the miniport is in the Paused state.
    //
    // The correct implementation is to go ahead and build the NBLs corresponding
    // to the inject packet - but queue them. When Restart is entered the
    // queued NBLs would be dequeued and indicated to the host.
    //
    if(tapAdapterSendAndReceiveReady(Adapter) != NDIS_STATUS_SUCCESS)
    {
        DEBUGP (("[%s] Lying send in IndicateReceivePacket while adapter paused\n",
            MINIPORT_INSTANCE_ID (Adapter)));

        return;
    }

    // Allocate flat buffer for packet data.
    injectBuffer = (PUCHAR )NdisAllocateMemoryWithTagPriority(
                        Adapter->MiniportAdapterHandle,
                        packetLength,
                        TAP_RX_INJECT_BUFFER_TAG,
                        NormalPoolPriority
                        );

    if( injectBuffer)
    {
        PMDL    mdl;

        // Copy packet data to flat buffer.
        NdisMoveMemory (injectBuffer, packetData, packetLength);

        // Allocate MDL for flat buffer.
        mdl = NdisAllocateMdl(
                Adapter->MiniportAdapterHandle,
                injectBuffer,
                packetLength
                );

        if( mdl )
        {
            PNET_BUFFER_LIST    netBufferList;

            mdl->Next = NULL;   // No next MDL

            // Allocate the NBL and NB. Link MDL chain to NB.
            netBufferList = NdisAllocateNetBufferAndNetBufferList(
                                Adapter->ReceiveNblPool,
                                0,                  // ContextSize
                                0,                  // ContextBackFill
                                mdl,                // MDL chain
                                0,
                                packetLength
                                );

            if(netBufferList != NULL)
            {
                ULONG       receiveFlags = 0;
                LONG        nblCount;

                NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                if(KeGetCurrentIrql() == DISPATCH_LEVEL)
                {
                    receiveFlags |= NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
                }

                // Set flag indicating that this is an injected packet
                TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);
                TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED);

                netBufferList->MiniportReserved[0] = NULL;
                netBufferList->MiniportReserved[1] = NULL;

                // Increment in-flight receive NBL count.
                nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
                ASSERT(nblCount > 0 );

                netBufferList->SourceHandle = Adapter->MiniportAdapterHandle;

                //
                // Indicate the packet
                // -------------------
                // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
                // contains the complete packet including Ethernet header and payload.
                //
                NdisMIndicateReceiveNetBufferLists(
                    Adapter->MiniportAdapterHandle,
                    netBufferList,
                    NDIS_DEFAULT_PORT_NUMBER,
                    1,      // NumberOfNetBufferLists
                    receiveFlags
                    );

                return;
            }
            else
            {
                DEBUGP (("[%s] NdisAllocateNetBufferAndNetBufferList failed in IndicateReceivePacket\n",
                    MINIPORT_INSTANCE_ID (Adapter)));
                NOTE_ERROR ();

                NdisFreeMdl(mdl);
                NdisFreeMemory(injectBuffer,0,0);
            }
        }
        else
        {
            DEBUGP (("[%s] NdisAllocateMdl failed in IndicateReceivePacket\n",
                MINIPORT_INSTANCE_ID (Adapter)));
            NOTE_ERROR ();

            NdisFreeMemory(injectBuffer,0,0);
        }
    }
    else
    {
        DEBUGP (("[%s] NdisAllocateMemoryWithTagPriority failed in IndicateReceivePacket\n",
            MINIPORT_INSTANCE_ID (Adapter)));
        NOTE_ERROR ();
    }
}
Ejemplo n.º 11
0
NDIS_STATUS
HelperPortFlushBSSList(
    __in PMP_PORT                 Port
    )
{
    MP_RW_LOCK_STATE          LockState;
    PLIST_ENTRY         pListEntry;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    LONG                APRefCount;
    LIST_ENTRY          TempList;
    PMP_HELPER_PORT     HelperPort = MP_GET_HELPPORT(Port);
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    //
    // Entries that are currently in use (eg for connection)
    // we cannot flush and instead would put in the temporary queue
    //
    InitializeListHead(&TempList);
    
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);
        
    while (!IsListEmpty(&(pDiscoveredBSSList->List)))
    {
        pListEntry = RemoveHeadList(&(pDiscoveredBSSList->List));
        pBSSEntry = CONTAINING_RECORD(pListEntry, MP_BSS_ENTRY, Link);

        APRefCount = NdisInterlockedDecrement(&(pBSSEntry->RefCount));
        if (APRefCount == 0)
        {        
            NdisAcquireSpinLock(&(pBSSEntry->Lock));
            MPASSERT(pBSSEntry->pAssocRequest == NULL);
            MPASSERT(pBSSEntry->pAssocResponse == NULL);
            
            if (pBSSEntry->pDot11BeaconFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                pBSSEntry->pDot11BeaconFrame = NULL;
                pBSSEntry->BeaconFrameSize = 0;
                pBSSEntry->MaxBeaconFrameSize= 0;
            }

            if (pBSSEntry->pDot11ProbeFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                pBSSEntry->pDot11ProbeFrame = NULL;
                pBSSEntry->ProbeFrameSize = 0;
                pBSSEntry->MaxProbeFrameSize= 0;
            }
            
            pBSSEntry->pDot11InfoElemBlob = NULL;
            pBSSEntry->InfoElemBlobSize = 0;            
            NdisReleaseSpinLock(&(pBSSEntry->Lock));
            
            MP_FREE_MEMORY(pBSSEntry);        
        }
        else
        {
            // Restore refcount and save for adding back to list
            NdisInterlockedIncrement(&(pBSSEntry->RefCount));
            InsertTailList(&TempList, pListEntry);
        }
    }
    pDiscoveredBSSList->NumOfBSSEntries = 0;

    //
    // Restore entries that are in use
    //
    while (!IsListEmpty(&TempList))
    {
        pListEntry = RemoveHeadList(&TempList);

        InsertTailList(&(pDiscoveredBSSList->List), pListEntry);
        pDiscoveredBSSList->NumOfBSSEntries++;
    }

    // Since our scan list is flushed, also clear the last scan time
    HelperPort->ScanContext.LastScanTime = 0;
    
    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    return NDIS_STATUS_SUCCESS;
Ejemplo n.º 12
0
NTSTATUS
NdisProtWrite(
    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                   DataLength;
    NTSTATUS                NtStatus;
    NDIS_STATUS             Status;
    PNDISPROT_OPEN_CONTEXT   pOpenContext;
    PNDIS_PACKET            pNdisPacket;
    PNDIS_BUFFER            pNdisBuffer;
    NDISPROT_ETH_HEADER UNALIGNED *pEthHeader;
#ifdef NDIS51
    PVOID                   CancelId;
#endif

    UNREFERENCED_PARAMETER(pDeviceObject);

    pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
    pOpenContext = pIrpSp->FileObject->FsContext;

    pNdisPacket = NULL;

    do
    {
        if (pOpenContext == NULL)
        {
            DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n",
                             pIrpSp->FileObject));
            NtStatus = STATUS_INVALID_HANDLE;
            break;
        }

        NPROT_STRUCT_ASSERT(pOpenContext, oc);

        if (pIrp->MdlAddress == NULL)
        {
            DEBUGP(DL_FATAL, ("Write: NULL MDL address on IRP %p\n", pIrp));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
        }
        //
        // Try to get a virtual address for the MDL.
        //

        pEthHeader = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);

        if (pEthHeader == NULL)
        {
            DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for"
                              " IRP %p, MDL %p\n",
                              pIrp, pIrp->MdlAddress));
            NtStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        //
        // Sanity-check the length.
        //
        DataLength = MmGetMdlByteCount(pIrp->MdlAddress);
        if (DataLength < sizeof(NDISPROT_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(NDISPROT_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;
        }

        //
        // To prevent applications from sending packets with spoofed
        // mac address, we will do the following check to make sure the source
        // address in the packet is same as the current MAC address of the NIC.
        //
        if ((pIrp->RequestorMode == UserMode) &&
                !NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN))
        {
            DEBUGP(DL_WARN, ("Write: Failing with invalid Source address"));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
        }

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);

        if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock);

            DEBUGP(DL_FATAL, ("Write: Open %p is not bound"
                              " or in low power state\n", pOpenContext));

            NtStatus = STATUS_INVALID_HANDLE;
            break;
        }

        //
        //  Allocate a send packet.
        //
        NPROT_ASSERT(pOpenContext->SendPacketPool != NULL);
        NdisAllocatePacket(
            &Status,
            &pNdisPacket,
            pOpenContext->SendPacketPool);

        if (Status != NDIS_STATUS_SUCCESS)
        {
            NPROT_RELEASE_LOCK(&pOpenContext->Lock);

            DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send pkt\n",
                              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)
            {
                NPROT_RELEASE_LOCK(&pOpenContext->Lock);

                NdisFreePacket(pNdisPacket);

                DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send buf\n",
                                  pOpenContext));
                NtStatus = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }
        }
        else
        {
            pNdisBuffer = pIrp->MdlAddress;
        }

        NdisInterlockedIncrement((PLONG)&pOpenContext->PendedSendCount);

        NPROT_REF_OPEN(pOpenContext);  // pended send

        IoMarkIrpPending(pIrp);

        //
        //  Initialize the packet ref count. This packet will be freed
        //  when this count goes to zero.
        //
        NPROT_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 = NPROT_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;

        NPROT_INSERT_TAIL_LIST(&pOpenContext->PendedWrites, &pIrp->Tail.Overlay.ListEntry);

        IoSetCancelRoutine(pIrp, NdisProtCancelWrite);

#endif // NDIS51

        NPROT_RELEASE_LOCK(&pOpenContext->Lock);

        //
        //  Set a back pointer from the packet to the IRP.
        //
        NPROT_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp;

        NtStatus = STATUS_PENDING;

        pNdisBuffer->Next = NULL;
        NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);

#if SEND_DBG
        {
            PUCHAR      pData;

            pData = MmGetSystemAddressForMdlSafe(pNdisBuffer, NormalPagePriority);
            NPROT_ASSERT(pEthHeader == pData);

            DEBUGP(DL_VERY_LOUD,
                   ("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytes\n",
                    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);
}
Ejemplo n.º 13
0
//
// FilterOidRequest Function
// http://msdn.microsoft.com/en-us/library/ff549954(v=VS.85).aspx
//
_Use_decl_annotations_
NDIS_STATUS
SxNdisOidRequest(
    NDIS_HANDLE FilterModuleContext,
    PNDIS_OID_REQUEST OidRequest
    )
{
    PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
    NDIS_STATUS status;
    PNDIS_OID_REQUEST clonedRequest=NULL;
    PVOID *cloneRequestContext;
    BOOLEAN completeOid = FALSE;
    ULONG bytesNeeded = 0;
   
    status = NDIS_STATUS_SUCCESS;

    DEBUGP(DL_TRACE, ("===>SxOidRequest: OidRequest %p.\n", OidRequest));
    
    NdisInterlockedIncrement(&switchObject->PendingOidCount);

    status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle,
                                         OidRequest,
                                         SxExtAllocationTag,
                                         &clonedRequest);
    if (status != NDIS_STATUS_SUCCESS)
    {
        DEBUGP(DL_WARN, ("FilerOidRequest: Cannot Clone OidRequest\n"));
        goto Cleanup;
    }

    cloneRequestContext = (PVOID*)(&clonedRequest->SourceReserved[0]);
    *cloneRequestContext = OidRequest;
    
    switch (clonedRequest->RequestType)
    {           
        case NdisRequestSetInformation:
            status = SxpNdisProcessSetOid(switchObject,
                                          clonedRequest,
                                          &completeOid);
            break;
        
        case NdisRequestMethod:
            status = SxpNdisProcessMethodOid(switchObject,
                                             clonedRequest,
                                             &completeOid,
                                             &bytesNeeded);

            break;
    }
    
    if (completeOid)
    {
        NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedRequest);
        OidRequest->DATA.METHOD_INFORMATION.BytesNeeded = bytesNeeded;
        NdisInterlockedDecrement(&switchObject->PendingOidCount);
        goto Cleanup;
    }

    status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedRequest);

    if (status != NDIS_STATUS_PENDING)
    {
        SxNdisOidRequestComplete(switchObject, clonedRequest, status);

        //
        // We must still return status as pending because we complete the
        // request using NdisFOidRequestComplete() in SxOidRequestComplete().
        //
        status = NDIS_STATUS_PENDING;
    }

Cleanup:

    DEBUGP(DL_TRACE, ("<===SxOidRequest: status %8x.\n", status));
    return status;
}
Ejemplo n.º 14
0
VOID
NICPostReadsWorkItemCallBack(
    PNDIS_WORK_ITEM WorkItem, 
    PVOID Context
    )
/*++

Routine Description:

   Workitem to post all the free read requests to the target
   driver. This workitme is scheduled from the MiniportInitialize
   worker routine during start and also from the NICFreeRCB whenever
   the outstanding read requests to the target driver goes below
   the NIC_SEND_LOW_WATERMARK.
      
Arguments:

    WorkItem - Pointer to workitem
    
    Dummy - Unused

Return Value:

    None.

--*/
{
    PMP_ADAPTER     Adapter = (PMP_ADAPTER)Context;
    NTSTATUS        ntStatus;
    PRCB            pRCB=NULL;

    UNREFERENCED_PARAMETER(WorkItem);
           
    DEBUGP(MP_TRACE, ("--->NICPostReadsWorkItemCallBack\n"));

    NdisAcquireSpinLock(&Adapter->RecvLock);

    while(MP_IS_READY(Adapter) && !IsListEmpty(&Adapter->RecvFreeList))
    {
        pRCB = (PRCB) RemoveHeadList(&Adapter->RecvFreeList);

        ASSERT(pRCB);// cannot be NULL
        
        //
        // Insert the RCB in the recv busy queue
        //     
        NdisInterlockedIncrement(&Adapter->nBusyRecv);          
        ASSERT(Adapter->nBusyRecv <= NIC_MAX_BUSY_RECVS);
        
        InsertTailList(&Adapter->RecvBusyList, &pRCB->List);

        NdisReleaseSpinLock(&Adapter->RecvLock);

        Adapter->nReadsPosted++;
        ntStatus = NICPostReadRequest(Adapter, pRCB);
        
        if (!NT_SUCCESS ( ntStatus ) ) {
            
            DEBUGP (MP_ERROR, ( "NICPostReadRequest failed %x\n", ntStatus ));
            break;            
        }
        
        NdisAcquireSpinLock(&Adapter->RecvLock);
        
    }

    NdisReleaseSpinLock(&Adapter->RecvLock);

    //
    // Clear the flag to let the WorkItem structure be reused for
    // scheduling another one.
    //
    InterlockedExchange(&Adapter->IsReadWorkItemQueued, FALSE);

    
    MP_DEC_REF(Adapter);     
    
    DEBUGP(MP_TRACE, ("<---NICPostReadsWorkItemCallBack\n"));        
}
Ejemplo n.º 15
0
VOID
NICIndicateReceivedPacket(
    IN PRCB             pRCB,
	IN ULONG            dataoffset,
    IN ULONG            BytesToIndicate,
	IN ULONG            PacketNum
    )
/*++

Routine Description:

    Initialize the packet to describe the received data and
    indicate to NDIS.
        
Arguments:

    pRCB - pointer to the RCB block    
    BytesToIndicate - number of bytes to indicate

Return value:

    VOID
--*/
{
    ULONG           PacketLength;
    PNDIS_BUFFER    CurrentBuffer = NULL;
    PETH_HEADER     pEthHeader = NULL;
    PMP_ADAPTER     Adapter = pRCB->Adapter;
    KIRQL           oldIrql;	
	PVOID  VirtualAddress=NULL;
	ASSERT(     PacketNum   <    RCB_BUFFERARRAY_SIZE);
	ASSERT((dataoffset+BytesToIndicate) <  pRCB->ulBufferSize);


    

	
    //NdisAdjustBufferLength(pRCB->Buffer, BytesToIndicate);
	//MmInitializeMdl(pRCB->BufferArray[PacketNum],pRCB->pDataForNTB+dataoffset,BytesToIndicate);
	VirtualAddress=MmGetMdlVirtualAddress(pRCB->BufferArray[PacketNum]);
	ASSERT(VirtualAddress!=NULL);
	NdisMoveMemory(VirtualAddress,pRCB->pDataForNTB+dataoffset,BytesToIndicate);
	NdisAdjustBufferLength(pRCB->BufferArray[PacketNum], BytesToIndicate);
	//NdisMoveMemory(pRCB->pDataForNet+NIC_BUFFER_SIZE*PacketNum,pRCB->pDataForNTB+dataoffset,BytesToIndicate);
    //
    // Prepare the recv packet
    //

    NdisReinitializePacket(pRCB->PacketArray[PacketNum]);

    *((PRCB *)pRCB->PacketArray[PacketNum]->MiniportReserved) = pRCB;

    //
    // Chain the TCB buffers to the packet
    //
    NdisChainBufferAtBack(pRCB->PacketArray[PacketNum], pRCB->BufferArray[PacketNum]);

    NdisQueryPacket(pRCB->PacketArray[PacketNum], NULL, NULL, &CurrentBuffer, (PUINT) &PacketLength);

    ASSERT(CurrentBuffer == pRCB->BufferArray[PacketNum]);

    pEthHeader = (PETH_HEADER)(pRCB->pDataForNTB+dataoffset);

    if(PacketLength >= sizeof(ETH_HEADER) && 
        Adapter->PacketFilter &&
        NICIsPacketAcceptable(Adapter, pEthHeader->DstAddr)){
            
        DEBUGP(MP_LOUD, ("Src Address = %02x-%02x-%02x-%02x-%02x-%02x", 
            pEthHeader->SrcAddr[0],
            pEthHeader->SrcAddr[1],
            pEthHeader->SrcAddr[2],
            pEthHeader->SrcAddr[3],
            pEthHeader->SrcAddr[4],
            pEthHeader->SrcAddr[5]));

        DEBUGP(MP_LOUD, ("  Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n", 
            pEthHeader->DstAddr[0],
            pEthHeader->DstAddr[1],
            pEthHeader->DstAddr[2],
            pEthHeader->DstAddr[3],
            pEthHeader->DstAddr[4],
            pEthHeader->DstAddr[5]));

        DEBUGP(MP_LOUD, ("Indicating packet = %p, Packet Length = %d\n", 
                            pRCB->PacketArray[PacketNum], PacketLength));

        NdisInterlockedIncrement(&pRCB->Ref);


        NDIS_SET_PACKET_STATUS(pRCB->PacketArray[PacketNum], NDIS_STATUS_SUCCESS);
        Adapter->nPacketsIndicated++;

        //
        // NDIS expects the indication to happen at DISPATCH_LEVEL if the
        // device is assinged any I/O resources in the IRP_MN_START_DEVICE_IRP.
        // Since this sample is flexible enough to be used as a standalone
        // virtual miniport talking to another device or part of a WDM stack for
        // devices consuming hw resources such as ISA, PCI, PCMCIA. I have to
        // do the following check. You should avoid raising the IRQL, if you
        // know for sure that your device wouldn't have any I/O resources. This
        // would be the case if your driver is talking to USB, 1394, etc.
        //
        if(Adapter->IsHardwareDevice){
            
            KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
            NdisMIndicateReceivePacket(Adapter->AdapterHandle,
                            &pRCB->PacketArray[PacketNum],
                            1);
            KeLowerIrql(oldIrql);            
            
        }else{
        
            NdisMIndicateReceivePacket(Adapter->AdapterHandle,
                            &pRCB->PacketArray[PacketNum],
                            1);
        }

    }else {
        DEBUGP(MP_VERY_LOUD, 
                ("Invalid packet or filter is not set packet = %p,Packet Length = %d\n",
                pRCB->PacketArray, PacketLength));        
    }            

}
Ejemplo n.º 16
0
VOID
NICPostInterruptNotifyItemCallBack(
    PNDIS_WORK_ITEM WorkItem, 
    PVOID Context
    )
/*++

Routine Description:

   Workitem to post all the free read requests to the target
   driver. This workitme is scheduled from the MiniportInitialize
   worker routine during start and also from the NICFreeRCB whenever
   the outstanding read requests to the target driver goes below
   the NIC_SEND_LOW_WATERMARK.
      
Arguments:

    WorkItem - Pointer to workitem
    
    Dummy - Unused

Return Value:

    None.

--*/
{


	PMP_ADAPTER     Adapter = (PMP_ADAPTER)Context;
	NTSTATUS        ntStatus;
	PNOTICB            pNotiCB=NULL;

	UNREFERENCED_PARAMETER(WorkItem);

	DEBUGP(MP_TRACE, ("--->NICPostInterruptNotifyItemCallBack\n"));

	NdisAcquireSpinLock(&Adapter->InterruptNotifyLock);

	while(MP_IS_READY(Adapter) && !IsListEmpty(&Adapter->InterruptFreeList))
	{
		pNotiCB = (PNOTICB) RemoveHeadList(&Adapter->InterruptFreeList);

		ASSERT(pNotiCB);// cannot be NULL

		//
		// Insert the RCB in the recv busy queue
		//     
		NdisInterlockedIncrement(&Adapter->nBusyNotify);          
		ASSERT(Adapter->nBusyNotify <= NOTICB_BUFFER_COUNT);

		InsertTailList(&Adapter->InterruptBusyList, &pNotiCB->List);

		NdisReleaseSpinLock(&Adapter->InterruptNotifyLock);

		ntStatus = NICPostInterruptRequest(Adapter, pNotiCB);

		if (!NT_SUCCESS ( ntStatus ) ) {

			DEBUGP (MP_ERROR, ( "NICPostInterruptRequest failed %x\n", ntStatus ));
			break;            
		}

		NdisAcquireSpinLock(&Adapter->InterruptNotifyLock);

	}

	NdisReleaseSpinLock(&Adapter->InterruptNotifyLock);

	MP_DEC_REF(Adapter);     

	DEBUGP(MP_TRACE, ("<---NICPostInterruptNotifyItemCallBack\n"));         
}
Ejemplo n.º 17
0
NDIS_STATUS
SxLibIssueOidRequest(
    _In_ PSX_SWITCH_OBJECT Switch,
    _In_ NDIS_REQUEST_TYPE RequestType,
    _In_ NDIS_OID Oid,
    _In_opt_ PVOID InformationBuffer,
    _In_ ULONG InformationBufferLength,
    _In_ ULONG OutputBufferLength,
    _In_ ULONG MethodId,
    _In_ UINT Timeout,
    _Out_ PULONG BytesNeeded
    )
{
    NDIS_STATUS status;
    PSX_OID_REQUEST oidRequest;
    PNDIS_OID_REQUEST ndisOidRequest;
    ULONG bytesNeeded;
    BOOLEAN asyncCompletion;

    status = NDIS_STATUS_SUCCESS;
    oidRequest = NULL;
    bytesNeeded = 0;
    asyncCompletion = FALSE;

    NdisInterlockedIncrement(&Switch->PendingOidCount);

    if (Switch->ControlFlowState != SxSwitchAttached)
    {
        status = NDIS_STATUS_CLOSING;
        goto Cleanup;
    }

    //
    // Dynamically allocate filter request so that we can handle asynchronous
    // completion.
    //
    oidRequest = (PSX_OID_REQUEST)ExAllocatePoolWithTag(NonPagedPoolNx,
                                                        sizeof(SX_OID_REQUEST),
                                                        SxExtAllocationTag);
    if (oidRequest == NULL)
    {
        goto Cleanup;
    }

    NdisZeroMemory(oidRequest, sizeof(SX_OID_REQUEST));
    ndisOidRequest = &oidRequest->NdisOidRequest;
    NdisInitializeEvent(&oidRequest->ReqEvent);

    ndisOidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
    ndisOidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
    ndisOidRequest->Header.Size = sizeof(NDIS_OID_REQUEST);
    ndisOidRequest->RequestType = RequestType;
    ndisOidRequest->Timeout = Timeout;

    switch (RequestType)
    {
    case NdisRequestQueryInformation:
         ndisOidRequest->DATA.QUERY_INFORMATION.Oid = Oid;
         ndisOidRequest->DATA.QUERY_INFORMATION.InformationBuffer =
             InformationBuffer;
         ndisOidRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
             InformationBufferLength;
        break;

    case NdisRequestSetInformation:
         ndisOidRequest->DATA.SET_INFORMATION.Oid = Oid;
         ndisOidRequest->DATA.SET_INFORMATION.InformationBuffer =
             InformationBuffer;
         ndisOidRequest->DATA.SET_INFORMATION.InformationBufferLength =
             InformationBufferLength;
        break;

    case NdisRequestMethod:
         ndisOidRequest->DATA.METHOD_INFORMATION.Oid = Oid;
         ndisOidRequest->DATA.METHOD_INFORMATION.MethodId = MethodId;
         ndisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer =
             InformationBuffer;
         ndisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength =
             InformationBufferLength;
         ndisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength =
             OutputBufferLength;
         break;

    default:
        NT_ASSERT(FALSE);
        break;
    }

    ndisOidRequest->RequestId = (PVOID)SxExtOidRequestId;
    status = NdisFOidRequest(Switch->NdisFilterHandle, ndisOidRequest);

    if (status == NDIS_STATUS_PENDING)
    {
        asyncCompletion = TRUE;
        NdisWaitEvent(&oidRequest->ReqEvent, 0);
    }
    else
    {
        SxpNdisCompleteInternalOidRequest(Switch, ndisOidRequest, status);
    }

    bytesNeeded = oidRequest->BytesNeeded;
    status = oidRequest->Status;

Cleanup:

    if (BytesNeeded != NULL)
    {
        *BytesNeeded = bytesNeeded;
    }
    
    if (!asyncCompletion)
    {
        NdisInterlockedDecrement(&Switch->PendingOidCount);
    }
    
    if (oidRequest != NULL)
    {
        ExFreePoolWithTag(oidRequest, SxExtAllocationTag);
    }
    
    return status;
}
/******************************************************
Required NDIS procedure
Allocates and initializes adapter context
Finally sets send and receive to Enabled state and reports connect
Returns:
NDIS_STATUS SUCCESS or some error code
*******************************************************/
static NDIS_STATUS ParaNdis5_Initialize(OUT PNDIS_STATUS OpenErrorStatus,
                                    OUT PUINT SelectedMediumIndex,
                                    IN PNDIS_MEDIUM MediumArray,
                                    IN UINT MediumArraySize,
                                    IN NDIS_HANDLE MiniportAdapterHandle,
                                    IN NDIS_HANDLE WrapperConfigurationContext)
{
    NDIS_STATUS  status = NDIS_STATUS_UNSUPPORTED_MEDIA;
    PARANDIS_ADAPTER *pContext = NULL;
    UINT i;
    for(i = 0; i < MediumArraySize; ++i)
    {
        if(MediumArray[i] == NdisMedium802_3)
        {
            *SelectedMediumIndex = i;
            status = NDIS_STATUS_SUCCESS;
            break;
        }
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        pContext =
            (PARANDIS_ADAPTER *)ParaNdis_AllocateMemory(NULL, sizeof(PARANDIS_ADAPTER));
        if (!pContext)
        {
            status = NDIS_STATUS_RESOURCES;
        }
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        PVOID pResourceList = &status;
        UINT  uSize = 0;
        NdisZeroMemory(pContext, sizeof(PARANDIS_ADAPTER));
        pContext->ulUniqueID = NdisInterlockedIncrement(&gID);
        pContext->DriverHandle = DriverHandle;
        pContext->MiniportHandle = MiniportAdapterHandle;
        pContext->WrapperConfigurationHandle = WrapperConfigurationContext;
        NdisMQueryAdapterResources(&status, WrapperConfigurationContext, pResourceList, &uSize);
        if (uSize > 0)
            pResourceList = ParaNdis_AllocateMemory(MiniportAdapterHandle, uSize);
        else
            pResourceList = NULL;
        if (!pResourceList)
            status = uSize > 0 ? NDIS_STATUS_RESOURCES : NDIS_STATUS_FAILURE;
        else
        {
            ULONG attributes;
            attributes = NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_BUS_MASTER;
            // in XP SP2, if this flag is NOT set, the NDIS halts miniport
            // upon transition to S1..S4.
            // it seems that XP SP3 ignores it and always sends SET_POWER to D3
#ifndef NO_XP_POWER_MANAGEMENT
            attributes |= NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
#endif
            NdisMSetAttributesEx(
                MiniportAdapterHandle,
                pContext,
                0,
                attributes,
                NdisInterfacePci);
            NdisMQueryAdapterResources(&status, WrapperConfigurationContext, pResourceList, &uSize);
            status = ParaNdis_InitializeContext(pContext, (PNDIS_RESOURCE_LIST)pResourceList);
            NdisFreeMemory(pResourceList, 0, 0);
        }
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        status = ParaNdis_FinishInitialization(pContext);
        if (status == NDIS_STATUS_SUCCESS)
        {
            ParaNdis_DebugRegisterMiniport(pContext, TRUE);
            ParaNdis_IndicateConnect(pContext, FALSE, TRUE);
            ParaNdis5_StopSend(pContext, FALSE, NULL);
            ParaNdis5_StopReceive(pContext, FALSE, NULL);
            if (!pContext->ulMilliesToConnect)
            {
                ParaNdis_ReportLinkStatus(pContext, FALSE);
            }
            else
            {
                NdisSetTimer(&pContext->ConnectTimer, pContext->ulMilliesToConnect);
            }
        }
        else
        {
            ParaNdis_CleanupContext(pContext);
        }
    }

    if (status != NDIS_STATUS_SUCCESS && pContext)
    {
        NdisFreeMemory(pContext, 0, 0);
    }

    DEBUG_EXIT_STATUS(0, status);
    return status;
}
/**********************************************************
Required NDIS handler
Initialize adapter context, prepare it for operation,
set in PAUSED STATE
Return value:
    SUCCESS or kind of error
***********************************************************/
static NDIS_STATUS ParaNdis6_Initialize(
    NDIS_HANDLE miniportAdapterHandle,
    NDIS_HANDLE miniportDriverContext,
    PNDIS_MINIPORT_INIT_PARAMETERS miniportInitParameters)
{
    NDIS_MINIPORT_ADAPTER_ATTRIBUTES        miniportAttributes;
    NDIS_STATUS  status = NDIS_STATUS_SUCCESS;
    BOOLEAN bNoPauseOnSuspend = FALSE;
    PARANDIS_ADAPTER *pContext;

    UNREFERENCED_PARAMETER(miniportDriverContext);
    DEBUG_ENTRY(0);
#pragma warning( suppress: 28197)
    /* allocate context structure */
    pContext = (PARANDIS_ADAPTER *)
        NdisAllocateMemoryWithTagPriority(
            miniportAdapterHandle,
            sizeof(PARANDIS_ADAPTER),
            PARANDIS_MEMORY_TAG,
            NormalPoolPriority);

    /* This call is for Static Driver Verifier only - has no real functionality*/
    __sdv_save_adapter_context(pContext);

    if (!pContext)
    {
        DPrintf(0, ("[%s] ERROR: Memory allocation failed!\n", __FUNCTION__));
        status = NDIS_STATUS_RESOURCES;
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        /* set mandatory fields which Common use */
        NdisZeroMemory(pContext, sizeof(PARANDIS_ADAPTER));
        pContext->ulUniqueID = NdisInterlockedIncrement(&gID);
        pContext->DriverHandle = DriverHandle;
        pContext->MiniportHandle = miniportAdapterHandle;
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes));
        miniportAttributes.RegistrationAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
        miniportAttributes.RegistrationAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
        miniportAttributes.RegistrationAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
        miniportAttributes.RegistrationAttributes.MiniportAdapterContext = pContext;
        miniportAttributes.RegistrationAttributes.AttributeFlags =
            // actual for USB
            // NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK
            NDIS_MINIPORT_ATTRIBUTES_HARDWARE_DEVICE |
            NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER;
#ifndef NO_VISTA_POWER_MANAGEMENT
        miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
#endif
#if NDIS_SUPPORT_NDIS630
        miniportAttributes.RegistrationAttributes.AttributeFlags |= NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND;
        bNoPauseOnSuspend = TRUE;
#endif
        miniportAttributes.RegistrationAttributes.CheckForHangTimeInSeconds = 4;
        miniportAttributes.RegistrationAttributes.InterfaceType = NdisInterfacePci;
        status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes);
        if (status != NDIS_STATUS_SUCCESS)
        {
            DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 1 failed (%X)!\n", __FUNCTION__, status));
        }
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        /* prepare statistics struct for further reports */
        pContext->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
        pContext->Statistics.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
        pContext->Statistics.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
        /* let Common do all the rest */
        status = ParaNdis_InitializeContext(pContext, miniportInitParameters->AllocatedResources);
        if (status != NDIS_STATUS_SUCCESS)
        {
            DPrintf(0, ("[%s] ERROR: ParaNdis6_InitializeContext failed (%X)!\n", __FUNCTION__, status));
        }
        pContext->bNoPauseOnSuspend = bNoPauseOnSuspend; 
    }

    if (status == NDIS_STATUS_SUCCESS)
    {
        ULONG i;
        NDIS_PNP_CAPABILITIES power60Caps;
#if NDIS_SUPPORT_NDIS620
        NDIS_PM_CAPABILITIES power620Caps;
#endif
#ifdef NO_VISTA_POWER_MANAGEMENT
        pPowerCaps = NULL;
#endif
        ParaNdis_FillPowerCapabilities(&power60Caps);

        NdisZeroMemory(&miniportAttributes, sizeof(miniportAttributes));
        miniportAttributes.GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
        miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
        miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
#if NDIS_SUPPORT_NDIS620
        miniportAttributes.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
        miniportAttributes.GeneralAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
        miniportAttributes.GeneralAttributes.PowerManagementCapabilitiesEx = &power620Caps;
        ParaNdis6_Fill620PowerCapabilities(&power620Caps);
#else
        miniportAttributes.GeneralAttributes.PowerManagementCapabilities = &power60Caps;
#endif
        miniportAttributes.GeneralAttributes.MediaType = NdisMedium802_3;
        miniportAttributes.GeneralAttributes.PhysicalMediumType = NdisPhysicalMedium802_3;
        miniportAttributes.GeneralAttributes.MtuSize = pContext->MaxPacketSize.nMaxDataSize;
        miniportAttributes.GeneralAttributes.LookaheadSize = pContext->MaxPacketSize.nMaxFullSizeOS;
        miniportAttributes.GeneralAttributes.MaxXmitLinkSpeed =
        miniportAttributes.GeneralAttributes.MaxRcvLinkSpeed  =  PARANDIS_FORMAL_LINK_SPEED;
        miniportAttributes.GeneralAttributes.MediaConnectState =
            pContext->bConnected ? MediaConnectStateConnected : MediaConnectStateDisconnected;
        miniportAttributes.GeneralAttributes.XmitLinkSpeed =
        miniportAttributes.GeneralAttributes.RcvLinkSpeed = pContext->bConnected ?
            PARANDIS_FORMAL_LINK_SPEED : NDIS_LINK_SPEED_UNKNOWN;
        miniportAttributes.GeneralAttributes.MediaDuplexState = MediaDuplexStateFull;
        miniportAttributes.GeneralAttributes.MacOptions =
                    NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |       /* NIC has no internal loopback support */
                    NDIS_MAC_OPTION_TRANSFERS_NOT_PEND  |       /* Must be set since using  NdisMIndicateReceivePacket */
                    NDIS_MAC_OPTION_NO_LOOPBACK;                /* NIC has no internal loopback support */
        if (IsPrioritySupported(pContext))
            miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY;
        if (IsVlanSupported(pContext))
            miniportAttributes.GeneralAttributes.MacOptions |= NDIS_MAC_OPTION_8021Q_VLAN;
        miniportAttributes.GeneralAttributes.SupportedPacketFilters = PARANDIS_PACKET_FILTERS;
        miniportAttributes.GeneralAttributes.MaxMulticastListSize = PARANDIS_MULTICAST_LIST_SIZE;
        miniportAttributes.GeneralAttributes.MacAddressLength =     ETH_LENGTH_OF_ADDRESS;

#if PARANDIS_SUPPORT_RSS
        if(pContext->bRSSOffloadSupported)
        {
            miniportAttributes.GeneralAttributes.RecvScaleCapabilities =
                ParaNdis6_RSSCreateConfiguration(
                                                &pContext->RSSParameters,
                                                &pContext->RSSCapabilities,
                                                pContext->RSSMaxQueuesNumber);
            pContext->bRSSInitialized = TRUE;
        }
#endif

        for(i = 0; i < ARRAYSIZE(pContext->ReceiveQueues); i++)
        {
            NdisAllocateSpinLock(&pContext->ReceiveQueues[i].Lock);
            InitializeListHead(&pContext->ReceiveQueues[i].BuffersList);

            pContext->ReceiveQueues[i].BatchReceiveArray =
                ParaNdis_AllocateMemory(pContext, sizeof(*pContext->ReceiveQueues[i].BatchReceiveArray)*pContext->NetMaxReceiveBuffers);
            if(!pContext->ReceiveQueues[i].BatchReceiveArray)
            {
                pContext->ReceiveQueues[i].BatchReceiveArray = &pContext->ReceiveQueues[i].BatchReceiveEmergencyItem;
                pContext->ReceiveQueues[i].BatchReceiveArraySize = 1;
            }
            else
            {
                pContext->ReceiveQueues[i].BatchReceiveArraySize = pContext->NetMaxReceiveBuffers;
            }
        }

        pContext->ReceiveQueuesInitialized = TRUE;

        miniportAttributes.GeneralAttributes.AccessType = NET_IF_ACCESS_BROADCAST;
        miniportAttributes.GeneralAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
        miniportAttributes.GeneralAttributes.IfType = IF_TYPE_ETHERNET_CSMACD;
        miniportAttributes.GeneralAttributes.IfConnectorPresent = TRUE;
        miniportAttributes.GeneralAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;

        ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.PermanentMacAddress, pContext->PermanentMacAddress);
        ETH_COPY_NETWORK_ADDRESS(miniportAttributes.GeneralAttributes.CurrentMacAddress, pContext->CurrentMacAddress);

        ParaNdis6_GetSupportedOid(&miniportAttributes.GeneralAttributes);
        /* update also SupportedStatistics in ready to use statistics block */
        pContext->Statistics.SupportedStatistics = ParaNdis6_GetSupportedStatisticsFlags();
        status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes);
        if (status != NDIS_STATUS_SUCCESS)
        {
            DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 2 failed (%X)!\n", __FUNCTION__, status));
        }
    }

    if (pContext && status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
    {
        // no need to cleanup
        NdisFreeMemory(pContext, 0, 0);
        pContext = NULL;
    }

    if (pContext && status == NDIS_STATUS_SUCCESS)
    {
        status = ParaNdis_FinishInitialization(pContext);
        if (status != NDIS_STATUS_SUCCESS)
        {
            ParaNdis_CleanupContext(pContext);
            NdisFreeMemory(pContext, 0, 0);
            pContext = NULL;
        }
    }
    if (pContext && status == NDIS_STATUS_SUCCESS)
    {
        if (NDIS_STATUS_SUCCESS ==
            ParaNdis6_GetRegistrationOffloadInfo(pContext,
                &miniportAttributes.OffloadAttributes))
            status = NdisMSetMiniportAttributes(miniportAdapterHandle, &miniportAttributes);
            if (status != NDIS_STATUS_SUCCESS)
            {
                DPrintf(0, ("[%s] ERROR: NdisMSetMiniportAttributes 3 failed (%X)!\n", __FUNCTION__, status));
            }
    }

    if (pContext && status == NDIS_STATUS_SUCCESS)
    {
        ParaNdis_DebugRegisterMiniport(pContext, TRUE);
    }

    DEBUG_EXIT_STATUS(status ? 0 : 2, status);
    return status;
}
Ejemplo n.º 20
0
NDIS_STATUS
Hw11Allocate(
    __in  NDIS_HANDLE             MiniportAdapterHandle,
    __deref_out_opt PHW*          Hw,
    __in  PADAPTER                Adapter
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PHW                         newHw = NULL;
    ULONG                       size;
    NDIS_TIMER_CHARACTERISTICS  timerChar;               

    *Hw = NULL;
    do
    {
        // Allocate a HW data structure
        MP_ALLOCATE_MEMORY(MiniportAdapterHandle, &newHw, sizeof(HW), HW_MEMORY_TAG);
        if (newHw == NULL)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate %d bytes for HW\n",
                                 sizeof(HW)));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }

        // Clear everything
        NdisZeroMemory(newHw, sizeof(HW));

        // We start in the PAUSED state
        HW_SET_ADAPTER_STATUS(newHw, HW_ADAPTER_PAUSED);
        newHw->InterruptDisableCount = 1;       // Since we are paused, we want the interrupts to be disabled
#if DBG
        NdisInterlockedIncrement(&newHw->Tracking_InterruptDisable[HW_ISR_TRACKING_PAUSE]);
#endif
        
        // Allocate memory for fields inside the HW structure
        size = sizeof(DOT11_REG_DOMAINS_SUPPORT_VALUE) + 
               (HW_MAX_NUM_DOT11_REG_DOMAINS_VALUE - 1) * sizeof(DOT11_REG_DOMAIN_VALUE);
        MP_ALLOCATE_MEMORY(MiniportAdapterHandle,
                           &(newHw->PhyState.RegDomainsSupportValue),
                           size,
                           HW_MEMORY_TAG);
        if (newHw->PhyState.RegDomainsSupportValue == NULL)
        {
            MpTrace(COMP_INIT_PNP,
                    DBG_SERIOUS,
                    ("Failed to allocate memory for RegDomainsSupportValue\n"));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        NdisZeroMemory(newHw->PhyState.RegDomainsSupportValue, size);

        size = sizeof(DOT11_DIVERSITY_SELECTION_RX_LIST) +
              (HW_MAX_NUM_DIVERSITY_SELECTION_RX_LIST - 1) * sizeof(DOT11_DIVERSITY_SELECTION_RX);
        MP_ALLOCATE_MEMORY(MiniportAdapterHandle,
                           &(newHw->PhyState.DiversitySelectionRxList),
                           size, 
                           HW_MEMORY_TAG);
        if (newHw->PhyState.DiversitySelectionRxList == NULL) 
        {
            MpTrace(COMP_INIT_PNP,
                    DBG_SERIOUS,
                    ("Failed to allocate memory for DiversitySelectionRxList\n"));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        NdisZeroMemory(newHw->PhyState.DiversitySelectionRxList, size);        

        NdisZeroMemory(&timerChar, sizeof(NDIS_TIMER_CHARACTERISTICS));
        
        // Allocate the power save wake timer
        timerChar.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;
        timerChar.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;
        timerChar.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);
        timerChar.AllocationTag = HW_MEMORY_TAG;
        
        timerChar.TimerFunction = HwAwakeTimer;
        timerChar.FunctionContext = newHw;

        ndisStatus = NdisAllocateTimerObject(
                        MiniportAdapterHandle,
                        &timerChar,
                        &newHw->PhyState.Timer_Awake
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate power save awake timer\n"));
            break;
        }

        // Allocate the power save sleep timer
        timerChar.TimerFunction = HwDozeTimer;
        timerChar.FunctionContext = newHw;

        ndisStatus = NdisAllocateTimerObject(
                        MiniportAdapterHandle,
                        &timerChar,
                        &newHw->PhyState.Timer_Doze
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate power save doze timer\n"));
            break;
        }
        
        // Allocate the scan timer
        timerChar.TimerFunction = HwScanTimer;
        timerChar.FunctionContext = newHw;

        ndisStatus = NdisAllocateTimerObject(
                        MiniportAdapterHandle,
                        &timerChar,
                        &newHw->ScanContext.Timer_Scan
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate scan timer\n"));
            break;
        }

        newHw->PhyState.PhyProgramWorkItem = NdisAllocateIoWorkItem(MiniportAdapterHandle);
        if(newHw->PhyState.PhyProgramWorkItem == NULL)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate channel switch work item\n"));
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }

        // The hardware lock
        NdisAllocateSpinLock(&newHw->Lock);

        // Save the Adapter pointer in the HW
        newHw->Adapter = Adapter;
        newHw->MiniportAdapterHandle = MiniportAdapterHandle;

        // Return the newly created structure to the caller
        *Hw = newHw;

    } while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        if (newHw != NULL)
        {
            Hw11Free(newHw);
        }
    }

    return ndisStatus;
}
Ejemplo n.º 21
0
// IRP_MJ_WRITE callback.
NTSTATUS
TapDeviceWrite(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )
{
    NTSTATUS                ntStatus = STATUS_SUCCESS;// Assume success
    PIO_STACK_LOCATION      irpSp;// Pointer to current stack location
    PTAP_ADAPTER_CONTEXT    adapter = NULL;
    ULONG                   dataLength;

    PAGED_CODE();

    irpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    // Fetch adapter context for this device.
    // --------------------------------------
    // Adapter pointer was stashed in FsContext when handle was opened.
    //
    adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;

    ASSERT(adapter);

    //
    // Sanity checks on state variables
    //
    if (!tapAdapterReadAndWriteReady(adapter))
    {
        //DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
        //    MINIPORT_INSTANCE_ID (adapter)));
        //NOTE_ERROR();

        Irp->IoStatus.Status = ntStatus = STATUS_CANCELLED;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    // Save IRP-accessible copy of buffer length
    Irp->IoStatus.Information = irpSp->Parameters.Write.Length;

    if (Irp->MdlAddress == NULL)
    {
        DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
            MINIPORT_INSTANCE_ID (adapter)));

        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    //
    // Try to get a virtual address for the MDL.
    //
    NdisQueryMdl(
        Irp->MdlAddress,
        &Irp->AssociatedIrp.SystemBuffer,
        &dataLength,
        NormalPagePriority
        );

    if (Irp->AssociatedIrp.SystemBuffer == NULL)
    {
        DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
            MINIPORT_INSTANCE_ID (adapter)));

        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    ASSERT(dataLength == irpSp->Parameters.Write.Length);

    Irp->IoStatus.Information = irpSp->Parameters.Write.Length;

    //
    // Handle miniport Pause
    // ---------------------
    // NDIS 6 miniports implement a temporary "Pause" state normally followed
    // by the Restart. While in the Pause state it is forbidden for the miniport
    // to indicate receive NBLs.
    //
    // That is: The device interface may be "up", but the NDIS miniport send/receive
    // interface may be temporarily "down".
    //
    // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas receive path
    // the code below will perform a "lying send" for write IRPs passed to the
    // driver while the miniport is in the Paused state.
    //
    // The correct implementation is to go ahead and build the NBLs corresponding
    // to the user-mode write - but queue them. When Restart is entered the
    // queued NBLs would be dequeued and indicated to the host.
    //
    if(tapAdapterSendAndReceiveReady(adapter) == NDIS_STATUS_SUCCESS)
    {
        if (!adapter->m_tun && ((irpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
        {
            PNET_BUFFER_LIST    netBufferList;

            DUMP_PACKET ("IRP_MJ_WRITE ETH",
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length);

            //=====================================================
            // If IPv4 packet, check whether or not packet
            // was truncated.
            //=====================================================
#if PACKET_TRUNCATION_CHECK
            IPv4PacketSizeVerify (
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length,
                FALSE,
                "RX",
                &adapter->m_RxTrunc
                );
#endif
            (Irp->MdlAddress)->Next = NULL; // No next MDL

            // Allocate the NBL and NB. Link MDL chain to NB.
            netBufferList = NdisAllocateNetBufferAndNetBufferList(
                adapter->ReceiveNblPool,
                0,                  // ContextSize
                0,                  // ContextBackFill
                Irp->MdlAddress,    // MDL chain
                0,
                dataLength
                );

            if(netBufferList != NULL)
            {
                LONG    nblCount;

                NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                // Stash IRP pointer in NBL MiniportReserved[0] field.
                netBufferList->MiniportReserved[0] = Irp;
                netBufferList->MiniportReserved[1] = NULL;

                // BUGBUG!!! Setup for IRP cancel!!!

                TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);

                // Increment in-flight receive NBL count.
                nblCount = NdisInterlockedIncrement(&adapter->ReceiveNblInFlightCount);
                ASSERT(nblCount > 0 );

                //
                // Indicate the packet
                // -------------------
                // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
                // contains the complete packet including Ethernet header and payload.
                //
                NdisMIndicateReceiveNetBufferLists(
                    adapter->MiniportAdapterHandle,
                    netBufferList,
                    NDIS_DEFAULT_PORT_NUMBER,
                    1,      // NumberOfNetBufferLists
                    0       // ReceiveFlags
                    );

                ntStatus = STATUS_PENDING;
            }
            else
            {
                DEBUGP (("[%s] NdisMIndicateReceiveNetBufferLists failed in IRP_MJ_WRITE\n",
                    MINIPORT_INSTANCE_ID (adapter)));
                NOTE_ERROR ();

                // Fail the IRP
                Irp->IoStatus.Information = 0;
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
        else if (adapter->m_tun && ((irpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
        {
            PETH_HEADER         p_UserToTap = &adapter->m_UserToTap;
            PMDL                mdl;    // Head of MDL chain.

            // For IPv6, need to use Ethernet header with IPv6 proto
            if ( IPH_GET_VER( ((IPHDR*) Irp->AssociatedIrp.SystemBuffer)->version_len) == 6 )
            {
                p_UserToTap = &adapter->m_UserToTap_IPv6;
            }

            DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
                p_UserToTap,
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length);

            //=====================================================
            // If IPv4 packet, check whether or not packet
            // was truncated.
            //=====================================================
#if PACKET_TRUNCATION_CHECK
            IPv4PacketSizeVerify (
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length,
                TRUE,
                "RX",
                &adapter->m_RxTrunc
                );
#endif

            //
            // Allocate MDL for Ethernet header
            // --------------------------------
            // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
            // contains the only the Ethernet payload. Prepend the user-mode provided
            // payload with the Ethernet header pointed to by p_UserToTap.
            //
            mdl = NdisAllocateMdl(
                adapter->MiniportAdapterHandle,
                p_UserToTap,
                sizeof(ETH_HEADER)
                );

            if(mdl != NULL)
            {
                PNET_BUFFER_LIST    netBufferList;

                // Chain user's Ethernet payload behind Ethernet header.
                mdl->Next = Irp->MdlAddress;
                (Irp->MdlAddress)->Next = NULL; // No next MDL

                // Allocate the NBL and NB. Link MDL chain to NB.
                netBufferList = NdisAllocateNetBufferAndNetBufferList(
                    adapter->ReceiveNblPool,
                    0,          // ContextSize
                    0,          // ContextBackFill
                    mdl,        // MDL chain
                    0,
                    sizeof(ETH_HEADER) + dataLength
                    );

                if(netBufferList != NULL)
                {
                    LONG        nblCount;

                    NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                    // This IRP is pended.
                    IoMarkIrpPending(Irp);

                    // This IRP cannot be cancelled while in-flight.
                    IoSetCancelRoutine(Irp,NULL);

                    // Stash IRP pointer in NBL MiniportReserved[0] field.
                    netBufferList->MiniportReserved[0] = Irp;
                    netBufferList->MiniportReserved[1] = NULL;

                    // Set flag indicating that this is P2P packet
                    TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);
                    TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_P2P);

                    // Increment in-flight receive NBL count.
                    nblCount = NdisInterlockedIncrement(&adapter->ReceiveNblInFlightCount);
                    ASSERT(nblCount > 0 );

                    //
                    // Indicate the packet
                    //
                    NdisMIndicateReceiveNetBufferLists(
                        adapter->MiniportAdapterHandle,
                        netBufferList,
                        NDIS_DEFAULT_PORT_NUMBER,
                        1,      // NumberOfNetBufferLists
                        0       // ReceiveFlags
                        );

                    ntStatus = STATUS_PENDING;
                }
                else
                {
                    mdl->Next = NULL;
                    NdisFreeMdl(mdl);

                    DEBUGP (("[%s] NdisMIndicateReceiveNetBufferLists failed in IRP_MJ_WRITE\n",
                        MINIPORT_INSTANCE_ID (adapter)));
                    NOTE_ERROR ();

                    // Fail the IRP
                    Irp->IoStatus.Information = 0;
                    ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
            else
            {
                DEBUGP (("[%s] NdisAllocateMdl failed in IRP_MJ_WRITE\n",
                    MINIPORT_INSTANCE_ID (adapter)));
                NOTE_ERROR ();

                // Fail the IRP
                Irp->IoStatus.Information = 0;
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
        else
        {
            DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
                MINIPORT_INSTANCE_ID (adapter),
                irpSp->Parameters.Write.Length));
            NOTE_ERROR ();

            Irp->IoStatus.Information = 0;	// ETHERNET_HEADER_SIZE;
            Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
        }
    }
    else
    {
        DEBUGP (("[%s] Lying send in IRP_MJ_WRITE while adapter paused\n",
            MINIPORT_INSTANCE_ID (adapter)));

        ntStatus = STATUS_SUCCESS;
    }

    if (ntStatus != STATUS_PENDING)
    {
        Irp->IoStatus.Status = ntStatus;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }

    return ntStatus;
}
Ejemplo n.º 22
0
//
//发送相关函数的实现、
//
NTSTATUS
SecLabSendPacket(
                 PADAPT			         pAdapt,
				 IN PDEVICE_OBJECT       DeviceObject,
				 IN PIRP                 pIrp
				 )
{
	PIO_STACK_LOCATION      pIrpSp;
    ULONG                   FunctionCode;
    ULONG                   DataLength;
    NTSTATUS                NtStatus=STATUS_INVALID_HANDLE;
    NDIS_STATUS             Status;
    
    PNDIS_PACKET                pNdisPacket;
    PNDIS_BUFFER                pNdisBuffer;
//  SECLAB_ETH_HEADER UNALIGNED *pEthHeader;

	PUCHAR      pData;
	ULONG        i;

#ifdef NDIS51
    PVOID                   CancelId;
#endif

    pIrpSp = IoGetCurrentIrpStackLocation(pIrp);

    pNdisPacket = NULL;
	pNdisBuffer = NULL;

    do
    {
        if (pAdapt == NULL)
        {
            DbgPrint("Write: FileObject not yet associated with a device\n");
            NtStatus = STATUS_INVALID_HANDLE;
            break;
        }

        //
        // 检查发送数据包的长度
        //

		DataLength=pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
		
        if (DataLength > MAX_SEND_PACKETLEN )
        {
            DbgPrint("Write: Open data length larger than max frame size\n");

            NtStatus = STATUS_UNSUCCESSFUL;
            break;
        }

        //
        //  构造一个发送封包
        //

		if(pAdapt->SendPacketPoolHandle==NULL)
		{
			DbgPrint("The Packet Pool should not be NULL");
			DbgBreakPoint();
			break;
		}

	    do
		{
			 //其实怎么样分配内存是无关紧要的,忘记资源的释放也不是很严重的
			 //最多导致内存支出过多。关键是不能让程序引用不存在的内存,这样会
			 //造成崩溃,比如重复释放内存。崩溃的另一大可能是在Dispatch>=passive
			 //级别上调用非分页内存。
		     //pData=(PUCHAR)ExAllocatePool(NonPagedPool,DataLength);
			 NdisAllocateMemoryWithTag((PVOID *)(&pData), DataLength,'lceS');

		     if(pData==NULL)
			 {
			      DbgPrint("Can not allocate pool for send");
			      break;
			 }
		     //RtlCopyMemory(pData,pIrp->AssociatedIrp.SystemBuffer,DataLength);
             NdisMoveMemory(pData,pIrp->AssociatedIrp.SystemBuffer,DataLength);

             //
             //  将其转化为NDIS_BUFFER.
             //
             NdisAllocateBuffer(
                 &Status,
                 &pNdisBuffer,
                 SendBufferPool,
                 pData,
                 DataLength);
        
              if (Status != NDIS_STATUS_SUCCESS)
			  {
                   DbgPrint("failed to allocate Ndis Buffer");
                   break;
			  }		

              NdisAllocatePacket(&Status, &pNdisPacket, pAdapt->SendPacketPoolHandle);

              if (Status != NDIS_STATUS_SUCCESS)
			  {
                   DbgPrint("failed to alloc NDIS packet");
                   break;
			  }

              NDIS_SET_PACKET_STATUS(pNdisPacket, 0);
              pNdisBuffer->Next = NULL;
              NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
			  
		      pNdisPacket->Private.Head->Next=NULL;
		      pNdisPacket->Private.Tail=NULL;

              break;
		}
        while (FALSE);

        if (pNdisPacket == NULL || pNdisBuffer==NULL)
		{
            //
            //  Clean up
            //
            if (pNdisBuffer != NULL)
			{
                NdisFreeBuffer(pNdisBuffer);
			}

            if (pData != NULL)
			{
                NdisFreeMemory(pData, 0, 0);
			}
		}

        IoMarkIrpPending(pIrp);
		NtStatus = STATUS_PENDING;
        pIrp->IoStatus.Status = STATUS_PENDING;
        //
        //  初始化封包中的标志符。当标志符值为0时此包被释放
        //
        SECLAB_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 = SECLAB_GET_NEXT_CANCEL_ID();
        NDIS_SET_PACKET_CANCEL_ID(pNdisPacket, CancelId);
        pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pAdapt;
        pIrp->Tail.Overlay.DriverContext[1] = (PVOID)pNdisPacket;

		NdisInterlockedIncrement(&PendedSendCount);

		NdisAcquireSpinLock(&WriteIrpLock);
        InsertTailList(&PendedWritesList, &pIrp->Tail.Overlay.ListEntry);
        IoSetCancelRoutine(pIrp, SecLabCancelWrite);
		NdisReleaseSpinLock(&WriteIrpLock);

#endif // NDIS51
               
        //
        //  创建一个指针从packet回指向IRP
        //
        SECLAB_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp;

		//
		//创建三个信号,以便在发送完成例程中指示此包
		//
		SECLAB_SIGNAL1_FROM_SEND_PKT(pNdisPacket)=SIGNAL1;
        SECLAB_SIGNAL2_FROM_SEND_PKT(pNdisPacket)=SIGNAL2;
		SECLAB_SIGNAL3_FROM_SEND_PKT(pNdisPacket)=SIGNAL3;

		//
		//发包
		//
        NdisSendPackets(pAdapt->BindingHandle, &pNdisPacket, 1); 
    }

    while (FALSE);

    if (NtStatus != STATUS_PENDING)
    {
        pIrp->IoStatus.Status = NtStatus;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);	
    }

    return (NtStatus);
}
Ejemplo n.º 23
0
// Write lock on the list must be held
// Returns an entry that can be expired. The caller frees it
PMP_BSS_ENTRY
HelperPortExpireBSSEntry(
    __in  PMP_BSS_LIST           pBSSList,
    __in  ULONGLONG               ullMaxActiveTime,
    __in  ULONGLONG               ullExpireTimeStamp
    )
{
    PLIST_ENTRY         pHead = NULL, pEntry = NULL;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    BOOLEAN             bFound = FALSE;

    //
    // We can expire an entry that has been around for longer 
    // than this time
    //
    if (ullMaxActiveTime <= ullExpireTimeStamp)
        ullExpireTimeStamp -= ullMaxActiveTime;

    pHead = &(pBSSList->List);
    pEntry = pHead->Flink;
    while(pEntry != pHead) 
    {
        pBSSEntry = CONTAINING_RECORD(pEntry, MP_BSS_ENTRY, Link);
        pEntry = pEntry->Flink;

        NdisAcquireSpinLock(&(pBSSEntry->Lock));

        //
        // If the entry is older than we expected and its not in
        // use, we can expire it
        //
        if (pBSSEntry->HostTimestamp < ullExpireTimeStamp)
        {
            if (NdisInterlockedDecrement(&(pBSSEntry->RefCount)) == 0)
            {
                MpTrace(COMP_SCAN, DBG_LOUD, ("Expiring AP: %02X-%02X-%02X-%02X-%02X-%02X\n", 
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5]));

                MPASSERT(pBSSEntry->pAssocRequest == NULL);
                MPASSERT(pBSSEntry->pAssocResponse == NULL);
                
                //
                // This is the entry we can expire. Remove it from the list.
                //
                NdisReleaseSpinLock(&(pBSSEntry->Lock));
                HelperPortRemoveBSSEntry(pBSSList, pBSSEntry);
                
                bFound = TRUE;
                break;
            }
            else
            {
                // Someone is using the entry, we cannot remove/delete this. Add back
                // a ref and we will delete later on

                // This is subobtimal. Ideally the last person to decrement
                // refcount should delete the entry and not us. Modify to remove
                // the entry from the list, decrement its refcount and only free
                // the memory if the refcount has gone to zero
                NdisInterlockedIncrement(&(pBSSEntry->RefCount));
            }
        }
        NdisReleaseSpinLock(&(pBSSEntry->Lock));
    }

    if (bFound != TRUE)
    {
        pBSSEntry = NULL;
    }
    
    return pBSSEntry;