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