ReactOS 0.4.15-dev-5667-ged97270
read.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 Read.c
8
9Abstract:
10
11 This module implements the File Read routine for Read called by the
12 Fsd/Fsp dispatch drivers.
13
14
15--*/
16
17#include "cdprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (CDFS_BUG_CHECK_READ)
24
25//
26// VOID
27// SafeZeroMemory (
28// _Out_ PUCHAR At,
29// _In_ ULONG ByteCount
30// );
31//
32
33//
34// This macro just puts a nice little try-except around RtlZeroMemory
35//
36
37#ifndef __REACTOS__
38#define SafeZeroMemory(IC,AT,BYTE_COUNT) { \
39 _SEH2_TRY { \
40 RtlZeroMemory( (AT), (BYTE_COUNT) ); \
41__pragma(warning(suppress: 6320)) \
42 } _SEH2_EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { \
43 CdRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
44 } _SEH2_END; \
45}
46#else
47#define SafeZeroMemory(IC,AT,BYTE_COUNT) { \
48 _SEH2_TRY { \
49 RtlZeroMemory( (AT), (BYTE_COUNT) ); \
50 } _SEH2_EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { \
51 CdRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
52 } _SEH2_END; \
53}
54#endif
55
56//
57// Read ahead amount used for normal data files
58//
59
60#define READ_AHEAD_GRANULARITY (0x10000)
61
62#ifdef ALLOC_PRAGMA
63#pragma alloc_text(PAGE, CdCommonRead)
64#endif
65
66
67
68_Requires_lock_held_(_Global_critical_region_)
70CdCommonRead (
71 _Inout_ PIRP_CONTEXT IrpContext,
73 )
74
75/*++
76
77Routine Description:
78
79 This is the common entry point for NtReadFile calls. For synchronous requests,
80 CommonRead will complete the request in the current thread. If not
81 synchronous the request will be passed to the Fsp if there is a need to
82 block.
83
84Arguments:
85
86 Irp - Supplies the Irp to process
87
88Return Value:
89
90 NTSTATUS - The result of this operation.
91
92--*/
93
94{
97
99 PFCB Fcb;
100 PCCB Ccb;
101
103 ULONG PagingIo;
104 ULONG SynchronousIo;
105 ULONG NonCachedIo;
106 PVOID UserBuffer;
107
109 LONGLONG ByteRange;
111 ULONG ReadByteCount;
112 ULONG OriginalByteCount;
113
114 PVOID SystemBuffer;
115
116 BOOLEAN ReleaseFile = TRUE;
117
118 CD_IO_CONTEXT LocalIoContext;
119
120 PAGED_CODE();
121
122 //
123 // If this is a zero length read then return SUCCESS immediately.
124 //
125
126 if (IrpSp->Parameters.Read.Length == 0) {
127
128 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
129 return STATUS_SUCCESS;
130 }
131
132 //
133 // Decode the file object and verify we support read on this. It
134 // must be a user file, stream file or volume file (for a data disk).
135 //
136
137 TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
138
139 // Internal lock object is acquired if return status is STATUS_PENDING
141
144
147 }
148
149 //
150 // Examine our input parameters to determine if this is noncached and/or
151 // a paging io operation.
152 //
153
154 Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
155 PagingIo = FlagOn( Irp->Flags, IRP_PAGING_IO );
156 NonCachedIo = FlagOn( Irp->Flags, IRP_NOCACHE );
157 SynchronousIo = FlagOn( IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO );
158
159
160 //
161 // Extract the range of the Io.
162 //
163
164 StartingOffset = IrpSp->Parameters.Read.ByteOffset.QuadPart;
165 OriginalByteCount = ByteCount = IrpSp->Parameters.Read.Length;
166
167 ByteRange = StartingOffset + ByteCount;
168
169 //
170 // Make sure that Dasd access is always non-cached.
171 //
172
173 if (TypeOfOpen == UserVolumeOpen) {
174
175 NonCachedIo = TRUE;
176 }
177
178 //
179 // Acquire the file shared to perform the read. If we are doing paging IO,
180 // it may be the case that we would have a deadlock imminent because we may
181 // block on shared access, so starve out any exclusive waiters. This requires
182 // a degree of caution - we believe that any paging IO bursts will recede and
183 // allow the exclusive waiter in.
184 //
185
186 if (PagingIo) {
187
189
190 } else {
191
192 CdAcquireFileShared( IrpContext, Fcb );
193 }
194
195 //
196 // Use a try-finally to facilitate cleanup.
197 //
198
199 _SEH2_TRY {
200
201 //
202 // Verify the Fcb. Allow reads if this is a DASD handle that is
203 // dismounting the volume.
204 //
205
206 if ((TypeOfOpen != UserVolumeOpen) || (NULL == Ccb) ||
208
209 CdVerifyFcbOperation( IrpContext, Fcb );
210 }
211
212 //
213 // If this is a non-cached then check whether we need to post this
214 // request if this thread can't block.
215 //
216
217 if (!Wait && NonCachedIo) {
218
219 //
220 // XA requests must always be waitable.
221 //
222
224
225 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
227 }
228 }
229
230 //
231 // If this is a user request then verify the oplock and filelock state.
232 //
233
234 if (TypeOfOpen == UserFileOpen) {
235
236 //
237 // We check whether we can proceed
238 // based on the state of the file oplocks.
239 //
240
242 Irp,
243 IrpContext,
244 (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */
245 (PVOID)CdPrePostIrp );/* ReactOS Change: GCC "assignment from incompatible pointer type" */
246
247 //
248 // If the result is not STATUS_SUCCESS then the Irp was completed
249 // elsewhere.
250 //
251
252 if (Status != STATUS_SUCCESS) {
253
254 Irp = NULL;
255 IrpContext = NULL;
256
258 }
259
260 if (!PagingIo &&
261 (Fcb->FileLock != NULL) &&
263
265 }
266 }
267
268 //
269 // Check request beyond end of file if this is not a read on a volume
270 // handle marked for extended DASD IO.
271 //
272
273 if ((TypeOfOpen != UserVolumeOpen) ||
275
276 //
277 // Complete the request if it begins beyond the end of file.
278 //
279
280 if (StartingOffset >= Fcb->FileSize.QuadPart) {
281
283 }
284
285 //
286 // Truncate the read if it extends beyond the end of the file.
287 //
288
289 if (ByteRange > Fcb->FileSize.QuadPart) {
290
291 ByteCount = (ULONG) (Fcb->FileSize.QuadPart - StartingOffset);
292 ByteRange = Fcb->FileSize.QuadPart;
293 }
294 }
295
296 //
297 // Handle the non-cached read first.
298 //
299
300 if (NonCachedIo) {
301
302 //
303 // If we have an unaligned transfer then post this request if
304 // we can't wait. Unaligned means that the starting offset
305 // is not on a sector boundary or the read is not integral
306 // sectors.
307 //
308
309 ReadByteCount = BlockAlign( Fcb->Vcb, ByteCount );
310
312 SectorOffset( ReadByteCount ) ||
313 (ReadByteCount > OriginalByteCount)) {
314
315 if (!Wait) {
316
317 CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
318 }
319
320 //
321 // Make sure we don't overwrite the buffer.
322 //
323
324 ReadByteCount = ByteCount;
325 }
326
327 //
328 // Initialize the IoContext for the read.
329 // If there is a context pointer, we need to make sure it was
330 // allocated and not a stale stack pointer.
331 //
332
333 if (IrpContext->IoContext == NULL ||
334 !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {
335
336 //
337 // If we can wait, use the context on the stack. Otherwise
338 // we need to allocate one.
339 //
340
341 if (Wait) {
342
343 IrpContext->IoContext = &LocalIoContext;
344 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
345
346 } else {
347
348 IrpContext->IoContext = CdAllocateIoContext();
349 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
350 }
351 }
352
353 RtlZeroMemory( IrpContext->IoContext, sizeof( CD_IO_CONTEXT ));
354
355 //
356 // Store whether we allocated this context structure in the structure
357 // itself.
358 //
359
360 IrpContext->IoContext->AllocatedContext =
361 BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
362
363 if (Wait) {
364
365 KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
367 FALSE );
368
369 } else {
370
371 IrpContext->IoContext->ResourceThreadId = ExGetCurrentResourceThread();
372 IrpContext->IoContext->Resource = Fcb->Resource;
373 IrpContext->IoContext->RequestedByteCount = ByteCount;
374 }
375
376 Irp->IoStatus.Information = ReadByteCount;
377
378 //
379 // Call one of the NonCacheIo routines to perform the actual
380 // read.
381 //
382
384
385 Status = CdNonCachedXARead( IrpContext, Fcb, StartingOffset, ReadByteCount );
386
387 } else {
388
389 Status = CdNonCachedRead( IrpContext, Fcb, StartingOffset, ReadByteCount );
390 }
391
392 //
393 // Don't complete this request now if STATUS_PENDING was returned.
394 //
395
396 if (Status == STATUS_PENDING) {
397
398 Irp = NULL;
399 ReleaseFile = FALSE;
400
401 //
402 // Test is we should zero part of the buffer or update the
403 // synchronous file position.
404 //
405
406 } else {
407
408 //
409 // Convert any unknown error code to IO_ERROR.
410 //
411
412 if (!NT_SUCCESS( Status )) {
413
414 //
415 // Set the information field to zero.
416 //
417
418 Irp->IoStatus.Information = 0;
419
420 //
421 // Raise if this is a user induced error.
422 //
423
425
426 CdRaiseStatus( IrpContext, Status );
427 }
428
430
431 //
432 // Check if there is any portion of the user's buffer to zero.
433 //
434
435 } else if (ReadByteCount != ByteCount) {
436
437 CdMapUserBuffer( IrpContext, &UserBuffer);
438
439 SafeZeroMemory( IrpContext,
440 Add2Ptr( UserBuffer,
441 ByteCount,
442 PVOID ),
443 ReadByteCount - ByteCount );
444
445 Irp->IoStatus.Information = ByteCount;
446 }
447
448 //
449 // Update the file position if this is a synchronous request.
450 //
451
452 if (SynchronousIo && !PagingIo && NT_SUCCESS( Status )) {
453
454 IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange;
455 }
456 }
457
459 }
460
461 //
462 // Handle the cached case. Start by initializing the private
463 // cache map.
464 //
465
466 if (IrpSp->FileObject->PrivateCacheMap == NULL) {
467
468 //
469 // Now initialize the cache map.
470 //
471
473 (PCC_FILE_SIZES) &Fcb->AllocationSize,
474 FALSE,
476 Fcb );
477
479 }
480
481 //
482 // Read from the cache if this is not an Mdl read.
483 //
484
485 if (!FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
486
487 //
488 // If we are in the Fsp now because we had to wait earlier,
489 // we must map the user buffer, otherwise we can use the
490 // user's buffer directly.
491 //
492
493 CdMapUserBuffer( IrpContext, &SystemBuffer );
494
495 //
496 // Now try to do the copy.
497 //
498
501 ByteCount,
502 Wait,
503 SystemBuffer,
504 &Irp->IoStatus )) {
505
507 }
508
509 //
510 // If the call didn't succeed, raise the error status
511 //
512
513 if (!NT_SUCCESS( Irp->IoStatus.Status )) {
514
515 CdNormalizeAndRaiseStatus( IrpContext, Irp->IoStatus.Status );
516 }
517
518 //
519 // Otherwise perform the MdlRead operation.
520 //
521
522 } else {
523
526 ByteCount,
527 &Irp->MdlAddress,
528 &Irp->IoStatus );
529
530 Status = Irp->IoStatus.Status;
531 }
532
533 //
534 // Update the current file position in the user file object.
535 //
536
537 if (SynchronousIo && !PagingIo && NT_SUCCESS( Status )) {
538
539 IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange;
540 }
541
542 try_exit: NOTHING;
543 } _SEH2_FINALLY {
544
545 //
546 // Release the Fcb.
547 //
548
549 if (ReleaseFile) {
550
551 CdReleaseFile( IrpContext, Fcb );
552 }
553 } _SEH2_END;
554
555 //
556 // Post the request if we got CANT_WAIT.
557 //
558
559 if (Status == STATUS_CANT_WAIT) {
560
561 Status = CdFsdPostRequest( IrpContext, Irp );
562
563 //
564 // Otherwise complete the request.
565 //
566
567 } else {
568
569 CdCompleteRequest( IrpContext, Irp, Status );
570 }
571
572 return Status;
573}
574
575
576
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcMdlRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus)
Definition: mdlsup.c:64
VOID NTAPI CcSetReadAheadGranularity(IN PFILE_OBJECT FileObject, IN ULONG Granularity)
Definition: cachesub.c:36
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
CD_DATA CdData
Definition: cddata.c:42
#define CdMapUserBuffer(IC, UB)
Definition: cdprocs.h:383
#define CdAcquireFileSharedStarveExclusive(IC, F)
Definition: cdprocs.h:1000
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
#define CdReleaseFile(IC, F)
Definition: cdprocs.h:1003
#define BlockAlign(V, L)
Definition: cdprocs.h:1638
@ UnopenedFileObject
Definition: cdprocs.h:573
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
#define CdGetFcbOplock(F)
Definition: cdprocs.h:1081
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define CdAllocateIoContext()
Definition: cdprocs.h:1344
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define CdNormalizeAndRaiseStatus(IC, S)
Definition: cdprocs.h:1860
#define SectorOffset(L)
Definition: cdprocs.h:1622
#define CdAcquireFileShared(IC, F)
Definition: cdprocs.h:997
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define try_return(S)
Definition: cdprocs.h:2179
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define FCB_STATE_RAWSECTOR_MASK
Definition: cdstruc.h:1052
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO
Definition: cdstruc.h:1108
#define IRP_CONTEXT_FLAG_FORCE_POST
Definition: cdstruc.h:1216
#define CCB_FLAG_DISMOUNT_ON_CLOSE
Definition: cdstruc.h:1107
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
#define IRP_CONTEXT_FLAG_ALLOC_IO
Definition: cdstruc.h:1221
#define _Requires_lock_held_(lock)
#define _Analysis_suppress_lock_checking_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExGetCurrentResourceThread()
Definition: env_spec_w32.h:633
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define READ_AHEAD_GRANULARITY
Definition: read.c:60
#define SafeZeroMemory(IC, AT, BYTE_COUNT)
Definition: read.c:38
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
Status
Definition: gdiplustypes.h:25
#define NOTHING
Definition: input_list.c:10
#define Add2Ptr(PTR, INC)
#define _Inout_
Definition: ms_sal.h:378
@ NotificationEvent
BOOLEAN NTAPI CcCopyRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus)
Definition: copysup.c:43
NTSTATUS NTAPI FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize, IN NTSTATUS NormalizedNtStatus)
Definition: filter.c:90
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:320
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:469
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
CACHE_MANAGER_CALLBACKS CacheManagerCallbacks
Definition: cdstruc.h:409
Definition: cdstruc.h:902
ULONG Flags
Definition: ntfs.h:536
PVCB Vcb
Definition: cdstruc.h:933
FILE_LOCK FileLock
Definition: fatstruc.h:1071
ULONG FcbState
Definition: cdstruc.h:971
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IRP_PAGING_IO
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define IRP_MN_MDL
Definition: iotypes.h:4419
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
#define IRP_NOCACHE