ReactOS 0.4.15-dev-5667-ged97270
read.c File Reference
#include "cdprocs.h"
Include dependency graph for read.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (CDFS_BUG_CHECK_READ)
 
#define SafeZeroMemory(IC, AT, BYTE_COUNT)
 
#define READ_AHEAD_GRANULARITY   (0x10000)
 

Functions

 _Requires_lock_held_ (_Global_critical_region_)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (CDFS_BUG_CHECK_READ)

Definition at line 23 of file read.c.

◆ READ_AHEAD_GRANULARITY

#define READ_AHEAD_GRANULARITY   (0x10000)

Definition at line 60 of file read.c.

◆ SafeZeroMemory

#define SafeZeroMemory (   IC,
  AT,
  BYTE_COUNT 
)
Value:
{ \
RtlZeroMemory( (AT), (BYTE_COUNT) ); \
__pragma(warning(suppress: 6320)) \
CdRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
} _SEH2_END; \
}
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
boolean suppress
Definition: jpeglib.h:1006
#define AT
Definition: mbstring.h:34
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define warning(s)
Definition: debug.h:83
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166

Definition at line 38 of file read.c.

Function Documentation

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 68 of file read.c.

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}
#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 _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 READ_AHEAD_GRANULARITY
Definition: read.c:60
#define SafeZeroMemory(AT, BYTE_COUNT)
Definition: read.c:301
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)
@ 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