/* * ReactOS kernel * Copyright (C) 2002, 2003 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/filesystems/cdfs/common.c * PURPOSE: CDROM (ISO 9660) filesystem driver * PROGRAMMER: Art Yerkes * Eric Kohl */ /* INCLUDES *****************************************************************/ #include "cdfs.h" #define NDEBUG #include /* FUNCTIONS ****************************************************************/ NTSTATUS CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, IN ULONG DiskSector, IN ULONG SectorCount, IN OUT PUCHAR Buffer, IN BOOLEAN Override) { PIO_STACK_LOCATION Stack; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER Offset; ULONG BlockSize; KEVENT Event; PIRP Irp; NTSTATUS Status; BOOLEAN LastChance = FALSE; again: KeInitializeEvent(&Event, NotificationEvent, FALSE); Offset.u.LowPart = DiskSector << 11; Offset.u.HighPart = DiskSector >> 21; BlockSize = BLOCKSIZE * SectorCount; DPRINT("CdfsReadSectors(DeviceObject %p, DiskSector %u, Buffer %p)\n", DeviceObject, DiskSector, Buffer); DPRINT("Offset %I64x BlockSize %u\n", Offset.QuadPart, BlockSize); DPRINT("Building synchronous FSD Request...\n"); Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, DeviceObject, Buffer, BlockSize, &Offset, &Event, &IoStatus); if (Irp == NULL) { DPRINT("IoBuildSynchronousFsdRequest failed\n"); return(STATUS_INSUFFICIENT_RESOURCES); } if (Override) { Stack = IoGetNextIrpStackLocation(Irp); Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; } DPRINT("Calling IO Driver... with irp %p\n", Irp); Status = IoCallDriver(DeviceObject, Irp); DPRINT("Waiting for IO Operation for %p\n", Irp); if (Status == STATUS_PENDING) { DPRINT("Operation pending\n"); KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); DPRINT("Getting IO Status... for %p\n", Irp); Status = IoStatus.Status; } if (!NT_SUCCESS(Status)) { if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify; DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume(DeviceToVerify, FALSE); if (NT_SUCCESS(Status) && !LastChance) { DPRINT("Volume verify succeeded; trying request again\n"); LastChance = TRUE; goto again; } else if (NT_SUCCESS(Status)) { DPRINT1("Failed to read after successful verify, aborting\n"); Status = STATUS_DEVICE_NOT_READY; } else { DPRINT1("IoVerifyVolume() failed (Status %lx)\n", Status); } } DPRINT("CdfsReadSectors() failed (Status %x)\n", Status); DPRINT("(DeviceObject %p, DiskSector %u, Buffer %p, Offset 0x%I64x)\n", DeviceObject, DiskSector, Buffer, Offset.QuadPart); return(Status); } DPRINT("Block request succeeded for %p\n", Irp); return(STATUS_SUCCESS); } NTSTATUS CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, IN ULONG CtlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer, IN OUT PULONG OutputBufferSize, IN BOOLEAN Override) { PIO_STACK_LOCATION Stack; IO_STATUS_BLOCK IoStatus; KEVENT Event; PIRP Irp; NTSTATUS Status; BOOLEAN LastChance = FALSE; DPRINT("CdfsDeviceIoControl(DeviceObject %p, CtlCode %u, " "InputBuffer %p, InputBufferSize %u, OutputBuffer %p, " "POutputBufferSize %p (%x)\n", DeviceObject, CtlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, OutputBufferSize ? *OutputBufferSize : 0); again: KeInitializeEvent (&Event, NotificationEvent, FALSE); DPRINT("Building device I/O control request ...\n"); Irp = IoBuildDeviceIoControlRequest(CtlCode, DeviceObject, InputBuffer, InputBufferSize, OutputBuffer, (OutputBufferSize != NULL) ? *OutputBufferSize : 0, FALSE, &Event, &IoStatus); if (Irp == NULL) { DPRINT("IoBuildDeviceIoControlRequest failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } if (Override) { Stack = IoGetNextIrpStackLocation(Irp); Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; } DPRINT ("Calling IO Driver... with irp %p\n", Irp); Status = IoCallDriver(DeviceObject, Irp); DPRINT ("Waiting for IO Operation for %p\n", Irp); if (Status == STATUS_PENDING) { DPRINT ("Operation pending\n"); KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL); DPRINT ("Getting IO Status... for %p\n", Irp); Status = IoStatus.Status; } if (OutputBufferSize != NULL) { *OutputBufferSize = IoStatus.Information; } if (Status == STATUS_VERIFY_REQUIRED) { PDEVICE_OBJECT DeviceToVerify; DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); IoSetDeviceToVerify(PsGetCurrentThread(), NULL); if (DeviceToVerify) { Status = IoVerifyVolume(DeviceToVerify, FALSE); DPRINT("IoVerifyVolume() returned (Status %lx)\n", Status); } if (NT_SUCCESS(Status) && !LastChance) { DPRINT1("Volume verify succeeded; trying request again\n"); LastChance = TRUE; goto again; } else if (NT_SUCCESS(Status)) { DPRINT1("Failed to read after successful verify, aborting\n"); Status = STATUS_DEVICE_NOT_READY; } else { DPRINT1("IoVerifyVolume() failed (Status %lx)\n", Status); } } DPRINT("Returning Status %x\n", Status); return Status; } /* EOF */