:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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 + Length > Fcb->Entry.DataLengthL)
77     Length = Fcb->Entry.DataLengthL - ReadOffset;
78
79   DPRINT("Reading %d bytes at %d\n", Length, ReadOffset);
80
81   if (Length == 0)
82     return(STATUS_UNSUCCESSFUL);
83
84   if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO)))
85     {
86       LARGE_INTEGER FileOffset;
87       IO_STATUS_BLOCK IoStatus;
88
89       if (FileObject->PrivateCacheMap == NULL)
90       {
91           CcRosInitializeFileCache(FileObject, &Fcb->RFCB.Bcb, PAGE_SIZE);
92       }
93
94       FileOffset.QuadPart = (LONGLONG)ReadOffset;
95       CcCopyRead(FileObject,
96                  &FileOffset,
97                  Length,
98                  TRUE,
99                  Buffer,
100                  &IoStatus);
101       *LengthRead = IoStatus.Information;
102
103       return(IoStatus.Status);
104     }
105
106   if ((ReadOffset % BLOCKSIZE) != 0)
107     {
108       TempLength = min(Length, BLOCKSIZE - (ReadOffset % BLOCKSIZE));
109       TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
110
111       Status = CdfsReadSectors(DeviceExt->StorageDevice,
112                                Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
113                                1,
114                                TempBuffer);
115       if (NT_SUCCESS(Status))
116         {
117           memcpy(Buffer, TempBuffer + (ReadOffset % BLOCKSIZE), TempLength);
118           (*LengthRead) = (*LengthRead) + TempLength;
119           Length = Length - TempLength;
120           Buffer = Buffer + TempLength;
121           ReadOffset = ReadOffset + TempLength;
122         }
123       ExFreePool(TempBuffer);
124     }
125
126   DPRINT("Status %lx\n", Status);
127
128   if ((Length / BLOCKSIZE) != 0 && NT_SUCCESS(Status))
129     {
130       TempLength = ROUND_DOWN(Length, BLOCKSIZE);
131       Status = CdfsReadSectors(DeviceExt->StorageDevice,
132                                Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
133                                TempLength / BLOCKSIZE,
134                                Buffer);
135       if (NT_SUCCESS(Status))
136         {
137           (*LengthRead) = (*LengthRead) + TempLength;
138           Length = Length - TempLength;
139           Buffer = Buffer + TempLength;
140           ReadOffset = ReadOffset + TempLength;
141         }
142     }
143
144   DPRINT("Status %lx\n", Status);
145
146   if (Length > 0 && NT_SUCCESS(Status))
147     {
148       TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
149
150       Status = CdfsReadSectors(DeviceExt->StorageDevice,
151                                Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
152                                1,
153                                TempBuffer);
154       if (NT_SUCCESS(Status))
155         {
156           memcpy(Buffer, TempBuffer, Length);
157           (*LengthRead) = (*LengthRead) + Length;
158         }
159       ExFreePool(TempBuffer);
160     }
161
162   return(Status);
163 }
164
165
166 NTSTATUS STDCALL
167 CdfsRead(PDEVICE_OBJECT DeviceObject,
168          PIRP Irp)
169 {
170   PDEVICE_EXTENSION DeviceExt;
171   PIO_STACK_LOCATION Stack;
172   PFILE_OBJECT FileObject;
173   PVOID Buffer;
174   ULONG ReadLength;
175   LARGE_INTEGER ReadOffset;
176   ULONG ReturnedReadLength = 0;
177   NTSTATUS Status = STATUS_SUCCESS;
178
179   DPRINT("CdfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
180
181   DeviceExt = DeviceObject->DeviceExtension;
182   Stack = IoGetCurrentIrpStackLocation(Irp);
183   FileObject = Stack->FileObject;
184
185   ReadLength = Stack->Parameters.Read.Length;
186   ReadOffset = Stack->Parameters.Read.ByteOffset;
187   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
188
189   Status = CdfsReadFile(DeviceExt,
190                         FileObject,
191                         Buffer,
192                         ReadLength,
193                         ReadOffset.u.LowPart,
194                         Irp->Flags,
195                         &ReturnedReadLength);
196
197 ByeBye:
198   if (NT_SUCCESS(Status))
199     {
200       if (FileObject->Flags & FO_SYNCHRONOUS_IO)
201         {
202           FileObject->CurrentByteOffset.QuadPart = 
203             ReadOffset.QuadPart + ReturnedReadLength;
204         }
205       Irp->IoStatus.Information = ReturnedReadLength;
206     }
207   else
208     {
209       Irp->IoStatus.Information = 0;
210     }
211
212   Irp->IoStatus.Status = Status;
213   IoCompleteRequest(Irp,IO_NO_INCREMENT);
214
215   return(Status);
216 }
217
218
219 NTSTATUS STDCALL
220 CdfsWrite(PDEVICE_OBJECT DeviceObject,
221           PIRP Irp)
222 {
223   DPRINT("CdfsWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
224
225   Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
226   Irp->IoStatus.Information = 0;
227   return(STATUS_NOT_SUPPORTED);
228 }
229
230 /* EOF */