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  Module Name: FsCntrl.cpp
9c2c66affSColin Finck 
10c2c66affSColin Finck  Abstract:
11c2c66affSColin Finck 
12c2c66affSColin Finck     Contains code to handle the "File System IOCTL" dispatch entry point.
13c2c66affSColin Finck 
14c2c66affSColin Finck  Environment:
15c2c66affSColin Finck 
16c2c66affSColin Finck     Kernel mode only
17c2c66affSColin Finck 
18c2c66affSColin Finck */
19c2c66affSColin Finck 
20c2c66affSColin Finck #include            "udffs.h"
21c2c66affSColin Finck 
22c2c66affSColin Finck // define the file specific bug-check id
23c2c66affSColin Finck #define         UDF_BUG_CHECK_ID    UDF_FILE_FS_CONTROL
24c2c66affSColin Finck 
25c2c66affSColin Finck NTSTATUS UDFBlankMount(IN PVCB Vcb);
26c2c66affSColin Finck 
27c2c66affSColin Finck PDIR_INDEX_HDR UDFDirIndexAlloc(IN uint_di i);
28c2c66affSColin Finck 
29c2c66affSColin Finck /*
30c2c66affSColin Finck  Function: UDFFSControl()
31c2c66affSColin Finck 
32c2c66affSColin Finck  Description:
33c2c66affSColin Finck     The I/O Manager will invoke this routine to handle a File System
34c2c66affSColin Finck     Control request (this is IRP_MJ_FILE_SYSTEM_CONTROL dispatch point)
35c2c66affSColin Finck 
36c2c66affSColin Finck */
37c2c66affSColin Finck NTSTATUS
38c2c66affSColin Finck NTAPI
UDFFSControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)39c2c66affSColin Finck UDFFSControl(
40c2c66affSColin Finck     PDEVICE_OBJECT      DeviceObject,      // the logical volume device object
41c2c66affSColin Finck     PIRP                Irp                // I/O Request Packet
42c2c66affSColin Finck     )
43c2c66affSColin Finck {
44c2c66affSColin Finck     NTSTATUS            RC = STATUS_SUCCESS;
45c2c66affSColin Finck     PtrUDFIrpContext    PtrIrpContext;
46c2c66affSColin Finck     BOOLEAN             AreWeTopLevel = FALSE;
47c2c66affSColin Finck 
48c2c66affSColin Finck     UDFPrint(("\nUDFFSControl: \n\n"));
49c2c66affSColin Finck 
50c2c66affSColin Finck     FsRtlEnterFileSystem();
51c2c66affSColin Finck     ASSERT(DeviceObject);
52c2c66affSColin Finck     ASSERT(Irp);
53c2c66affSColin Finck 
54c2c66affSColin Finck     // set the top level context
55c2c66affSColin Finck     AreWeTopLevel = UDFIsIrpTopLevel(Irp);
56c2c66affSColin Finck 
57c2c66affSColin Finck     _SEH2_TRY {
58c2c66affSColin Finck 
59c2c66affSColin Finck         // get an IRP context structure and issue the request
60c2c66affSColin Finck         PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
61c2c66affSColin Finck         if(PtrIrpContext) {
62c2c66affSColin Finck             RC = UDFCommonFSControl(PtrIrpContext, Irp);
63c2c66affSColin Finck         } else {
64c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
65c2c66affSColin Finck             Irp->IoStatus.Status = RC;
66c2c66affSColin Finck             Irp->IoStatus.Information = 0;
67c2c66affSColin Finck             // complete the IRP
68c2c66affSColin Finck             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
69c2c66affSColin Finck         }
70c2c66affSColin Finck 
71c2c66affSColin Finck     } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
72c2c66affSColin Finck 
73c2c66affSColin Finck         UDFPrintErr(("UDFFSControl: exception ***"));
74c2c66affSColin Finck         RC = UDFExceptionHandler(PtrIrpContext, Irp);
75c2c66affSColin Finck 
76c2c66affSColin Finck         UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
77c2c66affSColin Finck     } _SEH2_END;
78c2c66affSColin Finck 
79c2c66affSColin Finck     if(AreWeTopLevel) {
80c2c66affSColin Finck         IoSetTopLevelIrp(NULL);
81c2c66affSColin Finck     }
82c2c66affSColin Finck 
83c2c66affSColin Finck     FsRtlExitFileSystem();
84c2c66affSColin Finck 
85c2c66affSColin Finck     return(RC);
86c2c66affSColin Finck } // end UDFFSControl()
87c2c66affSColin Finck 
88c2c66affSColin Finck /*
89c2c66affSColin Finck  Function: UDFCommonFSControl()
90c2c66affSColin Finck 
91c2c66affSColin Finck  Description:
92c2c66affSColin Finck     The actual work is performed here.
93c2c66affSColin Finck 
94c2c66affSColin Finck  Expected Interrupt Level (for execution) :
95c2c66affSColin Finck   IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
96c2c66affSColin Finck     to be deferred to a worker thread context)
97c2c66affSColin Finck 
98c2c66affSColin Finck  Return Value: STATUS_SUCCESS/Error
99c2c66affSColin Finck */
100c2c66affSColin Finck 
101c2c66affSColin Finck NTSTATUS
102c2c66affSColin Finck NTAPI
UDFCommonFSControl(PtrUDFIrpContext PtrIrpContext,PIRP Irp)103c2c66affSColin Finck UDFCommonFSControl(
104c2c66affSColin Finck     PtrUDFIrpContext    PtrIrpContext,
105c2c66affSColin Finck     PIRP                Irp                // I/O Request Packet
106c2c66affSColin Finck     )
107c2c66affSColin Finck {
108c2c66affSColin Finck     NTSTATUS                RC = STATUS_UNRECOGNIZED_VOLUME;
109c2c66affSColin Finck     PIO_STACK_LOCATION      IrpSp = NULL;
110c2c66affSColin Finck //    PDEVICE_OBJECT          PtrTargetDeviceObject = NULL;
111c2c66affSColin Finck 
112c2c66affSColin Finck     UDFPrint(("\nUDFCommonFSControl\n\n"));
113c2c66affSColin Finck //    BrutePoint();
114c2c66affSColin Finck 
115c2c66affSColin Finck     _SEH2_TRY {
116c2c66affSColin Finck 
117c2c66affSColin Finck         IrpSp = IoGetCurrentIrpStackLocation(Irp);
118c2c66affSColin Finck         ASSERT(IrpSp);
119c2c66affSColin Finck 
120c2c66affSColin Finck         switch ((IrpSp)->MinorFunction)
121c2c66affSColin Finck         {
122c2c66affSColin Finck         case IRP_MN_USER_FS_REQUEST:
123c2c66affSColin Finck             UDFPrint(("  UDFFSControl: UserFsReq request ....\n"));
124c2c66affSColin Finck 
125c2c66affSColin Finck             RC = UDFUserFsCtrlRequest(PtrIrpContext,Irp);
126c2c66affSColin Finck             break;
127c2c66affSColin Finck         case IRP_MN_MOUNT_VOLUME:
128c2c66affSColin Finck 
129c2c66affSColin Finck             UDFPrint(("  UDFFSControl: MOUNT_VOLUME request ....\n"));
130c2c66affSColin Finck 
131c2c66affSColin Finck             RC = UDFMountVolume(PtrIrpContext,Irp);
132c2c66affSColin Finck             break;
133c2c66affSColin Finck         case IRP_MN_VERIFY_VOLUME:
134c2c66affSColin Finck 
135c2c66affSColin Finck             UDFPrint(("  UDFFSControl: VERIFY_VOLUME request ....\n"));
136c2c66affSColin Finck 
137c2c66affSColin Finck             RC = UDFVerifyVolume(Irp);
138c2c66affSColin Finck             break;
139c2c66affSColin Finck         default:
140c2c66affSColin Finck             UDFPrintErr(("  UDFFSControl: STATUS_INVALID_DEVICE_REQUEST MinorFunction %x\n", (IrpSp)->MinorFunction));
141c2c66affSColin Finck             RC = STATUS_INVALID_DEVICE_REQUEST;
142c2c66affSColin Finck 
143c2c66affSColin Finck             Irp->IoStatus.Status = RC;
144c2c66affSColin Finck             Irp->IoStatus.Information = 0;
145c2c66affSColin Finck             // complete the IRP
146c2c66affSColin Finck             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
147c2c66affSColin Finck             break;
148c2c66affSColin Finck         }
149c2c66affSColin Finck 
150c2c66affSColin Finck //try_exit:   NOTHING;
151c2c66affSColin Finck     } _SEH2_FINALLY {
152c2c66affSColin Finck         if (!_SEH2_AbnormalTermination()) {
153c2c66affSColin Finck             // Free up the Irp Context
154c2c66affSColin Finck             UDFPrint(("  UDFCommonFSControl: finally\n"));
155c2c66affSColin Finck             UDFReleaseIrpContext(PtrIrpContext);
156c2c66affSColin Finck         } else {
157c2c66affSColin Finck             UDFPrint(("  UDFCommonFSControl: finally after exception ***\n"));
158c2c66affSColin Finck         }
159c2c66affSColin Finck     } _SEH2_END;
160c2c66affSColin Finck 
161c2c66affSColin Finck     return(RC);
162c2c66affSColin Finck } // end UDFCommonFSControl()
163c2c66affSColin Finck 
164c2c66affSColin Finck /*
165c2c66affSColin Finck Routine Description:
166c2c66affSColin Finck     This is the common routine for implementing the user's requests made
167c2c66affSColin Finck     through NtFsControlFile.
168c2c66affSColin Finck 
169c2c66affSColin Finck Arguments:
170c2c66affSColin Finck     Irp - Supplies the Irp being processed
171c2c66affSColin Finck 
172c2c66affSColin Finck Return Value:
173c2c66affSColin Finck     NTSTATUS - The return status for the operation
174c2c66affSColin Finck 
175c2c66affSColin Finck */
176c2c66affSColin Finck NTSTATUS
177c2c66affSColin Finck NTAPI
UDFUserFsCtrlRequest(PtrUDFIrpContext IrpContext,PIRP Irp)178c2c66affSColin Finck UDFUserFsCtrlRequest(
179c2c66affSColin Finck     PtrUDFIrpContext IrpContext,
180c2c66affSColin Finck     PIRP             Irp
181c2c66affSColin Finck     )
182c2c66affSColin Finck {
183c2c66affSColin Finck     NTSTATUS RC;
184c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation( Irp );
185c2c66affSColin Finck 
186c2c66affSColin Finck     //  Case on the control code.
187c2c66affSColin Finck     switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) {
188c2c66affSColin Finck 
189c2c66affSColin Finck     case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
190c2c66affSColin Finck     case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
191c2c66affSColin Finck     case FSCTL_REQUEST_BATCH_OPLOCK :
192c2c66affSColin Finck     case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
193c2c66affSColin Finck     case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
194c2c66affSColin Finck     case FSCTL_OPLOCK_BREAK_NOTIFY :
195c2c66affSColin Finck     case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
196c2c66affSColin Finck     case FSCTL_REQUEST_FILTER_OPLOCK :
197c2c66affSColin Finck 
198c2c66affSColin Finck         UDFPrint(("UDFUserFsCtrlRequest: OPLOCKS\n"));
199c2c66affSColin Finck         RC = STATUS_INVALID_DEVICE_REQUEST;
200c2c66affSColin Finck 
201c2c66affSColin Finck         Irp->IoStatus.Information = 0;
202c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
203c2c66affSColin Finck         break;
204c2c66affSColin Finck /*
205c2c66affSColin Finck         RC = UDFOplockRequest( IrpContext, Irp );
206c2c66affSColin Finck         break;
207c2c66affSColin Finck */
208c2c66affSColin Finck     case FSCTL_INVALIDATE_VOLUMES :
209c2c66affSColin Finck 
210c2c66affSColin Finck         RC = UDFInvalidateVolumes( IrpContext, Irp );
211c2c66affSColin Finck         break;
212c2c66affSColin Finck /*
213c2c66affSColin Finck     case FSCTL_MOVE_FILE:
214c2c66affSColin Finck 
215c2c66affSColin Finck     case FSCTL_QUERY_ALLOCATED_RANGES:
216c2c66affSColin Finck     case FSCTL_SET_ZERO_DATA:
217c2c66affSColin Finck     case FSCTL_SET_SPARSE:
218c2c66affSColin Finck 
219c2c66affSColin Finck     case FSCTL_MARK_VOLUME_DIRTY:
220c2c66affSColin Finck 
221c2c66affSColin Finck         RC = UDFDirtyVolume( IrpContext, Irp );
222c2c66affSColin Finck         break;
223c2c66affSColin Finck 
224c2c66affSColin Finck   */
225c2c66affSColin Finck     case FSCTL_IS_VOLUME_DIRTY:
226c2c66affSColin Finck 
227c2c66affSColin Finck         RC = UDFIsVolumeDirty(IrpContext, Irp);
228c2c66affSColin Finck         break;
229c2c66affSColin Finck 
230c2c66affSColin Finck     case FSCTL_ALLOW_EXTENDED_DASD_IO:
231c2c66affSColin Finck 
232c2c66affSColin Finck         UDFPrint(("UDFUserFsCtrlRequest: FSCTL_ALLOW_EXTENDED_DASD_IO\n"));
233c2c66affSColin Finck         // DASD i/o is always permitted
234c2c66affSColin Finck         // So, no-op this call
235c2c66affSColin Finck         RC = STATUS_SUCCESS;
236c2c66affSColin Finck 
237c2c66affSColin Finck         Irp->IoStatus.Information = 0;
238c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_SUCCESS;
239c2c66affSColin Finck         break;
240c2c66affSColin Finck 
241c2c66affSColin Finck     case FSCTL_DISMOUNT_VOLUME:
242c2c66affSColin Finck 
243c2c66affSColin Finck         RC = UDFDismountVolume( IrpContext, Irp );
244c2c66affSColin Finck         break;
245c2c66affSColin Finck 
246c2c66affSColin Finck     case FSCTL_IS_VOLUME_MOUNTED:
247c2c66affSColin Finck 
248c2c66affSColin Finck         RC = UDFIsVolumeMounted( IrpContext, Irp );
249c2c66affSColin Finck         break;
250c2c66affSColin Finck 
251c2c66affSColin Finck     case FSCTL_FILESYSTEM_GET_STATISTICS:
252c2c66affSColin Finck 
253c2c66affSColin Finck         RC = UDFGetStatistics( IrpContext, Irp );
254c2c66affSColin Finck         break;
255c2c66affSColin Finck 
256c2c66affSColin Finck     case FSCTL_LOCK_VOLUME:
257c2c66affSColin Finck 
258c2c66affSColin Finck         RC = UDFLockVolume( IrpContext, Irp );
259c2c66affSColin Finck         break;
260c2c66affSColin Finck 
261c2c66affSColin Finck     case FSCTL_UNLOCK_VOLUME:
262c2c66affSColin Finck 
263c2c66affSColin Finck         RC = UDFUnlockVolume( IrpContext, Irp );
264c2c66affSColin Finck         break;
265c2c66affSColin Finck 
266c2c66affSColin Finck     case FSCTL_IS_PATHNAME_VALID:
267c2c66affSColin Finck 
268c2c66affSColin Finck         RC = UDFIsPathnameValid( IrpContext, Irp );
269c2c66affSColin Finck         break;
270c2c66affSColin Finck 
271c2c66affSColin Finck     case FSCTL_GET_VOLUME_BITMAP:
272c2c66affSColin Finck 
273c2c66affSColin Finck         UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_VOLUME_BITMAP\n"));
274c2c66affSColin Finck         RC = UDFGetVolumeBitmap( IrpContext, Irp );
275c2c66affSColin Finck         break;
276c2c66affSColin Finck 
277c2c66affSColin Finck     case FSCTL_GET_RETRIEVAL_POINTERS:
278c2c66affSColin Finck 
279c2c66affSColin Finck         UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_RETRIEVAL_POINTERS\n"));
280c2c66affSColin Finck         RC = UDFGetRetrievalPointers( IrpContext, Irp, 0 );
281c2c66affSColin Finck         break;
282c2c66affSColin Finck 
283c2c66affSColin Finck 
284c2c66affSColin Finck     //  We don't support any of the known or unknown requests.
285c2c66affSColin Finck     default:
286c2c66affSColin Finck 
287c2c66affSColin Finck         UDFPrintErr(("UDFUserFsCtrlRequest: STATUS_INVALID_DEVICE_REQUEST for %x\n",
288c2c66affSColin Finck             IrpSp->Parameters.FileSystemControl.FsControlCode));
289c2c66affSColin Finck         RC = STATUS_INVALID_DEVICE_REQUEST;
290c2c66affSColin Finck 
291c2c66affSColin Finck         Irp->IoStatus.Information = 0;
292c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
293c2c66affSColin Finck         break;
294c2c66affSColin Finck     }
295c2c66affSColin Finck 
296c2c66affSColin Finck     IoCompleteRequest(Irp,IO_DISK_INCREMENT);
297c2c66affSColin Finck     return RC;
298c2c66affSColin Finck 
299c2c66affSColin Finck } // end UDFUserFsCtrlRequest()
300c2c66affSColin Finck 
301c2c66affSColin Finck 
302c2c66affSColin Finck /*
303c2c66affSColin Finck Routine Description:
304c2c66affSColin Finck     This is the common routine for implementing the mount requests
305c2c66affSColin Finck 
306c2c66affSColin Finck Arguments:
307c2c66affSColin Finck     Irp - Supplies the Irp being processed
308c2c66affSColin Finck 
309c2c66affSColin Finck Return Value:
310c2c66affSColin Finck     NTSTATUS - The return status for the operation
311c2c66affSColin Finck 
312c2c66affSColin Finck */
313c2c66affSColin Finck NTSTATUS
314c2c66affSColin Finck NTAPI
UDFMountVolume(IN PtrUDFIrpContext PtrIrpContext,IN PIRP Irp)315c2c66affSColin Finck UDFMountVolume(
316c2c66affSColin Finck     IN PtrUDFIrpContext PtrIrpContext,
317c2c66affSColin Finck     IN PIRP Irp
318c2c66affSColin Finck     )
319c2c66affSColin Finck {
320c2c66affSColin Finck     NTSTATUS                RC;
321c2c66affSColin Finck     PIO_STACK_LOCATION      IrpSp = IoGetCurrentIrpStackLocation(Irp);
322c2c66affSColin Finck     PDEVICE_OBJECT          TargetDeviceObject = NULL;
323c2c66affSColin Finck     PFILTER_DEV_EXTENSION   filterDevExt;
324c2c66affSColin Finck     PDEVICE_OBJECT          fsDeviceObject;
325c2c66affSColin Finck     PVPB                    Vpb = IrpSp->Parameters.MountVolume.Vpb;
326c2c66affSColin Finck     PVCB                    Vcb = NULL;
327c2c66affSColin Finck //    PVCB                    OldVcb = NULL;
328c2c66affSColin Finck     PDEVICE_OBJECT          VolDo = NULL;
329c2c66affSColin Finck     IO_STATUS_BLOCK         Iosb;
330c2c66affSColin Finck     ULONG                   MediaChangeCount = 0;
331c2c66affSColin Finck     ULONG                   Characteristics;
332c2c66affSColin Finck     DEVICE_TYPE             FsDeviceType;
333c2c66affSColin Finck     BOOLEAN                 RestoreDoVerify = FALSE;
334c2c66affSColin Finck     BOOLEAN                 WrongMedia = FALSE;
335c2c66affSColin Finck     BOOLEAN                 RemovableMedia = TRUE;
336c2c66affSColin Finck     BOOLEAN                 CompleteIrp = FALSE;
337c2c66affSColin Finck     ULONG                   Mode;
338c2c66affSColin Finck     TEST_UNIT_READY_USER_OUT TestUnitReadyBuffer;
339c2c66affSColin Finck     ULONG                   i;
340c2c66affSColin Finck     LARGE_INTEGER           delay;
341c2c66affSColin Finck     BOOLEAN                 VcbAcquired = FALSE;
342c2c66affSColin Finck     BOOLEAN                 DeviceNotTouched = TRUE;
343c2c66affSColin Finck     BOOLEAN                 Locked = FALSE;
344c2c66affSColin Finck     int8*                   ioBuf = NULL;
345c2c66affSColin Finck 
346c2c66affSColin Finck     ASSERT(IrpSp);
347c2c66affSColin Finck     UDFPrint(("\n !!! UDFMountVolume\n"));
348c2c66affSColin Finck //    UDFPrint(("Build " VER_STR_PRODUCT "\n\n"));
349c2c66affSColin Finck 
350c2c66affSColin Finck     fsDeviceObject = PtrIrpContext->TargetDeviceObject;
351c2c66affSColin Finck     UDFPrint(("Mount on device object %x\n", fsDeviceObject));
352c2c66affSColin Finck     filterDevExt = (PFILTER_DEV_EXTENSION)fsDeviceObject->DeviceExtension;
353c2c66affSColin Finck     if (filterDevExt->NodeIdentifier.NodeType == UDF_NODE_TYPE_FILTER_DEVOBJ &&
354c2c66affSColin Finck         filterDevExt->NodeIdentifier.NodeSize == sizeof(FILTER_DEV_EXTENSION)) {
355c2c66affSColin Finck         CompleteIrp = FALSE;
356c2c66affSColin Finck     } else
357c2c66affSColin Finck     if (filterDevExt->NodeIdentifier.NodeType == UDF_NODE_TYPE_UDFFS_DEVOBJ &&
358c2c66affSColin Finck         filterDevExt->NodeIdentifier.NodeSize == sizeof(UDFFS_DEV_EXTENSION)) {
359c2c66affSColin Finck         CompleteIrp = TRUE;
360c2c66affSColin Finck     } else {
361c2c66affSColin Finck         UDFPrintErr(("Invalid node type in FS or FILTER DeviceObject\n"));
362c2c66affSColin Finck         ASSERT(FALSE);
363c2c66affSColin Finck     }
364c2c66affSColin Finck     // Get a pointer to the target physical/virtual device object.
365c2c66affSColin Finck     TargetDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject;
366c2c66affSColin Finck 
367c2c66affSColin Finck     if(((Characteristics = TargetDeviceObject->Characteristics) & FILE_FLOPPY_DISKETTE) ||
368c2c66affSColin Finck        (UDFGlobalData.UDFFlags & UDF_DATA_FLAGS_BEING_UNLOADED) ) {
369c2c66affSColin Finck         WrongMedia = TRUE;
370c2c66affSColin Finck     } else {
371c2c66affSColin Finck         RemovableMedia = (Characteristics & FILE_REMOVABLE_MEDIA) ? TRUE : FALSE;
372c2c66affSColin Finck         if(TargetDeviceObject->DeviceType != FILE_DEVICE_CD_ROM) {
373c2c66affSColin Finck             if(UDFGetRegParameter(NULL, REG_MOUNT_ON_CDONLY_NAME, TRUE)) {
374c2c66affSColin Finck                 WrongMedia = TRUE;
375c2c66affSColin Finck             }
376c2c66affSColin Finck         }
377c2c66affSColin Finck         if(TargetDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) {
378c2c66affSColin Finck             FsDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
379c2c66affSColin Finck #ifdef UDF_HDD_SUPPORT
380c2c66affSColin Finck         } else
381c2c66affSColin Finck         if (TargetDeviceObject->DeviceType == FILE_DEVICE_DISK) {
382c2c66affSColin Finck             if(RemovableMedia) {
383c2c66affSColin Finck                 if(!UDFGetRegParameter(NULL, REG_MOUNT_ON_ZIP_NAME, FALSE)) {
384c2c66affSColin Finck                     WrongMedia = TRUE;
385c2c66affSColin Finck                 }
386c2c66affSColin Finck             } else {
387c2c66affSColin Finck                 if(!UDFGetRegParameter(NULL, REG_MOUNT_ON_HDD_NAME, FALSE)) {
388c2c66affSColin Finck                     WrongMedia = TRUE;
389c2c66affSColin Finck                 }
390c2c66affSColin Finck             }
391c2c66affSColin Finck             FsDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
392c2c66affSColin Finck #endif //UDF_HDD_SUPPORT
393c2c66affSColin Finck         } else {
394c2c66affSColin Finck             WrongMedia = TRUE;
395c2c66affSColin Finck         }
396c2c66affSColin Finck     }
397c2c66affSColin Finck 
398c2c66affSColin Finck     // Acquire GlobalDataResource
399c2c66affSColin Finck     UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
400c2c66affSColin Finck 
401c2c66affSColin Finck     _SEH2_TRY {
402c2c66affSColin Finck 
403c2c66affSColin Finck         UDFScanForDismountedVcb(PtrIrpContext);
404c2c66affSColin Finck 
405c2c66affSColin Finck         if(WrongMedia) try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
406c2c66affSColin Finck 
407c2c66affSColin Finck         if(RemovableMedia) {
408c2c66affSColin Finck             UDFPrint(("UDFMountVolume: removable media\n"));
409c2c66affSColin Finck             // just remember current MediaChangeCount
410c2c66affSColin Finck             // or fail if No Media ....
411c2c66affSColin Finck 
412c2c66affSColin Finck             // experimental CHECK_VERIFY, for fucking BENQ DVD_DD_1620
413c2c66affSColin Finck 
414c2c66affSColin Finck                 // Now we can get device state via GET_EVENT (if supported)
415c2c66affSColin Finck                 // or still one TEST_UNIT_READY command
416c2c66affSColin Finck                 RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY,
417c2c66affSColin Finck                                      TargetDeviceObject,
418c2c66affSColin Finck                                      NULL,0,
419c2c66affSColin Finck                                      &MediaChangeCount,sizeof(ULONG),
420c2c66affSColin Finck                                      FALSE,&Iosb );
421c2c66affSColin Finck 
422c2c66affSColin Finck             // Send TEST_UNIT_READY comment
423c2c66affSColin Finck             // This can spin-up or wake-up the device
424c2c66affSColin Finck             if(UDFGetRegParameter(NULL, UDF_WAIT_CD_SPINUP, TRUE)) {
425c2c66affSColin Finck                 delay.QuadPart = -15000000LL; // 1.5 sec
426c2c66affSColin Finck                 for(i=0; i<UDF_READY_MAX_RETRY; i++) {
427c2c66affSColin Finck                     // Use device default ready timeout
428c2c66affSColin Finck                     Mode = 0;
429c2c66affSColin Finck                     RC = UDFPhSendIOCTL( IOCTL_CDRW_TEST_UNIT_READY,
430c2c66affSColin Finck                                          TargetDeviceObject,
431c2c66affSColin Finck                                          &Mode,sizeof(Mode),
432c2c66affSColin Finck                                          &TestUnitReadyBuffer,sizeof(TEST_UNIT_READY_USER_OUT),
433c2c66affSColin Finck                                          FALSE,NULL);
434c2c66affSColin Finck                     UDFPrint(("UDFMountVolume: TEST_UNIT_READY %x\n", RC));
435c2c66affSColin Finck                     if(!NT_SUCCESS(RC))
436c2c66affSColin Finck                         break;
437c2c66affSColin Finck                     if(TestUnitReadyBuffer.SenseKey == SCSI_SENSE_NOT_READY &&
438c2c66affSColin Finck                        TestUnitReadyBuffer.AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY &&
439c2c66affSColin Finck                        TestUnitReadyBuffer.AdditionalSenseCodeQualifier == SCSI_SENSEQ_BECOMING_READY) {
440c2c66affSColin Finck                         UDFPrint(("UDFMountVolume: retry\n"));
441c2c66affSColin Finck                         KeDelayExecutionThread(KernelMode, FALSE, &delay);
442c2c66affSColin Finck                         //delay.QuadPart -= 10000000LL; // 1.0 sec
443c2c66affSColin Finck                     } else {
444c2c66affSColin Finck                         break;
445c2c66affSColin Finck                     }
446c2c66affSColin Finck                 }
447c2c66affSColin Finck                 if(i) {
448c2c66affSColin Finck                     UDFPrint(("UDFMountVolume: additional delay 3 sec\n"));
449c2c66affSColin Finck                     delay.QuadPart = -30000000LL; // 3.0 sec
450c2c66affSColin Finck                     KeDelayExecutionThread(KernelMode, FALSE, &delay);
451c2c66affSColin Finck                 }
452c2c66affSColin Finck             }
453c2c66affSColin Finck 
454c2c66affSColin Finck             // Now we can get device state via GET_EVENT (if supported)
455c2c66affSColin Finck             // or still one TEST_UNIT_READY command
456c2c66affSColin Finck             RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY,
457c2c66affSColin Finck                                  TargetDeviceObject,
458c2c66affSColin Finck                                  NULL,0,
459c2c66affSColin Finck                                  &MediaChangeCount,sizeof(ULONG),
460c2c66affSColin Finck                                  FALSE,&Iosb );
461c2c66affSColin Finck 
462c2c66affSColin Finck             if(RC == STATUS_IO_DEVICE_ERROR) {
463c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: retry check verify\n"));
464c2c66affSColin Finck                 RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY,
465c2c66affSColin Finck                                      TargetDeviceObject,
466c2c66affSColin Finck                                      NULL,0,
467c2c66affSColin Finck                                      &MediaChangeCount,sizeof(ULONG),
468c2c66affSColin Finck                                      FALSE,&Iosb );
469c2c66affSColin Finck             }
470c2c66affSColin Finck 
471c2c66affSColin Finck             if(!NT_SUCCESS(RC) && (RC != STATUS_VERIFY_REQUIRED))
472c2c66affSColin Finck                 try_return(RC);
473c2c66affSColin Finck 
474c2c66affSColin Finck             //  Be safe about the count in case the driver didn't fill it in
475c2c66affSColin Finck             if(Iosb.Information != sizeof(ULONG)) {
476c2c66affSColin Finck                 MediaChangeCount = 0;
477c2c66affSColin Finck             }
478c2c66affSColin Finck 
479c2c66affSColin Finck             if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
480c2c66affSColin Finck                 // Check if device is busy before locking tray and performing
481c2c66affSColin Finck                 // further geomentry discovery. This is needed to avoid streaming
482c2c66affSColin Finck                 // loss during CD-R recording. Note, that some recording tools
483c2c66affSColin Finck                 // work with device via SPTI bypassing FS/Device driver layers.
484c2c66affSColin Finck 
485c2c66affSColin Finck                 ioBuf = (int8*)MyAllocatePool__(NonPagedPool,4096);
486c2c66affSColin Finck                 if(!ioBuf) {
487c2c66affSColin Finck                     try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
488c2c66affSColin Finck                 }
489c2c66affSColin Finck                 RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY,TargetDeviceObject,
490c2c66affSColin Finck                     ioBuf,sizeof(DISK_GEOMETRY),
491c2c66affSColin Finck                     ioBuf,sizeof(DISK_GEOMETRY),
492c2c66affSColin Finck                     FALSE, NULL );
493c2c66affSColin Finck 
494c2c66affSColin Finck                 if(RC == STATUS_DEVICE_NOT_READY) {
495c2c66affSColin Finck                     // probably, the device is really busy, may be by CD/DVD recording
496c2c66affSColin Finck                     UserPrint(("  busy (*)\n"));
497c2c66affSColin Finck                     try_return(RC);
498c2c66affSColin Finck                 }
499c2c66affSColin Finck             }
500c2c66affSColin Finck 
501c2c66affSColin Finck             // lock media for now
502c2c66affSColin Finck             if(!WrongMedia) {
503c2c66affSColin Finck                 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(&MediaChangeCount))->PreventMediaRemoval = TRUE;
504c2c66affSColin Finck                 RC = UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
505c2c66affSColin Finck                                      TargetDeviceObject,
506c2c66affSColin Finck                                      &MediaChangeCount,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
507c2c66affSColin Finck                                      NULL,0,
508c2c66affSColin Finck                                      FALSE,NULL);
509c2c66affSColin Finck                 Locked = TRUE;
510c2c66affSColin Finck             }
511c2c66affSColin Finck 
512c2c66affSColin Finck         }
513c2c66affSColin Finck         // Now before we can initialize the Vcb we need to set up the
514c2c66affSColin Finck         // Get our device object and alignment requirement.
515c2c66affSColin Finck         // Device extension == VCB
516c2c66affSColin Finck         UDFPrint(("UDFMountVolume: create device\n"));
517c2c66affSColin Finck         RC = IoCreateDevice( UDFGlobalData.DriverObject,
518c2c66affSColin Finck                                  sizeof(VCB),
519c2c66affSColin Finck                                  NULL,
520c2c66affSColin Finck                                  FsDeviceType,
521c2c66affSColin Finck                                  0,
522c2c66affSColin Finck                                  FALSE,
523c2c66affSColin Finck                                  &VolDo );
524c2c66affSColin Finck 
525c2c66affSColin Finck         if(!NT_SUCCESS(RC)) try_return(RC);
526c2c66affSColin Finck 
527c2c66affSColin Finck         // Our alignment requirement is the larger of the processor alignment requirement
528c2c66affSColin Finck         // already in the volume device object and that in the DeviceObjectWeTalkTo
529c2c66affSColin Finck         if(TargetDeviceObject->AlignmentRequirement > VolDo->AlignmentRequirement) {
530c2c66affSColin Finck             VolDo->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
531c2c66affSColin Finck         }
532c2c66affSColin Finck 
533c2c66affSColin Finck         VolDo->Flags &= ~DO_DEVICE_INITIALIZING;
534c2c66affSColin Finck 
535c2c66affSColin Finck         // device object field in the VPB to point to our new volume device
536c2c66affSColin Finck         // object.
537c2c66affSColin Finck         Vpb->DeviceObject = (PDEVICE_OBJECT) VolDo;
538c2c66affSColin Finck 
539c2c66affSColin Finck         // We must initialize the stack size in our device object before
540c2c66affSColin Finck         // the following reads, because the I/O system has not done it yet.
541c2c66affSColin Finck         ((PDEVICE_OBJECT)VolDo)->StackSize = (CCHAR) (TargetDeviceObject->StackSize + 1);
542c2c66affSColin Finck 
543c2c66affSColin Finck         Vcb = (PVCB)VolDo->DeviceExtension;
544c2c66affSColin Finck 
545c2c66affSColin Finck         // Initialize the Vcb.  This routine will raise on an allocation
546c2c66affSColin Finck         // failure.
547c2c66affSColin Finck         RC = UDFInitializeVCB(VolDo,TargetDeviceObject,Vpb);
548c2c66affSColin Finck         if(!NT_SUCCESS(RC)) {
549c2c66affSColin Finck             Vcb = NULL;
550c2c66affSColin Finck             try_return(RC);
551c2c66affSColin Finck         }
552c2c66affSColin Finck 
553c2c66affSColin Finck         VolDo = NULL;
554c2c66affSColin Finck         Vpb = NULL;
555c2c66affSColin Finck 
556c2c66affSColin Finck         UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE );
557c2c66affSColin Finck         VcbAcquired = TRUE;
558c2c66affSColin Finck 
559c2c66affSColin Finck         // Let's reference the Vpb to make sure we are the one to
560c2c66affSColin Finck         // have the last dereference.
561c2c66affSColin Finck         Vcb->Vpb->ReferenceCount ++;
562c2c66affSColin Finck 
563c2c66affSColin Finck         Vcb->MediaChangeCount = MediaChangeCount;
564c2c66affSColin Finck         Vcb->FsDeviceType = FsDeviceType;
565c2c66affSColin Finck 
566c2c66affSColin Finck         // Clear the verify bit for the start of mount.
567c2c66affSColin Finck         if(Vcb->Vpb->RealDevice->Flags & DO_VERIFY_VOLUME) {
568c2c66affSColin Finck             Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
569c2c66affSColin Finck             RestoreDoVerify = TRUE;
570c2c66affSColin Finck         }
571c2c66affSColin Finck 
572c2c66affSColin Finck         DeviceNotTouched = FALSE;
573c2c66affSColin Finck         RC = UDFGetDiskInfo(TargetDeviceObject,Vcb);
574c2c66affSColin Finck         if(!NT_SUCCESS(RC)) try_return(RC);
575c2c66affSColin Finck 
576c2c66affSColin Finck         //     ****  Read registry settings  ****
577c2c66affSColin Finck         UDFReadRegKeys(Vcb, FALSE, FALSE);
578c2c66affSColin Finck 
579c2c66affSColin Finck         Vcb->MountPhErrorCount = 0;
580c2c66affSColin Finck 
581c2c66affSColin Finck         // Initialize internal cache
582c2c66affSColin Finck         Mode = WCACHE_MODE_ROM;
583c2c66affSColin Finck         RC = WCacheInit__(&(Vcb->FastCache),
584c2c66affSColin Finck                           Vcb->WCacheMaxFrames,
585c2c66affSColin Finck                           Vcb->WCacheMaxBlocks,
586c2c66affSColin Finck                           Vcb->WriteBlockSize,
587c2c66affSColin Finck                           5, Vcb->BlockSizeBits,
588c2c66affSColin Finck                           Vcb->WCacheBlocksPerFrameSh,
589c2c66affSColin Finck                           0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode,
590c2c66affSColin Finck                               0/*WCACHE_CACHE_WHOLE_PACKET*/ |
591c2c66affSColin Finck                               (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) |
592c2c66affSColin Finck                               (Vcb->CacheChainedIo ? WCACHE_CHAINED_IO : 0) |
593c2c66affSColin Finck                               WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS,  // this will be cleared after mount
594c2c66affSColin Finck                           Vcb->WCacheFramesToKeepFree,
595c2c66affSColin Finck //                          UDFTWrite, UDFTRead,
596c2c66affSColin Finck                           UDFTWriteVerify, UDFTReadVerify,
597c2c66affSColin Finck #ifdef UDF_ASYNC_IO
598c2c66affSColin Finck                           UDFTWriteAsync, UDFTReadAsync,
599c2c66affSColin Finck #else  //UDF_ASYNC_IO
600c2c66affSColin Finck                           NULL, NULL,
601c2c66affSColin Finck #endif //UDF_ASYNC_IO
602c2c66affSColin Finck                           UDFIsBlockAllocated,
603c2c66affSColin Finck                           UDFUpdateVAT,
604c2c66affSColin Finck                           UDFWCacheErrorHandler);
605c2c66affSColin Finck         if(!NT_SUCCESS(RC)) try_return(RC);
606c2c66affSColin Finck 
607c2c66affSColin Finck         RC = UDFVInit(Vcb);
608c2c66affSColin Finck         if(!NT_SUCCESS(RC)) try_return(RC);
609c2c66affSColin Finck 
610c2c66affSColin Finck         UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
611c2c66affSColin Finck         RC = UDFGetDiskInfoAndVerify(TargetDeviceObject,Vcb);
612c2c66affSColin Finck         UDFReleaseResource(&(Vcb->BitMapResource1));
613c2c66affSColin Finck 
614c2c66affSColin Finck         ASSERT(!Vcb->Modified);
615c2c66affSColin Finck         WCacheChFlags__(&(Vcb->FastCache),
616c2c66affSColin Finck                         WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet
617c2c66affSColin Finck                         WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS);  // let user retry request on Bad Blocks
618c2c66affSColin Finck 
619c2c66affSColin Finck #ifdef UDF_READ_ONLY_BUILD
620c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
621c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_FLAGS_MEDIA_READ_ONLY;
622c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
623c2c66affSColin Finck 
624c2c66affSColin Finck         if(!NT_SUCCESS(RC)) {
625c2c66affSColin Finck             UDFPrint(("UDFMountVolume: try raw mount\n"));
626c2c66affSColin Finck             if(Vcb->NSRDesc & VRS_ISO9660_FOUND) {
627c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: block raw mount due to ISO9660 presence\n"));
628c2c66affSColin Finck                 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
629c2c66affSColin Finck                 try_return(RC);
630c2c66affSColin Finck             }
631c2c66affSColin Finck try_raw_mount:
632c2c66affSColin Finck             UDFPrint(("UDFMountVolume: try raw mount (2)\n"));
633c2c66affSColin Finck             if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
634c2c66affSColin Finck 
635c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: trying raw mount...\n"));
636c2c66affSColin Finck                 Vcb->VolIdent.Length =
637c2c66affSColin Finck                 (Vcb->VolIdent.MaximumLength = sizeof(UDF_BLANK_VOLUME_LABEL)) - 2;
638c2c66affSColin Finck                 if(Vcb->VolIdent.Buffer)
639c2c66affSColin Finck                     MyFreePool__(Vcb->VolIdent.Buffer);
640c2c66affSColin Finck                 Vcb->VolIdent.Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, sizeof(UDF_BLANK_VOLUME_LABEL));
641c2c66affSColin Finck                 if(!Vcb->VolIdent.Buffer)
642c2c66affSColin Finck                     try_return(STATUS_INSUFFICIENT_RESOURCES);
643c2c66affSColin Finck                 RtlCopyMemory(Vcb->VolIdent.Buffer, UDF_BLANK_VOLUME_LABEL, sizeof(UDF_BLANK_VOLUME_LABEL));
644c2c66affSColin Finck 
645c2c66affSColin Finck                 RC = UDFBlankMount(Vcb);
646c2c66affSColin Finck                 if(!NT_SUCCESS(RC)) try_return(RC);
647c2c66affSColin Finck 
648c2c66affSColin Finck             } else {
649c2c66affSColin Finck //                Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
650c2c66affSColin Finck                 try_return(RC);
651c2c66affSColin Finck             }
652c2c66affSColin Finck         } else {
653c2c66affSColin Finck             Vcb->MountPhErrorCount = -1;
654c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
655c2c66affSColin Finck             // set cache mode according to media type
656c2c66affSColin Finck             if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY)) {
657c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: writable volume\n"));
658c2c66affSColin Finck                 if(!Vcb->CDR_Mode) {
659c2c66affSColin Finck                     if((FsDeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||
660c2c66affSColin Finck                        CdrwMediaClassEx_IsRAM(Vcb->MediaClassEx)) {
661c2c66affSColin Finck                         UDFPrint(("UDFMountVolume: RAM mode\n"));
662c2c66affSColin Finck                         Mode = WCACHE_MODE_RAM;
663c2c66affSColin Finck                     } else {
664c2c66affSColin Finck                         UDFPrint(("UDFMountVolume: RW mode\n"));
665c2c66affSColin Finck                         Mode = WCACHE_MODE_RW;
666c2c66affSColin Finck                     }
667c2c66affSColin Finck /*                    if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
668c2c66affSColin Finck                     } else {
669c2c66affSColin Finck                         Vcb->WriteSecurity = TRUE;
670c2c66affSColin Finck                     }*/
671c2c66affSColin Finck                 } else {
672c2c66affSColin Finck                     UDFPrint(("UDFMountVolume: R mode\n"));
673c2c66affSColin Finck                     Mode = WCACHE_MODE_R;
674c2c66affSColin Finck                 }
675c2c66affSColin Finck                 // we can't record ACL on old format disks
676c2c66affSColin Finck                 if(!UDFNtAclSupported(Vcb)) {
677c2c66affSColin Finck                     UDFPrint(("UDFMountVolume: NO ACL and ExtFE support\n"));
678c2c66affSColin Finck                     Vcb->WriteSecurity = FALSE;
679c2c66affSColin Finck                     Vcb->UseExtendedFE = FALSE;
680c2c66affSColin Finck                 }
681c2c66affSColin Finck             }
682c2c66affSColin Finck             WCacheSetMode__(&(Vcb->FastCache), Mode);
683c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
684c2c66affSColin Finck             // Complete mount operations: create root FCB
685c2c66affSColin Finck             UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
686c2c66affSColin Finck             RC = UDFCompleteMount(Vcb);
687c2c66affSColin Finck             UDFReleaseResource(&(Vcb->BitMapResource1));
688c2c66affSColin Finck             if(!NT_SUCCESS(RC)) {
689c2c66affSColin Finck                 // We must have Vcb->VCBOpenCount = 1 for UDFBlankMount()
690c2c66affSColin Finck                 // Thus, we should not decrement it here
691c2c66affSColin Finck                 // Also, if we shall not perform BlankMount,
692c2c66affSColin Finck                 // but simply cleanup and return error, Vcb->VCBOpenCount
693c2c66affSColin Finck                 // will be decremented during cleanup. Thus anyway it must
694c2c66affSColin Finck                 // stay 1 unchanged here
695c2c66affSColin Finck                 //UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
696c2c66affSColin Finck                 UDFCloseResidual(Vcb);
697c2c66affSColin Finck                 Vcb->VCBOpenCount = 1;
698c2c66affSColin Finck                 if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
699c2c66affSColin Finck                     Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
700c2c66affSColin Finck                 goto try_raw_mount;
701c2c66affSColin Finck             }
702c2c66affSColin Finck             Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
703c2c66affSColin Finck         }
704c2c66affSColin Finck 
705c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
706c2c66affSColin Finck         if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY)) {
707c2c66affSColin Finck             RC = UDFStartEjectWaiter(Vcb);
708c2c66affSColin Finck             if(!NT_SUCCESS(RC)) try_return(RC);
709c2c66affSColin Finck         } else {
710c2c66affSColin Finck             UDFPrint(("UDFMountVolume: RO mount\n"));
711c2c66affSColin Finck             Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
712c2c66affSColin Finck         }
713c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
714c2c66affSColin Finck 
715c2c66affSColin Finck         Vcb->Vpb->SerialNumber = Vcb->PhSerialNumber;
716c2c66affSColin Finck         Vcb->Vpb->VolumeLabelLength = Vcb->VolIdent.Length;
717c2c66affSColin Finck         RtlCopyMemory( Vcb->Vpb->VolumeLabel,
718c2c66affSColin Finck                        Vcb->VolIdent.Buffer,
719c2c66affSColin Finck                        Vcb->VolIdent.Length );
720c2c66affSColin Finck 
721c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_MOUNTED;
722c2c66affSColin Finck 
723c2c66affSColin Finck         UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
724c2c66affSColin Finck         Vcb->TotalAllocUnits = UDFGetTotalSpace(Vcb);
725c2c66affSColin Finck         Vcb->FreeAllocUnits = UDFGetFreeSpace(Vcb);
726c2c66affSColin Finck         // Register shutdown routine
727c2c66affSColin Finck         if(!Vcb->ShutdownRegistered) {
728c2c66affSColin Finck             UDFPrint(("UDFMountVolume: Register shutdown routine\n"));
729c2c66affSColin Finck             IoRegisterShutdownNotification(Vcb->VCBDeviceObject);
730c2c66affSColin Finck             Vcb->ShutdownRegistered = TRUE;
731c2c66affSColin Finck         }
732c2c66affSColin Finck 
733c2c66affSColin Finck         // unlock media
734c2c66affSColin Finck         if(RemovableMedia) {
735c2c66affSColin Finck             if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) {
736c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: unlock media on RO volume\n"));
737c2c66affSColin Finck                 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(&MediaChangeCount))->PreventMediaRemoval = FALSE;
738c2c66affSColin Finck                 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
739c2c66affSColin Finck                                      TargetDeviceObject,
740c2c66affSColin Finck                                      &MediaChangeCount,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
741c2c66affSColin Finck                                      NULL,0,
742c2c66affSColin Finck                                      FALSE,NULL);
743c2c66affSColin Finck                 if(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER)
744c2c66affSColin Finck                     UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, TRUE);
745c2c66affSColin Finck             }
746c2c66affSColin Finck         }
747c2c66affSColin Finck 
748c2c66affSColin Finck         if (UDFGlobalData.MountEvent)
749c2c66affSColin Finck         {
750c2c66affSColin Finck             Vcb->IsVolumeJustMounted = TRUE;
751c2c66affSColin Finck             KeSetEvent(UDFGlobalData.MountEvent, 0, FALSE);
752c2c66affSColin Finck         }
753c2c66affSColin Finck 
754c2c66affSColin Finck         //  The new mount is complete.
755c2c66affSColin Finck         UDFReleaseResource( &(Vcb->VCBResource) );
756c2c66affSColin Finck         VcbAcquired = FALSE;
757c2c66affSColin Finck         Vcb = NULL;
758c2c66affSColin Finck 
759c2c66affSColin Finck         RC = STATUS_SUCCESS;
760c2c66affSColin Finck 
761c2c66affSColin Finck try_exit: NOTHING;
762c2c66affSColin Finck     } _SEH2_FINALLY {
763c2c66affSColin Finck 
764c2c66affSColin Finck         UDFPrint(("UDFMountVolume: RC = %x\n", RC));
765c2c66affSColin Finck 
766c2c66affSColin Finck         if(ioBuf) {
767c2c66affSColin Finck             MyFreePool__(ioBuf);
768c2c66affSColin Finck         }
769c2c66affSColin Finck 
770c2c66affSColin Finck         if(!NT_SUCCESS(RC)) {
771c2c66affSColin Finck 
772c2c66affSColin Finck             if(RemovableMedia && Locked) {
773c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: unlock media\n"));
774c2c66affSColin Finck                 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(&MediaChangeCount))->PreventMediaRemoval = FALSE;
775c2c66affSColin Finck                 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
776c2c66affSColin Finck                                      TargetDeviceObject,
777c2c66affSColin Finck                                      &MediaChangeCount,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
778c2c66affSColin Finck                                      NULL,0,
779c2c66affSColin Finck                                      FALSE,NULL);
780c2c66affSColin Finck             }
781c2c66affSColin Finck /*            if((RC != STATUS_DEVICE_NOT_READY) &&
782c2c66affSColin Finck                (RC != STATUS_NO_MEDIA_IN_DEVICE) ) {*/
783c2c66affSColin Finck                 // reset driver
784c2c66affSColin Finck             if(!DeviceNotTouched &&
785c2c66affSColin Finck                (!Vcb || (Vcb && (Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER)))) {
786c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: reset driver\n"));
787c2c66affSColin Finck                 UDFResetDeviceDriver(Vcb, TargetDeviceObject, TRUE);
788c2c66affSColin Finck             }
789c2c66affSColin Finck 
790c2c66affSColin Finck             if(RC == STATUS_CRC_ERROR || RC == STATUS_FILE_CORRUPT_ERROR) {
791c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: status -> STATUS_UNRECOGNIZED_VOLUME\n"));
792c2c66affSColin Finck                 RC = STATUS_UNRECOGNIZED_VOLUME;
793c2c66affSColin Finck             }
794c2c66affSColin Finck 
795c2c66affSColin Finck             // If we didn't complete the mount then cleanup any remaining structures.
796c2c66affSColin Finck             if(Vpb) {
797c2c66affSColin Finck                Vpb->DeviceObject = NULL;
798c2c66affSColin Finck             }
799c2c66affSColin Finck 
800c2c66affSColin Finck             if(Vcb) {
801c2c66affSColin Finck                 // Restore the verify bit.
802c2c66affSColin Finck                 if(RestoreDoVerify) {
803c2c66affSColin Finck                     Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
804c2c66affSColin Finck                 }
805c2c66affSColin Finck                 // Make sure there is no Vcb since it could go away
806c2c66affSColin Finck                 if(Vcb->VCBOpenCount)
807c2c66affSColin Finck                     UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
808c2c66affSColin Finck                 // This procedure will also delete the volume device object
809c2c66affSColin Finck                 if(UDFDismountVcb( Vcb, VcbAcquired )) {
810c2c66affSColin Finck                     UDFReleaseResource( &(Vcb->VCBResource) );
811c2c66affSColin Finck                 }
812c2c66affSColin Finck             } else if(VolDo) {
813c2c66affSColin Finck                 IoDeleteDevice( VolDo );
814c2c66affSColin Finck             }
815c2c66affSColin Finck         }
816c2c66affSColin Finck         // Release the global resource.
817c2c66affSColin Finck         UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
818c2c66affSColin Finck 
819c2c66affSColin Finck         if (CompleteIrp || NT_SUCCESS(RC)) {
820c2c66affSColin Finck             if(!_SEH2_AbnormalTermination()) {
821c2c66affSColin Finck                 // Set mount event
822c2c66affSColin Finck 
823c2c66affSColin Finck                 UDFPrint(("UDFMountVolume: complete req RC %x\n", RC));
824c2c66affSColin Finck                 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_MOUNT);
825c2c66affSColin Finck                 // Complete the IRP.
826c2c66affSColin Finck                 Irp->IoStatus.Status = RC;
827c2c66affSColin Finck                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
828c2c66affSColin Finck             }
829c2c66affSColin Finck         } else {
830c2c66affSColin Finck             // Pass Irp to lower driver (CDFS)
831c2c66affSColin Finck 
832c2c66affSColin Finck             // Get this driver out of the driver stack and get to the next driver as
833c2c66affSColin Finck             // quickly as possible.
834c2c66affSColin Finck             Irp->CurrentLocation++;
835c2c66affSColin Finck             Irp->Tail.Overlay.CurrentStackLocation++;
836c2c66affSColin Finck 
837c2c66affSColin Finck             // Now call the appropriate file system driver with the request.
838c2c66affSColin Finck             RC = IoCallDriver( filterDevExt->lowerFSDeviceObject, Irp );
839c2c66affSColin Finck 
840c2c66affSColin Finck         }
841c2c66affSColin Finck 
842c2c66affSColin Finck     } _SEH2_END;
843c2c66affSColin Finck 
844c2c66affSColin Finck     UDFPrint(("UDFMountVolume: final RC = %x\n", RC));
845c2c66affSColin Finck     return RC;
846c2c66affSColin Finck 
847c2c66affSColin Finck } // end UDFMountVolume()
848c2c66affSColin Finck 
849c2c66affSColin Finck NTSTATUS
UDFStartEjectWaiter(IN PVCB Vcb)850c2c66affSColin Finck UDFStartEjectWaiter(
851c2c66affSColin Finck     IN PVCB    Vcb
852c2c66affSColin Finck     )
853c2c66affSColin Finck {
854c2c66affSColin Finck //    NTSTATUS RC;
855c2c66affSColin Finck     PREVENT_MEDIA_REMOVAL_USER_IN Buff;
856c2c66affSColin Finck     UDFPrint(("UDFStartEjectWaiter:\n"));
857c2c66affSColin Finck 
858c2c66affSColin Finck     if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) {
859c2c66affSColin Finck         UDFPrint(("  UDF_VCB_FLAGS_MEDIA_READ_ONLY\n"));
860c2c66affSColin Finck     }
861c2c66affSColin Finck     if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_LOCKED) {
862c2c66affSColin Finck         UDFPrint(("  UDF_VCB_FLAGS_MEDIA_LOCKED\n"));
863c2c66affSColin Finck     }
864c2c66affSColin Finck     UDFPrint(("  EjectWaiter=%x\n", Vcb->EjectWaiter));
865c2c66affSColin Finck     if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) &&
866c2c66affSColin Finck        /*!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_LOCKED) &&*/
867c2c66affSColin Finck        !(Vcb->EjectWaiter)) {
868c2c66affSColin Finck 
869c2c66affSColin Finck         UDFPrint(("UDFStartEjectWaiter: check driver\n"));
870c2c66affSColin Finck         if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) &&
871c2c66affSColin Finck             (Vcb->FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)) {
872c2c66affSColin Finck             // we don't know how to write without our device driver
873c2c66affSColin Finck             Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
874c2c66affSColin Finck             UDFPrint(("  not our driver, ignore\n"));
875c2c66affSColin Finck             return STATUS_SUCCESS;
876c2c66affSColin Finck         }
877c2c66affSColin Finck         UDFPrint(("UDFStartEjectWaiter: check removable\n"));
878c2c66affSColin Finck         if(Vcb->VCBFlags & UDF_VCB_FLAGS_REMOVABLE_MEDIA) {
879c2c66affSColin Finck             // prevent media removal
880c2c66affSColin Finck             UDFPrint(("UDFStartEjectWaiter: lock media\n"));
881c2c66affSColin Finck             Buff.PreventMediaRemoval = TRUE;
882c2c66affSColin Finck             UDFTSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
883c2c66affSColin Finck                            Vcb,
884c2c66affSColin Finck                            &Buff,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
885c2c66affSColin Finck                            NULL,0,
886c2c66affSColin Finck                            FALSE,NULL );
887c2c66affSColin Finck             Vcb->VCBFlags |= UDF_VCB_FLAGS_MEDIA_LOCKED;
888c2c66affSColin Finck         }
889c2c66affSColin Finck         UDFPrint(("UDFStartEjectWaiter: prepare to start\n"));
890c2c66affSColin Finck         // initialize Eject Request waiter
891c2c66affSColin Finck         Vcb->EjectWaiter = (PUDFEjectWaitContext)MyAllocatePool__(NonPagedPool, sizeof(UDFEjectWaitContext));
892c2c66affSColin Finck         if(!(Vcb->EjectWaiter)) return STATUS_INSUFFICIENT_RESOURCES;
893c2c66affSColin Finck         KeInitializeEvent(&(Vcb->WaiterStopped), NotificationEvent, FALSE);
894c2c66affSColin Finck         Vcb->EjectWaiter->Vcb = Vcb;
895c2c66affSColin Finck         Vcb->EjectWaiter->SoftEjectReq = FALSE;
896c2c66affSColin Finck         KeInitializeEvent(&(Vcb->EjectWaiter->StopReq), NotificationEvent, FALSE);
897c2c66affSColin Finck //        Vcb->EjectWaiter->StopReq = FALSE;
898c2c66affSColin Finck         Vcb->EjectWaiter->WaiterStopped = &(Vcb->WaiterStopped);
899c2c66affSColin Finck         // This can occure after unexpected media loss, when EjectRequestWaiter
900c2c66affSColin Finck         // terminates automatically
901c2c66affSColin Finck         ASSERT(!(Vcb->VCBFlags & UDF_VCB_FLAGS_STOP_WAITER_EVENT));
902c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_FLAGS_STOP_WAITER_EVENT;
903c2c66affSColin Finck         ExInitializeWorkItem(&(Vcb->EjectWaiter->EjectReqWorkQueueItem), UDFEjectReqWaiter, Vcb->EjectWaiter);
904c2c66affSColin Finck         UDFPrint(("UDFStartEjectWaiter: create thread\n"));
905c2c66affSColin Finck         ExQueueWorkItem(&(Vcb->EjectWaiter->EjectReqWorkQueueItem), DelayedWorkQueue);
906c2c66affSColin Finck     } else {
907c2c66affSColin Finck         UDFPrint(("  ignore\n"));
908c2c66affSColin Finck     }
909c2c66affSColin Finck     return STATUS_SUCCESS;
910c2c66affSColin Finck } // end UDFStartEjectWaiter()
911c2c66affSColin Finck 
912c2c66affSColin Finck NTSTATUS
UDFCompleteMount(IN PVCB Vcb)913c2c66affSColin Finck UDFCompleteMount(
914c2c66affSColin Finck     IN PVCB    Vcb
915c2c66affSColin Finck     )
916c2c66affSColin Finck {
917c2c66affSColin Finck     NTSTATUS                    RC;// = STATUS_SUCCESS;
918c2c66affSColin Finck     PtrUDFNTRequiredFCB         NtReqFcb = NULL;
919c2c66affSColin Finck     PFSRTL_COMMON_FCB_HEADER    PtrCommonFCBHeader = NULL;
920c2c66affSColin Finck     UNICODE_STRING              LocalPath;
921c2c66affSColin Finck     PtrUDFObjectName            RootName;
922c2c66affSColin Finck     PtrUDFFCB                   RootFcb;
923c2c66affSColin Finck 
924c2c66affSColin Finck     UDFPrint(("UDFCompleteMount:\n"));
925c2c66affSColin Finck     Vcb->ZBuffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, max(Vcb->LBlockSize, PAGE_SIZE), 'zNWD');
926c2c66affSColin Finck     if(!Vcb->ZBuffer) return STATUS_INSUFFICIENT_RESOURCES;
927c2c66affSColin Finck     RtlZeroMemory(Vcb->ZBuffer, Vcb->LBlockSize);
928c2c66affSColin Finck 
929c2c66affSColin Finck     UDFPrint(("UDFCompleteMount: alloc Root FCB\n"));
930c2c66affSColin Finck     // Create the root index and reference it in the Vcb.
931c2c66affSColin Finck     RootFcb =
932c2c66affSColin Finck     Vcb->RootDirFCB = UDFAllocateFCB();
933c2c66affSColin Finck     if(!RootFcb) return STATUS_INSUFFICIENT_RESOURCES;
934c2c66affSColin Finck 
935c2c66affSColin Finck     UDFPrint(("UDFCompleteMount: alloc Root ObjName\n"));
936c2c66affSColin Finck     // Allocate and set root FCB unique name
937c2c66affSColin Finck     RootName = UDFAllocateObjectName();
938c2c66affSColin Finck     if(!RootName) {
939c2c66affSColin Finck         UDFCleanUpFCB(RootFcb);
940c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
941c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
942c2c66affSColin Finck     }
943c2c66affSColin Finck     RC = MyInitUnicodeString(&(RootName->ObjectName),UDF_ROOTDIR_NAME);
944c2c66affSColin Finck     if(!NT_SUCCESS(RC))
945c2c66affSColin Finck         goto insuf_res_1;
946c2c66affSColin Finck 
947c2c66affSColin Finck     RootFcb->FileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO));
948c2c66affSColin Finck     if(!RootFcb->FileInfo) {
949c2c66affSColin Finck         RC = STATUS_INSUFFICIENT_RESOURCES;
950c2c66affSColin Finck insuf_res_1:
951c2c66affSColin Finck         MyFreePool__(RootName->ObjectName.Buffer);
952c2c66affSColin Finck         UDFReleaseObjectName(RootName);
953c2c66affSColin Finck         UDFCleanUpFCB(RootFcb);
954c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
955c2c66affSColin Finck         return RC;
956c2c66affSColin Finck     }
957c2c66affSColin Finck     UDFPrint(("UDFCompleteMount: open Root Dir\n"));
958c2c66affSColin Finck     // Open Root Directory
959c2c66affSColin Finck     RC = UDFOpenRootFile__( Vcb, &(Vcb->RootLbAddr), RootFcb->FileInfo );
960c2c66affSColin Finck     if(!NT_SUCCESS(RC)) {
961c2c66affSColin Finck insuf_res_2:
962c2c66affSColin Finck         UDFCleanUpFile__(Vcb, RootFcb->FileInfo);
963c2c66affSColin Finck         MyFreePool__(RootFcb->FileInfo);
964c2c66affSColin Finck         goto insuf_res_1;
965c2c66affSColin Finck     }
966c2c66affSColin Finck     RootFcb->FileInfo->Fcb = RootFcb;
967c2c66affSColin Finck 
968c2c66affSColin Finck     if(!(RootFcb->NTRequiredFCB = RootFcb->FileInfo->Dloc->CommonFcb)) {
969c2c66affSColin Finck         UDFPrint(("UDFCompleteMount: alloc Root ObjName (2)\n"));
970c2c66affSColin Finck         if(!(RootFcb->NTRequiredFCB =
971c2c66affSColin Finck                     (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB))) ) ) {
972c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
973c2c66affSColin Finck             goto insuf_res_2;
974c2c66affSColin Finck         }
975c2c66affSColin Finck         RtlZeroMemory(RootFcb->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
976c2c66affSColin Finck         RootFcb->FileInfo->Dloc->CommonFcb = RootFcb->NTRequiredFCB;
977c2c66affSColin Finck     }
978c2c66affSColin Finck     UDFPrint(("UDFCompleteMount: init FCB\n"));
979c2c66affSColin Finck     RC = UDFInitializeFCB(RootFcb,Vcb,RootName,UDF_FCB_ROOT_DIRECTORY | UDF_FCB_DIRECTORY,NULL);
980c2c66affSColin Finck     if(!NT_SUCCESS(RC)) {
981c2c66affSColin Finck         // if we get here, no resources are inited
982c2c66affSColin Finck         RootFcb->OpenHandleCount =
983c2c66affSColin Finck         RootFcb->ReferenceCount  =
984c2c66affSColin Finck         RootFcb->NTRequiredFCB->CommonRefCount = 0;
985c2c66affSColin Finck 
986c2c66affSColin Finck         UDFCleanUpFile__(Vcb, RootFcb->FileInfo);
987c2c66affSColin Finck         MyFreePool__(RootFcb->FileInfo);
988c2c66affSColin Finck         MyFreePool__(RootFcb->NTRequiredFCB);
989c2c66affSColin Finck         UDFCleanUpFCB(RootFcb);
990c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
991c2c66affSColin Finck         return RC;
992c2c66affSColin Finck     }
993c2c66affSColin Finck 
994c2c66affSColin Finck     // this is a part of UDF_RESIDUAL_REFERENCE
995c2c66affSColin Finck     UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
996c2c66affSColin Finck     RootFcb->OpenHandleCount =
997c2c66affSColin Finck     RootFcb->ReferenceCount  =
998c2c66affSColin Finck     RootFcb->NTRequiredFCB->CommonRefCount = 1;
999c2c66affSColin Finck 
1000c2c66affSColin Finck     UDFGetFileXTime(RootFcb->FileInfo,
1001c2c66affSColin Finck                   &(RootFcb->NTRequiredFCB->CreationTime.QuadPart),
1002c2c66affSColin Finck                   &(RootFcb->NTRequiredFCB->LastAccessTime.QuadPart),
1003c2c66affSColin Finck                   &(RootFcb->NTRequiredFCB->ChangeTime.QuadPart),
1004c2c66affSColin Finck                   &(RootFcb->NTRequiredFCB->LastWriteTime.QuadPart) );
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     if(Vcb->SysStreamLbAddr.logicalBlockNum) {
1007c2c66affSColin Finck         Vcb->SysSDirFileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO));
1008c2c66affSColin Finck         if(!Vcb->SysSDirFileInfo) {
1009c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
1010c2c66affSColin Finck             goto unwind_1;
1011c2c66affSColin Finck         }
1012c2c66affSColin Finck         // Open System SDir Directory
1013c2c66affSColin Finck         RC = UDFOpenRootFile__( Vcb, &(Vcb->SysStreamLbAddr), Vcb->SysSDirFileInfo );
1014c2c66affSColin Finck         if(!NT_SUCCESS(RC)) {
1015c2c66affSColin Finck             UDFCleanUpFile__(Vcb, Vcb->SysSDirFileInfo);
1016c2c66affSColin Finck             MyFreePool__(Vcb->SysSDirFileInfo);
1017c2c66affSColin Finck             Vcb->SysSDirFileInfo = NULL;
1018c2c66affSColin Finck             goto unwind_1;
1019c2c66affSColin Finck         } else {
1020c2c66affSColin Finck             Vcb->SysSDirFileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_VERIFY;
1021c2c66affSColin Finck         }
1022c2c66affSColin Finck     }
1023c2c66affSColin Finck 
1024c2c66affSColin Finck     // Open Unallocatable space stream
1025c2c66affSColin Finck     // Generally, it should be placed in SystemStreamDirectory, but some
1026c2c66affSColin Finck     // stupid apps think that RootDirectory is much better place.... :((
1027c2c66affSColin Finck     RC = MyInitUnicodeString(&LocalPath, UDF_FN_NON_ALLOCATABLE);
1028c2c66affSColin Finck     if(NT_SUCCESS(RC)) {
1029c2c66affSColin Finck         RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, RootFcb->FileInfo, &(Vcb->NonAllocFileInfo), NULL);
1030c2c66affSColin Finck         MyFreePool__(LocalPath.Buffer);
1031c2c66affSColin Finck     }
1032c2c66affSColin Finck     if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) {
1033c2c66affSColin Finck 
1034c2c66affSColin Finck //unwind_2:
1035c2c66affSColin Finck         UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo);
1036c2c66affSColin Finck         Vcb->NonAllocFileInfo = NULL;
1037c2c66affSColin Finck         // this was a part of UDF_RESIDUAL_REFERENCE
1038c2c66affSColin Finck         UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
1039c2c66affSColin Finck unwind_1:
1040c2c66affSColin Finck 
1041c2c66affSColin Finck         // UDFCloseResidual() will clean up everything
1042c2c66affSColin Finck 
1043c2c66affSColin Finck         return RC;
1044c2c66affSColin Finck     }
1045c2c66affSColin Finck 
1046c2c66affSColin Finck     /* process Non-allocatable */
1047c2c66affSColin Finck     if(NT_SUCCESS(RC)) {
1048c2c66affSColin Finck         UDFMarkSpaceAsXXX(Vcb, Vcb->NonAllocFileInfo->Dloc, Vcb->NonAllocFileInfo->Dloc->DataLoc.Mapping, AS_USED); // used
1049c2c66affSColin Finck         UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL;
1050c2c66affSColin Finck     } else {
1051c2c66affSColin Finck         /* try to read Non-allocatable from alternate locations */
1052c2c66affSColin Finck         RC = MyInitUnicodeString(&LocalPath, UDF_FN_NON_ALLOCATABLE_2);
1053c2c66affSColin Finck         if(!NT_SUCCESS(RC)) {
1054c2c66affSColin Finck             goto unwind_1;
1055c2c66affSColin Finck         }
1056c2c66affSColin Finck         RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, RootFcb->FileInfo, &(Vcb->NonAllocFileInfo), NULL);
1057c2c66affSColin Finck         MyFreePool__(LocalPath.Buffer);
1058c2c66affSColin Finck         if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) {
1059c2c66affSColin Finck             goto unwind_1;
1060c2c66affSColin Finck         }
1061c2c66affSColin Finck         if(NT_SUCCESS(RC)) {
1062c2c66affSColin Finck             UDFMarkSpaceAsXXX(Vcb, Vcb->NonAllocFileInfo->Dloc, Vcb->NonAllocFileInfo->Dloc->DataLoc.Mapping, AS_USED); // used
1063c2c66affSColin Finck             UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL;
1064c2c66affSColin Finck         } else
1065c2c66affSColin Finck         if(Vcb->SysSDirFileInfo) {
1066c2c66affSColin Finck             RC = MyInitUnicodeString(&LocalPath, UDF_SN_NON_ALLOCATABLE);
1067c2c66affSColin Finck             if(!NT_SUCCESS(RC)) {
1068c2c66affSColin Finck                 goto unwind_1;
1069c2c66affSColin Finck             }
1070c2c66affSColin Finck             RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, Vcb->SysSDirFileInfo , &(Vcb->NonAllocFileInfo), NULL);
1071c2c66affSColin Finck             MyFreePool__(LocalPath.Buffer);
1072c2c66affSColin Finck             if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) {
1073c2c66affSColin Finck                 goto unwind_1;
1074c2c66affSColin Finck             }
1075c2c66affSColin Finck             if(NT_SUCCESS(RC)) {
1076c2c66affSColin Finck                 UDFMarkSpaceAsXXX(Vcb, Vcb->NonAllocFileInfo->Dloc, Vcb->NonAllocFileInfo->Dloc->DataLoc.Mapping, AS_USED); // used
1077c2c66affSColin Finck //                    UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL;
1078c2c66affSColin Finck             } else {
1079c2c66affSColin Finck                 RC = STATUS_SUCCESS;
1080c2c66affSColin Finck             }
1081c2c66affSColin Finck         } else {
1082c2c66affSColin Finck             RC = STATUS_SUCCESS;
1083c2c66affSColin Finck         }
1084c2c66affSColin Finck     }
1085c2c66affSColin Finck 
1086c2c66affSColin Finck     /* Read SN UID mapping */
1087c2c66affSColin Finck     if(Vcb->SysSDirFileInfo) {
1088c2c66affSColin Finck         RC = MyInitUnicodeString(&LocalPath, UDF_SN_UID_MAPPING);
1089c2c66affSColin Finck         if(!NT_SUCCESS(RC))
1090c2c66affSColin Finck             goto unwind_3;
1091c2c66affSColin Finck         RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, Vcb->SysSDirFileInfo , &(Vcb->UniqueIDMapFileInfo), NULL);
1092c2c66affSColin Finck         MyFreePool__(LocalPath.Buffer);
1093c2c66affSColin Finck         if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) {
1094c2c66affSColin Finck unwind_3:
1095c2c66affSColin Finck //            UDFCloseFile__(Vcb, Vcb->NonAllocFileInfo);
1096c2c66affSColin Finck //            UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo);
1097c2c66affSColin Finck //            if(Vcb->NonAllocFileInfo)
1098c2c66affSColin Finck //                MyFreePool__(Vcb->NonAllocFileInfo);
1099c2c66affSColin Finck //            Vcb->NonAllocFileInfo = NULL;
1100c2c66affSColin Finck             goto unwind_1;
1101c2c66affSColin Finck         } else {
1102c2c66affSColin Finck             Vcb->UniqueIDMapFileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_VERIFY;
1103c2c66affSColin Finck         }
1104c2c66affSColin Finck         RC = STATUS_SUCCESS;
1105c2c66affSColin Finck     }
1106c2c66affSColin Finck 
1107c2c66affSColin Finck #define DWN_MAX_CFG_FILE_SIZE  0x10000
1108c2c66affSColin Finck 
1109c2c66affSColin Finck     /* Read DWN config file from disk with disk-specific options */
1110c2c66affSColin Finck     RC = MyInitUnicodeString(&LocalPath, UDF_CONFIG_STREAM_NAME_W);
1111c2c66affSColin Finck     if(NT_SUCCESS(RC)) {
1112c2c66affSColin Finck 
1113c2c66affSColin Finck         int8* buff;
1114*c334c17dSTimo Kreuzer         SIZE_T len;
1115c2c66affSColin Finck         PUDF_FILE_INFO CfgFileInfo = NULL;
1116c2c66affSColin Finck 
1117c2c66affSColin Finck         RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, RootFcb->FileInfo, &CfgFileInfo, NULL);
1118c2c66affSColin Finck         if(OS_SUCCESS(RC)) {
1119c2c66affSColin Finck 
1120c2c66affSColin Finck             len = (ULONG)UDFGetFileSize(CfgFileInfo);
1121c2c66affSColin Finck             if(len && len < DWN_MAX_CFG_FILE_SIZE) {
1122c2c66affSColin Finck                 buff = (int8*)MyAllocatePool__(NonPagedPool, len);
1123c2c66affSColin Finck                 if(buff) {
1124c2c66affSColin Finck                     RC = UDFReadFile__(Vcb, CfgFileInfo, 0, len, FALSE, buff, &len);
1125c2c66affSColin Finck                     if(OS_SUCCESS(RC)) {
1126c2c66affSColin Finck                         // parse config
1127c2c66affSColin Finck                         Vcb->Cfg = (PUCHAR)buff;
1128c2c66affSColin Finck                         Vcb->CfgLength = len;
1129c2c66affSColin Finck                         UDFReadRegKeys(Vcb, TRUE /*update*/, TRUE /*cfg*/);
1130c2c66affSColin Finck                         Vcb->Cfg = NULL;
1131c2c66affSColin Finck                         Vcb->CfgLength = 0;
1132c2c66affSColin Finck                         Vcb->CfgVersion = 0;
1133c2c66affSColin Finck                     }
1134c2c66affSColin Finck                     MyFreePool__(buff);
1135c2c66affSColin Finck                 }
1136c2c66affSColin Finck             }
1137c2c66affSColin Finck 
1138c2c66affSColin Finck             UDFCloseFile__(Vcb, CfgFileInfo);
1139c2c66affSColin Finck         }
1140c2c66affSColin Finck         if(CfgFileInfo) {
1141c2c66affSColin Finck             UDFCleanUpFile__(Vcb, CfgFileInfo);
1142c2c66affSColin Finck         }
1143c2c66affSColin Finck         MyFreePool__(LocalPath.Buffer);
1144c2c66affSColin Finck     }
1145c2c66affSColin Finck     RC = STATUS_SUCCESS;
1146c2c66affSColin Finck 
1147c2c66affSColin Finck     // clear Modified flags. It was not real modify, just
1148c2c66affSColin Finck     // bitmap construction
1149c2c66affSColin Finck     Vcb->BitmapModified = FALSE;
1150c2c66affSColin Finck     //Vcb->Modified = FALSE;
1151c2c66affSColin Finck     UDFPreClrModified(Vcb);
1152c2c66affSColin Finck     UDFClrModified(Vcb);
1153c2c66affSColin Finck     // this is a part of UDF_RESIDUAL_REFERENCE
1154c2c66affSColin Finck     UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
1155c2c66affSColin Finck 
1156c2c66affSColin Finck     NtReqFcb = RootFcb->NTRequiredFCB;
1157c2c66affSColin Finck 
1158c2c66affSColin Finck     // Start initializing the fields contained in the CommonFCBHeader.
1159c2c66affSColin Finck     PtrCommonFCBHeader = &(NtReqFcb->CommonFCBHeader);
1160c2c66affSColin Finck 
1161c2c66affSColin Finck     // DisAllow fast-IO for now.
1162c2c66affSColin Finck //    PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible;
1163c2c66affSColin Finck     PtrCommonFCBHeader->IsFastIoPossible = FastIoIsPossible;
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     // Initialize the MainResource and PagingIoResource pointers in
1166c2c66affSColin Finck     // the CommonFCBHeader structure to point to the ERESOURCE structures we
1167c2c66affSColin Finck     // have allocated and already initialized above.
1168c2c66affSColin Finck //    PtrCommonFCBHeader->Resource = &(NtReqFcb->MainResource);
1169c2c66affSColin Finck //    PtrCommonFCBHeader->PagingIoResource = &(NtReqFcb->PagingIoResource);
1170c2c66affSColin Finck 
1171c2c66affSColin Finck     // Initialize the file size values here.
1172c2c66affSColin Finck     PtrCommonFCBHeader->AllocationSize.QuadPart = 0;
1173c2c66affSColin Finck     PtrCommonFCBHeader->FileSize.QuadPart = 0;
1174c2c66affSColin Finck 
1175c2c66affSColin Finck     // The following will disable ValidDataLength support.
1176c2c66affSColin Finck //    PtrCommonFCBHeader->ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFI64;
1177c2c66affSColin Finck     PtrCommonFCBHeader->ValidDataLength.QuadPart = 0;
1178c2c66affSColin Finck 
1179c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1180c2c66affSColin Finck         return RC;
1181c2c66affSColin Finck     UDFAssignAcl(Vcb, NULL, RootFcb, NtReqFcb);
1182c2c66affSColin Finck /*
1183c2c66affSColin Finck     Vcb->CDBurnerVolumeValid = true;
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     len =
1186c2c66affSColin Finck     Vcb->CDBurnerVolume.Length = 256;
1187c2c66affSColin Finck     Vcb->CDBurnerVolume.MaximumLength = 256;
1188c2c66affSColin Finck     Vcb->CDBurnerVolume.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, 256);
1189c2c66affSColin Finck     RC = RegTGetStringValue(NULL, REG_CD_BURNER_KEY_NAME, REG_CD_BURNER_VOLUME_NAME, Vcb->CDBurnerVolume.Buffer,
1190c2c66affSColin Finck         len);
1191c2c66affSColin Finck     Vcb->CDBurnerVolume.Length = (USHORT)(wcslen(Vcb->CDBurnerVolume.Buffer)*sizeof(WCHAR));
1192c2c66affSColin Finck 
1193c2c66affSColin Finck     if(RC != STATUS_OBJECT_NAME_NOT_FOUND && !NT_SUCCESS(RC) )
1194c2c66affSColin Finck         return RC;
1195c2c66affSColin Finck 
1196c2c66affSColin Finck     if (NT_SUCCESS(RC)) {
1197c2c66affSColin Finck         RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
1198c2c66affSColin Finck                               REG_CD_BURNER_KEY_NAME, REG_CD_BURNER_VOLUME_NAME,
1199c2c66affSColin Finck                               REG_SZ,L"",sizeof(L"")+1);
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     } else {
1202c2c66affSColin Finck         Vcb->CDBurnerVolumeValid = false;
1203c2c66affSColin Finck         RC = STATUS_SUCCESS;
1204c2c66affSColin Finck     }
1205c2c66affSColin Finck */
1206c2c66affSColin Finck     ASSERT(!Vcb->Modified);
1207c2c66affSColin Finck 
1208c2c66affSColin Finck     return RC;
1209c2c66affSColin Finck } // end UDFCompleteMount()
1210c2c66affSColin Finck 
1211c2c66affSColin Finck NTSTATUS
UDFBlankMount(IN PVCB Vcb)1212c2c66affSColin Finck UDFBlankMount(
1213c2c66affSColin Finck     IN PVCB    Vcb
1214c2c66affSColin Finck     )
1215c2c66affSColin Finck {
1216c2c66affSColin Finck     NTSTATUS                    RC;// = STATUS_SUCCESS;
1217c2c66affSColin Finck     PtrUDFNTRequiredFCB         NtReqFcb = NULL;
1218c2c66affSColin Finck     PFSRTL_COMMON_FCB_HEADER    PtrCommonFCBHeader = NULL;
1219c2c66affSColin Finck     PtrUDFObjectName            RootName;
1220c2c66affSColin Finck     PtrUDFFCB                   RootFcb;
1221c2c66affSColin Finck     PDIR_INDEX_HDR hDirNdx;
1222c2c66affSColin Finck     PDIR_INDEX_ITEM DirNdx;
1223c2c66affSColin Finck 
1224c2c66affSColin Finck     // Create the root index and reference it in the Vcb.
1225c2c66affSColin Finck     RootFcb =
1226c2c66affSColin Finck     Vcb->RootDirFCB = UDFAllocateFCB();
1227c2c66affSColin Finck     if(!RootFcb) return STATUS_INSUFFICIENT_RESOURCES;
1228c2c66affSColin Finck     RtlZeroMemory(RootFcb,sizeof(UDFFCB));
1229c2c66affSColin Finck 
1230c2c66affSColin Finck     // Allocate and set root FCB unique name
1231c2c66affSColin Finck     RootName = UDFAllocateObjectName();
1232c2c66affSColin Finck     if(!RootName) {
1233c2c66affSColin Finck //bl_unwind_2:
1234c2c66affSColin Finck         UDFCleanUpFCB(RootFcb);
1235c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
1236c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
1237c2c66affSColin Finck     }
1238c2c66affSColin Finck     RC = MyInitUnicodeString(&(RootName->ObjectName),UDF_ROOTDIR_NAME);
1239c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1240c2c66affSColin Finck         goto bl_unwind_1;
1241c2c66affSColin Finck 
1242c2c66affSColin Finck     RootFcb->NodeIdentifier.NodeType = UDF_NODE_TYPE_FCB;
1243c2c66affSColin Finck     RootFcb->NodeIdentifier.NodeSize = sizeof(UDFFCB);
1244c2c66affSColin Finck 
1245c2c66affSColin Finck     RootFcb->FileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO));
1246c2c66affSColin Finck     if(!RootFcb->FileInfo) {
1247c2c66affSColin Finck         MyFreePool__(RootName->ObjectName.Buffer);
1248c2c66affSColin Finck         RC = STATUS_INSUFFICIENT_RESOURCES;
1249c2c66affSColin Finck bl_unwind_1:
1250c2c66affSColin Finck         UDFReleaseObjectName(RootName);
1251c2c66affSColin Finck         UDFCleanUpFCB(RootFcb);
1252c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
1253c2c66affSColin Finck         return RC;
1254c2c66affSColin Finck     }
1255c2c66affSColin Finck     RtlZeroMemory(RootFcb->FileInfo, sizeof(UDF_FILE_INFO));
1256c2c66affSColin Finck     if(!OS_SUCCESS(RC = UDFStoreDloc(Vcb, RootFcb->FileInfo, 1))) {
1257c2c66affSColin Finck         MyFreePool__(RootFcb->FileInfo);
1258c2c66affSColin Finck         RootFcb->FileInfo = NULL;
1259c2c66affSColin Finck         MyFreePool__(RootName->ObjectName.Buffer);
1260c2c66affSColin Finck         goto  bl_unwind_1;
1261c2c66affSColin Finck     }
1262c2c66affSColin Finck     RootFcb->FileInfo->NextLinkedFile =
1263c2c66affSColin Finck     RootFcb->FileInfo->PrevLinkedFile = RootFcb->FileInfo;
1264c2c66affSColin Finck 
1265c2c66affSColin Finck     hDirNdx = UDFDirIndexAlloc(2);
1266c2c66affSColin Finck     DirNdx = UDFDirIndex(hDirNdx,0);
1267c2c66affSColin Finck     DirNdx->FileCharacteristics = FILE_DIRECTORY;
1268c2c66affSColin Finck     DirNdx->FI_Flags = UDF_FI_FLAG_SYS_ATTR;
1269c2c66affSColin Finck     DirNdx->SysAttr = FILE_ATTRIBUTE_READONLY;
1270c2c66affSColin Finck     RtlInitUnicodeString(&DirNdx->FName, L".");
1271c2c66affSColin Finck     DirNdx->FileInfo = RootFcb->FileInfo;
1272c2c66affSColin Finck     DirNdx->FI_Flags |= UDFBuildHashEntry(Vcb, &(DirNdx->FName), &(DirNdx->hashes), HASH_ALL | HASH_KEEP_NAME);
1273c2c66affSColin Finck 
1274c2c66affSColin Finck     DirNdx = UDFDirIndex(hDirNdx,1);
1275c2c66affSColin Finck     DirNdx->FI_Flags = UDF_FI_FLAG_SYS_ATTR;
1276c2c66affSColin Finck     if(Vcb->ShowBlankCd == 2) {
1277c2c66affSColin Finck         DirNdx->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL;
1278c2c66affSColin Finck     }
1279c2c66affSColin Finck     DirNdx->SysAttr = FILE_ATTRIBUTE_READONLY;
1280c2c66affSColin Finck     RtlInitUnicodeString(&DirNdx->FName, L"Blank.CD");
1281c2c66affSColin Finck     DirNdx->FI_Flags |= UDFBuildHashEntry(Vcb, &(DirNdx->FName), &(DirNdx->hashes), HASH_ALL);
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     RootFcb->FileInfo->Dloc->DirIndex = hDirNdx;
1284c2c66affSColin Finck     RootFcb->FileInfo->Fcb = RootFcb;
1285c2c66affSColin Finck 
1286c2c66affSColin Finck     if(!(RootFcb->NTRequiredFCB = RootFcb->FileInfo->Dloc->CommonFcb)) {
1287c2c66affSColin Finck         if(!(RootFcb->NTRequiredFCB =
1288c2c66affSColin Finck                     (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB))) ) ) {
1289c2c66affSColin Finck             MyFreePool__(RootName->ObjectName.Buffer);
1290c2c66affSColin Finck             UDFReleaseObjectName(RootName);
1291c2c66affSColin Finck             UDFCleanUpFCB(RootFcb);
1292c2c66affSColin Finck             Vcb->RootDirFCB = NULL;
1293c2c66affSColin Finck             return STATUS_INSUFFICIENT_RESOURCES;
1294c2c66affSColin Finck         }
1295c2c66affSColin Finck         RtlZeroMemory(RootFcb->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
1296c2c66affSColin Finck         RootFcb->FileInfo->Dloc->CommonFcb = RootFcb->NTRequiredFCB;
1297c2c66affSColin Finck     }
1298c2c66affSColin Finck     RC = UDFInitializeFCB(RootFcb,Vcb,RootName,UDF_FCB_ROOT_DIRECTORY | UDF_FCB_DIRECTORY,NULL);
1299c2c66affSColin Finck     if(!NT_SUCCESS(RC)) {
1300c2c66affSColin Finck         // if we get here, no resources are inited
1301c2c66affSColin Finck         RootFcb->OpenHandleCount =
1302c2c66affSColin Finck         RootFcb->ReferenceCount  =
1303c2c66affSColin Finck         RootFcb->NTRequiredFCB->CommonRefCount = 0;
1304c2c66affSColin Finck 
1305c2c66affSColin Finck         UDFCleanUpFile__(Vcb, RootFcb->FileInfo);
1306c2c66affSColin Finck         MyFreePool__(RootFcb->FileInfo);
1307c2c66affSColin Finck         MyFreePool__(RootFcb->NTRequiredFCB);
1308c2c66affSColin Finck         UDFCleanUpFCB(RootFcb);
1309c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
1310c2c66affSColin Finck         return RC;
1311c2c66affSColin Finck     }
1312c2c66affSColin Finck 
1313c2c66affSColin Finck     // this is a part of UDF_RESIDUAL_REFERENCE
1314c2c66affSColin Finck     UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
1315c2c66affSColin Finck     RootFcb->OpenHandleCount =
1316c2c66affSColin Finck     RootFcb->ReferenceCount  =
1317c2c66affSColin Finck     RootFcb->NTRequiredFCB->CommonRefCount =
1318c2c66affSColin Finck     RootFcb->FileInfo->RefCount =
1319c2c66affSColin Finck     RootFcb->FileInfo->Dloc->LinkRefCount = 1;
1320c2c66affSColin Finck 
1321c2c66affSColin Finck     // this is a part of UDF_RESIDUAL_REFERENCE
1322c2c66affSColin Finck     UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
1323c2c66affSColin Finck 
1324c2c66affSColin Finck     NtReqFcb = RootFcb->NTRequiredFCB;
1325c2c66affSColin Finck 
1326c2c66affSColin Finck     // Start initializing the fields contained in the CommonFCBHeader.
1327c2c66affSColin Finck     PtrCommonFCBHeader = &(NtReqFcb->CommonFCBHeader);
1328c2c66affSColin Finck 
1329c2c66affSColin Finck     // DisAllow fast-IO for now.
1330c2c66affSColin Finck     PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible;
1331c2c66affSColin Finck 
1332c2c66affSColin Finck     // Initialize the MainResource and PagingIoResource pointers in
1333c2c66affSColin Finck     // the CommonFCBHeader structure to point to the ERESOURCE structures we
1334c2c66affSColin Finck     // have allocated and already initialized above.
1335c2c66affSColin Finck     PtrCommonFCBHeader->Resource = &(NtReqFcb->MainResource);
1336c2c66affSColin Finck     PtrCommonFCBHeader->PagingIoResource = &(NtReqFcb->PagingIoResource);
1337c2c66affSColin Finck 
1338c2c66affSColin Finck     // Initialize the file size values here.
1339c2c66affSColin Finck     PtrCommonFCBHeader->AllocationSize.QuadPart = 0;
1340c2c66affSColin Finck     PtrCommonFCBHeader->FileSize.QuadPart = 0;
1341c2c66affSColin Finck 
1342c2c66affSColin Finck     // The following will disable ValidDataLength support.
1343c2c66affSColin Finck     PtrCommonFCBHeader->ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFLL;
1344c2c66affSColin Finck 
1345c2c66affSColin Finck     return RC;
1346c2c66affSColin Finck } // end UDFBlankMount()
1347c2c66affSColin Finck 
1348c2c66affSColin Finck VOID
UDFCloseResidual(IN PVCB Vcb)1349c2c66affSColin Finck UDFCloseResidual(
1350c2c66affSColin Finck     IN PVCB Vcb
1351c2c66affSColin Finck     )
1352c2c66affSColin Finck {
1353c2c66affSColin Finck     //  Deinitialize Non-alloc file
1354c2c66affSColin Finck     if(Vcb->VCBOpenCount)
1355c2c66affSColin Finck         UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
1356c2c66affSColin Finck     UDFPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb->NonAllocFileInfo));
1357c2c66affSColin Finck     if(Vcb->NonAllocFileInfo) {
1358c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->NonAllocFileInfo);
1359c2c66affSColin Finck         UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo);
1360c2c66affSColin Finck         MyFreePool__(Vcb->NonAllocFileInfo);
1361c2c66affSColin Finck         Vcb->NonAllocFileInfo = NULL;
1362c2c66affSColin Finck     }
1363c2c66affSColin Finck     //  Deinitialize Unique ID Mapping
1364c2c66affSColin Finck     UDFPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb->NonAllocFileInfo));
1365c2c66affSColin Finck     if(Vcb->UniqueIDMapFileInfo) {
1366c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->UniqueIDMapFileInfo);
1367c2c66affSColin Finck         UDFCleanUpFile__(Vcb, Vcb->UniqueIDMapFileInfo);
1368c2c66affSColin Finck         MyFreePool__(Vcb->UniqueIDMapFileInfo);
1369c2c66affSColin Finck         Vcb->UniqueIDMapFileInfo = NULL;
1370c2c66affSColin Finck     }
1371c2c66affSColin Finck     //  Deinitialize VAT file
1372c2c66affSColin Finck     UDFPrint(("UDFCloseResidual: VatFileInfo %x\n", Vcb->VatFileInfo));
1373c2c66affSColin Finck     if(Vcb->VatFileInfo) {
1374c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->VatFileInfo);
1375c2c66affSColin Finck         UDFCleanUpFile__(Vcb, Vcb->VatFileInfo);
1376c2c66affSColin Finck         MyFreePool__(Vcb->VatFileInfo);
1377c2c66affSColin Finck         Vcb->VatFileInfo = NULL;
1378c2c66affSColin Finck     }
1379c2c66affSColin Finck     //  System StreamDir
1380c2c66affSColin Finck     UDFPrint(("UDFCloseResidual: SysSDirFileInfo %x\n", Vcb->SysSDirFileInfo));
1381c2c66affSColin Finck     if(Vcb->SysSDirFileInfo) {
1382c2c66affSColin Finck         UDFCloseFile__(Vcb, Vcb->SysSDirFileInfo);
1383c2c66affSColin Finck         UDFCleanUpFile__(Vcb, Vcb->SysSDirFileInfo);
1384c2c66affSColin Finck         MyFreePool__(Vcb->SysSDirFileInfo);
1385c2c66affSColin Finck         Vcb->SysSDirFileInfo = NULL;
1386c2c66affSColin Finck     }
1387c2c66affSColin Finck /*    //  Deinitialize root dir fcb
1388c2c66affSColin Finck     if(Vcb->RootDirFCB) {
1389c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->RootDirFCB->FileInfo);
1390c2c66affSColin Finck         UDFCleanUpFile__(Vcb, Vcb->RootDirFCB->FileInfo);
1391c2c66affSColin Finck         MyFreePool__(Vcb->RootDirFCB->FileInfo);
1392c2c66affSColin Finck         UDFCleanUpFCB(Vcb->RootDirFCB);
1393c2c66affSColin Finck         //  Remove root FCB reference in vcb
1394c2c66affSColin Finck         if(Vcb->VCBOpenCount) Vcb->VCBOpenCount--;
1395c2c66affSColin Finck     }
1396c2c66affSColin Finck 
1397c2c66affSColin Finck     // Deinitialize Non-alloc file
1398c2c66affSColin Finck     if(Vcb->VCBOpenCount) Vcb->VCBOpenCount--;
1399c2c66affSColin Finck     if(Vcb->NonAllocFileInfo) {
1400c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->NonAllocFileInfo);
1401c2c66affSColin Finck         // We must release VCB here !!!!
1402c2c66affSColin Finck //        UDFCleanUpFcbChain(Vcb, Vcb->NonAllocFileInfo, 1);
1403c2c66affSColin Finck         Vcb->NonAllocFileInfo = NULL;
1404c2c66affSColin Finck     }
1405c2c66affSColin Finck     // Deinitialize VAT file
1406c2c66affSColin Finck     if(Vcb->VatFileInfo) {
1407c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->VatFileInfo);
1408c2c66affSColin Finck         // We must release VCB here !!!!
1409c2c66affSColin Finck //        UDFCleanUpFcbChain(Vcb, Vcb->VatFileInfo, 1);
1410c2c66affSColin Finck         Vcb->VatFileInfo = NULL;
1411c2c66affSColin Finck     }*/
1412c2c66affSColin Finck 
1413c2c66affSColin Finck     // Deinitialize root dir fcb
1414c2c66affSColin Finck     UDFPrint(("UDFCloseResidual: RootDirFCB %x\n", Vcb->RootDirFCB));
1415c2c66affSColin Finck     if(Vcb->RootDirFCB) {
1416c2c66affSColin Finck         UDFCloseFile__(Vcb,Vcb->RootDirFCB->FileInfo);
1417c2c66affSColin Finck         if(Vcb->RootDirFCB->OpenHandleCount)
1418c2c66affSColin Finck             Vcb->RootDirFCB->OpenHandleCount--;
1419c2c66affSColin Finck         UDFCleanUpFcbChain(Vcb, Vcb->RootDirFCB->FileInfo, 1, TRUE);
1420c2c66affSColin Finck         // Remove root FCB reference in vcb
1421c2c66affSColin Finck         if(Vcb->VCBOpenCount)
1422c2c66affSColin Finck             UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
1423c2c66affSColin Finck         Vcb->RootDirFCB = NULL;
1424c2c66affSColin Finck     }
1425c2c66affSColin Finck } // end UDFCloseResidual()
1426c2c66affSColin Finck 
1427c2c66affSColin Finck VOID
UDFCleanupVCB(IN PVCB Vcb)1428c2c66affSColin Finck UDFCleanupVCB(
1429c2c66affSColin Finck     IN PVCB Vcb
1430c2c66affSColin Finck     )
1431c2c66affSColin Finck {
1432c2c66affSColin Finck     _SEH2_TRY {
1433c2c66affSColin Finck         UDFReleaseFileIdCache(Vcb);
1434c2c66affSColin Finck         UDFReleaseDlocList(Vcb);
1435c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1436c2c66affSColin Finck         BrutePoint();
1437c2c66affSColin Finck     } _SEH2_END;
1438c2c66affSColin Finck 
1439c2c66affSColin Finck     if(Vcb->ShutdownRegistered && Vcb->VCBDeviceObject) {
1440c2c66affSColin Finck         IoUnregisterShutdownNotification(Vcb->VCBDeviceObject);
1441c2c66affSColin Finck         Vcb->ShutdownRegistered = FALSE;
1442c2c66affSColin Finck     }
1443c2c66affSColin Finck 
1444c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->Partitions);
1445c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->LVid);
1446c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->Vat);
1447c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->SparingTable);
1448c2c66affSColin Finck 
1449c2c66affSColin Finck     if(Vcb->FSBM_Bitmap) {
1450c2c66affSColin Finck         DbgFreePool(Vcb->FSBM_Bitmap);
1451c2c66affSColin Finck         Vcb->FSBM_Bitmap = NULL;
1452c2c66affSColin Finck     }
1453c2c66affSColin Finck     if(Vcb->ZSBM_Bitmap) {
1454c2c66affSColin Finck         DbgFreePool(Vcb->ZSBM_Bitmap);
1455c2c66affSColin Finck         Vcb->ZSBM_Bitmap = NULL;
1456c2c66affSColin Finck     }
1457c2c66affSColin Finck     if(Vcb->BSBM_Bitmap) {
1458c2c66affSColin Finck         DbgFreePool(Vcb->BSBM_Bitmap);
1459c2c66affSColin Finck         Vcb->BSBM_Bitmap = NULL;
1460c2c66affSColin Finck     }
1461c2c66affSColin Finck #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1462c2c66affSColin Finck     if(Vcb->FSBM_Bitmap_owners) {
1463c2c66affSColin Finck         DbgFreePool(Vcb->FSBM_Bitmap_owners);
1464c2c66affSColin Finck         Vcb->FSBM_Bitmap_owners = NULL;
1465c2c66affSColin Finck     }
1466c2c66affSColin Finck #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1467c2c66affSColin Finck     if(Vcb->FSBM_OldBitmap) {
1468c2c66affSColin Finck         DbgFreePool(Vcb->FSBM_OldBitmap);
1469c2c66affSColin Finck         Vcb->FSBM_OldBitmap = NULL;
1470c2c66affSColin Finck     }
1471c2c66affSColin Finck 
1472c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->Statistics);
1473c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->NTRequiredFCB);
1474c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->VolIdent.Buffer);
1475c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->TargetDevName.Buffer);
1476c2c66affSColin Finck 
1477c2c66affSColin Finck     if(Vcb->ZBuffer) {
1478c2c66affSColin Finck         DbgFreePool(Vcb->ZBuffer);
1479c2c66affSColin Finck         Vcb->ZBuffer = NULL;
1480c2c66affSColin Finck     }
1481c2c66affSColin Finck 
1482c2c66affSColin Finck     if(Vcb->fZBuffer) {
1483c2c66affSColin Finck         DbgFreePool(Vcb->fZBuffer);
1484c2c66affSColin Finck         Vcb->fZBuffer = NULL;
1485c2c66affSColin Finck     }
1486c2c66affSColin Finck 
1487c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->OPCh);
1488c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->WParams);
1489c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->Error);
1490c2c66affSColin Finck     MyFreeMemoryAndPointer(Vcb->TrackMap);
1491c2c66affSColin Finck 
1492c2c66affSColin Finck } // end UDFCleanupVCB()
1493c2c66affSColin Finck 
1494c2c66affSColin Finck /*
1495c2c66affSColin Finck 
1496c2c66affSColin Finck Routine Description:
1497c2c66affSColin Finck 
1498c2c66affSColin Finck     This routine walks through the list of Vcb's looking for any which may
1499c2c66affSColin Finck     now be deleted.  They may have been left on the list because there were
1500c2c66affSColin Finck     outstanding references.
1501c2c66affSColin Finck 
1502c2c66affSColin Finck Arguments:
1503c2c66affSColin Finck 
1504c2c66affSColin Finck Return Value:
1505c2c66affSColin Finck 
1506c2c66affSColin Finck     None
1507c2c66affSColin Finck 
1508c2c66affSColin Finck */
1509c2c66affSColin Finck VOID
UDFScanForDismountedVcb(IN PtrUDFIrpContext IrpContext)1510c2c66affSColin Finck UDFScanForDismountedVcb(
1511c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext
1512c2c66affSColin Finck     )
1513c2c66affSColin Finck {
1514c2c66affSColin Finck     PVCB Vcb;
1515c2c66affSColin Finck     PLIST_ENTRY Link;
1516c2c66affSColin Finck 
1517c2c66affSColin Finck 
1518c2c66affSColin Finck     // Walk through all of the Vcb's attached to the global data.
1519c2c66affSColin Finck     Link = UDFGlobalData.VCBQueue.Flink;
1520c2c66affSColin Finck 
1521c2c66affSColin Finck     while (Link != &(UDFGlobalData.VCBQueue)) {
1522c2c66affSColin Finck 
1523c2c66affSColin Finck         Vcb = CONTAINING_RECORD( Link, VCB, NextVCB );
1524c2c66affSColin Finck 
1525c2c66affSColin Finck         // Move to the next link now since the current Vcb may be deleted.
1526c2c66affSColin Finck         Link = Link->Flink;
1527c2c66affSColin Finck 
1528c2c66affSColin Finck         // If dismount is already underway then check if this Vcb can
1529c2c66affSColin Finck         // go away.
1530c2c66affSColin Finck         if((Vcb->VCBFlags & UDF_VCB_FLAGS_BEING_DISMOUNTED) ||
1531c2c66affSColin Finck             ((!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) && (Vcb->VCBOpenCount <= UDF_RESIDUAL_REFERENCE))) {
1532c2c66affSColin Finck 
1533c2c66affSColin Finck             UDFCheckForDismount( IrpContext, Vcb, FALSE );
1534c2c66affSColin Finck         }
1535c2c66affSColin Finck     }
1536c2c66affSColin Finck 
1537c2c66affSColin Finck     return;
1538c2c66affSColin Finck } // end UDFScanForDismountedVcb()
1539c2c66affSColin Finck 
1540c2c66affSColin Finck /*
1541c2c66affSColin Finck Routine Description:
1542c2c66affSColin Finck     This routine determines if a volume is currently mounted.
1543c2c66affSColin Finck 
1544c2c66affSColin Finck Arguments:
1545c2c66affSColin Finck     Irp - Supplies the Irp to process
1546c2c66affSColin Finck 
1547c2c66affSColin Finck Return Value:
1548c2c66affSColin Finck     NTSTATUS - The return status for the operation
1549c2c66affSColin Finck 
1550c2c66affSColin Finck */
1551c2c66affSColin Finck NTSTATUS
UDFIsVolumeMounted(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)1552c2c66affSColin Finck UDFIsVolumeMounted(
1553c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
1554c2c66affSColin Finck     IN PIRP Irp
1555c2c66affSColin Finck     )
1556c2c66affSColin Finck {
1557c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     PtrUDFFCB Fcb;
1560c2c66affSColin Finck     PtrUDFCCB Ccb;
1561c2c66affSColin Finck 
1562c2c66affSColin Finck     UDFPrint(("UDFIsVolumeMounted\n"));
1563c2c66affSColin Finck 
1564c2c66affSColin Finck     Ccb = (PtrUDFCCB)IrpSp->FileObject->FsContext2;
1565c2c66affSColin Finck     if(!Ccb) {
1566c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
1567c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1568c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1569c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1570c2c66affSColin Finck     }
1571c2c66affSColin Finck     Fcb = Ccb->Fcb;
1572c2c66affSColin Finck 
1573c2c66affSColin Finck     if(Fcb &&
1574c2c66affSColin Finck        !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) &&
1575c2c66affSColin Finck        !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ) {
1576c2c66affSColin Finck 
1577c2c66affSColin Finck         // Disable PopUps, we want to return any error.
1578c2c66affSColin Finck         IrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS;
1579c2c66affSColin Finck 
1580c2c66affSColin Finck         // Verify the Vcb.  This will raise in the error condition.
1581c2c66affSColin Finck         UDFVerifyVcb( IrpContext, Fcb->Vcb );
1582c2c66affSColin Finck     }
1583c2c66affSColin Finck 
1584c2c66affSColin Finck     Irp->IoStatus.Information = 0;
1585c2c66affSColin Finck     Irp->IoStatus.Status = STATUS_SUCCESS;
1586c2c66affSColin Finck 
1587c2c66affSColin Finck     return STATUS_SUCCESS;
1588c2c66affSColin Finck } // end UDFIsVolumeMounted()
1589c2c66affSColin Finck 
1590c2c66affSColin Finck /*
1591c2c66affSColin Finck     This routine returns the filesystem performance counters from the
1592c2c66affSColin Finck     appropriate VCB.
1593c2c66affSColin Finck 
1594c2c66affSColin Finck Arguments:
1595c2c66affSColin Finck     Irp - Supplies the Irp to process
1596c2c66affSColin Finck 
1597c2c66affSColin Finck Return Value:
1598c2c66affSColin Finck     NTSTATUS - The return status for the operation
1599c2c66affSColin Finck */
1600c2c66affSColin Finck NTSTATUS
UDFGetStatistics(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)1601c2c66affSColin Finck UDFGetStatistics(
1602c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
1603c2c66affSColin Finck     IN PIRP Irp
1604c2c66affSColin Finck     )
1605c2c66affSColin Finck {
1606c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
1607c2c66affSColin Finck     NTSTATUS status;
1608c2c66affSColin Finck     PVCB Vcb;
1609c2c66affSColin Finck 
1610c2c66affSColin Finck     PFILE_SYSTEM_STATISTICS Buffer;
1611c2c66affSColin Finck     ULONG BufferLength;
1612c2c66affSColin Finck     ULONG StatsSize;
1613c2c66affSColin Finck     ULONG BytesToCopy;
1614c2c66affSColin Finck 
1615c2c66affSColin Finck     UDFPrint(("UDFGetStatistics\n"));
1616c2c66affSColin Finck 
1617c2c66affSColin Finck     // Extract the buffer
1618c2c66affSColin Finck     BufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
1619c2c66affSColin Finck     //  Get a pointer to the output buffer.
1620c2c66affSColin Finck     Buffer = (PFILE_SYSTEM_STATISTICS)(Irp->AssociatedIrp.SystemBuffer);
1621c2c66affSColin Finck 
1622c2c66affSColin Finck     //  Make sure the buffer is big enough for at least the common part.
1623c2c66affSColin Finck     if (BufferLength < sizeof(FILESYSTEM_STATISTICS)) {
1624c2c66affSColin Finck         status = STATUS_BUFFER_TOO_SMALL;
1625c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1626c2c66affSColin Finck         goto EO_stat;
1627c2c66affSColin Finck     }
1628c2c66affSColin Finck 
1629c2c66affSColin Finck     //  Now see how many bytes we can copy.
1630c2c66affSColin Finck     StatsSize = sizeof(FILE_SYSTEM_STATISTICS) * KeNumberProcessors;
1631c2c66affSColin Finck     if (BufferLength < StatsSize) {
1632c2c66affSColin Finck         BytesToCopy = BufferLength;
1633c2c66affSColin Finck         status = STATUS_BUFFER_OVERFLOW;
1634c2c66affSColin Finck     } else {
1635c2c66affSColin Finck         BytesToCopy = StatsSize;
1636c2c66affSColin Finck         status =  STATUS_SUCCESS;
1637c2c66affSColin Finck     }
1638c2c66affSColin Finck 
1639c2c66affSColin Finck     Vcb = (PVCB)(((PDEVICE_OBJECT)IrpSp->DeviceObject)->DeviceExtension);
1640c2c66affSColin Finck     //  Fill in the output buffer
1641c2c66affSColin Finck     RtlCopyMemory( Buffer, Vcb->Statistics, BytesToCopy );
1642c2c66affSColin Finck     Irp->IoStatus.Information = BytesToCopy;
1643c2c66affSColin Finck EO_stat:
1644c2c66affSColin Finck     Irp->IoStatus.Status = status;
1645c2c66affSColin Finck 
1646c2c66affSColin Finck     return status;
1647c2c66affSColin Finck } // end UDFGetStatistics()
1648c2c66affSColin Finck 
1649c2c66affSColin Finck 
1650c2c66affSColin Finck /*
1651c2c66affSColin Finck     This routine determines if pathname is valid path for UDF Filesystem
1652c2c66affSColin Finck 
1653c2c66affSColin Finck Arguments:
1654c2c66affSColin Finck     Irp - Supplies the Irp to process
1655c2c66affSColin Finck 
1656c2c66affSColin Finck Return Value:
1657c2c66affSColin Finck     NTSTATUS - The return status for the operation
1658c2c66affSColin Finck */
1659c2c66affSColin Finck NTSTATUS
UDFIsPathnameValid(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)1660c2c66affSColin Finck UDFIsPathnameValid(
1661c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
1662c2c66affSColin Finck     IN PIRP Irp
1663c2c66affSColin Finck     )
1664c2c66affSColin Finck {
1665c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
1666c2c66affSColin Finck     NTSTATUS                    RC;
1667c2c66affSColin Finck     PPATHNAME_BUFFER            PathnameBuffer;
1668c2c66affSColin Finck     UNICODE_STRING              PathName;
1669c2c66affSColin Finck     UNICODE_STRING              CurName;
1670c2c66affSColin Finck     PWCHAR                      TmpBuffer;
1671c2c66affSColin Finck 
1672c2c66affSColin Finck     UDFPrint(("UDFIsPathnameValid\n"));
1673c2c66affSColin Finck 
1674c2c66affSColin Finck     // Extract the pathname
1675c2c66affSColin Finck     PathnameBuffer = (PPATHNAME_BUFFER)Irp->AssociatedIrp.SystemBuffer;
1676c2c66affSColin Finck     PathName.Buffer = PathnameBuffer->Name;
1677c2c66affSColin Finck     PathName.Length = (USHORT)PathnameBuffer->PathNameLength;
1678c2c66affSColin Finck 
1679c2c66affSColin Finck     _SEH2_TRY {
1680c2c66affSColin Finck         //  Check for an invalid buffer
1681c2c66affSColin Finck         if (FIELD_OFFSET(PATHNAME_BUFFER, Name[0]) + PathnameBuffer->PathNameLength >
1682c2c66affSColin Finck             IrpSp->Parameters.FileSystemControl.InputBufferLength) {
1683c2c66affSColin Finck             try_return( RC = STATUS_INVALID_PARAMETER);
1684c2c66affSColin Finck         }
1685c2c66affSColin Finck         while (TRUE) {
1686c2c66affSColin Finck             // get next path part...
1687c2c66affSColin Finck             TmpBuffer = PathName.Buffer;
1688c2c66affSColin Finck             PathName.Buffer = UDFDissectName(PathName.Buffer,&(CurName.Length) );
1689*c334c17dSTimo Kreuzer             PathName.Length -= (USHORT)((ULONG_PTR)(PathName.Buffer) - (ULONG_PTR)TmpBuffer);
1690c2c66affSColin Finck             CurName.Buffer = PathName.Buffer - CurName.Length;
1691c2c66affSColin Finck             CurName.Length *= sizeof(WCHAR);
1692c2c66affSColin Finck             CurName.MaximumLength -= CurName.Length;
1693c2c66affSColin Finck 
1694c2c66affSColin Finck             if (CurName.Length) {
1695c2c66affSColin Finck                 // check path fragment size
1696c2c66affSColin Finck                 if (CurName.Length > UDF_NAME_LEN*sizeof(WCHAR)) {
1697c2c66affSColin Finck                     try_return(RC = STATUS_OBJECT_NAME_INVALID);
1698c2c66affSColin Finck                 }
1699c2c66affSColin Finck                 if (!UDFIsNameValid(&CurName, NULL, NULL)) {
1700c2c66affSColin Finck                     try_return(RC = STATUS_OBJECT_NAME_INVALID);
1701c2c66affSColin Finck                 }
1702c2c66affSColin Finck             } else {
1703c2c66affSColin Finck                 try_return(RC = STATUS_SUCCESS);
1704c2c66affSColin Finck             }
1705c2c66affSColin Finck         }
1706c2c66affSColin Finck try_exit:   NOTHING;
1707c2c66affSColin Finck     } _SEH2_FINALLY {
1708c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1709c2c66affSColin Finck         Irp->IoStatus.Status = RC;
1710c2c66affSColin Finck     } _SEH2_END;
1711c2c66affSColin Finck 
1712c2c66affSColin Finck     return RC;
1713c2c66affSColin Finck } // end UDFIsPathnameValid()
1714c2c66affSColin Finck 
1715c2c66affSColin Finck /*
1716c2c66affSColin Finck     This routine performs the lock volume operation.  It is responsible for
1717c2c66affSColin Finck     either completing of enqueuing the input Irp.
1718c2c66affSColin Finck Arguments:
1719c2c66affSColin Finck     Irp - Supplies the Irp to process
1720c2c66affSColin Finck Return Value:
1721c2c66affSColin Finck     NTSTATUS - The return status for the operation
1722c2c66affSColin Finck */
1723c2c66affSColin Finck NTSTATUS
UDFLockVolume(IN PtrUDFIrpContext IrpContext,IN PIRP Irp,IN ULONG PID)1724c2c66affSColin Finck UDFLockVolume(
1725c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
1726c2c66affSColin Finck     IN PIRP             Irp,
1727c2c66affSColin Finck     IN ULONG            PID
1728c2c66affSColin Finck     )
1729c2c66affSColin Finck {
1730c2c66affSColin Finck     NTSTATUS RC;
1731c2c66affSColin Finck 
1732c2c66affSColin Finck     KIRQL SavedIrql;
1733c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
1734c2c66affSColin Finck 
1735c2c66affSColin Finck     PVCB Vcb;
1736c2c66affSColin Finck     PtrUDFFCB Fcb;
1737c2c66affSColin Finck     PtrUDFCCB Ccb;
1738c2c66affSColin Finck     BOOLEAN VcbAcquired = FALSE;
1739c2c66affSColin Finck 
1740c2c66affSColin Finck     UDFPrint(("UDFLockVolume: PID %x\n", PID));
1741c2c66affSColin Finck 
1742c2c66affSColin Finck     //  Decode the file object, the only type of opens we accept are
1743c2c66affSColin Finck     //  user volume opens.
1744c2c66affSColin Finck     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
1745c2c66affSColin Finck     if(!Ccb) {
1746c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
1747c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1748c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1749c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1750c2c66affSColin Finck     }
1751c2c66affSColin Finck     Fcb = Ccb->Fcb;
1752c2c66affSColin Finck     Vcb = Fcb->Vcb;
1753c2c66affSColin Finck 
1754c2c66affSColin Finck     // Check for volume open
1755c2c66affSColin Finck     if (Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) {
1756c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1757c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1758c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1759c2c66affSColin Finck     }
1760c2c66affSColin Finck 
1761c2c66affSColin Finck     UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_LOCK);
1762c2c66affSColin Finck 
1763c2c66affSColin Finck     _SEH2_TRY {
1764c2c66affSColin Finck 
1765c2c66affSColin Finck         if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
1766c2c66affSColin Finck             UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
1767c2c66affSColin Finck #ifdef UDF_DELAYED_CLOSE
1768c2c66affSColin Finck         UDFCloseAllDelayed(Vcb);
1769c2c66affSColin Finck #endif //UDF_DELAYED_CLOSE
1770c2c66affSColin Finck 
1771c2c66affSColin Finck         //  Acquire exclusive access to the Vcb.
1772c2c66affSColin Finck         UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE );
1773c2c66affSColin Finck         VcbAcquired = TRUE;
1774c2c66affSColin Finck 
1775c2c66affSColin Finck         //  Verify the Vcb.
1776c2c66affSColin Finck         UDFVerifyVcb( IrpContext, Vcb );
1777c2c66affSColin Finck 
1778c2c66affSColin Finck         //  If the volume is already locked then complete with success if this file
1779c2c66affSColin Finck         //  object has the volume locked, fail otherwise.
1780c2c66affSColin Finck /*        if (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) {
1781c2c66affSColin Finck 
1782c2c66affSColin Finck             if (Vcb->VolumeLockFileObject == IrpSp->FileObject) {
1783c2c66affSColin Finck                 RC = STATUS_SUCCESS;
1784c2c66affSColin Finck             } else {
1785c2c66affSColin Finck                 RC = STATUS_ACCESS_DENIED;
1786c2c66affSColin Finck             }
1787c2c66affSColin Finck         //  If the open count for the volume is greater than 1 then this request
1788c2c66affSColin Finck         //  will fail.
1789c2c66affSColin Finck         } else if (Vcb->VCBOpenCount > UDF_RESIDUAL_REFERENCE+1) {
1790c2c66affSColin Finck             RC = STATUS_ACCESS_DENIED;
1791c2c66affSColin Finck         //  We will try to get rid of all of the user references.  If there is only one
1792c2c66affSColin Finck         //  remaining after the purge then we can allow the volume to be locked.
1793c2c66affSColin Finck         } else {
1794c2c66affSColin Finck             // flush system cache
1795c2c66affSColin Finck             UDFReleaseResource( &(Vcb->VCBResource) );
1796c2c66affSColin Finck             VcbAcquired = FALSE;
1797c2c66affSColin Finck         }*/
1798c2c66affSColin Finck 
1799c2c66affSColin Finck     } _SEH2_FINALLY {
1800c2c66affSColin Finck 
1801c2c66affSColin Finck         //  Release the Vcb.
1802c2c66affSColin Finck         if(VcbAcquired) {
1803c2c66affSColin Finck             UDFReleaseResource( &(Vcb->VCBResource) );
1804c2c66affSColin Finck             VcbAcquired = FALSE;
1805c2c66affSColin Finck         }
1806c2c66affSColin Finck     } _SEH2_END;
1807c2c66affSColin Finck 
1808c2c66affSColin Finck     UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE );
1809c2c66affSColin Finck     VcbAcquired = TRUE;
1810c2c66affSColin Finck     UDFFlushLogicalVolume(NULL, NULL, Vcb/*, 0*/);
1811c2c66affSColin Finck     UDFReleaseResource( &(Vcb->VCBResource) );
1812c2c66affSColin Finck     VcbAcquired = FALSE;
1813c2c66affSColin Finck     //  Check if the Vcb is already locked, or if the open file count
1814c2c66affSColin Finck     //  is greater than 1 (which implies that someone else also is
1815c2c66affSColin Finck     //  currently using the volume, or a file on the volume).
1816c2c66affSColin Finck     IoAcquireVpbSpinLock( &SavedIrql );
1817c2c66affSColin Finck 
1818c2c66affSColin Finck     if (!(Vcb->Vpb->Flags & VPB_LOCKED) &&
1819c2c66affSColin Finck         (Vcb->VolumeLockPID == (ULONG)-1) &&
1820c2c66affSColin Finck         (Vcb->VCBOpenCount <= UDF_RESIDUAL_REFERENCE+1) &&
1821c2c66affSColin Finck         (Vcb->Vpb->ReferenceCount == 2)) {
1822c2c66affSColin Finck 
1823c2c66affSColin Finck         // Mark volume as locked
1824c2c66affSColin Finck         if(PID == (ULONG)-1) {
1825c2c66affSColin Finck             Vcb->Vpb->Flags |= VPB_LOCKED;
1826c2c66affSColin Finck         }
1827c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_LOCKED;
1828c2c66affSColin Finck         Vcb->VolumeLockFileObject = IrpSp->FileObject;
1829c2c66affSColin Finck         Vcb->VolumeLockPID        = PID;
1830c2c66affSColin Finck 
1831c2c66affSColin Finck         RC = STATUS_SUCCESS;
1832c2c66affSColin Finck 
1833c2c66affSColin Finck     } else {
1834c2c66affSColin Finck 
1835c2c66affSColin Finck         RC = STATUS_ACCESS_DENIED;
1836c2c66affSColin Finck     }
1837c2c66affSColin Finck 
1838c2c66affSColin Finck     IoReleaseVpbSpinLock( SavedIrql );
1839c2c66affSColin Finck 
1840c2c66affSColin Finck     if(!NT_SUCCESS(RC)) {
1841c2c66affSColin Finck         UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_LOCK_FAILED);
1842c2c66affSColin Finck     }
1843c2c66affSColin Finck 
1844c2c66affSColin Finck     //  Complete the request if there haven't been any exceptions.
1845c2c66affSColin Finck     Irp->IoStatus.Information = 0;
1846c2c66affSColin Finck     Irp->IoStatus.Status = RC;
1847c2c66affSColin Finck     return RC;
1848c2c66affSColin Finck } // end UDFLockVolume()
1849c2c66affSColin Finck 
1850c2c66affSColin Finck /*
1851c2c66affSColin Finck     This routine performs the unlock volume operation.  It is responsible for
1852c2c66affSColin Finck     either completing of enqueuing the input Irp.
1853c2c66affSColin Finck Arguments:
1854c2c66affSColin Finck     Irp - Supplies the Irp to process
1855c2c66affSColin Finck Return Value:
1856c2c66affSColin Finck     NTSTATUS - The return status for the operation
1857c2c66affSColin Finck */
1858c2c66affSColin Finck NTSTATUS
UDFUnlockVolume(IN PtrUDFIrpContext IrpContext,IN PIRP Irp,IN ULONG PID)1859c2c66affSColin Finck UDFUnlockVolume(
1860c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
1861c2c66affSColin Finck     IN PIRP             Irp,
1862c2c66affSColin Finck     IN ULONG            PID
1863c2c66affSColin Finck     )
1864c2c66affSColin Finck {
1865c2c66affSColin Finck     NTSTATUS RC = STATUS_INVALID_PARAMETER;
1866c2c66affSColin Finck 
1867c2c66affSColin Finck     KIRQL SavedIrql;
1868c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
1869c2c66affSColin Finck 
1870c2c66affSColin Finck     PVCB Vcb;
1871c2c66affSColin Finck     PtrUDFFCB Fcb;
1872c2c66affSColin Finck     PtrUDFCCB Ccb;
1873c2c66affSColin Finck 
1874c2c66affSColin Finck     UDFPrint(("UDFUnlockVolume: PID %x\n", PID));
1875c2c66affSColin Finck 
1876c2c66affSColin Finck     //  Decode the file object, the only type of opens we accept are
1877c2c66affSColin Finck     //  user volume opens.
1878c2c66affSColin Finck     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
1879c2c66affSColin Finck     if(!Ccb) {
1880c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
1881c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1882c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1883c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1884c2c66affSColin Finck     }
1885c2c66affSColin Finck     Fcb = Ccb->Fcb;
1886c2c66affSColin Finck     Vcb = Fcb->Vcb;
1887c2c66affSColin Finck 
1888c2c66affSColin Finck     // Check for volume open
1889c2c66affSColin Finck     if(Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) {
1890c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1891c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1892c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1893c2c66affSColin Finck     }
1894c2c66affSColin Finck 
1895c2c66affSColin Finck     //  Acquire exclusive access to the Vcb/Vpb.
1896c2c66affSColin Finck     IoAcquireVpbSpinLock( &SavedIrql );
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     _SEH2_TRY {
1899c2c66affSColin Finck 
1900c2c66affSColin Finck         //  We won't check for a valid Vcb for this request.  An unlock will always
1901c2c66affSColin Finck         //  succeed on a locked volume.
1902c2c66affSColin Finck         if(Vcb->Vpb->Flags & VPB_LOCKED ||
1903c2c66affSColin Finck            Vcb->VolumeLockPID == PID) {
1904c2c66affSColin Finck             Vcb->Vpb->Flags &= ~VPB_LOCKED;
1905c2c66affSColin Finck             Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
1906c2c66affSColin Finck             Vcb->VolumeLockFileObject = NULL;
1907c2c66affSColin Finck             Vcb->VolumeLockPID = -1;
1908c2c66affSColin Finck             UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_UNLOCK);
1909c2c66affSColin Finck             RC = STATUS_SUCCESS;
1910c2c66affSColin Finck         } else {
1911c2c66affSColin Finck             RC = STATUS_NOT_LOCKED;
1912c2c66affSColin Finck             RC = STATUS_SUCCESS;
1913c2c66affSColin Finck             RC = STATUS_VOLUME_DISMOUNTED;
1914c2c66affSColin Finck         }
1915c2c66affSColin Finck 
1916c2c66affSColin Finck     } _SEH2_FINALLY {
1917c2c66affSColin Finck         ;
1918c2c66affSColin Finck     } _SEH2_END;
1919c2c66affSColin Finck 
1920c2c66affSColin Finck     //  Release all of our resources
1921c2c66affSColin Finck     IoReleaseVpbSpinLock( SavedIrql );
1922c2c66affSColin Finck 
1923c2c66affSColin Finck     //  Complete the request if there haven't been any exceptions.
1924c2c66affSColin Finck     Irp->IoStatus.Information = 0;
1925c2c66affSColin Finck     Irp->IoStatus.Status = RC;
1926c2c66affSColin Finck     return RC;
1927c2c66affSColin Finck } // end UDFUnlockVolume()
1928c2c66affSColin Finck 
1929c2c66affSColin Finck 
1930c2c66affSColin Finck /*
1931c2c66affSColin Finck     This routine performs the dismount volume operation.  It is responsible for
1932c2c66affSColin Finck     either completing of enqueuing the input Irp.  We only dismount a volume which
1933c2c66affSColin Finck     has been locked.  The intent here is that someone has locked the volume (they are the
1934c2c66affSColin Finck     only remaining handle).  We set the verify bit here and the user will close his handle.
1935c2c66affSColin Finck     We will dismount a volume with no user's handles in the verify path.
1936c2c66affSColin Finck Arguments:
1937c2c66affSColin Finck     Irp - Supplies the Irp to process
1938c2c66affSColin Finck Return Value:
1939c2c66affSColin Finck     NTSTATUS - The return status for the operation
1940c2c66affSColin Finck */
1941c2c66affSColin Finck NTSTATUS
UDFDismountVolume(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)1942c2c66affSColin Finck UDFDismountVolume(
1943c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
1944c2c66affSColin Finck     IN PIRP Irp
1945c2c66affSColin Finck     )
1946c2c66affSColin Finck {
1947c2c66affSColin Finck     NTSTATUS RC;
1948c2c66affSColin Finck 
1949c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
1950c2c66affSColin Finck 
1951c2c66affSColin Finck     PVCB Vcb;
1952c2c66affSColin Finck     PtrUDFFCB Fcb;
1953c2c66affSColin Finck     PtrUDFCCB Ccb;
1954c2c66affSColin Finck     PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;
1955c2c66affSColin Finck     BOOLEAN VcbAcquired = FALSE;
1956c2c66affSColin Finck 
1957c2c66affSColin Finck     UDFPrint(("\n ### UDFDismountVolume ###\n\n"));
1958c2c66affSColin Finck 
1959c2c66affSColin Finck     //  Decode the file object, the only type of opens we accept are
1960c2c66affSColin Finck     //  user volume opens.
1961c2c66affSColin Finck     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
1962c2c66affSColin Finck     if(!Ccb) {
1963c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
1964c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1965c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1966c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1967c2c66affSColin Finck     }
1968c2c66affSColin Finck     Fcb = Ccb->Fcb;
1969c2c66affSColin Finck     Vcb = Fcb->Vcb;
1970c2c66affSColin Finck 
1971c2c66affSColin Finck     // Check for volume open
1972c2c66affSColin Finck     if(Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) {
1973c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1974c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1975c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1976c2c66affSColin Finck     }
1977c2c66affSColin Finck 
1978c2c66affSColin Finck     UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT);
1979c2c66affSColin Finck 
1980c2c66affSColin Finck     if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
1981c2c66affSColin Finck         UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
1982c2c66affSColin Finck #ifdef UDF_DELAYED_CLOSE
1983c2c66affSColin Finck     UDFCloseAllDelayed(Vcb);
1984c2c66affSColin Finck #endif //UDF_DELAYED_CLOSE
1985c2c66affSColin Finck 
1986c2c66affSColin Finck     //  Acquire exclusive access to the Vcb.
1987c2c66affSColin Finck     UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE );
1988c2c66affSColin Finck     VcbAcquired = TRUE;
1989c2c66affSColin Finck 
1990c2c66affSColin Finck     _SEH2_TRY {
1991c2c66affSColin Finck 
1992c2c66affSColin Finck         //  Mark the volume as needs to be verified, but only do it if
1993c2c66affSColin Finck         //  the vcb is locked by this handle and the volume is currently mounted.
1994c2c66affSColin Finck 
1995c2c66affSColin Finck         if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) {
1996c2c66affSColin Finck             // disable Eject Request Waiter if any
1997c2c66affSColin Finck             UDFReleaseResource( &(Vcb->VCBResource) );
1998c2c66affSColin Finck             VcbAcquired = FALSE;
1999c2c66affSColin Finck 
2000c2c66affSColin Finck             UDFStopEjectWaiter(Vcb);
2001c2c66affSColin Finck             RC = STATUS_SUCCESS;
2002c2c66affSColin Finck         } else
2003c2c66affSColin Finck         if(/*!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) ||*/
2004c2c66affSColin Finck            !(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ||
2005c2c66affSColin Finck             (Vcb->VCBOpenCount > (UDF_RESIDUAL_REFERENCE+1))) {
2006c2c66affSColin Finck 
2007c2c66affSColin Finck             RC = STATUS_NOT_LOCKED;
2008c2c66affSColin Finck         } else
2009c2c66affSColin Finck         if((Vcb->VolumeLockFileObject != IrpSp->FileObject)) {
2010c2c66affSColin Finck 
2011c2c66affSColin Finck             RC = STATUS_INVALID_PARAMETER;
2012c2c66affSColin Finck 
2013c2c66affSColin Finck         } else {
2014c2c66affSColin Finck 
2015c2c66affSColin Finck             Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
2016c2c66affSColin Finck             Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
2017c2c66affSColin Finck             if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2018c2c66affSColin Finck             UDFDoDismountSequence(Vcb, Buf, FALSE);
2019c2c66affSColin Finck             Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
2020c2c66affSColin Finck             Vcb->WriteSecurity = FALSE;
2021c2c66affSColin Finck             // disable Eject Request Waiter if any
2022c2c66affSColin Finck             UDFReleaseResource( &(Vcb->VCBResource) );
2023c2c66affSColin Finck             VcbAcquired = FALSE;
2024c2c66affSColin Finck 
2025c2c66affSColin Finck             UDFStopEjectWaiter(Vcb);
2026c2c66affSColin Finck             RC = STATUS_SUCCESS;
2027c2c66affSColin Finck         }
2028c2c66affSColin Finck try_exit: NOTHING;
2029c2c66affSColin Finck     } _SEH2_FINALLY {
2030c2c66affSColin Finck         //  Free memory
2031c2c66affSColin Finck         if(Buf) MyFreePool__(Buf);
2032c2c66affSColin Finck         //  Release all of our resources
2033c2c66affSColin Finck         if(VcbAcquired)
2034c2c66affSColin Finck             UDFReleaseResource( &(Vcb->VCBResource) );
2035c2c66affSColin Finck     } _SEH2_END;
2036c2c66affSColin Finck 
2037c2c66affSColin Finck     if(!NT_SUCCESS(RC)) {
2038c2c66affSColin Finck         UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT_FAILED);
2039c2c66affSColin Finck     }
2040c2c66affSColin Finck 
2041c2c66affSColin Finck     //  Complete the request if there haven't been any exceptions.
2042c2c66affSColin Finck     Irp->IoStatus.Information = 0;
2043c2c66affSColin Finck     Irp->IoStatus.Status = RC;
2044c2c66affSColin Finck     return RC;
2045c2c66affSColin Finck } // end UDFDismountVolume()
2046c2c66affSColin Finck 
2047c2c66affSColin Finck /*
2048c2c66affSColin Finck 
2049c2c66affSColin Finck     This routine returns the volume allocation bitmap.
2050c2c66affSColin Finck 
2051c2c66affSColin Finck         Input = the STARTING_LCN_INPUT_BUFFER data structure is passed in
2052c2c66affSColin Finck             through the input buffer.
2053c2c66affSColin Finck         Output = the VOLUME_BITMAP_BUFFER data structure is returned through
2054c2c66affSColin Finck             the output buffer.
2055c2c66affSColin Finck 
2056c2c66affSColin Finck     We return as much as the user buffer allows starting the specified input
2057c2c66affSColin Finck     LCN (trucated to a byte).  If there is no input buffer, we start at zero.
2058c2c66affSColin Finck 
2059c2c66affSColin Finck Arguments:
2060c2c66affSColin Finck 
2061c2c66affSColin Finck     Irp - Supplies the Irp being processed.
2062c2c66affSColin Finck 
2063c2c66affSColin Finck Return Value:
2064c2c66affSColin Finck 
2065c2c66affSColin Finck     NTSTATUS - The return status for the operation.
2066c2c66affSColin Finck 
2067c2c66affSColin Finck  */
2068c2c66affSColin Finck NTSTATUS
UDFGetVolumeBitmap(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)2069c2c66affSColin Finck UDFGetVolumeBitmap(
2070c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
2071c2c66affSColin Finck     IN PIRP Irp
2072c2c66affSColin Finck     )
2073c2c66affSColin Finck {
2074c2c66affSColin Finck //    NTSTATUS RC;
2075c2c66affSColin Finck 
2076c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp =
2077c2c66affSColin Finck         (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
2078c2c66affSColin Finck 
2079c2c66affSColin Finck     PVCB Vcb;
2080c2c66affSColin Finck     PtrUDFFCB Fcb;
2081c2c66affSColin Finck     PtrUDFCCB Ccb;
2082c2c66affSColin Finck 
2083c2c66affSColin Finck     UDFPrint(("UDFGetVolumeBitmap\n"));
2084c2c66affSColin Finck 
2085c2c66affSColin Finck     ULONG BytesToCopy;
2086c2c66affSColin Finck     ULONG TotalClusters;
2087c2c66affSColin Finck     ULONG DesiredClusters;
2088c2c66affSColin Finck     ULONG StartingCluster;
2089c2c66affSColin Finck     ULONG InputBufferLength;
2090c2c66affSColin Finck     ULONG OutputBufferLength;
2091c2c66affSColin Finck     LARGE_INTEGER StartingLcn;
2092c2c66affSColin Finck     PVOLUME_BITMAP_BUFFER OutputBuffer;
2093c2c66affSColin Finck     ULONG i, lim;
2094c2c66affSColin Finck     PULONG FSBM;
2095c2c66affSColin Finck //    PULONG Dest;
2096c2c66affSColin Finck     ULONG LSh;
2097c2c66affSColin Finck 
2098c2c66affSColin Finck     // Decode the file object, the only type of opens we accept are
2099c2c66affSColin Finck     // user volume opens.
2100c2c66affSColin Finck     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
2101c2c66affSColin Finck     if(!Ccb) {
2102c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
2103c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2104c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2105c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2106c2c66affSColin Finck     }
2107c2c66affSColin Finck     Fcb = Ccb->Fcb;
2108c2c66affSColin Finck     Vcb = Fcb->Vcb;
2109c2c66affSColin Finck 
2110c2c66affSColin Finck     InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
2111c2c66affSColin Finck     OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
2112c2c66affSColin Finck 
2113c2c66affSColin Finck     OutputBuffer = (PVOLUME_BITMAP_BUFFER)UDFGetCallersBuffer(IrpContext, Irp);
2114c2c66affSColin Finck     if(!OutputBuffer)
2115c2c66affSColin Finck         return STATUS_INVALID_USER_BUFFER;
2116c2c66affSColin Finck 
2117c2c66affSColin Finck     // Check for a minimum length on the input and output buffers.
2118c2c66affSColin Finck     if ((InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER)) ||
2119c2c66affSColin Finck         (OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))) {
2120c2c66affSColin Finck 
2121c2c66affSColin Finck         UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2122c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2123c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
2124c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
2125c2c66affSColin Finck     }
2126c2c66affSColin Finck 
2127c2c66affSColin Finck     //  Check if a starting cluster was specified.
2128c2c66affSColin Finck     TotalClusters = Vcb->FSBM_BitCount;
2129c2c66affSColin Finck     StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn;
2130c2c66affSColin Finck 
2131c2c66affSColin Finck     if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) {
2132c2c66affSColin Finck 
2133c2c66affSColin Finck         UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2134c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2135c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2136c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2137c2c66affSColin Finck 
2138c2c66affSColin Finck     } else {
2139c2c66affSColin Finck 
2140c2c66affSColin Finck         StartingCluster = StartingLcn.LowPart & ~7;
2141c2c66affSColin Finck     }
2142c2c66affSColin Finck 
2143c2c66affSColin Finck     OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer);
2144c2c66affSColin Finck     DesiredClusters = TotalClusters - StartingCluster;
2145c2c66affSColin Finck 
2146c2c66affSColin Finck     if (OutputBufferLength < (DesiredClusters + 7) / 8) {
2147c2c66affSColin Finck 
2148c2c66affSColin Finck         BytesToCopy = OutputBufferLength;
2149c2c66affSColin Finck //        RC = STATUS_BUFFER_OVERFLOW;
2150c2c66affSColin Finck 
2151c2c66affSColin Finck     } else {
2152c2c66affSColin Finck 
2153c2c66affSColin Finck         BytesToCopy = (DesiredClusters + 7) / 8;
2154c2c66affSColin Finck //        RC = STATUS_SUCCESS;
2155c2c66affSColin Finck     }
2156c2c66affSColin Finck 
2157c2c66affSColin Finck     UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE );
2158c2c66affSColin Finck 
2159c2c66affSColin Finck     _SEH2_TRY {
2160c2c66affSColin Finck 
2161c2c66affSColin Finck         //  Fill in the fixed part of the output buffer
2162c2c66affSColin Finck         OutputBuffer->StartingLcn.QuadPart = StartingCluster;
2163c2c66affSColin Finck         OutputBuffer->BitmapSize.QuadPart = DesiredClusters;
2164c2c66affSColin Finck 
2165c2c66affSColin Finck         RtlZeroMemory( &OutputBuffer->Buffer[0], BytesToCopy );
2166c2c66affSColin Finck         lim = BytesToCopy * 8;
2167c2c66affSColin Finck         FSBM = (PULONG)(Vcb->FSBM_Bitmap);
2168c2c66affSColin Finck         LSh = Vcb->LB2B_Bits;
2169c2c66affSColin Finck //        Dest = (PULONG)(&OutputBuffer->Buffer[0]);
2170c2c66affSColin Finck 
2171c2c66affSColin Finck         for(i=StartingCluster & ~7; i<lim; i++) {
2172c2c66affSColin Finck             if(UDFGetFreeBit(FSBM, i<<LSh))
2173c2c66affSColin Finck                 UDFSetFreeBit(FSBM, i);
2174c2c66affSColin Finck         }
2175c2c66affSColin Finck 
2176c2c66affSColin Finck     } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
2177c2c66affSColin Finck 
2178c2c66affSColin Finck         BrutePoint();
2179c2c66affSColin Finck         UDFPrintErr(("UDFGetVolumeBitmap: Exception\n"));
2180c2c66affSColin Finck //        UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2181c2c66affSColin Finck         BrutePoint();
2182c2c66affSColin Finck //        RC = UDFExceptionHandler(IrpContext, Irp);
2183c2c66affSColin Finck         UDFReleaseResource(&(Vcb->VCBResource));
2184c2c66affSColin Finck         UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2185c2c66affSColin Finck 
2186c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2187c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER;
2188c2c66affSColin Finck         return STATUS_INVALID_USER_BUFFER;
2189c2c66affSColin Finck     } _SEH2_END;
2190c2c66affSColin Finck 
2191c2c66affSColin Finck     UDFReleaseResource(&(Vcb->VCBResource));
2192c2c66affSColin Finck 
2193c2c66affSColin Finck     UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2194c2c66affSColin Finck     Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) +
2195c2c66affSColin Finck                                 BytesToCopy;
2196c2c66affSColin Finck     Irp->IoStatus.Status = STATUS_SUCCESS;
2197c2c66affSColin Finck 
2198c2c66affSColin Finck     return STATUS_SUCCESS;
2199c2c66affSColin Finck 
2200c2c66affSColin Finck 
2201c2c66affSColin Finck } // end UDFGetVolumeBitmap()
2202c2c66affSColin Finck 
2203c2c66affSColin Finck 
2204c2c66affSColin Finck NTSTATUS
UDFGetRetrievalPointers(IN PtrUDFIrpContext IrpContext,IN PIRP Irp,IN ULONG Special)2205c2c66affSColin Finck UDFGetRetrievalPointers(
2206c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
2207c2c66affSColin Finck     IN PIRP  Irp,
2208c2c66affSColin Finck     IN ULONG Special
2209c2c66affSColin Finck     )
2210c2c66affSColin Finck {
2211c2c66affSColin Finck     NTSTATUS RC;
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp =
2214c2c66affSColin Finck         (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
2215c2c66affSColin Finck 
2216c2c66affSColin Finck     PVCB Vcb;
2217c2c66affSColin Finck     PtrUDFFCB Fcb;
2218c2c66affSColin Finck     PtrUDFCCB Ccb;
2219c2c66affSColin Finck     PUDF_FILE_INFO FileInfo;
2220c2c66affSColin Finck 
2221c2c66affSColin Finck     ULONG InputBufferLength;
2222c2c66affSColin Finck     ULONG OutputBufferLength;
2223c2c66affSColin Finck 
2224c2c66affSColin Finck     PRETRIEVAL_POINTERS_BUFFER OutputBuffer;
2225c2c66affSColin Finck     PSTARTING_VCN_INPUT_BUFFER InputBuffer;
2226c2c66affSColin Finck 
2227c2c66affSColin Finck     LARGE_INTEGER StartingVcn;
2228c2c66affSColin Finck     int64 AllocationSize;
2229c2c66affSColin Finck 
2230c2c66affSColin Finck     PEXTENT_MAP SubMapping = NULL;
2231c2c66affSColin Finck     ULONG SubExtInfoSz;
2232c2c66affSColin Finck     ULONG i;
2233c2c66affSColin Finck     ULONG LBS;
2234c2c66affSColin Finck     ULONG LBSh;
2235c2c66affSColin Finck     ULONG L2BSh;
2236c2c66affSColin Finck 
2237c2c66affSColin Finck     UDFPrint(("UDFGetRetrievalPointers\n"));
2238c2c66affSColin Finck 
2239c2c66affSColin Finck     // Decode the file object, the only type of opens we accept are
2240c2c66affSColin Finck     // user volume opens.
2241c2c66affSColin Finck     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
2242c2c66affSColin Finck     if(!Ccb) {
2243c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
2244c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2245c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2246c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2247c2c66affSColin Finck     }
2248c2c66affSColin Finck     Fcb = Ccb->Fcb;
2249c2c66affSColin Finck     Vcb = Fcb->Vcb;
2250c2c66affSColin Finck 
2251c2c66affSColin Finck     //  Get the input and output buffer lengths and pointers.
2252c2c66affSColin Finck     //  Initialize some variables.
2253c2c66affSColin Finck     InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
2254c2c66affSColin Finck     OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
2255c2c66affSColin Finck 
2256c2c66affSColin Finck     //OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFGetCallersBuffer( IrpContext, Irp );
2257c2c66affSColin Finck     if(Special) {
2258c2c66affSColin Finck         OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->AssociatedIrp.SystemBuffer;
2259c2c66affSColin Finck     } else {
2260c2c66affSColin Finck         OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->UserBuffer;
2261c2c66affSColin Finck     }
2262c2c66affSColin Finck     InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
2263c2c66affSColin Finck     if(!InputBuffer) {
2264c2c66affSColin Finck         InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)OutputBuffer;
2265c2c66affSColin Finck     }
2266c2c66affSColin Finck 
2267c2c66affSColin Finck     _SEH2_TRY {
2268c2c66affSColin Finck 
2269c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2270c2c66affSColin Finck         //  Check for a minimum length on the input and ouput buffers.
2271c2c66affSColin Finck         if ((InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER)) ||
2272c2c66affSColin Finck             (OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))) {
2273c2c66affSColin Finck 
2274c2c66affSColin Finck             try_return( RC = STATUS_BUFFER_TOO_SMALL );
2275c2c66affSColin Finck         }
2276c2c66affSColin Finck 
2277c2c66affSColin Finck         _SEH2_TRY {
2278c2c66affSColin Finck 
2279c2c66affSColin Finck             if (Irp->RequestorMode != KernelMode) {
2280c2c66affSColin Finck                 ProbeForRead( IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
2281c2c66affSColin Finck                               InputBufferLength,
2282c2c66affSColin Finck                               sizeof(UCHAR) );
2283c2c66affSColin Finck                 ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(UCHAR) );
2284c2c66affSColin Finck             }
2285c2c66affSColin Finck             StartingVcn = InputBuffer->StartingVcn;
2286c2c66affSColin Finck 
2287c2c66affSColin Finck         } _SEH2_EXCEPT(Irp->RequestorMode != KernelMode ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) {
2288c2c66affSColin Finck 
2289c2c66affSColin Finck             RC = _SEH2_GetExceptionCode();
2290c2c66affSColin Finck             RC = FsRtlIsNtstatusExpected(RC) ?
2291c2c66affSColin Finck                               RC : STATUS_INVALID_USER_BUFFER;
2292c2c66affSColin Finck             try_return(RC);
2293c2c66affSColin Finck         } _SEH2_END;
2294c2c66affSColin Finck 
2295c2c66affSColin Finck         switch(Special) {
2296c2c66affSColin Finck         case 0:
2297c2c66affSColin Finck             FileInfo = Fcb->FileInfo;
2298c2c66affSColin Finck             break;
2299c2c66affSColin Finck         case 1:
2300c2c66affSColin Finck             FileInfo = Vcb->NonAllocFileInfo;
2301c2c66affSColin Finck             break;
2302c2c66affSColin Finck         default:
2303c2c66affSColin Finck             try_return( RC = STATUS_INVALID_PARAMETER );
2304c2c66affSColin Finck         }
2305c2c66affSColin Finck 
2306c2c66affSColin Finck         if(!FileInfo) {
2307c2c66affSColin Finck             try_return( RC = STATUS_OBJECT_NAME_NOT_FOUND );
2308c2c66affSColin Finck         }
2309c2c66affSColin Finck 
2310c2c66affSColin Finck         AllocationSize = UDFGetFileAllocationSize(Vcb, FileInfo);
2311c2c66affSColin Finck 
2312c2c66affSColin Finck         LBS   = Vcb->LBlockSize;
2313c2c66affSColin Finck         LBSh  = Vcb->LBlockSizeBits;
2314c2c66affSColin Finck         L2BSh = Vcb->LB2B_Bits;
2315c2c66affSColin Finck 
2316c2c66affSColin Finck         if (StartingVcn.HighPart ||
2317c2c66affSColin Finck             StartingVcn.LowPart >= (ULONG)(AllocationSize >> LBSh)) {
2318c2c66affSColin Finck 
2319c2c66affSColin Finck             try_return( RC = STATUS_END_OF_FILE );
2320c2c66affSColin Finck         }
2321c2c66affSColin Finck 
2322c2c66affSColin Finck         SubExtInfoSz = (OutputBufferLength - FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[0])) / (sizeof(LARGE_INTEGER)*2);
2323c2c66affSColin Finck         // re-use AllocationSize as NextVcn
2324c2c66affSColin Finck         RC = UDFReadFileLocation__(Vcb, FileInfo, StartingVcn.QuadPart << LBSh,
2325c2c66affSColin Finck                                    &SubMapping, &SubExtInfoSz, &AllocationSize);
2326c2c66affSColin Finck         if(!NT_SUCCESS(RC))
2327c2c66affSColin Finck             try_return(RC);
2328c2c66affSColin Finck 
2329c2c66affSColin Finck         OutputBuffer->ExtentCount = SubExtInfoSz;
2330c2c66affSColin Finck         OutputBuffer->StartingVcn = StartingVcn;
2331c2c66affSColin Finck         for(i=0; i<SubExtInfoSz; i++) {
2332c2c66affSColin Finck             // assume, that
2333c2c66affSColin Finck             // for not-allocated extents we have start Lba = -1
2334c2c66affSColin Finck             // for not-recorded extents start Lba.LowPart contains real Lba, Lba.HighPart = 0x80000000
2335c2c66affSColin Finck             // for recorded extents Lba.LowPart contains real Lba, Lba.HighPart = 0
2336c2c66affSColin Finck             if(SubMapping[i].extLocation == LBA_NOT_ALLOCATED) {
2337c2c66affSColin Finck                 OutputBuffer->Extents[i].Lcn.QuadPart = (int64)(-1);
2338c2c66affSColin Finck             } else
2339c2c66affSColin Finck             if(SubMapping[i].extLocation & 0x80000000) {
2340c2c66affSColin Finck                 OutputBuffer->Extents[i].Lcn.LowPart = (SubMapping[i].extLocation & 0x7fffffff) >> L2BSh;
2341c2c66affSColin Finck                 OutputBuffer->Extents[i].Lcn.HighPart = 0x80000000;
2342c2c66affSColin Finck             } else {
2343c2c66affSColin Finck                 OutputBuffer->Extents[i].Lcn.LowPart = SubMapping[i].extLocation >> L2BSh;
2344c2c66affSColin Finck                 OutputBuffer->Extents[i].Lcn.HighPart = 0;
2345c2c66affSColin Finck             }
2346c2c66affSColin Finck             // alignment for last sector
2347c2c66affSColin Finck             SubMapping[i].extLength += LBS-1;
2348c2c66affSColin Finck             StartingVcn.QuadPart += SubMapping[i].extLength   >> LBSh;
2349c2c66affSColin Finck             OutputBuffer->Extents[i].NextVcn = StartingVcn;
2350c2c66affSColin Finck         }
2351c2c66affSColin Finck 
2352c2c66affSColin Finck         Irp->IoStatus.Information = FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[0]) + i * sizeof(LARGE_INTEGER) * 2;
2353c2c66affSColin Finck 
2354c2c66affSColin Finck try_exit:   NOTHING;
2355c2c66affSColin Finck     } _SEH2_FINALLY {
2356c2c66affSColin Finck 
2357c2c66affSColin Finck         if(SubMapping)
2358c2c66affSColin Finck             MyFreePool__(SubMapping);
2359c2c66affSColin Finck         Irp->IoStatus.Status = RC;
2360c2c66affSColin Finck     } _SEH2_END;
2361c2c66affSColin Finck 
2362c2c66affSColin Finck     return RC;
2363c2c66affSColin Finck } // end UDFGetRetrievalPointers()
2364c2c66affSColin Finck 
2365c2c66affSColin Finck 
2366c2c66affSColin Finck NTSTATUS
UDFIsVolumeDirty(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)2367c2c66affSColin Finck UDFIsVolumeDirty(
2368c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
2369c2c66affSColin Finck     IN PIRP Irp
2370c2c66affSColin Finck     )
2371c2c66affSColin Finck {
2372c2c66affSColin Finck     PULONG VolumeState;
2373c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp =
2374c2c66affSColin Finck         (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
2375c2c66affSColin Finck 
2376c2c66affSColin Finck     PVCB Vcb;
2377c2c66affSColin Finck     PtrUDFFCB Fcb;
2378c2c66affSColin Finck     PtrUDFCCB Ccb;
2379c2c66affSColin Finck 
2380c2c66affSColin Finck     UDFPrint(("UDFIsVolumeDirty\n"));
2381c2c66affSColin Finck 
2382c2c66affSColin Finck     Irp->IoStatus.Information = 0;
2383c2c66affSColin Finck 
2384c2c66affSColin Finck     if (Irp->AssociatedIrp.SystemBuffer != NULL) {
2385c2c66affSColin Finck         VolumeState = (PULONG)(Irp->AssociatedIrp.SystemBuffer);
2386c2c66affSColin Finck     } else if (Irp->MdlAddress != NULL) {
2387c2c66affSColin Finck         VolumeState = (PULONG)MmGetSystemAddressForMdl(Irp->MdlAddress);
2388c2c66affSColin Finck     } else {
2389c2c66affSColin Finck         UDFPrintErr(("  STATUS_INVALID_USER_BUFFER\n"));
2390c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER;
2391c2c66affSColin Finck         return STATUS_INVALID_USER_BUFFER;
2392c2c66affSColin Finck     }
2393c2c66affSColin Finck 
2394c2c66affSColin Finck     if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) {
2395c2c66affSColin Finck         UDFPrintErr(("  STATUS_BUFFER_TOO_SMALL\n"));
2396c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
2397c2c66affSColin Finck         return STATUS_BUFFER_TOO_SMALL;
2398c2c66affSColin Finck     }
2399c2c66affSColin Finck 
2400c2c66affSColin Finck     (*VolumeState) = 0;
2401c2c66affSColin Finck 
2402c2c66affSColin Finck     // Decode the file object, the only type of opens we accept are
2403c2c66affSColin Finck     // user volume opens.
2404c2c66affSColin Finck     Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2);
2405c2c66affSColin Finck     if(!Ccb) {
2406c2c66affSColin Finck         UDFPrintErr(("  !Ccb\n"));
2407c2c66affSColin Finck         Irp->IoStatus.Information = 0;
2408c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2409c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2410c2c66affSColin Finck     }
2411c2c66affSColin Finck     Fcb = Ccb->Fcb;
2412c2c66affSColin Finck     Vcb = Fcb->Vcb;
2413c2c66affSColin Finck 
2414c2c66affSColin Finck     if(Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) {
2415c2c66affSColin Finck         UDFPrintErr(("  !Volume\n"));
2416c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2417c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2418c2c66affSColin Finck     }
2419c2c66affSColin Finck 
2420c2c66affSColin Finck     if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) {
2421c2c66affSColin Finck         UDFPrintErr(("  !Mounted\n"));
2422c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_VOLUME_DISMOUNTED;
2423c2c66affSColin Finck         return STATUS_VOLUME_DISMOUNTED;
2424c2c66affSColin Finck     }
2425c2c66affSColin Finck 
2426c2c66affSColin Finck     if(Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) {
2427c2c66affSColin Finck         UDFPrint(("  Dirty\n"));
2428c2c66affSColin Finck         (*VolumeState) |= VOLUME_IS_DIRTY;
2429c2c66affSColin Finck         Irp->IoStatus.Information = sizeof(ULONG);
2430c2c66affSColin Finck     } else {
2431c2c66affSColin Finck         UDFPrint(("  Clean\n"));
2432c2c66affSColin Finck     }
2433c2c66affSColin Finck     Irp->IoStatus.Status = STATUS_SUCCESS;
2434c2c66affSColin Finck 
2435c2c66affSColin Finck     return STATUS_SUCCESS;
2436c2c66affSColin Finck 
2437c2c66affSColin Finck } // end UDFIsVolumeDirty()
2438c2c66affSColin Finck 
2439c2c66affSColin Finck 
2440c2c66affSColin Finck NTSTATUS
UDFInvalidateVolumes(IN PtrUDFIrpContext IrpContext,IN PIRP Irp)2441c2c66affSColin Finck UDFInvalidateVolumes(
2442c2c66affSColin Finck     IN PtrUDFIrpContext IrpContext,
2443c2c66affSColin Finck     IN PIRP Irp
2444c2c66affSColin Finck     )
2445c2c66affSColin Finck {
2446c2c66affSColin Finck     NTSTATUS RC;
2447c2c66affSColin Finck     PEXTENDED_IO_STACK_LOCATION IrpSp =
2448c2c66affSColin Finck         (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );
2449c2c66affSColin Finck     PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;
2450c2c66affSColin Finck 
2451c2c66affSColin Finck     UDFPrint(("UDFInvalidateVolumes\n"));
2452c2c66affSColin Finck 
2453c2c66affSColin Finck     KIRQL SavedIrql;
2454c2c66affSColin Finck 
2455c2c66affSColin Finck     LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
2456c2c66affSColin Finck 
2457c2c66affSColin Finck     HANDLE Handle;
2458c2c66affSColin Finck 
2459c2c66affSColin Finck     PVPB NewVpb;
2460c2c66affSColin Finck     PVCB Vcb;
2461c2c66affSColin Finck 
2462c2c66affSColin Finck     PLIST_ENTRY Link;
2463c2c66affSColin Finck 
2464c2c66affSColin Finck     PFILE_OBJECT FileToMarkBad;
2465c2c66affSColin Finck     PDEVICE_OBJECT DeviceToMarkBad;
2466c2c66affSColin Finck 
2467c2c66affSColin Finck     Irp->IoStatus.Information = 0;
2468c2c66affSColin Finck 
2469c2c66affSColin Finck     //  Check for the correct security access.
2470c2c66affSColin Finck     //  The caller must have the SeTcbPrivilege.
2471c2c66affSColin Finck     if (IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
2472c2c66affSColin Finck         IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST &&
2473c2c66affSColin Finck         IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_INVALIDATE_VOLUMES &&
2474c2c66affSColin Finck         !SeSinglePrivilegeCheck( TcbPrivilege, UserMode )) {
2475c2c66affSColin Finck         UDFPrintErr(("UDFInvalidateVolumes: STATUS_PRIVILEGE_NOT_HELD\n"));
2476c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_PRIVILEGE_NOT_HELD;
2477c2c66affSColin Finck         return STATUS_PRIVILEGE_NOT_HELD;
2478c2c66affSColin Finck     }
2479c2c66affSColin Finck     //  Try to get a pointer to the device object from the handle passed in.
2480c2c66affSColin Finck     if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( HANDLE )) {
2481c2c66affSColin Finck         UDFPrintErr(("UDFInvalidateVolumes: STATUS_INVALID_PARAMETER\n"));
2482c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2483c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2484c2c66affSColin Finck     }
2485c2c66affSColin Finck 
2486c2c66affSColin Finck     Handle = *((PHANDLE) Irp->AssociatedIrp.SystemBuffer);
2487c2c66affSColin Finck 
2488c2c66affSColin Finck     RC = ObReferenceObjectByHandle( Handle,
2489c2c66affSColin Finck                                     0,
2490c2c66affSColin Finck                                     *IoFileObjectType,
2491c2c66affSColin Finck                                     KernelMode,
2492c2c66affSColin Finck                                     (PVOID*)&FileToMarkBad,
2493c2c66affSColin Finck                                     NULL );
2494c2c66affSColin Finck 
2495c2c66affSColin Finck     if (!NT_SUCCESS(RC)) {
2496c2c66affSColin Finck         UDFPrintErr(("UDFInvalidateVolumes: can't get handle, RC=%x\n", RC));
2497c2c66affSColin Finck         Irp->IoStatus.Status = RC;
2498c2c66affSColin Finck         return RC;
2499c2c66affSColin Finck     }
2500c2c66affSColin Finck 
2501c2c66affSColin Finck     //  We only needed the pointer, not a reference.
2502c2c66affSColin Finck     ObDereferenceObject( FileToMarkBad );
2503c2c66affSColin Finck 
2504c2c66affSColin Finck     //  Grab the DeviceObject from the FileObject.
2505c2c66affSColin Finck     DeviceToMarkBad = FileToMarkBad->DeviceObject;
2506c2c66affSColin Finck 
2507c2c66affSColin Finck     //  Create a new Vpb for this device so that any new opens will mount
2508c2c66affSColin Finck     //  a new volume.
2509c2c66affSColin Finck     NewVpb = (PVPB)DbgAllocatePoolWithTag( NonPagedPool, sizeof( VPB ), 'bpvU' );
2510c2c66affSColin Finck     if(!NewVpb) {
2511c2c66affSColin Finck         UDFPrintErr(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES\n"));
2512c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2513c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
2514c2c66affSColin Finck     }
2515c2c66affSColin Finck     RtlZeroMemory( NewVpb, sizeof( VPB ) );
2516c2c66affSColin Finck 
2517c2c66affSColin Finck     NewVpb->Type = IO_TYPE_VPB;
2518c2c66affSColin Finck     NewVpb->Size = sizeof( VPB );
2519c2c66affSColin Finck     NewVpb->RealDevice = DeviceToMarkBad;
2520c2c66affSColin Finck     NewVpb->Flags = DeviceToMarkBad->Vpb->Flags & VPB_REMOVE_PENDING;
2521c2c66affSColin Finck 
2522c2c66affSColin Finck     // Acquire GlobalDataResource
2523c2c66affSColin Finck     UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
2524c2c66affSColin Finck 
2525c2c66affSColin Finck     //  Nothing can go wrong now.
2526c2c66affSColin Finck     IoAcquireVpbSpinLock( &SavedIrql );
2527c2c66affSColin Finck     if (DeviceToMarkBad->Vpb->Flags & VPB_MOUNTED) {
2528c2c66affSColin Finck         DeviceToMarkBad->Vpb = NewVpb;
2529c2c66affSColin Finck         NewVpb = NULL;
2530c2c66affSColin Finck     }
2531c2c66affSColin Finck     ASSERT( DeviceToMarkBad->Vpb->DeviceObject == NULL );
2532c2c66affSColin Finck     IoReleaseVpbSpinLock( SavedIrql );
2533c2c66affSColin Finck 
2534c2c66affSColin Finck     if (NewVpb) {
2535c2c66affSColin Finck         DbgFreePool( NewVpb );
2536c2c66affSColin Finck     }
2537c2c66affSColin Finck 
2538c2c66affSColin Finck     // Walk through all of the Vcb's attached to the global data.
2539c2c66affSColin Finck     Link = UDFGlobalData.VCBQueue.Flink;
2540c2c66affSColin Finck 
2541c2c66affSColin Finck     //ASSERT(FALSE);
2542c2c66affSColin Finck 
2543c2c66affSColin Finck     while (Link != &(UDFGlobalData.VCBQueue)) {
2544c2c66affSColin Finck         // Get 'next' Vcb
2545c2c66affSColin Finck         Vcb = CONTAINING_RECORD( Link, VCB, NextVCB );
2546c2c66affSColin Finck         // Move to the next link now since the current Vcb may be deleted.
2547c2c66affSColin Finck         Link = Link->Flink;
2548c2c66affSColin Finck 
2549c2c66affSColin Finck         // Acquire Vcb resource
2550c2c66affSColin Finck         UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
2551c2c66affSColin Finck 
2552c2c66affSColin Finck         if (Vcb->Vpb->RealDevice == DeviceToMarkBad) {
2553c2c66affSColin Finck 
2554c2c66affSColin Finck             if(!Buf) {
2555c2c66affSColin Finck                 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN)*2);
2556c2c66affSColin Finck                 if(!Buf) {
2557c2c66affSColin Finck                     UDFPrintErr(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES (2)\n"));
2558c2c66affSColin Finck                     UDFReleaseResource(&(Vcb->VCBResource));
2559c2c66affSColin Finck                     MyFreePool__(NewVpb);
2560c2c66affSColin Finck                     Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2561c2c66affSColin Finck                     return STATUS_INSUFFICIENT_RESOURCES;
2562c2c66affSColin Finck                 }
2563c2c66affSColin Finck             }
2564c2c66affSColin Finck 
2565c2c66affSColin Finck #ifdef UDF_DELAYED_CLOSE
2566c2c66affSColin Finck             UDFPrint(("    UDFInvalidateVolumes:     set UDF_VCB_FLAGS_NO_DELAYED_CLOSE\n"));
2567c2c66affSColin Finck             Vcb->VCBFlags |= UDF_VCB_FLAGS_NO_DELAYED_CLOSE;
2568c2c66affSColin Finck             UDFReleaseResource(&(Vcb->VCBResource));
2569c2c66affSColin Finck #endif //UDF_DELAYED_CLOSE
2570c2c66affSColin Finck 
2571c2c66affSColin Finck             if(Vcb->RootDirFCB && Vcb->RootDirFCB->FileInfo) {
2572c2c66affSColin Finck                 UDFPrint(("    UDFInvalidateVolumes:     UDFCloseAllSystemDelayedInDir\n"));
2573c2c66affSColin Finck                 RC = UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
2574c2c66affSColin Finck                 ASSERT(OS_SUCCESS(RC));
2575c2c66affSColin Finck             }
2576c2c66affSColin Finck #ifdef UDF_DELAYED_CLOSE
2577c2c66affSColin Finck             UDFPrint(("    UDFInvalidateVolumes:     UDFCloseAllDelayed\n"));
2578c2c66affSColin Finck             UDFCloseAllDelayed(Vcb);
2579c2c66affSColin Finck             //ASSERT(OS_SUCCESS(RC));
2580c2c66affSColin Finck #endif //UDF_DELAYED_CLOSE
2581c2c66affSColin Finck 
2582c2c66affSColin Finck             UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
2583c2c66affSColin Finck 
2584c2c66affSColin Finck             UDFDoDismountSequence(Vcb, Buf, FALSE);
2585c2c66affSColin Finck             UDFReleaseResource(&(Vcb->VCBResource));
2586c2c66affSColin Finck 
2587c2c66affSColin Finck             UDFStopEjectWaiter(Vcb);
2588c2c66affSColin Finck             UDFPrint(("UDFInvalidateVolumes: Vcb %x dismounted\n", Vcb));
2589c2c66affSColin Finck             break;
2590c2c66affSColin Finck         } else {
2591c2c66affSColin Finck             UDFPrint(("UDFInvalidateVolumes: skip Vcb %x\n", Vcb));
2592c2c66affSColin Finck             UDFReleaseResource(&(Vcb->VCBResource));
2593c2c66affSColin Finck         }
2594c2c66affSColin Finck 
2595c2c66affSColin Finck     }
2596c2c66affSColin Finck     // Once we have processed all the mounted logical volumes, we can release
2597c2c66affSColin Finck     // all acquired global resources and leave (in peace :-)
2598c2c66affSColin Finck     UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
2599c2c66affSColin Finck 
2600c2c66affSColin Finck     Irp->IoStatus.Status = STATUS_SUCCESS;
2601c2c66affSColin Finck 
2602c2c66affSColin Finck     if(Buf) {
2603c2c66affSColin Finck         UDFPrint(("UDFInvalidateVolumes: free buffer\n"));
2604c2c66affSColin Finck         MyFreePool__(Buf);
2605c2c66affSColin Finck     }
2606c2c66affSColin Finck 
2607c2c66affSColin Finck     // drop volume completly
2608c2c66affSColin Finck     UDFPrint(("UDFInvalidateVolumes: drop volume completly\n"));
2609c2c66affSColin Finck     UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
2610c2c66affSColin Finck     UDFScanForDismountedVcb(IrpContext);
2611c2c66affSColin Finck     UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
2612c2c66affSColin Finck 
2613c2c66affSColin Finck     UDFPrint(("UDFInvalidateVolumes: done\n"));
2614c2c66affSColin Finck     return STATUS_SUCCESS;
2615c2c66affSColin Finck 
2616c2c66affSColin Finck } // end UDFInvalidateVolumes()
2617