82ae382ae5fafccb8f187f2a80ddee13646fb01e
[reactos.git] / drivers / fs / cdfs / rw.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2002 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * COPYRIGHT:        See COPYING in the top level directory
22  * PROJECT:          ReactOS kernel
23  * FILE:             services/fs/cdfs/rw.c
24  * PURPOSE:          CDROM (ISO 9660) filesystem driver
25  * PROGRAMMER:       Art Yerkes
26  * UPDATE HISTORY: 
27  */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ddk/ntddk.h>
32 #include <ntos/minmax.h>
33
34 #define NDEBUG
35 #include <debug.h>
36
37 #include "cdfs.h"
38
39
40 /* GLOBALS *******************************************************************/
41
42 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
43 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
44
45
46 /* FUNCTIONS ****************************************************************/
47
48 static NTSTATUS
49 CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
50              PFILE_OBJECT FileObject,
51              PUCHAR Buffer,
52              ULONG Length,
53              ULONG ReadOffset,
54              ULONG IrpFlags,
55              PULONG LengthRead)
56 /*
57  * FUNCTION: Reads data from a file
58  */
59 {
60   NTSTATUS Status = STATUS_SUCCESS;
61   PUCHAR TempBuffer;
62   ULONG TempLength;
63   PCCB Ccb;
64   PFCB Fcb;
65
66   DPRINT("CdfsReadFile(ReadOffset %lu  Length %lu)\n", ReadOffset, Length);
67
68   *LengthRead = 0;
69
70   if (Length == 0)
71     return(STATUS_SUCCESS);
72
73   Ccb = (PCCB)FileObject->FsContext2;
74   Fcb = Ccb->Fcb;
75
76   if (ReadOffset >= Fcb->Entry.DataLengthL)
77     return(STATUS_END_OF_FILE);
78
79   DPRINT("Reading %d bytes at %d\n", Length, ReadOffset);
80
81   if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO)))
82     {
83       LARGE_INTEGER FileOffset;
84       IO_STATUS_BLOCK IoStatus;
85
86       if (ReadOffset + Length > Fcb->Entry.DataLengthL)
87          Length = Fcb->Entry.DataLengthL - ReadOffset;
88       if (FileObject->PrivateCacheMap == NULL)
89       {
90           CcRosInitializeFileCache(FileObject, &Fcb->RFCB.Bcb, PAGE_SIZE);
91       }
92
93       FileOffset.QuadPart = (LONGLONG)ReadOffset;
94       CcCopyRead(FileObject,
95                  &FileOffset,
96                  Length,
97                  TRUE,
98                  Buffer,
99                  &IoStatus);
100       *LengthRead = IoStatus.Information;
101
102       return(IoStatus.Status);
103     }
104
105   if ((ReadOffset % BLOCKSIZE) != 0 || (Length % BLOCKSIZE) != 0)
106     {
107       return STATUS_INVALID_PARAMETER;
108     }
109   if (ReadOffset + Length > ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE))
110     Length = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE) - ReadOffset;
111
112   Status = CdfsReadSectors(DeviceExt->StorageDevice,
113                            Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
114                            Length / BLOCKSIZE,
115                            Buffer);
116   if (NT_SUCCESS(Status))
117     {
118       *LengthRead = Length;
119       if (Length + ReadOffset > Fcb->Entry.DataLengthL)
120       {
121         memset(Buffer + Fcb->Entry.DataLengthL - ReadOffset, 
122                0, Length + ReadOffset - Fcb->Entry.DataLengthL);
123       }
124     }
125
126   return(Status);
127 }
128
129
130 NTSTATUS STDCALL
131 CdfsRead(PDEVICE_OBJECT DeviceObject,
132          PIRP Irp)
133 {
134   PDEVICE_EXTENSION DeviceExt;
135   PIO_STACK_LOCATION Stack;
136   PFILE_OBJECT FileObject;
137   PVOID Buffer;
138   ULONG ReadLength;
139   LARGE_INTEGER ReadOffset;
140   ULONG ReturnedReadLength = 0;
141   NTSTATUS Status = STATUS_SUCCESS;
142
143   DPRINT("CdfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
144
145   DeviceExt = DeviceObject->DeviceExtension;
146   Stack = IoGetCurrentIrpStackLocation(Irp);
147   FileObject = Stack->FileObject;
148
149   ReadLength = Stack->Parameters.Read.Length;
150   ReadOffset = Stack->Parameters.Read.ByteOffset;
151   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
152
153   Status = CdfsReadFile(DeviceExt,
154                         FileObject,
155                         Buffer,
156                         ReadLength,
157                         ReadOffset.u.LowPart,
158                         Irp->Flags,
159                         &ReturnedReadLength);
160
161 ByeBye:
162   if (NT_SUCCESS(Status))
163     {
164       if (FileObject->Flags & FO_SYNCHRONOUS_IO)
165         {
166           FileObject->CurrentByteOffset.QuadPart = 
167             ReadOffset.QuadPart + ReturnedReadLength;
168         }
169       Irp->IoStatus.Information = ReturnedReadLength;
170     }
171   else
172     {
173       Irp->IoStatus.Information = 0;
174     }
175
176   Irp->IoStatus.Status = Status;
177   IoCompleteRequest(Irp,IO_NO_INCREMENT);
178
179   return(Status);
180 }
181
182
183 NTSTATUS STDCALL
184 CdfsWrite(PDEVICE_OBJECT DeviceObject,
185           PIRP Irp)
186 {
187   DPRINT("CdfsWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
188
189   Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
190   Irp->IoStatus.Information = 0;
191   return(STATUS_NOT_SUPPORTED);
192 }
193
194 /* EOF */