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

create.c File Reference

#include "UdfProcs.h"

Go to the source code of this file.

Defines

#define BugCheckFileId   (UDFS_BUG_CHECK_CREATE)
#define Dbg   (UDFS_DEBUG_LEVEL_CREATE)

Functions

NTSTATUS UdfNormalizeFileNames (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN OpenByFileId, IN BOOLEAN IgnoreCase, IN TYPE_OF_OPEN RelatedTypeOfOpen, IN PCCB RelatedCcb OPTIONAL, IN PUNICODE_STRING RelatedFileName OPTIONAL, IN OUT PUNICODE_STRING FileName, IN OUT PUNICODE_STRING RemainingName)
NTSTATUS UdfOpenExistingFcb (IN PIRP_CONTEXT IrpContext, IN PIO_STACK_LOCATION IrpSp, IN OUT PFCB *CurrentFcb, IN PLCB OpenLcb, IN TYPE_OF_OPEN TypeOfOpen, IN BOOLEAN IgnoreCase, IN PCCB RelatedCcb OPTIONAL)
NTSTATUS UdfOpenObjectByFileId (IN PIRP_CONTEXT IrpContext, IN PIO_STACK_LOCATION IrpSp, IN PVCB Vcb, IN OUT PFCB *CurrentFcb)
NTSTATUS UdfOpenObjectFromDirContext (IN PIRP_CONTEXT IrpContext, IN PIO_STACK_LOCATION IrpSp, IN PVCB Vcb, IN OUT PFCB *CurrentFcb, IN BOOLEAN ShortNameMatch, IN BOOLEAN IgnoreCase, IN PDIR_ENUM_CONTEXT DirContext, IN BOOLEAN PerformUserOpen, IN PCCB RelatedCcb OPTIONAL)
NTSTATUS UdfCompleteFcbOpen (IN PIRP_CONTEXT IrpContext, PIO_STACK_LOCATION IrpSp, IN PVCB Vcb, IN OUT PFCB *CurrentFcb, IN PLCB OpenLcb, IN TYPE_OF_OPEN TypeOfOpen, IN ULONG UserCcbFlags, IN ACCESS_MASK DesiredAccess)
NTSTATUS UdfCommonCreate (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)


Define Documentation

#define BugCheckFileId   (UDFS_BUG_CHECK_CREATE)
 

Definition at line 28 of file udfs/create.c.

#define Dbg   (UDFS_DEBUG_LEVEL_CREATE)
 

Definition at line 34 of file udfs/create.c.


Function Documentation

NTSTATUS UdfCommonCreate IN PIRP_CONTEXT  IrpContext,
IN PIRP  Irp
 

Definition at line 108 of file udfs/create.c.

References ASSERT, BooleanFlagOn, DIR_ENUM_CONTEXT, FALSE, _DIR_ENUM_CONTEXT::Fid, _FCB::FileAttributes, FileName, _FILE_OBJECT::FileName, _IO_STACK_LOCATION::FileObject, FlagOn, _IO_STACK_LOCATION::Flags, NSR_FID::Flags, IoGetCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH, IRP_CONTEXT_FLAG_WAIT, NSR_FID_F_DIRECTORY, NT_SUCCESS, NTSTATUS(), NULL, _DIR_ENUM_CONTEXT::ObjectName, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _FILE_OBJECT::RelatedFileObject, _VCB::RootIndexFcb, SafeNodeType, SL_CASE_SENSITIVE, SL_OPEN_PAGING_FILE, SL_OPEN_TARGET_DIRECTORY, Status, TRUE, try_leave, TYPE_OF_OPEN, UdfAcquireFcbExclusive, UdfAcquireVcbExclusive, UdfAcquireVcbShared, UdfCandidateShortName(), UdfCleanupDirContext(), UdfCompleteRequest(), UdfDecodeFileObject(), UdfDissectName(), UdfFindDirEntry(), UdfFindPrefix(), UdfInitializeDirContext(), UdfNormalizeFileNames(), UdfOpenExistingFcb(), UdfOpenObjectByFileId(), UdfOpenObjectFromDirContext(), UdfRaiseStatus(), UdfReleaseFcb, UdfReleaseVcb, UDFS_NTC_FCB_DATA, UdfTeardownStructures(), UdfVerifyVcb(), UnopenedFileObject, UserDirectoryOpen, UserFileOpen, UserVolumeOpen, VCB_STATE_LOCKED, _VCB::VcbState, _VCB::VolumeDasdFcb, and _FILE_OBJECT::Vpb.

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

00115 : 00116 00117 This is the common routine for opening a file called by both the 00118 Fsp and Fsd threads. 00119 00120 The file can be opened either by name or by file Id either with or without 00121 a relative name. The file name field in the file object passed to this routine 00122 contains either a unicode string or a 64 bit value which is the file Id. 00123 If there is a related file object with a name then we will already have converted 00124 that name to Oem. 00125 00126 We will store the full name for the file in the file object on a successful 00127 open. We will allocate a larger buffer if necessary and combine the 00128 related and file object names. The only exception is the relative open 00129 when the related file object is for an OpenByFileId file. If we need to 00130 allocate a buffer for a case insensitive name then we allocate it at 00131 the tail of the buffer we will store into the file object. The upcased 00132 portion will begin immediately after the name defined by the FileName 00133 in the file object. 00134 00135 Once we have the full name in the file object we don't want to split the 00136 name in the event of a retry. We use a flag in the IrpContext to indicate 00137 that the name has been split. 00138 00139 Arguments: 00140 00141 Irp - Supplies the Irp to process 00142 00143 Return Value: 00144 00145 NTSTATUS - This is the status from this open operation. 00146 00147 --*/ 00148 00149 { 00150 NTSTATUS Status = STATUS_SUCCESS; 00151 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 00152 00153 PFILE_OBJECT FileObject; 00154 00155 DIR_ENUM_CONTEXT DirContext; 00156 BOOLEAN CleanupDirContext = FALSE; 00157 00158 BOOLEAN FoundEntry; 00159 00160 PVCB Vcb; 00161 00162 BOOLEAN OpenByFileId; 00163 BOOLEAN IgnoreCase; 00164 ULONG CreateDisposition; 00165 00166 BOOLEAN ShortNameMatch; 00167 00168 BOOLEAN VolumeOpen = FALSE; 00169 00170 // 00171 // We will be acquiring and releasing file Fcb's as we move down the 00172 // directory tree during opens. At any time we need to know the deepest 00173 // point we have traversed down in the tree in case we need to cleanup 00174 // any structures created here. 00175 // 00176 // CurrentFcb - represents this point. If non-null it means we have 00177 // acquired it and need to release it in finally clause. 00178 // 00179 // NextFcb - represents the NextFcb to walk to but haven't acquired yet. 00180 // 00181 // CurrentLcb - represents the name of the CurrentFcb. 00182 // 00183 00184 TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject; 00185 PFILE_OBJECT RelatedFileObject; 00186 PCCB RelatedCcb = NULL; 00187 00188 PFCB NextFcb; 00189 PFCB CurrentFcb = NULL; 00190 00191 PLCB CurrentLcb = NULL; 00192 00193 // 00194 // During the open we need to combine the related file object name 00195 // with the remaining name. We also may need to upcase the file name 00196 // in order to do a case-insensitive name comparison. We also need 00197 // to restore the name in the file object in the event that we retry 00198 // the request. We use the following string variables to manage the 00199 // name. We will can put these strings into either Unicode or Ansi 00200 // form. 00201 // 00202 // FileName - Pointer to name as currently stored in the file 00203 // object. We store the full name into the file object early in 00204 // the open operation. 00205 // 00206 // RelatedFileName - Pointer to the name in the related file object. 00207 // 00208 // RemainingName - String containing remaining name to parse. 00209 // 00210 00211 PUNICODE_STRING FileName; 00212 PUNICODE_STRING RelatedFileName; 00213 00214 UNICODE_STRING RemainingName; 00215 UNICODE_STRING FinalName; 00216 00217 PAGED_CODE(); 00218 00219 // 00220 // If we were called with our file system device object instead of a 00221 // volume device object, just complete this request with STATUS_SUCCESS. 00222 // 00223 00224 if (IrpContext->Vcb == NULL) { 00225 00226 UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); 00227 return STATUS_SUCCESS; 00228 } 00229 00230 // 00231 // Get create parameters from the Irp. 00232 // 00233 00234 OpenByFileId = BooleanFlagOn( IrpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID ); 00235 IgnoreCase = !BooleanFlagOn( IrpSp->Flags, SL_CASE_SENSITIVE ); 00236 CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff; 00237 00238 // 00239 // Do some preliminary checks to make sure the operation is supported. 00240 // We fail in the following cases immediately. 00241 // 00242 // - Open a paging file. 00243 // - Open a target directory. 00244 // - Open a file with Eas. 00245 // - Create a file. 00246 // 00247 00248 if (FlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE | SL_OPEN_TARGET_DIRECTORY) || 00249 (IrpSp->Parameters.Create.EaLength != 0) || 00250 (CreateDisposition == FILE_CREATE)) { 00251 00252 UdfCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED ); 00253 return STATUS_ACCESS_DENIED; 00254 } 00255 00256 // 00257 // Copy the Vcb to a local. Assume the starting directory is the root. 00258 // 00259 00260 Vcb = IrpContext->Vcb; 00261 NextFcb = Vcb->RootIndexFcb; 00262 00263 // 00264 // Reference our input parameters to make things easier 00265 // 00266 00267 FileObject = IrpSp->FileObject; 00268 RelatedFileObject = NULL; 00269 00270 FileName = &FileObject->FileName; 00271 00272 // 00273 // Set up the file object's Vpb pointer in case anything happens. 00274 // This will allow us to get a reasonable pop-up. 00275 // 00276 00277 if ((FileObject->RelatedFileObject != NULL) && !OpenByFileId) { 00278 00279 RelatedFileObject = FileObject->RelatedFileObject; 00280 FileObject->Vpb = RelatedFileObject->Vpb; 00281 00282 RelatedTypeOfOpen = UdfDecodeFileObject( RelatedFileObject, &NextFcb, &RelatedCcb ); 00283 00284 // 00285 // Fail the request if this is not a user file object. 00286 // 00287 00288 if (RelatedTypeOfOpen < UserVolumeOpen) { 00289 00290 UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); 00291 return STATUS_INVALID_PARAMETER; 00292 } 00293 00294 // 00295 // Remember the name in the related file object. 00296 // 00297 00298 RelatedFileName = &RelatedFileObject->FileName; 00299 } 00300 00301 // 00302 // If we haven't initialized the names then make sure the strings are valid. 00303 // If this an OpenByFileId then verify the file id buffer. 00304 // 00305 // After this routine returns we know that the full name is in the 00306 // FileName buffer and the buffer will hold the upcased portion 00307 // of the name yet to parse immediately after the full name in the 00308 // buffer. Any trailing backslash has been removed and the flag 00309 // in the IrpContext will indicate whether we removed the 00310 // backslash. 00311 // 00312 00313 Status = UdfNormalizeFileNames( IrpContext, 00314 Vcb, 00315 OpenByFileId, 00316 IgnoreCase, 00317 RelatedTypeOfOpen, 00318 RelatedCcb, 00319 RelatedFileName, 00320 FileName, 00321 &RemainingName ); 00322 00323 // 00324 // Return the error code if not successful. 00325 // 00326 00327 if (!NT_SUCCESS( Status )) { 00328 00329 UdfCompleteRequest( IrpContext, Irp, Status ); 00330 return Status; 00331 } 00332 00333 // 00334 // We want to acquire the Vcb. Exclusively for a volume open, shared otherwise. 00335 // The file name is empty for a volume open. 00336 // 00337 00338 if ((FileName->Length == 0) && 00339 (RelatedTypeOfOpen <= UserVolumeOpen) && 00340 !OpenByFileId) { 00341 00342 VolumeOpen = TRUE; 00343 UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE ); 00344 00345 } else { 00346 00347 UdfAcquireVcbShared( IrpContext, Vcb, FALSE ); 00348 } 00349 00350 // 00351 // Use a try-finally to facilitate cleanup. 00352 // 00353 00354 try { 00355 00356 // 00357 // Verify that the Vcb is not in an unusable condition. This routine 00358 // will raise if not usable. 00359 // 00360 00361 UdfVerifyVcb( IrpContext, Vcb ); 00362 00363 // 00364 // If the Vcb is locked then we cannot open another file 00365 // 00366 00367 if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) { 00368 00369 try_leave( Status = STATUS_ACCESS_DENIED ); 00370 } 00371 00372 // 00373 // If we are opening this file by FileId then process this immediately 00374 // and exit. 00375 // 00376 00377 if (OpenByFileId) { 00378 00379 // 00380 // The only create disposition we allow is OPEN. 00381 // 00382 00383 if ((CreateDisposition != FILE_OPEN) && 00384 (CreateDisposition != FILE_OPEN_IF)) { 00385 00386 try_leave( Status = STATUS_ACCESS_DENIED ); 00387 } 00388 00389 try_leave( Status = UdfOpenObjectByFileId( IrpContext, 00390 IrpSp, 00391 Vcb, 00392 &CurrentFcb )); 00393 } 00394 00395 // 00396 // If we are opening this volume Dasd then process this immediately 00397 // and exit. 00398 // 00399 00400 if (VolumeOpen) { 00401 00402 // 00403 // The only create disposition we allow is OPEN. 00404 // 00405 00406 if ((CreateDisposition != FILE_OPEN) && 00407 (CreateDisposition != FILE_OPEN_IF)) { 00408 00409 try_leave( Status = STATUS_ACCESS_DENIED ); 00410 } 00411 00412 // 00413 // If they wanted to open a directory, surprise. 00414 // 00415 00416 if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { 00417 00418 try_leave( Status = STATUS_NOT_A_DIRECTORY ); 00419 } 00420 00421 // 00422 // Acquire the Fcb first. 00423 // 00424 00425 CurrentFcb = Vcb->VolumeDasdFcb; 00426 UdfAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE ); 00427 00428 try_leave( Status = UdfOpenExistingFcb( IrpContext, 00429 IrpSp, 00430 &CurrentFcb, 00431 NULL, 00432 UserVolumeOpen, 00433 FALSE, 00434 NULL )); 00435 } 00436 00437 // 00438 // Acquire the Fcb at the beginning of our search to keep it from being 00439 // deleted beneath us. 00440 // 00441 00442 UdfAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); 00443 CurrentFcb = NextFcb; 00444 00445 // 00446 // Do a prefix search if there is more of the name to parse. 00447 // 00448 00449 if (RemainingName.Length != 0) { 00450 00451 // 00452 // Do the prefix search to find the longest matching name. 00453 // 00454 00455 CurrentLcb = UdfFindPrefix( IrpContext, 00456 &CurrentFcb, 00457 &RemainingName, 00458 IgnoreCase ); 00459 } 00460 00461 // 00462 // At this point CurrentFcb points at the lowest Fcb in the tree for this 00463 // file name, CurrentLcb is that name, and RemainingName is the rest of the 00464 // name we have to do any directory traversals for. 00465 // 00466 00467 // 00468 // If the remaining name length is zero then we have found our 00469 // target. 00470 // 00471 00472 if (RemainingName.Length == 0) { 00473 00474 // 00475 // If this is a file so verify the user didn't want to open 00476 // a directory. 00477 // 00478 00479 if (SafeNodeType( CurrentFcb ) == UDFS_NTC_FCB_DATA) { 00480 00481 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) || 00482 FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { 00483 00484 try_leave( Status = STATUS_NOT_A_DIRECTORY ); 00485 } 00486 00487 // 00488 // The only create disposition we allow is OPEN. 00489 // 00490 00491 if ((CreateDisposition != FILE_OPEN) && 00492 (CreateDisposition != FILE_OPEN_IF)) { 00493 00494 try_leave( Status = STATUS_ACCESS_DENIED ); 00495 } 00496 00497 try_leave( Status = UdfOpenExistingFcb( IrpContext, 00498 IrpSp, 00499 &CurrentFcb, 00500 CurrentLcb, 00501 UserFileOpen, 00502 IgnoreCase, 00503 RelatedCcb )); 00504 00505 // 00506 // This is a directory. Verify the user didn't want to open 00507 // as a file. 00508 // 00509 00510 } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { 00511 00512 try_leave( Status = STATUS_FILE_IS_A_DIRECTORY ); 00513 00514 // 00515 // Open the file as a directory. 00516 // 00517 00518 } else { 00519 00520 // 00521 // The only create disposition we allow is OPEN. 00522 // 00523 00524 if ((CreateDisposition != FILE_OPEN) && 00525 (CreateDisposition != FILE_OPEN_IF)) { 00526 00527 try_leave( Status = STATUS_ACCESS_DENIED ); 00528 } 00529 00530 try_leave( Status = UdfOpenExistingFcb( IrpContext, 00531 IrpSp, 00532 &CurrentFcb, 00533 CurrentLcb, 00534 UserDirectoryOpen, 00535 IgnoreCase, 00536 RelatedCcb )); 00537 } 00538 } 00539 00540 // 00541 // We have more work to do. We have a starting Fcb which we own shared. 00542 // We also have the remaining name to parse. Walk through the name 00543 // component by component looking for the full name. 00544 // 00545 00546 // 00547 // Our starting Fcb better be a directory. 00548 // 00549 00550 if (!FlagOn( CurrentFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 00551 00552 try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND ); 00553 } 00554 00555 // 00556 // If we can't wait then post this request. 00557 // 00558 00559 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 00560 00561 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 00562 } 00563 00564 // 00565 // Prepare the enumeration context for use. 00566 // 00567 00568 UdfInitializeDirContext( IrpContext, &DirContext ); 00569 CleanupDirContext = TRUE; 00570 00571 while (TRUE) { 00572 00573 ShortNameMatch = FALSE; 00574 00575 // 00576 // Split off the next component from the name. 00577 // 00578 00579 UdfDissectName( IrpContext, 00580 &RemainingName, 00581 &FinalName ); 00582 00583 // 00584 // Go ahead and look this entry up in the directory. 00585 // 00586 00587 FoundEntry = UdfFindDirEntry( IrpContext, 00588 CurrentFcb, 00589 &FinalName, 00590 IgnoreCase, 00591 FALSE, 00592 &DirContext ); 00593 00594 // 00595 // If we didn't find the entry then check if the current name 00596 // is a possible short name. 00597 // 00598 00599 if (!FoundEntry && UdfCandidateShortName( IrpContext, &FinalName)) { 00600 00601 // 00602 // If the name looks like it could be a short name, try to find 00603 // a matching real directory entry. 00604 // 00605 00606 ShortNameMatch = 00607 FoundEntry = UdfFindDirEntry( IrpContext, 00608 CurrentFcb, 00609 &FinalName, 00610 IgnoreCase, 00611 TRUE, 00612 &DirContext ); 00613 } 00614 00615 // 00616 // If we didn't find a match then check what the caller was trying to do to 00617 // determine which error code to return. 00618 // 00619 00620 if (!FoundEntry) { 00621 00622 if ((CreateDisposition == FILE_OPEN) || 00623 (CreateDisposition == FILE_OVERWRITE)) { 00624 00625 try_leave( Status = STATUS_OBJECT_NAME_NOT_FOUND ); 00626 } 00627 00628 // 00629 // Any other operation return STATUS_ACCESS_DENIED. 00630 // 00631 00632 try_leave( Status = STATUS_ACCESS_DENIED ); 00633 } 00634 00635 // 00636 // If this is an ignore case open then copy the exact case 00637 // in the file object name. 00638 // 00639 00640 if (IgnoreCase && !ShortNameMatch) { 00641 00642 ASSERT( FinalName.Length == DirContext.ObjectName.Length ); 00643 00644 RtlCopyMemory( FinalName.Buffer, 00645 DirContext.ObjectName.Buffer, 00646 DirContext.ObjectName.Length ); 00647 } 00648 00649 // 00650 // If we have found the last component then break out to open for the caller. 00651 // 00652 00653 if (RemainingName.Length == 0) { 00654 00655 break; 00656 } 00657 00658 // 00659 // The object we just found must be a directory. 00660 // 00661 00662 if (!FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) { 00663 00664 try_leave( Status = STATUS_OBJECT_PATH_NOT_FOUND ); 00665 } 00666 00667 // 00668 // Now open an Fcb for this intermediate index Fcb. 00669 // 00670 00671 UdfOpenObjectFromDirContext( IrpContext, 00672 IrpSp, 00673 Vcb, 00674 &CurrentFcb, 00675 ShortNameMatch, 00676 IgnoreCase, 00677 &DirContext, 00678 FALSE, 00679 NULL ); 00680 } 00681 00682 // 00683 // Make sure our opener is about to get what they expect. 00684 // 00685 00686 if ((FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) || 00687 FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) && 00688 !FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) { 00689 00690 try_leave( Status = STATUS_NOT_A_DIRECTORY ); 00691 00692 } 00693 00694 if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE ) && 00695 FlagOn( DirContext.Fid->Flags, NSR_FID_F_DIRECTORY )) { 00696 00697 try_leave( Status = STATUS_FILE_IS_A_DIRECTORY ); 00698 } 00699 00700 // 00701 // The only create disposition we allow is OPEN. 00702 // 00703 00704 if ((CreateDisposition != FILE_OPEN) && 00705 (CreateDisposition != FILE_OPEN_IF)) { 00706 00707 try_leave( Status = STATUS_ACCESS_DENIED ); 00708 } 00709 00710 // 00711 // Open the object for the caller. 00712 // 00713 00714 try_leave( Status = UdfOpenObjectFromDirContext( IrpContext, 00715 IrpSp, 00716 Vcb, 00717 &CurrentFcb, 00718 ShortNameMatch, 00719 IgnoreCase, 00720 &DirContext, 00721 TRUE, 00722 RelatedCcb )); 00723 } finally { 00724 00725 // 00726 // Cleanup the enumeration context if initialized. 00727 // 00728 00729 if (CleanupDirContext) { 00730 00731 UdfCleanupDirContext( IrpContext, &DirContext ); 00732 } 00733 00734 // 00735 // The result of this open could be success, pending or some error 00736 // condition. 00737 // 00738 00739 if (AbnormalTermination()) { 00740 00741 00742 // 00743 // In the error path we start by calling our teardown routine if we 00744 // have a CurrentFcb. 00745 // 00746 00747 if (CurrentFcb != NULL) { 00748 00749 BOOLEAN RemovedFcb; 00750 00751 UdfTeardownStructures( IrpContext, CurrentFcb, FALSE, &RemovedFcb ); 00752 00753 if (RemovedFcb) { 00754 00755 CurrentFcb = NULL; 00756 } 00757 } 00758 00759 // 00760 // No need to complete the request. 00761 // 00762 00763 IrpContext = NULL; 00764 Irp = NULL; 00765 00766 // 00767 // If we posted this request through the oplock package we need 00768 // to show that there is no reason to complete the request. 00769 // 00770 00771 } else if (Status == STATUS_PENDING) { 00772 00773 IrpContext = NULL; 00774 Irp = NULL; 00775 } 00776 00777 // 00778 // Release the Current Fcb if still acquired. 00779 // 00780 00781 if (CurrentFcb != NULL) { 00782 00783 UdfReleaseFcb( IrpContext, CurrentFcb ); 00784 } 00785 00786 // 00787 // Release the Vcb. 00788 // 00789 00790 UdfReleaseVcb( IrpContext, Vcb ); 00791 00792 // 00793 // Call our completion routine. It will handle the case where either 00794 // the Irp and/or IrpContext are gone. 00795 // 00796 00797 UdfCompleteRequest( IrpContext, Irp, Status ); 00798 } 00799 00800 return Status; 00801 }

NTSTATUS UdfCompleteFcbOpen IN PIRP_CONTEXT  IrpContext,
PIO_STACK_LOCATION  IrpSp,
IN PVCB  Vcb,
IN OUT PFCB CurrentFcb,
IN PLCB  OpenLcb,
IN TYPE_OF_OPEN  TypeOfOpen,
IN ULONG  UserCcbFlags,
IN ACCESS_MASK  DesiredAccess
 

Definition at line 1955 of file udfs/create.c.

References Dbg, DebugTrace, FALSE, FastIoIsNotPossible, _FCB::FcbCleanup, _FCB::FcbNonpaged, _FCB::FcbReference, _FCB::FcbUserReference, _IO_STACK_LOCATION::FileObject, FlagOn, _FILE_OBJECT::Flags, FO_CACHE_SUPPORTED, FO_NO_INTERMEDIATE_BUFFERING, FsRtlCheckOplock(), FsRtlCurrentBatchOplock(), IoCheckShareAccess(), IoSetShareAccess(), IoUpdateShareAccess(), IRP_CONTEXT_FLAG_WAIT, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _FILE_OBJECT::SectionObjectPointer, _FCB_NONPAGED::SegmentObject, SetFlag, _FCB::ShareAccess, Status, TRUE, UdfCreateCcb(), UdfFspClose(), UdfIncrementCleanupCounts, UdfIncrementReferenceCounts, UdfIsFastIoPossible, UdfLockFcb, UdfLockVcb, UdfOplockComplete(), UdfPrePostIrp(), UdfPurgeVolume(), UdfRaiseStatus(), UdfSetFileObject(), UdfUnlockFcb, UdfUnlockVcb, UserFileOpen, UserVolumeOpen, and VCB_STATE_LOCKED.

Referenced by UdfOpenExistingFcb(), UdfOpenObjectByFileId(), and UdfOpenObjectFromDirContext().

01968 : 01969 01970 This is the worker routine which takes an existing Fcb and completes 01971 the open. We will do any necessary oplock checks and sharing checks. 01972 Finally we will create the Ccb and update the file object and any 01973 file object flags. 01974 01975 Arguments: 01976 01977 IrpSp - Stack location for the current request. 01978 01979 Vcb - Vcb for the current volume. 01980 01981 CurrentFcb - Address of pointer to Fcb to open. We clear this field if 01982 we release the resource for this file. 01983 01984 OpenLcb - Lcb this Fcb is being opened by 01985 01986 TypeOfOpen - Type of open for this request. 01987 01988 UserCcbFlags - Flags to OR into the Ccb flags. 01989 01990 DesiredAccess - Desired access for this open. 01991 01992 Return Value: 01993 01994 NTSTATUS - STATUS_SUCCESS if we complete this request, STATUS_PENDING if 01995 the oplock package takes the Irp or SHARING_VIOLATION if there is a 01996 sharing check conflict. 01997 01998 --*/ 01999 02000 { 02001 NTSTATUS Status; 02002 NTSTATUS OplockStatus = STATUS_SUCCESS; 02003 ULONG Information = FILE_OPENED; 02004 02005 BOOLEAN LockVolume = FALSE; 02006 02007 PFCB Fcb = *CurrentFcb; 02008 PCCB Ccb; 02009 02010 PAGED_CODE(); 02011 02012 // 02013 // If this a volume open and the user wants to lock the volume then 02014 // purge and lock the volume. 02015 // 02016 02017 if ((TypeOfOpen <= UserVolumeOpen) && 02018 !FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ )) { 02019 02020 // 02021 // If there are open handles then fail this immediately. 02022 // 02023 02024 if (Vcb->VcbCleanup != 0) { 02025 02026 return STATUS_SHARING_VIOLATION; 02027 } 02028 02029 // 02030 // If we can't wait then force this to be posted. 02031 // 02032 02033 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 02034 02035 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 02036 } 02037 02038 LockVolume = TRUE; 02039 02040 // 02041 // Purge the volume and make sure all of the user references 02042 // are gone. 02043 // 02044 02045 Status = UdfPurgeVolume( IrpContext, Vcb, FALSE ); 02046 02047 if (Status != STATUS_SUCCESS) { 02048 02049 return Status; 02050 } 02051 02052 // 02053 // Now force all of the delayed close operations to go away. 02054 // 02055 02056 UdfFspClose( Vcb ); 02057 02058 if (Vcb->VcbUserReference > Vcb->VcbResidualUserReference) { 02059 02060 return STATUS_SHARING_VIOLATION; 02061 } 02062 } 02063 02064 // 02065 // If the Fcb already existed then we need to check the oplocks and 02066 // the share access. 02067 // 02068 02069 if (Fcb->FcbCleanup != 0) { 02070 02071 // 02072 // If this is a user file open then check whether there are any 02073 // batch oplock. 02074 // 02075 02076 if (TypeOfOpen == UserFileOpen) { 02077 02078 // 02079 // Store the address of the Fcb for a possible teardown into 02080 // the IrpContext. We will release this in the call to 02081 // prepost the Irp. 02082 // 02083 02084 IrpContext->TeardownFcb = CurrentFcb; 02085 02086 if (FsRtlCurrentBatchOplock( &Fcb->Oplock )) { 02087 02088 // 02089 // We remember if a batch oplock break is underway for the 02090 // case where the sharing check fails. 02091 // 02092 02093 Information = FILE_OPBATCH_BREAK_UNDERWAY; 02094 02095 OplockStatus = FsRtlCheckOplock( &Fcb->Oplock, 02096 IrpContext->Irp, 02097 IrpContext, 02098 UdfOplockComplete, 02099 UdfPrePostIrp ); 02100 02101 if (OplockStatus == STATUS_PENDING) { 02102 02103 return STATUS_PENDING; 02104 } 02105 } 02106 02107 // 02108 // Check the share access before breaking any exclusive oplocks. 02109 // 02110 02111 Status = IoCheckShareAccess( DesiredAccess, 02112 IrpSp->Parameters.Create.ShareAccess, 02113 IrpSp->FileObject, 02114 &Fcb->ShareAccess, 02115 FALSE ); 02116 02117 if (!NT_SUCCESS( Status )) { 02118 02119 return Status; 02120 } 02121 02122 // 02123 // Now check that we can continue based on the oplock state of the 02124 // file. 02125 // 02126 02127 OplockStatus = FsRtlCheckOplock( &Fcb->Oplock, 02128 IrpContext->Irp, 02129 IrpContext, 02130 UdfOplockComplete, 02131 UdfPrePostIrp ); 02132 02133 if (OplockStatus == STATUS_PENDING) { 02134 02135 return STATUS_PENDING; 02136 } 02137 02138 IrpContext->TeardownFcb = NULL; 02139 02140 // 02141 // Otherwise just do the sharing check. 02142 // 02143 02144 } else { 02145 02146 Status = IoCheckShareAccess( DesiredAccess, 02147 IrpSp->Parameters.Create.ShareAccess, 02148 IrpSp->FileObject, 02149 &Fcb->ShareAccess, 02150 FALSE ); 02151 02152 if (!NT_SUCCESS( Status )) { 02153 02154 return Status; 02155 } 02156 } 02157 } 02158 02159 // 02160 // Create the Ccb now. 02161 // 02162 02163 Ccb = UdfCreateCcb( IrpContext, Fcb, OpenLcb, UserCcbFlags ); 02164 02165 // 02166 // Update the share access. 02167 // 02168 02169 if (Fcb->FcbCleanup == 0) { 02170 02171 IoSetShareAccess( DesiredAccess, 02172 IrpSp->Parameters.Create.ShareAccess, 02173 IrpSp->FileObject, 02174 &Fcb->ShareAccess ); 02175 02176 } else { 02177 02178 IoUpdateShareAccess( IrpSp->FileObject, &Fcb->ShareAccess ); 02179 } 02180 02181 // 02182 // Set the file object type. 02183 // 02184 02185 UdfSetFileObject( IrpContext, IrpSp->FileObject, TypeOfOpen, Fcb, Ccb ); 02186 02187 // 02188 // Set the appropriate cache flags for a user file object. 02189 // 02190 02191 if (TypeOfOpen == UserFileOpen) { 02192 02193 if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NO_INTERMEDIATE_BUFFERING )) { 02194 02195 SetFlag( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ); 02196 02197 } else { 02198 02199 SetFlag( IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED ); 02200 } 02201 } 02202 // 02203 // Update the open and cleanup counts. Check the fast io state here. 02204 // 02205 02206 UdfLockVcb( IrpContext, Vcb ); 02207 02208 UdfIncrementCleanupCounts( IrpContext, Fcb ); 02209 02210 DebugTrace(( +1, Dbg, 02211 "UdfCompleteFcbOpen, Fcb %08x Vcb %d/%d Fcb %d/%d\n", Fcb, 02212 Vcb->VcbReference, 02213 Vcb->VcbUserReference, 02214 Fcb->FcbReference, 02215 Fcb->FcbUserReference )); 02216 02217 UdfIncrementReferenceCounts( IrpContext, Fcb, 1, 1 ); 02218 02219 DebugTrace(( -1, Dbg, 02220 "UdfCompleteFcbOpen, Vcb %d/%d Fcb %d/%d\n", 02221 Vcb->VcbReference, 02222 Vcb->VcbUserReference, 02223 Fcb->FcbReference, 02224 Fcb->FcbUserReference )); 02225 02226 if (LockVolume) { 02227 02228 Vcb->VolumeLockFileObject = IrpSp->FileObject; 02229 SetFlag( Vcb->VcbState, VCB_STATE_LOCKED ); 02230 } 02231 02232 UdfUnlockVcb( IrpContext, Vcb ); 02233 02234 UdfLockFcb( IrpContext, Fcb ); 02235 02236 if (TypeOfOpen == UserFileOpen) { 02237 02238 Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb ); 02239 02240 } else { 02241 02242 Fcb->IsFastIoPossible = FastIoIsNotPossible; 02243 } 02244 02245 UdfUnlockFcb( IrpContext, Fcb ); 02246 02247 // 02248 // Show that we opened the file. 02249 // 02250 02251 IrpContext->Irp->IoStatus.Information = Information; 02252 02253 // 02254 // Point to the section object pointer in the non-paged Fcb. 02255 // 02256 02257 IrpSp->FileObject->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject; 02258 return OplockStatus; 02259 }

NTSTATUS UdfNormalizeFileNames IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb,
IN BOOLEAN  OpenByFileId,
IN BOOLEAN  IgnoreCase,
IN TYPE_OF_OPEN  RelatedTypeOfOpen,
IN PCCB RelatedCcb  OPTIONAL,
IN PUNICODE_STRING RelatedFileName  OPTIONAL,
IN OUT PUNICODE_STRING  FileName,
IN OUT PUNICODE_STRING  RemainingName
 

Definition at line 809 of file udfs/create.c.

References Add2Ptr, CCB_FLAG_OPEN_BY_ID, ExFreePool(), FILE_ID, FileName, FlagOn, FsRtlAllocatePoolWithTag, FsRtlDoesNameContainWildCards(), IRP_CONTEXT_FLAG_FULL_NAME, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH, L, NULL, PAGED_CODE, SetFlag, TAG_FILE_NAME, UdfPagedPool, UdfUpcaseName(), UnopenedFileObject, UserDirectoryOpen, UserFileOpen, UserVolumeOpen, and USHORT.

Referenced by UdfCommonCreate().

00823 : 00824 00825 This routine is called to store the full name and upcased name into the 00826 filename buffer. We only upcase the portion yet to parse. We also 00827 check for a trailing backslash and lead-in double backslashes. This 00828 routine also verifies the mode of the related open against the name 00829 currently in the filename. 00830 00831 Arguments: 00832 00833 Vcb - Vcb for this volume. 00834 00835 OpenByFileId - Indicates if the filename should be a 64 bit FileId. 00836 00837 IgnoreCase - Indicates if this open is a case-insensitive operation. 00838 00839 RelatedTypeOfOpen - Indicates the type of the related file object. 00840 00841 RelatedCcb - Ccb for the related open. Ignored if no relative open. 00842 00843 RelatedFileName - FileName buffer for related open. Ignored if no 00844 relative open. 00845 00846 FileName - FileName to update in this routine. The name should 00847 either be a 64-bit FileId or a Unicode string. 00848 00849 RemainingName - Name with the remaining portion of the name. This 00850 will begin after the related name and any separator. For a 00851 non-relative open we also step over the initial separator. 00852 00853 Return Value: 00854 00855 NTSTATUS - STATUS_SUCCESS if the names are OK, appropriate error code 00856 otherwise. 00857 00858 --*/ 00859 00860 { 00861 ULONG RemainingNameLength; 00862 ULONG RelatedNameLength = 0; 00863 ULONG SeparatorLength = 0; 00864 00865 ULONG BufferLength; 00866 00867 UNICODE_STRING NewFileName; 00868 00869 PAGED_CODE(); 00870 00871 // 00872 // If this is the first pass then we need to build the full name and 00873 // check for name compatibility. 00874 // 00875 00876 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME )) { 00877 00878 // 00879 // Deal with the regular file name case first. 00880 // 00881 00882 if (!OpenByFileId) { 00883 00884 // 00885 // Here is the "M A R K L U C O V S K Y" hack. 00886 // 00887 // It's here because Mark says he can't avoid sending me double beginning 00888 // backslashes via the Win32 layer. 00889 // 00890 00891 if ((FileName->Length > sizeof( WCHAR )) && 00892 (FileName->Buffer[1] == L'\\') && 00893 (FileName->Buffer[0] == L'\\')) { 00894 00895 // 00896 // If there are still two beginning backslashes, the name is bogus. 00897 // 00898 00899 if ((FileName->Length > 2 * sizeof( WCHAR )) && 00900 (FileName->Buffer[2] == L'\\')) { 00901 00902 return STATUS_OBJECT_NAME_INVALID; 00903 } 00904 00905 // 00906 // Slide the name down in the buffer. 00907 // 00908 00909 RtlMoveMemory( FileName->Buffer, 00910 FileName->Buffer + 1, 00911 FileName->Length ); 00912 00913 FileName->Length -= sizeof( WCHAR ); 00914 } 00915 00916 // 00917 // Check for a trailing backslash. Don't strip off if only character 00918 // in the full name or for relative opens where this is illegal. 00919 // 00920 00921 if (((FileName->Length > sizeof( WCHAR)) || 00922 ((FileName->Length == sizeof( WCHAR )) && (RelatedTypeOfOpen == UserDirectoryOpen))) && 00923 (FileName->Buffer[ (FileName->Length/2) - 1 ] == L'\\')) { 00924 00925 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ); 00926 FileName->Length -= sizeof( WCHAR ); 00927 } 00928 00929 // 00930 // Remember the length we need for this portion of the name. 00931 // 00932 00933 RemainingNameLength = FileName->Length; 00934 00935 // 00936 // If this is a related file object then we verify the compatibility 00937 // of the name in the file object with the relative file object. 00938 // 00939 00940 if (RelatedTypeOfOpen != UnopenedFileObject) { 00941 00942 // 00943 // If the filename length was zero then it must be legal. 00944 // If there are characters then check with the related 00945 // type of open. 00946 // 00947 00948 if (FileName->Length != 0) { 00949 00950 // 00951 // The name length must always be zero for a volume open. 00952 // 00953 00954 if (RelatedTypeOfOpen <= UserVolumeOpen) { 00955 00956 return STATUS_INVALID_PARAMETER; 00957 00958 // 00959 // The remaining name cannot begin with a backslash. 00960 // 00961 00962 } else if (FileName->Buffer[0] == L'\\' ) { 00963 00964 return STATUS_INVALID_PARAMETER; 00965 00966 // 00967 // If the related file is a user file then there 00968 // is no file with this path. 00969 // 00970 00971 } else if (RelatedTypeOfOpen == UserFileOpen) { 00972 00973 return STATUS_OBJECT_PATH_NOT_FOUND; 00974 } 00975 } 00976 00977 // 00978 // Remember the length of the related name when building 00979 // the full name. We leave the RelatedNameLength and 00980 // SeparatorLength at zero if the relative file is opened 00981 // by Id. 00982 // 00983 00984 if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) { 00985 00986 // 00987 // Add a separator if the name length is non-zero 00988 // unless the relative Fcb is at the root. 00989 // 00990 00991 if ((FileName->Length != 0) && 00992 (RelatedCcb->Fcb != Vcb->RootIndexFcb)) { 00993 00994 SeparatorLength = sizeof( WCHAR ); 00995 } 00996 00997 RelatedNameLength = RelatedFileName->Length; 00998 } 00999 01000 // 01001 // The full name is already in the filename. It must either 01002 // be length 0 or begin with a backslash. 01003 // 01004 01005 } else if (FileName->Length != 0) { 01006 01007 if (FileName->Buffer[0] != L'\\') { 01008 01009 return STATUS_INVALID_PARAMETER; 01010 } 01011 01012 // 01013 // We will want to trim the leading backslash from the 01014 // remaining name we return. 01015 // 01016 01017 RemainingNameLength -= sizeof( WCHAR ); 01018 SeparatorLength = sizeof( WCHAR ); 01019 } 01020 01021 // 01022 // Now see if the buffer is large enough to hold the full name. 01023 // 01024 01025 BufferLength = RelatedNameLength + SeparatorLength + RemainingNameLength; 01026 01027 // 01028 // Check for an overflow of the maximum filename size. 01029 // 01030 01031 if (BufferLength > MAXUSHORT) { 01032 01033 return STATUS_INVALID_PARAMETER; 01034 } 01035 01036 // 01037 // Now see if we need to allocate a new buffer. 01038 // 01039 01040 if (FileName->MaximumLength < BufferLength) { 01041 01042 NewFileName.Buffer = FsRtlAllocatePoolWithTag( UdfPagedPool, 01043 BufferLength, 01044 TAG_FILE_NAME ); 01045 01046 NewFileName.MaximumLength = (USHORT) BufferLength; 01047 01048 } else { 01049 01050 NewFileName.Buffer = FileName->Buffer; 01051 NewFileName.MaximumLength = FileName->MaximumLength; 01052 } 01053 01054 // 01055 // If there is a related name then we need to slide the remaining bytes up and 01056 // insert the related name. Otherwise the name is in the correct position 01057 // already. 01058 // 01059 01060 if (RelatedNameLength != 0) { 01061 01062 // 01063 // Store the remaining name in its correct position. 01064 // 01065 01066 if (RemainingNameLength != 0) { 01067 01068 RtlMoveMemory( Add2Ptr( NewFileName.Buffer, RelatedNameLength + SeparatorLength, PVOID ), 01069 FileName->Buffer, 01070 RemainingNameLength ); 01071 } 01072 01073 RtlCopyMemory( NewFileName.Buffer, 01074 RelatedFileName->Buffer, 01075 RelatedNameLength ); 01076 01077 // 01078 // Add the separator if needed. 01079 // 01080 01081 if (SeparatorLength != 0) { 01082 01083 *(Add2Ptr( NewFileName.Buffer, RelatedNameLength, PWCHAR )) = L'\\'; 01084 } 01085 01086 // 01087 // Update the filename value we got from the user. 01088 // 01089 01090 if (NewFileName.Buffer != FileName->Buffer) { 01091 01092 if (FileName->Buffer != NULL) { 01093 01094 ExFreePool( FileName->Buffer ); 01095 } 01096 01097 FileName->Buffer = NewFileName.Buffer; 01098 FileName->MaximumLength = NewFileName.MaximumLength; 01099 } 01100 01101 // 01102 // Copy the name length to the user's filename. 01103 // 01104 01105 FileName->Length = (USHORT) (RelatedNameLength + SeparatorLength + RemainingNameLength); 01106 } 01107 01108 // 01109 // Now update the remaining name to parse. 01110 // 01111 01112 RemainingName->MaximumLength = 01113 RemainingName->Length = (USHORT) RemainingNameLength; 01114 01115 RemainingName->Buffer = Add2Ptr( FileName->Buffer, 01116 RelatedNameLength + SeparatorLength, 01117 PWCHAR ); 01118 01119 // 01120 // Upcase the name if necessary. 01121 // 01122 01123 if (IgnoreCase && (RemainingNameLength != 0)) { 01124 01125 UdfUpcaseName( IrpContext, 01126 RemainingName, 01127 RemainingName ); 01128 } 01129 01130 // 01131 // Do a quick check to make sure there are no wildcards. 01132 // 01133 01134 if (FsRtlDoesNameContainWildCards( RemainingName )) { 01135 01136 return STATUS_OBJECT_NAME_INVALID; 01137 } 01138 01139 // 01140 // For the open by file Id case we verify the name really contains 01141 // a 64 bit value. 01142 // 01143 01144 } else { 01145 01146 // 01147 // Check for validity of the buffer. 01148 // 01149 01150 if (FileName->Length != sizeof( FILE_ID )) { 01151 01152 return STATUS_INVALID_PARAMETER; 01153 } 01154 } 01155 01156 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME ); 01157 01158 // 01159 // If we are in the retry path then the full name is already in the 01160 // file object name. If this is a case-sensitive operation then 01161 // we need to upcase the name from the end of any related file name already stored 01162 // there. 01163 // 01164 01165 } else { 01166 01167 // 01168 // Assume there is no relative name. 01169 // 01170 01171 *RemainingName = *FileName; 01172 01173 // 01174 // Nothing to do if the name length is zero. 01175 // 01176 01177 if (RemainingName->Length != 0) { 01178 01179 // 01180 // If there is a relative name then we need to walk past it. 01181 // 01182 01183 if (RelatedTypeOfOpen != UnopenedFileObject) { 01184 01185 // 01186 // Nothing to walk past if the RelatedCcb is opened by FileId. 01187 // 01188 01189 01190 if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) { 01191 01192 // 01193 // Related file name is a proper prefix of the full name. 01194 // We step over the related name and if we are then 01195 // pointing at a separator character we step over that. 01196 // 01197 01198 RemainingName->Buffer = Add2Ptr( RemainingName->Buffer, 01199 RelatedFileName->Length, 01200 PWCHAR ); 01201 01202 RemainingName->Length -= RelatedFileName->Length; 01203 } 01204 } 01205 01206 // 01207 // If we are pointing at a separator character then step past that. 01208 // 01209 01210 if (RemainingName->Length != 0) { 01211 01212 if (*(RemainingName->Buffer) == L'\\') { 01213 01214 RemainingName->Buffer = Add2Ptr( RemainingName->Buffer, 01215 sizeof( WCHAR ), 01216 PWCHAR ); 01217 01218 RemainingName->Length -= sizeof( WCHAR ); 01219 } 01220 } 01221 } 01222 01223 // 01224 // Upcase the name if necessary. 01225 // 01226 01227 if (IgnoreCase && (RemainingName->Length != 0)) { 01228 01229 UdfUpcaseName( IrpContext, 01230 RemainingName, 01231 RemainingName ); 01232 } 01233 } 01234 01235 return STATUS_SUCCESS; 01236 }

NTSTATUS UdfOpenExistingFcb IN PIRP_CONTEXT  IrpContext,
IN PIO_STACK_LOCATION  IrpSp,
IN OUT PFCB CurrentFcb,
IN PLCB  OpenLcb,
IN TYPE_OF_OPEN  TypeOfOpen,
IN BOOLEAN  IgnoreCase,
IN PCCB RelatedCcb  OPTIONAL
 

Definition at line 1522 of file udfs/create.c.

References ASSERT_EXCLUSIVE_FCB, ASSERT_IRP_CONTEXT, ASSERT_OPTIONAL_CCB, CCB_FLAG_IGNORE_CASE, CCB_FLAG_OPEN_BY_ID, CCB_FLAG_OPEN_RELATIVE_BY_ID, FlagOn, NTSTATUS(), PAGED_CODE, SetFlag, Status, UdfCompleteFcbOpen(), and UdfIllegalFcbAccess().

Referenced by UdfCommonCreate().

01534 : 01535 01536 This routine is called to open an Fcb which is already in the Fcb table. 01537 We will verify the access to the file and then call our worker routine 01538 to perform the final operations. 01539 01540 Arguments: 01541 01542 IrpSp - Pointer to the stack location for this open. 01543 01544 CurrentFcb - Address of Fcb to open. We will clear this if the Fcb 01545 is released here. 01546 01547 OpenLcb - Lcb used to find this Fcb. 01548 01549 TypeOfOpen - Indicates whether we are opening a file, directory or volume. 01550 01551 IgnoreCase - Indicates if this open is case-insensitive. 01552 01553 RelatedCcb - Ccb for related file object if relative open. We use 01554 this when setting the Ccb flags for this open. It will tell 01555 us whether the name currently in the file object is relative or 01556 absolute. 01557 01558 Return Value: 01559 01560 NTSTATUS - Status indicating the result of the operation. 01561 01562 --*/ 01563 01564 { 01565 ULONG CcbFlags = 0; 01566 01567 NTSTATUS Status = STATUS_ACCESS_DENIED; 01568 01569 PAGED_CODE(); 01570 01571 // 01572 // Check inputs. 01573 // 01574 01575 ASSERT_IRP_CONTEXT( IrpContext ); 01576 ASSERT_EXCLUSIVE_FCB( *CurrentFcb ); 01577 ASSERT_OPTIONAL_CCB( RelatedCcb ); 01578 01579 // 01580 // Check that the desired access is legal. 01581 // 01582 01583 if (!UdfIllegalFcbAccess( IrpContext, 01584 TypeOfOpen, 01585 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { 01586 01587 // 01588 // Set the Ignore case. 01589 // 01590 01591 if (IgnoreCase) { 01592 01593 SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); 01594 } 01595 01596 // 01597 // Check the related Ccb to see if this was an OpenByFileId and 01598 // whether there was a version. 01599 // 01600 01601 if (ARGUMENT_PRESENT( RelatedCcb )) { 01602 01603 if (FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { 01604 01605 SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID ); 01606 } 01607 } 01608 01609 // 01610 // Call our worker routine to complete the open. 01611 // 01612 01613 Status = UdfCompleteFcbOpen( IrpContext, 01614 IrpSp, 01615 (*CurrentFcb)->Vcb, 01616 CurrentFcb, 01617 OpenLcb, 01618 TypeOfOpen, 01619 CcbFlags, 01620 IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); 01621 } 01622 01623 return Status; 01624 }

NTSTATUS UdfOpenObjectByFileId IN PIRP_CONTEXT  IrpContext,
IN PIO_STACK_LOCATION  IrpSp,
IN PVCB  Vcb,
IN OUT PFCB CurrentFcb
 

Definition at line 1244 of file udfs/create.c.

References ASSERT_IRP_CONTEXT, ASSERT_VCB, CCB_FLAG_OPEN_BY_ID, FALSE, FCB_STATE_INITIALIZED, _FCB::FcbReference, _FCB::FcbState, FILE_ID, _FCB::FileAttributes, _FCB::FileId, FlagOn, ICB_SEARCH_CONTEXT, IRP_CONTEXT_FLAG_WAIT, NODE_TYPE_CODE, NTSTATUS(), NULL, PAGED_CODE, Status, TRUE, try_leave, TYPE_OF_OPEN, UdfAcquireFcbExclusive, UdfCleanupIcbContext(), UdfCompleteFcbOpen(), UdfCreateFcb(), UdfDeleteFcb(), UdfExceptionFilter(), UdfGetFidReservedZero, UdfIllegalFcbAccess(), UdfInitializeFcbFromIcbContext(), UdfInitializeIcbContextFromFcb(), UdfIsFidDirectory, UdfLockVcb, UdfLookupActiveIcb(), UdfRaiseStatus(), UDFS_NTC_FCB_DATA, UDFS_NTC_FCB_INDEX, UdfUnlockVcb, UserDirectoryOpen, and UserFileOpen.

Referenced by UdfCommonCreate().

01253 : 01254 01255 This routine is called to open a file by the FileId. The file Id is in 01256 the FileObject name buffer and has been verified to be 64 bits. 01257 01258 We extract the Id number and then check to see whether we are opening a 01259 file or directory and compare that with the create options. If this 01260 generates no error then optimistically look up the Fcb in the Fcb Table. 01261 01262 If we don't find the Fcb then we take what is effectively a wild-a** guess. 01263 Since we would need more than 64bits to contain the root extent length along 01264 with the partition, lbn and dir/file flag we have to speculate that the 01265 opener knows what they are doing and try to crack an ICB hierarchy at the 01266 specified location. This can fail for any number of reasons, which then have 01267 to be mapped to an open failure. 01268 01269 If found then build the Fcb from this entry and store the new Fcb in the 01270 tree. 01271 01272 Finally we call our worker routine to complete the open on this Fcb. 01273 01274 Arguments: 01275 01276 IrpSp - Stack location within the create Irp. 01277 01278 Vcb - Vcb for this volume. 01279 01280 CurrentFcb - Address to store the Fcb for this open. We only store the 01281 CurrentFcb here when we have acquired it so our caller knows to 01282 free or deallocate it. 01283 01284 Return Value: 01285 01286 NTSTATUS - Status indicating the result of the operation. 01287 01288 --*/ 01289 01290 { 01291 NTSTATUS Status = STATUS_ACCESS_DENIED; 01292 01293 BOOLEAN UnlockVcb = FALSE; 01294 BOOLEAN Found; 01295 BOOLEAN FcbExisted; 01296 01297 ICB_SEARCH_CONTEXT IcbContext; 01298 BOOLEAN CleanupIcbContext = FALSE; 01299 01300 NODE_TYPE_CODE NodeTypeCode; 01301 TYPE_OF_OPEN TypeOfOpen; 01302 01303 FILE_ID FileId; 01304 01305 PFCB NextFcb = NULL; 01306 01307 PAGED_CODE(); 01308 01309 // 01310 // Check inputs. 01311 // 01312 01313 ASSERT_IRP_CONTEXT( IrpContext ); 01314 ASSERT_VCB( Vcb ); 01315 01316 // 01317 // Extract the FileId from the FileObject. 01318 // 01319 01320 RtlCopyMemory( &FileId, IrpSp->FileObject->FileName.Buffer, sizeof( FILE_ID )); 01321 01322 // 01323 // Now do a quick check that the reserved, unused chunk of the fileid is 01324 // unused in this specimen. 01325 // 01326 01327 if (UdfGetFidReservedZero( FileId )) { 01328 01329 return STATUS_INVALID_PARAMETER; 01330 } 01331 01332 // 01333 // Go ahead and figure out the TypeOfOpen and NodeType. We can 01334 // get these from the input FileId. 01335 // 01336 01337 if (UdfIsFidDirectory( FileId )) { 01338 01339 TypeOfOpen = UserDirectoryOpen; 01340 NodeTypeCode = UDFS_NTC_FCB_INDEX; 01341 01342 } else { 01343 01344 TypeOfOpen = UserFileOpen; 01345 NodeTypeCode = UDFS_NTC_FCB_DATA; 01346 } 01347 01348 // 01349 // Use a try-finally to facilitate cleanup. 01350 // 01351 01352 try { 01353 01354 // 01355 // Acquire the Vcb and check if there is already an Fcb. 01356 // If not we will need to carefully hunt for the on-disc 01357 // structures. 01358 // 01359 // We will post the request if we don't find the Fcb and this 01360 // request can't wait. 01361 // 01362 01363 UdfLockVcb( IrpContext, Vcb ); 01364 UnlockVcb = TRUE; 01365 01366 NextFcb = UdfCreateFcb( IrpContext, FileId, NodeTypeCode, &FcbExisted ); 01367 01368 // 01369 // Now, if the Fcb was not already here we have some work to do. 01370 // 01371 01372 if (!FcbExisted) { 01373 01374 // 01375 // If we can't wait then post this request. 01376 // 01377 01378 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) { 01379 01380 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT ); 01381 } 01382 01383 // 01384 // Use a try-finally to transform errors we get as a result of going 01385 // off on a wild goose chase into a simple open failure. 01386 // 01387 01388 try { 01389 01390 NextFcb->FileId = FileId; 01391 01392 UdfInitializeIcbContextFromFcb( IrpContext, &IcbContext, NextFcb ); 01393 CleanupIcbContext = TRUE; 01394 01395 UdfLookupActiveIcb( IrpContext, &IcbContext ); 01396 01397 UdfInitializeFcbFromIcbContext( IrpContext, 01398 NextFcb, 01399 &IcbContext ); 01400 01401 UdfCleanupIcbContext( IrpContext, &IcbContext ); 01402 CleanupIcbContext = FALSE; 01403 01404 } except( UdfExceptionFilter( IrpContext, GetExceptionInformation() )) { 01405 01406 // 01407 // Any error we receive is an indication that the given fileid is 01408 // not valid. 01409 // 01410 01411 Status = STATUS_INVALID_PARAMETER; 01412 } 01413 01414 // 01415 // Do a little dance to leave the exception handler if we had problems. 01416 // 01417 01418 if (Status == STATUS_INVALID_PARAMETER) { 01419 01420 try_leave( NOTHING ); 01421 } 01422 } 01423 01424 // 01425 // We have the Fcb. Check that the type of the file is compatible with 01426 // the desired type of file to open. 01427 // 01428 01429 if (FlagOn( NextFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 01430 01431 if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) { 01432 01433 try_leave( Status = STATUS_FILE_IS_A_DIRECTORY ); 01434 } 01435 01436 } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) { 01437 01438 try_leave( Status = STATUS_NOT_A_DIRECTORY ); 01439 } 01440 01441 // 01442 // We now know the Fcb and currently hold the Vcb lock. 01443 // Try to acquire this Fcb without waiting. Otherwise we 01444 // need to reference it, drop the Vcb, acquire the Fcb, the 01445 // Vcb and then dereference the Fcb. 01446 // 01447 01448 if (!UdfAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { 01449 01450 NextFcb->FcbReference += 1; 01451 UdfUnlockVcb( IrpContext, Vcb ); 01452 01453 UdfAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); 01454 01455 UdfLockVcb( IrpContext, Vcb ); 01456 NextFcb->FcbReference -= 1; 01457 } 01458 01459 UdfUnlockVcb( IrpContext, Vcb ); 01460 UnlockVcb = FALSE; 01461 01462 // 01463 // Move to this Fcb. 01464 // 01465 01466 *CurrentFcb = NextFcb; 01467 01468 // 01469 // Check the requested access on this Fcb. 01470 // 01471 01472 if (!UdfIllegalFcbAccess( IrpContext, 01473 TypeOfOpen, 01474 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { 01475 01476 // 01477 // Call our worker routine to complete the open. 01478 // 01479 01480 Status = UdfCompleteFcbOpen( IrpContext, 01481 IrpSp, 01482 Vcb, 01483 CurrentFcb, 01484 NULL, 01485 TypeOfOpen, 01486 CCB_FLAG_OPEN_BY_ID, 01487 IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); 01488 } 01489 01490 } finally { 01491 01492 if (UnlockVcb) { 01493 01494 UdfUnlockVcb( IrpContext, Vcb ); 01495 } 01496 01497 if (CleanupIcbContext) { 01498 01499 UdfCleanupIcbContext( IrpContext, &IcbContext ); 01500 } 01501 01502 // 01503 // Destroy the new Fcb if it was not fully initialized. 01504 // 01505 01506 if (NextFcb && !FlagOn( NextFcb->FcbState, FCB_STATE_INITIALIZED )) { 01507 01508 UdfDeleteFcb( IrpContext, NextFcb ); 01509 } 01510 01511 } 01512 01513 return Status; 01514 }

NTSTATUS UdfOpenObjectFromDirContext IN PIRP_CONTEXT  IrpContext,
IN PIO_STACK_LOCATION  IrpSp,
IN PVCB  Vcb,
IN OUT PFCB CurrentFcb,
IN BOOLEAN  ShortNameMatch,
IN BOOLEAN  IgnoreCase,
IN PDIR_ENUM_CONTEXT  DirContext,
IN BOOLEAN  PerformUserOpen,
IN PCCB RelatedCcb  OPTIONAL
 

Definition at line 1632 of file udfs/create.c.

References CCB_FLAG_IGNORE_CASE, CCB_FLAG_OPEN_BY_ID, CCB_FLAG_OPEN_RELATIVE_BY_ID, Dbg, DebugTrace, FALSE, FCB_STATE_INITIALIZED, _FCB::FcbReference, _FCB::FcbState, _FCB::FcbUserReference, FILE_ID, FlagOn, NODE_TYPE_CODE, NSR_FID_F_DIRECTORY, NTSTATUS(), NULL, PAGED_CODE, _FCB::RootExtentLength, SetFlag, Status, TRUE, TYPE_OF_OPEN, UdfAcquireFcbExclusive, UdfCleanupIcbContext(), UdfCompleteFcbOpen(), UdfCreateFcb(), UdfDeleteFcb(), UdfIllegalFcbAccess(), UdfIncrementReferenceCounts, UdfInitializeFcbFromIcbContext(), UdfInitializeIcbContextFromFcb(), UdfInitializeLcbFromDirContext(), UdfInsertPrefix(), UdfLockVcb, UdfLookupActiveIcb(), UdfReleaseFcb, UDFS_NTC_FCB_DATA, UDFS_NTC_FCB_INDEX, UdfSetFidDirectory, UdfSetFidFromLbAddr, UdfUnlockVcb, UserDirectoryOpen, and UserFileOpen.

Referenced by UdfCommonCreate().

01646 : 01647 01648 This routine is called to open an object found in a directory scan. This 01649 can be a directory or a file as indicated in the scan's results. 01650 01651 We first check that the desired access is legal for this file. Then we 01652 construct the FileId for this and do a check to see if it is the Fcb 01653 Table. It is always possible that either it was created since or simply 01654 wasn't in the prefix table at the time of the prefix table search. 01655 Lookup the active ICB, initialize the Fcb and store into the FcbTable 01656 if not present. 01657 01658 Next we will add this to the prefix table of our parent if needed. 01659 01660 Once we know that the new Fcb has been initialized then we move our pointer 01661 in the tree down to this position. 01662 01663 This routine does not own the Vcb lock on entry. We must be sure to release 01664 it on exit. 01665 01666 Arguments: 01667 01668 IrpSp - Stack location for this request. 01669 01670 Vcb - Vcb for the current volume. 01671 01672 CurrentFcb - On input this is the parent of the Fcb to open. On output we 01673 store the Fcb for the file being opened. 01674 01675 ShortNameMatch - Indicates whether this object was opened by the shortname. 01676 01677 IgnoreCase - Indicates the case sensitivity of the caller. 01678 01679 DirContext - This is the context used to find the object. 01680 01681 PerformUserOpen - Indicates if we are at the object the user wants to finally open. 01682 01683 RelatedCcb - RelatedCcb for relative file object used to make this open. 01684 01685 Return Value: 01686 01687 NTSTATUS - Status indicating the result of the operation. 01688 01689 --*/ 01690 01691 { 01692 ULONG CcbFlags = 0; 01693 FILE_ID FileId; 01694 01695 BOOLEAN UnlockVcb = FALSE; 01696 BOOLEAN FcbExisted; 01697 01698 PFCB NextFcb = NULL; 01699 PFCB ParentFcb = NULL; 01700 01701 TYPE_OF_OPEN TypeOfOpen; 01702 NODE_TYPE_CODE NodeTypeCode; 01703 01704 ICB_SEARCH_CONTEXT IcbContext; 01705 BOOLEAN CleanupIcbContext = FALSE; 01706 01707 PLCB OpenLcb; 01708 01709 NTSTATUS Status; 01710 01711 PAGED_CODE(); 01712 01713 // 01714 // Figure out what kind of open we will be performing here. The caller has already insured 01715 // that the user is expecting us to do this. 01716 // 01717 01718 if (FlagOn( DirContext->Fid->Flags, NSR_FID_F_DIRECTORY )) { 01719 01720 TypeOfOpen = UserDirectoryOpen; 01721 NodeTypeCode = UDFS_NTC_FCB_INDEX; 01722 01723 } else { 01724 01725 TypeOfOpen = UserFileOpen; 01726 NodeTypeCode = UDFS_NTC_FCB_DATA; 01727 } 01728 01729 // 01730 // Check for illegal access to this file. 01731 // 01732 01733 if (PerformUserOpen && 01734 UdfIllegalFcbAccess( IrpContext, 01735 TypeOfOpen, 01736 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) { 01737 01738 return STATUS_ACCESS_DENIED; 01739 } 01740 01741 // 01742 // Use a try-finally to facilitate cleanup. 01743 // 01744 01745 try { 01746 01747 // 01748 // Check the related Ccb to see if this was an OpenByFileId. 01749 // 01750 01751 if (ARGUMENT_PRESENT( RelatedCcb ) && 01752 FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) { 01753 01754 SetFlag( CcbFlags, CCB_FLAG_OPEN_RELATIVE_BY_ID ); 01755 } 01756 01757 if (IgnoreCase) { 01758 01759 SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE ); 01760 } 01761 01762 // 01763 // Build the file Id for this object. 01764 // 01765 01766 UdfSetFidFromLbAddr( FileId, DirContext->Fid->Icb.Start ); 01767 01768 if (TypeOfOpen == UserDirectoryOpen) { 01769 01770 UdfSetFidDirectory( FileId ); 01771 } 01772 01773 // 01774 // Lock the Vcb so we can examine the Fcb Table. 01775 // 01776 01777 UdfLockVcb( IrpContext, Vcb ); 01778 UnlockVcb = TRUE; 01779 01780 // 01781 // Get the Fcb for this file. 01782 // 01783 01784 NextFcb = UdfCreateFcb( IrpContext, FileId, NodeTypeCode, &FcbExisted ); 01785 01786 // 01787 // If the Fcb was created here then initialize from the values in the 01788 // dirent. We have optimistically assumed that there isn't any corrupt 01789 // information to this point - we're about to discover it if there is. 01790 // 01791 01792 if (!FcbExisted) { 01793 01794 // 01795 // Set the root extent length and go get the active ICB, initialize. 01796 // 01797 01798 NextFcb->RootExtentLength = DirContext->Fid->Icb.Length.Length; 01799 01800 UdfInitializeIcbContextFromFcb( IrpContext, &IcbContext, NextFcb ); 01801 CleanupIcbContext = TRUE; 01802 01803 UdfLookupActiveIcb( IrpContext, &IcbContext ); 01804 01805 UdfInitializeFcbFromIcbContext( IrpContext, 01806 NextFcb, 01807 &IcbContext ); 01808 01809 UdfCleanupIcbContext( IrpContext, &IcbContext ); 01810 CleanupIcbContext = FALSE; 01811 01812 } 01813 01814 // 01815 // Now try to acquire the new Fcb without waiting. We will reference 01816 // the Fcb and retry with wait if unsuccessful. 01817 // 01818 01819 if (!UdfAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) { 01820 01821 NextFcb->FcbReference += 1; 01822 01823 UdfUnlockVcb( IrpContext, Vcb ); 01824 01825 UdfReleaseFcb( IrpContext, *CurrentFcb ); 01826 UdfAcquireFcbExclusive( IrpContext, NextFcb, FALSE ); 01827 UdfAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE ); 01828 01829 UdfLockVcb( IrpContext, Vcb ); 01830 NextFcb->FcbReference -= 1; 01831 } 01832 01833 // 01834 // Move down to this new Fcb. Remember that we still own the parent however. 01835 // 01836 01837 ParentFcb = *CurrentFcb; 01838 *CurrentFcb = NextFcb; 01839 01840 // 01841 // Store this name into the prefix table for the parent. 01842 // 01843 01844 OpenLcb = UdfInsertPrefix( IrpContext, 01845 NextFcb, 01846 ( ShortNameMatch? 01847 &DirContext->ShortObjectName : 01848 &DirContext->CaseObjectName ), 01849 ShortNameMatch, 01850 IgnoreCase, 01851 ParentFcb ); 01852 01853 // 01854 // Now increment the reference counts for the parent and drop the Vcb. 01855 // 01856 01857 DebugTrace(( +1, Dbg, 01858 "UdfOpenObjectFromDirContext, PFcb %08x Vcb %d/%d Fcb %d/%d\n", ParentFcb, 01859 Vcb->VcbReference, 01860 Vcb->VcbUserReference, 01861 ParentFcb->FcbReference, 01862 ParentFcb->FcbUserReference )); 01863 01864 UdfIncrementReferenceCounts( IrpContext, ParentFcb, 1, 1 ); 01865 01866 DebugTrace(( -1, Dbg, 01867 "UdfOpenObjectFromDirContext, Vcb %d/%d Fcb %d/%d\n", 01868 Vcb->VcbReference, 01869 Vcb->VcbUserReference, 01870 ParentFcb->FcbReference, 01871 ParentFcb->FcbUserReference )); 01872 01873 UdfUnlockVcb( IrpContext, Vcb ); 01874 UnlockVcb = FALSE; 01875 01876 // 01877 // Perform initialization associated with the directory context. 01878 // 01879 01880 UdfInitializeLcbFromDirContext( IrpContext, 01881 OpenLcb, 01882 DirContext ); 01883 01884 // 01885 // Release the parent Fcb at this point. 01886 // 01887 01888 UdfReleaseFcb( IrpContext, ParentFcb ); 01889 ParentFcb = NULL; 01890 01891 // 01892 // Call our worker routine to complete the open. 01893 // 01894 01895 if (PerformUserOpen) { 01896 01897 Status = UdfCompleteFcbOpen( IrpContext, 01898 IrpSp, 01899 Vcb, 01900 CurrentFcb, 01901 OpenLcb, 01902 TypeOfOpen, 01903 CcbFlags, 01904 IrpSp->Parameters.Create.SecurityContext->DesiredAccess ); 01905 } 01906 01907 } finally { 01908 01909 // 01910 // Unlock the Vcb if held. 01911 // 01912 01913 if (UnlockVcb) { 01914 01915 UdfUnlockVcb( IrpContext, Vcb ); 01916 } 01917 01918 // 01919 // Release the parent if held. 01920 // 01921 01922 if (ParentFcb != NULL) { 01923 01924 UdfReleaseFcb( IrpContext, ParentFcb ); 01925 } 01926 01927 // 01928 // Destroy the new Fcb if it was not fully initialized. 01929 // 01930 01931 if (NextFcb && !FlagOn( NextFcb->FcbState, FCB_STATE_INITIALIZED )) { 01932 01933 UdfDeleteFcb( IrpContext, NextFcb ); 01934 } 01935 01936 // 01937 // Clean up the Icb context if used. 01938 // 01939 01940 if (CleanupIcbContext) { 01941 01942 UdfCleanupIcbContext( IrpContext, &IcbContext ); 01943 } 01944 } 01945 01946 return Status; 01947 }


Generated on Sat May 15 19:43:18 2004 for test by doxygen 1.3.7