xref: /reactos/drivers/filesystems/udfs/read.cpp (revision 34593d93)
1c2c66affSColin Finck ////////////////////////////////////////////////////////////////////
2c2c66affSColin Finck // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3c2c66affSColin Finck // All rights reserved
4c2c66affSColin Finck // This file was released under the GPLv2 on June 2015.
5c2c66affSColin Finck ////////////////////////////////////////////////////////////////////
6c2c66affSColin Finck /*************************************************************************
7c2c66affSColin Finck *
8c2c66affSColin Finck * File: Read.cpp
9c2c66affSColin Finck *
10c2c66affSColin Finck * Module: UDF File System Driver (Kernel mode execution only)
11c2c66affSColin Finck *
12c2c66affSColin Finck * Description:
13c2c66affSColin Finck *   Contains code to handle the "Read" dispatch entry point.
14c2c66affSColin Finck *
15c2c66affSColin Finck *************************************************************************/
16c2c66affSColin Finck 
17c2c66affSColin Finck #include            "udffs.h"
18c2c66affSColin Finck 
19c2c66affSColin Finck // define the file specific bug-check id
20c2c66affSColin Finck #define         UDF_BUG_CHECK_ID                UDF_FILE_READ
21c2c66affSColin Finck 
22c2c66affSColin Finck #ifdef _M_IX86
23c2c66affSColin Finck #if DBG
24c2c66affSColin Finck #define OVERFLOW_READ_THRESHHOLD         (0xE00)
25c2c66affSColin Finck #else
26c2c66affSColin Finck #define OVERFLOW_READ_THRESHHOLD         (0xA00)
27c2c66affSColin Finck #endif // UDF_DBG
28c2c66affSColin Finck #else  // defined(_M_IX86)
29c2c66affSColin Finck #define OVERFLOW_READ_THRESHHOLD         (0x1000)
30c2c66affSColin Finck #endif // defined(_M_IX86)
31c2c66affSColin Finck 
32c2c66affSColin Finck //#define POST_LOCK_PAGES
33c2c66affSColin Finck 
34c2c66affSColin Finck 
35c2c66affSColin Finck /*************************************************************************
36c2c66affSColin Finck *
37c2c66affSColin Finck * Function: UDFRead()
38c2c66affSColin Finck *
39c2c66affSColin Finck * Description:
40c2c66affSColin Finck *   The I/O Manager will invoke this routine to handle a read
41c2c66affSColin Finck *   request
42c2c66affSColin Finck *
43c2c66affSColin Finck * Expected Interrupt Level (for execution) :
44c2c66affSColin Finck *
45c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
46c2c66affSColin Finck *   to be deferred to a worker thread context)
47c2c66affSColin Finck *
48c2c66affSColin Finck * Return Value: STATUS_SUCCESS/Error
49c2c66affSColin Finck *
50c2c66affSColin Finck *************************************************************************/
51c2c66affSColin Finck NTSTATUS
52c2c66affSColin Finck NTAPI
UDFRead(PDEVICE_OBJECT DeviceObject,PIRP Irp)53c2c66affSColin Finck UDFRead(
54c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject,       // the logical volume device object
55c2c66affSColin Finck     PIRP           Irp)                // I/O Request Packet
56c2c66affSColin Finck {
57c2c66affSColin Finck     NTSTATUS            RC = STATUS_SUCCESS;
58c2c66affSColin Finck     PtrUDFIrpContext    PtrIrpContext = NULL;
59c2c66affSColin Finck     BOOLEAN             AreWeTopLevel = FALSE;
60c2c66affSColin Finck 
61c2c66affSColin Finck     TmPrint(("UDFRead: \n"));
62c2c66affSColin Finck 
63c2c66affSColin Finck     FsRtlEnterFileSystem();
64c2c66affSColin Finck     ASSERT(DeviceObject);
65c2c66affSColin Finck     ASSERT(Irp);
66c2c66affSColin Finck 
67c2c66affSColin Finck     // set the top level context
68c2c66affSColin Finck     AreWeTopLevel = UDFIsIrpTopLevel(Irp);
69c2c66affSColin Finck     ASSERT(!UDFIsFSDevObj(DeviceObject));
70c2c66affSColin Finck 
71c2c66affSColin Finck     _SEH2_TRY {
72c2c66affSColin Finck 
73c2c66affSColin Finck         // get an IRP context structure and issue the request
74c2c66affSColin Finck         PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
75c2c66affSColin Finck         if(PtrIrpContext) {
76c2c66affSColin Finck             RC = UDFCommonRead(PtrIrpContext, Irp);
77c2c66affSColin Finck         } else {
78c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
79c2c66affSColin Finck             Irp->IoStatus.Status = RC;
80c2c66affSColin Finck             Irp->IoStatus.Information = 0;
81c2c66affSColin Finck             // complete the IRP
82c2c66affSColin Finck             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
83c2c66affSColin Finck         }
84c2c66affSColin Finck 
85c2c66affSColin Finck     } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
86c2c66affSColin Finck 
87c2c66affSColin Finck         RC = UDFExceptionHandler(PtrIrpContext, Irp);
88c2c66affSColin Finck 
89c2c66affSColin Finck         UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
90c2c66affSColin Finck     } _SEH2_END;
91c2c66affSColin Finck 
92c2c66affSColin Finck     if (AreWeTopLevel) {
93c2c66affSColin Finck         IoSetTopLevelIrp(NULL);
94c2c66affSColin Finck     }
95c2c66affSColin Finck 
96c2c66affSColin Finck     FsRtlExitFileSystem();
97c2c66affSColin Finck 
98c2c66affSColin Finck     return(RC);
99c2c66affSColin Finck } // end UDFRead()
100c2c66affSColin Finck 
101c2c66affSColin Finck 
102c2c66affSColin Finck /*************************************************************************
103c2c66affSColin Finck *
104c2c66affSColin Finck * Function: UDFPostStackOverflowRead()
105c2c66affSColin Finck *
106c2c66affSColin Finck * Description:
107c2c66affSColin Finck *    Post a read request that could not be processed by
108c2c66affSColin Finck *    the fsp thread because of stack overflow potential.
109c2c66affSColin Finck *
110c2c66affSColin Finck * Arguments:
111c2c66affSColin Finck *    Irp - Supplies the request to process.
112c2c66affSColin Finck *    Fcb - Supplies the file.
113c2c66affSColin Finck *
114c2c66affSColin Finck * Return Value: STATUS_PENDING.
115c2c66affSColin Finck *
116c2c66affSColin Finck *************************************************************************/
117c2c66affSColin Finck NTSTATUS
UDFPostStackOverflowRead(IN PtrUDFIrpContext PtrIrpContext,IN PIRP Irp,IN PtrUDFFCB Fcb)118c2c66affSColin Finck UDFPostStackOverflowRead(
119c2c66affSColin Finck     IN PtrUDFIrpContext PtrIrpContext,
120c2c66affSColin Finck     IN PIRP             Irp,
121c2c66affSColin Finck     IN PtrUDFFCB        Fcb
122c2c66affSColin Finck     )
123c2c66affSColin Finck {
124c2c66affSColin Finck     PKEVENT Event;
125c2c66affSColin Finck     PERESOURCE Resource;
126c2c66affSColin Finck 
127c2c66affSColin Finck     UDFPrint(("Getting too close to stack limit pass request to Fsp\n"));
128c2c66affSColin Finck 
129c2c66affSColin Finck     //  Allocate an event and get shared on the resource we will
130c2c66affSColin Finck     //  be later using the common read.
131c2c66affSColin Finck     Event = (PKEVENT)MyAllocatePool__(NonPagedPool, sizeof(KEVENT));
132c2c66affSColin Finck     if(!Event)
133c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
134c2c66affSColin Finck     KeInitializeEvent( Event, NotificationEvent, FALSE );
135c2c66affSColin Finck 
136c2c66affSColin Finck     if ((Irp->Flags & IRP_PAGING_IO) && (Fcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource)) {
137c2c66affSColin Finck         Resource = Fcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource;
138c2c66affSColin Finck     } else {
139c2c66affSColin Finck         Resource = Fcb->NTRequiredFCB->CommonFCBHeader.Resource;
140c2c66affSColin Finck     }
141c2c66affSColin Finck 
142c2c66affSColin Finck     UDFAcquireResourceShared( Resource, TRUE );
143c2c66affSColin Finck 
144c2c66affSColin Finck     _SEH2_TRY {
145c2c66affSColin Finck         //  If this read is the result of a verify, we have to
146c2c66affSColin Finck         //  tell the overflow read routne to temporarily
147c2c66affSColin Finck         //  hijack the Vcb->VerifyThread field so that reads
148c2c66affSColin Finck         //  can go through.
149c2c66affSColin Finck         FsRtlPostStackOverflow(PtrIrpContext, Event, UDFStackOverflowRead);
150c2c66affSColin Finck         //  And wait for the worker thread to complete the item
151c2c66affSColin Finck         DbgWaitForSingleObject(Event, NULL);
152c2c66affSColin Finck 
153c2c66affSColin Finck     } _SEH2_FINALLY {
154c2c66affSColin Finck 
155c2c66affSColin Finck         UDFReleaseResource( Resource );
156c2c66affSColin Finck         MyFreePool__( Event );
157c2c66affSColin Finck     } _SEH2_END;
158c2c66affSColin Finck 
159c2c66affSColin Finck     return STATUS_PENDING;
160c2c66affSColin Finck 
161c2c66affSColin Finck } // end UDFPostStackOverflowRead()
162c2c66affSColin Finck 
163c2c66affSColin Finck /*************************************************************************
164c2c66affSColin Finck *
165c2c66affSColin Finck * Function: UDFStackOverflowRead()
166c2c66affSColin Finck *
167c2c66affSColin Finck * Description:
168c2c66affSColin Finck *    Process a read request that could not be processed by
169c2c66affSColin Finck *    the fsp thread because of stack overflow potential.
170c2c66affSColin Finck *
171c2c66affSColin Finck * Arguments:
172c2c66affSColin Finck *    Context - Supplies the IrpContext being processed
173c2c66affSColin Finck *    Event - Supplies the event to be signaled when we are done processing this
174c2c66affSColin Finck *        request.
175c2c66affSColin Finck *
176c2c66affSColin Finck * Expected Interrupt Level (for execution) :
177c2c66affSColin Finck *
178c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
179c2c66affSColin Finck *
180c2c66affSColin Finck * Return Value: None.
181c2c66affSColin Finck *
182c2c66affSColin Finck *************************************************************************/
183c2c66affSColin Finck VOID
184c2c66affSColin Finck NTAPI
UDFStackOverflowRead(IN PVOID Context,IN PKEVENT Event)185c2c66affSColin Finck UDFStackOverflowRead(
186c2c66affSColin Finck     IN PVOID Context,
187c2c66affSColin Finck     IN PKEVENT Event
188c2c66affSColin Finck     )
189c2c66affSColin Finck {
190c2c66affSColin Finck     PtrUDFIrpContext PtrIrpContext = (PtrUDFIrpContext)Context;
191c2c66affSColin Finck     NTSTATUS RC;
192c2c66affSColin Finck 
193c2c66affSColin Finck     UDFPrint(("UDFStackOverflowRead: \n"));
194c2c66affSColin Finck     //  Make it now look like we can wait for I/O to complete
195c2c66affSColin Finck     PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_CAN_BLOCK;
196c2c66affSColin Finck 
197c2c66affSColin Finck     //  Do the read operation protected by a try-except clause
198c2c66affSColin Finck     _SEH2_TRY {
199c2c66affSColin Finck         UDFCommonRead(PtrIrpContext, PtrIrpContext->Irp);
200c2c66affSColin Finck     } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
201c2c66affSColin Finck         RC = UDFExceptionHandler(PtrIrpContext, PtrIrpContext->Irp);
202c2c66affSColin Finck         UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
203c2c66affSColin Finck     } _SEH2_END;
204c2c66affSColin Finck 
205c2c66affSColin Finck     //  Set the stack overflow item's event to tell the original
206c2c66affSColin Finck     //  thread that we're done.
207c2c66affSColin Finck     KeSetEvent( Event, 0, FALSE );
208c2c66affSColin Finck } // end UDFStackOverflowRead()
209c2c66affSColin Finck 
210c2c66affSColin Finck 
211c2c66affSColin Finck /*************************************************************************
212c2c66affSColin Finck *
213c2c66affSColin Finck * Function: UDFCommonRead()
214c2c66affSColin Finck *
215c2c66affSColin Finck * Description:
216c2c66affSColin Finck *   The actual work is performed here. This routine may be invoked in one
217c2c66affSColin Finck *   of the two possible contexts:
218c2c66affSColin Finck *   (a) in the context of a system worker thread
219c2c66affSColin Finck *   (b) in the context of the original caller
220c2c66affSColin Finck *
221c2c66affSColin Finck * Expected Interrupt Level (for execution) :
222c2c66affSColin Finck *
223c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
224c2c66affSColin Finck *
225c2c66affSColin Finck * Return Value: STATUS_SUCCESS/Error
226c2c66affSColin Finck *
227c2c66affSColin Finck *************************************************************************/
228c2c66affSColin Finck NTSTATUS
UDFCommonRead(PtrUDFIrpContext PtrIrpContext,PIRP Irp)229c2c66affSColin Finck UDFCommonRead(
230c2c66affSColin Finck     PtrUDFIrpContext PtrIrpContext,
231c2c66affSColin Finck     PIRP             Irp
232c2c66affSColin Finck     )
233c2c66affSColin Finck {
234c2c66affSColin Finck     NTSTATUS                RC = STATUS_SUCCESS;
235c2c66affSColin Finck     PIO_STACK_LOCATION      IrpSp = NULL;
236c2c66affSColin Finck     LARGE_INTEGER           ByteOffset;
237c2c66affSColin Finck     ULONG                   ReadLength = 0, TruncatedLength = 0;
238*c334c17dSTimo Kreuzer     SIZE_T                  NumberBytesRead = 0;
239c2c66affSColin Finck     PFILE_OBJECT            FileObject = NULL;
240c2c66affSColin Finck     PtrUDFFCB               Fcb = NULL;
241c2c66affSColin Finck     PtrUDFCCB               Ccb = NULL;
242c2c66affSColin Finck     PVCB                    Vcb = NULL;
243c2c66affSColin Finck     PtrUDFNTRequiredFCB     NtReqFcb = NULL;
244c2c66affSColin Finck     PERESOURCE              PtrResourceAcquired = NULL;
245c2c66affSColin Finck     PERESOURCE              PtrResourceAcquired2 = NULL;
246c2c66affSColin Finck     PVOID                   SystemBuffer = NULL;
247c2c66affSColin Finck     PIRP                    TopIrp;
248c2c66affSColin Finck //    uint32                  KeyValue = 0;
249c2c66affSColin Finck 
250c2c66affSColin Finck     ULONG                   Res1Acq = 0;
251c2c66affSColin Finck     ULONG                   Res2Acq = 0;
252c2c66affSColin Finck 
253c2c66affSColin Finck     BOOLEAN                 CacheLocked = FALSE;
254c2c66affSColin Finck 
255c2c66affSColin Finck     BOOLEAN                 CanWait = FALSE;
256c2c66affSColin Finck     BOOLEAN                 PagingIo = FALSE;
257c2c66affSColin Finck     BOOLEAN                 NonBufferedIo = FALSE;
258c2c66affSColin Finck     BOOLEAN                 SynchronousIo = FALSE;
259c2c66affSColin Finck 
260c2c66affSColin Finck     TmPrint(("UDFCommonRead: irp %x\n", Irp));
261c2c66affSColin Finck 
262c2c66affSColin Finck     _SEH2_TRY {
263c2c66affSColin Finck 
264c2c66affSColin Finck         TopIrp = IoGetTopLevelIrp();
265*c334c17dSTimo Kreuzer         switch((ULONG_PTR)TopIrp) {
266c2c66affSColin Finck         case FSRTL_FSP_TOP_LEVEL_IRP:
267c2c66affSColin Finck             UDFPrint(("  FSRTL_FSP_TOP_LEVEL_IRP\n"));
268c2c66affSColin Finck             break;
269c2c66affSColin Finck         case FSRTL_CACHE_TOP_LEVEL_IRP:
270c2c66affSColin Finck             UDFPrint(("  FSRTL_CACHE_TOP_LEVEL_IRP\n"));
271c2c66affSColin Finck             break;
272c2c66affSColin Finck         case FSRTL_MOD_WRITE_TOP_LEVEL_IRP:
273c2c66affSColin Finck             UDFPrint(("  FSRTL_MOD_WRITE_TOP_LEVEL_IRP\n"));
274c2c66affSColin Finck //            BrutePoint()
275c2c66affSColin Finck             break;
276c2c66affSColin Finck         case FSRTL_FAST_IO_TOP_LEVEL_IRP:
277c2c66affSColin Finck             UDFPrint(("  FSRTL_FAST_IO_TOP_LEVEL_IRP\n"));
278c2c66affSColin Finck //            BrutePoint()
279c2c66affSColin Finck             break;
280c2c66affSColin Finck         case NULL:
281c2c66affSColin Finck             UDFPrint(("  NULL TOP_LEVEL_IRP\n"));
282c2c66affSColin Finck             break;
283c2c66affSColin Finck         default:
284c2c66affSColin Finck             if(TopIrp == Irp) {
285c2c66affSColin Finck                 UDFPrint(("  TOP_LEVEL_IRP\n"));
286c2c66affSColin Finck             } else {
287c2c66affSColin Finck                 UDFPrint(("  RECURSIVE_IRP, TOP = %x\n", TopIrp));
288c2c66affSColin Finck             }
289c2c66affSColin Finck             break;
290c2c66affSColin Finck         }
291c2c66affSColin Finck         // First, get a pointer to the current I/O stack location
292c2c66affSColin Finck         IrpSp = IoGetCurrentIrpStackLocation(Irp);
293c2c66affSColin Finck         ASSERT(IrpSp);
294c2c66affSColin Finck         MmPrint(("    Enter Irp, MDL=%x\n", Irp->MdlAddress));
295c2c66affSColin Finck         if(Irp->MdlAddress) {
296c2c66affSColin Finck             UDFTouch(Irp->MdlAddress);
297c2c66affSColin Finck         }
298c2c66affSColin Finck 
299c2c66affSColin Finck         // If this happens to be a MDL read complete request, then
300c2c66affSColin Finck         // there is not much processing that the FSD has to do.
301c2c66affSColin Finck         if (IrpSp->MinorFunction & IRP_MN_COMPLETE) {
302c2c66affSColin Finck             // Caller wants to tell the Cache Manager that a previously
303c2c66affSColin Finck             // allocated MDL can be freed.
304c2c66affSColin Finck             UDFMdlComplete(PtrIrpContext, Irp, IrpSp, TRUE);
305c2c66affSColin Finck             // The IRP has been completed.
306c2c66affSColin Finck             try_return(RC = STATUS_SUCCESS);
307c2c66affSColin Finck         }
308c2c66affSColin Finck 
309c2c66affSColin Finck         // If this is a request at IRQL DISPATCH_LEVEL, then post
310c2c66affSColin Finck         // the request (your FSD may choose to process it synchronously
311c2c66affSColin Finck         // if you implement the support correctly; obviously you will be
312c2c66affSColin Finck         // quite constrained in what you can do at such IRQL).
313c2c66affSColin Finck         if (IrpSp->MinorFunction & IRP_MN_DPC) {
314c2c66affSColin Finck             try_return(RC = STATUS_PENDING);
315c2c66affSColin Finck         }
316c2c66affSColin Finck 
317c2c66affSColin Finck         FileObject = IrpSp->FileObject;
318c2c66affSColin Finck         ASSERT(FileObject);
319c2c66affSColin Finck 
320c2c66affSColin Finck         // Get the FCB and CCB pointers
321c2c66affSColin Finck         Ccb = (PtrUDFCCB)(FileObject->FsContext2);
322c2c66affSColin Finck         ASSERT(Ccb);
323c2c66affSColin Finck         Fcb = Ccb->Fcb;
324c2c66affSColin Finck         ASSERT(Fcb);
325c2c66affSColin Finck         Vcb = Fcb->Vcb;
326c2c66affSColin Finck 
327c2c66affSColin Finck         if(Fcb->FCBFlags & UDF_FCB_DELETED) {
328c2c66affSColin Finck             ASSERT(FALSE);
329c2c66affSColin Finck             try_return(RC = STATUS_ACCESS_DENIED);
330c2c66affSColin Finck         }
331c2c66affSColin Finck 
332c2c66affSColin Finck         // check for stack overflow
333c2c66affSColin Finck         if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {
334c2c66affSColin Finck             RC = UDFPostStackOverflowRead( PtrIrpContext, Irp, Fcb );
335c2c66affSColin Finck             try_return(RC);
336c2c66affSColin Finck         }
337c2c66affSColin Finck 
338c2c66affSColin Finck         // Disk based file systems might decide to verify the logical volume
339c2c66affSColin Finck         //  (if required and only if removable media are supported) at this time
340c2c66affSColin Finck         // As soon as Tray is locked, we needn't call UDFVerifyVcb()
341c2c66affSColin Finck 
342c2c66affSColin Finck         ByteOffset = IrpSp->Parameters.Read.ByteOffset;
343c2c66affSColin Finck 
344c2c66affSColin Finck         CanWait = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE;
345c2c66affSColin Finck         PagingIo = (Irp->Flags & IRP_PAGING_IO) ? TRUE : FALSE;
346c2c66affSColin Finck         NonBufferedIo = (Irp->Flags & IRP_NOCACHE) ? TRUE : FALSE;
347c2c66affSColin Finck         SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO) ? TRUE : FALSE;
348c2c66affSColin Finck         UDFPrint(("    Flags: %s %s %s %s\n",
349c2c66affSColin Finck                       CanWait ? "W" : "w", PagingIo ? "Pg" : "pg",
350c2c66affSColin Finck                       NonBufferedIo ? "NBuf" : "buff", SynchronousIo ? "Snc" : "Asc"));
351c2c66affSColin Finck 
352c2c66affSColin Finck         if(!NonBufferedIo &&
353c2c66affSColin Finck            (Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB)) {
354c2c66affSColin Finck             if(UDFIsAStream(Fcb->FileInfo)) {
355c2c66affSColin Finck                 UDFNotifyFullReportChange( Vcb, Fcb->FileInfo,
356c2c66affSColin Finck                                            FILE_NOTIFY_CHANGE_LAST_ACCESS,
357c2c66affSColin Finck                                            FILE_ACTION_MODIFIED_STREAM);
358c2c66affSColin Finck             } else {
359c2c66affSColin Finck                 UDFNotifyFullReportChange( Vcb, Fcb->FileInfo,
360c2c66affSColin Finck                                            FILE_NOTIFY_CHANGE_LAST_ACCESS,
361c2c66affSColin Finck                                            FILE_ACTION_MODIFIED);
362c2c66affSColin Finck             }
363c2c66affSColin Finck         }
364c2c66affSColin Finck 
365c2c66affSColin Finck         // Get some of the parameters supplied to us
366c2c66affSColin Finck         ReadLength = IrpSp->Parameters.Read.Length;
367c2c66affSColin Finck         if (ReadLength == 0) {
368c2c66affSColin Finck             // a 0 byte read can be immediately succeeded
369c2c66affSColin Finck             try_return(RC);
370c2c66affSColin Finck         }
371c2c66affSColin Finck         UDFPrint(("    ByteOffset = %I64x, ReadLength = %x\n", ByteOffset.QuadPart, ReadLength));
372c2c66affSColin Finck 
373c2c66affSColin Finck         // Is this a read of the volume itself ?
374c2c66affSColin Finck         if (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) {
375c2c66affSColin Finck             // Yup, we need to send this on to the disk driver after
376c2c66affSColin Finck             //  validation of the offset and length.
377c2c66affSColin Finck             Vcb = (PVCB)Fcb;
378c2c66affSColin Finck             Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
379c2c66affSColin Finck             if(!CanWait)
380c2c66affSColin Finck                 try_return(RC = STATUS_PENDING);
381c2c66affSColin Finck 
382c2c66affSColin Finck 
383c2c66affSColin Finck             if(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) {
384c2c66affSColin Finck 
385c2c66affSColin Finck                 UDFPrint(("  UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n"));
386c2c66affSColin Finck                 PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED;
387c2c66affSColin Finck 
388c2c66affSColin Finck                 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) {
389c2c66affSColin Finck                     UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
390c2c66affSColin Finck                 }
391c2c66affSColin Finck #ifdef UDF_DELAYED_CLOSE
392c2c66affSColin Finck                 UDFCloseAllDelayed(Vcb);
393c2c66affSColin Finck #endif //UDF_DELAYED_CLOSE
394c2c66affSColin Finck 
395c2c66affSColin Finck             }
396c2c66affSColin Finck 
397c2c66affSColin Finck             if(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_FLUSH_REQUIRED) {
398c2c66affSColin Finck 
399c2c66affSColin Finck                 UDFPrint(("  UDF_IRP_CONTEXT_FLUSH_REQUIRED\n"));
400c2c66affSColin Finck                 PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_FLUSH_REQUIRED;
401c2c66affSColin Finck 
402c2c66affSColin Finck                 // Acquire the volume resource exclusive
403c2c66affSColin Finck                 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
404c2c66affSColin Finck                 PtrResourceAcquired = &(Vcb->VCBResource);
405c2c66affSColin Finck 
406c2c66affSColin Finck                 UDFFlushLogicalVolume(NULL, NULL, Vcb, 0);
407c2c66affSColin Finck 
408c2c66affSColin Finck                 UDFReleaseResource(PtrResourceAcquired);
409c2c66affSColin Finck                 PtrResourceAcquired = NULL;
410c2c66affSColin Finck             }
411c2c66affSColin Finck 
412c2c66affSColin Finck             // Acquire the volume resource shared ...
413c2c66affSColin Finck             UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
414c2c66affSColin Finck             PtrResourceAcquired = &(Vcb->VCBResource);
415c2c66affSColin Finck 
416c2c66affSColin Finck #if 0
417c2c66affSColin Finck             if(PagingIo) {
418c2c66affSColin Finck                 CollectStatistics(Vcb, MetaDataReads);
419c2c66affSColin Finck                 CollectStatisticsEx(Vcb, MetaDataReadBytes, NumberBytesRead);
420c2c66affSColin Finck             }
421c2c66affSColin Finck #endif
422c2c66affSColin Finck 
423c2c66affSColin Finck             // Forward the request to the lower level driver
424c2c66affSColin Finck             // Lock the callers buffer
425c2c66affSColin Finck             if (!NT_SUCCESS(RC = UDFLockCallersBuffer(PtrIrpContext, Irp, TRUE, ReadLength))) {
426c2c66affSColin Finck                 try_return(RC);
427c2c66affSColin Finck             }
428c2c66affSColin Finck             SystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
429c2c66affSColin Finck             if(!SystemBuffer) {
430c2c66affSColin Finck                 try_return(RC = STATUS_INVALID_USER_BUFFER);
431c2c66affSColin Finck             }
432c2c66affSColin Finck             if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) {
433c2c66affSColin Finck                  RC = UDFReadData(Vcb, TRUE, ByteOffset.QuadPart,
434c2c66affSColin Finck                                 ReadLength, FALSE, (PCHAR)SystemBuffer,
435c2c66affSColin Finck                                 &NumberBytesRead);
436c2c66affSColin Finck             } else {
437c2c66affSColin Finck                  RC = UDFTRead(Vcb, SystemBuffer, ReadLength,
438c2c66affSColin Finck                                 (ULONG)(ByteOffset.QuadPart >> Vcb->BlockSizeBits),
439c2c66affSColin Finck                                 &NumberBytesRead);
440c2c66affSColin Finck             }
441c2c66affSColin Finck             UDFUnlockCallersBuffer(PtrIrpContext, Irp, SystemBuffer);
442c2c66affSColin Finck             try_return(RC);
443c2c66affSColin Finck         }
444c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
445c2c66affSColin Finck 
446c2c66affSColin Finck         // If the read request is directed to a page file (if your FSD
447c2c66affSColin Finck         // supports paging files), send the request directly to the disk
448c2c66affSColin Finck         // driver. For requests directed to a page file, you have to trust
449c2c66affSColin Finck         // that the offsets will be set correctly by the VMM. You should not
450c2c66affSColin Finck         // attempt to acquire any FSD resources either.
451c2c66affSColin Finck         if(Fcb->FCBFlags & UDF_FCB_PAGE_FILE) {
452c2c66affSColin Finck             NonBufferedIo = TRUE;
453c2c66affSColin Finck         }
454c2c66affSColin Finck 
455c2c66affSColin Finck         if(ByteOffset.HighPart == -1) {
456c2c66affSColin Finck             if(ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION) {
457c2c66affSColin Finck                 ByteOffset = FileObject->CurrentByteOffset;
458c2c66affSColin Finck             }
459c2c66affSColin Finck         }
460c2c66affSColin Finck 
461c2c66affSColin Finck         // If this read is directed to a directory, it is not allowed
462c2c66affSColin Finck         //  by the UDF FSD.
463c2c66affSColin Finck         if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
464c2c66affSColin Finck             RC = STATUS_INVALID_DEVICE_REQUEST;
465c2c66affSColin Finck             try_return(RC);
466c2c66affSColin Finck         }
467c2c66affSColin Finck 
468c2c66affSColin Finck         NtReqFcb = Fcb->NTRequiredFCB;
469c2c66affSColin Finck 
470c2c66affSColin Finck         Res1Acq = UDFIsResourceAcquired(&(NtReqFcb->MainResource));
471c2c66affSColin Finck         if(!Res1Acq) {
472c2c66affSColin Finck             Res1Acq = PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_RES1_ACQ;
473c2c66affSColin Finck         }
474c2c66affSColin Finck         Res2Acq = UDFIsResourceAcquired(&(NtReqFcb->PagingIoResource));
475c2c66affSColin Finck         if(!Res2Acq) {
476c2c66affSColin Finck             Res2Acq = PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_RES2_ACQ;
477c2c66affSColin Finck         }
478c2c66affSColin Finck 
479c2c66affSColin Finck #if 0
480c2c66affSColin Finck         if(PagingIo) {
481c2c66affSColin Finck             CollectStatistics(Vcb, UserFileReads);
482c2c66affSColin Finck             CollectStatisticsEx(Vcb, UserFileReadBytes, NumberBytesRead);
483c2c66affSColin Finck         }
484c2c66affSColin Finck #endif
485c2c66affSColin Finck 
486c2c66affSColin Finck         // This is a good place for oplock related processing.
487c2c66affSColin Finck 
488c2c66affSColin Finck         // If this is the normal file we have to check for
489c2c66affSColin Finck         // write access according to the current state of the file locks.
490c2c66affSColin Finck         if (!PagingIo &&
491c2c66affSColin Finck             !FsRtlCheckLockForReadAccess( &(NtReqFcb->FileLock), Irp )) {
492c2c66affSColin Finck                 try_return( RC = STATUS_FILE_LOCK_CONFLICT );
493c2c66affSColin Finck         }
494c2c66affSColin Finck 
495c2c66affSColin Finck         // Validate start offset and length supplied.
496c2c66affSColin Finck         //  If start offset is > end-of-file, return an appropriate error. Note
497c2c66affSColin Finck         // that since a FCB resource has already been acquired, and since all
498c2c66affSColin Finck         // file size changes require acquisition of both FCB resources,
499c2c66affSColin Finck         // the contents of the FCB and associated data structures
500c2c66affSColin Finck         // can safely be examined.
501c2c66affSColin Finck 
502c2c66affSColin Finck         //  Also note that we are using the file size in the "Common FCB Header"
503c2c66affSColin Finck         // to perform the check. However, your FSD might decide to keep a
504c2c66affSColin Finck         // separate copy in the FCB (or some other representation of the
505c2c66affSColin Finck         //  file associated with the FCB).
506c2c66affSColin Finck 
507c2c66affSColin Finck         TruncatedLength = ReadLength;
508c2c66affSColin Finck         if (ByteOffset.QuadPart >= NtReqFcb->CommonFCBHeader.FileSize.QuadPart) {
509c2c66affSColin Finck             // Starting offset is >= file size
510c2c66affSColin Finck             try_return(RC = STATUS_END_OF_FILE);
511c2c66affSColin Finck         }
512c2c66affSColin Finck         // We can also go ahead and truncate the read length here
513c2c66affSColin Finck         //  such that it is contained within the file size
514c2c66affSColin Finck         if( NtReqFcb->CommonFCBHeader.FileSize.QuadPart < (ByteOffset.QuadPart + ReadLength) ) {
515c2c66affSColin Finck             TruncatedLength = (ULONG)(NtReqFcb->CommonFCBHeader.FileSize.QuadPart - ByteOffset.QuadPart);
516c2c66affSColin Finck             // we can't get ZERO here
517c2c66affSColin Finck         }
518c2c66affSColin Finck         UDFPrint(("    TruncatedLength = %x\n", TruncatedLength));
519c2c66affSColin Finck 
520c2c66affSColin Finck         // There are certain complications that arise when the same file stream
521c2c66affSColin Finck         // has been opened for cached and non-cached access. The FSD is then
522c2c66affSColin Finck         // responsible for maintaining a consistent view of the data seen by
523c2c66affSColin Finck         // the caller.
524c2c66affSColin Finck         // Also, it is possible for file streams to be mapped in both as data files
525c2c66affSColin Finck         // and as an executable. This could also lead to consistency problems since
526c2c66affSColin Finck         // there now exist two separate sections (and pages) containing file
527c2c66affSColin Finck         // information.
528c2c66affSColin Finck 
529c2c66affSColin Finck         // The test below flushes the data cached in system memory if the current
530c2c66affSColin Finck         // request madates non-cached access (file stream must be cached) and
531c2c66affSColin Finck         // (a) the current request is not paging-io which indicates it is not
532c2c66affSColin Finck         //       a recursive I/O operation OR originating in the Cache Manager
533c2c66affSColin Finck         // (b) OR the current request is paging-io BUT it did not originate via
534c2c66affSColin Finck         //       the Cache Manager (or is a recursive I/O operation) and we do
535c2c66affSColin Finck         //       have an image section that has been initialized.
536c2c66affSColin Finck #define UDF_REQ_NOT_VIA_CACHE_MGR(ptr)  (!MmIsRecursiveIoFault() && ((ptr)->ImageSectionObject != NULL))
537c2c66affSColin Finck 
538c2c66affSColin Finck         if(NonBufferedIo &&
539c2c66affSColin Finck            (NtReqFcb->SectionObject.DataSectionObject != NULL)) {
540c2c66affSColin Finck             if(!PagingIo) {
541c2c66affSColin Finck 
542c2c66affSColin Finck /*                // We hold the main resource exclusive here because the flush
543c2c66affSColin Finck                 // may generate a recursive write in this thread.  The PagingIo
544c2c66affSColin Finck                 // resource is held shared so the drop-and-release serialization
545c2c66affSColin Finck                 // below will work.
546c2c66affSColin Finck                 if(!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
547c2c66affSColin Finck                     try_return(RC = STATUS_PENDING);
548c2c66affSColin Finck                 }
549c2c66affSColin Finck                 PtrResourceAcquired = &(NtReqFcb->MainResource);
550c2c66affSColin Finck 
551c2c66affSColin Finck                 // We hold PagingIo shared around the flush to fix a
552c2c66affSColin Finck                 // cache coherency problem.
553c2c66affSColin Finck                 UDFAcquireResourceShared(&(NtReqFcb->PagingIoResource), TRUE );*/
554c2c66affSColin Finck 
555c2c66affSColin Finck                 MmPrint(("    CcFlushCache()\n"));
556c2c66affSColin Finck                 CcFlushCache(&(NtReqFcb->SectionObject), &ByteOffset, TruncatedLength, &(Irp->IoStatus));
557c2c66affSColin Finck 
558c2c66affSColin Finck /*                UDFReleaseResource(&(NtReqFcb->PagingIoResource));
559c2c66affSColin Finck                 UDFReleaseResource(PtrResourceAcquired);
560c2c66affSColin Finck                 PtrResourceAcquired = NULL;
561c2c66affSColin Finck                 // If the flush failed, return error to the caller
562c2c66affSColin Finck                 if(!NT_SUCCESS(RC = Irp->IoStatus.Status)) {
563c2c66affSColin Finck                     try_return(RC);
564c2c66affSColin Finck                 }
565c2c66affSColin Finck 
566c2c66affSColin Finck                 // Acquiring and immediately dropping the resource serializes
567c2c66affSColin Finck                 // us behind any other writes taking place (either from the
568c2c66affSColin Finck                 // lazy writer or modified page writer).*/
569c2c66affSColin Finck                 if(!Res2Acq) {
570c2c66affSColin Finck                     UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE );
571c2c66affSColin Finck                     UDFReleaseResource(&(NtReqFcb->PagingIoResource));
572c2c66affSColin Finck                 }
573c2c66affSColin Finck             }
574c2c66affSColin Finck         }
575c2c66affSColin Finck 
576c2c66affSColin Finck         // Acquire the appropriate FCB resource shared
577c2c66affSColin Finck         if (PagingIo) {
578c2c66affSColin Finck             // Try to acquire the FCB PagingIoResource shared
579c2c66affSColin Finck             if(!Res2Acq) {
580c2c66affSColin Finck                 if (!UDFAcquireResourceShared(&(NtReqFcb->PagingIoResource), CanWait)) {
581c2c66affSColin Finck                     try_return(RC = STATUS_PENDING);
582c2c66affSColin Finck                 }
583c2c66affSColin Finck                 // Remember the resource that was acquired
584c2c66affSColin Finck                 PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
585c2c66affSColin Finck             }
586c2c66affSColin Finck         } else {
587c2c66affSColin Finck             // Try to acquire the FCB MainResource shared
588c2c66affSColin Finck             if(NonBufferedIo) {
589c2c66affSColin Finck                 if(!Res2Acq) {
590c2c66affSColin Finck                     if(!UDFAcquireSharedWaitForExclusive(&(NtReqFcb->PagingIoResource), CanWait)) {
591c2c66affSColin Finck                         try_return(RC = STATUS_PENDING);
592c2c66affSColin Finck                     }
593c2c66affSColin Finck                     PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
594c2c66affSColin Finck                 }
595c2c66affSColin Finck             } else {
596c2c66affSColin Finck                 if(!Res1Acq) {
597c2c66affSColin Finck                     UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
598c2c66affSColin Finck                     if(!UDFAcquireResourceShared(&(NtReqFcb->MainResource), CanWait)) {
599c2c66affSColin Finck                         try_return(RC = STATUS_PENDING);
600c2c66affSColin Finck                     }
601c2c66affSColin Finck                     // Remember the resource that was acquired
602c2c66affSColin Finck                     PtrResourceAcquired = &(NtReqFcb->MainResource);
603c2c66affSColin Finck                 }
604c2c66affSColin Finck             }
605c2c66affSColin Finck         }
606c2c66affSColin Finck 
607c2c66affSColin Finck         // This is also a good place to set whether fast-io can be performed
608c2c66affSColin Finck         // on this particular file or not. Your FSD must make it's own
609c2c66affSColin Finck         // determination on whether or not to allow fast-io operations.
610c2c66affSColin Finck         // Commonly, fast-io is not allowed if any byte range locks exist
611c2c66affSColin Finck         // on the file or if oplocks prevent fast-io. Practically any reason
612c2c66affSColin Finck         // choosen by your FSD could result in your setting FastIoIsNotPossible
613c2c66affSColin Finck         // OR FastIoIsQuestionable instead of FastIoIsPossible.
614c2c66affSColin Finck 
615c2c66affSColin Finck         NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb);
616c2c66affSColin Finck /*        if(NtReqFcb->CommonFCBHeader.IsFastIoPossible == FastIoIsPossible)
617c2c66affSColin Finck             NtReqFcb->CommonFCBHeader.IsFastIoPossible = FastIoIsQuestionable;*/
618c2c66affSColin Finck 
619c2c66affSColin Finck #ifdef UDF_DISABLE_SYSTEM_CACHE_MANAGER
620c2c66affSColin Finck         NonBufferedIo = TRUE;
621c2c66affSColin Finck #endif
622c2c66affSColin Finck 
623c2c66affSColin Finck         if(Fcb && Fcb->FileInfo && Fcb->FileInfo->Dloc) {
624c2c66affSColin Finck             AdPrint(("UDFCommonRead: DataLoc %x, Mapping %x\n", &Fcb->FileInfo->Dloc->DataLoc, Fcb->FileInfo->Dloc->DataLoc.Mapping));
625c2c66affSColin Finck         }
626c2c66affSColin Finck 
627c2c66affSColin Finck         //  Branch here for cached vs non-cached I/O
628c2c66affSColin Finck         if (!NonBufferedIo) {
629c2c66affSColin Finck 
630c2c66affSColin Finck             if(FileObject->Flags & FO_WRITE_THROUGH) {
631c2c66affSColin Finck                 CanWait = TRUE;
632c2c66affSColin Finck             }
633c2c66affSColin Finck             // The caller wishes to perform cached I/O. Initiate caching if
634c2c66affSColin Finck             // this is the first cached I/O operation using this file object
635c2c66affSColin Finck             if (!(FileObject->PrivateCacheMap)) {
636c2c66affSColin Finck                 // This is the first cached I/O operation. You must ensure
637c2c66affSColin Finck                 // that the FCB Common FCB Header contains valid sizes at this time
638c2c66affSColin Finck                 MmPrint(("    CcInitializeCacheMap()\n"));
639c2c66affSColin Finck                 CcInitializeCacheMap(FileObject, (PCC_FILE_SIZES)(&(NtReqFcb->CommonFCBHeader.AllocationSize)),
640c2c66affSColin Finck                     FALSE,      // We will not utilize pin access for this file
641c2c66affSColin Finck                     &(UDFGlobalData.CacheMgrCallBacks), // callbacks
642c2c66affSColin Finck                     NtReqFcb);        // The context used in callbacks
643c2c66affSColin Finck                 MmPrint(("    CcSetReadAheadGranularity()\n"));
644c2c66affSColin Finck                 CcSetReadAheadGranularity(FileObject, Vcb->SystemCacheGran);
645c2c66affSColin Finck             }
646c2c66affSColin Finck 
647c2c66affSColin Finck             // Check and see if this request requires a MDL returned to the caller
648c2c66affSColin Finck             if (IrpSp->MinorFunction & IRP_MN_MDL) {
649c2c66affSColin Finck                 // Caller does want a MDL returned. Note that this mode
650c2c66affSColin Finck                 // implies that the caller is prepared to block
651c2c66affSColin Finck                 MmPrint(("    CcMdlRead()\n"));
652c2c66affSColin Finck //                CcMdlRead(FileObject, &ByteOffset, TruncatedLength, &(Irp->MdlAddress), &(Irp->IoStatus));
653c2c66affSColin Finck //                NumberBytesRead = Irp->IoStatus.Information;
654c2c66affSColin Finck //                RC = Irp->IoStatus.Status;
655c2c66affSColin Finck                 NumberBytesRead = 0;
656c2c66affSColin Finck                 RC = STATUS_INVALID_PARAMETER;
657c2c66affSColin Finck 
658c2c66affSColin Finck                 try_return(RC);
659c2c66affSColin Finck             }
660c2c66affSColin Finck 
661c2c66affSColin Finck             // This is a regular run-of-the-mill cached I/O request. Let the
662c2c66affSColin Finck             // Cache Manager worry about it!
663c2c66affSColin Finck             // First though, we need a buffer pointer (address) that is valid
664c2c66affSColin Finck             SystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
665c2c66affSColin Finck             if(!SystemBuffer)
666c2c66affSColin Finck                 try_return(RC = STATUS_INVALID_USER_BUFFER);
667c2c66affSColin Finck             ASSERT(SystemBuffer);
668c2c66affSColin Finck             MmPrint(("    CcCopyRead()\n"));
669c2c66affSColin Finck             if (!CcCopyRead(FileObject, &(ByteOffset), TruncatedLength, CanWait, SystemBuffer, &(Irp->IoStatus))) {
670c2c66affSColin Finck                 // The caller was not prepared to block and data is not immediately
671c2c66affSColin Finck                 // available in the system cache
672c2c66affSColin Finck                 try_return(RC = STATUS_PENDING);
673c2c66affSColin Finck             }
674c2c66affSColin Finck 
675c2c66affSColin Finck             UDFUnlockCallersBuffer(PtrIrpContext, Irp, SystemBuffer);
676c2c66affSColin Finck             // We have the data
677c2c66affSColin Finck             RC = Irp->IoStatus.Status;
678c2c66affSColin Finck             NumberBytesRead = Irp->IoStatus.Information;
679c2c66affSColin Finck 
680c2c66affSColin Finck             try_return(RC);
681c2c66affSColin Finck 
682c2c66affSColin Finck         } else {
683c2c66affSColin Finck 
684c2c66affSColin Finck             MmPrint(("    Read NonBufferedIo\n"));
685c2c66affSColin Finck 
686c2c66affSColin Finck #if 1
687*c334c17dSTimo Kreuzer             if((ULONG_PTR)TopIrp == FSRTL_MOD_WRITE_TOP_LEVEL_IRP) {
688c2c66affSColin Finck                 UDFPrint(("FSRTL_MOD_WRITE_TOP_LEVEL_IRP => CanWait\n"));
689c2c66affSColin Finck                 CanWait = TRUE;
690c2c66affSColin Finck             } else
691*c334c17dSTimo Kreuzer             if((ULONG_PTR)TopIrp == FSRTL_CACHE_TOP_LEVEL_IRP) {
692c2c66affSColin Finck                 UDFPrint(("FSRTL_CACHE_TOP_LEVEL_IRP => CanWait\n"));
693c2c66affSColin Finck                 CanWait = TRUE;
694c2c66affSColin Finck             }
695c2c66affSColin Finck 
696c2c66affSColin Finck             if(NtReqFcb->AcqSectionCount || NtReqFcb->AcqFlushCount) {
697c2c66affSColin Finck                 MmPrint(("    AcqCount (%d/%d)=> CanWait ?\n", NtReqFcb->AcqSectionCount, NtReqFcb->AcqFlushCount));
698c2c66affSColin Finck                 CanWait = TRUE;
699c2c66affSColin Finck             } else
700c2c66affSColin Finck             {}
701c2c66affSColin Finck /*            if((TopIrp != Irp)) {
702c2c66affSColin Finck                 UDFPrint(("(TopIrp != Irp) => CanWait\n"));
703c2c66affSColin Finck                 CanWait = TRUE;
704c2c66affSColin Finck             } else*/
705c2c66affSColin Finck #endif
706c2c66affSColin Finck             if(KeGetCurrentIrql() > PASSIVE_LEVEL) {
707c2c66affSColin Finck                 MmPrint(("    !PASSIVE_LEVEL\n"));
708c2c66affSColin Finck                 CanWait = FALSE;
709c2c66affSColin Finck                 PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FORCED_POST;
710c2c66affSColin Finck             }
711c2c66affSColin Finck             if(!CanWait && UDFIsFileCached__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength, FALSE)) {
712c2c66affSColin Finck                 MmPrint(("    Locked => CanWait\n"));
713c2c66affSColin Finck                 CacheLocked = TRUE;
714c2c66affSColin Finck                 CanWait = TRUE;
715c2c66affSColin Finck             }
716c2c66affSColin Finck 
717c2c66affSColin Finck             // Send the request to lower level drivers
718c2c66affSColin Finck             if(!CanWait) {
719c2c66affSColin Finck                 try_return(RC = STATUS_PENDING);
720c2c66affSColin Finck             }
721c2c66affSColin Finck 
722c2c66affSColin Finck //                ASSERT(NT_SUCCESS(RC));
723c2c66affSColin Finck             if(!Res2Acq) {
724c2c66affSColin Finck                 if(UDFAcquireResourceSharedWithCheck(&(NtReqFcb->PagingIoResource)))
725c2c66affSColin Finck                     PtrResourceAcquired2 = &(NtReqFcb->PagingIoResource);
726c2c66affSColin Finck             }
727c2c66affSColin Finck 
728c2c66affSColin Finck             RC = UDFLockCallersBuffer(PtrIrpContext, Irp, TRUE, TruncatedLength);
729c2c66affSColin Finck             if(!NT_SUCCESS(RC)) {
730c2c66affSColin Finck                 try_return(RC);
731c2c66affSColin Finck             }
732c2c66affSColin Finck 
733c2c66affSColin Finck             SystemBuffer = UDFGetCallersBuffer(PtrIrpContext, Irp);
734c2c66affSColin Finck             if(!SystemBuffer) {
735c2c66affSColin Finck                 try_return(RC = STATUS_INVALID_USER_BUFFER);
736c2c66affSColin Finck             }
737c2c66affSColin Finck 
738c2c66affSColin Finck             RC = UDFReadFile__(Vcb, Fcb->FileInfo, ByteOffset.QuadPart, TruncatedLength,
739c2c66affSColin Finck                            CacheLocked, (PCHAR)SystemBuffer, &NumberBytesRead);
740c2c66affSColin Finck /*                // AFAIU, CacheManager wants this:
741c2c66affSColin Finck             if(!NT_SUCCESS(RC)) {
742c2c66affSColin Finck                 NumberBytesRead = 0;
743c2c66affSColin Finck             }*/
744c2c66affSColin Finck 
745c2c66affSColin Finck             UDFUnlockCallersBuffer(PtrIrpContext, Irp, SystemBuffer);
746c2c66affSColin Finck 
747c2c66affSColin Finck #if 0
748c2c66affSColin Finck             if(PagingIo) {
749c2c66affSColin Finck                 CollectStatistics(Vcb, UserDiskReads);
750c2c66affSColin Finck             } else {
751c2c66affSColin Finck                 CollectStatistics2(Vcb, NonCachedDiskReads);
752c2c66affSColin Finck             }
753c2c66affSColin Finck #endif
754c2c66affSColin Finck 
755c2c66affSColin Finck             try_return(RC);
756c2c66affSColin Finck 
757c2c66affSColin Finck             // For paging-io, the FSD has to trust the VMM to do the right thing
758c2c66affSColin Finck 
759c2c66affSColin Finck             // Here is a common method used by Windows NT native file systems
760c2c66affSColin Finck             // that are in the process of sending a request to the disk driver.
761c2c66affSColin Finck             // First, mark the IRP as pending, then invoke the lower level driver
762c2c66affSColin Finck             // after setting a completion routine.
763c2c66affSColin Finck             // Meanwhile, this particular thread can immediately return a
764c2c66affSColin Finck             // STATUS_PENDING return code.
765c2c66affSColin Finck             // The completion routine is then responsible for completing the IRP
766c2c66affSColin Finck             // and unlocking appropriate resources
767c2c66affSColin Finck 
768c2c66affSColin Finck             // Also, at this point, the FSD might choose to utilize the
769c2c66affSColin Finck             // information contained in the ValidDataLength field to simply
770c2c66affSColin Finck             // return zeroes to the caller for reads extending beyond current
771c2c66affSColin Finck             // valid data length.
772c2c66affSColin Finck 
773c2c66affSColin Finck         }
774c2c66affSColin Finck 
775c2c66affSColin Finck try_exit:   NOTHING;
776c2c66affSColin Finck 
777c2c66affSColin Finck     } _SEH2_FINALLY {
778c2c66affSColin Finck 
779c2c66affSColin Finck         if(CacheLocked) {
780c2c66affSColin Finck             WCacheEODirect__(&(Vcb->FastCache), Vcb);
781c2c66affSColin Finck         }
782c2c66affSColin Finck 
783c2c66affSColin Finck         // Release any resources acquired here ...
784c2c66affSColin Finck         if(PtrResourceAcquired2) {
785c2c66affSColin Finck             UDFReleaseResource(PtrResourceAcquired2);
786c2c66affSColin Finck         }
787c2c66affSColin Finck         if(PtrResourceAcquired) {
788c2c66affSColin Finck             if(NtReqFcb &&
789c2c66affSColin Finck                (PtrResourceAcquired ==
790c2c66affSColin Finck                 &(NtReqFcb->MainResource))) {
791c2c66affSColin Finck                 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
792c2c66affSColin Finck             }
793c2c66affSColin Finck             UDFReleaseResource(PtrResourceAcquired);
794c2c66affSColin Finck         }
795c2c66affSColin Finck 
796c2c66affSColin Finck         // Post IRP if required
797c2c66affSColin Finck         if(RC == STATUS_PENDING) {
798c2c66affSColin Finck 
799c2c66affSColin Finck             // Lock the callers buffer here. Then invoke a common routine to
800c2c66affSColin Finck             // perform the post operation.
801c2c66affSColin Finck             if (!(IrpSp->MinorFunction & IRP_MN_MDL)) {
802c2c66affSColin Finck                 RC = UDFLockCallersBuffer(PtrIrpContext, Irp, TRUE, ReadLength);
803c2c66affSColin Finck                 ASSERT(NT_SUCCESS(RC));
804c2c66affSColin Finck             }
805c2c66affSColin Finck             if(PagingIo) {
806c2c66affSColin Finck                 if(Res1Acq) {
807c2c66affSColin Finck                     PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_RES1_ACQ;
808c2c66affSColin Finck                 }
809c2c66affSColin Finck                 if(Res2Acq) {
810c2c66affSColin Finck                     PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_RES2_ACQ;
811c2c66affSColin Finck                 }
812c2c66affSColin Finck             }
813c2c66affSColin Finck             // Perform the post operation which will mark the IRP pending
814c2c66affSColin Finck             // and will return STATUS_PENDING back to us
815c2c66affSColin Finck             RC = UDFPostRequest(PtrIrpContext, Irp);
816c2c66affSColin Finck 
817c2c66affSColin Finck         } else {
818c2c66affSColin Finck             // For synchronous I/O, the FSD must maintain the current byte offset
819c2c66affSColin Finck             // Do not do this however, if I/O is marked as paging-io
820c2c66affSColin Finck             if (SynchronousIo && !PagingIo && NT_SUCCESS(RC)) {
821c2c66affSColin Finck                 FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + NumberBytesRead;
822c2c66affSColin Finck             }
823c2c66affSColin Finck             // If the read completed successfully and this was not a paging-io
824c2c66affSColin Finck             // operation, set a flag in the CCB that indicates that a read was
825c2c66affSColin Finck             // performed and that the file time should be updated at cleanup
826c2c66affSColin Finck             if (NT_SUCCESS(RC) && !PagingIo) {
827c2c66affSColin Finck                 FileObject->Flags |= FO_FILE_FAST_IO_READ;
828c2c66affSColin Finck                 Ccb->CCBFlags |= UDF_CCB_ACCESSED;
829c2c66affSColin Finck             }
830c2c66affSColin Finck 
831c2c66affSColin Finck             if(!_SEH2_AbnormalTermination()) {
832c2c66affSColin Finck                 Irp->IoStatus.Status = RC;
833c2c66affSColin Finck                 Irp->IoStatus.Information = NumberBytesRead;
834c2c66affSColin Finck                 UDFPrint(("    NumberBytesRead = %x\n", NumberBytesRead));
835c2c66affSColin Finck                 // Free up the Irp Context
836c2c66affSColin Finck                 UDFReleaseIrpContext(PtrIrpContext);
837c2c66affSColin Finck                 // complete the IRP
838c2c66affSColin Finck                 MmPrint(("    Complete Irp, MDL=%x\n", Irp->MdlAddress));
839c2c66affSColin Finck                 if(Irp->MdlAddress) {
840c2c66affSColin Finck                     UDFTouch(Irp->MdlAddress);
841c2c66affSColin Finck                 }
842c2c66affSColin Finck                 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
843c2c66affSColin Finck             }
844c2c66affSColin Finck         } // can we complete the IRP ?
845c2c66affSColin Finck     } _SEH2_END; // end of "__finally" processing
846c2c66affSColin Finck 
847c2c66affSColin Finck     return(RC);
848c2c66affSColin Finck } // end UDFCommonRead()
849c2c66affSColin Finck 
850c2c66affSColin Finck 
851c2c66affSColin Finck #ifdef UDF_DBG
852c2c66affSColin Finck ULONG LockBufferCounter = 0;
853c2c66affSColin Finck ULONG BuildMdlCounter = 0;
854c2c66affSColin Finck #endif //UDF_DBG
855c2c66affSColin Finck 
856c2c66affSColin Finck /*************************************************************************
857c2c66affSColin Finck *
858c2c66affSColin Finck * Function: UDFGetCallersBuffer()
859c2c66affSColin Finck *
860c2c66affSColin Finck * Description:
861c2c66affSColin Finck *   Obtain a pointer to the caller's buffer.
862c2c66affSColin Finck *
863c2c66affSColin Finck * Expected Interrupt Level (for execution) :
864c2c66affSColin Finck *
865c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
866c2c66affSColin Finck *
867c2c66affSColin Finck * Return Value: STATUS_SUCCESS/Error
868c2c66affSColin Finck *
869c2c66affSColin Finck *************************************************************************/
870c2c66affSColin Finck PVOID
UDFGetCallersBuffer(PtrUDFIrpContext PtrIrpContext,PIRP Irp)871c2c66affSColin Finck UDFGetCallersBuffer(
872c2c66affSColin Finck     PtrUDFIrpContext PtrIrpContext,
873c2c66affSColin Finck     PIRP             Irp
874c2c66affSColin Finck     )
875c2c66affSColin Finck {
876c2c66affSColin Finck     VOID            *ReturnedBuffer = NULL;
877c2c66affSColin Finck 
878c2c66affSColin Finck     UDFPrint(("UDFGetCallersBuffer: \n"));
879c2c66affSColin Finck 
880c2c66affSColin Finck     // If an MDL is supplied, use it.
881c2c66affSColin Finck     if(Irp->MdlAddress) {
882c2c66affSColin Finck         MmPrint(("    UDFGetCallersBuffer: MmGetSystemAddressForMdl(Irp->MdlAddress) MDL=%x\n", Irp->MdlAddress));
883c2c66affSColin Finck //        ReturnedBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
884c2c66affSColin Finck         ReturnedBuffer = MmGetSystemAddressForMdlSafer(Irp->MdlAddress);
885c2c66affSColin Finck     } else
886c2c66affSColin Finck     if (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_BUFFER_LOCKED) {
887c2c66affSColin Finck         // Free buffer
888c2c66affSColin Finck #ifndef POST_LOCK_PAGES
889c2c66affSColin Finck         MmPrint(("    UDFGetCallersBuffer: MmGetSystemAddressForMdl(PtrIrpContext->PtrMdl) MDL=%x\n", PtrIrpContext->PtrMdl));
890c2c66affSColin Finck         ReturnedBuffer = MmGetSystemAddressForMdlSafe(PtrIrpContext->PtrMdl, NormalPagePriority);
891c2c66affSColin Finck #else //POST_LOCK_PAGES
892c2c66affSColin Finck             if(PtrIrpContext->TransitionBuffer) {
893c2c66affSColin Finck                 MmPrint(("    UDFGetCallersBuffer: TransitionBuffer\n"));
894c2c66affSColin Finck                 return PtrIrpContext->TransitionBuffer;
895c2c66affSColin Finck             }
896c2c66affSColin Finck 
897c2c66affSColin Finck             _SEH2_TRY {
898c2c66affSColin Finck                 MmPrint(("    MmProbeAndLockPages()\n"));
899c2c66affSColin Finck                 MmProbeAndLockPages(PtrIrpContext->PtrMdl, Irp->RequestorMode,
900c2c66affSColin Finck                                     ((PtrIrpContext->MajorFunction == IRP_MJ_READ) ? IoWriteAccess:IoReadAccess));
901c2c66affSColin Finck #ifdef UDF_DBG
902c2c66affSColin Finck                 LockBufferCounter++;
903c2c66affSColin Finck #endif //UDF_DBG
904c2c66affSColin Finck             } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
905c2c66affSColin Finck                 //RC = STATUS_INVALID_USER_BUFFER;
906c2c66affSColin Finck                 BrutePoint();
907c2c66affSColin Finck                 return NULL;
908c2c66affSColin Finck             } _SEH2_END;
909c2c66affSColin Finck 
910c2c66affSColin Finck             MmPrint(("    MmGetSystemAddressForMdlSafer()\n"));
911c2c66affSColin Finck         ReturnedBuffer = MmGetSystemAddressForMdlSafer(PtrIrpContext->PtrMdl);
912c2c66affSColin Finck #endif //POST_LOCK_PAGES
913c2c66affSColin Finck     } else {
914c2c66affSColin Finck         MmPrint(("    UDFGetCallersBuffer: Irp->UserBuffer\n"));
915c2c66affSColin Finck         ReturnedBuffer = Irp->UserBuffer;
916c2c66affSColin Finck     }
917c2c66affSColin Finck 
918c2c66affSColin Finck     return(ReturnedBuffer);
919c2c66affSColin Finck } // end UDFGetCallersBuffer()
920c2c66affSColin Finck 
921c2c66affSColin Finck /*************************************************************************
922c2c66affSColin Finck *
923c2c66affSColin Finck * Function: UDFLockCallersBuffer()
924c2c66affSColin Finck *
925c2c66affSColin Finck * Description:
926c2c66affSColin Finck *   Obtain a MDL that describes the buffer. Lock pages for I/O
927c2c66affSColin Finck *
928c2c66affSColin Finck * Expected Interrupt Level (for execution) :
929c2c66affSColin Finck *
930c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
931c2c66affSColin Finck *
932c2c66affSColin Finck * Return Value: STATUS_SUCCESS/Error
933c2c66affSColin Finck *
934c2c66affSColin Finck *************************************************************************/
935c2c66affSColin Finck NTSTATUS
UDFLockCallersBuffer(PtrUDFIrpContext PtrIrpContext,PIRP Irp,BOOLEAN IsReadOperation,uint32 Length)936c2c66affSColin Finck UDFLockCallersBuffer(
937c2c66affSColin Finck     PtrUDFIrpContext  PtrIrpContext,
938c2c66affSColin Finck     PIRP              Irp,
939c2c66affSColin Finck     BOOLEAN           IsReadOperation,
940c2c66affSColin Finck     uint32            Length
941c2c66affSColin Finck     )
942c2c66affSColin Finck {
943c2c66affSColin Finck     NTSTATUS            RC = STATUS_SUCCESS;
944c2c66affSColin Finck     PMDL                PtrMdl = NULL;
945c2c66affSColin Finck 
946c2c66affSColin Finck     UDFPrint(("UDFLockCallersBuffer: \n"));
947c2c66affSColin Finck 
948c2c66affSColin Finck     ASSERT(Irp);
949c2c66affSColin Finck 
950c2c66affSColin Finck     _SEH2_TRY {
951c2c66affSColin Finck         // Is a MDL already present in the IRP
952c2c66affSColin Finck         if (!(Irp->MdlAddress)) {
953c2c66affSColin Finck             // Allocate a MDL
954c2c66affSColin Finck /*
955c2c66affSColin Finck             if(!IsReadOperation) {
956c2c66affSColin Finck                 MmPrint(("  Allocate TransitionBuffer\n"));
957c2c66affSColin Finck                 PtrIrpContext->TransitionBuffer = (PCHAR)DbgAllocatePool(NonPagedPool, Length);
958c2c66affSColin Finck                 if(!PtrIrpContext->TransitionBuffer) {
959c2c66affSColin Finck                     RC = STATUS_INSUFFICIENT_RESOURCES;
960c2c66affSColin Finck                     try_return(RC);
961c2c66affSColin Finck                 }
962c2c66affSColin Finck                 _SEH2_TRY {
963c2c66affSColin Finck                     RtlCopyMemory(PtrIrpContext->TransitionBuffer, Irp->UserBuffer, Length);
964c2c66affSColin Finck                 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
965c2c66affSColin Finck                     RC = STATUS_INVALID_USER_BUFFER;
966c2c66affSColin Finck                 } _SEH2_END;
967c2c66affSColin Finck             } else*/ {
968c2c66affSColin Finck 
969c2c66affSColin Finck                 MmPrint(("  IoAllocateMdl()\n"));
970c2c66affSColin Finck //                if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, NULL))) {
971c2c66affSColin Finck 
972c2c66affSColin Finck                 // This will place allocated Mdl to Irp
973c2c66affSColin Finck                 if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp))) {
974c2c66affSColin Finck                     RC = STATUS_INSUFFICIENT_RESOURCES;
975c2c66affSColin Finck                     try_return(RC);
976c2c66affSColin Finck                 }
977c2c66affSColin Finck                 MmPrint(("    Alloc MDL=%x\n", PtrMdl));
978c2c66affSColin Finck #ifdef UDF_DBG
979c2c66affSColin Finck                 BuildMdlCounter++;
980c2c66affSColin Finck #endif //UDF_DBG
981c2c66affSColin Finck             }
982c2c66affSColin Finck             // Probe and lock the pages described by the MDL
983c2c66affSColin Finck             // We could encounter an exception doing so, swallow the exception
984c2c66affSColin Finck             // NOTE: The exception could be due to an unexpected (from our
985c2c66affSColin Finck             // perspective), invalidation of the virtual addresses that comprise
986c2c66affSColin Finck             // the passed in buffer
987c2c66affSColin Finck #ifndef POST_LOCK_PAGES
988c2c66affSColin Finck             _SEH2_TRY {
989c2c66affSColin Finck                 MmPrint(("    MmProbeAndLockPages()\n"));
990c2c66affSColin Finck                 MmProbeAndLockPages(PtrMdl, Irp->RequestorMode, (IsReadOperation ? IoWriteAccess:IoReadAccess));
991c2c66affSColin Finck             } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
992c2c66affSColin Finck                 MmPrint(("    MmProbeAndLockPages() failed\n"));
993c2c66affSColin Finck                 Irp->MdlAddress = NULL;
994c2c66affSColin Finck                 RC = STATUS_INVALID_USER_BUFFER;
995c2c66affSColin Finck             } _SEH2_END;
996c2c66affSColin Finck #endif //POST_LOCK_PAGES
997c2c66affSColin Finck 
998c2c66affSColin Finck             if(NT_SUCCESS(RC)) {
999c2c66affSColin Finck                 PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_BUFFER_LOCKED;
1000c2c66affSColin Finck                 PtrIrpContext->PtrMdl = PtrMdl;
1001c2c66affSColin Finck             }
1002c2c66affSColin Finck         } else {
1003c2c66affSColin Finck             MmPrint(("    UDFLockCallersBuffer: do nothing, MDL=%x\n", Irp->MdlAddress));
1004c2c66affSColin Finck             UDFTouch(Irp->MdlAddress);
1005c2c66affSColin Finck         }
1006c2c66affSColin Finck 
1007c2c66affSColin Finck try_exit:   NOTHING;
1008c2c66affSColin Finck 
1009c2c66affSColin Finck     } _SEH2_FINALLY {
1010c2c66affSColin Finck         if (!NT_SUCCESS(RC) && PtrMdl) {
1011c2c66affSColin Finck             MmPrint(("    Free MDL=%x\n", PtrMdl));
1012c2c66affSColin Finck             IoFreeMdl(PtrMdl);
1013c2c66affSColin Finck         }
1014c2c66affSColin Finck     } _SEH2_END;
1015c2c66affSColin Finck 
1016c2c66affSColin Finck     return(RC);
1017c2c66affSColin Finck } // end UDFLockCallersBuffer()
1018c2c66affSColin Finck 
1019c2c66affSColin Finck /*************************************************************************
1020c2c66affSColin Finck *
1021c2c66affSColin Finck * Function: UDFUnlockCallersBuffer()
1022c2c66affSColin Finck *
1023c2c66affSColin Finck * Description:
1024c2c66affSColin Finck *   Obtain a MDL that describes the buffer. Lock pages for I/O
1025c2c66affSColin Finck *
1026c2c66affSColin Finck * Expected Interrupt Level (for execution) :
1027c2c66affSColin Finck *
1028c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
1029c2c66affSColin Finck *
1030c2c66affSColin Finck * Return Value: STATUS_SUCCESS/Error
1031c2c66affSColin Finck *
1032c2c66affSColin Finck *************************************************************************/
1033c2c66affSColin Finck NTSTATUS
UDFUnlockCallersBuffer(PtrUDFIrpContext PtrIrpContext,PIRP Irp,PVOID SystemBuffer)1034c2c66affSColin Finck UDFUnlockCallersBuffer(
1035c2c66affSColin Finck     PtrUDFIrpContext PtrIrpContext,
1036c2c66affSColin Finck     PIRP    Irp,
1037c2c66affSColin Finck     PVOID   SystemBuffer
1038c2c66affSColin Finck     )
1039c2c66affSColin Finck {
1040c2c66affSColin Finck     NTSTATUS            RC = STATUS_SUCCESS;
1041c2c66affSColin Finck 
1042c2c66affSColin Finck     UDFPrint(("UDFUnlockCallersBuffer: \n"));
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     ASSERT(Irp);
1045c2c66affSColin Finck 
1046c2c66affSColin Finck     _SEH2_TRY {
1047c2c66affSColin Finck         // Is a nonPaged buffer already present in the IRP
1048c2c66affSColin Finck         if (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_BUFFER_LOCKED) {
1049c2c66affSColin Finck 
1050c2c66affSColin Finck             UDFPrint(("  UDF_IRP_CONTEXT_BUFFER_LOCKED MDL=%x, Irp MDL=%x\n", PtrIrpContext->PtrMdl, Irp->MdlAddress));
1051c2c66affSColin Finck             if(PtrIrpContext->TransitionBuffer) {
1052c2c66affSColin Finck                 MmPrint(("    UDFUnlockCallersBuffer: free TransitionBuffer\n"));
1053c2c66affSColin Finck                 DbgFreePool(PtrIrpContext->TransitionBuffer);
1054c2c66affSColin Finck                 PtrIrpContext->TransitionBuffer = NULL;
1055c2c66affSColin Finck                 PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_BUFFER_LOCKED;
1056c2c66affSColin Finck                 try_return(RC);
1057c2c66affSColin Finck             }
1058c2c66affSColin Finck             // Free buffer
1059c2c66affSColin Finck             KeFlushIoBuffers( PtrIrpContext->PtrMdl, TRUE, FALSE );
1060c2c66affSColin Finck //            MmPrint(("    IrpCtx->Mdl, MmUnmapLockedPages()\n"));
1061c2c66affSColin Finck //            MmUnmapLockedPages(SystemBuffer, PtrIrpContext->PtrMdl);
1062c2c66affSColin Finck 
1063c2c66affSColin Finck             // This will be done in IoCompleteIrp !!!
1064c2c66affSColin Finck 
1065c2c66affSColin Finck             //MmPrint(("    MmUnlockPages()\n"));
1066c2c66affSColin Finck             //MmUnlockPages(PtrIrpContext->PtrMdl);
1067c2c66affSColin Finck 
1068c2c66affSColin Finck #ifdef UDF_DBG
1069c2c66affSColin Finck             LockBufferCounter--;
1070c2c66affSColin Finck #endif //UDF_DBG
1071c2c66affSColin Finck 
1072c2c66affSColin Finck             // This will be done in IoCompleteIrp !!!
1073c2c66affSColin Finck 
1074c2c66affSColin Finck             //IoFreeMdl(PtrIrpContext->PtrMdl);
1075c2c66affSColin Finck 
1076c2c66affSColin Finck #ifdef UDF_DBG
1077c2c66affSColin Finck             BuildMdlCounter--;
1078c2c66affSColin Finck #endif //UDF_DBG
1079c2c66affSColin Finck             UDFTouch(PtrIrpContext->PtrMdl);
1080c2c66affSColin Finck             PtrIrpContext->PtrMdl = NULL;
1081c2c66affSColin Finck             PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_BUFFER_LOCKED;
1082c2c66affSColin Finck         } else
1083c2c66affSColin Finck         if(Irp->MdlAddress) {
1084c2c66affSColin Finck //            MmPrint(("    Irp->Mdl, MmUnmapLockedPages()\n"));
1085c2c66affSColin Finck //            MmUnmapLockedPages(SystemBuffer, Irp->MdlAddress);
1086c2c66affSColin Finck             UDFPrint(("  UDF_IRP_CONTEXT_BUFFER_LOCKED MDL=%x, Irp MDL=%x\n", PtrIrpContext->PtrMdl, Irp->MdlAddress));
1087c2c66affSColin Finck             UDFTouch(Irp->MdlAddress);
1088c2c66affSColin Finck             KeFlushIoBuffers( Irp->MdlAddress,
1089c2c66affSColin Finck                               ((IoGetCurrentIrpStackLocation(Irp))->MajorFunction) == IRP_MJ_READ,
1090c2c66affSColin Finck                               FALSE );
1091c2c66affSColin Finck         } else
1092c2c66affSColin Finck         { ; }
1093c2c66affSColin Finck 
1094c2c66affSColin Finck try_exit:   NOTHING;
1095c2c66affSColin Finck 
1096c2c66affSColin Finck     } _SEH2_FINALLY {
1097c2c66affSColin Finck         NOTHING;
1098c2c66affSColin Finck     } _SEH2_END;
1099c2c66affSColin Finck 
1100c2c66affSColin Finck     return(RC);
1101c2c66affSColin Finck } // end UDFUnlockCallersBuffer()
1102c2c66affSColin Finck 
1103c2c66affSColin Finck /*************************************************************************
1104c2c66affSColin Finck *
1105c2c66affSColin Finck * Function: UDFMdlComplete()
1106c2c66affSColin Finck *
1107c2c66affSColin Finck * Description:
1108c2c66affSColin Finck *   Tell Cache Manager to release MDL (and possibly flush).
1109c2c66affSColin Finck *
1110c2c66affSColin Finck * Expected Interrupt Level (for execution) :
1111c2c66affSColin Finck *
1112c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
1113c2c66affSColin Finck *
1114c2c66affSColin Finck * Return Value: None.
1115c2c66affSColin Finck *
1116c2c66affSColin Finck *************************************************************************/
UDFMdlComplete(PtrUDFIrpContext PtrIrpContext,PIRP Irp,PIO_STACK_LOCATION IrpSp,BOOLEAN ReadCompletion)1117c2c66affSColin Finck VOID UDFMdlComplete(
1118c2c66affSColin Finck PtrUDFIrpContext            PtrIrpContext,
1119c2c66affSColin Finck PIRP                        Irp,
1120c2c66affSColin Finck PIO_STACK_LOCATION          IrpSp,
1121c2c66affSColin Finck BOOLEAN                     ReadCompletion)
1122c2c66affSColin Finck {
1123c2c66affSColin Finck     NTSTATUS                RC = STATUS_SUCCESS;
1124c2c66affSColin Finck     PFILE_OBJECT            FileObject = NULL;
1125c2c66affSColin Finck 
1126c2c66affSColin Finck     UDFPrint(("UDFMdlComplete: \n"));
1127c2c66affSColin Finck 
1128c2c66affSColin Finck     FileObject = IrpSp->FileObject;
1129c2c66affSColin Finck     ASSERT(FileObject);
1130c2c66affSColin Finck 
1131c2c66affSColin Finck     UDFTouch(Irp->MdlAddress);
1132c2c66affSColin Finck     // Not much to do here.
1133c2c66affSColin Finck     if (ReadCompletion) {
1134c2c66affSColin Finck         MmPrint(("    CcMdlReadComplete() MDL=%x\n", Irp->MdlAddress));
1135c2c66affSColin Finck         CcMdlReadComplete(FileObject, Irp->MdlAddress);
1136c2c66affSColin Finck     } else {
1137c2c66affSColin Finck         // The Cache Manager needs the byte offset in the I/O stack location.
1138c2c66affSColin Finck         MmPrint(("    CcMdlWriteComplete() MDL=%x\n", Irp->MdlAddress));
1139c2c66affSColin Finck         CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
1140c2c66affSColin Finck     }
1141c2c66affSColin Finck 
1142c2c66affSColin Finck     // Clear the MDL address field in the IRP so the IoCompleteRequest()
1143c2c66affSColin Finck     // does not __try to play around with the MDL.
1144c2c66affSColin Finck     Irp->MdlAddress = NULL;
1145c2c66affSColin Finck 
1146c2c66affSColin Finck     // Free up the Irp Context.
1147c2c66affSColin Finck     UDFReleaseIrpContext(PtrIrpContext);
1148c2c66affSColin Finck 
1149c2c66affSColin Finck     // Complete the IRP.
1150c2c66affSColin Finck     Irp->IoStatus.Status = RC;
1151c2c66affSColin Finck     Irp->IoStatus.Information = 0;
1152c2c66affSColin Finck     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1153c2c66affSColin Finck 
1154c2c66affSColin Finck     return;
1155c2c66affSColin Finck }
1156