3 * Copyright (C) 2017 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 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.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: sdk/lib/drivers/copysup/copysup.c
23 * PURPOSE: CopySup library
24 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
27 /* INCLUDES *****************************************************************/
30 #include <pseh/pseh2.h>
32 /* FUNCTIONS ****************************************************************/
39 IN PFILE_OBJECT FileObject
,
40 IN PLARGE_INTEGER FileOffset
,
45 OUT PIO_STATUS_BLOCK IoStatus
,
46 IN PDEVICE_OBJECT DeviceObject
,
47 IN PVOID TopLevelContext
)
51 LARGE_INTEGER FinalOffset
;
52 PFSRTL_COMMON_FCB_HEADER Fcb
;
53 PFAST_IO_DISPATCH FastIoDispatch
;
54 PDEVICE_OBJECT RelatedDeviceObject
;
59 PageCount
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset
, Length
);
61 /* Null-length read is always OK */
64 IoStatus
->Information
= 0;
65 IoStatus
->Status
= STATUS_SUCCESS
;
70 /* Check we don't overflow */
71 FinalOffset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
72 if (FinalOffset
.QuadPart
<= 0)
77 /* Get the FCB (at least, its header) */
78 Fcb
= FileObject
->FsContext
;
80 FsRtlEnterFileSystem();
82 /* Acquire its resource (shared) */
85 ExAcquireResourceSharedLite(Fcb
->Resource
, TRUE
);
89 if (!ExAcquireResourceSharedLite(Fcb
->Resource
, FALSE
))
96 /* If cache wasn't initialized, or FastIO isn't possible, fail */
97 if (FileObject
->PrivateCacheMap
== NULL
|| Fcb
->IsFastIoPossible
== FastIoIsNotPossible
)
103 /* If FastIO is questionable, then, question! */
104 if (Fcb
->IsFastIoPossible
== FastIoIsQuestionable
)
106 RelatedDeviceObject
= IoGetRelatedDeviceObject(FileObject
);
107 FastIoDispatch
= RelatedDeviceObject
->DriverObject
->FastIoDispatch
;
108 ASSERT(FastIoDispatch
!= NULL
);
109 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
111 /* If it's not possible, then fail */
112 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
, FileOffset
, Length
,
113 Wait
, LockKey
, TRUE
, IoStatus
, RelatedDeviceObject
))
120 /* If we get beyond file end... */
121 if (FinalOffset
.QuadPart
> Fcb
->FileSize
.QuadPart
)
123 /* Fail if the offset was already beyond file end */
124 if (FileOffset
->QuadPart
>= Fcb
->FileSize
.QuadPart
)
126 IoStatus
->Information
= 0;
127 IoStatus
->Status
= STATUS_END_OF_FILE
;
131 /* Otherwise, just fix read length */
132 Length
= (ULONG
)(Fcb
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
135 /* Set caller provided context as TLI */
136 IoSetTopLevelIrp(TopLevelContext
);
140 /* If we cannot wait, or if file is bigger than 4GB */
141 if (!Wait
|| (FinalOffset
.HighPart
| Fcb
->FileSize
.HighPart
) != 0)
144 Ret
= CcCopyRead(FileObject
, FileOffset
, Length
, Wait
, Buffer
, IoStatus
);
145 SetFlag(FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
147 /* Validate output */
148 ASSERT(!Ret
|| (IoStatus
->Status
== STATUS_END_OF_FILE
) || (((ULONGLONG
)FileOffset
->QuadPart
+ IoStatus
->Information
) <= (ULONGLONG
)Fcb
->FileSize
.QuadPart
));
153 CcFastCopyRead(FileObject
, FileOffset
->LowPart
, Length
, PageCount
, Buffer
, IoStatus
);
154 SetFlag(FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
156 /* Validate output */
157 ASSERT((IoStatus
->Status
== STATUS_END_OF_FILE
) || ((FileOffset
->LowPart
+ IoStatus
->Information
) <= Fcb
->FileSize
.LowPart
));
160 /* If read was successful, update the byte offset in the FO */
163 FileObject
->CurrentByteOffset
.QuadPart
= FileOffset
->QuadPart
+ IoStatus
->Information
;
166 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
167 EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
)
174 IoSetTopLevelIrp(NULL
);
177 ExReleaseResourceLite(Fcb
->Resource
);
179 FsRtlExitFileSystem();