1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 /************************************************************************* 7 * 8 * File: Create.cpp 9 * 10 * Module: UDF File System Driver (Kernel mode execution only) 11 * 12 * Description: 13 * Contains code to handle the "Create"/"Open" dispatch entry point. 14 * 15 *************************************************************************/ 16 17 #include "udffs.h" 18 19 #define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess)) 20 21 // define the file specific bug-check id 22 #define UDF_BUG_CHECK_ID UDF_FILE_CREATE 23 24 #define MEM_USABS_TAG "US_Abs" 25 #define MEM_USLOC_TAG "US_Loc" 26 #define MEM_USOBJ_TAG "US_Obj" 27 28 #define UDF_LOG_CREATE_DISPOSITION 29 30 /************************************************************************* 31 * 32 * Function: UDFCreate() 33 * 34 * Description: 35 * The I/O Manager will invoke this routine to handle a create/open 36 * request 37 * 38 * Expected Interrupt Level (for execution) : 39 * 40 * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 41 * to be deferred to a worker thread context) 42 * 43 * Return Value: STATUS_SUCCESS/Error 44 * 45 *************************************************************************/ 46 NTSTATUS 47 NTAPI 48 UDFCreate( 49 PDEVICE_OBJECT DeviceObject, // the logical volume device object 50 PIRP Irp) // I/O Request Packet 51 { 52 NTSTATUS RC = STATUS_SUCCESS; 53 PtrUDFIrpContext PtrIrpContext; 54 BOOLEAN AreWeTopLevel = FALSE; 55 56 TmPrint(("UDFCreate:\n")); 57 58 FsRtlEnterFileSystem(); 59 ASSERT(DeviceObject); 60 ASSERT(Irp); 61 62 // sometimes, we may be called here with the device object representing 63 // the file system (instead of the device object created for a logical 64 // volume. In this case, there is not much we wish to do (this create 65 // typically will happen 'cause some process has to open the FSD device 66 // object so as to be able to send an IOCTL to the FSD) 67 68 // All of the logical volume device objects we create have a device 69 // extension whereas the device object representing the FSD has no 70 // device extension. This seems like a good enough method to identify 71 // between the two device objects ... 72 if (UDFIsFSDevObj(DeviceObject)) { 73 // this is an open of the FSD itself 74 Irp->IoStatus.Status = RC; 75 Irp->IoStatus.Information = FILE_OPENED; 76 77 IoCompleteRequest(Irp, IO_NO_INCREMENT); 78 FsRtlExitFileSystem(); 79 return(RC); 80 } 81 82 // set the top level context 83 AreWeTopLevel = UDFIsIrpTopLevel(Irp); 84 85 _SEH2_TRY { 86 87 // get an IRP context structure and issue the request 88 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); 89 if(PtrIrpContext) { 90 RC = UDFCommonCreate(PtrIrpContext, Irp); 91 } else { 92 RC = STATUS_INSUFFICIENT_RESOURCES; 93 Irp->IoStatus.Status = RC; 94 Irp->IoStatus.Information = 0; 95 // complete the IRP 96 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 97 } 98 99 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) { 100 101 RC = UDFExceptionHandler(PtrIrpContext, Irp); 102 103 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); 104 } _SEH2_END; 105 106 if (AreWeTopLevel) { 107 IoSetTopLevelIrp(NULL); 108 } 109 110 AdPrint(("UDFCreate: %x\n", RC)); 111 112 FsRtlExitFileSystem(); 113 114 return(RC); 115 116 } // end UDFCreate() 117 118 /* 119 */ 120 VOID 121 __fastcall 122 UDFReleaseResFromCreate( 123 IN PERESOURCE* PagingIoRes, 124 IN PERESOURCE* Res1, 125 IN PERESOURCE* Res2 126 ) 127 { 128 if(*PagingIoRes) { 129 UDFReleaseResource(*PagingIoRes); 130 (*PagingIoRes) = NULL; 131 } 132 if(*Res1) { 133 UDFReleaseResource(*Res1); 134 (*Res1) = NULL; 135 } 136 if(*Res2) { 137 UDFReleaseResource(*Res2); 138 (*Res2) = NULL; 139 } 140 } // end UDFReleaseResFromCreate() 141 142 /* 143 */ 144 VOID 145 __fastcall 146 UDFAcquireParent( 147 IN PUDF_FILE_INFO RelatedFileInfo, 148 IN PERESOURCE* Res1, 149 IN PERESOURCE* Res2 150 ) 151 { 152 if(RelatedFileInfo->Fcb && 153 RelatedFileInfo->Fcb->ParentFcb) { 154 155 UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->ParentFcb->NTRequiredFCB); 156 UDFAcquireResourceExclusive((*Res2) = &(RelatedFileInfo->Fcb->ParentFcb->NTRequiredFCB->MainResource),TRUE); 157 } 158 159 UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB); 160 UDFAcquireResourceExclusive((*Res1) = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE); 161 162 UDFInterlockedIncrement((PLONG)&(RelatedFileInfo->Fcb->ReferenceCount)); 163 UDFInterlockedIncrement((PLONG)&(RelatedFileInfo->Dloc->CommonFcb->CommonRefCount)); 164 UDFReferenceFile__(RelatedFileInfo); 165 ASSERT_REF(RelatedFileInfo->Fcb->ReferenceCount >= RelatedFileInfo->RefCount); 166 } // end UDFAcquireParent() 167 168 /************************************************************************* 169 * 170 * Function: UDFCommonCreate() 171 * 172 * Description: 173 * The actual work is performed here. This routine may be invoked in one' 174 * of the two possible contexts: 175 * (a) in the context of a system worker thread 176 * (b) in the context of the original caller 177 * 178 * Expected Interrupt Level (for execution) : 179 * 180 * IRQL_PASSIVE_LEVEL 181 * 182 * Return Value: STATUS_SUCCESS/Error 183 * 184 *************************************************************************/ 185 NTSTATUS 186 UDFCommonCreate( 187 PtrUDFIrpContext PtrIrpContext, 188 PIRP Irp 189 ) 190 { 191 NTSTATUS RC = STATUS_SUCCESS; 192 PIO_STACK_LOCATION IrpSp = NULL; 193 PIO_SECURITY_CONTEXT PtrSecurityContext = NULL; 194 PFILE_OBJECT PtrNewFileObject = NULL; 195 PFILE_OBJECT PtrRelatedFileObject = NULL; 196 LONGLONG AllocationSize; // if we create a new file 197 PFILE_FULL_EA_INFORMATION PtrExtAttrBuffer = NULL; 198 ULONG RequestedOptions; 199 ULONG RequestedDisposition; 200 USHORT FileAttributes; 201 USHORT TmpFileAttributes; 202 USHORT ShareAccess; 203 ULONG ExtAttrLength = 0; 204 ACCESS_MASK DesiredAccess; 205 PACCESS_STATE AccessState; 206 207 PVCB Vcb = NULL; 208 _SEH2_VOLATILE BOOLEAN AcquiredVcb = FALSE; 209 BOOLEAN OpenExisting = FALSE; 210 PERESOURCE Res1 = NULL; 211 PERESOURCE Res2 = NULL; 212 PERESOURCE PagingIoRes = NULL; 213 214 // BOOLEAN DirectoryOnlyRequested; 215 // BOOLEAN FileOnlyRequested; 216 // BOOLEAN NoBufferingSpecified; 217 BOOLEAN WriteThroughRequested; 218 BOOLEAN DeleteOnCloseSpecified; 219 // BOOLEAN NoExtAttrKnowledge; 220 // BOOLEAN CreateTreeConnection = FALSE; 221 // BOOLEAN OpenByFileId; 222 223 // Are we dealing with a page file? 224 BOOLEAN PageFileManipulation; 225 // Is this open for a target directory (used in rename operations)? 226 BOOLEAN OpenTargetDirectory; 227 // Should we ignore case when attempting to locate the object? 228 BOOLEAN IgnoreCase; 229 230 PtrUDFCCB PtrRelatedCCB = NULL, PtrNewCcb = NULL; 231 PtrUDFFCB PtrRelatedFCB = NULL, PtrNewFcb = NULL; 232 PtrUDFNTRequiredFCB NtReqFcb; 233 234 ULONG ReturnedInformation; 235 236 UNICODE_STRING TargetObjectName; 237 UNICODE_STRING RelatedObjectName; 238 239 UNICODE_STRING AbsolutePathName; // '\aaa\cdf\fff\rrrr.tre:s' 240 UNICODE_STRING LocalPath; // '\aaa\cdf' 241 UNICODE_STRING CurName; // 'cdf' 242 UNICODE_STRING TailName; // 'fff\rrrr.tre:s' 243 UNICODE_STRING LastGoodName; // it depends... 244 UNICODE_STRING LastGoodTail; // it depends... 245 UNICODE_STRING StreamName; // ':s' 246 247 PUDF_FILE_INFO RelatedFileInfo; 248 PUDF_FILE_INFO OldRelatedFileInfo = NULL; 249 PUDF_FILE_INFO NewFileInfo = NULL; 250 PUDF_FILE_INFO LastGoodFileInfo = NULL; 251 PWCHAR TmpBuffer; 252 ULONG TreeLength = 0; 253 // ULONG i = 0; 254 255 BOOLEAN StreamOpen = FALSE; 256 BOOLEAN StreamExists = FALSE; 257 BOOLEAN RestoreVCBOpenCounter = FALSE; 258 BOOLEAN RestoreShareAccess = FALSE; 259 PWCHAR TailNameBuffer = NULL; 260 ULONG SNameIndex = 0; 261 262 TmPrint(("UDFCommonCreate:\n")); 263 264 ASSERT(PtrIrpContext); 265 ASSERT(Irp); 266 267 _SEH2_TRY { 268 269 AbsolutePathName.Buffer = 270 LocalPath.Buffer = NULL; 271 // If we were called with our file system device object instead of a 272 // volume device object, just complete this request with STATUS_SUCCESS. 273 if (!(PtrIrpContext->TargetDeviceObject->DeviceExtension)) { 274 275 ReturnedInformation = FILE_OPENED; 276 try_return(RC = STATUS_SUCCESS); 277 } 278 279 AbsolutePathName.Length = AbsolutePathName.MaximumLength = 280 LocalPath.Length = LocalPath.MaximumLength = 0; 281 // First, get a pointer to the current I/O stack location 282 IrpSp = IoGetCurrentIrpStackLocation(Irp); 283 ASSERT(IrpSp); 284 285 // If the caller cannot block, post the request to be handled 286 // asynchronously 287 if (!(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK)) { 288 // We must defer processing of this request since we could 289 // block anytime while performing the create/open ... 290 ASSERT(FALSE); 291 RC = UDFPostRequest(PtrIrpContext, Irp); 292 try_return(RC); 293 } 294 295 // Now, we can obtain the parameters specified by the user. 296 // Note that the file object is the new object created by the 297 // I/O Manager in anticipation that this create/open request 298 // will succeed. 299 PtrNewFileObject = IrpSp->FileObject; 300 TargetObjectName = PtrNewFileObject->FileName; 301 PtrRelatedFileObject = PtrNewFileObject->RelatedFileObject; 302 303 // If a related file object is present, get the pointers 304 // to the CCB and the FCB for the related file object 305 if (PtrRelatedFileObject) { 306 PtrRelatedCCB = (PtrUDFCCB)(PtrRelatedFileObject->FsContext2); 307 ASSERT(PtrRelatedCCB); 308 ASSERT(PtrRelatedCCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_CCB); 309 // each CCB in turn points to a FCB 310 PtrRelatedFCB = PtrRelatedCCB->Fcb; 311 ASSERT(PtrRelatedFCB); 312 ASSERT((PtrRelatedFCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB) 313 ||(PtrRelatedFCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB)); 314 RelatedObjectName = PtrRelatedFileObject->FileName; 315 if (!(RelatedObjectName.Length) || (RelatedObjectName.Buffer[0] != L'\\')) { 316 if(PtrRelatedFCB->FCBName) 317 RelatedObjectName = PtrRelatedFCB->FCBName->ObjectName; 318 } 319 } 320 321 // Allocation size is only used if a new file is created 322 // or a file is superseded. 323 AllocationSize = Irp->Overlay.AllocationSize.QuadPart; 324 325 // Get a ptr to the supplied security context 326 PtrSecurityContext = IrpSp->Parameters.Create.SecurityContext; 327 AccessState = PtrSecurityContext->AccessState; 328 329 // The desired access can be obtained from the SecurityContext 330 DesiredAccess = PtrSecurityContext->DesiredAccess; 331 332 // Two values are supplied in the Create.Options field: 333 // (a) the actual user supplied options 334 // (b) the create disposition 335 RequestedOptions = (IrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS); 336 337 // The file disposition is packed with the user options ... 338 // Disposition includes FILE_SUPERSEDE, FILE_OPEN_IF, etc. 339 RequestedDisposition = (IrpSp->Parameters.Create.Options >> 24);// & 0xFF; 340 341 //#ifdef UDF_LOG_CREATE_DISPOSITION 342 switch(RequestedDisposition) { 343 case FILE_SUPERSEDE: 344 AdPrint((" Dispos: FILE_SUPERSEDE\n")); 345 break; 346 case FILE_OPEN: 347 AdPrint((" Dispos: FILE_OPEN\n")); 348 break; 349 case FILE_CREATE: 350 AdPrint((" Dispos: FILE_CREATE\n")); 351 break; 352 case FILE_OPEN_IF: 353 AdPrint((" Dispos: FILE_OPEN_IF\n")); 354 break; 355 case FILE_OVERWRITE: 356 AdPrint((" Dispos: FILE_OVERWRITE\n")); 357 break; 358 case FILE_OVERWRITE_IF: 359 AdPrint((" Dispos: FILE_OVERWRITE_IF\n")); 360 break; 361 default: 362 AdPrint((" Dispos: *** Unknown ***\n")); 363 break; 364 } 365 //#endif // UDF_LOG_CREATE_DISPOSITION 366 367 FileAttributes = (USHORT)(IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS); 368 ShareAccess = IrpSp->Parameters.Create.ShareAccess; 369 370 // If the FSD does not support EA manipulation, we might return 371 // invalid parameter if the following are supplied. 372 // EA arguments are only used if a new file is created or a file is 373 // superseded 374 375 // But some applications _require_ EA support 376 // (Notepad... rather strange, isn't it ?) 377 378 // So, for such stupid ones 379 // !!! We shall ignore these parameters !!! 380 381 // PtrExtAttrBuffer = (struct _FILE_FULL_EA_INFORMATION *) Irp->AssociatedIrp.SystemBuffer; 382 // ExtAttrLength = IrpSp->Parameters.Create.EaLength; 383 384 // Get the options supplied by the user 385 386 #define OpenForBackup (RequestedOptions & FILE_OPEN_FOR_BACKUP_INTENT) 387 // User specifies that returned object MUST be a directory. 388 // Lack of presence of this flag does not mean it *cannot* be a 389 // directory *unless* FileOnlyRequested is set (see below) 390 391 // Presence of the flag however, does require that the returned object be 392 // a directory (container) object. 393 #define DirectoryOnlyRequested (RequestedOptions & FILE_DIRECTORY_FILE) 394 395 // User specifies that returned object MUST NOT be a directory. 396 // Lack of presence of this flag does not mean it *cannot* be a 397 // file *unless* DirectoryOnlyRequested is set (see above). 398 399 // Presence of the flag however does require that the returned object be 400 // a simple file (non-container) object. 401 #define FileOnlyRequested (RequestedOptions & FILE_NON_DIRECTORY_FILE) 402 403 // We cannot cache the file if the following flag is set. 404 // However, things do get a little bit interesting if caching 405 // has been already initiated due to a previous open ... 406 // (maintaining consistency then becomes a little bit more 407 // of a headache - see read/write file descriptions) 408 #define NoBufferingSpecified (RequestedOptions & FILE_NO_INTERMEDIATE_BUFFERING) 409 410 // Write-through simply means that the FSD must *not* return from 411 // a user write request until the data has been flushed to secondary 412 // storage (either to disks directly connected to the node or across 413 // the network in the case of a redirector) 414 WriteThroughRequested = (RequestedOptions & FILE_WRITE_THROUGH) ? TRUE : FALSE; 415 416 #define SequentialIoRequested (RequestedOptions & FILE_SEQUENTIAL_ONLY ? TRUE : FALSE) 417 418 // Not all of the native file system implementations support 419 // the delete-on-close option. All this means is that after the 420 // last close on the FCB has been performed, the FSD should 421 // delete the file. It simply saves the caller from issuing a 422 // separate delete request. Also, some FSD implementations might choose 423 // to implement a Windows NT idiosyncratic behavior wherein we 424 // could create such "delete-on-close" marked files under directories 425 // marked for deletion. Ordinarily, a FSD will not allow us to create 426 // a new file under a directory that has been marked for deletion. 427 DeleteOnCloseSpecified = (IrpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE) ? TRUE : FALSE; 428 429 if(DeleteOnCloseSpecified) { 430 AdPrint((" DeleteOnClose\n")); 431 } 432 433 #define NoExtAttrKnowledge /*(RequestedOptions & FILE_NO_EA_KNOWLEDGE) ?*/ TRUE /*: FALSE*/ 434 435 // The following flag is only used by the LAN Manager redirector 436 // to initiate a "new mapping" to a remote share. Typically, 437 // a FSD will not see this flag (especially disk based FSD's) 438 // CreateTreeConnection = (RequestedOptions & FILE_CREATE_TREE_CONNECTION) ? TRUE : FALSE; 439 440 // The NTFS file system for exmaple supports the OpenByFileId option. 441 // The FSD may also be able to associate a unique numerical ID with 442 // an on-disk object. The caller would get this ID in a "query file 443 // information" call. 444 445 // Later, the caller might decide to reopen the object, this time 446 // though it may supply the FSD with the file identifier instead of 447 // a file/path name. 448 #define OpenByFileId (RequestedOptions & FILE_OPEN_BY_FILE_ID) 449 450 // Are we dealing with a page file? 451 PageFileManipulation = (IrpSp->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE; 452 453 // The open target directory flag is used as part of the sequence of 454 // operations performed by the I/O Manager is response to a file/dir 455 // rename operation. See the explanation in the book for details. 456 OpenTargetDirectory = (IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE; 457 458 // If the FSD supports case-sensitive file name checks, we may 459 // choose to honor the following flag ... 460 IgnoreCase = (IrpSp->Flags & SL_CASE_SENSITIVE) ? FALSE : TRUE; 461 462 // Ensure that the operation has been directed to a valid VCB ... 463 Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension); 464 ASSERT(Vcb); 465 ASSERT(Vcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB); 466 // Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK; 467 468 WriteThroughRequested = WriteThroughRequested || 469 (Vcb->CompatFlags & UDF_VCB_IC_FORCE_WRITE_THROUGH); 470 471 // Do some preliminary checks to make sure the operation is supported. 472 // We fail in the following cases immediately. 473 // - Open a paging file. 474 // - Open a file with Eas. 475 if(PageFileManipulation) { 476 ReturnedInformation = 0; 477 AdPrint(("Can't create a page file\n")); 478 try_return(RC = STATUS_ACCESS_DENIED); 479 } 480 if(ExtAttrLength) { 481 ReturnedInformation = 0; 482 AdPrint(("Can't create file with EAs\n")); 483 try_return(RC = STATUS_EAS_NOT_SUPPORTED); 484 } 485 486 UDFFlushTryBreak(Vcb); 487 488 if (Vcb->SoftEjectReq) { 489 AdPrint((" Eject requested\n")); 490 try_return(RC = STATUS_FILE_INVALID); 491 } 492 493 // If the volume has been locked, fail the request 494 if ((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) && 495 (Vcb->VolumeLockPID != GetCurrentPID())) { 496 AdPrint((" Volume is locked\n")); 497 RC = STATUS_ACCESS_DENIED; 498 try_return(RC); 499 } 500 // We need EXCLUSIVE access to Vcb to avoid parallel calls to UDFVerifyVcb() 501 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); 502 AcquiredVcb = TRUE; 503 504 // Disk based file systems might decide to verify the logical volume 505 // (if required and only if removable media are supported) at this time 506 RC = UDFVerifyVcb(PtrIrpContext,Vcb); 507 if(!NT_SUCCESS(RC)) 508 try_return(RC); 509 510 UDFConvertExclusiveToSharedLite(&(Vcb->VCBResource)); 511 512 ASSERT(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED); 513 514 // We fail in the following cases for Read-Only volumes 515 // - Open a target directory. 516 // - Create a file. 517 if( 518 ( 519 ((Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) && 520 (Vcb->CompatFlags & UDF_VCB_IC_DIRTY_RO)) 521 #ifndef UDF_READ_ONLY_BUILD 522 || (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) 523 #endif //UDF_READ_ONLY_BUILD 524 ) && 525 (DeleteOnCloseSpecified || 526 OpenTargetDirectory || 527 (RequestedDisposition == FILE_CREATE) || 528 (RequestedDisposition == FILE_OVERWRITE) || 529 (RequestedDisposition == FILE_OVERWRITE_IF) || 530 (RequestedDisposition == FILE_SUPERSEDE) || 531 AllocationSize) ) { 532 ReturnedInformation = 0; 533 AdPrint((" Write protected or dirty\n")); 534 try_return(RC = STATUS_MEDIA_WRITE_PROTECTED); 535 } 536 537 /* if(DesiredAccess & (FILE_READ_EA | FILE_WRITE_EA)) { 538 ReturnedInformation = 0; 539 AdPrint((" EAs not supported\n")); 540 try_return(RC = STATUS_ACCESS_DENIED); 541 }*/ 542 543 // **************** 544 // If a Volume open is requested, satisfy it now 545 // **************** 546 if (!(PtrNewFileObject->FileName.Length) && (!PtrRelatedFileObject || 547 (PtrRelatedFCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB))) { 548 549 BOOLEAN UndoLock = FALSE; 550 551 AdPrint((" Opening Volume\n")); 552 // If the supplied file name is NULL *and* either there exists 553 // no related file object *or* if a related file object was supplied 554 // but it too refers to a previously opened instance of a logical 555 // volume, this open must be for a logical volume. 556 557 // Note: the FSD might decide to do "special" things (whatever they 558 // might be) in response to an open request for the logical volume. 559 560 // Logical volume open requests are done primarily to get/set volume 561 // information, lock the volume, dismount the volume (using the IOCTL 562 // FSCTL_DISMOUNT_VOLUME) etc. 563 564 // If a volume open is requested, perform checks to ensure that 565 // invalid options have not also been specified ... 566 if ((OpenTargetDirectory) || (PtrExtAttrBuffer)) { 567 try_return(RC = STATUS_INVALID_PARAMETER); 568 } 569 570 if (DirectoryOnlyRequested) { 571 // a volume is not a directory 572 try_return(RC = STATUS_NOT_A_DIRECTORY); 573 } 574 575 #ifndef UDF_READ_ONLY_BUILD 576 if (DeleteOnCloseSpecified) { 577 // delete volume.... hmm 578 try_return(RC = STATUS_CANNOT_DELETE); 579 } 580 581 if ((RequestedDisposition != FILE_OPEN) && (RequestedDisposition != FILE_OPEN_IF)) { 582 // cannot create a new volume, I'm afraid ... 583 try_return(RC = STATUS_ACCESS_DENIED); 584 } 585 #endif //UDF_READ_ONLY_BUILD 586 587 UDFPrint((" ShareAccess %x, DesiredAccess %x\n", ShareAccess, DesiredAccess)); 588 /* 589 if(!(ShareAccess & (FILE_SHARE_WRITE | FILE_SHARE_DELETE)) && 590 !(DesiredAccess & (FILE_GENERIC_WRITE & ~SYNCHRONIZE)) && 591 (ShareAccess & FILE_SHARE_READ) ) { 592 */ 593 if(!(DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) && 594 (ShareAccess & FILE_SHARE_READ) ) { 595 UDFPrint((" R/O volume open\n")); 596 } else { 597 598 UDFPrint((" R/W volume open\n")); 599 if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) { 600 UDFPrint((" media-ro\n")); 601 try_return(RC = STATUS_MEDIA_WRITE_PROTECTED); 602 } 603 } 604 605 if(!(ShareAccess & (FILE_SHARE_WRITE | FILE_SHARE_DELETE)) && 606 !(DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) && 607 (ShareAccess & FILE_SHARE_READ) ) { 608 // do nothing 609 } else { 610 611 if(!(ShareAccess & FILE_SHARE_READ) || 612 (DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) ) { 613 // As soon as OpenVolume flushes the volume 614 // we should complete all pending requests (Close) 615 616 UDFPrint((" set UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n")); 617 PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FLUSH2_REQUIRED; 618 619 /* 620 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 621 UDFReleaseResource(&(Vcb->VCBResource)); 622 AcquiredVcb = FALSE; 623 624 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) { 625 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo); 626 } 627 #ifdef UDF_DELAYED_CLOSE 628 UDFCloseAllDelayed(Vcb); 629 #endif //UDF_DELAYED_CLOSE 630 631 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); 632 AcquiredVcb = TRUE; 633 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 634 */ 635 } 636 } 637 638 // If the user does not want to share write or delete then we will try 639 // and take out a lock on the volume. 640 if(!(ShareAccess & (FILE_SHARE_WRITE | FILE_SHARE_DELETE))) { 641 // Do a quick check here for handles on exclusive open. 642 if ((Vcb->VCBHandleCount) && 643 !(ShareAccess & FILE_SHARE_READ)) { 644 // Sharing violation 645 UDFPrint((" !FILE_SHARE_READ + open handles (%d)\n", Vcb->VCBHandleCount)); 646 try_return(RC = STATUS_SHARING_VIOLATION); 647 } 648 if(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) { 649 650 UDFPrint((" perform flush\n")); 651 PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED; 652 653 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 654 UDFReleaseResource(&(Vcb->VCBResource)); 655 AcquiredVcb = FALSE; 656 657 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) { 658 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo); 659 } 660 #ifdef UDF_DELAYED_CLOSE 661 UDFCloseAllDelayed(Vcb); 662 #endif //UDF_DELAYED_CLOSE 663 664 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); 665 AcquiredVcb = TRUE; 666 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 667 668 UDFFlushLogicalVolume(NULL, NULL, Vcb); 669 670 if((ShareAccess & FILE_SHARE_READ) && 671 ((Vcb->VCBOpenCount - UDF_RESIDUAL_REFERENCE) != (Vcb->VCBOpenCountRO))) { 672 UDFPrint((" FILE_SHARE_READ + R/W handles: %d(%d) -> STATUS_SHARING_VIOLATION ?\n", 673 Vcb->VCBOpenCount - UDF_RESIDUAL_REFERENCE, 674 Vcb->VCBOpenCountRO)); 675 /* we shall not check it here, let System do it in IoCheckShareAccess() */ 676 //try_return(RC = STATUS_SHARING_VIOLATION); 677 } 678 } 679 // Lock the volume 680 if(!(ShareAccess & FILE_SHARE_READ)) { 681 UDFPrint((" set Lock\n")); 682 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_LOCKED; 683 Vcb->VolumeLockFileObject = PtrNewFileObject; 684 UndoLock = TRUE; 685 } else 686 if(DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) { 687 UDFPrint((" set UDF_IRP_CONTEXT_FLUSH_REQUIRED\n")); 688 PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FLUSH_REQUIRED; 689 } 690 } 691 692 PtrNewFcb = (PtrUDFFCB)Vcb; 693 ASSERT(!(PtrNewFcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE)); 694 695 RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb); 696 if (!NT_SUCCESS(RC)) 697 goto op_vol_accs_dnd; 698 699 PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2); 700 if(PtrNewCcb) PtrNewCcb->CCBFlags |= UDF_CCB_VOLUME_OPEN; 701 // Check _Security_ 702 RC = UDFCheckAccessRights(NULL, AccessState, Vcb->RootDirFCB, PtrNewCcb, DesiredAccess, ShareAccess); 703 if (!NT_SUCCESS(RC)) { 704 AdPrint((" Access violation (Volume)\n")); 705 goto op_vol_accs_dnd; 706 } 707 // Check _ShareAccess_ 708 RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); 709 if(!NT_SUCCESS(RC)) { 710 AdPrint((" Sharing violation (Volume)\n")); 711 op_vol_accs_dnd: 712 if(UndoLock) { 713 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED; 714 Vcb->VolumeLockFileObject = NULL; 715 } 716 try_return(RC); 717 } 718 719 // NoBufferingSpecified = TRUE; See #define above 720 RequestedOptions |= FILE_NO_INTERMEDIATE_BUFFERING; 721 722 ReturnedInformation = FILE_OPENED; 723 UDFNotifyVolumeEvent(PtrNewFileObject, FSRTL_VOLUME_LOCK); 724 try_return(RC); 725 } 726 727 if((Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) && 728 (!(Vcb->CompatFlags & UDF_VCB_IC_SHOW_BLANK_CD) || UDFGlobalData.AutoFormatCount)) { 729 ReturnedInformation = 0; 730 AdPrint((" Can't open anything on blank volume ;)\n")); 731 try_return(RC = STATUS_OBJECT_NAME_NOT_FOUND); 732 } 733 734 if(UdfIllegalFcbAccess(Vcb,DesiredAccess)) { 735 ReturnedInformation = 0; 736 AdPrint((" Illegal share access\n")); 737 try_return(RC = STATUS_ACCESS_DENIED); 738 } 739 // we could mount blank R/RW media in order to allow 740 // user-mode applications to get access with Write privileges 741 ASSERT(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED); 742 743 // we should check appropriate privilege if OpenForBackup requested 744 if(OpenForBackup) { 745 if (!SeSinglePrivilegeCheck(SeExports->SeBackupPrivilege, UserMode)) { 746 try_return(RC = STATUS_PRIVILEGE_NOT_HELD); 747 } 748 } 749 750 // The FSD might wish to implement the open-by-id option. The "id" 751 // is some unique numerical representation of the on-disk object. 752 // The caller then therefore give us this file id and the FSD 753 // should be completely capable of "opening" the object (it must 754 // exist since the caller received an id for the object from the 755 // FSD in a "query file" call ... 756 757 // If the file has been deleted in the meantime, we'll return 758 // "not found" 759 760 // **************** 761 // Open by FileID 762 // **************** 763 if (OpenByFileId) { 764 // perform the open ... 765 PUNICODE_STRING TmpPath; 766 LONGLONG Id; 767 768 UDFPrint((" open by File ID\n")); 769 if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) { 770 ReturnedInformation = 0; 771 AdPrint((" Can't open by FileID on blank volume ;)\n")); 772 try_return(RC = STATUS_OBJECT_NAME_NOT_FOUND); 773 } 774 775 if (TargetObjectName.Length != sizeof(FILE_ID)) { 776 AdPrint((" Invalid file ID\n")); 777 try_return(RC = STATUS_INVALID_PARAMETER); 778 } 779 Id = *((FILE_ID*)(TargetObjectName.Buffer)); 780 AdPrint((" Opening by ID %8.8x%8.8x\n", (ULONG)(Id>>32), (ULONG)Id)); 781 if ((RequestedDisposition != FILE_OPEN) && 782 (RequestedDisposition != FILE_OPEN_IF)) { 783 AdPrint((" Illegal disposition for ID open\n")); 784 try_return(RC = STATUS_ACCESS_DENIED); 785 } 786 787 RC = UDFGetOpenParamsByFileId(Vcb, Id, &TmpPath, &IgnoreCase); 788 if(!NT_SUCCESS(RC)) { 789 AdPrint((" ID open failed\n")); 790 try_return(RC); 791 } 792 // simulate absolute path open 793 /* if(!NT_SUCCESS(RC = MyInitUnicodeString(&TargetObjectName, L"")) || 794 !NT_SUCCESS(RC = MyAppendUnicodeStringToStringTag(&TargetObjectName, TmpPath, MEM_USABS_TAG))) {*/ 795 if(!NT_SUCCESS(RC = MyCloneUnicodeString(&TargetObjectName, TmpPath))) { 796 AdPrint((" Init String failed\n")); 797 try_return(RC); 798 } 799 //ASSERT(TargetObjectName.Buffer); 800 AbsolutePathName = TargetObjectName; 801 PtrRelatedFileObject = NULL; 802 } else 803 // **************** 804 // Relative open 805 // **************** 806 // Now determine the starting point from which to begin the parsing 807 if (PtrRelatedFileObject) { 808 // We have a user supplied related file object. 809 // This implies a "relative" open i.e. relative to the directory 810 // represented by the related file object ... 811 812 UDFPrint((" PtrRelatedFileObject %x, FCB %x\n", PtrRelatedFileObject, PtrRelatedFCB)); 813 // Note: The only purpose FSD implementations ever have for 814 // the related file object is to determine whether this 815 // is a relative open or not. At all other times (including 816 // during I/O operations), this field is meaningless from 817 // the FSD's perspective. 818 if (!(PtrRelatedFCB->FCBFlags & UDF_FCB_DIRECTORY)) { 819 // we must have a directory as the "related" object 820 RC = STATUS_INVALID_PARAMETER; 821 AdPrint((" Related object must be a directory\n")); 822 AdPrint((" Flags %x\n", PtrRelatedFCB->FCBFlags)); 823 _SEH2_TRY { 824 AdPrint((" ObjName %x, ", PtrRelatedFCB->FCBName->ObjectName)); 825 AdPrint((" Name %S\n", PtrRelatedFCB->FCBName->ObjectName.Buffer)); 826 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 827 AdPrint((" exception when printing name\n")); 828 } _SEH2_END; 829 try_return(RC); 830 } 831 832 // So we have a directory, ensure that the name begins with 833 // a "\" i.e. begins at the root and does *not* begin with a "\\" 834 // NOTE: This is just an example of the kind of path-name string 835 // validation that a FSD must do. Although the remainder of 836 // the code may not include such checks, any commercial 837 // FSD *must* include such checking (no one else, including 838 // the I/O Manager will perform checks on the FSD's behalf) 839 if (!(RelatedObjectName.Length) || (RelatedObjectName.Buffer[0] != L'\\')) { 840 AdPrint((" Wrong pathname (1)\n")); 841 RC = STATUS_INVALID_PARAMETER; 842 try_return(RC); 843 } 844 // similarly, if the target file name starts with a "\", it 845 // is wrong since the target file name can no longer be absolute 846 ASSERT(TargetObjectName.Buffer || !TargetObjectName.Length); 847 if (TargetObjectName.Length && (TargetObjectName.Buffer[0] == L'\\')) { 848 AdPrint((" Wrong pathname (2)\n")); 849 RC = STATUS_INVALID_PARAMETER; 850 try_return(RC); 851 } 852 // Create an absolute path-name. We could potentially use 853 // the absolute path-name if we cache previously opened 854 // file/directory object names. 855 /* if(!NT_SUCCESS(RC = MyInitUnicodeString(&AbsolutePathName, L"")) || 856 !NT_SUCCESS(RC MyAppendUnicodeStringToStringTag(&AbsolutePathName, &RelatedObjectName, MEM_USABS_TAG)))*/ 857 if(!NT_SUCCESS(RC = MyCloneUnicodeString(&AbsolutePathName, &RelatedObjectName))) 858 try_return(RC); 859 if(RelatedObjectName.Length && 860 (RelatedObjectName.Buffer[ (RelatedObjectName.Length/sizeof(WCHAR)) - 1 ] != L'\\')) { 861 RC = MyAppendUnicodeToString(&AbsolutePathName, L"\\"); 862 if(!NT_SUCCESS(RC)) try_return(RC); 863 } 864 if(!AbsolutePathName.Length || 865 (AbsolutePathName.Buffer[ (AbsolutePathName.Length/sizeof(WCHAR)) - 1 ] != L'\\')) { 866 ASSERT(TargetObjectName.Buffer); 867 if(TargetObjectName.Length && TargetObjectName.Buffer[0] != L'\\') { 868 RC = MyAppendUnicodeToString(&AbsolutePathName, L"\\"); 869 if(!NT_SUCCESS(RC)) try_return(RC); 870 } 871 } 872 //ASSERT(TargetObjectName.Buffer); 873 RC = MyAppendUnicodeStringToStringTag(&AbsolutePathName, &TargetObjectName, MEM_USABS_TAG); 874 if(!NT_SUCCESS(RC)) 875 try_return(RC); 876 877 } else { 878 // **************** 879 // Absolute open 880 // **************** 881 // The suplied path-name must be an absolute path-name i.e. 882 // starting at the root of the file system tree 883 UDFPrint((" Absolute open\n")); 884 ASSERT(TargetObjectName.Buffer); 885 if (!TargetObjectName.Length || TargetObjectName.Buffer[0] != L'\\') { 886 AdPrint((" Wrong target name (1)\n")); 887 try_return(RC = STATUS_INVALID_PARAMETER); 888 } 889 /* if(!NT_SUCCESS(RC = MyInitUnicodeString(&AbsolutePathName, L"")) || 890 !NT_SUCCESS(RC = MyAppendUnicodeStringToStringTag(&AbsolutePathName, &TargetObjectName, MEM_USABS_TAG)))*/ 891 ASSERT(TargetObjectName.Buffer); 892 if(!NT_SUCCESS(RC = MyCloneUnicodeString(&AbsolutePathName, &TargetObjectName))) 893 try_return(RC); 894 } 895 // Win 32 protection :) 896 if ((AbsolutePathName.Length >= sizeof(WCHAR)*2) && 897 (AbsolutePathName.Buffer[1] == L'\\') && 898 (AbsolutePathName.Buffer[0] == L'\\')) { 899 900 // If there are still two beginning backslashes, the name is bogus. 901 if ((AbsolutePathName.Length > 2*sizeof(WCHAR)) && 902 (AbsolutePathName.Buffer[2] == L'\\')) { 903 AdPrint((" Wrong target name (2)\n")); 904 try_return (RC = STATUS_OBJECT_NAME_INVALID); 905 } 906 // Slide the name down in the buffer. 907 RtlMoveMemory( AbsolutePathName.Buffer, 908 AbsolutePathName.Buffer + 1, 909 AbsolutePathName.Length ); // .Length includes 910 // NULL-terminator 911 AbsolutePathName.Length -= sizeof(WCHAR); 912 } 913 if ( (AbsolutePathName.Length > sizeof(WCHAR) ) && 914 (AbsolutePathName.Buffer[ (AbsolutePathName.Length/sizeof(WCHAR)) - 1 ] == L'\\') ) { 915 916 AbsolutePathName.Length -= sizeof(WCHAR); 917 } 918 // TERMINATOR (2) ;) 919 AbsolutePathName.Buffer[AbsolutePathName.Length/sizeof(WCHAR)] = 0; 920 921 // Sometimes W2000 decides to duplicate handle of 922 // already opened File/Dir. In this case it sends us 923 // RelatedFileObject & specifies zero-filled RelativePath 924 if(!TargetObjectName.Length) { 925 TargetObjectName = AbsolutePathName; 926 OpenExisting = TRUE; 927 } 928 //ASSERT(TargetObjectName.Buffer); 929 930 // **************** 931 // First, check if the caller simply wishes to open the Root 932 // of the file system tree. 933 // **************** 934 if (AbsolutePathName.Length == sizeof(WCHAR)) { 935 AdPrint((" Opening RootDir\n")); 936 // this is an open of the root directory, ensure that the caller 937 // has not requested a file only 938 if (FileOnlyRequested || (RequestedDisposition == FILE_SUPERSEDE) || 939 (RequestedDisposition == FILE_OVERWRITE) || 940 (RequestedDisposition == FILE_OVERWRITE_IF)) { 941 AdPrint((" Can't overwrite RootDir\n")); 942 RC = STATUS_FILE_IS_A_DIRECTORY; 943 try_return(RC); 944 } 945 946 #if 0 947 CollectStatistics(Vcb, MetaDataReads); 948 #endif 949 950 if (DeleteOnCloseSpecified) { 951 // delete RootDir.... rather strange idea... I dislike it 952 AdPrint((" Can't delete RootDir\n")); 953 try_return(RC = STATUS_CANNOT_DELETE); 954 } 955 956 PtrNewFcb = Vcb->RootDirFCB; 957 RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb); 958 if(!NT_SUCCESS(RC)) try_return(RC); 959 // DbgPrint("UDF: Open/Create RootDir : ReferenceCount %x\n",PtrNewFcb->ReferenceCount); 960 UDFReferenceFile__(PtrNewFcb->FileInfo); 961 PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2); 962 TreeLength = 1; 963 964 RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); 965 if(!NT_SUCCESS(RC)) { 966 AdPrint((" Access/Sharing violation (RootDir)\n")); 967 try_return(RC); 968 } 969 970 ReturnedInformation = FILE_OPENED; 971 972 try_return(RC); 973 } // end of OpenRootDir 974 975 _SEH2_TRY { 976 AdPrint((" Opening file %ws %8.8x\n",AbsolutePathName.Buffer, PtrNewFileObject)); 977 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 978 AdPrint((" Exception when printing FN\n")); 979 } _SEH2_END; 980 // **************** 981 // Check if we have DuplicateHandle (or Reopen) request 982 // **************** 983 if(OpenExisting) { 984 985 // BrutePoint(); 986 // We don't handle OpenTargetDirectory in this case 987 if(OpenTargetDirectory) 988 try_return(RC = STATUS_INVALID_PARAMETER); 989 990 // Init environment to simulate normal open procedure behavior 991 /* if(!NT_SUCCESS(RC = MyInitUnicodeString(&LocalPath, L"")) || 992 !NT_SUCCESS(RC = MyAppendUnicodeStringToStringTag(&LocalPath, &TargetObjectName, MEM_USLOC_TAG)))*/ 993 ASSERT(TargetObjectName.Buffer); 994 if(!NT_SUCCESS(RC = MyCloneUnicodeString(&LocalPath, &TargetObjectName))) 995 try_return(RC); 996 997 ASSERT(PtrRelatedFCB); 998 RelatedFileInfo = PtrRelatedFCB->FileInfo; 999 1000 RC = STATUS_SUCCESS; 1001 NewFileInfo = 1002 LastGoodFileInfo = RelatedFileInfo; 1003 1004 RelatedFileInfo = 1005 OldRelatedFileInfo = RelatedFileInfo->ParentFile; 1006 PtrRelatedFCB = PtrRelatedFCB->ParentFcb; 1007 // prevent releasing parent structures 1008 UDFAcquireParent(RelatedFileInfo, &Res1, &Res2); 1009 TreeLength++; 1010 1011 if(Res1) UDFReleaseResource(Res1); 1012 if(Res2) UDFReleaseResource(Res2); 1013 1014 UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB); 1015 UDFAcquireResourceExclusive(Res2 = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE); 1016 PtrNewFcb = NewFileInfo->Fcb; 1017 1018 UDF_CHECK_PAGING_IO_RESOURCE(PtrNewFcb->NTRequiredFCB); 1019 UDFAcquireResourceExclusive(Res1 = &(PtrNewFcb->NTRequiredFCB->MainResource),TRUE); 1020 UDFReferenceFile__(NewFileInfo); 1021 TreeLength++; 1022 1023 goto AlreadyOpened; 1024 } 1025 1026 if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) { 1027 ReturnedInformation = 0; 1028 AdPrint((" Can't open File on blank volume ;)\n")); 1029 try_return(RC = STATUS_OBJECT_NAME_NOT_FOUND); 1030 } 1031 1032 //AdPrint((" Opening file %ws %8.8x\n",AbsolutePathName.Buffer, PtrNewFileObject)); 1033 1034 if(AbsolutePathName.Length > UDF_X_PATH_LEN*sizeof(WCHAR)) { 1035 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1036 } 1037 1038 // validate path specified 1039 // (sometimes we can see here very strange characters ;) 1040 if(!UDFIsNameValid(&AbsolutePathName, &StreamOpen, &SNameIndex)) { 1041 AdPrint((" Absolute path is not valid\n")); 1042 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1043 } 1044 if(StreamOpen && !UDFStreamsSupported(Vcb)) { 1045 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1046 } 1047 1048 RC = MyInitUnicodeString(&LocalPath, L""); 1049 if(!NT_SUCCESS(RC)) 1050 try_return(RC); 1051 if (PtrRelatedFileObject) { 1052 // Our "start directory" is the one identified 1053 // by the related file object 1054 RelatedFileInfo = PtrRelatedFCB->FileInfo; 1055 if(RelatedFileInfo != Vcb->RootDirFCB->FileInfo) { 1056 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &(PtrRelatedFCB->FCBName->ObjectName), MEM_USLOC_TAG); 1057 if(!NT_SUCCESS(RC)) 1058 try_return(RC); 1059 } 1060 if(TargetObjectName.Buffer != AbsolutePathName.Buffer) { 1061 ASSERT(TargetObjectName.Buffer); 1062 if(!NT_SUCCESS(RC = MyCloneUnicodeString(&TailName, &TargetObjectName))) { 1063 AdPrint((" Init String 'TargetObjectName' failed\n")); 1064 try_return(RC); 1065 } 1066 TailNameBuffer = TailName.Buffer; 1067 } else { 1068 TailName = AbsolutePathName; 1069 } 1070 } else { 1071 // Start at the root of the file system 1072 RelatedFileInfo = Vcb->RootDirFCB->FileInfo; 1073 TailName = AbsolutePathName; 1074 } 1075 1076 if(StreamOpen) { 1077 StreamName = AbsolutePathName; 1078 StreamName.Buffer += SNameIndex; 1079 StreamName.Length -= (USHORT)SNameIndex*sizeof(WCHAR); 1080 // if StreamOpen specified & stream name starts with NULL character 1081 // we should create Stream Dir at first 1082 TailName.Length -= (AbsolutePathName.Length - (USHORT)SNameIndex*sizeof(WCHAR)); 1083 AbsolutePathName.Length = (USHORT)SNameIndex*sizeof(WCHAR); 1084 } 1085 CurName.MaximumLength = TailName.MaximumLength; 1086 1087 RC = STATUS_SUCCESS; 1088 LastGoodName.Length = 0; 1089 LastGoodFileInfo = RelatedFileInfo; 1090 // reference RelatedObject to prevent releasing parent structures 1091 UDFAcquireParent(RelatedFileInfo, &Res1, &Res2); 1092 TreeLength++; 1093 1094 // go into a loop parsing the supplied name 1095 1096 // Note that we may have to "open" intermediate directory objects 1097 // while traversing the path. We should __try to reuse existing code 1098 // whenever possible therefore we should consider using a common 1099 // open routine regardless of whether the open is on behalf of the 1100 // caller or an intermediate (internal) open performed by the driver. 1101 1102 // **************** 1103 // now we'll parse path to desired file 1104 // **************** 1105 1106 while (TRUE) { 1107 1108 // remember last 'good' ('good' means NO ERRORS before) path tail 1109 if(NT_SUCCESS(RC)) { 1110 LastGoodTail = TailName; 1111 while(LastGoodTail.Buffer[0] == L'\\') { 1112 LastGoodTail.Buffer++; 1113 LastGoodTail.Length -= sizeof(WCHAR); 1114 } 1115 } 1116 // get next path part... 1117 TmpBuffer = TailName.Buffer; 1118 TailName.Buffer = UDFDissectName(TailName.Buffer,&(CurName.Length) ); 1119 TailName.Length -= (USHORT)((ULONG_PTR)(TailName.Buffer) - (ULONG_PTR)TmpBuffer); 1120 CurName.Buffer = TailName.Buffer - CurName.Length; 1121 CurName.Length *= sizeof(WCHAR); 1122 CurName.MaximumLength = CurName.Length + sizeof(WCHAR); 1123 // check if we have already opened the component before last one 1124 // in this case OpenTargetDir request will be served in a special 1125 // way... 1126 if(OpenTargetDirectory && NT_SUCCESS(RC) && !TailName.Length) { 1127 // check if we should open SDir.. 1128 if(!StreamOpen || 1129 (TailName.Buffer[0]!=L':')) { 1130 // no, we should not. Continue with OpenTargetDir 1131 break; 1132 } 1133 } 1134 1135 if( CurName.Length && 1136 (NT_SUCCESS(RC) || !StreamOpen)) { 1137 // ...wow! non-zero! try to open! 1138 if(!NT_SUCCESS(RC)) { 1139 AdPrint((" Error opening path component\n")); 1140 // we haven't reached last name part... hm.. 1141 // probably, the path specified is invalid.. 1142 // or we had a hard error... What else can we do ? 1143 // Only say ..CK OFF !!!! 1144 if(RC == STATUS_OBJECT_NAME_NOT_FOUND) 1145 RC = STATUS_OBJECT_PATH_NOT_FOUND; 1146 ReturnedInformation = FILE_DOES_NOT_EXIST; 1147 try_return(RC); 1148 } 1149 1150 ASSERT_REF(RelatedFileInfo->Fcb->ReferenceCount >= RelatedFileInfo->RefCount); 1151 1152 if(RelatedFileInfo && (TreeLength>1)) { 1153 // it was an internal Open operation. Thus, assume 1154 // RelatedFileInfo's Fcb to be valid 1155 RelatedFileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; 1156 RelatedFileInfo->Fcb->FCBFlags |= UDF_FCB_VALID; 1157 } 1158 // check path fragment size 1159 if(CurName.Length > UDF_X_NAME_LEN * sizeof(WCHAR)) { 1160 AdPrint((" Path component is too long\n")); 1161 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1162 } 1163 // ...and now release previously acquired objects, 1164 if(Res1) UDFReleaseResource(Res1); 1165 if(Res2) { 1166 UDFReleaseResource(Res2); 1167 Res2 = NULL; 1168 } 1169 // acquire new _parent_ directory & try to open what 1170 // we want. 1171 1172 UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB); 1173 UDFAcquireResourceExclusive(Res1 = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE); 1174 1175 // check traverse rights 1176 RC = UDFCheckAccessRights(NULL, NULL, RelatedFileInfo->Fcb, PtrRelatedCCB, FILE_TRAVERSE, 0); 1177 if(!NT_SUCCESS(RC)) { 1178 NewFileInfo = NULL; 1179 AdPrint((" Traverse check failed\n")); 1180 goto Skip_open_attempt; 1181 } 1182 // check if we should open normal File/Dir or SDir 1183 if(CurName.Buffer[0] != ':') { 1184 // standard open, nothing interesting.... 1185 RC = UDFOpenFile__(Vcb, 1186 IgnoreCase,TRUE,&CurName, 1187 RelatedFileInfo,&NewFileInfo,NULL); 1188 if(RC == STATUS_FILE_DELETED) { 1189 // file has gone, but system still remembers it... 1190 NewFileInfo = NULL; 1191 AdPrint((" File deleted\n")); 1192 RC = STATUS_ACCESS_DENIED; 1193 #ifdef UDF_DBG 1194 } else 1195 if(RC == STATUS_NOT_A_DIRECTORY) { 1196 AdPrint((" Not a directory\n")); 1197 #endif // UDF_DBG 1198 } else 1199 if(RC == STATUS_SHARING_PAUSED) { 1200 AdPrint((" Dloc is being initialized\n")); 1201 BrutePoint(); 1202 RC = STATUS_SHARING_VIOLATION; 1203 } 1204 } else { 1205 // And here we should open Stream Dir (if any, of cource) 1206 RC = UDFOpenStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo); 1207 if(NT_SUCCESS(RC)) { 1208 SuccessOpen_SDir: 1209 // this indicates that we needn't Stream Dir creation 1210 StreamExists = TRUE; 1211 StreamName.Buffer++; 1212 StreamName.Length-=sizeof(WCHAR); 1213 // update TailName 1214 TailName = StreamName; 1215 } else 1216 if(RC == STATUS_NOT_FOUND) { 1217 #ifndef UDF_READ_ONLY_BUILD 1218 // Stream Dir doesn't exist, but caller wants it to be 1219 // created. Lets try to help him... 1220 if((RequestedDisposition == FILE_CREATE) || 1221 (RequestedDisposition == FILE_OPEN_IF) || 1222 (RequestedDisposition == FILE_OVERWRITE_IF) || 1223 OpenTargetDirectory ) { 1224 RC = UDFCreateStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo); 1225 if(NT_SUCCESS(RC)) 1226 goto SuccessOpen_SDir; 1227 } 1228 #endif //UDF_READ_ONLY_BUILD 1229 } 1230 /* } else { 1231 AdPrint((" File deleted (2)\n")); 1232 RC = STATUS_ACCESS_DENIED;*/ 1233 } 1234 #if 0 1235 CollectStatistics(Vcb, MetaDataReads); 1236 #endif 1237 1238 Skip_open_attempt: 1239 1240 // check if we have successfully opened path component 1241 if(NT_SUCCESS(RC)) { 1242 // Yesss !!! 1243 if (!(PtrNewFcb = NewFileInfo->Fcb)) { 1244 // It is a first open operation 1245 // Allocate new FCB 1246 // Here we set FileObject pointer to NULL to avoid 1247 // new CCB allocation 1248 RC = UDFFirstOpenFile(Vcb, 1249 NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo, 1250 &LocalPath, &CurName); 1251 1252 if(!NT_SUCCESS(RC)) { 1253 BrutePoint(); 1254 AdPrint((" Can't perform FirstOpen\n")); 1255 UDFCloseFile__(Vcb, NewFileInfo); 1256 if(PtrNewFcb) UDFCleanUpFCB(PtrNewFcb); 1257 PtrNewFcb = NULL; 1258 NewFileInfo->Fcb = NULL; 1259 if(UDFCleanUpFile__(Vcb, NewFileInfo)) { 1260 MyFreePool__(NewFileInfo); 1261 NewFileInfo = NULL; 1262 } 1263 try_return(RC); 1264 } 1265 } else { 1266 // It is not a first open operation 1267 // Validate Fcb. It is possible to get 1268 // not completly initialized Fcb here. 1269 if(!(PtrNewFcb->FCBFlags & UDF_FCB_VALID)) { 1270 BrutePoint(); 1271 AdPrint((" Fcb not valid\n")); 1272 UDFCloseFile__(Vcb, NewFileInfo); 1273 PtrNewFcb = NULL; 1274 if(UDFCleanUpFile__(Vcb, NewFileInfo)) { 1275 MyFreePool__(NewFileInfo); 1276 NewFileInfo = NULL; 1277 } 1278 try_return(RC = STATUS_ACCESS_DENIED); 1279 } 1280 } 1281 // Acquire newly opened File... 1282 Res2 = Res1; 1283 UDF_CHECK_PAGING_IO_RESOURCE(NewFileInfo->Fcb->NTRequiredFCB); 1284 UDFAcquireResourceExclusive(Res1 = &(NewFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE); 1285 // ...and reference it 1286 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount)); 1287 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 1288 1289 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount); 1290 // update unwind information 1291 LastGoodFileInfo = NewFileInfo; 1292 LastGoodName = CurName; 1293 TreeLength++; 1294 // update current path 1295 if(!StreamOpen || 1296 ((CurName.Buffer[0] != L':') && 1297 (!LocalPath.Length || (LocalPath.Buffer[LocalPath.Length/sizeof(WCHAR)-1] != L':'))) ) { 1298 // we should not insert '\' before or after ':' 1299 ASSERT(!LocalPath.Length || 1300 (LocalPath.Buffer[LocalPath.Length/2-1] != L'\\')); 1301 RC = MyAppendUnicodeToString(&LocalPath, L"\\"); 1302 if(!NT_SUCCESS(RC)) try_return(RC); 1303 } 1304 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &CurName, MEM_USLOC_TAG); 1305 if(!NT_SUCCESS(RC)) 1306 try_return(RC); 1307 // DbgPrint("UDF: Open/Create File %ws : ReferenceCount %x\n",CurName.Buffer,PtrNewFcb->ReferenceCount); 1308 } else { 1309 AdPrint((" Can't open file\n")); 1310 // We have failed durring last Open attempt 1311 // Roll back to last good state 1312 PtrUDFNTRequiredFCB NtReqFcb = NULL; 1313 // Cleanup FileInfo if any 1314 if(NewFileInfo) { 1315 PtrNewFcb = NewFileInfo->Fcb; 1316 // acquire appropriate resource if possible 1317 if(PtrNewFcb && 1318 PtrNewFcb->NTRequiredFCB) { 1319 NtReqFcb = PtrNewFcb->NTRequiredFCB; 1320 Res2 = Res1; 1321 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); 1322 UDFAcquireResourceExclusive(Res1 = &(NtReqFcb->MainResource),TRUE); 1323 } 1324 // cleanup pointer to Fcb in FileInfo to allow 1325 // UDF_INFO package release FileInfo if there are 1326 // no more references 1327 if(PtrNewFcb && 1328 !PtrNewFcb->ReferenceCount && 1329 !PtrNewFcb->OpenHandleCount) { 1330 NewFileInfo->Fcb = NULL; 1331 } 1332 // cleanup pointer to CommonFcb in Dloc to allow 1333 // UDF_INFO package release Dloc if there are 1334 // no more references 1335 if(NewFileInfo->Dloc && 1336 !NewFileInfo->Dloc->LinkRefCount && 1337 (!PtrNewFcb || !PtrNewFcb->ReferenceCount)) { 1338 NewFileInfo->Dloc->CommonFcb = NULL; 1339 } 1340 // try to release FileInfo 1341 if(UDFCleanUpFile__(Vcb, NewFileInfo)) { 1342 ASSERT(!PtrNewFcb); 1343 if(PtrNewFcb) { 1344 BrutePoint(); 1345 UDFCleanUpFCB(PtrNewFcb); 1346 } 1347 MyFreePool__(NewFileInfo); 1348 } else { 1349 // if we can't release FileInfo 1350 // restore pointers to Fcb & CommonFcb in 1351 // FileInfo & Dloc 1352 NewFileInfo->Fcb = PtrNewFcb; 1353 if(NtReqFcb) 1354 NewFileInfo->Dloc->CommonFcb = NtReqFcb; 1355 } 1356 // forget about last FileInfo & Fcb, 1357 // further unwind staff needs only last good 1358 // structures 1359 PtrNewFcb = NULL; 1360 NewFileInfo = NULL; 1361 } 1362 } 1363 1364 // should return error if 'delete in progress' 1365 if(LastGoodFileInfo->Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE | 1366 UDF_FCB_DELETED | 1367 UDF_FCB_POSTED_RENAME)) { 1368 AdPrint((" Return DeletePending (no err)\n")); 1369 try_return(RC = STATUS_DELETE_PENDING); 1370 } 1371 // update last good state information... 1372 OldRelatedFileInfo = RelatedFileInfo; 1373 RelatedFileInfo = NewFileInfo; 1374 // ...and go to the next open cycle 1375 } else { 1376 // ************ 1377 if(StreamOpen && (RC == STATUS_NOT_FOUND)) 1378 // handle SDir return code 1379 RC = STATUS_OBJECT_NAME_NOT_FOUND; 1380 if(RC == STATUS_OBJECT_NAME_NOT_FOUND) { 1381 // good path, but no such file.... Amen 1382 // break open loop and continue with Create 1383 break; 1384 } 1385 if (!NT_SUCCESS(RC)) { 1386 // Hard error or damaged data structures ... 1387 #ifdef UDF_DBG 1388 if((RC != STATUS_OBJECT_PATH_NOT_FOUND) && 1389 (RC != STATUS_ACCESS_DENIED) && 1390 (RC != STATUS_NOT_A_DIRECTORY)) { 1391 AdPrint((" Hard error or damaged data structures\n")); 1392 } 1393 #endif // UDF_DBG 1394 // ... and exit with error 1395 try_return(RC); 1396 } 1397 // discard changes for last successfully opened file 1398 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->ReferenceCount)); 1399 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 1400 RC = STATUS_SUCCESS; 1401 ASSERT(!OpenTargetDirectory); 1402 // break open loop and continue with Open 1403 // (Create will be skipped) 1404 break; 1405 } 1406 } // end of while(TRUE) 1407 1408 // **************** 1409 // If "open target directory" was specified 1410 // **************** 1411 if(OpenTargetDirectory) { 1412 1413 if(!UDFIsADirectory(LastGoodFileInfo)) { 1414 AdPrint((" Not a directory (2)\n")); 1415 RC = STATUS_NOT_A_DIRECTORY; 1416 } 1417 if(!NT_SUCCESS(RC) || 1418 TailName.Length) { 1419 AdPrint((" Target name should not contain (back)slashes\n")); 1420 NewFileInfo = NULL; 1421 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1422 } 1423 1424 NewFileInfo = LastGoodFileInfo; 1425 RtlCopyUnicodeString(&(PtrNewFileObject->FileName), &CurName); 1426 1427 // now we have to check if last component exists... 1428 if(NT_SUCCESS(RC = UDFFindFile__(Vcb, IgnoreCase, 1429 &CurName, RelatedFileInfo))) { 1430 // file exists, set this information in the Information field 1431 ReturnedInformation = FILE_EXISTS; 1432 AdPrint((" Open Target: FILE_EXISTS\n")); 1433 } else 1434 if(RC == STATUS_OBJECT_NAME_NOT_FOUND) { 1435 #ifdef UDF_DBG 1436 // check name. If there are '\\'s in TailName, some 1437 // directories in path specified do not exist 1438 for(TmpBuffer = LastGoodTail.Buffer; *TmpBuffer; TmpBuffer++) { 1439 if((*TmpBuffer) == L'\\') { 1440 ASSERT(FALSE); 1441 AdPrint((" Target name should not contain (back)slashes\n")); 1442 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1443 } 1444 } 1445 #endif // UDF_DBG 1446 // Tell the I/O Manager that file does not exit 1447 ReturnedInformation = FILE_DOES_NOT_EXIST; 1448 AdPrint((" Open Target: FILE_DOES_NOT_EXIST\n")); 1449 RC = STATUS_SUCCESS; // is already set here 1450 } else { 1451 AdPrint((" Open Target: unexpected error\n")); 1452 NewFileInfo = NULL; 1453 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1454 } 1455 1456 // RC = STATUS_SUCCESS; // is already set here 1457 1458 // Update the file object FsContext and FsContext2 fields 1459 // to reflect the fact that the parent directory of the 1460 // target has been opened 1461 PtrNewFcb = NewFileInfo->Fcb; 1462 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->ReferenceCount)); 1463 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 1464 RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb); 1465 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount); 1466 if (!NT_SUCCESS(RC)) { 1467 AdPrint((" Can't perform OpenFile operation for target\n")); 1468 try_return(RC); 1469 } 1470 PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2); 1471 1472 ASSERT(Res1); 1473 RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); 1474 if(!NT_SUCCESS(RC)) { 1475 AdPrint((" Access/Share access check failed (Open Target)\n")); 1476 } 1477 1478 try_return(RC); 1479 } 1480 1481 // **************** 1482 // should we CREATE a new file ? 1483 // **************** 1484 if (!NT_SUCCESS(RC)) { 1485 if (RC == STATUS_OBJECT_NAME_NOT_FOUND || 1486 RC == STATUS_OBJECT_PATH_NOT_FOUND) { 1487 if( ((RequestedDisposition == FILE_OPEN) || 1488 (RequestedDisposition == FILE_OVERWRITE)) /*&& 1489 (!StreamOpen || !StreamExists)*/ ){ 1490 ReturnedInformation = FILE_DOES_NOT_EXIST; 1491 AdPrint((" File doesn't exist\n")); 1492 try_return(RC); 1493 } 1494 } else { 1495 // Any other operation return STATUS_ACCESS_DENIED. 1496 AdPrint((" Can't create due to unexpected error\n")); 1497 try_return(RC); 1498 } 1499 // Object was not found, create if requested 1500 if ((RequestedDisposition != FILE_CREATE) && (RequestedDisposition != FILE_OPEN_IF) && 1501 (RequestedDisposition != FILE_OVERWRITE_IF) && (RequestedDisposition != FILE_SUPERSEDE)) { 1502 AdPrint((" File doesn't exist (2)\n")); 1503 try_return(RC); 1504 } 1505 // Check Volume ReadOnly attr 1506 #ifndef UDF_READ_ONLY_BUILD 1507 if((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY)) { 1508 #endif //UDF_READ_ONLY_BUILD 1509 ReturnedInformation = 0; 1510 AdPrint((" Write protected\n")); 1511 try_return(RC = STATUS_MEDIA_WRITE_PROTECTED); 1512 #ifndef UDF_READ_ONLY_BUILD 1513 } 1514 // Check r/o + delete on close 1515 if(DeleteOnCloseSpecified && 1516 (FileAttributes & FILE_ATTRIBUTE_READONLY)) { 1517 AdPrint((" Can't create r/o file marked for deletion\n")); 1518 try_return(RC = STATUS_CANNOT_DELETE); 1519 } 1520 1521 // Create a new file/directory here ... 1522 if(StreamOpen) 1523 StreamName.Buffer[StreamName.Length/sizeof(WCHAR)] = 0; 1524 for(TmpBuffer = LastGoodTail.Buffer; *TmpBuffer; TmpBuffer++) { 1525 if((*TmpBuffer) == L'\\') { 1526 AdPrint((" Target name should not contain (back)slashes\n")); 1527 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1528 } 1529 } 1530 if( DirectoryOnlyRequested && 1531 ((IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_TEMPORARY) || 1532 StreamOpen || FALSE)) { 1533 AdPrint((" Creation of _temporary_ directory not permited\n")); 1534 try_return(RC = STATUS_INVALID_PARAMETER); 1535 } 1536 // check access rights 1537 ASSERT(Res1); 1538 RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, PtrRelatedCCB, DirectoryOnlyRequested ? FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE, 0); 1539 if(!NT_SUCCESS(RC)) { 1540 AdPrint((" Creation of File/Dir not permitted\n")); 1541 try_return(RC); 1542 } 1543 // Note that a FCB structure will be allocated at this time 1544 // and so will a CCB structure. Assume that these are called 1545 // PtrNewFcb and PtrNewCcb respectively. 1546 // Further, note that since the file is being created, no other 1547 // thread can have the file stream open at this time. 1548 RelatedFileInfo = OldRelatedFileInfo; 1549 1550 RC = UDFCreateFile__(Vcb, IgnoreCase, &LastGoodTail, 0, 0, 1551 Vcb->UseExtendedFE || (StreamOpen && !StreamExists), 1552 (RequestedDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo); 1553 if(!NT_SUCCESS(RC)) { 1554 AdPrint((" Creation error\n")); 1555 Creation_Err_1: 1556 if(NewFileInfo) { 1557 PtrNewFcb = NewFileInfo->Fcb; 1558 ASSERT(!PtrNewFcb); 1559 if(PtrNewFcb && 1560 !PtrNewFcb->ReferenceCount && 1561 !PtrNewFcb->OpenHandleCount) { 1562 NewFileInfo->Fcb = NULL; 1563 } 1564 if(NewFileInfo->Dloc && 1565 !NewFileInfo->Dloc->LinkRefCount) { 1566 NewFileInfo->Dloc->CommonFcb = NULL; 1567 } 1568 if(UDFCleanUpFile__(Vcb, NewFileInfo)) { 1569 if(PtrNewFcb) { 1570 BrutePoint(); 1571 UDFCleanUpFCB(PtrNewFcb); 1572 } 1573 MyFreePool__(NewFileInfo); 1574 PtrNewFcb = PtrNewFcb; 1575 } else { 1576 NewFileInfo->Fcb = PtrNewFcb; 1577 } 1578 PtrNewFcb = NULL; 1579 } 1580 try_return(RC); 1581 } 1582 // Update parent object 1583 if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) && 1584 PtrRelatedFCB && 1585 PtrRelatedFileObject && 1586 (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) { 1587 PtrRelatedFileObject->Flags |= (FO_FILE_MODIFIED | FO_FILE_SIZE_CHANGED); 1588 } 1589 #if 0 1590 CollectStatistics(Vcb, MetaDataWrites); 1591 #endif 1592 1593 if(DirectoryOnlyRequested) { 1594 // user wants the directory to be created 1595 RC = UDFRecordDirectory__(Vcb, NewFileInfo); 1596 if(!NT_SUCCESS(RC)) { 1597 AdPrint((" Can't transform to directory\n")); 1598 Undo_Create_1: 1599 if((RC != STATUS_FILE_IS_A_DIRECTORY) && 1600 (RC != STATUS_NOT_A_DIRECTORY) && 1601 (RC != STATUS_ACCESS_DENIED)) { 1602 UDFFlushFile__(Vcb, NewFileInfo); 1603 UDFUnlinkFile__(Vcb, NewFileInfo, TRUE); 1604 } 1605 UDFCloseFile__(Vcb, NewFileInfo); 1606 BrutePoint(); 1607 goto Creation_Err_1; 1608 } 1609 #if 0 1610 CollectStatistics(Vcb, MetaDataWrites); 1611 #endif 1612 } else if(AllocationSize) { 1613 // set initial file size 1614 /* if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) { 1615 AdPrint((" Can't set initial file size\n")); 1616 goto Undo_Create_1; 1617 } 1618 CollectStatistics(Vcb, MetaDataWrites);*/ 1619 } 1620 1621 if(StreamOpen && !StreamExists) { 1622 1623 // PHASE 0 1624 1625 // Open the newly created object (file) 1626 if (!(PtrNewFcb = NewFileInfo->Fcb)) { 1627 // It is a first open operation 1628 // Allocate new FCB 1629 // Here we set FileObject pointer to NULL to avoid 1630 // new CCB allocation 1631 RC = UDFFirstOpenFile(Vcb, 1632 NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo, 1633 &LocalPath, &LastGoodTail); 1634 if(!NT_SUCCESS(RC)) { 1635 AdPrint((" Can't perform FirstOpenFile operation for file to contain stream\n")); 1636 BrutePoint(); 1637 UDFCleanUpFCB(NewFileInfo->Fcb); 1638 NewFileInfo->Fcb = NULL; 1639 goto Creation_Err_1; 1640 } 1641 } else { 1642 BrutePoint(); 1643 } 1644 1645 // Update unwind information 1646 TreeLength++; 1647 LastGoodFileInfo = NewFileInfo; 1648 // update FCB tree 1649 RC = MyAppendUnicodeToString(&LocalPath, L"\\"); 1650 if(!NT_SUCCESS(RC)) try_return(RC); 1651 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &LastGoodTail, MEM_USLOC_TAG); 1652 if(!NT_SUCCESS(RC)) 1653 goto Creation_Err_1; 1654 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount)); 1655 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 1656 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount); 1657 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; 1658 PtrNewFcb->FCBFlags |= UDF_FCB_VALID; 1659 1660 UDFNotifyFullReportChange( Vcb, NewFileInfo, 1661 UDFIsADirectory(NewFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, 1662 FILE_ACTION_ADDED); 1663 1664 // PHASE 1 1665 1666 // we need to create Stream Dir 1667 RelatedFileInfo = NewFileInfo; 1668 RC = UDFCreateStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo); 1669 if(!NT_SUCCESS(RC)) { 1670 AdPrint((" Can't create SDir\n")); 1671 BrutePoint(); 1672 goto Creation_Err_1; 1673 } 1674 #if 0 1675 CollectStatistics(Vcb, MetaDataWrites); 1676 #endif 1677 1678 // normalize stream name 1679 StreamName.Buffer++; 1680 StreamName.Length-=sizeof(WCHAR); 1681 // Open the newly created object 1682 if (!(PtrNewFcb = NewFileInfo->Fcb)) { 1683 // It is a first open operation 1684 // Allocate new FCB 1685 // Here we set FileObject pointer to NULL to avoid 1686 // new CCB allocation 1687 RC = UDFFirstOpenFile(Vcb, 1688 NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo, 1689 &LocalPath, &(UDFGlobalData.UnicodeStrSDir)); 1690 } else { 1691 BrutePoint(); 1692 } 1693 if(!NT_SUCCESS(RC)) { 1694 AdPrint((" Can't perform OpenFile operation for SDir\n")); 1695 BrutePoint(); 1696 goto Creation_Err_1; 1697 } 1698 1699 // Update unwind information 1700 TreeLength++; 1701 LastGoodFileInfo = NewFileInfo; 1702 // update FCB tree 1703 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &(UDFGlobalData.UnicodeStrSDir), MEM_USLOC_TAG); 1704 if(!NT_SUCCESS(RC)) { 1705 AdPrint((" Can't append UNC str\n")); 1706 BrutePoint(); 1707 goto Creation_Err_1; 1708 } 1709 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount)); 1710 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 1711 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount); 1712 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; 1713 PtrNewFcb->FCBFlags |= UDF_FCB_VALID; 1714 1715 // PHASE 2 1716 1717 // create stream 1718 RelatedFileInfo = NewFileInfo; 1719 RC = UDFCreateFile__(Vcb, IgnoreCase, &StreamName, 0, 0, 1720 Vcb->UseExtendedFE, (RequestedDisposition == FILE_CREATE), 1721 RelatedFileInfo, &NewFileInfo); 1722 if(!NT_SUCCESS(RC)) { 1723 AdPrint((" Can't create Stream\n")); 1724 BrutePoint(); 1725 goto Creation_Err_1; 1726 } 1727 #if 0 1728 CollectStatistics(Vcb, MetaDataWrites); 1729 #endif 1730 1731 // Update unwind information 1732 LastGoodTail = StreamName; 1733 } 1734 // NT wants ARCHIVE bit to be set on Files 1735 if(!DirectoryOnlyRequested) 1736 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; 1737 // Open the newly created object 1738 if (!(PtrNewFcb = NewFileInfo->Fcb)) { 1739 // It is a first open operation 1740 #ifndef IFS_40 1741 // Set attributes for the file ... 1742 UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo),NewFileInfo->Index), 1743 NewFileInfo->Dloc->FileEntry, FileAttributes); 1744 #endif //IFS_40 1745 // Allocate new FCB 1746 // Here we set FileObject pointer to NULL to avoid 1747 // new CCB allocation 1748 RC = UDFFirstOpenFile(Vcb, 1749 PtrNewFileObject, &PtrNewFcb, RelatedFileInfo, NewFileInfo, 1750 &LocalPath, &LastGoodTail); 1751 } else { 1752 BrutePoint(); 1753 } 1754 1755 if(!NT_SUCCESS(RC)) { 1756 AdPrint((" Can't perform OpenFile operation for file or stream\n")); 1757 BrutePoint(); 1758 goto Undo_Create_1; 1759 } 1760 1761 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.FileSize.QuadPart = 1762 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.ValidDataLength.QuadPart = 0; 1763 if(AllocationSize) { 1764 // inform NT about size changes 1765 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.AllocationSize.QuadPart = AllocationSize; 1766 MmPrint((" CcIsFileCached()\n")); 1767 if(CcIsFileCached(PtrNewFileObject)) { 1768 MmPrint((" CcSetFileSizes()\n")); 1769 BrutePoint(); 1770 CcSetFileSizes(PtrNewFileObject, (PCC_FILE_SIZES)&(PtrNewFcb->NTRequiredFCB->CommonFCBHeader.AllocationSize)); 1771 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; 1772 } 1773 } 1774 1775 // Update unwind information 1776 TreeLength++; 1777 LastGoodFileInfo = NewFileInfo; 1778 1779 // Set the Share Access for the file stream. 1780 // The FCBShareAccess field will be set by the I/O Manager. 1781 PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2); 1782 RC = UDFSetAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); 1783 1784 if(!NT_SUCCESS(RC)) { 1785 AdPrint((" Can't set Access Rights on Create\n")); 1786 BrutePoint(); 1787 UDFFlushFile__(Vcb, NewFileInfo); 1788 UDFUnlinkFile__(Vcb, NewFileInfo, TRUE); 1789 try_return(RC); 1790 } 1791 1792 #ifdef IFS_40 1793 // Set attributes for the file ... 1794 UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo),NewFileInfo->Index), 1795 NewFileInfo->Dloc->FileEntry, FileAttributes); 1796 // It is rather strange for me, but NT requires us to allow 1797 // Create operation for r/o + WriteAccess, but denies all 1798 // the rest operations in this case. Thus, we should update 1799 // r/o flag in Fcb _after_ Access check :-/ 1800 if(FileAttributes & FILE_ATTRIBUTE_READONLY) 1801 PtrNewFcb->FCBFlags |= UDF_FCB_READ_ONLY; 1802 #endif //IFS_40 1803 // We call the notify package to report that the 1804 // we have added a stream. 1805 if(UDFIsAStream(NewFileInfo)) { 1806 UDFNotifyFullReportChange( Vcb, NewFileInfo, 1807 FILE_NOTIFY_CHANGE_STREAM_NAME, 1808 FILE_ACTION_ADDED_STREAM ); 1809 } else { 1810 UDFNotifyFullReportChange( Vcb, NewFileInfo, 1811 UDFIsADirectory(NewFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, 1812 FILE_ACTION_ADDED); 1813 } 1814 /*#ifdef UDF_DBG 1815 { 1816 ULONG i; 1817 PDIR_INDEX_HDR hDirIndex = NewFileInfo->ParentFile->Dloc->DirIndex; 1818 1819 for(i=0;DirIndex[i].FName.Buffer;i++) { 1820 AdPrint(("%ws\n", DirIndex[i].FName.Buffer)); 1821 } 1822 } 1823 #endif*/ 1824 ReturnedInformation = FILE_CREATED; 1825 1826 try_return(RC); 1827 #endif //UDF_READ_ONLY_BUILD 1828 1829 } 1830 1831 AlreadyOpened: 1832 1833 // **************** 1834 // we have always STATUS_SUCCESS here 1835 // **************** 1836 1837 ASSERT(NewFileInfo != OldRelatedFileInfo); 1838 // A new CCB will be allocated. 1839 // Assume that this structure named PtrNewCcb 1840 RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb); 1841 if (!NT_SUCCESS(RC)) try_return(RC); 1842 PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2); 1843 1844 if(RequestedDisposition == FILE_CREATE) { 1845 ReturnedInformation = FILE_EXISTS; 1846 AdPrint((" Object name collision\n")); 1847 try_return(RC = STATUS_OBJECT_NAME_COLLISION); 1848 } 1849 1850 NtReqFcb = PtrNewFcb->NTRequiredFCB; 1851 NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(PtrNewFcb); 1852 1853 // Check if caller wanted a directory only and target object 1854 // is not a directory, or caller wanted a file only and target 1855 // object is not a file ... 1856 if((PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY) && ((RequestedDisposition == FILE_SUPERSEDE) || 1857 (RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF) || 1858 FileOnlyRequested)) { 1859 if(FileOnlyRequested) { 1860 AdPrint((" Can't open directory as a plain file\n")); 1861 } else { 1862 AdPrint((" Can't supersede directory\n")); 1863 } 1864 RC = STATUS_FILE_IS_A_DIRECTORY; 1865 try_return(RC); 1866 } 1867 1868 if(DirectoryOnlyRequested && !(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)) { 1869 AdPrint((" This is not a directory\n")); 1870 RC = STATUS_NOT_A_DIRECTORY; 1871 try_return(RC); 1872 } 1873 1874 if(DeleteOnCloseSpecified && (PtrNewFcb->FCBFlags & UDF_FCB_READ_ONLY)) { 1875 AdPrint((" Can't delete Read-Only file\n")); 1876 RC = STATUS_CANNOT_DELETE; 1877 try_return(RC); 1878 } 1879 // Check share access and fail if the share conflicts with an existing 1880 // open. 1881 ASSERT(Res1 != NULL); 1882 ASSERT(Res2 != NULL); 1883 RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess); 1884 if(!NT_SUCCESS(RC)) { 1885 AdPrint((" Access/Share access check failed\n")); 1886 try_return(RC); 1887 } 1888 1889 RestoreShareAccess = TRUE; 1890 1891 if(FileOnlyRequested) { 1892 // If the user wants 'write access' access to the file make sure there 1893 // is not a process mapping this file as an image. Any attempt to 1894 // delete the file will be stopped in fileinfo.cpp 1895 // 1896 // If the user wants to delete on close, we must check at this 1897 // point though. 1898 if( (DesiredAccess & FILE_WRITE_DATA) || DeleteOnCloseSpecified ) { 1899 MmPrint((" MmFlushImageSection();\n")); 1900 NtReqFcb->AcqFlushCount++; 1901 if(!MmFlushImageSection( &(NtReqFcb->SectionObject), 1902 MmFlushForWrite )) { 1903 1904 NtReqFcb->AcqFlushCount--; 1905 RC = DeleteOnCloseSpecified ? STATUS_CANNOT_DELETE : 1906 STATUS_SHARING_VIOLATION; 1907 AdPrint((" File is mapped or deletion in progress\n")); 1908 try_return (RC); 1909 } 1910 NtReqFcb->AcqFlushCount--; 1911 } 1912 if( NoBufferingSpecified && 1913 /* (PtrNewFileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) &&*/ 1914 !(PtrNewFcb->CachedOpenHandleCount) && 1915 (NtReqFcb->SectionObject.DataSectionObject) ) { 1916 // If this is a non-cached open, and there are no open cached 1917 // handles, but there is still a data section, attempt a flush 1918 // and purge operation to avoid cache coherency overhead later. 1919 // We ignore any I/O errors from the flush. 1920 MmPrint((" CcFlushCache()\n")); 1921 CcFlushCache( &(NtReqFcb->SectionObject), NULL, 0, NULL ); 1922 MmPrint((" CcPurgeCacheSection()\n")); 1923 CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE ); 1924 } 1925 } 1926 1927 if(DeleteOnCloseSpecified && UDFIsADirectory(NewFileInfo) && !UDFIsDirEmpty__(NewFileInfo)) { 1928 AdPrint((" Directory in not empry\n")); 1929 try_return (RC = STATUS_DIRECTORY_NOT_EMPTY); 1930 } 1931 1932 // Get attributes for the file ... 1933 TmpFileAttributes = 1934 (USHORT)UDFAttributesToNT(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index), 1935 NewFileInfo->Dloc->FileEntry); 1936 1937 if(DeleteOnCloseSpecified && 1938 (TmpFileAttributes & FILE_ATTRIBUTE_READONLY)) { 1939 ASSERT(Res1 != NULL); 1940 ASSERT(Res2 != NULL); 1941 RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, PtrRelatedCCB, FILE_DELETE_CHILD, 0); 1942 if(!NT_SUCCESS(RC)) { 1943 AdPrint((" Read-only. DeleteOnClose attempt failed\n")); 1944 try_return (RC = STATUS_CANNOT_DELETE); 1945 } 1946 } 1947 1948 // If a supersede or overwrite was requested, do so now ... 1949 if((RequestedDisposition == FILE_SUPERSEDE) || 1950 (RequestedDisposition == FILE_OVERWRITE) || 1951 (RequestedDisposition == FILE_OVERWRITE_IF)) { 1952 // Attempt the operation here ... 1953 1954 #ifndef UDF_READ_ONLY_BUILD 1955 ASSERT(!UDFIsADirectory(NewFileInfo)); 1956 1957 if(RequestedDisposition == FILE_SUPERSEDE) { 1958 BOOLEAN RestoreRO = FALSE; 1959 1960 ASSERT(Res1 != NULL); 1961 ASSERT(Res2 != NULL); 1962 // NT wants us to allow Supersede on RO files 1963 if(PtrNewFcb->FCBFlags & UDF_FCB_READ_ONLY) { 1964 // Imagine, that file is not RO and check other permissions 1965 RestoreRO = TRUE; 1966 PtrNewFcb->FCBFlags &= ~UDF_FCB_READ_ONLY; 1967 } 1968 RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb, DELETE, 0); 1969 if(RestoreRO) { 1970 // Restore RO state if changed 1971 PtrNewFcb->FCBFlags |= UDF_FCB_READ_ONLY; 1972 } 1973 if(!NT_SUCCESS(RC)) { 1974 AdPrint((" Can't supersede. DELETE permission required\n")); 1975 try_return (RC); 1976 } 1977 } else { 1978 ASSERT(Res1 != NULL); 1979 ASSERT(Res2 != NULL); 1980 RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb, 1981 FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES, 0); 1982 if(!NT_SUCCESS(RC)) { 1983 AdPrint((" Can't overwrite. Permission denied\n")); 1984 try_return (RC); 1985 } 1986 } 1987 // Existing & requested System and Hidden bits must match 1988 if( (TmpFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) & 1989 (FileAttributes ^ (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) ) { 1990 AdPrint((" The Hidden and/or System bits do not match\n")); 1991 try_return(RC = STATUS_ACCESS_DENIED); 1992 } 1993 1994 // Before we actually truncate, check to see if the purge 1995 // is going to fail. 1996 MmPrint((" MmCanFileBeTruncated()\n")); 1997 if (!MmCanFileBeTruncated( &NtReqFcb->SectionObject, 1998 &(UDFGlobalData.UDFLargeZero) )) { 1999 AdPrint((" Can't truncate. File is mapped\n")); 2000 try_return(RC = STATUS_USER_MAPPED_FILE); 2001 } 2002 2003 ASSERT(Res1 != NULL); 2004 ASSERT(Res2 != NULL); 2005 2006 #if 0 2007 CollectStatistics(Vcb, MetaDataWrites); 2008 #endif 2009 // Synchronize with PagingIo 2010 UDFAcquireResourceExclusive(PagingIoRes = &(NtReqFcb->PagingIoResource),TRUE); 2011 // Set file sizes 2012 if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, 0))) { 2013 AdPrint((" Error during resize operation\n")); 2014 try_return(RC); 2015 } 2016 /* if(AllocationSize) { 2017 if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) { 2018 AdPrint((" Error during resize operation (2)\n")); 2019 try_return(RC); 2020 } 2021 }*/ 2022 NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFSysGetAllocSize(Vcb, AllocationSize); 2023 NtReqFcb->CommonFCBHeader.FileSize.QuadPart = 2024 NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = 0 /*AllocationSize*/; 2025 PtrNewFcb->FCBFlags &= ~UDF_FCB_DELAY_CLOSE; 2026 MmPrint((" CcSetFileSizes()\n")); 2027 CcSetFileSizes(PtrNewFileObject, (PCC_FILE_SIZES)&(NtReqFcb->CommonFCBHeader.AllocationSize)); 2028 NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED; 2029 // Release PagingIoResource 2030 UDFReleaseResource(PagingIoRes); 2031 PagingIoRes = NULL; 2032 2033 if(NT_SUCCESS(RC)) { 2034 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; 2035 if (RequestedDisposition == FILE_SUPERSEDE) { 2036 // Set attributes for the file ... 2037 UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index), 2038 NewFileInfo->Dloc->FileEntry, FileAttributes); 2039 ReturnedInformation = FILE_SUPERSEDED; 2040 } else { 2041 // Get attributes for the file ... 2042 FileAttributes |= TmpFileAttributes; 2043 // Set attributes for the file ... 2044 UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index), 2045 NewFileInfo->Dloc->FileEntry, FileAttributes); 2046 ReturnedInformation = FILE_OVERWRITTEN; 2047 } 2048 } 2049 // notify changes 2050 UDFNotifyFullReportChange( Vcb, NewFileInfo, 2051 FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE, 2052 FILE_ACTION_MODIFIED); 2053 2054 // Update parent object 2055 if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) && 2056 PtrRelatedFCB && 2057 PtrRelatedFileObject && 2058 (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) { 2059 PtrRelatedFileObject->Flags |= (FO_FILE_MODIFIED | FO_FILE_SIZE_CHANGED); 2060 } 2061 #else //UDF_READ_ONLY_BUILD 2062 try_return(RC = STATUS_ACCESS_DENIED); 2063 #endif //UDF_READ_ONLY_BUILD 2064 } else { 2065 ReturnedInformation = FILE_OPENED; 2066 } 2067 2068 // Update parent object 2069 if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_READ) && 2070 PtrRelatedFCB && 2071 PtrRelatedFileObject && 2072 (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) { 2073 PtrRelatedFileObject->Flags |= FO_FILE_FAST_IO_READ; 2074 } 2075 2076 try_exit: NOTHING; 2077 2078 } _SEH2_FINALLY { 2079 // Complete the request unless we are here as part of unwinding 2080 // when an exception condition was encountered, OR 2081 // if the request has been deferred (i.e. posted for later handling) 2082 2083 if(RestoreVCBOpenCounter) { 2084 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 2085 RestoreVCBOpenCounter = FALSE; 2086 } 2087 2088 if (RC != STATUS_PENDING) { 2089 // If any intermediate (directory) open operations were performed, 2090 // implement the corresponding close (do *not* however close 2091 // the target we have opened on behalf of the caller ...). 2092 2093 #if 0 2094 if(NT_SUCCESS(RC)) { 2095 CollectStatistics2(Vcb, SuccessfulCreates); 2096 } else { 2097 CollectStatistics2(Vcb, FailedCreates); 2098 } 2099 #endif 2100 2101 if (NT_SUCCESS(RC) && PtrNewFcb) { 2102 // Update the file object such that: 2103 // (a) the FsContext field points to the NTRequiredFCB field 2104 // in the FCB 2105 // (b) the FsContext2 field points to the CCB created as a 2106 // result of the open operation 2107 2108 // If write-through was requested, then mark the file object 2109 // appropriately 2110 2111 // directories are not cached 2112 // so we should prevent flush attepmts on cleanup 2113 if(!(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)) { 2114 #ifndef UDF_READ_ONLY_BUILD 2115 if(WriteThroughRequested) { 2116 PtrNewFileObject->Flags |= FO_WRITE_THROUGH; 2117 PtrNewFcb->FCBFlags |= UDF_FCB_WRITE_THROUGH; 2118 MmPrint((" FO_WRITE_THROUGH\n")); 2119 } 2120 #endif //UDF_READ_ONLY_BUILD 2121 if(SequentialIoRequested && 2122 !(Vcb->CompatFlags & UDF_VCB_IC_IGNORE_SEQUENTIAL_IO)) { 2123 PtrNewFileObject->Flags |= FO_SEQUENTIAL_ONLY; 2124 MmPrint((" FO_SEQUENTIAL_ONLY\n")); 2125 #ifndef UDF_READ_ONLY_BUILD 2126 if(Vcb->TargetDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { 2127 PtrNewFileObject->Flags &= ~FO_WRITE_THROUGH; 2128 PtrNewFcb->FCBFlags &= ~UDF_FCB_WRITE_THROUGH; 2129 MmPrint((" FILE_REMOVABLE_MEDIA + FO_SEQUENTIAL_ONLY => ~FO_WRITE_THROUGH\n")); 2130 } 2131 #endif //UDF_READ_ONLY_BUILD 2132 if(PtrNewFcb->FileInfo) { 2133 UDFSetFileAllocMode__(PtrNewFcb->FileInfo, EXTENT_FLAG_ALLOC_SEQUENTIAL); 2134 } 2135 } 2136 if(NoBufferingSpecified) { 2137 PtrNewFileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING; 2138 MmPrint((" FO_NO_INTERMEDIATE_BUFFERING\n")); 2139 } else { 2140 PtrNewFileObject->Flags |= FO_CACHE_SUPPORTED; 2141 MmPrint((" FO_CACHE_SUPPORTED\n")); 2142 } 2143 } 2144 2145 if((DesiredAccess & FILE_EXECUTE) /*&& 2146 !(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)*/) { 2147 MmPrint((" FO_FILE_FAST_IO_READ\n")); 2148 PtrNewFileObject->Flags |= FO_FILE_FAST_IO_READ; 2149 } 2150 // All right. Now we can safely increment OpenHandleCount 2151 UDFInterlockedIncrement((PLONG)&(Vcb->VCBHandleCount)); 2152 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->OpenHandleCount)); 2153 2154 if(PtrNewFileObject->Flags & FO_CACHE_SUPPORTED) 2155 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->CachedOpenHandleCount)); 2156 // Store some flags in CCB 2157 if(PtrNewCcb) { 2158 PtrNewCcb->TreeLength = TreeLength; 2159 // delete on close 2160 #ifndef UDF_READ_ONLY_BUILD 2161 if(DeleteOnCloseSpecified) { 2162 ASSERT(!(PtrNewFcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY)); 2163 PtrNewCcb->CCBFlags |= UDF_CCB_DELETE_ON_CLOSE; 2164 } 2165 #endif //UDF_READ_ONLY_BUILD 2166 // case sensetivity 2167 if(!IgnoreCase) { 2168 // remember this for possible Rename/Move operation 2169 PtrNewCcb->CCBFlags |= UDF_CCB_CASE_SENSETIVE; 2170 PtrNewFileObject->Flags |= FO_OPENED_CASE_SENSITIVE; 2171 } 2172 if(IsFileObjectReadOnly(PtrNewFileObject)) { 2173 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCountRO)); 2174 PtrNewCcb->CCBFlags |= UDF_CCB_READ_ONLY; 2175 } 2176 } else { 2177 BrutePoint(); 2178 } 2179 // it was a stream... 2180 if(StreamOpen) 2181 PtrNewFileObject->Flags |= FO_STREAM_FILE; 2182 // PtrNewCcb->CCBFlags |= UDF_CCB_VALID; 2183 // increment the number of outstanding open operations on this 2184 // logical volume (i.e. volume cannot be dismounted) 2185 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 2186 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; 2187 PtrNewFcb->FCBFlags |= UDF_FCB_VALID; 2188 #ifdef UDF_DBG 2189 // We have no FileInfo for Volume 2190 if(PtrNewFcb->FileInfo) { 2191 ASSERT_REF(PtrNewFcb->ReferenceCount >= PtrNewFcb->FileInfo->RefCount); 2192 } 2193 #endif // UDF_DBG 2194 AdPrint((" FCB %x, CCB %x, FO %x, Flags %x\n", PtrNewFcb, PtrNewCcb, PtrNewFileObject, PtrNewFcb->FCBFlags)); 2195 2196 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); 2197 2198 } else if(!NT_SUCCESS(RC)) { 2199 // Perform failure related post-processing now 2200 if(RestoreShareAccess && NtReqFcb && PtrNewFileObject) { 2201 IoRemoveShareAccess(PtrNewFileObject, &(NtReqFcb->FCBShareAccess)); 2202 } 2203 UDFCleanUpCCB(PtrNewCcb); 2204 if(PtrNewFileObject) { 2205 PtrNewFileObject->FsContext2 = NULL; 2206 } 2207 // We have successfully opened LastGoodFileInfo, 2208 // so mark it as VALID to avoid future troubles... 2209 if(LastGoodFileInfo && LastGoodFileInfo->Fcb) { 2210 LastGoodFileInfo->Fcb->FCBFlags |= UDF_FCB_VALID; 2211 if(LastGoodFileInfo->Fcb->NTRequiredFCB) { 2212 LastGoodFileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID; 2213 } 2214 } 2215 // Release resources... 2216 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); 2217 ASSERT(AcquiredVcb); 2218 // close the chain 2219 UDFCloseFileInfoChain(Vcb, LastGoodFileInfo, TreeLength, TRUE); 2220 // cleanup FCBs (if any) 2221 if( Vcb && (PtrNewFcb != Vcb->RootDirFCB) && 2222 LastGoodFileInfo ) { 2223 UDFCleanUpFcbChain(Vcb, LastGoodFileInfo, TreeLength, TRUE); 2224 } else { 2225 ASSERT(!LastGoodFileInfo); 2226 } 2227 } else { 2228 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); 2229 } 2230 // As long as this unwinding is not being performed as a result of 2231 // an exception condition, complete the IRP ... 2232 if (!_SEH2_AbnormalTermination()) { 2233 Irp->IoStatus.Status = RC; 2234 Irp->IoStatus.Information = ReturnedInformation; 2235 2236 // complete the IRP 2237 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 2238 // Free up the Irp Context 2239 UDFReleaseIrpContext(PtrIrpContext); 2240 } 2241 } else { 2242 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2); 2243 } 2244 2245 if(AcquiredVcb) { 2246 UDFReleaseResource(&(Vcb->VCBResource)); 2247 } 2248 // free allocated tmp buffers (if any) 2249 if(AbsolutePathName.Buffer) 2250 MyFreePool__(AbsolutePathName.Buffer); 2251 if(LocalPath.Buffer) 2252 MyFreePool__(LocalPath.Buffer); 2253 if(TailNameBuffer) 2254 MyFreePool__(TailNameBuffer); 2255 } _SEH2_END; 2256 2257 return(RC); 2258 } // end UDFCommonCreate() 2259 2260 /************************************************************************* 2261 * 2262 * Function: UDFFirstOpenFile() 2263 * 2264 * Description: 2265 * Perform first Open/Create initialization. 2266 * 2267 * Expected Interrupt Level (for execution) : 2268 * 2269 * IRQL_PASSIVE_LEVEL 2270 * 2271 * Return Value: STATUS_SUCCESS/Error 2272 * 2273 *************************************************************************/ 2274 NTSTATUS 2275 UDFFirstOpenFile( 2276 IN PVCB Vcb, // volume control block 2277 IN PFILE_OBJECT PtrNewFileObject, // I/O Mgr. created file object 2278 OUT PtrUDFFCB* PtrNewFcb, 2279 IN PUDF_FILE_INFO RelatedFileInfo, 2280 IN PUDF_FILE_INFO NewFileInfo, 2281 IN PUNICODE_STRING LocalPath, 2282 IN PUNICODE_STRING CurName 2283 ) 2284 { 2285 // DIR_INDEX NewFileIndex; 2286 PtrUDFObjectName NewFCBName; 2287 PtrUDFNTRequiredFCB NtReqFcb; 2288 NTSTATUS RC; 2289 BOOLEAN Linked = TRUE; 2290 PDIR_INDEX_HDR hDirIndex; 2291 PDIR_INDEX_ITEM DirIndex; 2292 2293 AdPrint(("UDFFirstOpenFile\n")); 2294 2295 if(!((*PtrNewFcb) = UDFAllocateFCB())) { 2296 AdPrint(("Can't allocate FCB\n")); 2297 return STATUS_INSUFFICIENT_RESOURCES; 2298 } 2299 2300 // Allocate and set new FCB unique name (equal to absolute path name) 2301 if(!(NewFCBName = UDFAllocateObjectName())) return STATUS_INSUFFICIENT_RESOURCES; 2302 2303 if(RelatedFileInfo && RelatedFileInfo->Fcb && 2304 !(RelatedFileInfo->Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY)) { 2305 RC = MyCloneUnicodeString(&(NewFCBName->ObjectName), &(RelatedFileInfo->Fcb->FCBName->ObjectName)); 2306 } else { 2307 RC = MyInitUnicodeString(&(NewFCBName->ObjectName), L""); 2308 } 2309 if(!NT_SUCCESS(RC)) 2310 return STATUS_INSUFFICIENT_RESOURCES; 2311 if( (CurName->Buffer[0] != L':') && 2312 (!LocalPath->Length || 2313 ((LocalPath->Buffer[LocalPath->Length/sizeof(WCHAR)-1] != L':') /*&& 2314 (LocalPath->Buffer[LocalPath->Length/sizeof(WCHAR)-1] != L'\\')*/) )) { 2315 RC = MyAppendUnicodeToString(&(NewFCBName->ObjectName), L"\\"); 2316 if(!NT_SUCCESS(RC)) { 2317 UDFReleaseObjectName(NewFCBName); 2318 return STATUS_INSUFFICIENT_RESOURCES; 2319 } 2320 } 2321 2322 // Make link between Fcb and FileInfo 2323 (*PtrNewFcb)->FileInfo = NewFileInfo; 2324 NewFileInfo->Fcb = (*PtrNewFcb); 2325 (*PtrNewFcb)->ParentFcb = RelatedFileInfo->Fcb; 2326 2327 if(!((*PtrNewFcb)->NTRequiredFCB = NewFileInfo->Dloc->CommonFcb)) { 2328 (*PtrNewFcb)->NTRequiredFCB = (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB))); 2329 if(!((*PtrNewFcb)->NTRequiredFCB)) { 2330 UDFReleaseObjectName(NewFCBName); 2331 return STATUS_INSUFFICIENT_RESOURCES; 2332 } 2333 2334 UDFPrint(("UDFAllocateNtReqFCB: %x\n", (*PtrNewFcb)->NTRequiredFCB)); 2335 RtlZeroMemory((*PtrNewFcb)->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB))); 2336 (*PtrNewFcb)->FileInfo->Dloc->CommonFcb = (*PtrNewFcb)->NTRequiredFCB; 2337 Linked = FALSE; 2338 } else { 2339 if(!(NewFileInfo->Dloc->CommonFcb->NtReqFCBFlags & UDF_NTREQ_FCB_VALID)) { 2340 (*PtrNewFcb)->NTRequiredFCB = NULL; 2341 BrutePoint(); 2342 UDFReleaseObjectName(NewFCBName); 2343 return STATUS_ACCESS_DENIED; 2344 } 2345 } 2346 2347 NtReqFcb = (*PtrNewFcb)->NTRequiredFCB; 2348 // Set times 2349 if(!Linked) { 2350 UDFGetFileXTime((*PtrNewFcb)->FileInfo, 2351 &(NtReqFcb->CreationTime.QuadPart), 2352 &(NtReqFcb->LastAccessTime.QuadPart), 2353 &(NtReqFcb->ChangeTime.QuadPart), 2354 &(NtReqFcb->LastWriteTime.QuadPart) ); 2355 2356 // Set the allocation size for the object is specified 2357 NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = 2358 UDFSysGetAllocSize(Vcb, NewFileInfo->Dloc->DataLoc.Length); 2359 // NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFGetFileAllocationSize(Vcb, NewFileInfo); 2360 NtReqFcb->CommonFCBHeader.FileSize.QuadPart = 2361 NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = NewFileInfo->Dloc->DataLoc.Length; 2362 } 2363 // begin transaction 2364 UDFAcquireResourceExclusive(&(Vcb->FcbListResource), TRUE); 2365 2366 RC = UDFInitializeFCB(*PtrNewFcb, Vcb, NewFCBName, 2367 UDFIsADirectory(NewFileInfo) ? UDF_FCB_DIRECTORY : 0, PtrNewFileObject); 2368 if(!NT_SUCCESS(RC)) { 2369 if(!Linked) { 2370 MyFreePool__((*PtrNewFcb)->NTRequiredFCB); 2371 (*PtrNewFcb)->NTRequiredFCB = NULL; 2372 } 2373 UDFReleaseResource(&(Vcb->FcbListResource)); 2374 return RC; 2375 } 2376 // set Read-only attribute 2377 if(!UDFIsAStreamDir(NewFileInfo)) { 2378 hDirIndex = UDFGetDirIndexByFileInfo(NewFileInfo); 2379 #ifdef UDF_DBG 2380 if(!hDirIndex) { 2381 BrutePoint(); 2382 } else { 2383 #endif // UDF_DBG 2384 if(UDFAttributesToNT(DirIndex = UDFDirIndex(hDirIndex, NewFileInfo->Index),NULL) & FILE_ATTRIBUTE_READONLY) { 2385 (*PtrNewFcb)->FCBFlags |= UDF_FCB_READ_ONLY; 2386 } 2387 MyAppendUnicodeStringToStringTag(&(NewFCBName->ObjectName), &(DirIndex->FName), MEM_USOBJ_TAG); 2388 #ifdef UDF_DBG 2389 } 2390 #endif // UDF_DBG 2391 } else if (RelatedFileInfo->ParentFile) { 2392 hDirIndex = UDFGetDirIndexByFileInfo(RelatedFileInfo); 2393 if(UDFAttributesToNT(DirIndex = UDFDirIndex(hDirIndex, RelatedFileInfo->Index),NULL) & FILE_ATTRIBUTE_READONLY) { 2394 (*PtrNewFcb)->FCBFlags |= UDF_FCB_READ_ONLY; 2395 } 2396 RC = MyAppendUnicodeStringToStringTag(&(NewFCBName->ObjectName), CurName, MEM_USOBJ_TAG); 2397 // } else { 2398 // BrutePoint(); 2399 } 2400 // do not allocate CCB if it is internal Create/Open 2401 if(NT_SUCCESS(RC)) { 2402 if(PtrNewFileObject) { 2403 RC = UDFOpenFile(Vcb, PtrNewFileObject, *PtrNewFcb); 2404 } else { 2405 RC = STATUS_SUCCESS; 2406 } 2407 } 2408 UDFReleaseResource(&(Vcb->FcbListResource)); 2409 // end transaction 2410 2411 // if(!NT_SUCCESS(RC)) return RC; 2412 2413 return RC; 2414 } // end UDFFirstOpenFile() 2415 2416 /************************************************************************* 2417 * 2418 * Function: UDFOpenFile() 2419 * 2420 * Description: 2421 * Open a file/dir for the caller. 2422 * 2423 * Expected Interrupt Level (for execution) : 2424 * 2425 * IRQL_PASSIVE_LEVEL 2426 * 2427 * Return Value: STATUS_SUCCESS/Error 2428 * 2429 *************************************************************************/ 2430 NTSTATUS 2431 UDFOpenFile( 2432 PVCB Vcb, // volume control block 2433 PFILE_OBJECT PtrNewFileObject, // I/O Mgr. created file object 2434 PtrUDFFCB PtrNewFcb 2435 ) 2436 { 2437 NTSTATUS RC = STATUS_SUCCESS; 2438 PtrUDFCCB Ccb = NULL; 2439 PtrUDFNTRequiredFCB NtReqFcb; 2440 2441 AdPrint(("UDFOpenFile\n")); 2442 ASSERT((PtrNewFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB) 2443 ||(PtrNewFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB)); 2444 2445 _SEH2_TRY { 2446 2447 #if 0 2448 CollectStatistics2(Vcb, CreateHits); 2449 #endif 2450 // create a new CCB structure 2451 if (!(Ccb = UDFAllocateCCB())) { 2452 AdPrint(("Can't allocate CCB\n")); 2453 PtrNewFileObject->FsContext2 = NULL; 2454 // 2455 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount)); 2456 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 2457 RC = STATUS_INSUFFICIENT_RESOURCES; 2458 try_return(RC); 2459 } 2460 // initialize the CCB 2461 Ccb->Fcb = PtrNewFcb; 2462 // initialize the CCB to point to the file object 2463 Ccb->FileObject = PtrNewFileObject; 2464 2465 // initialize the file object appropriately 2466 PtrNewFileObject->FsContext2 = (PVOID)(Ccb); 2467 PtrNewFileObject->Vpb = Vcb->Vpb; 2468 PtrNewFileObject->FsContext = (PVOID)(NtReqFcb = PtrNewFcb->NTRequiredFCB); 2469 PtrNewFileObject->SectionObjectPointer = &(NtReqFcb->SectionObject); 2470 #ifdef DBG 2471 // NtReqFcb ->FileObject = PtrNewFileObject; 2472 #endif //DBG 2473 2474 #ifdef UDF_DELAYED_CLOSE 2475 PtrNewFcb->FCBFlags &= ~UDF_FCB_DELAY_CLOSE; 2476 #endif //UDF_DELAYED_CLOSE 2477 2478 UDFAcquireResourceExclusive(&(PtrNewFcb->CcbListResource),TRUE); 2479 // insert CCB into linked list of open file object to Fcb or 2480 // to Vcb and do other intialization 2481 InsertTailList(&(PtrNewFcb->NextCCB), &(Ccb->NextCCB)); 2482 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount)); 2483 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount)); 2484 UDFReleaseResource(&(PtrNewFcb->CcbListResource)); 2485 2486 try_exit: NOTHING; 2487 } _SEH2_FINALLY { 2488 NOTHING; 2489 } _SEH2_END; 2490 2491 return(RC); 2492 } // end UDFOpenFile() 2493 2494 2495 /************************************************************************* 2496 * 2497 * Function: UDFInitializeFCB() 2498 * 2499 * Description: 2500 * Initialize a new FCB structure and also the sent-in file object 2501 * (if supplied) 2502 * 2503 * Expected Interrupt Level (for execution) : 2504 * 2505 * IRQL_PASSIVE_LEVEL 2506 * 2507 * Return Value: None 2508 * 2509 *************************************************************************/ 2510 NTSTATUS 2511 UDFInitializeFCB( 2512 IN PtrUDFFCB PtrNewFcb, // FCB structure to be initialized 2513 IN PVCB Vcb, // logical volume (VCB) pointer 2514 IN PtrUDFObjectName PtrObjectName, // name of the object 2515 IN ULONG Flags, // is this a file/directory, etc. 2516 IN PFILE_OBJECT FileObject) // optional file object to be initialized 2517 { 2518 AdPrint(("UDFInitializeFCB\n")); 2519 NTSTATUS status; 2520 BOOLEAN Linked = TRUE; 2521 2522 if(!PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource) { 2523 // record signature 2524 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode = UDF_NODE_TYPE_NT_REQ_FCB; 2525 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeByteSize = sizeof(UDFNTRequiredFCB); 2526 // Initialize the ERESOURCE objects 2527 if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->NTRequiredFCB->MainResource)))) { 2528 AdPrint((" Can't init resource\n")); 2529 return status; 2530 } 2531 if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->NTRequiredFCB->PagingIoResource)))) { 2532 AdPrint((" Can't init resource (2)\n")); 2533 UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->MainResource)); 2534 return status; 2535 } 2536 // Fill NT required Fcb part 2537 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource = &(PtrNewFcb->NTRequiredFCB->MainResource); 2538 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource = &(PtrNewFcb->NTRequiredFCB->PagingIoResource); 2539 // Itialize byte-range locks support structure 2540 FsRtlInitializeFileLock(&(PtrNewFcb->NTRequiredFCB->FileLock),NULL,NULL); 2541 // Init reference counter 2542 PtrNewFcb->NTRequiredFCB->CommonRefCount = 0; 2543 Linked = FALSE; 2544 } else { 2545 ASSERT(PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode == UDF_NODE_TYPE_NT_REQ_FCB); 2546 } 2547 if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->CcbListResource)))) { 2548 AdPrint((" Can't init resource (3)\n")); 2549 BrutePoint(); 2550 if(!Linked) { 2551 UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->PagingIoResource)); 2552 UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->MainResource)); 2553 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource = 2554 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource = NULL; 2555 FsRtlUninitializeFileLock(&(PtrNewFcb->NTRequiredFCB->FileLock)); 2556 } 2557 return status; 2558 } 2559 2560 // caller MUST ensure that VCB has been acquired exclusively 2561 InsertTailList(&(Vcb->NextFCB), &(PtrNewFcb->NextFCB)); 2562 2563 // initialize the various list heads 2564 InitializeListHead(&(PtrNewFcb->NextCCB)); 2565 2566 PtrNewFcb->ReferenceCount = 0; 2567 PtrNewFcb->OpenHandleCount = 0; 2568 2569 PtrNewFcb->FCBFlags = Flags | UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE; 2570 2571 PtrNewFcb->FCBName = PtrObjectName; 2572 2573 PtrNewFcb->Vcb = Vcb; 2574 2575 return STATUS_SUCCESS; 2576 } // end UDFInitializeFCB() 2577 2578