Esempio n. 1
0
// XXX this whole thing is f****d up
static void get_mac(PADAPT adapt)
{
    NDIS_STATUS                 Status;

    _req.RequestType = NdisRequestQueryInformation;
    _req.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
    _req.DATA.QUERY_INFORMATION.InformationBuffer = _mac;
    _req.DATA.QUERY_INFORMATION.InformationBufferLength = NPROT_MAC_ADDR_LEN;

    NdisRequest(&Status,
                adapt->BindingHandle,
                &_req);
   
    if (Status == NDIS_STATUS_PENDING) {
		DbgPrint("f**K PENDING\n");

		while (_req.DATA.QUERY_INFORMATION.Oid != 0)
			NdisMSleep(2);

    } else {
		_req.DATA.QUERY_INFORMATION.Oid = 0;
    		DbgPrint("MAC %x %x %x %x %x %x\n",
			 _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5]);
    }
}
Esempio n. 2
0
VOID 
	StartQueryInfo( 
		IN PFILTER_ADAPTER pAdapter 
		)
{
	NTSTATUS             nNtStatus;
	PINTERNAL_REQUEST    pIntReq;

	pIntReq = &pAdapter->IntReq;

	RtlZeroMemory(pIntReq, sizeof(*pIntReq));

	pIntReq->NdisRequest.RequestType = NdisRequestQueryInformation;
	pIntReq->NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
	pIntReq->NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = pAdapter->ctrl.MacAddr.Arr;
	pIntReq->NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( pAdapter->ctrl.MacAddr.Arr);

	nNtStatus = NDIS_STATUS_FAILURE;
	pIntReq->nRequestStatus = NDIS_STATUS_PENDING;

	pIntReq->bLocalRequest = TRUE;
	pIntReq->pLocalCompletionFunc = MakeCurrentAddressQueryComplete;
	pAdapter->LocalOutstandingRequests = TRUE;
	
	NdisRequest(
		&nNtStatus,
		pAdapter->BindingHandle,
		&pIntReq->NdisRequest
		);

	if( nNtStatus != NDIS_STATUS_PENDING ){
		natpRequestComplete(
			(NDIS_HANDLE )pAdapter,
			&pIntReq->NdisRequest,
			nNtStatus
			);
	}

}
Esempio n. 3
0
NDIS_STATUS
MPSetInformation(
    IN NDIS_HANDLE             MiniportAdapterContext,
    IN NDIS_OID                Oid,
    IN PVOID                   InformationBuffer,
    IN ULONG                   InformationBufferLength,
    OUT PULONG                 BytesRead,
    OUT PULONG                 BytesNeeded
    )
/*++

Routine Description:

    Miniport SetInfo handler.

    In the case of OID_PNP_SET_POWER, record the power state and return the OID.    
    Do not pass below
    If the device is suspended, do not block the SET_POWER_OID 
    as it is used to reactivate the Passthru miniport

    
    PM- If the MP is not ON (DeviceState > D0) return immediately  (except for 'query power' and 'set power')
         If MP is ON, but the PT is not at D0, then queue the queue the request for later processing

    Requests to miniports are always serialized


Arguments:

    MiniportAdapterContext    Pointer to the adapter structure
    Oid                       Oid for this query
    InformationBuffer         Buffer for information
    InformationBufferLength   Size of this buffer
    BytesRead                 Specifies how much info is read
    BytesNeeded               In case the buffer is smaller than what we need, tell them how much is needed

Return Value:

    Return code from the NdisRequest below.

--*/
{
    PADAPT        pAdapt = (PADAPT)MiniportAdapterContext;
    NDIS_STATUS   Status;

    Status = NDIS_STATUS_FAILURE;

    do
    {
        //
        // The Set Power should not be sent to the miniport below the Passthru, but is handled internally
        //
        if (Oid == OID_PNP_SET_POWER)
        {
            MPProcessSetPowerOid(&Status, 
                                 pAdapt, 
                                 InformationBuffer, 
                                 InformationBufferLength, 
                                 BytesRead, 
                                 BytesNeeded);
            break;

        }

        //
        // If the miniport below is unbinding, fail the request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);     
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        NdisReleaseSpinLock(&pAdapt->Lock);
        //
        // All other Set Information requests are failed, if the miniport is
        // not at D0 or is transitioning to a device state greater than D0.
        //
        if (pAdapt->MPDeviceState > NdisDeviceStateD0)
        {
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        // Set up the Request and return the result
        pAdapt->Request.RequestType = NdisRequestSetInformation;
        pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;
        pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
        pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
        pAdapt->BytesNeeded = BytesNeeded;
        pAdapt->BytesReadOrWritten = BytesRead;

        //
        // If the miniport below is unbinding, fail the request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);     
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
            
        //
        // If the device below is at a low power state, we cannot send it the
        // request now, and must pend it.
        //
        if ((pAdapt->PTDeviceState > NdisDeviceStateD0) 
                && (pAdapt->StandingBy == FALSE))
        {
            pAdapt->QueuedRequest = TRUE;
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_PENDING;
            break;
        }
        //
        // This is in the process of powering down the system, always fail the request
        // 
        if (pAdapt->StandingBy == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        pAdapt->OutstandingRequests = TRUE;
        
        NdisReleaseSpinLock(&pAdapt->Lock);
        //
        // Forward the request to the device below.
        //
        NdisRequest(&Status,
                    pAdapt->BindingHandle,
                    &pAdapt->Request);

        if (Status != NDIS_STATUS_PENDING)
        {
            *BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead;
            *BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;
            pAdapt->OutstandingRequests = FALSE;
        }

    } while (FALSE);

    return(Status);
}
Esempio n. 4
0
NDIS_STATUS
MPQueryInformation(
    IN NDIS_HANDLE                MiniportAdapterContext,
    IN NDIS_OID                   Oid,
    IN PVOID                      InformationBuffer,
    IN ULONG                      InformationBufferLength,
    OUT PULONG                    BytesWritten,
    OUT PULONG                    BytesNeeded
    )
/*++

Routine Description:

    Entry point called by NDIS to query for the value of the specified OID.
    Typical processing is to forward the query down to the underlying miniport.

    The following OIDs are filtered here:

    OID_PNP_QUERY_POWER - return success right here

    OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up
    multiple instances of private GUIDs supported by the underlying miniport.

    OID_PNP_CAPABILITIES - we do send this down to the lower miniport, but
    the values returned are postprocessed before we complete this request;
    see PtRequestComplete.

    NOTE on OID_TCP_TASK_OFFLOAD - if this IM driver modifies the contents
    of data it passes through such that a lower miniport may not be able
    to perform TCP task offload, then it should not forward this OID down,
    but fail it here with the status NDIS_STATUS_NOT_SUPPORTED. This is to
    avoid performing incorrect transformations on data.

    If our miniport edge (upper edge) is at a low-power state, fail the request.

    If our protocol edge (lower edge) has been notified of a low-power state,
    we pend this request until the miniport below has been set to D0. Since
    requests to miniports are serialized always, at most a single request will
    be pended.

Arguments:

    MiniportAdapterContext    Pointer to the adapter structure
    Oid                       Oid for this query
    InformationBuffer         Buffer for information
    InformationBufferLength   Size of this buffer
    BytesWritten              Specifies how much info is written
    BytesNeeded               In case the buffer is smaller than what we need, tell them how much is needed


Return Value:

    Return code from the NdisRequest below.

--*/
{
    PADAPT        pAdapt = (PADAPT)MiniportAdapterContext;
    NDIS_STATUS   Status = NDIS_STATUS_FAILURE;

    do
    {
        if (Oid == OID_PNP_QUERY_POWER)
        {
            //
            //  Do not forward this.
            //
            Status = NDIS_STATUS_SUCCESS;
            break;
        }

        if (Oid == OID_GEN_SUPPORTED_GUIDS)
        {
            //
            //  Do not forward this, otherwise we will end up with multiple
            //  instances of private GUIDs that the underlying miniport
            //  supports.
            //
            Status = NDIS_STATUS_NOT_SUPPORTED;
            break;
        }

        if (Oid == OID_TCP_TASK_OFFLOAD)
        {
            //
            // Fail this -if- this driver performs data transformations
            // that can interfere with a lower driver's ability to offload
            // TCP tasks.
            //
            // Status = NDIS_STATUS_NOT_SUPPORTED;
            // break;
            //
        }
        //
        // If the miniport below is unbinding, just fail any request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        NdisReleaseSpinLock(&pAdapt->Lock);
        //
        // All other queries are failed, if the miniport is not at D0,
        //
        if (pAdapt->MPDeviceState > NdisDeviceStateD0) 
        {
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        pAdapt->Request.RequestType = NdisRequestQueryInformation;
        pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
        pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
        pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
        pAdapt->BytesNeeded = BytesNeeded;
        pAdapt->BytesReadOrWritten = BytesWritten;

        //
        // If the miniport below is binding, fail the request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);
            
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        //
        // If the Protocol device state is OFF, mark this request as being 
        // pended. We queue this until the device state is back to D0. 
        //
        if ((pAdapt->PTDeviceState > NdisDeviceStateD0) 
                && (pAdapt->StandingBy == FALSE))
        {
            pAdapt->QueuedRequest = TRUE;
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_PENDING;
            break;
        }
        //
        // This is in the process of powering down the system, always fail the request
        // 
        if (pAdapt->StandingBy == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        pAdapt->OutstandingRequests = TRUE;
        
        NdisReleaseSpinLock(&pAdapt->Lock);

        //
        // default case, most requests will be passed to the miniport below
        //
        NdisRequest(&Status,
                    pAdapt->BindingHandle,
                    &pAdapt->Request);


        if (Status != NDIS_STATUS_PENDING)
        {
            PtRequestComplete(pAdapt, &pAdapt->Request, Status);
            Status = NDIS_STATUS_PENDING;
        }

    } while (FALSE);

    return(Status);

}
Esempio n. 5
0
File: Openclos.c Progetto: 52M/npcap
NTSTATUS
NPF_GetDeviceMTU(
			 IN POPEN_INSTANCE pOpen,
			 IN PIRP	pIrp,
			 OUT PUINT  pMtu)
{
    PLIST_ENTRY			RequestListEntry;
	PINTERNAL_REQUEST	MaxSizeReq;
	NDIS_STATUS			ReqStatus;

	TRACE_ENTER();

	ASSERT(pOpen != NULL);
	ASSERT(pIrp != NULL);
	ASSERT(pMtu != NULL);

	// Extract a request from the list of free ones
	RequestListEntry = ExInterlockedRemoveHeadList(&pOpen->RequestList, &pOpen->RequestSpinLock);

	if (RequestListEntry == NULL)
	{
		//
		// THIS IS WRONG
		//

		//
		// Assume Ethernet
		//
		*pMtu = 1514;	
		TRACE_EXIT();
		return STATUS_SUCCESS;
	}

	MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);

	MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
	MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;

	MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = pMtu;
	MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(*pMtu);

	NdisResetEvent(&MaxSizeReq->InternalRequestCompletedEvent);

	//  submit the request
	NdisRequest(
		&ReqStatus,
		pOpen->AdapterHandle,
		&MaxSizeReq->Request);

	if (ReqStatus == NDIS_STATUS_PENDING)
	{
		NdisWaitEvent(&MaxSizeReq->InternalRequestCompletedEvent, 0);
		ReqStatus = MaxSizeReq->RequestStatus;
	}

	//
	// Put the request in the list of the free ones
	//
	ExInterlockedInsertTailList(&pOpen->RequestList, &MaxSizeReq->ListElement, &pOpen->RequestSpinLock);

	if (ReqStatus == NDIS_STATUS_SUCCESS)
	{
		TRACE_EXIT();
		return STATUS_SUCCESS;
	}
	else
	{
		//
		// THIS IS WRONG
		//

		//
		// Assume Ethernet
		//
		*pMtu = 1514;	

		TRACE_EXIT();
		return STATUS_SUCCESS;
	
		// return ReqStatus;
	}
}
Esempio n. 6
0
static
NDIS_STATUS
BindAdapterByName(PNDIS_STRING DeviceName)
{
    NDIS_STATUS OpenErrorStatus;
    PNDISUIO_ADAPTER_CONTEXT AdapterContext;
    NDIS_MEDIUM SupportedMedia[1] = {NdisMedium802_3};
    UINT SelectedMedium;
    NDIS_STATUS Status;
    NDIS_REQUEST Request;

    /* Allocate the adapter context */
    AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext));
    if (!AdapterContext)
    {
        return NDIS_STATUS_RESOURCES;
    }

    /* Set up the adapter context */
    RtlZeroMemory(AdapterContext, sizeof(*AdapterContext));
    KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE);
    KeInitializeEvent(&AdapterContext->PacketReadEvent, SynchronizationEvent, FALSE);
    KeInitializeSpinLock(&AdapterContext->Spinlock);
    InitializeListHead(&AdapterContext->PacketList);
    InitializeListHead(&AdapterContext->OpenEntryList);
    AdapterContext->OpenCount = 0;

    AdapterContext->DeviceName.Length =
    AdapterContext->DeviceName.MaximumLength = DeviceName->Length;
    AdapterContext->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length);
    if (!AdapterContext->DeviceName.Buffer)
    {
        ExFreePool(AdapterContext);
        return NDIS_STATUS_RESOURCES;
    }

    /* Copy the device name into the adapter context */
    RtlCopyMemory(AdapterContext->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length);
    
    DPRINT("Binding adapter %wZ\n", &AdapterContext->DeviceName);

    /* Create the buffer pool */
    NdisAllocateBufferPool(&Status,
                           &AdapterContext->BufferPoolHandle,
                           50);
    if (Status != NDIS_STATUS_SUCCESS)
    {
        DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status);
        RtlFreeUnicodeString(&AdapterContext->DeviceName);
        ExFreePool(AdapterContext);
        return Status;
    }

    /* Create the packet pool */
    NdisAllocatePacketPool(&Status,
                           &AdapterContext->PacketPoolHandle,
                           25,
                           PROTOCOL_RESERVED_SIZE_IN_PACKET);
    if (Status != NDIS_STATUS_SUCCESS)
    {
        DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status);
        NdisFreeBufferPool(AdapterContext->BufferPoolHandle);
        RtlFreeUnicodeString(&AdapterContext->DeviceName);
        ExFreePool(AdapterContext);
        return Status;
    }

    /* Send the open request */
    NdisOpenAdapter(&Status,
                    &OpenErrorStatus,
                    &AdapterContext->BindingHandle,
                    &SelectedMedium,
                    SupportedMedia,
                    1,
                    GlobalProtocolHandle,
                    AdapterContext,
                    DeviceName,
                    0,
                    NULL);
    
    /* Wait for a pending open */
    if (Status == NDIS_STATUS_PENDING)
    {
        KeWaitForSingleObject(&AdapterContext->AsyncEvent,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
        Status = AdapterContext->AsyncStatus;
    }
    
    /* Check the final status */
    if (Status != NDIS_STATUS_SUCCESS)
    {
        DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status);
        NdisFreePacketPool(AdapterContext->PacketPoolHandle);
        NdisFreeBufferPool(AdapterContext->BufferPoolHandle);
        RtlFreeUnicodeString(&AdapterContext->DeviceName);
        ExFreePool(AdapterContext);
        return Status;
    }
    
    /* Get the MAC options */
    Request.RequestType = NdisRequestQueryInformation;
    Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS;
    Request.DATA.QUERY_INFORMATION.InformationBuffer = &AdapterContext->MacOptions;
    Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG);
    NdisRequest(&Status,
                AdapterContext->BindingHandle,
                &Request);

    /* Wait for a pending request */
    if (Status == NDIS_STATUS_PENDING)
    {
        KeWaitForSingleObject(&AdapterContext->AsyncEvent,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
        Status = AdapterContext->AsyncStatus;
    }
    
    /* Check the final status */
    if (Status != NDIS_STATUS_SUCCESS)
    {
        NDIS_STATUS CloseStatus;

        DPRINT1("Failed to get MAC options with status 0x%x\n", Status);

        NdisCloseAdapter(&CloseStatus,
                         AdapterContext->BindingHandle);
        if (CloseStatus == NDIS_STATUS_PENDING)
        {
            KeWaitForSingleObject(&AdapterContext->AsyncEvent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
        }

        NdisFreePacketPool(AdapterContext->PacketPoolHandle);
        NdisFreeBufferPool(AdapterContext->BufferPoolHandle);
        RtlFreeUnicodeString(&AdapterContext->DeviceName);
        ExFreePool(AdapterContext);
        return Status;
    }
    
    /* Add the adapter context to the global list */
    ExInterlockedInsertTailList(&GlobalAdapterList,
                                &AdapterContext->ListEntry,
                                &GlobalAdapterListLock);

    return STATUS_SUCCESS;
}
Esempio n. 7
0
NDIS_STATUS
	natpPnPNetEventSetPower(
		IN PFILTER_ADAPTER	pAdapt,
		IN PNET_PNP_EVENT	pNetPnPEvent
		)
{
	PNDIS_DEVICE_POWER_STATE	pDeviceState  =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
	NDIS_DEVICE_POWER_STATE		PrevDeviceState = pAdapt->natpDeviceState;  
	NDIS_STATUS					Status;
	NDIS_STATUS					ReturnStatus;

	ReturnStatus = NDIS_STATUS_SUCCESS;

	NdisAcquireSpinLock(&pAdapt->Lock);
	pAdapt->natpDeviceState = *pDeviceState;

	if (pAdapt->natpDeviceState > NdisDeviceStateD0){

		if (PrevDeviceState == NdisDeviceStateD0)
			pAdapt->StandingBy = TRUE;

		NdisReleaseSpinLock(&pAdapt->Lock);

		while (pAdapt->SendPending != 0)
			NdisMSleep(2);

		while (pAdapt->OutstandingRequests == TRUE)
			NdisMSleep(2);

		while (pAdapt->LocalOutstandingRequests == TRUE)
			NdisMSleep(2);

		NdisAcquireSpinLock(&pAdapt->Lock);
		if (pAdapt->QueuedRequest){
			pAdapt->QueuedRequest = FALSE;
			NdisReleaseSpinLock(&pAdapt->Lock);
			natpRequestComplete(pAdapt, &pAdapt->IntReq.NdisRequest, NDIS_STATUS_FAILURE);
		}else{
			NdisReleaseSpinLock(&pAdapt->Lock);
		}

	}else{
		if (PrevDeviceState > NdisDeviceStateD0)
			pAdapt->StandingBy = FALSE;

		if (pAdapt->QueuedRequest == TRUE){

			pAdapt->QueuedRequest = FALSE;

			pAdapt->OutstandingRequests = TRUE;
			NdisReleaseSpinLock(&pAdapt->Lock);

			NdisRequest(
				&Status,
				pAdapt->BindingHandle,
				&pAdapt->IntReq.NdisRequest
				);

			if (Status != NDIS_STATUS_PENDING){
				natpRequestComplete(
					pAdapt,
					&pAdapt->IntReq.NdisRequest,
					Status
					);

			}

		}else{
			NdisReleaseSpinLock(&pAdapt->Lock);
		}
	}

	return ReturnStatus;
}
NDIS_STATUS
PtPnPNetEventSetPower(
	IN	PADAPT			pAdapt,
	IN  PNET_PNP_EVENT	pNetPnPEvent
	)
/*++
Routine Description:

	This is a notification to our protocol edge of the power state
	of the lower miniport. If it is going to a low-power state, we must
	wait here for all outstanding sends and requests to complete.

	NDIS 5.1:  Since we use packet stacking, it is not sufficient to
	check usage of our local send packet pool to detect whether or not
	all outstanding sends have completed. For this, use the new API
	NdisQueryPendingIOCount.

	NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP
	notifications to upper protocol(s).

Arguments:

	pAdapt			-	Pointer to the adpater structure
	pNetPnPEvent	-	The Net Pnp Event. this contains the new device state

Return Value:

	NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols.

--*/
{
	PNDIS_DEVICE_POWER_STATE	pDeviceState  =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
	NDIS_DEVICE_POWER_STATE		PrevDeviceState = pAdapt->PTDeviceState;  
	NDIS_STATUS					Status;
	NDIS_STATUS					ReturnStatus;
#ifdef NDIS51
	ULONG						PendingIoCount = 0;
#endif // NDIS51

	ReturnStatus = NDIS_STATUS_SUCCESS;

	//
	// Set the Internal Device State, this blocks all new sends or receives
	//
	pAdapt->PTDeviceState = *pDeviceState;

	//
	// Check if the miniport below is going to a low power state.
	//
	if (*pDeviceState > NdisDeviceStateD0)
	{

#ifdef NDIS51
		//
		// Notify upper layer protocol(s) first.
		//
		if (pAdapt->MiniportHandle != NULL)
		{
			ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
		}
#endif // NDIS51

		//
		// If the miniport below is going to standby, fail all incoming requests
		//
		if (PrevDeviceState == NdisDeviceStateD0)
		{
			pAdapt->StandingBy = TRUE;
		}

		//
		// Wait for outstanding sends and requests to complete.
		//
#ifdef NDIS51
		do
		{
			Status = NdisQueryPendingIOCount(pAdapt->BindingHandle, &PendingIoCount);

			if ((Status != NDIS_STATUS_SUCCESS) ||
				(PendingIoCount == 0))
			{
				break;
			}
			NdisMSleep(2);
		}
		while (TRUE);
#else
		while (NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) != 0)
		{
			NdisMSleep(2);
		}

		while (pAdapt->OutstandingRequests == TRUE)
		{
			//
			// sleep till outstanding requests complete
			//
			NdisMSleep(2);
		}

#endif // NDIS51

		ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);
		ASSERT(pAdapt->OutstandingRequests == FALSE);
	}
	else
	{
		//
		// The device below is being turned on. If we had a request
		// pending, send it down now.
		//
		if (pAdapt->QueuedRequest == TRUE)
		{
			pAdapt->QueuedRequest = FALSE;

			NdisRequest(&Status,
			            pAdapt->BindingHandle,
			            &pAdapt->Request);

			if (Status != NDIS_STATUS_PENDING)
			{
				PtRequestComplete(pAdapt,
			    	              &pAdapt->Request,
			        	          Status);
			}
		}

		//
		// If the physical miniport is powering up (from Low power state to D0), 
		// clear the flag
		//
		if (PrevDeviceState > NdisDeviceStateD0)
		{
			pAdapt->StandingBy = FALSE;
		}

#ifdef NDIS51
		//
		// Pass on this notification to protocol(s) above
		//
		if (pAdapt->MiniportHandle)
		{
			ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent);
		}
#endif // NDIS51

	}

	return ReturnStatus;
}
Esempio n. 9
0
NDIS_STATUS
MiniportSetInformation5(
    IN NDIS_HANDLE             MiniportAdapterContext,
    IN NDIS_OID                Oid,
    IN PVOID                   InformationBuffer,
    IN ULONG                   InformationBufferLength,
    OUT PULONG                 BytesRead,
    OUT PULONG                 BytesNeeded
    )
{
    PADAPTER        pAdapt = (PADAPTER)MiniportAdapterContext;
    NDIS_STATUS   Status;

    Status = NDIS_STATUS_FAILURE;

    do
    {
        //
        // The Set Power should not be sent to the miniport below the Passthru, but is handled internally
        //
        if (Oid == OID_PNP_SET_POWER)
        {
            MiniportProcessSetPowerOid5(&Status, 
                                 pAdapt, 
                                 InformationBuffer, 
                                 InformationBufferLength, 
                                 BytesRead, 
                                 BytesNeeded);
            break;

        }

        //
        // If the miniport below is unbinding, fail the request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);     
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        NdisReleaseSpinLock(&pAdapt->Lock);
        //
        // All other Set Information requests are failed, if the miniport is
        // not at D0 or is transitioning to a device state greater than D0.
        //
        if (pAdapt->MiniportDeviceState > NdisDeviceStateD0)
        {
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        // Set up the Request and return the result
        pAdapt->Request5.RequestType = NdisRequestSetInformation;
        pAdapt->Request5.DATA.SET_INFORMATION.Oid = Oid;
        pAdapt->Request5.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
        pAdapt->Request5.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
        pAdapt->BytesNeeded = BytesNeeded;
        pAdapt->BytesReadOrWritten = BytesRead;

        //
        // If the miniport below is unbinding, fail the request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);     
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
            
        //
        // If the device below is at a low power state, we cannot send it the
        // request now, and must pend it.
        //
        if ((pAdapt->PTDeviceState > NdisDeviceStateD0) 
                && (pAdapt->StandingBy == FALSE))
        {
            pAdapt->QueuedRequest = TRUE;
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_PENDING;
            break;
        }
        //
        // This is in the process of powering down the system, always fail the request
        // 
        if (pAdapt->StandingBy == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        pAdapt->OutstandingRequests = TRUE;
        
        NdisReleaseSpinLock(&pAdapt->Lock);
        //
        // Forward the request to the device below.
        //
        NdisRequest(&Status,
                    pAdapt->BindingHandle,
                    (PVOID)&pAdapt->Request5);

        if (Status != NDIS_STATUS_PENDING)
        {
            *BytesRead = pAdapt->Request5.DATA.SET_INFORMATION.BytesRead;
            *BytesNeeded = pAdapt->Request5.DATA.SET_INFORMATION.BytesNeeded;
            pAdapt->OutstandingRequests = FALSE;
        }

    } while (FALSE);

    return(Status);
}
Esempio n. 10
0
// I/O控制派遣例程
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	// 假设失败
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;

	// 取得此IRP(pIrp)的I/O堆栈指针
	PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

	// 取得I/O控制代码
	ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	// 取得I/O缓冲区指针和它的长度
	PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
	ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	if(uIoControlCode == IOCTL_ENUM_ADAPTERS)
	{
		ULONG nDataLen = 0;
		if(pDevObj != g_data.pControlDevice)
			status = STATUS_INVALID_DEVICE_REQUEST;
		else
		{
			status = GetAdapterList(pIoBuffer, uOutSize, &nDataLen);
			if(status != STATUS_SUCCESS)
				DbgPrint("GetAdapterList error ");
		}
		pIrp->IoStatus.Information = nDataLen;
		pIrp->IoStatus.Status = status;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		return status;
	}

	OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)pDevObj->DeviceExtension;
	if(pOpen == NULL || !pOpen->bBound)
	{
		pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		return STATUS_UNSUCCESSFUL;
	}

	IoIncrement(pOpen);

	IoMarkIrpPending(pIrp);

	if(uIoControlCode == IOCTL_PROTOCOL_RESET) 
	{
		// 插入此IRP到重置IRP列表
       ExInterlockedInsertTailList(
                &pOpen->ResetIrpList,
                &pIrp->Tail.Overlay.ListEntry,
                &pOpen->ResetQueueLock);

	   // 发出重置请求
        NdisReset(
            &status,
            pOpen->hAdapter
            );
        if(status != NDIS_STATUS_PENDING) 
		{
            ProtocolResetComplete(
                pOpen,
                status);
        }
    }

	// 获取或者设置OID信息
	else if(uIoControlCode == IOCTL_PROTOCOL_SET_OID 
				|| uIoControlCode == IOCTL_PROTOCOL_QUERY_OID) // 输入参数是一个自定义的PROTOCOL_OID_DATA结构
	{
		PPROTOCOL_OID_DATA pOidData = (PPROTOCOL_OID_DATA)pIoBuffer;
		// 申请一个INTERNAL_REQUEST结构
		PINTERNAL_REQUEST pInterRequest = 
			(PINTERNAL_REQUEST)ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST));
	   if(pInterRequest == NULL)
        {
            pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest(pIrp, IO_NO_INCREMENT);
            IoDecrement(pOpen);
            return STATUS_PENDING;
        }         
        pInterRequest->pIrp = pIrp;

		if(uOutSize == uInSize && uOutSize >= sizeof(PROTOCOL_OID_DATA) &&
					uOutSize >= sizeof(PROTOCOL_OID_DATA) - 1 + pOidData->Length)	// 缓冲区可用?
		{
			// 初始化NDIS_REQUEST结构
			if(uIoControlCode == IOCTL_PROTOCOL_SET_OID)
			{
				pInterRequest->Request.RequestType = NdisRequestSetInformation;
				pInterRequest->Request.DATA.SET_INFORMATION.Oid = pOidData->Oid;
				pInterRequest->Request.DATA.SET_INFORMATION.InformationBuffer = pOidData->Data;
				pInterRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = pOidData->Length;
			}
			else
			{
				pInterRequest->Request.RequestType = NdisRequestQueryInformation;
				pInterRequest->Request.DATA.QUERY_INFORMATION.Oid = pOidData->Oid;
				pInterRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = pOidData->Data;
				pInterRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = pOidData->Length;
			}

			// 提交这个请求
			NdisRequest(&status, pOpen->hAdapter, &pInterRequest->Request);
		}
		else
		{
			status = NDIS_STATUS_FAILURE;
            pInterRequest->Request.DATA.SET_INFORMATION.BytesRead = 0;
            pInterRequest->Request.DATA.QUERY_INFORMATION.BytesWritten = 0;
		}
		
		if(status != NDIS_STATUS_PENDING)
		{
			ProtocolRequestComplete(pOpen, &pInterRequest->Request, status);
		}
	}

	return STATUS_PENDING;
}
Esempio n. 11
0
NDIS_STATUS
MiniportQueryInformation5(
    IN NDIS_HANDLE                MiniportAdapterContext,
    IN NDIS_OID                   Oid,
    IN PVOID                      InformationBuffer,
    IN ULONG                      InformationBufferLength,
    OUT PULONG                    BytesWritten,
    OUT PULONG                    BytesNeeded
    )
{
    PADAPTER      pAdapt = (PADAPTER)MiniportAdapterContext;
    NDIS_STATUS   Status = NDIS_STATUS_FAILURE;

    do
    {
        if (Oid == OID_PNP_QUERY_POWER)
        {
            //
            //  Do not forward this.
            //
            Status = NDIS_STATUS_SUCCESS;
            break;
        }

        if (Oid == OID_GEN_SUPPORTED_GUIDS)
        {
            //
            //  Do not forward this, otherwise we will end up with multiple
            //  instances of private GUIDs that the underlying miniport
            //  supports.
            //
            Status = NDIS_STATUS_NOT_SUPPORTED;
            break;
        }

        if (Oid == OID_TCP_TASK_OFFLOAD)
        {
            //
            // Fail this -if- this driver performs data transformations
            // that can interfere with a lower driver's ability to offload
            // TCP tasks.
            //
            // Status = NDIS_STATUS_NOT_SUPPORTED;
            // break;
            //
        }
        //
        // If the miniport below is unbinding, just fail any request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        NdisReleaseSpinLock(&pAdapt->Lock);
        //
        // All other queries are failed, if the miniport is not at D0,
        //
        if (pAdapt->MiniportDeviceState > NdisDeviceStateD0) 
        {
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        pAdapt->Request5.RequestType = NdisRequestQueryInformation;
        pAdapt->Request5.DATA.QUERY_INFORMATION.Oid = Oid;
        pAdapt->Request5.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
        pAdapt->Request5.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
        pAdapt->BytesNeeded = BytesNeeded;
        pAdapt->BytesReadOrWritten = BytesWritten;

        //
        // If the miniport below is binding, fail the request
        //
        NdisAcquireSpinLock(&pAdapt->Lock);
            
        if (pAdapt->UnbindingInProcess == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        //
        // If the Protocol device state is OFF, mark this request as being 
        // pended. We queue this until the device state is back to D0. 
        //
        if ((pAdapt->PTDeviceState > NdisDeviceStateD0) 
                && (pAdapt->StandingBy == FALSE))
        {
            pAdapt->QueuedRequest = TRUE;
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_PENDING;
            break;
        }
        //
        // This is in the process of powering down the system, always fail the request
        // 
        if (pAdapt->StandingBy == TRUE)
        {
            NdisReleaseSpinLock(&pAdapt->Lock);
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        pAdapt->OutstandingRequests = TRUE;
        
        NdisReleaseSpinLock(&pAdapt->Lock);

        //
        // default case, most requests will be passed to the miniport below
        //
        NdisRequest(&Status,
                    pAdapt->BindingHandle,
                    (PVOID)&pAdapt->Request5);


        if (Status != NDIS_STATUS_PENDING)
        {
            ProtocolRequestComplete5(pAdapt, (PVOID)&pAdapt->Request5, Status);
            Status = NDIS_STATUS_PENDING;
        }

    } while (FALSE);

    return(Status);

}
Esempio n. 12
0
DWORD NDIS_API PacketRequest(POPEN_INSTANCE  Open,
                             DWORD           FunctionCode,
                             DWORD           dwDDB,
                             DWORD           hDevice,
                             PDIOCPARAMETERS pDiocParms)
{
  // perform a packet request

  PLIST_ENTRY       RequestListEntry;
  PINTERNAL_REQUEST pRequest;
  PPACKET_RESERVED  pReserved;
  EPACKET_OID *  OidData;
  NDIS_STATUS       Status;
  

  // Acquire request element from list
  NdisAcquireSpinLock(&Open->RequestSpinLock);
  
  if (IsListEmpty(&Open->RequestList)) { 
    *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
    NdisReleaseSpinLock(&Open->RequestSpinLock);
    return NDIS_STATUS_SUCCESS;
  }

  RequestListEntry = RemoveHeadList(&Open->RequestList);
  NdisReleaseSpinLock(&Open->RequestSpinLock);
  
  pReserved = CONTAINING_RECORD(RequestListEntry, PACKET_RESERVED, ListElement);
  pRequest  = CONTAINING_RECORD(pReserved, INTERNAL_REQUEST, Reserved);
  OidData   = (EPACKET_OID*)(pDiocParms->lpvInBuffer);

  if ((pDiocParms->cbInBuffer != pDiocParms->cbOutBuffer) ||
      (pDiocParms->cbInBuffer < sizeof(*OidData) - sizeof(OidData->Data) + OidData->Length)) {
    *(DWORD *)pDiocParms->lpcbBytesReturned = 1;
    return NDIS_STATUS_BUFFER_TOO_SHORT;
  }

  // The buffer is valid
  pReserved->lpBuffer          = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer);
  pReserved->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD));
  pReserved->lpoOverlapped     = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED));
  pReserved->cbBuffer          = pDiocParms->cbInBuffer;
  pReserved->hDevice           = pDiocParms->hDevice;
  pReserved->tagProcess        = pDiocParms->tagProcess;
  
  if (FunctionCode == IOCTL_EPACKET_SET_OID) {                      
    pRequest->Request.RequestType                                  = NdisRequestSetInformation;
    pRequest->Request.DATA.SET_INFORMATION.Oid                     = OidData->Oid;
    pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length;
    pRequest->Request.DATA.SET_INFORMATION.InformationBuffer       = OidData->Data;
  } 
  else {
    if (OidData->Oid >= 0x01000000)
      pRequest->Request.RequestType = NdisRequestQueryInformation;
    else
      pRequest->Request.RequestType = NdisRequestGeneric1;
    pRequest->Request.DATA.QUERY_INFORMATION.Oid                     = OidData->Oid;
    pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length;
    pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer       = OidData->Data;
  }

  // submit the request
  NdisRequest(&Status, Open->AdapterHandle, &pRequest->Request);

  if (Status == NDIS_STATUS_PENDING)
    return(-1);      // This will make DeviceIOControl return ERROR_IO_PENDING

  PacketRequestComplete(Open, &pRequest->Request, Status);
  return Status;
}
Esempio n. 13
0
static
NTSTATUS
QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
    PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
    PNDISUIO_QUERY_OID QueryOidRequest;
    NDIS_REQUEST Request;
    ULONG RequestLength;
    NDIS_STATUS Status;

    Irp->IoStatus.Information = 0;

    QueryOidRequest = Irp->AssociatedIrp.SystemBuffer;
    RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
    if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
    {
        /* Setup the NDIS request */
        Request.RequestType = NdisRequestQueryInformation;
        Request.DATA.QUERY_INFORMATION.Oid = QueryOidRequest->Oid;
        Request.DATA.QUERY_INFORMATION.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
        if (Request.DATA.QUERY_INFORMATION.InformationBufferLength != 0)
        {
            Request.DATA.QUERY_INFORMATION.InformationBuffer = QueryOidRequest->Data;
        }
        else
        {
            Request.DATA.QUERY_INFORMATION.InformationBuffer = NULL;
        }
        Request.DATA.QUERY_INFORMATION.BytesWritten = 0;

        DPRINT("Querying OID 0x%x on adapter %wZ\n", QueryOidRequest->Oid, &AdapterContext->DeviceName);
        
        /* Dispatch the request */
        NdisRequest(&Status,
                    AdapterContext->BindingHandle,
                    &Request);
        
        /* Wait for the request */
        if (Status == NDIS_STATUS_PENDING)
        {
            KeWaitForSingleObject(&AdapterContext->AsyncEvent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = AdapterContext->AsyncStatus;
        }

        /* Return the bytes written */
        if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(NDIS_OID) + Request.DATA.QUERY_INFORMATION.BytesWritten;

        DPRINT("Final request status: 0x%x (%d)\n", Status, Irp->IoStatus.Information);
    }
    else
    {
        /* Bad parameters */
        Status = STATUS_INVALID_PARAMETER;
    }
    
    Irp->IoStatus.Status = Status;
    
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return Status;
}
Esempio n. 14
0
VOID
NdisMlidStatisticTimer(
    IN PVOID SystemSpecific1,
    IN PVOID Context,
    IN PVOID SystemSpecific2,
    IN PVOID SystemSpecific3
    )

/*++

Routine Description:

    This DPC routine is queued to gather statistics from then
    NDIS MAC.

Arguments:

    Context - Really a pointer to the MLID.

Return Value:

    None.

--*/
{
    PMLID_STRUCT Mlid = (PMLID_STRUCT)Context;
    PNDIS_REQUEST NdisMlidRequest = &(Mlid->StatsTable->NdisRequest);
    NDIS_STATUS NdisStatus;

    NdisAcquireSpinLock(&(Mlid->MlidSpinLock));

    //
    // Loop
    //
    while (TRUE) {

        //
        // Set up NdisRequest
        //
        NdisMlidRequest->RequestType = NdisRequestQueryInformation;

        switch (Mlid->NdisMlidMedium) {

            case NdisMedium802_3:

                switch (Mlid->StatsTable->StatisticNumber) {

                    case 0:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_XMIT_ONE_COLLISION;
                        break;

                    case 1:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_XMIT_MORE_COLLISIONS;
                        break;

                    case 2:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_XMIT_DEFERRED;
                        break;

                    case 3:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_XMIT_LATE_COLLISIONS;
                        break;

                    case 4:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_XMIT_MAX_COLLISIONS;
                        break;

                    case 5:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_XMIT_TIMES_CRS_LOST;
                        break;

                    case 6:
                        goto DoNextStatistic;

                    case 7:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_3_RCV_ERROR_ALIGNMENT;
                        break;

                }

                break;

            case NdisMedium802_5:
                switch (Mlid->StatsTable->StatisticNumber) {

                    case 0:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_AC_ERRORS;
                        break;

                    case 1:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_ABORT_DELIMETERS;
                        break;

                    case 2:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_BURST_ERRORS;
                        break;

                    case 3:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_FRAME_COPIED_ERRORS;
                        break;

                    case 4:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_FREQUENCY_ERRORS;
                        break;

                    case 5:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_INTERNAL_ERRORS;
                        break;

                    case 6:

                        goto DoNextStatistic;

                    case 7:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_LINE_ERRORS;
                        break;

                    case 8:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_LOST_FRAMES;
                        break;

                    case 9:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                                 OID_802_5_TOKEN_ERRORS;
                        break;

                    case 10:
                    case 11:
                    case 12:

                        goto DoNextStatistic;

                }

                break;

            case NdisMediumFddi:

                switch (Mlid->StatsTable->StatisticNumber) {

                    case 0:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_ATTACHMENT_TYPE;

                        break;

                    case 1:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_UPSTREAM_NODE_LONG;

                        break;

                    case 2:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_DOWNSTREAM_NODE_LONG;

                        break;

                    case 3:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_FRAME_ERRORS;

                        break;

                    case 4:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_FRAMES_LOST;

                        break;

                    case 5:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_RING_MGT_STATE;

                        break;

                    case 6:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_LCT_FAILURES;

                        break;

                    case 7:
                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_LEM_REJECTS;

                        break;

                    case 8: // LemCount

                        goto DoNextStatistic;

                    case 9:

                        NdisMlidRequest->DATA.QUERY_INFORMATION.Oid =
                            OID_FDDI_LCONNECTION_STATE;

                        break;

                    default:

                        goto DoNextStatistic;
                }

                break;

        }

        NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBuffer =
               (PVOID)&(Mlid->StatsTable->StatisticValue);
        NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
               sizeof(Mlid->StatsTable->StatisticValue);
        NdisMlidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
        NdisMlidRequest->DATA.QUERY_INFORMATION.BytesNeeded = 0;

        NdisReleaseSpinLock(&(Mlid->MlidSpinLock));

        NdisRequest(
            &NdisStatus,
            Mlid->NdisBindingHandle,
            NdisMlidRequest
            );

        //
        // if (pending), exit.
        //

        if (NdisStatus == NDIS_STATUS_PENDING) {

            return;

        }

        NdisAcquireSpinLock(&(Mlid->MlidSpinLock));

        if (NdisStatus == NDIS_STATUS_SUCCESS) {

            //
            // Store Statistic
            //
            (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MMediaCountsPtr))
                [
                Mlid->StatsTable->StatisticNumber
                ].StatCounter))) =
                Mlid->StatsTable->StatisticValue;

        }

DoNextStatistic:

        Mlid->StatsTable->StatisticNumber++;


        switch (Mlid->NdisMlidMedium) {

            case NdisMedium802_3:

                if (Mlid->StatsTable->StatisticNumber >= NUM_ETHERNET_COUNTS) {
                    Mlid->StatsTable->StatisticNumber = 0;
                }

                break;

            case NdisMedium802_5:

                if (Mlid->StatsTable->StatisticNumber >= NUM_TOKEN_RING_COUNTS) {
                    Mlid->StatsTable->StatisticNumber = 0;
                }

                break;

            case NdisMediumFddi:

                if (Mlid->StatsTable->StatisticNumber >= NUM_FDDI_COUNTS) {
                    Mlid->StatsTable->StatisticNumber = 0;
                }

                break;

        }

        if (Mlid->StatsTable->StatisticNumber == 0) {

            //
            // Set timer for 30 seconds from now.
            //
            NdisReleaseSpinLock(&(Mlid->MlidSpinLock));

            NdisSetTimer(&(Mlid->StatsTable->StatisticTimer), 30000);

            return;

        }

    }

}
NDIS_STATUS
SecLabDoRequest(
    IN PADAPT			            pAdapt,
    IN NDIS_REQUEST_TYPE            RequestType,
    IN NDIS_OID                     Oid,
    IN PVOID                        InformationBuffer,
    IN UINT                         InformationBufferLength,
    OUT PUINT                       pBytesProcessed
    )
{
	SECLAB_REQUEST              ReqContext;
    PNDIS_REQUEST               pNdisRequest = &ReqContext.Request;
    NDIS_STATUS                 Status;

    NdisInitializeEvent(&ReqContext.ReqEvent);
    ReqContext.Signal=REQUEST_SIGNAL;

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

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

        default:
            break;
    }

    NdisRequest(&Status,
                pAdapt->BindingHandle,
                pNdisRequest);
    

    if (Status == NDIS_STATUS_PENDING)
    {
        NdisWaitEvent(&ReqContext.ReqEvent, 0);
        Status = ReqContext.Status;
    }

    if (Status == NDIS_STATUS_SUCCESS)
    {
        *pBytesProcessed = (RequestType == NdisRequestQueryInformation)?
                            pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten:
                            pNdisRequest->DATA.SET_INFORMATION.BytesRead;
    }

    return (Status);
}