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