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 /* FUNCTIONS ****************************************************************/
38 * FUNCTION: Reads data from a file
42 NtfsReadFile(PDEVICE_EXTENSION DeviceExt
,
43 PFILE_OBJECT FileObject
,
50 NTSTATUS Status
= STATUS_SUCCESS
;
52 PFILE_RECORD_HEADER FileRecord
;
53 PNTFS_ATTR_CONTEXT DataContext
;
58 BOOLEAN AllocatedBuffer
= FALSE
;
59 PCHAR ReadBuffer
= (PCHAR
)Buffer
;
61 DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt
, FileObject
, Buffer
, Length
, ReadOffset
, IrpFlags
, LengthRead
);
67 DPRINT1("Null read!\n");
68 return STATUS_SUCCESS
;
71 Fcb
= (PNTFS_FCB
)FileObject
->FsContext
;
73 if (ReadOffset
>= Fcb
->Entry
.AllocatedSize
)
75 DPRINT1("Reading beyond file end!\n");
76 return STATUS_END_OF_FILE
;
80 if (ReadOffset
+ Length
> Fcb
->Entry
.AllocatedSize
)
81 ToRead
= Fcb
->Entry
.AllocatedSize
- ReadOffset
;
83 RealReadOffset
= ReadOffset
;
86 if ((ReadOffset
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0 || (ToRead
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0)
88 RealReadOffset
= ROUND_DOWN(ReadOffset
, DeviceExt
->NtfsInfo
.BytesPerSector
);
89 RealLength
= ROUND_UP(ToRead
, DeviceExt
->NtfsInfo
.BytesPerSector
);
91 ReadBuffer
= ExAllocatePoolWithTag(NonPagedPool
, RealLength
+ DeviceExt
->NtfsInfo
.BytesPerSector
, TAG_NTFS
);
92 if (ReadBuffer
== NULL
)
94 DPRINT1("Not enough memory!\n");
95 return STATUS_INSUFFICIENT_RESOURCES
;
97 AllocatedBuffer
= TRUE
;
100 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
101 if (FileRecord
== NULL
)
103 DPRINT1("Not enough memory!\n");
106 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
108 return STATUS_INSUFFICIENT_RESOURCES
;
111 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
112 if (!NT_SUCCESS(Status
))
114 DPRINT1("Can't find record!\n");
115 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
118 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
123 Status
= FindAttribute(DeviceExt
, FileRecord
, AttributeData
, L
"", 0, &DataContext
);
124 if (!NT_SUCCESS(Status
))
126 DPRINT1("No data associated with file!\n");
127 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
130 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
135 DPRINT1("Effective read: %lu at %lu\n", RealLength
, RealReadOffset
);
136 RealLengthRead
= ReadAttribute(DeviceExt
, DataContext
, RealReadOffset
, (PCHAR
)ReadBuffer
, RealLength
);
137 if (RealLengthRead
!= RealLength
)
139 DPRINT1("Read failure!\n");
140 ReleaseAttributeContext(DataContext
);
141 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
144 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
149 ReleaseAttributeContext(DataContext
);
150 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
152 *LengthRead
= ToRead
;
154 DPRINT1("%lu got read\n", *LengthRead
);
158 RtlCopyMemory(Buffer
, ReadBuffer
+ (ReadOffset
- RealReadOffset
), ToRead
);
161 if (ToRead
!= Length
)
163 RtlZeroMemory(Buffer
+ ToRead
, Length
- ToRead
);
168 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
171 return STATUS_SUCCESS
;
176 NtfsRead(PNTFS_IRP_CONTEXT IrpContext
)
178 PDEVICE_EXTENSION DeviceExt
;
179 PIO_STACK_LOCATION Stack
;
180 PFILE_OBJECT FileObject
;
183 LARGE_INTEGER ReadOffset
;
184 ULONG ReturnedReadLength
= 0;
185 NTSTATUS Status
= STATUS_SUCCESS
;
187 PDEVICE_OBJECT DeviceObject
;
189 DPRINT("NtfsRead(IrpContext %p)\n", IrpContext
);
191 DeviceObject
= IrpContext
->DeviceObject
;
192 Irp
= IrpContext
->Irp
;
193 Stack
= IrpContext
->Stack
;
194 FileObject
= IrpContext
->FileObject
;
196 DeviceExt
= DeviceObject
->DeviceExtension
;
197 ReadLength
= Stack
->Parameters
.Read
.Length
;
198 ReadOffset
= Stack
->Parameters
.Read
.ByteOffset
;
199 Buffer
= NtfsGetUserBuffer(Irp
, Irp
->Flags
& IRP_PAGING_IO
);
201 Status
= NtfsReadFile(DeviceExt
,
205 ReadOffset
.u
.LowPart
,
207 &ReturnedReadLength
);
208 if (NT_SUCCESS(Status
))
210 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
212 FileObject
->CurrentByteOffset
.QuadPart
=
213 ReadOffset
.QuadPart
+ ReturnedReadLength
;
216 Irp
->IoStatus
.Information
= ReturnedReadLength
;
220 Irp
->IoStatus
.Information
= 0;
228 NtfsWrite(PNTFS_IRP_CONTEXT IrpContext
)
230 DPRINT("NtfsWrite(IrpContext %p)\n",IrpContext
);
232 IrpContext
->Irp
->IoStatus
.Information
= 0;
233 return STATUS_NOT_SUPPORTED
;