Home | Info | Community | Development | myReactOS | Contact Us
Definition at line 2596 of file iofunc.c.
{ PFILE_OBJECT FileObject; PLARGE_INTEGER LocalLength = NULL; PIRP Irp; PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; PKEVENT Event = NULL; BOOLEAN LocalEvent = FALSE; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); LARGE_INTEGER CapturedByteOffset, CapturedLength; NTSTATUS Status; OBJECT_HANDLE_INFORMATION HandleInformation; IO_STATUS_BLOCK KernelIosb; PAGED_CODE(); CapturedByteOffset.QuadPart = 0; CapturedLength.QuadPart = 0; IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType, PreviousMode, (PVOID*)&FileObject, &HandleInformation); if (!NT_SUCCESS(Status)) return Status; /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */ if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA))) { ObDereferenceObject(FileObject); return STATUS_ACCESS_DENIED; } /* Enter SEH for probing */ _SEH2_TRY { /* Probe the I/O Status block */ ProbeForWriteIoStatusBlock(IoStatusBlock); /* Probe and capture the large integers */ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); CapturedLength = ProbeForReadLargeInteger(Length); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Dereference the object and return exception code */ ObDereferenceObject(FileObject); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } else { /* Otherwise, capture them directly */ CapturedByteOffset = *ByteOffset; CapturedLength = *Length; } /* Check if this is a direct open or not */ if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) { DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); } else { DeviceObject = IoGetRelatedDeviceObject(FileObject); } /* Check if we should use Sync IO or not */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { /* Lock it */ IopLockFileObject(FileObject); } else { /* Use local event */ Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); if (!Event) { ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; } KeInitializeEvent(Event, SynchronizationEvent, FALSE); LocalEvent = TRUE; } /* Clear File Object event */ KeClearEvent(&FileObject->Event); /* Allocate the IRP */ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, Event); /* Set up the IRP */ Irp->RequestorMode = PreviousMode; Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; Irp->UserEvent = (LocalEvent) ? Event : NULL; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Tail.Overlay.OriginalFileObject = FileObject; Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; /* Set up Stack Data */ StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE; StackPtr->FileObject = FileObject; /* Enter SEH */ _SEH2_TRY { /* Allocate a buffer */ LocalLength = ExAllocatePoolWithTag(NonPagedPool, sizeof(LARGE_INTEGER), TAG_LOCK); /* Set the length */ *LocalLength = CapturedLength; Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength; StackPtr->Parameters.LockControl.Length = LocalLength; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Allocating failed, clean up and return the exception code */ IopCleanupAfterException(FileObject, Irp, NULL, Event); if (LocalLength) ExFreePool(LocalLength); /* Return the exception code */ _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; /* Set Parameters */ StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset; StackPtr->Parameters.LockControl.Key = Key; /* Call the Driver */ Status = IopPerformSynchronousRequest(DeviceObject, Irp, FileObject, FALSE, PreviousMode, !LocalEvent, IopOtherTransfer); /* Check if this was async I/O */ if (LocalEvent) { /* It was, finalize this request */ Status = IopFinalizeAsynchronousIo(Status, Event, Irp, PreviousMode, &KernelIosb, IoStatusBlock); } /* Return status */ return Status; }