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
;
62 DPRINT1("NtfsReadFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt
, FileObject
, Buffer
, Length
, ReadOffset
, IrpFlags
, LengthRead
);
68 DPRINT1("Null read!\n");
69 return STATUS_SUCCESS
;
72 Fcb
= (PNTFS_FCB
)FileObject
->FsContext
;
74 if (NtfsFCBIsCompressed(Fcb
))
76 DPRINT1("Compressed file!\n");
78 return STATUS_NOT_IMPLEMENTED
;
81 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
82 if (FileRecord
== NULL
)
84 DPRINT1("Not enough memory!\n");
85 return STATUS_INSUFFICIENT_RESOURCES
;
88 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
89 if (!NT_SUCCESS(Status
))
91 DPRINT1("Can't find record!\n");
92 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
97 Status
= FindAttribute(DeviceExt
, FileRecord
, AttributeData
, Fcb
->Stream
, wcslen(Fcb
->Stream
), &DataContext
);
98 if (!NT_SUCCESS(Status
))
100 NTSTATUS BrowseStatus
;
101 FIND_ATTR_CONTXT Context
;
102 PNTFS_ATTR_RECORD Attribute
;
104 DPRINT1("No '%S' data stream associated with file!\n", Fcb
->Stream
);
106 BrowseStatus
= FindFirstAttribute(&Context
, DeviceExt
, FileRecord
, FALSE
, &Attribute
);
107 while (NT_SUCCESS(BrowseStatus
))
109 if (Attribute
->Type
== AttributeData
)
113 Name
.Length
= Attribute
->NameLength
* sizeof(WCHAR
);
114 Name
.MaximumLength
= Name
.Length
;
115 Name
.Buffer
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
);
116 DPRINT1("Data stream: '%wZ' available\n", &Name
);
119 BrowseStatus
= FindNextAttribute(&Context
, &Attribute
);
121 FindCloseAttribute(&Context
);
123 ReleaseAttributeContext(DataContext
);
124 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
128 StreamSize
= AttributeDataLength(&DataContext
->Record
);
129 if (ReadOffset
>= StreamSize
)
131 DPRINT1("Reading beyond stream end!\n");
132 ReleaseAttributeContext(DataContext
);
133 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
134 return STATUS_END_OF_FILE
;
138 if (ReadOffset
+ Length
> StreamSize
)
139 ToRead
= StreamSize
- ReadOffset
;
141 RealReadOffset
= ReadOffset
;
144 if ((ReadOffset
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0 || (ToRead
% DeviceExt
->NtfsInfo
.BytesPerSector
) != 0)
146 RealReadOffset
= ROUND_DOWN(ReadOffset
, DeviceExt
->NtfsInfo
.BytesPerSector
);
147 RealLength
= ROUND_UP(ToRead
, DeviceExt
->NtfsInfo
.BytesPerSector
);
148 /* do we need to extend RealLength by one sector? */
149 if (RealLength
+ RealReadOffset
< ReadOffset
+ Length
)
150 RealLength
+= DeviceExt
->NtfsInfo
.BytesPerSector
;
153 ReadBuffer
= ExAllocatePoolWithTag(NonPagedPool
, RealLength
+ (DeviceExt
->NtfsInfo
.BytesPerSector
* 2), TAG_NTFS
);
154 if (ReadBuffer
== NULL
)
156 DPRINT1("Not enough memory!\n");
157 ReleaseAttributeContext(DataContext
);
158 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
159 return STATUS_INSUFFICIENT_RESOURCES
;
161 AllocatedBuffer
= TRUE
;
164 DPRINT1("Effective read: %lu at %lu for stream '%S'\n", RealLength
, RealReadOffset
, Fcb
->Stream
);
165 RealLengthRead
= ReadAttribute(DeviceExt
, DataContext
, RealReadOffset
, (PCHAR
)ReadBuffer
, RealLength
);
166 if (RealLengthRead
== 0)
168 DPRINT1("Read failure!\n");
169 ReleaseAttributeContext(DataContext
);
170 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
173 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
178 ReleaseAttributeContext(DataContext
);
179 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
181 *LengthRead
= ToRead
;
183 DPRINT1("%lu got read\n", *LengthRead
);
187 RtlCopyMemory(Buffer
, ReadBuffer
+ (ReadOffset
- RealReadOffset
), ToRead
);
190 if (ToRead
!= Length
)
192 RtlZeroMemory(Buffer
+ ToRead
, Length
- ToRead
);
197 ExFreePoolWithTag(ReadBuffer
, TAG_NTFS
);
200 return STATUS_SUCCESS
;
205 NtfsRead(PNTFS_IRP_CONTEXT IrpContext
)
207 PDEVICE_EXTENSION DeviceExt
;
208 PIO_STACK_LOCATION Stack
;
209 PFILE_OBJECT FileObject
;
212 LARGE_INTEGER ReadOffset
;
213 ULONG ReturnedReadLength
= 0;
214 NTSTATUS Status
= STATUS_SUCCESS
;
216 PDEVICE_OBJECT DeviceObject
;
218 DPRINT("NtfsRead(IrpContext %p)\n", IrpContext
);
220 DeviceObject
= IrpContext
->DeviceObject
;
221 Irp
= IrpContext
->Irp
;
222 Stack
= IrpContext
->Stack
;
223 FileObject
= IrpContext
->FileObject
;
225 DeviceExt
= DeviceObject
->DeviceExtension
;
226 ReadLength
= Stack
->Parameters
.Read
.Length
;
227 ReadOffset
= Stack
->Parameters
.Read
.ByteOffset
;
228 Buffer
= NtfsGetUserBuffer(Irp
, BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
));
230 Status
= NtfsReadFile(DeviceExt
,
234 ReadOffset
.u
.LowPart
,
236 &ReturnedReadLength
);
237 if (NT_SUCCESS(Status
))
239 if (FileObject
->Flags
& FO_SYNCHRONOUS_IO
)
241 FileObject
->CurrentByteOffset
.QuadPart
=
242 ReadOffset
.QuadPart
+ ReturnedReadLength
;
245 Irp
->IoStatus
.Information
= ReturnedReadLength
;
249 Irp
->IoStatus
.Information
= 0;
257 NtfsWrite(PNTFS_IRP_CONTEXT IrpContext
)
259 DPRINT("NtfsWrite(IrpContext %p)\n",IrpContext
);
261 IrpContext
->Irp
->IoStatus
.Information
= 0;
262 return STATUS_NOT_SUPPORTED
;