Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

verfysup.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 VerfySup.c 00008 00009 Abstract: 00010 00011 This module implements the Udfs Verification routines. 00012 00013 Author: 00014 00015 Dan Lovinger [DanLo] 18-July-1996 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "UdfProcs.h" 00022 00023 // 00024 // The Bug check file id for this module 00025 // 00026 00027 #define BugCheckFileId (UDFS_BUG_CHECK_VERFYSUP) 00028 00029 // 00030 // The local debug trace level 00031 // 00032 00033 #define Dbg (UDFS_DEBUG_LEVEL_VERFYSUP) 00034 00035 #ifdef ALLOC_PRAGMA 00036 #pragma alloc_text(PAGE, UdfVerifyFcbOperation) 00037 #pragma alloc_text(PAGE, UdfVerifyVcb) 00038 #endif 00039 00040 00041 NTSTATUS 00042 UdfPerformVerify ( 00043 IN PIRP_CONTEXT IrpContext, 00044 IN PIRP Irp, 00045 IN PDEVICE_OBJECT DeviceToVerify 00046 ) 00047 00048 /*++ 00049 00050 Routine Description: 00051 00052 This routines performs an IoVerifyVolume operation and takes the 00053 appropriate action. If the verify is successful then we send the originating 00054 Irp off to an Ex Worker Thread. This routine is called from the exception handler. 00055 00056 No file system resources are held when this routine is called. 00057 00058 Arguments: 00059 00060 Irp - The irp to send off after all is well and done. 00061 00062 Device - The real device needing verification. 00063 00064 Return Value: 00065 00066 None. 00067 00068 --*/ 00069 00070 { 00071 PVCB Vcb; 00072 NTSTATUS Status = STATUS_SUCCESS; 00073 PIO_STACK_LOCATION IrpSp; 00074 00075 ASSERT_IRP_CONTEXT( IrpContext ); 00076 ASSERT_IRP( Irp ); 00077 00078 // 00079 // Check if this Irp has a status of Verify required and if it does 00080 // then call the I/O system to do a verify. 00081 // 00082 // Skip the IoVerifyVolume if this is a mount or verify request 00083 // itself. Trying a recursive mount will cause a deadlock with 00084 // the DeviceObject->DeviceLock. 00085 // 00086 00087 if ((IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && 00088 ((IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) || 00089 (IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME))) { 00090 00091 return UdfFsdPostRequest( IrpContext, Irp ); 00092 } 00093 00094 // 00095 // Extract a pointer to the Vcb from the VolumeDeviceObject. 00096 // Note that since we have specifically excluded mount, 00097 // requests, we know that IrpSp->DeviceObject is indeed a 00098 // volume device object. 00099 // 00100 00101 IrpSp = IoGetCurrentIrpStackLocation( Irp ); 00102 00103 Vcb = &CONTAINING_RECORD( IrpSp->DeviceObject, 00104 VOLUME_DEVICE_OBJECT, 00105 DeviceObject )->Vcb; 00106 00107 // 00108 // Check if the volume still thinks it needs to be verified, 00109 // if it doesn't then we can skip doing a verify because someone 00110 // else beat us to it. 00111 // 00112 00113 try { 00114 00115 if (FlagOn( DeviceToVerify->Flags, DO_VERIFY_VOLUME )) { 00116 00117 BOOLEAN AllowRawMount = FALSE; 00118 00119 // 00120 // We will allow Raw to mount this volume if we were doing a 00121 // an absolute DASD open. 00122 // 00123 00124 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && 00125 (IrpSp->FileObject->FileName.Length == 0) && 00126 (IrpSp->FileObject->RelatedFileObject == NULL)) { 00127 00128 AllowRawMount = TRUE; 00129 } 00130 00131 // 00132 // If the IopMount in IoVerifyVolume did something, and 00133 // this is an absolute open, force a reparse. 00134 // 00135 00136 Status = IoVerifyVolume( DeviceToVerify, AllowRawMount ); 00137 00138 // 00139 // If the verify operation completed it will return 00140 // either STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly. 00141 // 00142 // If UdfVerifyVolume encountered an error during 00143 // processing, it will return that error. If we got 00144 // STATUS_WRONG_VOLUME from the verify, and our volume 00145 // is now mounted, commute the status to STATUS_SUCCESS. 00146 // 00147 00148 if ((Status == STATUS_WRONG_VOLUME) && 00149 (Vcb->VcbCondition == VcbMounted)) { 00150 00151 Status = STATUS_SUCCESS; 00152 } 00153 00154 // 00155 // Do a quick unprotected check here. The routine will do 00156 // a safe check. After here we can release the resource. 00157 // Note that if the volume really went away, we will be taking 00158 // the Reparse path. 00159 // 00160 00161 // 00162 // If the device might need to go away then call our dismount routine. 00163 // 00164 00165 if (((Vcb->VcbCondition == VcbNotMounted) || 00166 (Vcb->VcbCondition == VcbInvalid) || 00167 (Vcb->VcbCondition == VcbDismountInProgress)) && 00168 (Vcb->VcbReference <= Vcb->VcbResidualReference)) { 00169 00170 UdfAcquireUdfData( IrpContext ); 00171 UdfCheckForDismount( IrpContext, Vcb, FALSE ); 00172 UdfReleaseUdfData( IrpContext ); 00173 } 00174 00175 // 00176 // If this is a create and the verify succeeded then complete the 00177 // request with a REPARSE status. 00178 // 00179 00180 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && 00181 (IrpSp->FileObject->RelatedFileObject == NULL) && 00182 ((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) { 00183 00184 Irp->IoStatus.Information = IO_REMOUNT; 00185 00186 UdfCompleteRequest( IrpContext, Irp, STATUS_REPARSE ); 00187 Status = STATUS_REPARSE; 00188 Irp = NULL; 00189 IrpContext = NULL; 00190 00191 // 00192 // If there is still an error to process then call the Io system 00193 // for a popup. 00194 // 00195 00196 } else if ((Irp != NULL) && !NT_SUCCESS( Status )) { 00197 00198 // 00199 // Fill in the device object if required. 00200 // 00201 00202 if (IoIsErrorUserInduced( Status ) ) { 00203 00204 IoSetHardErrorOrVerifyDevice( Irp, DeviceToVerify ); 00205 } 00206 00207 UdfNormalizeAndRaiseStatus( IrpContext, Status ); 00208 } 00209 } 00210 00211 // 00212 // If there is still an Irp, send it off to an Ex Worker thread. 00213 // 00214 00215 if (IrpContext != NULL) { 00216 00217 Status = UdfFsdPostRequest( IrpContext, Irp ); 00218 } 00219 00220 } except(UdfExceptionFilter( IrpContext, GetExceptionInformation() )) { 00221 00222 // 00223 // We had some trouble trying to perform the verify or raised 00224 // an error ourselves. So we'll abort the I/O request with 00225 // the error status that we get back from the execption code. 00226 // 00227 00228 Status = UdfProcessException( IrpContext, Irp, GetExceptionCode() ); 00229 } 00230 00231 return Status; 00232 } 00233 00234 00235 BOOLEAN 00236 UdfCheckForDismount ( 00237 IN PIRP_CONTEXT IrpContext, 00238 IN PVCB Vcb, 00239 IN BOOLEAN Force 00240 ) 00241 00242 /*++ 00243 00244 Routine Description: 00245 00246 This routine is called to check if a volume is ready for dismount. This 00247 occurs when only file system references are left on the volume. 00248 00249 If the dismount is not currently underway and the user reference count 00250 has gone to zero then we can begin the dismount. 00251 00252 If the dismount is in progress and there are no references left on the 00253 volume (we check the Vpb for outstanding references as well to catch 00254 any create calls dispatched to the file system) then we can delete 00255 the Vcb. 00256 00257 Arguments: 00258 00259 Vcb - Vcb for the volume to try to dismount. 00260 00261 Force - Whether we will force this volume to be dismounted. 00262 00263 Return Value: 00264 00265 BOOLEAN - True if the Vcb was not gone by the time this function finished, 00266 False if it was deleted. 00267 00268 This is only a trustworthy indication to the caller if it had the vcb 00269 exclusive itself. 00270 00271 --*/ 00272 00273 { 00274 BOOLEAN UnlockVcb = TRUE; 00275 BOOLEAN VcbPresent = TRUE; 00276 KIRQL SavedIrql; 00277 00278 ASSERT_IRP_CONTEXT( IrpContext ); 00279 ASSERT_VCB( Vcb ); 00280 00281 ASSERT_EXCLUSIVE_UDFDATA; 00282 00283 // 00284 // Acquire and lock this Vcb to check the dismount state. 00285 // 00286 00287 UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE ); 00288 00289 // 00290 // Lets get rid of any pending closes for this volume. 00291 // 00292 00293 UdfFspClose( Vcb ); 00294 00295 UdfLockVcb( IrpContext, Vcb ); 00296 00297 // 00298 // If the dismount is not already underway then check if the 00299 // user reference count has gone to zero or we are being forced 00300 // to disconnect. If so start the teardown on the Vcb. 00301 // 00302 00303 if (Vcb->VcbCondition != VcbDismountInProgress) { 00304 00305 if (Vcb->VcbUserReference <= Vcb->VcbResidualUserReference || Force) { 00306 00307 UdfUnlockVcb( IrpContext, Vcb ); 00308 UnlockVcb = FALSE; 00309 VcbPresent = UdfDismountVcb( IrpContext, Vcb ); 00310 } 00311 00312 // 00313 // If the teardown is underway and there are absolutely no references 00314 // remaining then delete the Vcb. References here include the 00315 // references in the Vcb and Vpb. 00316 // 00317 00318 } else if (Vcb->VcbReference == 0) { 00319 00320 IoAcquireVpbSpinLock( &SavedIrql ); 00321 00322 // 00323 // If there are no file objects and no reference counts in the 00324 // Vpb we can delete the Vcb. Don't forget that we have the 00325 // last reference in the Vpb. 00326 // 00327 00328 if (Vcb->Vpb->ReferenceCount == 1) { 00329 00330 IoReleaseVpbSpinLock( SavedIrql ); 00331 UdfUnlockVcb( IrpContext, Vcb ); 00332 UnlockVcb = FALSE; 00333 UdfDeleteVcb( IrpContext, Vcb ); 00334 VcbPresent = FALSE; 00335 00336 } else { 00337 00338 IoReleaseVpbSpinLock( SavedIrql ); 00339 } 00340 } 00341 00342 // 00343 // Unlock the Vcb if still held. 00344 // 00345 00346 if (UnlockVcb) { 00347 00348 UdfUnlockVcb( IrpContext, Vcb ); 00349 } 00350 00351 // 00352 // Release any resources still acquired. 00353 // 00354 00355 if (VcbPresent) { 00356 00357 UdfReleaseVcb( IrpContext, Vcb ); 00358 } 00359 00360 return VcbPresent; 00361 } 00362 00363 00364 BOOLEAN 00365 UdfDismountVcb ( 00366 IN PIRP_CONTEXT IrpContext, 00367 IN PVCB Vcb 00368 ) 00369 00370 /*++ 00371 00372 Routine Description: 00373 00374 This routine is called when all of the user references to a volume are 00375 gone. We will initiate all of the teardown any system resources. 00376 00377 If all of the references to this volume are gone at the end of this routine 00378 then we will complete the teardown of this Vcb and mark the current Vpb 00379 as not mounted. Otherwise we will allocated a new Vpb for this device 00380 and keep the current Vpb attached to the Vcb. 00381 00382 Arguments: 00383 00384 Vcb - Vcb for the volume to dismount. 00385 00386 Return Value: 00387 00388 BOOLEAN - TRUE if we didn't delete the Vcb, FALSE otherwise. 00389 00390 --*/ 00391 00392 { 00393 PVPB OldVpb; 00394 PVPB NewVpb; 00395 BOOLEAN VcbPresent = TRUE; 00396 KIRQL SavedIrql; 00397 00398 BOOLEAN FinalReference; 00399 00400 ASSERT_EXCLUSIVE_UDFDATA; 00401 ASSERT_EXCLUSIVE_VCB( Vcb ); 00402 00403 UdfLockVcb( IrpContext, Vcb ); 00404 00405 // 00406 // We should only take this path once. 00407 // 00408 00409 ASSERT( Vcb->VcbCondition != VcbDismountInProgress ); 00410 00411 // 00412 // Mark the Vcb as DismountInProgress. 00413 // 00414 00415 Vcb->VcbCondition = VcbDismountInProgress; 00416 00417 // 00418 // Remove our reference to the internal Fcb's. The Fcb's will then 00419 // be removed in the purge path below. 00420 // 00421 00422 if (Vcb->RootIndexFcb != NULL) { 00423 00424 Vcb->RootIndexFcb->FcbReference -= 1; 00425 Vcb->RootIndexFcb->FcbUserReference -= 1; 00426 } 00427 00428 if (Vcb->MetadataFcb != NULL) { 00429 00430 Vcb->MetadataFcb->FcbReference -= 1; 00431 Vcb->MetadataFcb->FcbUserReference -= 1; 00432 } 00433 00434 if (Vcb->VatFcb != NULL) { 00435 00436 Vcb->VatFcb->FcbReference -= 1; 00437 Vcb->VatFcb->FcbUserReference -= 1; 00438 } 00439 00440 if (Vcb->VolumeDasdFcb != NULL) { 00441 00442 Vcb->VolumeDasdFcb->FcbReference -= 1; 00443 Vcb->VolumeDasdFcb->FcbUserReference -= 1; 00444 } 00445 00446 UdfUnlockVcb( IrpContext, Vcb ); 00447 00448 // 00449 // Purge the volume. 00450 // 00451 00452 UdfPurgeVolume( IrpContext, Vcb, TRUE ); 00453 00454 // 00455 // Empty the delayed and async close queues. 00456 // 00457 00458 UdfFspClose( Vcb ); 00459 00460 // 00461 // Allocate a new Vpb in case we will need it. 00462 // 00463 00464 NewVpb = ExAllocatePoolWithTag( NonPagedPoolMustSucceed, sizeof( VPB ), TAG_VPB ); 00465 RtlZeroMemory( NewVpb, sizeof( VPB ) ); 00466 00467 OldVpb = Vcb->Vpb; 00468 00469 // 00470 // Remove the mount volume reference. 00471 // 00472 00473 UdfLockVcb( IrpContext, Vcb ); 00474 Vcb->VcbReference -= 1; 00475 00476 // 00477 // Acquire the Vpb spinlock to check for Vpb references. 00478 // 00479 00480 IoAcquireVpbSpinLock( &SavedIrql ); 00481 00482 // 00483 // Remember if this is the last reference on this Vcb. We incremented 00484 // the count on the Vpb earlier so we get one last crack it. If our 00485 // reference has gone to zero but the vpb reference count is greater 00486 // than zero then the Io system will be responsible for deleting the 00487 // Vpb. 00488 // 00489 00490 FinalReference = (BOOLEAN) ((Vcb->VcbReference == 0) && 00491 (OldVpb->ReferenceCount == 1)); 00492 00493 // 00494 // There is a reference count in the Vpb and in the Vcb. We have 00495 // incremented the reference count in the Vpb to make sure that 00496 // we have last crack at it. If this is a failed mount then we 00497 // want to return the Vpb to the IO system to use for the next 00498 // mount request. 00499 // 00500 00501 if (OldVpb->RealDevice->Vpb == OldVpb) { 00502 00503 // 00504 // If not the final reference then swap out the Vpb. We must 00505 // preserve the REMOVE_PENDING flag so that the device is 00506 // not remounted in the middle of a PnP remove operation. 00507 // 00508 00509 if (!FinalReference) { 00510 00511 NewVpb->Type = IO_TYPE_VPB; 00512 NewVpb->Size = sizeof( VPB ); 00513 NewVpb->RealDevice = OldVpb->RealDevice; 00514 00515 NewVpb->RealDevice->Vpb = NewVpb; 00516 00517 NewVpb->Flags = FlagOn( OldVpb->Flags, VPB_REMOVE_PENDING ); 00518 00519 NewVpb = NULL; 00520 IoReleaseVpbSpinLock( SavedIrql ); 00521 UdfUnlockVcb( IrpContext, Vcb ); 00522 00523 // 00524 // We want to leave the Vpb for the IO system. Mark it 00525 // as being not mounted. Go ahead and delete the Vcb as 00526 // well. 00527 // 00528 00529 } else { 00530 00531 // 00532 // Make sure to remove the last reference on the Vpb. 00533 // 00534 00535 OldVpb->ReferenceCount -= 1; 00536 00537 OldVpb->DeviceObject = NULL; 00538 ClearFlag( Vcb->Vpb->Flags, VPB_MOUNTED ); 00539 00540 // 00541 // Clear the Vpb flag so we know not to delete it. 00542 // 00543 00544 Vcb->Vpb = NULL; 00545 00546 IoReleaseVpbSpinLock( SavedIrql ); 00547 UdfUnlockVcb( IrpContext, Vcb ); 00548 UdfDeleteVcb( IrpContext, Vcb ); 00549 VcbPresent = FALSE; 00550 } 00551 00552 // 00553 // Someone has already swapped in a new Vpb. If this is the final reference 00554 // then the file system is responsible for deleting the Vpb. 00555 // 00556 00557 } else if (FinalReference) { 00558 00559 // 00560 // Make sure to remove the last reference on the Vpb. 00561 // 00562 00563 OldVpb->ReferenceCount -= 1; 00564 00565 IoReleaseVpbSpinLock( SavedIrql ); 00566 UdfUnlockVcb( IrpContext, Vcb ); 00567 UdfDeleteVcb( IrpContext, Vcb ); 00568 VcbPresent = FALSE; 00569 00570 // 00571 // The current Vpb is no longer the Vpb for the device (the IO system 00572 // has already allocated a new one). We leave our reference in the 00573 // Vpb and will be responsible for deleting it at a later time. 00574 // 00575 00576 } else { 00577 00578 OldVpb->DeviceObject = NULL; 00579 ClearFlag( Vcb->Vpb->Flags, VPB_MOUNTED ); 00580 00581 IoReleaseVpbSpinLock( SavedIrql ); 00582 UdfUnlockVcb( IrpContext, Vcb ); 00583 } 00584 00585 // 00586 // Deallocate the new Vpb if we don't need it. 00587 // 00588 00589 if (NewVpb != NULL) { 00590 00591 UdfFreePool( &NewVpb ); 00592 } 00593 00594 // 00595 // Let our caller know whether the Vcb is still present. 00596 // 00597 00598 return VcbPresent; 00599 } 00600 00601 00602 00603 VOID 00604 UdfVerifyVcb ( 00605 IN PIRP_CONTEXT IrpContext, 00606 IN PVCB Vcb 00607 ) 00608 00609 /*++ 00610 00611 Routine Description: 00612 00613 This routine checks that the current Vcb is valid and currently mounted 00614 on the device. It will raise on an error condition. 00615 00616 We check whether the volume needs verification and the current state 00617 of the Vcb. 00618 00619 Arguments: 00620 00621 Vcb - This is the volume to verify. 00622 00623 Return Value: 00624 00625 None 00626 00627 --*/ 00628 00629 { 00630 NTSTATUS Status; 00631 IO_STATUS_BLOCK Iosb; 00632 ULONG MediaChangeCount = 0; 00633 00634 PAGED_CODE(); 00635 00636 // 00637 // Fail immediately if the volume is in the progress of being dismounted 00638 // or has been marked invalid. 00639 // 00640 00641 if ((Vcb->VcbCondition == VcbInvalid) || 00642 (Vcb->VcbCondition == VcbDismountInProgress)) { 00643 00644 UdfRaiseStatus( IrpContext, STATUS_FILE_INVALID ); 00645 } 00646 00647 // 00648 // If the media is removable and the verify volume flag in the 00649 // device object is not set then we want to ping the device 00650 // to see if it needs to be verified 00651 // 00652 00653 if ((Vcb->VcbCondition != VcbMountInProgress) && 00654 FlagOn( Vcb->VcbState, VCB_STATE_REMOVABLE_MEDIA ) && 00655 !FlagOn( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME )) { 00656 00657 Status = UdfPerformDevIoCtrl( IrpContext, 00658 ( Vcb->Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ? 00659 IOCTL_CDROM_CHECK_VERIFY : 00660 IOCTL_DISK_CHECK_VERIFY ), 00661 Vcb->TargetDeviceObject, 00662 &MediaChangeCount, 00663 sizeof(ULONG), 00664 FALSE, 00665 FALSE, 00666 &Iosb ); 00667 00668 if (Iosb.Information != sizeof(ULONG)) { 00669 00670 // 00671 // Be safe about the count in case the driver didn't fill it in 00672 // 00673 00674 MediaChangeCount = 0; 00675 } 00676 00677 // 00678 // If the volume is now an empty device, or we have receieved a 00679 // bare STATUS_VERIFY_REQUIRED (various hardware conditions such 00680 // as bus resets, etc., will trigger this in the drivers), or the 00681 // media change count has moved since we last inspected the device, 00682 // then mark the volume to be verified. 00683 // 00684 00685 if ((Vcb->VcbCondition == VcbMounted && 00686 UdfIsRawDevice( IrpContext, Status )) || 00687 (Status == STATUS_VERIFY_REQUIRED) || 00688 (NT_SUCCESS(Status) && 00689 (Vcb->MediaChangeCount != MediaChangeCount))) { 00690 00691 SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME ); 00692 00693 // 00694 // If the volume is not mounted and we got a media change count, 00695 // update the Vcb so we do not trigger a verify again at this 00696 // count value. If the verify->mount path detects that the media 00697 // has actually changed and this Vcb is valid again, this will have 00698 // done nothing. We are already synchronized since the caller has 00699 // the Vcb. 00700 // 00701 00702 if ((Vcb->VcbCondition == VcbNotMounted) && 00703 NT_SUCCESS(Status)) { 00704 00705 Vcb->MediaChangeCount = MediaChangeCount; 00706 } 00707 00708 // 00709 // Raise the error condition otherwise. 00710 // 00711 00712 } else if (!NT_SUCCESS( Status )) { 00713 00714 UdfNormalizeAndRaiseStatus( IrpContext, Status ); 00715 } 00716 00717 } 00718 00719 // 00720 // The Vcb may be mounted but the underlying real device may need to be verified. 00721 // If it does then we'll set the Iosb in the irp to be our real device 00722 // and raise Verify required 00723 // 00724 00725 if (FlagOn( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME )) { 00726 00727 IoSetHardErrorOrVerifyDevice( IrpContext->Irp, 00728 Vcb->Vpb->RealDevice ); 00729 00730 UdfRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED ); 00731 } 00732 00733 // 00734 // Based on the condition of the Vcb we'll either return to our 00735 // caller or raise an error condition 00736 // 00737 00738 switch (Vcb->VcbCondition) { 00739 00740 case VcbNotMounted: 00741 00742 SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME ); 00743 00744 IoSetHardErrorOrVerifyDevice( IrpContext->Irp, Vcb->Vpb->RealDevice ); 00745 00746 UdfRaiseStatus( IrpContext, STATUS_WRONG_VOLUME ); 00747 break; 00748 00749 case VcbInvalid: 00750 case VcbDismountInProgress : 00751 00752 UdfRaiseStatus( IrpContext, STATUS_FILE_INVALID ); 00753 break; 00754 } 00755 00756 return; 00757 } 00758 00759 00760 00761 BOOLEAN 00762 UdfVerifyFcbOperation ( 00763 IN PIRP_CONTEXT IrpContext OPTIONAL, 00764 IN PFCB Fcb 00765 ) 00766 00767 /*++ 00768 00769 Routine Description: 00770 00771 This routine is called to verify that the state of the Fcb is valid 00772 to allow the current operation to continue. We use the state of the 00773 Vcb, target device and type of operation to determine this. 00774 00775 Arguments: 00776 00777 IrpContext - IrpContext for the request. If not present then we 00778 were called from the fast IO path. 00779 00780 Fcb - Fcb to perform the request on. 00781 00782 Return Value: 00783 00784 BOOLEAN - TRUE if the request can continue, FALSE otherwise. 00785 00786 --*/ 00787 00788 { 00789 NTSTATUS Status = STATUS_SUCCESS; 00790 PVCB Vcb = Fcb->Vcb; 00791 PDEVICE_OBJECT RealDevice = Vcb->Vpb->RealDevice; 00792 00793 PAGED_CODE(); 00794 00795 // 00796 // Fail immediately if the volume is in the progress of being dismounted 00797 // or has been marked invalid. 00798 // 00799 00800 if ((Vcb->VcbCondition == VcbInvalid) || 00801 (Vcb->VcbCondition == VcbDismountInProgress)) { 00802 00803 if (ARGUMENT_PRESENT( IrpContext )) { 00804 00805 UdfRaiseStatus( IrpContext, STATUS_FILE_INVALID ); 00806 } 00807 00808 return FALSE; 00809 } 00810 00811 // 00812 // Always fail if the volume needs to be verified. 00813 // 00814 00815 if (FlagOn( RealDevice->Flags, DO_VERIFY_VOLUME )) { 00816 00817 if (ARGUMENT_PRESENT( IrpContext )) { 00818 00819 IoSetHardErrorOrVerifyDevice( IrpContext->Irp, 00820 RealDevice ); 00821 00822 UdfRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED ); 00823 } 00824 00825 return FALSE; 00826 00827 // 00828 // All operations are allowed on mounted volumes. 00829 // 00830 00831 } else if ((Vcb->VcbCondition == VcbMounted) || 00832 (Vcb->VcbCondition == VcbMountInProgress)) { 00833 00834 return TRUE; 00835 00836 // 00837 // Fail all requests for fast Io on other Vcb conditions. 00838 // 00839 00840 } else if (!ARGUMENT_PRESENT( IrpContext )) { 00841 00842 return FALSE; 00843 00844 // 00845 // The remaining case is VcbNotMounted. 00846 // Mark the device to be verified and raise WRONG_VOLUME. 00847 // 00848 00849 } else if (Vcb->VcbCondition == VcbNotMounted) { 00850 00851 if (ARGUMENT_PRESENT( IrpContext )) { 00852 00853 SetFlag(RealDevice->Flags, DO_VERIFY_VOLUME); 00854 00855 IoSetHardErrorOrVerifyDevice( IrpContext->Irp, RealDevice ); 00856 UdfRaiseStatus( IrpContext, STATUS_WRONG_VOLUME ); 00857 } 00858 00859 return FALSE; 00860 } 00861 00862 return TRUE; 00863 } 00864 00865

Generated on Sat May 15 19:42:22 2004 for test by doxygen 1.3.7