1 /* 2 * COPYRIGHT: See COPYRIGHT.TXT 3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP 4 * FILE: fileinfo.c 5 * PROGRAMMER: Matt Wu <mattwu@163.com> 6 * HOMEPAGE: http://www.ext2fsd.com 7 * UPDATE HISTORY: 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include "ext2fs.h" 13 #ifdef __REACTOS__ 14 #include "linux/ext4.h" 15 #include "linux/ext4_xattr.h" 16 #else 17 #include "linux\ext4.h" 18 #include "linux\ext4_xattr.h" 19 #endif 20 21 /* GLOBALS ***************************************************************/ 22 23 extern PEXT2_GLOBAL Ext2Global; 24 25 /* DEFINITIONS *************************************************************/ 26 27 #ifdef ALLOC_PRAGMA 28 #pragma alloc_text(PAGE, Ext2QueryFileInformation) 29 #pragma alloc_text(PAGE, Ext2SetFileInformation) 30 #pragma alloc_text(PAGE, Ext2ExpandFile) 31 #pragma alloc_text(PAGE, Ext2TruncateFile) 32 #pragma alloc_text(PAGE, Ext2SetDispositionInfo) 33 #pragma alloc_text(PAGE, Ext2SetRenameInfo) 34 #pragma alloc_text(PAGE, Ext2SetLinkInfo) 35 #pragma alloc_text(PAGE, Ext2DeleteFile) 36 #endif 37 38 static int Ext2IterateAllEa(struct ext4_xattr_ref *xattr_ref, struct ext4_xattr_item *item, BOOL is_last) 39 { 40 PULONG EaSize = xattr_ref->iter_arg; 41 ULONG EaEntrySize = 4 + 1 + 1 + 2 + item->name_len + 1 + item->data_size; 42 43 *EaSize += EaEntrySize - 4; 44 return EXT4_XATTR_ITERATE_CONT; 45 } 46 47 NTSTATUS 48 Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) 49 { 50 PDEVICE_OBJECT DeviceObject; 51 NTSTATUS Status = STATUS_UNSUCCESSFUL; 52 PFILE_OBJECT FileObject; 53 PEXT2_VCB Vcb = NULL; 54 PEXT2_FCB Fcb = NULL; 55 PEXT2_MCB Mcb = NULL; 56 PEXT2_CCB Ccb = NULL; 57 PIRP Irp = NULL; 58 PIO_STACK_LOCATION IoStackLocation; 59 FILE_INFORMATION_CLASS FileInformationClass; 60 ULONG Length; 61 PVOID Buffer; 62 BOOLEAN FcbResourceAcquired = FALSE; 63 64 _SEH2_TRY { 65 66 ASSERT(IrpContext != NULL); 67 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 68 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 69 70 DeviceObject = IrpContext->DeviceObject; 71 72 // 73 // This request is not allowed on the main device object 74 // 75 if (IsExt2FsDevice(DeviceObject)) { 76 Status = STATUS_INVALID_DEVICE_REQUEST; 77 _SEH2_LEAVE; 78 } 79 80 FileObject = IrpContext->FileObject; 81 Fcb = (PEXT2_FCB) FileObject->FsContext; 82 if (Fcb == NULL) { 83 Status = STATUS_INVALID_PARAMETER; 84 _SEH2_LEAVE; 85 } 86 87 // 88 // This request is not allowed on volumes 89 // 90 if (Fcb->Identifier.Type == EXT2VCB) { 91 Status = STATUS_INVALID_PARAMETER; 92 _SEH2_LEAVE; 93 } 94 95 if (!((Fcb->Identifier.Type == EXT2FCB) && 96 (Fcb->Identifier.Size == sizeof(EXT2_FCB)))) { 97 Status = STATUS_INVALID_PARAMETER; 98 _SEH2_LEAVE; 99 } 100 101 Vcb = Fcb->Vcb; 102 103 { 104 if (!ExAcquireResourceSharedLite( 105 &Fcb->MainResource, 106 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) 107 )) { 108 109 Status = STATUS_PENDING; 110 _SEH2_LEAVE; 111 } 112 113 FcbResourceAcquired = TRUE; 114 } 115 116 Ccb = (PEXT2_CCB) FileObject->FsContext2; 117 ASSERT(Ccb != NULL); 118 ASSERT((Ccb->Identifier.Type == EXT2CCB) && 119 (Ccb->Identifier.Size == sizeof(EXT2_CCB))); 120 Mcb = Ccb->SymLink; 121 if (!Mcb) 122 Mcb = Fcb->Mcb; 123 124 Irp = IrpContext->Irp; 125 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 126 FileInformationClass = 127 IoStackLocation->Parameters.QueryFile.FileInformationClass; 128 129 Length = IoStackLocation->Parameters.QueryFile.Length; 130 Buffer = Irp->AssociatedIrp.SystemBuffer; 131 RtlZeroMemory(Buffer, Length); 132 133 switch (FileInformationClass) { 134 135 case FileBasicInformation: 136 { 137 PFILE_BASIC_INFORMATION FileBasicInformation; 138 139 if (Length < sizeof(FILE_BASIC_INFORMATION)) { 140 Status = STATUS_BUFFER_OVERFLOW; 141 _SEH2_LEAVE; 142 } 143 144 FileBasicInformation = (PFILE_BASIC_INFORMATION) Buffer; 145 146 FileBasicInformation->CreationTime = Mcb->CreationTime; 147 FileBasicInformation->LastAccessTime = Mcb->LastAccessTime; 148 FileBasicInformation->LastWriteTime = Mcb->LastWriteTime; 149 FileBasicInformation->ChangeTime = Mcb->ChangeTime; 150 151 FileBasicInformation->FileAttributes = Mcb->FileAttr; 152 if (IsLinkInvalid(Mcb)) { 153 ClearFlag(FileBasicInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY); 154 } 155 if (FileBasicInformation->FileAttributes == 0) { 156 FileBasicInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL; 157 } 158 159 Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION); 160 Status = STATUS_SUCCESS; 161 } 162 break; 163 164 case FileStandardInformation: 165 { 166 PFILE_STANDARD_INFORMATION FSI; 167 168 if (Length < sizeof(FILE_STANDARD_INFORMATION)) { 169 Status = STATUS_BUFFER_OVERFLOW; 170 _SEH2_LEAVE; 171 } 172 173 FSI = (PFILE_STANDARD_INFORMATION) Buffer; 174 175 FSI->NumberOfLinks = Mcb->Inode.i_nlink; 176 177 if (IsVcbReadOnly(Fcb->Vcb)) 178 FSI->DeletePending = FALSE; 179 else 180 FSI->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING); 181 182 if (IsLinkInvalid(Mcb)) { 183 FSI->Directory = FALSE; 184 FSI->AllocationSize.QuadPart = 0; 185 FSI->EndOfFile.QuadPart = 0; 186 } else if (IsMcbDirectory(Mcb)) { 187 FSI->Directory = TRUE; 188 FSI->AllocationSize.QuadPart = 0; 189 FSI->EndOfFile.QuadPart = 0; 190 } else { 191 FSI->Directory = FALSE; 192 FSI->AllocationSize = Fcb->Header.AllocationSize; 193 FSI->EndOfFile = Fcb->Header.FileSize; 194 } 195 196 Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION); 197 Status = STATUS_SUCCESS; 198 } 199 break; 200 201 case FileInternalInformation: 202 { 203 PFILE_INTERNAL_INFORMATION FileInternalInformation; 204 205 if (Length < sizeof(FILE_INTERNAL_INFORMATION)) { 206 Status = STATUS_BUFFER_OVERFLOW; 207 _SEH2_LEAVE; 208 } 209 210 FileInternalInformation = (PFILE_INTERNAL_INFORMATION) Buffer; 211 212 /* we use the inode number as the internal index */ 213 FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Mcb->Inode.i_ino; 214 215 Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION); 216 Status = STATUS_SUCCESS; 217 } 218 break; 219 220 221 case FileEaInformation: 222 { 223 struct ext4_xattr_ref xattr_ref; 224 PFILE_EA_INFORMATION FileEaInformation; 225 226 if (Length < sizeof(FILE_EA_INFORMATION)) { 227 Status = STATUS_BUFFER_OVERFLOW; 228 _SEH2_LEAVE; 229 } 230 231 FileEaInformation = (PFILE_EA_INFORMATION) Buffer; 232 FileEaInformation->EaSize = 0; 233 234 Status = Ext2WinntError(ext4_fs_get_xattr_ref(IrpContext, Vcb, Fcb->Mcb, &xattr_ref)); 235 if (!NT_SUCCESS(Status)) 236 _SEH2_LEAVE; 237 238 xattr_ref.iter_arg = &FileEaInformation->EaSize; 239 ext4_fs_xattr_iterate(&xattr_ref, Ext2IterateAllEa); 240 ext4_fs_put_xattr_ref(&xattr_ref); 241 242 if (FileEaInformation->EaSize) 243 FileEaInformation->EaSize += 4; 244 245 Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION); 246 Status = STATUS_SUCCESS; 247 } 248 break; 249 250 case FileNameInformation: 251 { 252 PFILE_NAME_INFORMATION FileNameInformation; 253 ULONG BytesToCopy = 0; 254 255 if (Length < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + 256 Mcb->FullName.Length) { 257 BytesToCopy = Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 258 Status = STATUS_BUFFER_OVERFLOW; 259 } else { 260 BytesToCopy = Mcb->FullName.Length; 261 Status = STATUS_SUCCESS; 262 } 263 264 FileNameInformation = (PFILE_NAME_INFORMATION) Buffer; 265 FileNameInformation->FileNameLength = Mcb->FullName.Length; 266 267 RtlCopyMemory( 268 FileNameInformation->FileName, 269 Mcb->FullName.Buffer, 270 BytesToCopy ); 271 272 Irp->IoStatus.Information = BytesToCopy + 273 + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 274 } 275 break; 276 277 case FilePositionInformation: 278 { 279 PFILE_POSITION_INFORMATION FilePositionInformation; 280 281 if (Length < sizeof(FILE_POSITION_INFORMATION)) { 282 Status = STATUS_BUFFER_OVERFLOW; 283 _SEH2_LEAVE; 284 } 285 286 FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer; 287 FilePositionInformation->CurrentByteOffset = 288 FileObject->CurrentByteOffset; 289 290 Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION); 291 Status = STATUS_SUCCESS; 292 } 293 break; 294 295 case FileAllInformation: 296 { 297 PFILE_ALL_INFORMATION FileAllInformation; 298 PFILE_BASIC_INFORMATION FileBasicInformation; 299 PFILE_STANDARD_INFORMATION FSI; 300 PFILE_INTERNAL_INFORMATION FileInternalInformation; 301 PFILE_EA_INFORMATION FileEaInformation; 302 PFILE_POSITION_INFORMATION FilePositionInformation; 303 PFILE_NAME_INFORMATION FileNameInformation; 304 305 if (Length < sizeof(FILE_ALL_INFORMATION)) { 306 Status = STATUS_BUFFER_OVERFLOW; 307 _SEH2_LEAVE; 308 } 309 310 FileAllInformation = (PFILE_ALL_INFORMATION) Buffer; 311 312 FileBasicInformation = 313 &FileAllInformation->BasicInformation; 314 315 FSI = 316 &FileAllInformation->StandardInformation; 317 318 FileInternalInformation = 319 &FileAllInformation->InternalInformation; 320 321 FileEaInformation = 322 &FileAllInformation->EaInformation; 323 324 FilePositionInformation = 325 &FileAllInformation->PositionInformation; 326 327 FileNameInformation = 328 &FileAllInformation->NameInformation; 329 330 FileBasicInformation->CreationTime = Mcb->CreationTime; 331 FileBasicInformation->LastAccessTime = Mcb->LastAccessTime; 332 FileBasicInformation->LastWriteTime = Mcb->LastWriteTime; 333 FileBasicInformation->ChangeTime = Mcb->ChangeTime; 334 335 FileBasicInformation->FileAttributes = Mcb->FileAttr; 336 if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target)) { 337 ClearFlag(FileBasicInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY); 338 } 339 if (FileBasicInformation->FileAttributes == 0) { 340 FileBasicInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL; 341 } 342 343 FSI->NumberOfLinks = Mcb->Inode.i_nlink; 344 345 if (IsVcbReadOnly(Fcb->Vcb)) 346 FSI->DeletePending = FALSE; 347 else 348 FSI->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING); 349 350 if (IsLinkInvalid(Mcb)) { 351 FSI->Directory = FALSE; 352 FSI->AllocationSize.QuadPart = 0; 353 FSI->EndOfFile.QuadPart = 0; 354 } else if (IsDirectory(Fcb)) { 355 FSI->Directory = TRUE; 356 FSI->AllocationSize.QuadPart = 0; 357 FSI->EndOfFile.QuadPart = 0; 358 } else { 359 FSI->Directory = FALSE; 360 FSI->AllocationSize = Fcb->Header.AllocationSize; 361 FSI->EndOfFile = Fcb->Header.FileSize; 362 } 363 364 // The "inode number" 365 FileInternalInformation->IndexNumber.QuadPart = (LONGLONG)Mcb->Inode.i_ino; 366 367 // Romfs doesn't have any extended attributes 368 FileEaInformation->EaSize = 0; 369 370 FilePositionInformation->CurrentByteOffset = 371 FileObject->CurrentByteOffset; 372 373 FileNameInformation->FileNameLength = Mcb->ShortName.Length; 374 375 if (Length < sizeof(FILE_ALL_INFORMATION) + 376 Mcb->ShortName.Length - sizeof(WCHAR)) { 377 Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION); 378 Status = STATUS_BUFFER_OVERFLOW; 379 RtlCopyMemory( 380 FileNameInformation->FileName, 381 Mcb->ShortName.Buffer, 382 Length - FIELD_OFFSET(FILE_ALL_INFORMATION, 383 NameInformation.FileName) 384 ); 385 _SEH2_LEAVE; 386 } 387 388 RtlCopyMemory( 389 FileNameInformation->FileName, 390 Mcb->ShortName.Buffer, 391 Mcb->ShortName.Length 392 ); 393 394 Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) + 395 Mcb->ShortName.Length - sizeof(WCHAR); 396 #if 0 397 sizeof(FILE_ACCESS_INFORMATION) - 398 sizeof(FILE_MODE_INFORMATION) - 399 sizeof(FILE_ALIGNMENT_INFORMATION); 400 #endif 401 402 Status = STATUS_SUCCESS; 403 } 404 break; 405 406 /* 407 case FileAlternateNameInformation: 408 { 409 // TODO: Handle FileAlternateNameInformation 410 411 // Here we would like to use RtlGenerate8dot3Name but I don't 412 // know how to use the argument PGENERATE_NAME_CONTEXT 413 } 414 */ 415 416 case FileNetworkOpenInformation: 417 { 418 PFILE_NETWORK_OPEN_INFORMATION PFNOI; 419 420 if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION)) { 421 Status = STATUS_BUFFER_OVERFLOW; 422 _SEH2_LEAVE; 423 } 424 425 PFNOI = (PFILE_NETWORK_OPEN_INFORMATION) Buffer; 426 427 PFNOI->FileAttributes = Mcb->FileAttr; 428 if (IsLinkInvalid(Mcb)) { 429 ClearFlag(PFNOI->FileAttributes, FILE_ATTRIBUTE_DIRECTORY); 430 PFNOI->AllocationSize.QuadPart = 0; 431 PFNOI->EndOfFile.QuadPart = 0; 432 } else if (IsDirectory(Fcb)) { 433 PFNOI->AllocationSize.QuadPart = 0; 434 PFNOI->EndOfFile.QuadPart = 0; 435 } else { 436 PFNOI->AllocationSize = Fcb->Header.AllocationSize; 437 PFNOI->EndOfFile = Fcb->Header.FileSize; 438 } 439 440 if (PFNOI->FileAttributes == 0) { 441 PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL; 442 } 443 444 PFNOI->CreationTime = Mcb->CreationTime; 445 PFNOI->LastAccessTime = Mcb->LastAccessTime; 446 PFNOI->LastWriteTime = Mcb->LastWriteTime; 447 PFNOI->ChangeTime = Mcb->ChangeTime; 448 449 450 Irp->IoStatus.Information = 451 sizeof(FILE_NETWORK_OPEN_INFORMATION); 452 Status = STATUS_SUCCESS; 453 } 454 break; 455 456 #if (_WIN32_WINNT >= 0x0500) 457 458 case FileAttributeTagInformation: 459 { 460 PFILE_ATTRIBUTE_TAG_INFORMATION FATI; 461 462 if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION)) { 463 Status = STATUS_BUFFER_OVERFLOW; 464 _SEH2_LEAVE; 465 } 466 467 FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer; 468 FATI->FileAttributes = Mcb->FileAttr; 469 if (IsLinkInvalid(Mcb)) { 470 ClearFlag(FATI->FileAttributes, FILE_ATTRIBUTE_DIRECTORY); 471 } 472 if (FATI->FileAttributes == 0) { 473 FATI->FileAttributes = FILE_ATTRIBUTE_NORMAL; 474 } 475 FATI->ReparseTag = IO_REPARSE_TAG_RESERVED_ZERO; 476 Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION); 477 Status = STATUS_SUCCESS; 478 } 479 break; 480 #endif // (_WIN32_WINNT >= 0x0500) 481 482 case FileStreamInformation: 483 Status = STATUS_INVALID_PARAMETER; 484 break; 485 486 default: 487 DEBUG(DL_WRN, ( "Ext2QueryInformation: invalid class: %d\n", 488 FileInformationClass)); 489 Status = STATUS_INVALID_PARAMETER; /* STATUS_INVALID_INFO_CLASS; */ 490 break; 491 } 492 493 } _SEH2_FINALLY { 494 495 if (FcbResourceAcquired) { 496 ExReleaseResourceLite(&Fcb->MainResource); 497 } 498 499 if (!IrpContext->ExceptionInProgress) { 500 if (Status == STATUS_PENDING || 501 Status == STATUS_CANT_WAIT) { 502 Status = Ext2QueueRequest(IrpContext); 503 } else { 504 Ext2CompleteIrpContext(IrpContext, Status); 505 } 506 } 507 } _SEH2_END; 508 509 return Status; 510 } 511 512 513 NTSTATUS 514 Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) 515 { 516 PDEVICE_OBJECT DeviceObject; 517 NTSTATUS Status = STATUS_UNSUCCESSFUL; 518 PEXT2_VCB Vcb = NULL; 519 PFILE_OBJECT FileObject = NULL; 520 PEXT2_FCB Fcb = NULL; 521 PEXT2_CCB Ccb = NULL; 522 PEXT2_MCB Mcb = NULL; 523 PIRP Irp = NULL; 524 PIO_STACK_LOCATION IoStackLocation = NULL; 525 FILE_INFORMATION_CLASS FileInformationClass; 526 527 ULONG NotifyFilter = 0; 528 529 ULONG Length; 530 PVOID Buffer; 531 532 BOOLEAN FcbMainResourceAcquired = FALSE; 533 BOOLEAN FcbPagingIoResourceAcquired = FALSE; 534 535 _SEH2_TRY { 536 537 ASSERT(IrpContext != NULL); 538 539 ASSERT((IrpContext->Identifier.Type == EXT2ICX) && 540 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); 541 DeviceObject = IrpContext->DeviceObject; 542 543 // 544 // This request is not allowed on the main device object 545 // 546 if (IsExt2FsDevice(DeviceObject)) { 547 Status = STATUS_INVALID_DEVICE_REQUEST; 548 _SEH2_LEAVE; 549 } 550 551 /* check io stack location of irp stack */ 552 Irp = IrpContext->Irp; 553 IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 554 FileInformationClass = 555 IoStackLocation->Parameters.SetFile.FileInformationClass; 556 Length = IoStackLocation->Parameters.SetFile.Length; 557 Buffer = Irp->AssociatedIrp.SystemBuffer; 558 559 /* check Vcb */ 560 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; 561 ASSERT(Vcb != NULL); 562 ASSERT((Vcb->Identifier.Type == EXT2VCB) && 563 (Vcb->Identifier.Size == sizeof(EXT2_VCB))); 564 if (!IsMounted(Vcb)) { 565 Status = STATUS_INVALID_DEVICE_REQUEST; 566 _SEH2_LEAVE; 567 } 568 569 if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { 570 Status = STATUS_ACCESS_DENIED; 571 _SEH2_LEAVE; 572 } 573 574 FileObject = IrpContext->FileObject; 575 Fcb = (PEXT2_FCB) FileObject->FsContext; 576 577 // This request is issued to volumes, just return success 578 if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { 579 Status = STATUS_SUCCESS; 580 _SEH2_LEAVE; 581 } 582 ASSERT((Fcb->Identifier.Type == EXT2FCB) && 583 (Fcb->Identifier.Size == sizeof(EXT2_FCB))); 584 585 if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { 586 Status = STATUS_FILE_DELETED; 587 _SEH2_LEAVE; 588 } 589 590 Ccb = (PEXT2_CCB) FileObject->FsContext2; 591 ASSERT(Ccb != NULL); 592 ASSERT((Ccb->Identifier.Type == EXT2CCB) && 593 (Ccb->Identifier.Size == sizeof(EXT2_CCB))); 594 Mcb = Ccb->SymLink; 595 if (Mcb) { 596 if (IsFlagOn(Mcb->Flags, MCB_FILE_DELETED)) { 597 Status = STATUS_FILE_DELETED; 598 _SEH2_LEAVE; 599 } 600 } else { 601 Mcb = Fcb->Mcb; 602 } 603 604 if (FileInformationClass != FilePositionInformation) { 605 if (IsVcbReadOnly(Vcb)) { 606 Status = STATUS_MEDIA_WRITE_PROTECTED; 607 _SEH2_LEAVE; 608 } 609 if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) { 610 Status = STATUS_ACCESS_DENIED; 611 _SEH2_LEAVE; 612 } 613 } 614 615 if ( !IsDirectory(Fcb) && !FlagOn(Fcb->Flags, FCB_PAGE_FILE) && 616 ((FileInformationClass == FileEndOfFileInformation) || 617 (FileInformationClass == FileValidDataLengthInformation) || 618 (FileInformationClass == FileAllocationInformation))) { 619 620 Status = FsRtlCheckOplock( &Fcb->Oplock, 621 Irp, 622 IrpContext, 623 NULL, 624 NULL ); 625 626 if (Status != STATUS_SUCCESS) { 627 _SEH2_LEAVE; 628 } 629 630 // 631 // Set the flag indicating if Fast I/O is possible 632 // 633 634 Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); 635 } 636 637 /* for renaming or set link, we must not grab any Fcb locks, 638 and later we will get Dcb or Fcb resources exclusively. */ 639 if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) && 640 FileInformationClass != FileRenameInformation && 641 FileInformationClass != FileLinkInformation) { 642 643 if (!ExAcquireResourceExclusiveLite( 644 &Fcb->MainResource, 645 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { 646 Status = STATUS_PENDING; 647 _SEH2_LEAVE; 648 } 649 650 FcbMainResourceAcquired = TRUE; 651 652 if ( FileInformationClass == FileAllocationInformation || 653 FileInformationClass == FileEndOfFileInformation || 654 FileInformationClass == FileValidDataLengthInformation) { 655 656 if (!ExAcquireResourceExclusiveLite( 657 &Fcb->PagingIoResource, 658 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { 659 Status = STATUS_PENDING; 660 DbgBreak(); 661 _SEH2_LEAVE; 662 } 663 FcbPagingIoResourceAcquired = TRUE; 664 } 665 } 666 667 switch (FileInformationClass) { 668 669 case FileBasicInformation: 670 { 671 PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION) Buffer; 672 struct inode *Inode = &Mcb->Inode; 673 674 if (FBI->CreationTime.QuadPart != 0 && FBI->CreationTime.QuadPart != -1) { 675 Inode->i_ctime = Ext2LinuxTime(FBI->CreationTime); 676 Mcb->CreationTime = Ext2NtTime(Inode->i_ctime); 677 NotifyFilter |= FILE_NOTIFY_CHANGE_CREATION; 678 } 679 680 if (FBI->LastAccessTime.QuadPart != 0 && FBI->LastAccessTime.QuadPart != -1) { 681 Inode->i_atime = Ext2LinuxTime(FBI->LastAccessTime); 682 Mcb->LastAccessTime = Ext2NtTime(Inode->i_atime); 683 NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS; 684 } 685 686 if (FBI->LastWriteTime.QuadPart != 0 && FBI->LastWriteTime.QuadPart != -1) { 687 Inode->i_mtime = Ext2LinuxTime(FBI->LastWriteTime); 688 Mcb->LastWriteTime = Ext2NtTime(Inode->i_mtime); 689 NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE; 690 SetFlag(Ccb->Flags, CCB_LAST_WRITE_UPDATED); 691 } 692 693 if (FBI->ChangeTime.QuadPart !=0 && FBI->ChangeTime.QuadPart != -1) { 694 Mcb->ChangeTime = FBI->ChangeTime; 695 } 696 697 if (FBI->FileAttributes != 0) { 698 699 BOOLEAN bIsDirectory = IsDirectory(Fcb); 700 NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES; 701 702 if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) { 703 Ext2SetOwnerReadOnly(Inode->i_mode); 704 } else { 705 Ext2SetOwnerWritable(Inode->i_mode); 706 } 707 708 if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) { 709 SetFlag(FileObject->Flags, FO_TEMPORARY_FILE); 710 } else { 711 ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE); 712 } 713 714 Mcb->FileAttr = FBI->FileAttributes; 715 if (bIsDirectory) { 716 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY); 717 ClearFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL); 718 } 719 } 720 721 if (NotifyFilter != 0) { 722 if (Ext2SaveInode(IrpContext, Vcb, Inode)) { 723 Status = STATUS_SUCCESS; 724 } 725 } 726 727 ClearFlag(NotifyFilter, FILE_NOTIFY_CHANGE_LAST_ACCESS); 728 Status = STATUS_SUCCESS; 729 } 730 731 break; 732 733 case FileAllocationInformation: 734 { 735 PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer; 736 LARGE_INTEGER AllocationSize; 737 738 if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) { 739 Status = STATUS_INVALID_DEVICE_REQUEST; 740 _SEH2_LEAVE; 741 } else { 742 Status = STATUS_SUCCESS; 743 } 744 745 /* set Mcb to it's target */ 746 if (IsMcbSymLink(Mcb)) { 747 ASSERT(Fcb->Mcb == Mcb->Target); 748 } 749 Mcb = Fcb->Mcb; 750 751 /* get user specified allocationsize aligned with BLOCK_SIZE */ 752 AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG, 753 (ULONGLONG)FAI->AllocationSize.QuadPart, 754 (ULONGLONG)BLOCK_SIZE); 755 756 if (AllocationSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) { 757 758 Status = Ext2ExpandFile(IrpContext, Vcb, Mcb, &AllocationSize); 759 Fcb->Header.AllocationSize = AllocationSize; 760 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE; 761 SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_SETINFO); 762 763 } else if (AllocationSize.QuadPart < Fcb->Header.AllocationSize.QuadPart) { 764 765 if (MmCanFileBeTruncated(&(Fcb->SectionObject), &AllocationSize)) { 766 767 /* truncate file blocks */ 768 Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &AllocationSize); 769 770 if (NT_SUCCESS(Status)) { 771 ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE); 772 } 773 774 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE; 775 Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart; 776 if (Mcb->Inode.i_size > (loff_t)AllocationSize.QuadPart) { 777 Mcb->Inode.i_size = AllocationSize.QuadPart; 778 } 779 Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size; 780 if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) { 781 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; 782 } 783 784 } else { 785 786 Status = STATUS_USER_MAPPED_FILE; 787 DbgBreak(); 788 _SEH2_LEAVE; 789 } 790 } 791 792 if (NotifyFilter) { 793 794 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 795 SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); 796 Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); 797 if (CcIsFileCached(FileObject)) { 798 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); 799 } 800 } 801 802 DEBUG(DL_IO, ("Ext2SetInformation: %wZ NewSize=%I64xh AllocationSize=%I64xh " 803 "FileSize=%I64xh VDL=%I64xh i_size=%I64xh status = %xh\n", 804 &Fcb->Mcb->ShortName, AllocationSize.QuadPart, 805 Fcb->Header.AllocationSize.QuadPart, 806 Fcb->Header.FileSize.QuadPart, Fcb->Header.ValidDataLength.QuadPart, 807 Mcb->Inode.i_size, Status)); 808 } 809 810 break; 811 812 case FileEndOfFileInformation: 813 { 814 PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer; 815 LARGE_INTEGER NewSize, OldSize, EndOfFile; 816 817 if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) { 818 Status = STATUS_INVALID_DEVICE_REQUEST; 819 _SEH2_LEAVE; 820 } else { 821 Status = STATUS_SUCCESS; 822 } 823 824 /* set Mcb to it's target */ 825 if (IsMcbSymLink(Mcb)) { 826 ASSERT(Fcb->Mcb == Mcb->Target); 827 } 828 Mcb = Fcb->Mcb; 829 830 OldSize = Fcb->Header.AllocationSize; 831 EndOfFile = FEOFI->EndOfFile; 832 833 if (IoStackLocation->Parameters.SetFile.AdvanceOnly) { 834 835 if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { 836 _SEH2_LEAVE; 837 } 838 839 if (EndOfFile.QuadPart > Fcb->Header.FileSize.QuadPart) { 840 EndOfFile.QuadPart = Fcb->Header.FileSize.QuadPart; 841 } 842 843 if (EndOfFile.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { 844 Fcb->Header.ValidDataLength.QuadPart = EndOfFile.QuadPart; 845 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE; 846 } 847 848 _SEH2_LEAVE; 849 } 850 851 NewSize.QuadPart = CEILING_ALIGNED(ULONGLONG, 852 EndOfFile.QuadPart, BLOCK_SIZE); 853 854 if (NewSize.QuadPart > OldSize.QuadPart) { 855 856 Fcb->Header.AllocationSize = NewSize; 857 Status = Ext2ExpandFile( 858 IrpContext, 859 Vcb, 860 Mcb, 861 &(Fcb->Header.AllocationSize) 862 ); 863 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE; 864 SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_SETINFO); 865 866 867 } else if (NewSize.QuadPart == OldSize.QuadPart) { 868 869 /* we are luck ;) */ 870 Status = STATUS_SUCCESS; 871 872 } else { 873 874 /* don't truncate file data since it's still being written */ 875 if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_WRITE)) { 876 877 Status = STATUS_SUCCESS; 878 879 } else { 880 881 if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &NewSize)) { 882 Status = STATUS_USER_MAPPED_FILE; 883 DbgBreak(); 884 _SEH2_LEAVE; 885 } 886 887 /* truncate file blocks */ 888 Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &NewSize); 889 890 /* restore original file size */ 891 if (NT_SUCCESS(Status)) { 892 ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE); 893 } 894 895 /* update file allocateion size */ 896 Fcb->Header.AllocationSize.QuadPart = NewSize.QuadPart; 897 898 ASSERT((loff_t)NewSize.QuadPart >= Mcb->Inode.i_size); 899 if ((loff_t)Fcb->Header.FileSize.QuadPart < Mcb->Inode.i_size) { 900 Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size; 901 } 902 if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) { 903 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; 904 } 905 906 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 907 SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); 908 } 909 910 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE; 911 } 912 913 if (NT_SUCCESS(Status)) { 914 915 Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size = EndOfFile.QuadPart; 916 if (CcIsFileCached(FileObject)) { 917 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); 918 } 919 920 if (Fcb->Header.FileSize.QuadPart >= 0x80000000 && 921 !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { 922 SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE); 923 Ext2SaveSuper(IrpContext, Vcb); 924 } 925 926 SetFlag(FileObject->Flags, FO_FILE_MODIFIED); 927 SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); 928 NotifyFilter = FILE_NOTIFY_CHANGE_SIZE; 929 } 930 931 932 Ext2SaveInode( IrpContext, Vcb, &Mcb->Inode); 933 934 DEBUG(DL_IO, ("Ext2SetInformation: FileEndOfFileInformation %wZ EndofFile=%I64xh " 935 "AllocatieonSize=%I64xh FileSize=%I64xh VDL=%I64xh i_size=%I64xh status = %xh\n", 936 &Fcb->Mcb->ShortName, EndOfFile.QuadPart, Fcb->Header.AllocationSize.QuadPart, 937 Fcb->Header.FileSize.QuadPart, Fcb->Header.ValidDataLength.QuadPart, 938 Mcb->Inode.i_size, Status)); 939 } 940 941 break; 942 943 case FileValidDataLengthInformation: 944 { 945 PFILE_VALID_DATA_LENGTH_INFORMATION FVDL = (PFILE_VALID_DATA_LENGTH_INFORMATION) Buffer; 946 LARGE_INTEGER NewVDL; 947 948 if (IsMcbDirectory(Mcb) || IsMcbSpecialFile(Mcb)) { 949 Status = STATUS_INVALID_DEVICE_REQUEST; 950 _SEH2_LEAVE; 951 } else { 952 Status = STATUS_SUCCESS; 953 } 954 955 NewVDL = FVDL->ValidDataLength; 956 if ((NewVDL.QuadPart < Fcb->Header.ValidDataLength.QuadPart)) { 957 Status = STATUS_INVALID_PARAMETER; 958 _SEH2_LEAVE; 959 } 960 if (NewVDL.QuadPart > Fcb->Header.FileSize.QuadPart) 961 NewVDL = Fcb->Header.FileSize; 962 963 if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, 964 &NewVDL)) { 965 Status = STATUS_USER_MAPPED_FILE; 966 _SEH2_LEAVE; 967 } 968 969 Fcb->Header.ValidDataLength = NewVDL; 970 FileObject->Flags |= FO_FILE_MODIFIED; 971 if (CcIsFileCached(FileObject)) { 972 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); 973 } 974 } 975 976 break; 977 978 case FileDispositionInformation: 979 { 980 PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer; 981 982 Status = Ext2SetDispositionInfo(IrpContext, Vcb, Fcb, Ccb, FDI->DeleteFile); 983 984 DEBUG(DL_INF, ( "Ext2SetInformation: SetDispositionInformation: DeleteFile=%d %wZ status = %xh\n", 985 FDI->DeleteFile, &Mcb->ShortName, Status)); 986 } 987 988 break; 989 990 case FileRenameInformation: 991 { 992 Status = Ext2SetRenameInfo(IrpContext, Vcb, Fcb, Ccb); 993 } 994 995 break; 996 997 998 case FileLinkInformation: 999 { 1000 Status = Ext2SetLinkInfo(IrpContext, Vcb, Fcb, Ccb); 1001 } 1002 1003 break; 1004 1005 // 1006 // This is the only set file information request supported on read 1007 // only file systems 1008 // 1009 case FilePositionInformation: 1010 { 1011 PFILE_POSITION_INFORMATION FilePositionInformation; 1012 1013 if (Length < sizeof(FILE_POSITION_INFORMATION)) { 1014 Status = STATUS_INVALID_PARAMETER; 1015 _SEH2_LEAVE; 1016 } 1017 1018 FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer; 1019 1020 if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) && 1021 (FilePositionInformation->CurrentByteOffset.LowPart & 1022 DeviceObject->AlignmentRequirement) ) { 1023 Status = STATUS_INVALID_PARAMETER; 1024 _SEH2_LEAVE; 1025 } 1026 1027 FileObject->CurrentByteOffset = 1028 FilePositionInformation->CurrentByteOffset; 1029 1030 Status = STATUS_SUCCESS; 1031 _SEH2_LEAVE; 1032 } 1033 1034 break; 1035 1036 default: 1037 DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n", 1038 FileInformationClass)); 1039 Status = STATUS_INVALID_PARAMETER;/* STATUS_INVALID_INFO_CLASS; */ 1040 } 1041 1042 } _SEH2_FINALLY { 1043 1044 if (FcbPagingIoResourceAcquired) { 1045 ExReleaseResourceLite(&Fcb->PagingIoResource); 1046 } 1047 1048 if (NT_SUCCESS(Status) && (NotifyFilter != 0)) { 1049 Ext2NotifyReportChange( 1050 IrpContext, 1051 Vcb, 1052 Mcb, 1053 NotifyFilter, 1054 FILE_ACTION_MODIFIED ); 1055 1056 } 1057 1058 if (FcbMainResourceAcquired) { 1059 ExReleaseResourceLite(&Fcb->MainResource); 1060 } 1061 1062 if (!IrpContext->ExceptionInProgress) { 1063 if (Status == STATUS_PENDING || 1064 Status == STATUS_CANT_WAIT ) { 1065 DbgBreak(); 1066 Status = Ext2QueueRequest(IrpContext); 1067 } else { 1068 Ext2CompleteIrpContext(IrpContext, Status); 1069 } 1070 } 1071 } _SEH2_END; 1072 1073 return Status; 1074 } 1075 1076 ULONG 1077 Ext2TotalBlocks( 1078 PEXT2_VCB Vcb, 1079 PLARGE_INTEGER Size, 1080 PULONG pMeta 1081 ) 1082 { 1083 ULONG Blocks, Meta =0, Remain; 1084 1085 Blocks = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); 1086 if (Blocks <= EXT2_NDIR_BLOCKS) 1087 goto errorout; 1088 Blocks -= EXT2_NDIR_BLOCKS; 1089 1090 Meta += 1; 1091 if (Blocks <= Vcb->max_blocks_per_layer[1]) { 1092 goto errorout; 1093 } 1094 Blocks -= Vcb->max_blocks_per_layer[1]; 1095 1096 level2: 1097 1098 if (Blocks <= Vcb->max_blocks_per_layer[2]) { 1099 Meta += 1 + ((Blocks + BLOCK_SIZE/4 - 1) >> (BLOCK_BITS - 2)); 1100 goto errorout; 1101 } 1102 Meta += 1 + BLOCK_SIZE/4; 1103 Blocks -= Vcb->max_blocks_per_layer[2]; 1104 1105 if (Blocks > Vcb->max_blocks_per_layer[3]) { 1106 Blocks = Vcb->max_blocks_per_layer[3]; 1107 } 1108 1109 ASSERT(Vcb->max_blocks_per_layer[2]); 1110 Remain = Blocks % Vcb->max_blocks_per_layer[2]; 1111 Blocks = Blocks / Vcb->max_blocks_per_layer[2]; 1112 Meta += 1 + Blocks * (1 + BLOCK_SIZE/4); 1113 if (Remain) { 1114 Blocks = Remain; 1115 goto level2; 1116 } 1117 1118 errorout: 1119 1120 if (pMeta) 1121 *pMeta = Meta; 1122 Blocks = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); 1123 return (Blocks + Meta); 1124 } 1125 1126 NTSTATUS 1127 Ext2BlockMap( 1128 IN PEXT2_IRP_CONTEXT IrpContext, 1129 IN PEXT2_VCB Vcb, 1130 IN PEXT2_MCB Mcb, 1131 IN ULONG Index, 1132 IN BOOLEAN bAlloc, 1133 OUT PULONG pBlock, 1134 OUT PULONG Number 1135 ) 1136 { 1137 NTSTATUS status; 1138 1139 if (INODE_HAS_EXTENT(&Mcb->Inode)) { 1140 status = Ext2MapExtent(IrpContext, Vcb, Mcb, Index, 1141 bAlloc, pBlock, Number ); 1142 } else { 1143 status = Ext2MapIndirect(IrpContext, Vcb, Mcb, Index, 1144 bAlloc, pBlock, Number ); 1145 } 1146 1147 return status; 1148 } 1149 1150 1151 NTSTATUS 1152 Ext2ExpandFile( 1153 PEXT2_IRP_CONTEXT IrpContext, 1154 PEXT2_VCB Vcb, 1155 PEXT2_MCB Mcb, 1156 PLARGE_INTEGER Size 1157 ) 1158 { 1159 NTSTATUS status = STATUS_SUCCESS; 1160 ULONG Start = 0; 1161 ULONG End = 0; 1162 1163 Start = (ULONG)((Mcb->Inode.i_size + BLOCK_SIZE - 1) >> BLOCK_BITS); 1164 End = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); 1165 1166 /* it's a truncate operation, not expanding */ 1167 if (Start >= End) { 1168 Size->QuadPart = ((LONGLONG) Start) << BLOCK_BITS; 1169 return STATUS_SUCCESS; 1170 } 1171 1172 /* ignore special files */ 1173 if (IsMcbSpecialFile(Mcb)) { 1174 return STATUS_INVALID_DEVICE_REQUEST; 1175 } 1176 1177 /* expandind file extents */ 1178 if (INODE_HAS_EXTENT(&Mcb->Inode)) { 1179 1180 status = Ext2ExpandExtent(IrpContext, Vcb, Mcb, Start, End, Size); 1181 1182 } else { 1183 1184 BOOLEAN do_expand; 1185 1186 #if EXT2_PRE_ALLOCATION_SUPPORT 1187 do_expand = TRUE; 1188 #else 1189 do_expand = (IrpContext->MajorFunction == IRP_MJ_WRITE) || 1190 IsMcbDirectory(Mcb); 1191 #endif 1192 if (!do_expand) 1193 goto errorout; 1194 1195 status = Ext2ExpandIndirect(IrpContext, Vcb, Mcb, Start, End, Size); 1196 } 1197 1198 errorout: 1199 return status; 1200 } 1201 1202 1203 NTSTATUS 1204 Ext2TruncateFile( 1205 PEXT2_IRP_CONTEXT IrpContext, 1206 PEXT2_VCB Vcb, 1207 PEXT2_MCB Mcb, 1208 PLARGE_INTEGER Size 1209 ) 1210 { 1211 NTSTATUS status = STATUS_SUCCESS; 1212 1213 if (INODE_HAS_EXTENT(&Mcb->Inode)) { 1214 status = Ext2TruncateExtent(IrpContext, Vcb, Mcb, Size); 1215 } else { 1216 status = Ext2TruncateIndirect(IrpContext, Vcb, Mcb, Size); 1217 } 1218 1219 /* check and clear data/meta mcb extents */ 1220 if (Size->QuadPart == 0) { 1221 1222 /* check and remove all data extents */ 1223 if (Ext2ListExtents(&Mcb->Extents)) { 1224 DbgBreak(); 1225 } 1226 Ext2ClearAllExtents(&Mcb->Extents); 1227 /* check and remove all meta extents */ 1228 if (Ext2ListExtents(&Mcb->MetaExts)) { 1229 DbgBreak(); 1230 } 1231 Ext2ClearAllExtents(&Mcb->MetaExts); 1232 ClearLongFlag(Mcb->Flags, MCB_ZONE_INITED); 1233 } 1234 1235 return status; 1236 } 1237 1238 NTSTATUS 1239 Ext2IsFileRemovable( 1240 IN PEXT2_IRP_CONTEXT IrpContext, 1241 IN PEXT2_VCB Vcb, 1242 IN PEXT2_FCB Fcb, 1243 IN PEXT2_CCB Ccb 1244 ) 1245 { 1246 PEXT2_MCB Mcb = Fcb->Mcb; 1247 1248 if (Mcb->Inode.i_ino == EXT2_ROOT_INO) { 1249 return STATUS_CANNOT_DELETE; 1250 } 1251 1252 if (IsMcbDirectory(Mcb)) { 1253 if (!Ext2IsDirectoryEmpty(IrpContext, Vcb, Mcb)) { 1254 return STATUS_DIRECTORY_NOT_EMPTY; 1255 } 1256 } 1257 1258 if (!MmFlushImageSection(&Fcb->SectionObject, 1259 MmFlushForDelete )) { 1260 return STATUS_CANNOT_DELETE; 1261 } 1262 1263 if (IsMcbDirectory(Mcb)) { 1264 FsRtlNotifyFullChangeDirectory( 1265 Vcb->NotifySync, 1266 &Vcb->NotifyList, 1267 Ccb, 1268 NULL, 1269 FALSE, 1270 FALSE, 1271 0, 1272 NULL, 1273 NULL, 1274 NULL 1275 ); 1276 } 1277 1278 return STATUS_SUCCESS; 1279 } 1280 1281 NTSTATUS 1282 Ext2SetDispositionInfo( 1283 PEXT2_IRP_CONTEXT IrpContext, 1284 PEXT2_VCB Vcb, 1285 PEXT2_FCB Fcb, 1286 PEXT2_CCB Ccb, 1287 BOOLEAN bDelete 1288 ) 1289 { 1290 PIRP Irp = IrpContext->Irp; 1291 PIO_STACK_LOCATION IrpSp; 1292 NTSTATUS status = STATUS_SUCCESS; 1293 PEXT2_MCB Mcb = Fcb->Mcb; 1294 1295 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1296 1297 DEBUG(DL_INF, ( "Ext2SetDispositionInfo: bDelete=%x\n", bDelete)); 1298 1299 if (bDelete) { 1300 1301 DEBUG(DL_INF, ( "Ext2SetDispositionInformation: Removing %wZ.\n", 1302 &Mcb->FullName)); 1303 1304 if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { 1305 /* always allow deleting on symlinks */ 1306 } else { 1307 status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb); 1308 } 1309 1310 if (NT_SUCCESS(status)) { 1311 SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING); 1312 IrpSp->FileObject->DeletePending = TRUE; 1313 } 1314 1315 } else { 1316 1317 ClearLongFlag(Fcb->Flags, FCB_DELETE_PENDING); 1318 IrpSp->FileObject->DeletePending = FALSE; 1319 } 1320 1321 return status; 1322 } 1323 1324 NTSTATUS 1325 Ext2SetRenameInfo( 1326 PEXT2_IRP_CONTEXT IrpContext, 1327 PEXT2_VCB Vcb, 1328 PEXT2_FCB Fcb, 1329 PEXT2_CCB Ccb 1330 ) 1331 { 1332 PEXT2_MCB Mcb = Fcb->Mcb; 1333 1334 PEXT2_FCB TargetDcb = NULL; /* Dcb of target directory */ 1335 PEXT2_MCB TargetMcb = NULL; 1336 PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ 1337 PEXT2_MCB ParentMcb = NULL; 1338 1339 PEXT2_FCB ExistingFcb = NULL; /* Target file Fcb if it exists*/ 1340 PEXT2_MCB ExistingMcb = NULL; 1341 1342 UNICODE_STRING FileName; 1343 1344 NTSTATUS Status; 1345 1346 PIRP Irp; 1347 PIO_STACK_LOCATION IrpSp; 1348 1349 PFILE_OBJECT FileObject; 1350 PFILE_OBJECT TargetObject; 1351 1352 struct dentry *NewEntry = NULL; 1353 1354 BOOLEAN ReplaceIfExists; 1355 BOOLEAN bMove = FALSE; 1356 BOOLEAN bTargetRemoved = FALSE; 1357 1358 BOOLEAN bFcbLockAcquired = FALSE; 1359 1360 PFILE_RENAME_INFORMATION FRI; 1361 1362 if (Ccb->SymLink) { 1363 Mcb = Ccb->SymLink; 1364 } 1365 1366 if (Mcb->Inode.i_ino == EXT2_ROOT_INO) { 1367 Status = STATUS_INVALID_PARAMETER; 1368 goto errorout; 1369 } 1370 1371 Irp = IrpContext->Irp; 1372 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1373 1374 FileObject = IrpSp->FileObject; 1375 TargetObject = IrpSp->Parameters.SetFile.FileObject; 1376 ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists; 1377 1378 FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer; 1379 1380 if (TargetObject == NULL) { 1381 1382 UNICODE_STRING NewName; 1383 1384 NewName.Buffer = FRI->FileName; 1385 NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength; 1386 1387 while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') { 1388 NewName.Buffer[NewName.Length/2 - 1] = 0; 1389 NewName.Length -= 2; 1390 } 1391 1392 while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') { 1393 NewName.Length -= 2; 1394 } 1395 1396 NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length); 1397 NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length); 1398 1399 FileName = NewName; 1400 1401 TargetMcb = Mcb->Parent; 1402 if (IsMcbSymLink(TargetMcb)) { 1403 TargetMcb = TargetMcb->Target; 1404 ASSERT(!IsMcbSymLink(TargetMcb)); 1405 } 1406 1407 if (TargetMcb == NULL || FileName.Length >= EXT2_NAME_LEN*2) { 1408 Status = STATUS_OBJECT_NAME_INVALID; 1409 goto errorout; 1410 } 1411 1412 } else { 1413 1414 TargetDcb = (PEXT2_FCB)(TargetObject->FsContext); 1415 1416 if (!TargetDcb || TargetDcb->Vcb != Vcb) { 1417 1418 DbgBreak(); 1419 1420 Status = STATUS_INVALID_PARAMETER; 1421 goto errorout; 1422 } 1423 1424 TargetMcb = TargetDcb->Mcb; 1425 FileName = TargetObject->FileName; 1426 } 1427 1428 if (FsRtlDoesNameContainWildCards(&FileName)) { 1429 Status = STATUS_OBJECT_NAME_INVALID; 1430 goto errorout; 1431 } 1432 1433 if (TargetMcb->Inode.i_ino == Mcb->Parent->Inode.i_ino) { 1434 if (FsRtlAreNamesEqual( &FileName, 1435 &(Mcb->ShortName), 1436 FALSE, 1437 NULL )) { 1438 Status = STATUS_SUCCESS; 1439 goto errorout; 1440 } 1441 } else { 1442 bMove = TRUE; 1443 } 1444 1445 if (!bFcbLockAcquired) { 1446 ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); 1447 bFcbLockAcquired = TRUE; 1448 } 1449 1450 TargetDcb = TargetMcb->Fcb; 1451 if (TargetDcb == NULL) { 1452 TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); 1453 } 1454 if (TargetDcb) { 1455 Ext2ReferXcb(&TargetDcb->ReferenceCount); 1456 } 1457 1458 ParentMcb = Mcb->Parent; 1459 ParentDcb = ParentMcb->Fcb; 1460 1461 if ((TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino)) { 1462 1463 if (ParentDcb == NULL) { 1464 ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); 1465 } 1466 } 1467 if (ParentDcb) { 1468 Ext2ReferXcb(&ParentDcb->ReferenceCount); 1469 } 1470 1471 if (bFcbLockAcquired) { 1472 ExReleaseResourceLite(&Vcb->FcbLock); 1473 bFcbLockAcquired = FALSE; 1474 } 1475 1476 if (!TargetDcb || !ParentDcb) { 1477 Status = STATUS_INSUFFICIENT_RESOURCES; 1478 goto errorout; 1479 } 1480 1481 DEBUG(DL_RES, ("Ext2SetRenameInfo: rename %wZ to %wZ\\%wZ\n", 1482 &Mcb->FullName, &TargetMcb->FullName, &FileName)); 1483 1484 Status = Ext2LookupFile( 1485 IrpContext, 1486 Vcb, 1487 &FileName, 1488 TargetMcb, 1489 &ExistingMcb, 1490 0 1491 ); 1492 1493 if (NT_SUCCESS(Status) && ExistingMcb != Mcb) { 1494 1495 if (!ReplaceIfExists) { 1496 1497 Status = STATUS_OBJECT_NAME_COLLISION; 1498 DEBUG(DL_RES, ("Ext2SetRenameInfo: Target file %wZ exists\n", 1499 &ExistingMcb->FullName)); 1500 goto errorout; 1501 1502 } else { 1503 1504 if ( (ExistingFcb = ExistingMcb->Fcb) && !IsMcbSymLink(ExistingMcb) ) { 1505 1506 Status = Ext2IsFileRemovable(IrpContext, Vcb, ExistingFcb, Ccb); 1507 if (!NT_SUCCESS(Status)) { 1508 DEBUG(DL_REN, ("Ext2SetRenameInfo: Target file %wZ cannot be removed.\n", 1509 &ExistingMcb->FullName)); 1510 goto errorout; 1511 } 1512 } 1513 1514 Status = Ext2DeleteFile(IrpContext, Vcb, ExistingFcb, ExistingMcb); 1515 if (!NT_SUCCESS(Status)) { 1516 DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to delete %wZ with status: %xh.\n", 1517 &FileName, Status)); 1518 1519 goto errorout; 1520 } 1521 1522 bTargetRemoved = TRUE; 1523 } 1524 } 1525 1526 /* remove directory entry of old name */ 1527 Status = Ext2RemoveEntry(IrpContext, Vcb, ParentDcb, Mcb); 1528 if (!NT_SUCCESS(Status)) { 1529 DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to remove entry %wZ with status %xh.\n", 1530 &Mcb->FullName, Status)); 1531 DbgBreak(); 1532 goto errorout; 1533 } 1534 1535 /* add new entry for new target name */ 1536 Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, &NewEntry); 1537 if (!NT_SUCCESS(Status)) { 1538 DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to add entry for %wZ with status: %xh.\n", 1539 &FileName, Status)); 1540 Ext2AddEntry(IrpContext, Vcb, ParentDcb, &Mcb->Inode, &Mcb->ShortName, &NewEntry); 1541 goto errorout; 1542 } 1543 1544 /* correct the inode number in .. entry */ 1545 if (IsMcbDirectory(Mcb)) { 1546 Status = Ext2SetParentEntry( 1547 IrpContext, Vcb, Fcb, 1548 ParentMcb->Inode.i_ino, 1549 TargetMcb->Inode.i_ino ); 1550 if (!NT_SUCCESS(Status)) { 1551 DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to set parent refer of %wZ with %xh.\n", 1552 &Mcb->FullName, Status)); 1553 DbgBreak(); 1554 goto errorout; 1555 } 1556 } 1557 1558 /* Update current dentry from the newly created one. We need keep the original 1559 dentry to assure children's links are valid if current entry is a directory */ 1560 if (Mcb->de) { 1561 char *np = Mcb->de->d_name.name; 1562 *(Mcb->de) = *NewEntry; 1563 NewEntry->d_name.name = np; 1564 } 1565 1566 if (bTargetRemoved) { 1567 Ext2NotifyReportChange( 1568 IrpContext, 1569 Vcb, 1570 ExistingMcb, 1571 (IsMcbDirectory(ExistingMcb) ? 1572 FILE_NOTIFY_CHANGE_DIR_NAME : 1573 FILE_NOTIFY_CHANGE_FILE_NAME ), 1574 FILE_ACTION_REMOVED); 1575 } 1576 1577 if (NT_SUCCESS(Status)) { 1578 1579 if (bMove) { 1580 Ext2NotifyReportChange( 1581 IrpContext, 1582 Vcb, 1583 Mcb, 1584 (IsDirectory(Fcb) ? 1585 FILE_NOTIFY_CHANGE_DIR_NAME : 1586 FILE_NOTIFY_CHANGE_FILE_NAME ), 1587 FILE_ACTION_REMOVED); 1588 1589 } else { 1590 Ext2NotifyReportChange( 1591 IrpContext, 1592 Vcb, 1593 Mcb, 1594 (IsDirectory(Fcb) ? 1595 FILE_NOTIFY_CHANGE_DIR_NAME : 1596 FILE_NOTIFY_CHANGE_FILE_NAME ), 1597 FILE_ACTION_RENAMED_OLD_NAME); 1598 1599 } 1600 1601 if (TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino) { 1602 Ext2RemoveMcb(Vcb, Mcb); 1603 Ext2InsertMcb(Vcb, TargetMcb, Mcb); 1604 } 1605 1606 if (!Ext2BuildName( &Mcb->ShortName, 1607 &FileName, NULL )) { 1608 Status = STATUS_INSUFFICIENT_RESOURCES; 1609 goto errorout; 1610 } 1611 1612 if (!Ext2BuildName( &Mcb->FullName, 1613 &FileName, 1614 &TargetMcb->FullName)) { 1615 Status = STATUS_INSUFFICIENT_RESOURCES; 1616 goto errorout; 1617 } 1618 1619 if (bMove) { 1620 Ext2NotifyReportChange( 1621 IrpContext, 1622 Vcb, 1623 Mcb, 1624 (IsDirectory(Fcb) ? 1625 FILE_NOTIFY_CHANGE_DIR_NAME : 1626 FILE_NOTIFY_CHANGE_FILE_NAME ), 1627 FILE_ACTION_ADDED); 1628 } else { 1629 Ext2NotifyReportChange( 1630 IrpContext, 1631 Vcb, 1632 Mcb, 1633 (IsDirectory(Fcb) ? 1634 FILE_NOTIFY_CHANGE_DIR_NAME : 1635 FILE_NOTIFY_CHANGE_FILE_NAME ), 1636 FILE_ACTION_RENAMED_NEW_NAME ); 1637 } 1638 } 1639 1640 errorout: 1641 1642 if (bFcbLockAcquired) { 1643 ExReleaseResourceLite(&Vcb->FcbLock); 1644 bFcbLockAcquired = FALSE; 1645 } 1646 1647 if (NewEntry) 1648 Ext2FreeEntry(NewEntry); 1649 1650 if (TargetDcb) { 1651 Ext2ReleaseFcb(TargetDcb); 1652 } 1653 1654 if (ParentDcb) { 1655 Ext2ReleaseFcb(ParentDcb); 1656 } 1657 1658 if (ExistingMcb) 1659 Ext2DerefMcb(ExistingMcb); 1660 1661 return Status; 1662 } 1663 1664 NTSTATUS 1665 Ext2SetLinkInfo( 1666 PEXT2_IRP_CONTEXT IrpContext, 1667 PEXT2_VCB Vcb, 1668 PEXT2_FCB Fcb, 1669 PEXT2_CCB Ccb 1670 ) 1671 { 1672 PEXT2_MCB Mcb = Fcb->Mcb; 1673 1674 PEXT2_FCB TargetDcb = NULL; /* Dcb of target directory */ 1675 PEXT2_MCB TargetMcb = NULL; 1676 PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ 1677 PEXT2_MCB ParentMcb = NULL; 1678 1679 PEXT2_FCB ExistingFcb = NULL; /* Target file Fcb if it exists*/ 1680 PEXT2_MCB ExistingMcb = NULL; 1681 PEXT2_MCB LinkMcb = NULL; /* Mcb for new hardlink */ 1682 1683 UNICODE_STRING FileName; 1684 1685 NTSTATUS Status; 1686 1687 PIRP Irp; 1688 PIO_STACK_LOCATION IrpSp; 1689 1690 PFILE_OBJECT FileObject; 1691 PFILE_OBJECT TargetObject; 1692 1693 BOOLEAN ReplaceIfExists; 1694 BOOLEAN bTargetRemoved = FALSE; 1695 1696 BOOLEAN bFcbLockAcquired = FALSE; 1697 1698 PFILE_LINK_INFORMATION FLI; 1699 1700 if (Ccb->SymLink) { 1701 Mcb = Ccb->SymLink; 1702 } 1703 1704 if (IsMcbDirectory(Mcb)) { 1705 Status = STATUS_INVALID_PARAMETER; 1706 goto errorout; 1707 } 1708 1709 Irp = IrpContext->Irp; 1710 IrpSp = IoGetCurrentIrpStackLocation(Irp); 1711 1712 FileObject = IrpSp->FileObject; 1713 TargetObject = IrpSp->Parameters.SetFile.FileObject; 1714 ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists; 1715 1716 FLI = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer; 1717 1718 if (TargetObject == NULL) { 1719 1720 UNICODE_STRING NewName; 1721 1722 NewName.Buffer = FLI->FileName; 1723 NewName.MaximumLength = NewName.Length = (USHORT)FLI->FileNameLength; 1724 1725 while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') { 1726 NewName.Buffer[NewName.Length/2 - 1] = 0; 1727 NewName.Length -= 2; 1728 } 1729 1730 while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') { 1731 NewName.Length -= 2; 1732 } 1733 1734 NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length); 1735 NewName.Length = (USHORT)(FLI->FileNameLength - NewName.Length); 1736 1737 FileName = NewName; 1738 1739 TargetMcb = Mcb->Parent; 1740 if (IsMcbSymLink(TargetMcb)) { 1741 TargetMcb = TargetMcb->Target; 1742 ASSERT(!IsMcbSymLink(TargetMcb)); 1743 } 1744 1745 if (TargetMcb == NULL || FileName.Length >= EXT2_NAME_LEN*2) { 1746 Status = STATUS_OBJECT_NAME_INVALID; 1747 goto errorout; 1748 } 1749 1750 } else { 1751 1752 TargetDcb = (PEXT2_FCB)(TargetObject->FsContext); 1753 if (!TargetDcb || TargetDcb->Vcb != Vcb) { 1754 DbgBreak(); 1755 Status = STATUS_INVALID_PARAMETER; 1756 goto errorout; 1757 } 1758 1759 TargetMcb = TargetDcb->Mcb; 1760 FileName = TargetObject->FileName; 1761 } 1762 1763 if (FsRtlDoesNameContainWildCards(&FileName)) { 1764 Status = STATUS_OBJECT_NAME_INVALID; 1765 goto errorout; 1766 } 1767 1768 if (TargetMcb->Inode.i_ino == Mcb->Parent->Inode.i_ino) { 1769 if (FsRtlAreNamesEqual( &FileName, 1770 &(Mcb->ShortName), 1771 FALSE, 1772 NULL )) { 1773 Status = STATUS_SUCCESS; 1774 goto errorout; 1775 } 1776 } 1777 1778 ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); 1779 bFcbLockAcquired = TRUE; 1780 1781 TargetDcb = TargetMcb->Fcb; 1782 if (TargetDcb == NULL) { 1783 TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); 1784 } 1785 if (TargetDcb) { 1786 Ext2ReferXcb(&TargetDcb->ReferenceCount); 1787 } 1788 1789 ParentMcb = Mcb->Parent; 1790 ParentDcb = ParentMcb->Fcb; 1791 1792 if ((TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino)) { 1793 1794 if (ParentDcb == NULL) { 1795 ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); 1796 } 1797 } 1798 if (ParentDcb) { 1799 Ext2ReferXcb(&ParentDcb->ReferenceCount); 1800 } 1801 1802 if (bFcbLockAcquired) { 1803 ExReleaseResourceLite(&Vcb->FcbLock); 1804 bFcbLockAcquired = FALSE; 1805 } 1806 1807 if (!TargetDcb || !ParentDcb) { 1808 Status = STATUS_INSUFFICIENT_RESOURCES; 1809 goto errorout; 1810 } 1811 1812 DEBUG(DL_RES, ("Ext2SetLinkInfo: %wZ\\%wZ -> %wZ\n", 1813 &TargetMcb->FullName, &FileName, &Mcb->FullName)); 1814 1815 Status = Ext2LookupFile(IrpContext, Vcb, &FileName, 1816 TargetMcb, &ExistingMcb, 0); 1817 if (NT_SUCCESS(Status) && ExistingMcb != Mcb) { 1818 1819 if (!ReplaceIfExists) { 1820 1821 Status = STATUS_OBJECT_NAME_COLLISION; 1822 DEBUG(DL_RES, ("Ext2SetRenameInfo: Target file %wZ exists\n", 1823 &ExistingMcb->FullName)); 1824 goto errorout; 1825 1826 } else { 1827 1828 if ( (ExistingFcb = ExistingMcb->Fcb) && !IsMcbSymLink(ExistingMcb) ) { 1829 Status = Ext2IsFileRemovable(IrpContext, Vcb, ExistingFcb, Ccb); 1830 if (!NT_SUCCESS(Status)) { 1831 DEBUG(DL_REN, ("Ext2SetRenameInfo: Target file %wZ cannot be removed.\n", 1832 &ExistingMcb->FullName)); 1833 goto errorout; 1834 } 1835 } 1836 1837 Status = Ext2DeleteFile(IrpContext, Vcb, ExistingFcb, ExistingMcb); 1838 if (!NT_SUCCESS(Status)) { 1839 DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to delete %wZ with status: %xh.\n", 1840 &FileName, Status)); 1841 1842 goto errorout; 1843 } 1844 bTargetRemoved = TRUE; 1845 } 1846 } 1847 1848 /* add new entry for new target name */ 1849 Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, NULL); 1850 if (!NT_SUCCESS(Status)) { 1851 DEBUG(DL_REN, ("Ext2SetLinkInfo: Failed to add entry for %wZ with status: %xh.\n", 1852 &FileName, Status)); 1853 goto errorout; 1854 } 1855 1856 if (bTargetRemoved) { 1857 Ext2NotifyReportChange( 1858 IrpContext, 1859 Vcb, 1860 ExistingMcb, 1861 (IsMcbDirectory(ExistingMcb) ? 1862 FILE_NOTIFY_CHANGE_DIR_NAME : 1863 FILE_NOTIFY_CHANGE_FILE_NAME ), 1864 FILE_ACTION_REMOVED); 1865 } 1866 1867 if (NT_SUCCESS(Status)) { 1868 1869 Ext2LookupFile(IrpContext, Vcb, &FileName, TargetMcb, &LinkMcb, 0); 1870 if (!LinkMcb) 1871 goto errorout; 1872 1873 Ext2NotifyReportChange( 1874 IrpContext, 1875 Vcb, 1876 LinkMcb, 1877 FILE_NOTIFY_CHANGE_FILE_NAME, 1878 FILE_ACTION_ADDED); 1879 } 1880 1881 errorout: 1882 1883 if (bFcbLockAcquired) { 1884 ExReleaseResourceLite(&Vcb->FcbLock); 1885 bFcbLockAcquired = FALSE; 1886 } 1887 1888 if (TargetDcb) { 1889 Ext2ReleaseFcb(TargetDcb); 1890 } 1891 1892 if (ParentDcb) { 1893 Ext2ReleaseFcb(ParentDcb); 1894 } 1895 1896 if (ExistingMcb) 1897 Ext2DerefMcb(ExistingMcb); 1898 1899 if (LinkMcb) 1900 Ext2DerefMcb(LinkMcb); 1901 1902 return Status; 1903 } 1904 1905 ULONG 1906 Ext2InodeType(PEXT2_MCB Mcb) 1907 { 1908 if (IsMcbSymLink(Mcb)) { 1909 return EXT2_FT_SYMLINK; 1910 } 1911 1912 if (IsMcbDirectory(Mcb)) { 1913 return EXT2_FT_DIR; 1914 } 1915 1916 return EXT2_FT_REG_FILE; 1917 } 1918 1919 NTSTATUS 1920 Ext2DeleteFile( 1921 PEXT2_IRP_CONTEXT IrpContext, 1922 PEXT2_VCB Vcb, 1923 PEXT2_FCB Fcb, 1924 PEXT2_MCB Mcb 1925 ) 1926 { 1927 PEXT2_FCB Dcb = NULL; 1928 1929 NTSTATUS Status = STATUS_UNSUCCESSFUL; 1930 1931 BOOLEAN VcbResourceAcquired = FALSE; 1932 BOOLEAN FcbPagingIoAcquired = FALSE; 1933 BOOLEAN FcbResourceAcquired = FALSE; 1934 BOOLEAN DcbResourceAcquired = FALSE; 1935 1936 LARGE_INTEGER Size; 1937 LARGE_INTEGER SysTime; 1938 1939 BOOLEAN bFcbLockAcquired = FALSE; 1940 1941 DEBUG(DL_INF, ( "Ext2DeleteFile: File %wZ (%xh) will be deleted!\n", 1942 &Mcb->FullName, Mcb->Inode.i_ino)); 1943 1944 if (IsFlagOn(Mcb->Flags, MCB_FILE_DELETED)) { 1945 return STATUS_SUCCESS; 1946 } 1947 1948 if (!IsMcbSymLink(Mcb) && IsMcbDirectory(Mcb)) { 1949 if (!Ext2IsDirectoryEmpty(IrpContext, Vcb, Mcb)) { 1950 return STATUS_DIRECTORY_NOT_EMPTY; 1951 } 1952 } 1953 1954 _SEH2_TRY { 1955 1956 Ext2ReferMcb(Mcb); 1957 1958 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); 1959 VcbResourceAcquired = TRUE; 1960 1961 ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); 1962 bFcbLockAcquired = TRUE; 1963 1964 /* Mcb->Parent could be NULL when working with layered file systems */ 1965 if (Mcb->Parent) { 1966 Dcb = Mcb->Parent->Fcb; 1967 if (!Dcb) 1968 Dcb = Ext2AllocateFcb(Vcb, Mcb->Parent); 1969 } 1970 if (Dcb) 1971 Ext2ReferXcb(&Dcb->ReferenceCount); 1972 1973 if (bFcbLockAcquired) { 1974 ExReleaseResourceLite(&Vcb->FcbLock); 1975 bFcbLockAcquired = FALSE; 1976 } 1977 1978 if (Dcb) { 1979 DcbResourceAcquired = 1980 ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); 1981 1982 /* remove it's entry form it's parent */ 1983 Status = Ext2RemoveEntry(IrpContext, Vcb, Dcb, Mcb); 1984 } 1985 1986 if (NT_SUCCESS(Status)) { 1987 1988 SetFlag(Mcb->Flags, MCB_FILE_DELETED); 1989 Ext2RemoveMcb(Vcb, Mcb); 1990 1991 if (Fcb) { 1992 FcbResourceAcquired = 1993 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); 1994 1995 FcbPagingIoAcquired = 1996 ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); 1997 } 1998 1999 if (DcbResourceAcquired) { 2000 ExReleaseResourceLite(&Dcb->MainResource); 2001 DcbResourceAcquired = FALSE; 2002 } 2003 2004 if (VcbResourceAcquired) { 2005 ExReleaseResourceLite(&Vcb->MainResource); 2006 VcbResourceAcquired = FALSE; 2007 } 2008 2009 if (IsMcbSymLink(Mcb)) { 2010 if (Mcb->Inode.i_nlink > 0) { 2011 Status = STATUS_CANNOT_DELETE; 2012 _SEH2_LEAVE; 2013 } 2014 } else if (!IsMcbDirectory(Mcb)) { 2015 if (Mcb->Inode.i_nlink > 0) { 2016 _SEH2_LEAVE; 2017 } 2018 } else { 2019 if (Mcb->Inode.i_nlink >= 2) { 2020 _SEH2_LEAVE; 2021 } 2022 } 2023 2024 if (S_ISLNK(Mcb->Inode.i_mode)) { 2025 2026 /* for symlink, we should do differenctly */ 2027 if (Mcb->Inode.i_size > EXT2_LINKLEN_IN_INODE) { 2028 Size.QuadPart = (LONGLONG)0; 2029 Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &Size); 2030 } 2031 2032 } else { 2033 2034 /* truncate file size */ 2035 Size.QuadPart = (LONGLONG)0; 2036 Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &Size); 2037 2038 /* check file offset mappings */ 2039 DEBUG(DL_EXT, ("Ext2DeleteFile ...: %wZ\n", &Mcb->FullName)); 2040 2041 if (Fcb) { 2042 Fcb->Header.AllocationSize.QuadPart = Size.QuadPart; 2043 if (Fcb->Header.FileSize.QuadPart > Size.QuadPart) { 2044 Fcb->Header.FileSize.QuadPart = Size.QuadPart; 2045 Fcb->Mcb->Inode.i_size = Size.QuadPart; 2046 } 2047 if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) { 2048 Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; 2049 } 2050 } else if (Mcb) { 2051 /* Update the inode's data length . It should be ZERO if succeeds. */ 2052 if (Mcb->Inode.i_size > (loff_t)Size.QuadPart) { 2053 Mcb->Inode.i_size = Size.QuadPart; 2054 } 2055 } 2056 } 2057 2058 /* set delete time and free the inode */ 2059 KeQuerySystemTime(&SysTime); 2060 Mcb->Inode.i_nlink = 0; 2061 Mcb->Inode.i_dtime = Ext2LinuxTime(SysTime); 2062 Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); 2063 Ext2FreeInode(IrpContext, Vcb, Mcb->Inode.i_ino, Ext2InodeType(Mcb)); 2064 } 2065 2066 } _SEH2_FINALLY { 2067 2068 if (FcbPagingIoAcquired) { 2069 ExReleaseResourceLite(&Fcb->PagingIoResource); 2070 } 2071 2072 if (FcbResourceAcquired) { 2073 ExReleaseResourceLite(&Fcb->MainResource); 2074 } 2075 2076 if (DcbResourceAcquired) { 2077 ExReleaseResourceLite(&Dcb->MainResource); 2078 } 2079 2080 if (bFcbLockAcquired) { 2081 ExReleaseResourceLite(&Vcb->FcbLock); 2082 } 2083 2084 if (VcbResourceAcquired) { 2085 ExReleaseResourceLite(&Vcb->MainResource); 2086 } 2087 2088 if (Dcb) { 2089 Ext2ReleaseFcb(Dcb); 2090 } 2091 2092 Ext2DerefMcb(Mcb); 2093 } _SEH2_END; 2094 2095 DEBUG(DL_INF, ( "Ext2DeleteFile: %wZ Succeed... EXT2SB->S_FREE_BLOCKS = %I64xh .\n", 2096 &Mcb->FullName, ext3_free_blocks_count(SUPER_BLOCK))); 2097 2098 return Status; 2099 } 2100