2518ea0750b024ff1eaff7ec6c224ea11b8445af
[reactos.git] / reactos / drivers / filesystems / ntfs / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/rw.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMER: Art Yerkes
24 * UPDATE HISTORY:
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include <ntddk.h>
30 #include "ntfs.h"
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* GLOBALS *******************************************************************/
36
37 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
38 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
39
40 /* FUNCTIONS ****************************************************************/
41
42 /*
43 * FUNCTION: Reads data from a file
44 */
45 static
46 NTSTATUS
47 NtfsReadFile(PDEVICE_EXTENSION DeviceExt,
48 PFILE_OBJECT FileObject,
49 PUCHAR Buffer,
50 ULONG Length,
51 ULONG ReadOffset,
52 ULONG IrpFlags,
53 PULONG LengthRead)
54 {
55 NTSTATUS Status = STATUS_SUCCESS;
56 PNTFS_FCB Fcb;
57 PFILE_RECORD_HEADER FileRecord;
58 PNTFS_ATTR_CONTEXT DataContext;
59 ULONG RealLength;
60 ULONG RealReadOffset;
61 ULONG RealLengthRead;
62 ULONG ToRead;
63 BOOLEAN AllocatedBuffer = FALSE;
64 PCHAR ReadBuffer = (PCHAR)Buffer;
65
66 DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt, FileObject, Buffer, Length, ReadOffset, IrpFlags, LengthRead);
67
68 *LengthRead = 0;
69
70 if (Length == 0)
71 {
72 DPRINT1("Null read!\n");
73 return STATUS_SUCCESS;
74 }
75
76 Fcb = (PNTFS_FCB)FileObject->FsContext;
77
78 if (ReadOffset >= Fcb->Entry.AllocatedSize)
79 {
80 DPRINT1("Reading beyond file end!\n");
81 return STATUS_END_OF_FILE;
82 }
83
84 ToRead = Length;
85 if (ReadOffset + Length > Fcb->Entry.AllocatedSize)
86 ToRead = Fcb->Entry.AllocatedSize - ReadOffset;
87
88 RealReadOffset = ReadOffset;
89 RealLength = ToRead;
90
91 if ((ReadOffset % DeviceExt->NtfsInfo.BytesPerSector) != 0 || (ToRead % DeviceExt->NtfsInfo.BytesPerSector) != 0)
92 {
93 RealReadOffset = ROUND_DOWN(ReadOffset, DeviceExt->NtfsInfo.BytesPerSector);
94 RealLength = ROUND_UP(ToRead, DeviceExt->NtfsInfo.BytesPerSector);
95
96 ReadBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength + DeviceExt->NtfsInfo.BytesPerSector, TAG_NTFS);
97 if (ReadBuffer == NULL)
98 {
99 DPRINT1("Not enough memory!\n");
100 return STATUS_INSUFFICIENT_RESOURCES;
101 }
102 AllocatedBuffer = TRUE;
103 }
104
105 FileRecord = ExAllocatePoolWithTag(NonPagedPool, DeviceExt->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
106 if (FileRecord == NULL)
107 {
108 DPRINT1("Not enough memory!\n");
109 return STATUS_INSUFFICIENT_RESOURCES;
110 }
111
112 Status = ReadFileRecord(DeviceExt, Fcb->MFTIndex, FileRecord);
113 if (!NT_SUCCESS(Status))
114 {
115 DPRINT1("Can't find record!\n");
116 ExFreePoolWithTag(FileRecord, TAG_NTFS);
117 return Status;
118 }
119
120 Status = FindAttribute(DeviceExt, FileRecord, AttributeData, L"", 0, &DataContext);
121 if (!NT_SUCCESS(Status))
122 {
123 DPRINT1("No data associated with file!\n");
124 ExFreePoolWithTag(FileRecord, TAG_NTFS);
125 return Status;
126 }
127
128 DPRINT1("Effective read: %lu at %lu\n", RealLength, RealReadOffset);
129 RealLengthRead = ReadAttribute(DeviceExt, DataContext, RealReadOffset, (PCHAR)ReadBuffer, RealLength);
130 if (RealLengthRead != RealLength)
131 {
132 DPRINT1("Read failure!\n");
133 ReleaseAttributeContext(DataContext);
134 ExFreePoolWithTag(FileRecord, TAG_NTFS);
135 if (AllocatedBuffer)
136 {
137 ExFreePoolWithTag(ReadBuffer, TAG_NTFS);
138 }
139 return Status;
140 }
141
142 ReleaseAttributeContext(DataContext);
143 ExFreePoolWithTag(FileRecord, TAG_NTFS);
144
145 *LengthRead = ToRead;
146
147 DPRINT1("%lu got read\n", *LengthRead);
148
149 if (AllocatedBuffer)
150 {
151 RtlCopyMemory(Buffer, ReadBuffer + (ReadOffset - RealReadOffset), ToRead);
152 }
153
154 if (ToRead != Length)
155 {
156 RtlZeroMemory(Buffer + ToRead, Length - ToRead);
157 }
158
159 if (AllocatedBuffer)
160 {
161 ExFreePoolWithTag(ReadBuffer, TAG_NTFS);
162 }
163
164 return STATUS_SUCCESS;
165 }
166
167
168 NTSTATUS
169 NTAPI
170 NtfsFsdRead(PDEVICE_OBJECT DeviceObject,
171 PIRP Irp)
172 {
173 PDEVICE_EXTENSION DeviceExt;
174 PIO_STACK_LOCATION Stack;
175 PFILE_OBJECT FileObject;
176 PVOID Buffer;
177 ULONG ReadLength;
178 LARGE_INTEGER ReadOffset;
179 ULONG ReturnedReadLength = 0;
180 NTSTATUS Status = STATUS_SUCCESS;
181
182 DPRINT("NtfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
183
184 DeviceExt = DeviceObject->DeviceExtension;
185 Stack = IoGetCurrentIrpStackLocation(Irp);
186 FileObject = Stack->FileObject;
187
188 ReadLength = Stack->Parameters.Read.Length;
189 ReadOffset = Stack->Parameters.Read.ByteOffset;
190 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
191
192 Status = NtfsReadFile(DeviceExt,
193 FileObject,
194 Buffer,
195 ReadLength,
196 ReadOffset.u.LowPart,
197 Irp->Flags,
198 &ReturnedReadLength);
199 if (NT_SUCCESS(Status))
200 {
201 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
202 {
203 FileObject->CurrentByteOffset.QuadPart =
204 ReadOffset.QuadPart + ReturnedReadLength;
205 }
206
207 Irp->IoStatus.Information = ReturnedReadLength;
208 }
209 else
210 {
211 Irp->IoStatus.Information = 0;
212 }
213
214 Irp->IoStatus.Status = Status;
215 IoCompleteRequest(Irp,IO_NO_INCREMENT);
216
217 return Status;
218 }
219
220
221 NTSTATUS
222 NTAPI
223 NtfsFsdWrite(PDEVICE_OBJECT DeviceObject,
224 PIRP Irp)
225 {
226 DPRINT("NtfwWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
227
228 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
229 Irp->IoStatus.Information = 0;
230 return STATUS_NOT_SUPPORTED;
231 }
232
233 /* EOF */