[CDFS]
[reactos.git] / reactos / drivers / filesystems / cdfs / rw.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/fs/cdfs/rw.c
23 * PURPOSE: CDROM (ISO 9660) filesystem driver
24 * PROGRAMMER: Art Yerkes
25 * Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include "cdfs.h"
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* FUNCTIONS ****************************************************************/
36
37 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
38 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
39
40
41 /* FUNCTIONS ****************************************************************/
42
43 static NTSTATUS
44 CdfsReadFile(PDEVICE_EXTENSION DeviceExt,
45 PFILE_OBJECT FileObject,
46 PUCHAR Buffer,
47 ULONG Length,
48 ULONG ReadOffset,
49 ULONG IrpFlags,
50 PULONG LengthRead)
51 /*
52 * FUNCTION: Reads data from a file
53 */
54 {
55 NTSTATUS Status = STATUS_SUCCESS;
56 PFCB Fcb;
57 ULONG ToRead = Length;
58
59 DPRINT("CdfsReadFile(ReadOffset %lu Length %lu)\n", ReadOffset, Length);
60
61 *LengthRead = 0;
62
63 if (Length == 0)
64 return(STATUS_SUCCESS);
65
66 Fcb = (PFCB)FileObject->FsContext;
67
68 if (ReadOffset >= Fcb->Entry.DataLengthL)
69 return(STATUS_END_OF_FILE);
70
71 if (ReadOffset + Length > Fcb->Entry.DataLengthL)
72 ToRead = Fcb->Entry.DataLengthL - ReadOffset;
73
74 DPRINT("Reading %u bytes at %u\n", Length, ReadOffset);
75
76 if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO)))
77 {
78 LARGE_INTEGER FileOffset;
79 IO_STATUS_BLOCK IoStatus;
80 CC_FILE_SIZES FileSizes;
81
82 DPRINT("Using cache\n");
83
84 if (FileObject->PrivateCacheMap == NULL)
85 {
86 FileSizes.AllocationSize = Fcb->RFCB.AllocationSize;
87 FileSizes.FileSize = Fcb->RFCB.FileSize;
88 FileSizes.ValidDataLength = Fcb->RFCB.ValidDataLength;
89
90 DPRINT("Attach FCB to File: Size %08x%08x\n",
91 Fcb->RFCB.ValidDataLength.HighPart,
92 Fcb->RFCB.ValidDataLength.LowPart);
93
94 _SEH2_TRY
95 {
96 CcInitializeCacheMap(FileObject,
97 &FileSizes,
98 FALSE,
99 &(CdfsGlobalData->CacheMgrCallbacks),
100 Fcb);
101 }
102 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
103 {
104 return _SEH2_GetExceptionCode();
105 }
106 _SEH2_END;
107 }
108
109 FileOffset.QuadPart = (LONGLONG)ReadOffset;
110 _SEH2_TRY
111 {
112 CcCopyRead(FileObject,
113 &FileOffset,
114 ToRead,
115 TRUE,
116 Buffer,
117 &IoStatus);
118 }
119 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
120 {
121 IoStatus.Information = 0;
122 IoStatus.Status = _SEH2_GetExceptionCode();
123 }
124 _SEH2_END;
125 *LengthRead = IoStatus.Information;
126
127 Status = IoStatus.Status;
128 }
129 else
130 {
131 ULONG ActualReadOffset = ROUND_DOWN(ReadOffset, BLOCKSIZE);
132 ULONG nBlocks = (ROUND_UP(ReadOffset + ToRead, BLOCKSIZE) - ActualReadOffset) / BLOCKSIZE;
133 PUCHAR PageBuf;
134 BOOLEAN bFreeBuffer = FALSE;
135 if ((ReadOffset % BLOCKSIZE) != 0 || (ToRead % BLOCKSIZE) != 0)
136 {
137 PageBuf = ExAllocatePoolWithTag(NonPagedPool,
138 nBlocks * BLOCKSIZE,
139 CDFS_TAG);
140 if (!PageBuf)
141 {
142 return STATUS_NO_MEMORY;
143 }
144 bFreeBuffer = TRUE;
145 }
146 else
147 {
148 PageBuf = Buffer;
149 }
150 Status = CdfsReadSectors(DeviceExt->StorageDevice,
151 Fcb->Entry.ExtentLocationL + (ActualReadOffset / BLOCKSIZE),
152 nBlocks,
153 (PVOID)PageBuf,
154 FALSE);
155
156 if(NT_SUCCESS(Status))
157 {
158 *LengthRead = ToRead;
159 if(bFreeBuffer)
160 {
161 /* Copy what we've got */
162 RtlCopyMemory(Buffer, PageBuf + (ReadOffset - ActualReadOffset), ToRead);
163 }
164 /* Zero out the rest */
165 if(ToRead != Length)
166 RtlZeroMemory(Buffer + ToRead, Length - ToRead);
167 }
168
169 if(bFreeBuffer)
170 ExFreePoolWithTag(PageBuf, CDFS_TAG);
171 }
172
173 return Status;
174 }
175
176
177 NTSTATUS NTAPI
178 CdfsRead(
179 PCDFS_IRP_CONTEXT IrpContext)
180 {
181 PIRP Irp;
182 PDEVICE_OBJECT DeviceObject;
183 PDEVICE_EXTENSION DeviceExt;
184 PIO_STACK_LOCATION Stack;
185 PFILE_OBJECT FileObject;
186 PVOID Buffer = NULL;
187 ULONG ReadLength;
188 LARGE_INTEGER ReadOffset;
189 ULONG ReturnedReadLength = 0;
190 NTSTATUS Status = STATUS_SUCCESS;
191
192 DPRINT("CdfsRead(%p)\n", IrpContext);
193
194 ASSERT(IrpContext);
195
196 Irp = IrpContext->Irp;
197 DeviceObject = IrpContext->DeviceObject;
198 Stack = IrpContext->Stack;
199
200 DeviceExt = DeviceObject->DeviceExtension;
201 FileObject = Stack->FileObject;
202
203 ReadLength = Stack->Parameters.Read.Length;
204 ReadOffset = Stack->Parameters.Read.ByteOffset;
205 if (ReadLength) Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
206
207 Status = CdfsReadFile(DeviceExt,
208 FileObject,
209 Buffer,
210 ReadLength,
211 ReadOffset.u.LowPart,
212 Irp->Flags,
213 &ReturnedReadLength);
214 if (NT_SUCCESS(Status))
215 {
216 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
217 {
218 FileObject->CurrentByteOffset.QuadPart =
219 ReadOffset.QuadPart + ReturnedReadLength;
220 }
221 Irp->IoStatus.Information = ReturnedReadLength;
222 }
223 else
224 {
225 Irp->IoStatus.Information = 0;
226 }
227
228 return(Status);
229 }
230
231
232 NTSTATUS NTAPI
233 CdfsWrite(
234 PCDFS_IRP_CONTEXT IrpContext)
235 {
236 PIRP Irp;
237
238 DPRINT("CdfsWrite(%p)\n", IrpContext);
239
240 ASSERT(IrpContext);
241
242 Irp = IrpContext->Irp;
243 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
244 Irp->IoStatus.Information = 0;
245 return(STATUS_NOT_SUPPORTED);
246 }
247
248 /* EOF */