Home | Info | Community | Development | myReactOS | Contact Us
Definition at line 140 of file rw.c.
{ PIO_STACK_LOCATION Stack; PSERIAL_DEVICE_EXTENSION DeviceExtension; ULONG Length; PUCHAR Buffer; PWORKITEM_DATA WorkItemData; PIO_WORKITEM WorkItem; NTSTATUS Status; TRACE_(SERIAL, "IRP_MJ_READ\n"); Stack = IoGetCurrentIrpStackLocation(Irp); Length = Stack->Parameters.Read.Length; Buffer = SerialGetUserBuffer(Irp); DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (Stack->Parameters.Read.ByteOffset.QuadPart != 0 || Buffer == NULL) { Status = STATUS_INVALID_PARAMETER; goto ByeBye; } if (Length == 0) { Status = STATUS_SUCCESS; goto ByeBye; } /* Allocate memory for parameters */ WorkItemData = ExAllocatePoolWithTag(PagedPool, sizeof(WORKITEM_DATA), SERIAL_TAG); if (!WorkItemData) { Status = STATUS_INSUFFICIENT_RESOURCES; goto ByeBye; } RtlZeroMemory(WorkItemData, sizeof(WORKITEM_DATA)); WorkItemData->Irp = Irp; /* Calculate time outs */ if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE && DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == INFINITE && DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 && DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant < INFINITE) { /* read at least one byte, and at most bytes already received */ WorkItemData->DontWait = TRUE; WorkItemData->ReadAtLeastOneByte = TRUE; } else if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE && DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 && DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0) { /* read only bytes that are already in buffer */ WorkItemData->DontWait = TRUE; } else { /* use timeouts */ if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0) { WorkItemData->UseIntervalTimeout = TRUE; WorkItemData->IntervalTimeout.QuadPart = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout; } if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0 || DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0) { ULONG TotalTimeout; LARGE_INTEGER SystemTime; WorkItemData->UseTotalTimeout = TRUE; TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant + DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier * Length; KeQuerySystemTime(&SystemTime); WorkItemData->TotalTimeoutTime.QuadPart = SystemTime.QuadPart + TotalTimeout * 10000; } } /* Pend IRP */ WorkItem = IoAllocateWorkItem(DeviceObject); if (WorkItem) { WorkItemData->IoWorkItem = WorkItem; IoMarkIrpPending(Irp); IoQueueWorkItem(WorkItem, SerialReadWorkItem, DelayedWorkQueue, WorkItemData); return STATUS_PENDING; } /* Insufficient resources, we can't pend the Irp */ INFO_(SERIAL, "Insufficient resources\n"); Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(WorkItemData, SERIAL_TAG); goto ByeBye; } ReadBytes(DeviceObject, Irp, WorkItemData); Status = Irp->IoStatus.Status; IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort)); ByeBye: Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }