/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/bug.c * PURPOSE: Graceful system shutdown if a bug is detected * PROGRAMMER: David Welch (welch@mcmail.com) * UPDATE HISTORY: * Created 22/05/98 */ /* INCLUDES *****************************************************************/ #include #define NDEBUG #include #define TAG_LOCK TAG('F','l','c','k') /* FUNCTIONS *****************************************************************/ NTSTATUS STDCALL NtLockFileCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { ExFreePool(Context); return STATUS_SUCCESS; //FIXME: should I call IoFreeIrp and return STATUS_MORE_PROCESSING_REQUIRED? } NTSTATUS STDCALL NtLockFile ( IN HANDLE FileHandle, IN HANDLE EventHandle OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK UserIoStatusBlock, IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER Length, IN PULONG Key, IN BOOLEAN FailImmediatedly, IN BOOLEAN ExclusiveLock ) { NTSTATUS Status; PFILE_OBJECT FileObject = NULL; PLARGE_INTEGER LocalLength = NULL; PKEVENT Event = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION StackPtr; IO_STATUS_BLOCK LocalIoStatusBlock; PIO_STATUS_BLOCK IoStatusBlock; PDEVICE_OBJECT DeviceObject; //FIXME: instead of this, use SEH when available? if (!Length || !ByteOffset) { Status = STATUS_INVALID_PARAMETER; goto fail; } /* BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode! It should ONLY fail if we desire an access that conflict with granted access! */ Status = ObReferenceObjectByHandle( FileHandle, FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to! IoFileObjectType, ExGetPreviousMode(), (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)){ goto fail; } DeviceObject = IoGetRelatedDeviceObject(FileObject); Irp = IoAllocateIrp( DeviceObject->StackSize, TRUE ); if (Irp == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto fail; } if (EventHandle != NULL && !FailImmediatedly) { Status = ObReferenceObjectByHandle( EventHandle, SYNCHRONIZE, ExEventObjectType, ExGetPreviousMode(), (PVOID*)&Event, NULL); if (!NT_SUCCESS(Status)) { goto fail; } } else { Event = &FileObject->Event; KeResetEvent(Event); } if ((FileObject->Flags & FO_SYNCHRONOUS_IO) || FailImmediatedly) IoStatusBlock = &LocalIoStatusBlock; else IoStatusBlock = UserIoStatusBlock; Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; Irp->UserEvent = Event; Irp->UserIosb = IoStatusBlock; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; StackPtr->MinorFunction = IRP_MN_LOCK; StackPtr->DeviceObject = DeviceObject; StackPtr->FileObject = FileObject; if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK; if (FailImmediatedly) StackPtr->Flags |= SL_FAIL_IMMEDIATELY; LocalLength = ExAllocatePoolWithTag( NonPagedPool, sizeof(LARGE_INTEGER), TAG_LOCK ); if (!LocalLength){ Status = STATUS_INSUFFICIENT_RESOURCES; goto fail; } *LocalLength = *Length; StackPtr->Parameters.LockControl.Length = LocalLength; StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset; StackPtr->Parameters.LockControl.Key = Key ? *Key : 0; IoSetCompletionRoutine( Irp, NtLockFileCompletionRoutine, LocalLength, TRUE, TRUE, TRUE ); Status = IofCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO)) { Status = KeWaitForSingleObject( Event, Executive, ExGetPreviousMode() , (FileObject->Flags & FO_ALERTABLE_IO) ? TRUE : FALSE, NULL ); if (Status != STATUS_WAIT_0) { DPRINT1("NtLockFile -> KeWaitForSingleObject failed!\n"); /* FIXME: should do some special processing here if alertable wait was interupted by user apc or a thread alert (STATUS_ALERTED, STATUS_USER_APC) */ return Status; //set status to something else? } Status = LocalIoStatusBlock.Status; } if (FileObject->Flags & FO_SYNCHRONOUS_IO) *UserIoStatusBlock = LocalIoStatusBlock; return Status; fail:; if (LocalLength) ExFreePool(LocalLength); if (Irp) IoFreeIrp(Irp); if (Event) ObDereferenceObject(Event); if (FileObject) ObDereferenceObject(FileObject); return Status; } NTSTATUS STDCALL NtUnlockFile ( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK UserIoStatusBlock, IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER Length, OUT PULONG Key OPTIONAL ) { NTSTATUS Status; PFILE_OBJECT FileObject = NULL; PLARGE_INTEGER LocalLength = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION StackPtr; IO_STATUS_BLOCK LocalIoStatusBlock; PDEVICE_OBJECT DeviceObject; //FIXME: instead of this, use SEH when available if (!Length || !ByteOffset) { Status = STATUS_INVALID_PARAMETER; goto fail; } /* BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode It should ONLY fail if we desire an access that conflict with granted access! */ Status = ObReferenceObjectByHandle( FileHandle, FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to! IoFileObjectType, ExGetPreviousMode(), (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)){ goto fail; } DeviceObject = IoGetRelatedDeviceObject(FileObject); Irp = IoAllocateIrp( DeviceObject->StackSize, TRUE ); if (Irp == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto fail; } Irp->UserIosb = &LocalIoStatusBlock; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); StackPtr = IoGetNextIrpStackLocation(Irp); StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE; StackPtr->DeviceObject = DeviceObject; StackPtr->FileObject = FileObject; LocalLength = ExAllocatePoolWithTag( NonPagedPool, sizeof(LARGE_INTEGER), TAG_LOCK ); if (!LocalLength){ Status = STATUS_INSUFFICIENT_RESOURCES; goto fail; } *LocalLength = *Length; StackPtr->Parameters.LockControl.Length = LocalLength; StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset; StackPtr->Parameters.LockControl.Key = Key ? *Key : 0; //allways syncronious Status = IofCallDriver(DeviceObject, Irp); *UserIoStatusBlock = LocalIoStatusBlock; ExFreePool(LocalLength); return Status; fail:; if (LocalLength) ExFreePool(LocalLength); if (Irp) IoFreeIrp(Irp); if (FileObject) ObDereferenceObject(FileObject); return Status; }