NTSTATUS LpxTdiIoCallDriver( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp, IN PIO_STATUS_BLOCK IoStatusBlock, IN PKEVENT Event, IN PLARGE_INTEGER TimeOut ) { NTSTATUS ntStatus; NTSTATUS wait_status; // LARGE_INTEGER timeout; // // set a expire time to IRP. // LPX takes whole charge of IRP completion. // LPX will measure time-out. // Do not wait with time-out here. // BSOD may occur if you do. // // added by hootch 02092004 if(TimeOut) SET_IRP_EXPTIME(Irp, CurrentTime().QuadPart + TimeOut->QuadPart); else SET_IRP_EXPTIME(Irp, 0); Irp->Tail.Overlay.DriverContext[2] = (PVOID)0; LtDebugPrint(2, ("[LpxTdi] Irp->Tail.Overlay.DriverContext[2] == %p\n", Irp->Tail.Overlay.DriverContext[2])); ntStatus = IoCallDriver( DeviceObject, Irp ); if(ntStatus == STATUS_PENDING) { if(Event) { wait_status = KeWaitForSingleObject( Event, Executive, KernelMode, FALSE, NULL ); if(wait_status != STATUS_SUCCESS) { LtDebugPrint(1, ("[LpxTdi] LpxTdiIoCallDriver: Wait for event Failed.\n")); return STATUS_CONNECTION_DISCONNECTED; // STATUS_TIMEOUT; } } else { return ntStatus; } } ntStatus = IoStatusBlock->Status; return ntStatus; }
NTSTATUS LpxTdiRecvWithCompletionEvent_TimeOut( IN PFILE_OBJECT ConnectionFileObject, IN PTDI_RECEIVE_CONTEXT TdiReceiveContext, OUT PUCHAR RecvBuffer, IN ULONG RecvLength, IN ULONG Flags, IN PLARGE_INTEGER TimeOut ) { PDEVICE_OBJECT deviceObject; PIRP irp; NTSTATUS ntStatus; PMDL mdl; ASSERT(ConnectionFileObject); LtDebugPrint (3, ("LpxTdiRecvWithCompletionEvent: Entered\n")); if((RecvBuffer == NULL) || (RecvLength == 0)) { LtDebugPrint(1, ("[LpxTdi]TdiReceive: Rcv buffer == NULL or RcvLen == 0.\n")); return STATUS_NOT_IMPLEMENTED; } deviceObject = IoGetRelatedDeviceObject(ConnectionFileObject); // // Make IRP. // irp = TdiBuildInternalDeviceControlIrp( TDI_RECEIVE, deviceObject, connectionFileObject, NULL, NULL ); if(irp == NULL) { LtDebugPrint(1, ("[LpxTdi]TdiReceive: Can't Build IRP.\n")); return STATUS_INSUFFICIENT_RESOURCES; } mdl = IoAllocateMdl( RecvBuffer, RecvLength, FALSE, FALSE, irp ); if(mdl == NULL) { LtDebugPrint(1, ("[LpxTdi]TdiReceive: Can't Allocate MDL.\n")); IoFreeIrp(irp); return STATUS_INSUFFICIENT_RESOURCES; } mdl->Next = NULL; MmBuildMdlForNonPagedPool(mdl); TdiBuildReceive( irp, deviceObject, ConnectionFileObject, LpxTdiRecvWithCompletionEventCompletionRoutine, TdiReceiveContext, mdl, Flags, RecvLength ); if(TimeOut) SET_IRP_EXPTIME(irp, CurrentTime().QuadPart + TimeOut->QuadPart); else SET_IRP_EXPTIME(irp, 0); ntStatus = IoCallDriver( deviceObject, irp ); if(!NT_SUCCESS(ntStatus)) { TdiReceiveContext->Irp = NULL; LtDebugPrint(1, ("[LpxTdi]LpxTdiRecv: Failed.\n")); return ntStatus; } TdiReceiveContext->Irp = irp; return ntStatus; }
NTSTATUS LpxTdiIoCallDriver( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, OUT PTRANS_STAT TransStat, IN PLARGE_INTEGER TimeOut, IN BOOLEAN Synchronous ){ NTSTATUS ntStatus; PKEVENT userEvent; PIO_STATUS_BLOCK userIoStatusBlock; // // set a expire time to IRP. // LPX takes whole charge of IRP completion. // LPX will measure time-out. // Do not wait with time-out here to prevent BSOD. // if(TimeOut) SET_IRP_EXPTIME(Irp, CurrentTime().QuadPart + TimeOut->QuadPart); else SET_IRP_EXPTIME(Irp, 0); Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_FOR_TRANS_STAT] = (PVOID)TransStat; // This entry is used for getting flow control hint. LtDebugPrint(2, ("[LpxTdi] LpxTdiIoCallDriver: Irp->Tail.Overlay.DriverContext[2] == %p\n", Irp->Tail.Overlay.DriverContext[DRIVER_CONTEXT_FOR_TRANS_STAT])); // // Extract event and IoStatusBlock set by the caller // if(Synchronous) { userEvent = Irp->UserEvent; userIoStatusBlock = Irp->UserIosb; if(userIoStatusBlock == NULL) { return STATUS_INVALID_PARAMETER; } if(Synchronous && userEvent == NULL) { return STATUS_INVALID_PARAMETER; } } else { userEvent = NULL; userIoStatusBlock = NULL; } // // Send IRP to the target device object. // ntStatus = IoCallDriver( DeviceObject, Irp ); if(ntStatus == STATUS_PENDING) { NTSTATUS wait_status; // // Target device is doing the request asynchronously. // If user event is set, wait for it instead of the caller. // if(Synchronous) { wait_status = KeWaitForSingleObject( userEvent, Executive, KernelMode, FALSE, NULL ); if(wait_status == STATUS_SUCCESS) { return userIoStatusBlock->Status; } else { LtDebugPrint(1, ("[LpxTdi] LpxTdiIoCallDriver: Wait for event Failed.\n")); ASSERT(FALSE); return STATUS_CONNECTION_DISCONNECTED; } } } else { // // the IRP is completed synchronously // // // If return value from IoCallDriver() is SUCCESS, // Make IoStatusBlock and return value same // by returning userIoStatusBlock. // If not, forwards the return value. // if (ntStatus == STATUS_SUCCESS) { if(userIoStatusBlock) { ASSERT(userIoStatusBlock->Status != STATUS_PENDING); return userIoStatusBlock->Status; } } else { if(userIoStatusBlock) { userIoStatusBlock->Status = ntStatus; } } } return ntStatus; }