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

	// DebugPrint(("PacketCancelReadIrps\n"));

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

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

		ASSERT(myPacket);

		pendingIrp = RESERVED(myPacket)->Irp;

		NdisFreePacket(myPacket);

		// DebugPrint(("Cancelled : 0%0x\n", pendingIrp));

		IoSetCancelRoutine(pendingIrp, NULL);

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

	return STATUS_SUCCESS;
}
예제 #2
0
NTSTATUS
PacketClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    // This is the dispatch routine for create/open and close requests.
    // These requests complete successfully.

    POPEN_INSTANCE      open;
    NTSTATUS            status = STATUS_SUCCESS;

    DebugPrint(("CloseAdapter \n"));

#ifdef XNSDRW_LOG_PACKETS
    // reset the packet sniffing log
    LogReset();
#endif

    if (DeviceObject == Globals.ControlDeviceObject)
    {
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    open = DeviceObject->DeviceExtension;

    IoIncrement(open);

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

    IoDecrement(open);
    return status;
}
예제 #3
0
NTSTATUS
DispatchCleanup(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    POPEN_INSTANCE      pOpen = (POPEN_INSTANCE)DeviceObject->DeviceExtension;
    NTSTATUS            status = STATUS_SUCCESS;


    if(DeviceObject == g_data.pControlDevice) 
	{
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    IoIncrement(pOpen);
 
    CancelReadIrp(DeviceObject);

    IoDecrement(pOpen);

    NdisWaitEvent(&pOpen->CleanupEvent, 0);

    Irp->IoStatus.Information = 0;    
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    return status;

}
예제 #4
0
VOID
ProtocolResetComplete(
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status
    )

{
	OPEN_INSTANCE *pOpen;
    pOpen = (OPEN_INSTANCE*)ProtocolBindingContext;

	// 取出IRP指针
	PLIST_ENTRY pListEntry = ExInterlockedRemoveHeadList(
                       &pOpen->ResetIrpList,
                       &pOpen->ResetQueueLock
                       );
    PIRP pIrp = CONTAINING_RECORD(pListEntry,IRP,Tail.Overlay.ListEntry);

	// 完成此IRP
    if(Status == NDIS_STATUS_SUCCESS) 
	{
        pIrp->IoStatus.Status = STATUS_SUCCESS;
    } 
	else 
	{
        pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
    }
    pIrp->IoStatus.Information = 0;    
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    IoDecrement(pOpen);
}
예제 #5
0
// 处理IRP_MJ_CREATE、IRP_MJ_CLOSE功能代码
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint(" ProtoDrv: DispatchCreate \n");
	NTSTATUS status = STATUS_SUCCESS;
	
	if(pDevObj == g_data.pControlDevice)
	{
		pIrp->IoStatus.Status = STATUS_SUCCESS;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		return status;
	}
	
	POPEN_INSTANCE pOpen = (POPEN_INSTANCE)pDevObj->DeviceExtension;


	IoIncrement(pOpen);

	if(!pOpen->bBound)
	{
		status = STATUS_DEVICE_NOT_READY;
	}
	
	pIrp->IoStatus.Information = 0;
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	
	IoDecrement(pOpen);
	return status;
}
예제 #6
0
VOID
ProtocolSendComplete(
    IN NDIS_HANDLE   ProtocolBindingContext,
    IN PNDIS_PACKET  pPacket,
    IN NDIS_STATUS   Status
    )
{
	OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)ProtocolBindingContext;
	PIRP pIrp = RESERVED(pPacket)->pIrp;
	PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);

	// 释放封包
	NdisFreePacket(pPacket);
	// 完成IRP请求
	if(Status == NDIS_STATUS_SUCCESS)
	{
		pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
		pIrp->IoStatus.Status = STATUS_SUCCESS;

		DbgPrint(" ProtoDrv: Send data success \n");
	}
	else
	{
		pIrp->IoStatus.Information = 0;
		pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
	}
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	IoDecrement(pOpen);
}
예제 #7
0
NTSTATUS PacketRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
	POPEN_INSTANCE      open;
	PNDIS_PACKET        pPacket;
	NDIS_STATUS         status;
	NTSTATUS            ntStatus;
	PIO_STACK_LOCATION  irpSp;

	// DebugPrint(("Read\n"));

	open = DeviceObject->DeviceExtension;

	IoIncrement(open);

	if(!open->Bound) {
		ntStatus = STATUS_DEVICE_NOT_READY;
		goto ERROR;
	}

	irpSp = IoGetCurrentIrpStackLocation(Irp);

	if (irpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) {
		ntStatus = STATUS_BUFFER_TOO_SMALL;
		goto ERROR;
	}

	NdisAllocatePacket( &status, &pPacket, open->PacketPool );
	if (status != NDIS_STATUS_SUCCESS) {
		// DebugPrint(("Packet: Read- No free packets\n"));
		ntStatus = STATUS_INSUFFICIENT_RESOURCES;
		goto ERROR;
	}

	RESERVED(pPacket)->Irp=Irp;
	RESERVED(pPacket)->pMdl=NULL;
	IoMarkIrpPending(Irp);

	IoSetCancelRoutine(Irp, PacketCancelRoutine);

	ExInterlockedInsertTailList(
			&open->RcvList,
			&RESERVED(pPacket)->ListElement,
			&open->RcvQSpinLock);

	return STATUS_PENDING;

ERROR:
	Irp->IoStatus.Status = ntStatus;
	IoCompleteRequest (Irp, IO_NO_INCREMENT);
	IoDecrement(open);
	return ntStatus;
}
예제 #8
0
NTSTATUS DispatchWrite(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS status;

	// 取得描述适配器的OPEN_INSTANCE结构的指针
	OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)pDevObj->DeviceExtension;
	// 增加IO引用计数
	IoIncrement(pOpen);
	do
	{
		if(!pOpen->bBound)
		{
			status = STATUS_DEVICE_NOT_READY;
			break;
		}

		// 从封包池中申请一个封包
		PNDIS_PACKET pPacket;
		NdisAllocatePacket((NDIS_STATUS*)&status, &pPacket, pOpen->hPacketPool);
		if(status != NDIS_STATUS_SUCCESS)	// 封包被申请完了!
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}

		RESERVED(pPacket)->pIrp = pIrp; // 保存IRP指针,在完成例程中还要使用

		// 附加写缓冲区到封包
		NdisChainBufferAtFront(pPacket, pIrp->MdlAddress);

		// 注意,既然我们已经标识此IRP未决,我们必须返回STATUS_PENDING,即便是
		// 我们恰巧同步完成了这个IRP
		IoMarkIrpPending(pIrp);

		// 发送封包到下层NIC设备
		NdisSend((NDIS_STATUS*)&status, pOpen->hAdapter, pPacket);
		if(status != NDIS_STATUS_PENDING)
		{
			ProtocolSendComplete(pOpen, pPacket, status);
		}
		return STATUS_PENDING;		
	}while(FALSE);

	if(status != STATUS_SUCCESS)
	{
		IoDecrement(pOpen);
		pIrp->IoStatus.Information = 0;
		pIrp->IoStatus.Status = status;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	}
	return status;
}
예제 #9
0
VOID
PacketResetComplete(IN NDIS_HANDLE  ProtocolBindingContext, IN NDIS_STATUS  Status)
{
    // This routine  is called when a protocol-initiated reset operation, 
    // begun with a call to NdisReset that returned NDIS_STATUS_PENDING, 
    // is completed. 

    POPEN_INSTANCE      open;
    PIRP                irp;

    PLIST_ENTRY         resetListEntry;

    DebugPrint(("PacketResetComplte\n"));

#ifdef XNSDRW_LOG_PACKETS
    // reset the packet sniff log
    LogReset();
#endif

    open = (POPEN_INSTANCE)ProtocolBindingContext;


    //  remove the reset IRP from the list
    resetListEntry = ExInterlockedRemoveHeadList(&open->ResetIrpList, &open->ResetQueueLock);

#if DBG
    if (resetListEntry == NULL)
    {
        DbgBreakPoint();
        return;
    }
#endif

    irp = CONTAINING_RECORD(resetListEntry, IRP, Tail.Overlay.ListEntry);

    if (Status == NDIS_STATUS_SUCCESS) irp->IoStatus.Status = STATUS_SUCCESS;
    else irp->IoStatus.Status = STATUS_UNSUCCESSFUL;

    irp->IoStatus.Information = 0;    
    IoCompleteRequest(irp, IO_NO_INCREMENT);
    IoDecrement(open);

    DebugPrint(("PacketResetComplte exit\n"));
}
예제 #10
0
NTSTATUS
PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    // This is the dispatch routine for create/open and close requests.
    // These requests complete successfully.

    POPEN_INSTANCE      open;
    NTSTATUS            status = STATUS_SUCCESS;

    DebugPrint(("OpenAdapter\n"));

#ifdef XNSDRW_LOG_PACKETS
    // reset the packet sniffing log
    LogReset();
#endif

    if (DeviceObject == Globals.ControlDeviceObject)
    {
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
    
    open = DeviceObject->DeviceExtension;

    DebugPrint(("AdapterName :%ws\n", open->AdapterName.Buffer));

    IoIncrement(open);

    // Check to see whether you are still bound to the adapter
    if(! open->Bound)
    {
        status = STATUS_DEVICE_NOT_READY;
    }

    Irp->IoStatus.Information = 0;    
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    IoDecrement(open);
    return status;
}
예제 #11
0
VOID
ProtocolRequestComplete(
    IN NDIS_HANDLE   ProtocolBindingContext,
    IN PNDIS_REQUEST NdisRequest,
    IN NDIS_STATUS   Status
    )
{
	POPEN_INSTANCE pOpen = (POPEN_INSTANCE)ProtocolBindingContext;
	PINTERNAL_REQUEST pInterRequest = CONTAINING_RECORD(NdisRequest, INTERNAL_REQUEST, Request);
	PIRP pIrp = pInterRequest->pIrp;

	if(Status == NDIS_STATUS_SUCCESS)
	{
		PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
		UINT nIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
		PPROTOCOL_OID_DATA pOidData = (PPROTOCOL_OID_DATA)pIrp->AssociatedIrp.SystemBuffer;

		//  将大小返回到用户缓冲区
        if(nIoControlCode == IOCTL_PROTOCOL_SET_OID) 
		{
            pOidData->Length = pInterRequest->Request.DATA.SET_INFORMATION.BytesRead;
        } 
		else if(nIoControlCode == IOCTL_PROTOCOL_QUERY_OID) 
		{
			pOidData->Length = pInterRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
		}	

		// 设置返回给I/O管理器的信息
		pIrp->IoStatus.Information = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
		pIrp->IoStatus.Status = STATUS_SUCCESS;
	}
	else
	{
		pIrp->IoStatus.Information = 0;
		pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
	}
	ExFreePool(pInterRequest);
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	IoDecrement(pOpen);
}
예제 #12
0
VOID
PacketTransferDataComplete (
	IN NDIS_HANDLE   ProtocolBindingContext,
	IN PNDIS_PACKET  pPacket,
	IN NDIS_STATUS   Status,
	IN UINT          BytesTransfered
)
{
	PIO_STACK_LOCATION   irpSp;
	POPEN_INSTANCE       open;
	PIRP                 irp;
	PMDL                 pMdl;

	// DebugPrint(("Packet: TransferDataComplete\n"));

	open = (POPEN_INSTANCE)ProtocolBindingContext;
	irp = RESERVED(pPacket)->Irp;
	irpSp = IoGetCurrentIrpStackLocation(irp);
	pMdl = RESERVED(pPacket)->pMdl;


	if(pMdl) IoFreeMdl(pMdl);

	NdisFreePacket(pPacket);

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

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

	IoCompleteRequest(irp, IO_NO_INCREMENT);
	IoDecrement(open);
}
예제 #13
0
NTSTATUS
PacketCleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    // This is the dispatch routine for cleanup requests.
    // This routine is called whenever a handle to the device is closed.

    POPEN_INSTANCE      open;
    NTSTATUS            status = STATUS_SUCCESS;

    DebugPrint(("Packet: Cleanup\n"));

    if (DeviceObject == Globals.ControlDeviceObject)
    {
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    open = DeviceObject->DeviceExtension;

    IoIncrement(open);
    
    // Cancel all the pending reads.
    PacketCancelReadIrps(DeviceObject);

    // Since the current implementation of NDIS doesn't
    // allow us to cancel requests pending at the 
    // miniport, we must wait here until they complete.
    IoDecrement(open);

    NdisWaitEvent(&open->CleanupEvent, 0);

    Irp->IoStatus.Information = 0;    
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    return status;
}
예제 #14
0
VOID
PacketCancelRoutine (
	IN PDEVICE_OBJECT   DeviceObject,
	IN PIRP             Irp
)

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

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

	oldIrql = Irp->CancelIrql;

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

	KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock);
	IoReleaseCancelSpinLock( KeGetCurrentIrql() );

	listHead = &open->RcvList;
	for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) {
		reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
		myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);
		pendingIrp = RESERVED(myPacket)->Irp;
		if (pendingIrp == Irp) {
			RemoveEntryList(thisEntry);
			irpToComplete = pendingIrp;
			break;
		}
	}

	KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql);

	if(irpToComplete) {
		// DebugPrint(("Cancelling IRP\n"));
		// ASSERT(myPacket);

		NdisFreePacket(myPacket);

		irpToComplete->IoStatus.Status = STATUS_CANCELLED;
		irpToComplete->IoStatus.Information = 0;
		IoCompleteRequest(irpToComplete, IO_NO_INCREMENT);
		IoDecrement(open);
	}
}
예제 #15
0
INT
PacketReceivePacket(
	IN    NDIS_HANDLE         ProtocolBindingContext,
	IN    PNDIS_PACKET        Packet
)
{
	UINT                bytesTransfered = 0;
	POPEN_INSTANCE      open;
	PIRP                irp;
	PNDIS_PACKET        myPacket;
	PLIST_ENTRY         packetListEntry;
	ULONG               bufferLength;
	PPACKET_RESERVED    reserved;
	PIO_STACK_LOCATION  irpSp;
	PMDL                mdl;
	PVOID               startAddress;
	NTSTATUS           status;

	// DebugPrint(("PacketReceivePacket\n"));

	open = (POPEN_INSTANCE)ProtocolBindingContext;

	packetListEntry = ExInterlockedRemoveHeadList(
											&open->RcvList,
											&open->RcvQSpinLock
											);

	if (packetListEntry == NULL) {
		// DebugPrint(("No pending read, dropping packets\n"));
		return 0;
	}

	reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement);
	myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

	irp = RESERVED(myPacket)->Irp;
	irpSp = IoGetCurrentIrpStackLocation(irp);

	// We don't have to worry about the situation where the IRP is cancelled
	// after we remove it from the queue and before we reset the cancel
	// routine because the cancel routine has been coded to cancel an IRP
	// only if it's in the queue.

	IoSetCancelRoutine(irp, NULL);

	// Following block of code locks the destination packet
	// MDLs in a safe manner. This is a temporary workaround
	// for NdisCopyFromPacketToPacket that currently doesn't use
	// safe functions to lock pages of MDL. This is required to
	// prevent system from bugchecking under low memory resources.
	//
	{
		PVOID           virtualAddress;
		PNDIS_BUFFER    firstBuffer, nextBuffer;
		ULONG           totalLength;

		NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
		while( firstBuffer ) {
			NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority );
			if(!virtualAddress) {
				status = STATUS_INSUFFICIENT_RESOURCES;
				goto CleanExit;
			}
			NdisGetNextBuffer(firstBuffer,  &nextBuffer);
			firstBuffer = nextBuffer;
		}
	}

	NdisChainBufferAtFront( myPacket, irp->MdlAddress );
	bufferLength=irpSp->Parameters.Read.Length;
	NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0,  &bytesTransfered );

CleanExit:
	NdisFreePacket(myPacket);
	irp->IoStatus.Status = status;
	irp->IoStatus.Information = bytesTransfered;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	// DebugPrint(("BytesTransfered:%d\n", bytesTransfered));
	IoDecrement(open);
	return 0;
}
예제 #16
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;
}