3 * Copyright (C) 2002, 2014 ReactOS Team
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.
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.
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.
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 * PROGRAMMERS: Art Yerkes
24 * Pierre Schweitzer (pierre@reactos.org)
27 /* INCLUDES *****************************************************************/
35 /* GLOBALS *******************************************************************/
37 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
38 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
40 /* FUNCTIONS ****************************************************************/
43 * FUNCTION: Reads data from a file
47 NtfsReadFile(PDEVICE_EXTENSION DeviceExt
,
48 PFILE_OBJECT FileObject
,
55 NTSTATUS Status
= STATUS_SUCCESS
;
57 PFILE_RECORD_HEADER FileRecord
;
58 PNTFS_ATTR_CONTEXT DataContext
;
63 BOOLEAN AllocatedBuffer
= FALSE
;
64 PCHAR ReadBuffer
= (PCHAR
)Buffer
;
66 DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt
, FileObject
, Buffer
, Length
, ReadOffset
, IrpFlags
, LengthRead
);
72 DPRINT1("Null read!\n");
73 return STATUS_SUCCESS
;
76 Fcb
= (PNTFS_FCB
)FileObject
->FsContext
;
78 if (ReadOffset
>= Fcb
->Entry
.AllocatedSize
)
80 DPRINT1("Reading beyond file end!\n");
81 return STATUS_END_OF_FILE
;
85 if (ReadOffset
+ Length
> Fcb
->Entry
.AllocatedSize
)
86 ToRead
= Fcb
->Entry
.AllocatedSize
- ReadOffset
;
88 RealReadOffset
= ReadOffset
;
91 if ((ReadOffset
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0 || (ToRead
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0)
93 RealReadOffset
= ROUND_DOWN(ReadOffset
, DeviceExt
->NtfsInfo
.BytesPerSector
);
94 RealLength
= ROUND_UP(ToRead
, DeviceExt
->NtfsInfo
.BytesPerSector
);
96 ReadBuffer
= ExAllocatePoolWithTag(NonPagedPool
, RealLength
+ DeviceExt
->NtfsInfo
.BytesPerSector
, TAG_NTFS
);
97 if (ReadBuffer
== NULL
)
99 DPRINT1("Not enough memory!\n");
100 return STATUS_INSUFFICIENT_RESOURCES
;
102 AllocatedBuffer
= TRUE
;
105 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
106 if (FileRecord
== NULL
)
108 DPRINT1("Not enough memory!\n");
109 return STATUS_INSUFFICIENT_RESOURCES
;
112 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
113 if (!NT_SUCCESS(Status
))
115 DPRINT1("Can't find record!\n");
116 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
120 Status
= FindAttribute(DeviceExt
, FileRecord
, AttributeData
, L
"", 0, &DataContext
);
121 if (!NT_SUCCESS(Status
))
123 DPRINT1("No data associated with file!\n");
124 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
128 DPRINT1("Effective read: %lu at %lu\n", RealLength
, RealReadOffset
);
129 RealLengthRead
= ReadAttribute(DeviceExt
, DataContext
, RealReadOffset
, (PCHAR
)ReadBuffer
, RealLength
);
130 if (RealLengthRead
!= RealLength
)
132 DPRINT1("Read failure!\n");
133 ReleaseAttributeContext(DataContext
);
134 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
137 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
142 ReleaseAttributeContext(DataContext
);
143 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
145 *LengthRead
= ToRead
;
147 DPRINT1("%lu got read\n", *LengthRead
);
151 RtlCopyMemory(Buffer
, ReadBuffer
+ (ReadOffset
- RealReadOffset
), ToRead
);
154 if (ToRead
!= Length
)
156 RtlZeroMemory(Buffer
+ ToRead
, Length
- ToRead
);
161 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
164 return STATUS_SUCCESS
;
170 NtfsFsdRead(PDEVICE_OBJECT DeviceObject
,
173 PDEVICE_EXTENSION DeviceExt
;
174 PIO_STACK_LOCATION Stack
;
175 PFILE_OBJECT FileObject
;
178 LARGE_INTEGER ReadOffset
;
179 ULONG ReturnedReadLength
= 0;
180 NTSTATUS Status
= STATUS_SUCCESS
;
182 DPRINT("NtfsRead(DeviceObject %x, Irp %x)\n",DeviceObject
,Irp
);
184 DeviceExt
= DeviceObject
->DeviceExtension
;
185 Stack
= IoGetCurrentIrpStackLocation(Irp
);
186 FileObject
= Stack
->FileObject
;
188 ReadLength
= Stack
->Parameters
.Read
.Length
;
189 ReadOffset
= Stack
->Parameters
.Read
.ByteOffset
;
190 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
192 Status
= NtfsReadFile(DeviceExt
,
196 ReadOffset
.u
.LowPart
,
198 &ReturnedReadLength
);
199 if (NT_SUCCESS(Status
))
201 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
203 FileObject
->CurrentByteOffset
.QuadPart
=
204 ReadOffset
.QuadPart
+ ReturnedReadLength
;
207 Irp
->IoStatus
.Information
= ReturnedReadLength
;
211 Irp
->IoStatus
.Information
= 0;
214 Irp
->IoStatus
.Status
= Status
;
215 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);
223 NtfsFsdWrite(PDEVICE_OBJECT DeviceObject
,
226 DPRINT("NtfwWrite(DeviceObject %x Irp %x)\n",DeviceObject
,Irp
);
228 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
229 Irp
->IoStatus
.Information
= 0;
230 return STATUS_NOT_SUPPORTED
;