Fixed several cache-related bugs.
[reactos.git] / reactos / 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: rw.c,v 1.4 2002/05/14 23:16:23 ekohl Exp $
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 FileOffset.QuadPart = (LONGLONG)ReadOffset;
90 CcCopyRead(FileObject,
91 &FileOffset,
92 Length,
93 TRUE,
94 Buffer,
95 &IoStatus);
96 *LengthRead = IoStatus.Information;
97
98 return(IoStatus.Status);
99 }
100
101 if ((ReadOffset % BLOCKSIZE) != 0)
102 {
103 TempLength = min(Length, BLOCKSIZE - (ReadOffset % BLOCKSIZE));
104 TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
105
106 Status = CdfsReadSectors(DeviceExt->StorageDevice,
107 Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
108 1,
109 TempBuffer);
110 if (NT_SUCCESS(Status))
111 {
112 memcpy(Buffer, TempBuffer + (ReadOffset % BLOCKSIZE), TempLength);
113 (*LengthRead) = (*LengthRead) + TempLength;
114 Length = Length - TempLength;
115 Buffer = Buffer + TempLength;
116 ReadOffset = ReadOffset + TempLength;
117 }
118 ExFreePool(TempBuffer);
119 }
120
121 DPRINT("Status %lx\n", Status);
122
123 if ((Length / BLOCKSIZE) != 0 && NT_SUCCESS(Status))
124 {
125 TempLength = ROUND_DOWN(Length, BLOCKSIZE);
126 Status = CdfsReadSectors(DeviceExt->StorageDevice,
127 Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
128 Length / BLOCKSIZE,
129 Buffer);
130 if (NT_SUCCESS(Status))
131 {
132 (*LengthRead) = (*LengthRead) + TempLength;
133 Length = Length - TempLength;
134 Buffer = Buffer + TempLength;
135 ReadOffset = ReadOffset + TempLength;
136 }
137 }
138
139 DPRINT("Status %lx\n", Status);
140
141 if (Length > 0 && NT_SUCCESS(Status))
142 {
143 TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
144
145 Status = CdfsReadSectors(DeviceExt->StorageDevice,
146 Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE),
147 1,
148 TempBuffer);
149 if (NT_SUCCESS(Status))
150 {
151 memcpy(Buffer, TempBuffer, Length);
152 (*LengthRead) = (*LengthRead) + Length;
153 }
154 ExFreePool(TempBuffer);
155 }
156
157 return(Status);
158 }
159
160
161 NTSTATUS STDCALL
162 CdfsRead(PDEVICE_OBJECT DeviceObject,
163 PIRP Irp)
164 {
165 PDEVICE_EXTENSION DeviceExt;
166 PIO_STACK_LOCATION Stack;
167 PFILE_OBJECT FileObject;
168 PVOID Buffer;
169 ULONG ReadLength;
170 LARGE_INTEGER ReadOffset;
171 ULONG ReturnedReadLength = 0;
172 NTSTATUS Status = STATUS_SUCCESS;
173
174 DPRINT("CdfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
175
176 DeviceExt = DeviceObject->DeviceExtension;
177 Stack = IoGetCurrentIrpStackLocation(Irp);
178 FileObject = Stack->FileObject;
179
180 ReadLength = Stack->Parameters.Read.Length;
181 ReadOffset = Stack->Parameters.Read.ByteOffset;
182 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
183
184 Status = CdfsReadFile(DeviceExt,
185 FileObject,
186 Buffer,
187 ReadLength,
188 ReadOffset.u.LowPart,
189 Irp->Flags,
190 &ReturnedReadLength);
191
192 ByeBye:
193 if (NT_SUCCESS(Status))
194 {
195 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
196 {
197 FileObject->CurrentByteOffset.QuadPart =
198 ReadOffset.QuadPart + ReturnedReadLength;
199 }
200 Irp->IoStatus.Information = ReturnedReadLength;
201 }
202 else
203 {
204 Irp->IoStatus.Information = 0;
205 }
206
207 Irp->IoStatus.Status = Status;
208 IoCompleteRequest(Irp,IO_NO_INCREMENT);
209
210 return(Status);
211 }
212
213
214 NTSTATUS STDCALL
215 CdfsWrite(PDEVICE_OBJECT DeviceObject,
216 PIRP Irp)
217 {
218 DPRINT("CdfsWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
219
220 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
221 Irp->IoStatus.Information = 0;
222 return(STATUS_NOT_SUPPORTED);
223 }
224
225 /* EOF */