// 处理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; }
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; }
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; }
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; }
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; }
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; }
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; }
// 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; }