1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 FileInfo.c 8 9 Abstract: 10 11 This module implements the File Information routines for Cdfs called by 12 the Fsd/Fsp dispatch drivers. 13 14 15 --*/ 16 17 #include "cdprocs.h" 18 19 // 20 // The Bug check file id for this module 21 // 22 23 #define BugCheckFileId (CDFS_BUG_CHECK_FILEINFO) 24 25 // 26 // Local support routines 27 // 28 29 VOID 30 CdQueryBasicInfo ( 31 _In_ PIRP_CONTEXT IrpContext, 32 _In_ PFCB Fcb, 33 _Out_ PFILE_BASIC_INFORMATION Buffer, 34 _Inout_ PULONG Length 35 ); 36 37 VOID 38 CdQueryStandardInfo ( 39 _In_ PIRP_CONTEXT IrpContext, 40 _In_ PFCB Fcb, 41 _Out_ PFILE_STANDARD_INFORMATION Buffer, 42 _Inout_ PULONG Length 43 ); 44 45 VOID 46 CdQueryInternalInfo ( 47 _In_ PIRP_CONTEXT IrpContext, 48 _In_ PFCB Fcb, 49 _Out_ PFILE_INTERNAL_INFORMATION Buffer, 50 _Inout_ PULONG Length 51 ); 52 53 VOID 54 CdQueryEaInfo ( 55 _In_ PIRP_CONTEXT IrpContext, 56 _In_ PFCB Fcb, 57 _Out_ PFILE_EA_INFORMATION Buffer, 58 _Inout_ PULONG Length 59 ); 60 61 VOID 62 CdQueryPositionInfo ( 63 _In_ PIRP_CONTEXT IrpContext, 64 _In_ PFILE_OBJECT FileObject, 65 _Out_ PFILE_POSITION_INFORMATION Buffer, 66 _Inout_ PULONG Length 67 ); 68 69 NTSTATUS 70 CdQueryNameInfo ( 71 _In_ PIRP_CONTEXT IrpContext, 72 _In_ PFILE_OBJECT FileObject, 73 _Out_ PFILE_NAME_INFORMATION Buffer, 74 _Inout_ PULONG Length 75 ); 76 77 _Requires_lock_held_(_Global_critical_region_) 78 NTSTATUS 79 CdQueryAlternateNameInfo ( 80 _In_ PIRP_CONTEXT IrpContext, 81 _In_ PFCB Fcb, 82 _In_ PCCB Ccb, 83 _Out_ PFILE_NAME_INFORMATION Buffer, 84 _Inout_ PULONG Length 85 ); 86 87 VOID 88 CdQueryNetworkInfo ( 89 _In_ PIRP_CONTEXT IrpContext, 90 _In_ PFCB Fcb, 91 _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer, 92 _Inout_ PULONG Length 93 ); 94 95 #ifdef ALLOC_PRAGMA 96 #pragma alloc_text(PAGE, CdCommonQueryInfo) 97 #pragma alloc_text(PAGE, CdCommonSetInfo) 98 #pragma alloc_text(PAGE, CdFastQueryBasicInfo) 99 #pragma alloc_text(PAGE, CdFastQueryStdInfo) 100 #pragma alloc_text(PAGE, CdFastQueryNetworkInfo) 101 #pragma alloc_text(PAGE, CdQueryAlternateNameInfo) 102 #pragma alloc_text(PAGE, CdQueryBasicInfo) 103 #pragma alloc_text(PAGE, CdQueryEaInfo) 104 #pragma alloc_text(PAGE, CdQueryInternalInfo) 105 #pragma alloc_text(PAGE, CdQueryNameInfo) 106 #pragma alloc_text(PAGE, CdQueryNetworkInfo) 107 #pragma alloc_text(PAGE, CdQueryPositionInfo) 108 #pragma alloc_text(PAGE, CdQueryStandardInfo) 109 #endif 110 111 112 _Requires_lock_held_(_Global_critical_region_) 113 NTSTATUS 114 CdCommonQueryInfo ( 115 _Inout_ PIRP_CONTEXT IrpContext, 116 _Inout_ PIRP Irp 117 ) 118 119 /*++ 120 121 Routine Description: 122 123 This is the common routine for query file information called by both the 124 fsd and fsp threads. 125 126 Arguments: 127 128 Irp - Supplies the Irp to process. 129 130 Return Value: 131 132 NTSTATUS - The return status for this operation. 133 134 --*/ 135 136 { 137 NTSTATUS Status = STATUS_SUCCESS; 138 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 139 140 ULONG Length; 141 FILE_INFORMATION_CLASS FileInformationClass; 142 PFILE_ALL_INFORMATION Buffer; 143 144 TYPE_OF_OPEN TypeOfOpen; 145 PFCB Fcb; 146 PCCB Ccb; 147 148 BOOLEAN ReleaseFcb = FALSE; 149 150 PAGED_CODE(); 151 152 // 153 // Reference our input parameters to make things easier 154 // 155 156 Length = IrpSp->Parameters.QueryFile.Length; 157 FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass; 158 Buffer = Irp->AssociatedIrp.SystemBuffer; 159 160 // 161 // Decode the file object 162 // 163 164 TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); 165 166 // 167 // Use a try-finally to facilitate cleanup. 168 // 169 170 _SEH2_TRY { 171 172 // 173 // We only support query on file and directory handles. 174 // 175 176 switch (TypeOfOpen) { 177 178 case UserDirectoryOpen : 179 case UserFileOpen : 180 181 // 182 // Acquire shared access to this file. NOTE that this could be 183 // a recursive acquire, if we already preacquired in 184 // CdAcquireForCreateSection(). 185 // 186 187 CdAcquireFileShared( IrpContext, Fcb ); 188 ReleaseFcb = TRUE; 189 190 // 191 // Make sure we have the correct sizes for a directory. 192 // 193 194 if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) { 195 196 NT_ASSERT( TypeOfOpen == UserDirectoryOpen ); 197 CdVerifyOrCreateDirStreamFile( IrpContext, Fcb); 198 } 199 200 // 201 // Make sure the Fcb is in a usable condition. This will raise 202 // an error condition if the volume is unusable 203 // 204 205 CdVerifyFcbOperation( IrpContext, Fcb ); 206 207 // 208 // Based on the information class we'll do different 209 // actions. Each of hte procedures that we're calling fills 210 // up the output buffer, if possible. They will raise the 211 // status STATUS_BUFFER_OVERFLOW for an insufficient buffer. 212 // This is considered a somewhat unusual case and is handled 213 // more cleanly with the exception mechanism rather than 214 // testing a return status value for each call. 215 // 216 217 switch (FileInformationClass) { 218 219 case FileAllInformation: 220 221 // 222 // We don't allow this operation on a file opened by file Id. 223 // 224 225 if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) { 226 227 Status = STATUS_INVALID_PARAMETER; 228 break; 229 } 230 231 // 232 // In this case go ahead and call the individual routines to 233 // fill in the buffer. Only the name routine will 234 // pointer to the output buffer and then call the 235 // individual routines to fill in the buffer. 236 // 237 238 Length -= (sizeof( FILE_ACCESS_INFORMATION ) + 239 sizeof( FILE_MODE_INFORMATION ) + 240 sizeof( FILE_ALIGNMENT_INFORMATION )); 241 242 CdQueryBasicInfo( IrpContext, Fcb, &Buffer->BasicInformation, &Length ); 243 CdQueryStandardInfo( IrpContext, Fcb, &Buffer->StandardInformation, &Length ); 244 CdQueryInternalInfo( IrpContext, Fcb, &Buffer->InternalInformation, &Length ); 245 CdQueryEaInfo( IrpContext, Fcb, &Buffer->EaInformation, &Length ); 246 CdQueryPositionInfo( IrpContext, IrpSp->FileObject, &Buffer->PositionInformation, &Length ); 247 Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, &Buffer->NameInformation, &Length ); 248 249 break; 250 251 case FileBasicInformation: 252 253 CdQueryBasicInfo( IrpContext, Fcb, (PFILE_BASIC_INFORMATION) Buffer, &Length ); 254 break; 255 256 case FileStandardInformation: 257 258 CdQueryStandardInfo( IrpContext, Fcb, (PFILE_STANDARD_INFORMATION) Buffer, &Length ); 259 break; 260 261 case FileInternalInformation: 262 263 CdQueryInternalInfo( IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION) Buffer, &Length ); 264 break; 265 266 case FileEaInformation: 267 268 CdQueryEaInfo( IrpContext, Fcb, (PFILE_EA_INFORMATION) Buffer, &Length ); 269 break; 270 271 case FilePositionInformation: 272 273 CdQueryPositionInfo( IrpContext, IrpSp->FileObject, (PFILE_POSITION_INFORMATION) Buffer, &Length ); 274 break; 275 276 case FileNameInformation: 277 278 // 279 // We don't allow this operation on a file opened by file Id. 280 // 281 282 if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) { 283 284 Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, (PFILE_NAME_INFORMATION) Buffer, &Length ); 285 286 } else { 287 288 Status = STATUS_INVALID_PARAMETER; 289 } 290 291 break; 292 293 case FileAlternateNameInformation: 294 295 if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) { 296 297 Status = CdQueryAlternateNameInfo( IrpContext, Fcb, Ccb, (PFILE_NAME_INFORMATION) Buffer, &Length ); 298 299 } else { 300 301 Status = STATUS_INVALID_PARAMETER; 302 } 303 304 break; 305 306 case FileNetworkOpenInformation: 307 308 CdQueryNetworkInfo( IrpContext, Fcb, (PFILE_NETWORK_OPEN_INFORMATION) Buffer, &Length ); 309 break; 310 311 default : 312 313 Status = STATUS_INVALID_PARAMETER; 314 } 315 316 break; 317 318 default : 319 320 Status = STATUS_INVALID_PARAMETER; 321 } 322 323 // 324 // Set the information field to the number of bytes actually filled in 325 // and then complete the request 326 // 327 328 Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length; 329 330 } _SEH2_FINALLY { 331 332 // 333 // Release the file. 334 // 335 336 if (ReleaseFcb) { 337 338 CdReleaseFile( IrpContext, Fcb ); 339 } 340 } _SEH2_END; 341 342 // 343 // Complete the request if we didn't raise. 344 // 345 346 CdCompleteRequest( IrpContext, Irp, Status ); 347 348 return Status; 349 } 350 351 352 _Requires_lock_held_(_Global_critical_region_) 353 NTSTATUS 354 CdCommonSetInfo ( 355 _Inout_ PIRP_CONTEXT IrpContext, 356 _Inout_ PIRP Irp 357 ) 358 359 /*++ 360 361 Routine Description: 362 363 This is the common routine for set file information called by both the 364 fsd and fsp threads. We only support operations which set the file position. 365 366 Arguments: 367 368 Irp - Supplies the Irp to process. 369 370 Return Value: 371 372 NTSTATUS - The return status for this operation. 373 374 --*/ 375 376 { 377 NTSTATUS Status = STATUS_INVALID_PARAMETER; 378 379 TYPE_OF_OPEN TypeOfOpen; 380 PFCB Fcb; 381 PCCB Ccb; 382 383 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 384 385 PFILE_POSITION_INFORMATION Buffer; 386 387 PAGED_CODE(); 388 389 // 390 // Decode the file object 391 // 392 393 TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); 394 395 // 396 // We only support a SetPositionInformation on a user file. 397 // 398 399 if ((TypeOfOpen != UserFileOpen) || 400 (IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) { 401 402 CdCompleteRequest( IrpContext, Irp, Status ); 403 return Status; 404 } 405 406 // 407 // Acquire shared access to this file. 408 // 409 410 CdAcquireFileShared( IrpContext, Fcb ); 411 412 _SEH2_TRY { 413 414 // 415 // Make sure the Fcb is in a usable condition. This 416 // will raise an error condition if the fcb is unusable 417 // 418 419 CdVerifyFcbOperation( IrpContext, Fcb ); 420 421 Buffer = Irp->AssociatedIrp.SystemBuffer; 422 423 // 424 // Check if the file does not use intermediate buffering. If it 425 // does not use intermediate buffering then the new position we're 426 // supplied must be aligned properly for the device 427 // 428 429 if (FlagOn( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) && 430 ((Buffer->CurrentByteOffset.LowPart & Fcb->Vcb->BlockMask) != 0)) { 431 432 try_return( NOTHING ); 433 } 434 435 // 436 // The input parameter is fine so set the current byte offset and 437 // complete the request 438 // 439 440 // 441 // Lock the Fcb to provide synchronization. 442 // 443 444 CdLockFcb( IrpContext, Fcb ); 445 IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset; 446 CdUnlockFcb( IrpContext, Fcb ); 447 448 Status = STATUS_SUCCESS; 449 450 try_exit: NOTHING; 451 } _SEH2_FINALLY { 452 453 CdReleaseFile( IrpContext, Fcb ); 454 } _SEH2_END; 455 456 // 457 // Complete the request if there was no raise. 458 // 459 460 CdCompleteRequest( IrpContext, Irp, Status ); 461 return Status; 462 } 463 464 465 _Function_class_(FAST_IO_QUERY_BASIC_INFO) 466 _IRQL_requires_same_ 467 _Success_(return != FALSE) 468 BOOLEAN 469 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 470 CdFastQueryBasicInfo ( 471 _In_ PFILE_OBJECT FileObject, 472 _In_ BOOLEAN Wait, 473 _Out_ PFILE_BASIC_INFORMATION Buffer, 474 _Out_ PIO_STATUS_BLOCK IoStatus, 475 _In_ PDEVICE_OBJECT DeviceObject 476 ) 477 478 /*++ 479 480 Routine Description: 481 482 This routine is for the fast query call for basic file information. 483 484 Arguments: 485 486 FileObject - Supplies the file object used in this operation 487 488 Wait - Indicates if we are allowed to wait for the information 489 490 Buffer - Supplies the output buffer to receive the basic information 491 492 IoStatus - Receives the final status of the operation 493 494 Return Value: 495 496 BOOLEAN - TRUE if the operation succeeded and FALSE if the caller 497 needs to take the long route. 498 499 --*/ 500 501 { 502 BOOLEAN Result = FALSE; 503 TYPE_OF_OPEN TypeOfOpen; 504 505 PFCB Fcb; 506 507 PAGED_CODE(); 508 509 UNREFERENCED_PARAMETER( DeviceObject ); 510 511 ASSERT_FILE_OBJECT( FileObject ); 512 513 FsRtlEnterFileSystem(); 514 515 // 516 // Decode the file object to find the type of open and the data 517 // structures. 518 // 519 520 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 521 522 // 523 // We only support this request on user file or directory objects. 524 // 525 526 if ((TypeOfOpen != UserFileOpen) && 527 ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) { 528 529 FsRtlExitFileSystem(); 530 return FALSE; 531 } 532 533 // 534 // Acquire the file shared to access the Fcb. 535 // 536 537 if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) { 538 539 FsRtlExitFileSystem(); 540 return FALSE; 541 } 542 543 // 544 // Use a try-finally to facilitate cleanup. 545 // 546 547 _SEH2_TRY { 548 549 // 550 // Only deal with 'good' Fcb's. 551 // 552 553 if (CdVerifyFcbOperation( NULL, Fcb )) { 554 555 // 556 // Fill in the input buffer from the Fcb fields. 557 // 558 559 Buffer->CreationTime.QuadPart = 560 Buffer->LastWriteTime.QuadPart = 561 Buffer->ChangeTime.QuadPart = Fcb->CreationTime; 562 563 Buffer->LastAccessTime.QuadPart = 0; 564 565 Buffer->FileAttributes = Fcb->FileAttributes; 566 567 // 568 // Update the IoStatus block with the size of this data. 569 // 570 571 IoStatus->Status = STATUS_SUCCESS; 572 IoStatus->Information = sizeof( FILE_BASIC_INFORMATION ); 573 574 Result = TRUE; 575 } 576 577 } _SEH2_FINALLY { 578 579 ExReleaseResourceLite( Fcb->Resource ); 580 581 FsRtlExitFileSystem(); 582 } _SEH2_END; 583 584 return Result; 585 } 586 587 588 _Function_class_(FAST_IO_QUERY_STANDARD_INFO) 589 _IRQL_requires_same_ 590 _Success_(return != FALSE) 591 BOOLEAN 592 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 593 CdFastQueryStdInfo ( 594 _In_ PFILE_OBJECT FileObject, 595 _In_ BOOLEAN Wait, 596 _Out_ PFILE_STANDARD_INFORMATION Buffer, 597 _Out_ PIO_STATUS_BLOCK IoStatus, 598 _In_ PDEVICE_OBJECT DeviceObject 599 ) 600 601 /*++ 602 603 Routine Description: 604 605 This routine is for the fast query call for standard file information. 606 607 Arguments: 608 609 FileObject - Supplies the file object used in this operation 610 611 Wait - Indicates if we are allowed to wait for the information 612 613 Buffer - Supplies the output buffer to receive the basic information 614 615 IoStatus - Receives the final status of the operation 616 617 Return Value: 618 619 BOOLEAN - TRUE if the operation succeeded and FALSE if the caller 620 needs to take the long route. 621 622 --*/ 623 624 { 625 BOOLEAN Result = FALSE; 626 TYPE_OF_OPEN TypeOfOpen; 627 628 PFCB Fcb; 629 630 PAGED_CODE(); 631 632 UNREFERENCED_PARAMETER( DeviceObject ); 633 634 ASSERT_FILE_OBJECT( FileObject ); 635 636 FsRtlEnterFileSystem(); 637 638 // 639 // Decode the file object to find the type of open and the data 640 // structures. 641 // 642 643 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 644 645 // 646 // We only support this request on initialized user file or directory objects. 647 // 648 649 if ((TypeOfOpen != UserFileOpen) && 650 ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ))) { 651 652 FsRtlExitFileSystem(); 653 return FALSE; 654 } 655 656 // 657 // Acquire the file shared to access the Fcb. 658 // 659 660 if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) { 661 662 FsRtlExitFileSystem(); 663 return FALSE; 664 } 665 666 // 667 // Use a try-finally to facilitate cleanup. 668 // 669 670 _SEH2_TRY { 671 672 // 673 // Only deal with 'good' Fcb's. 674 // 675 676 if (CdVerifyFcbOperation( NULL, Fcb )) { 677 678 // 679 // Check whether this is a directory. 680 // 681 682 if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 683 684 Buffer->AllocationSize.QuadPart = 685 Buffer->EndOfFile.QuadPart = 0; 686 687 Buffer->Directory = TRUE; 688 689 } else { 690 691 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; 692 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; 693 694 Buffer->Directory = FALSE; 695 } 696 697 Buffer->NumberOfLinks = 1; 698 Buffer->DeletePending = FALSE; 699 700 // 701 // Update the IoStatus block with the size of this data. 702 // 703 704 IoStatus->Status = STATUS_SUCCESS; 705 IoStatus->Information = sizeof( FILE_STANDARD_INFORMATION ); 706 707 Result = TRUE; 708 } 709 710 } _SEH2_FINALLY { 711 712 ExReleaseResourceLite( Fcb->Resource ); 713 714 FsRtlExitFileSystem(); 715 } _SEH2_END; 716 717 return Result; 718 } 719 720 721 _Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO) 722 _IRQL_requires_same_ 723 _Success_(return != FALSE) 724 BOOLEAN 725 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 726 CdFastQueryNetworkInfo ( 727 _In_ PFILE_OBJECT FileObject, 728 _In_ BOOLEAN Wait, 729 _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer, 730 _Out_ PIO_STATUS_BLOCK IoStatus, 731 _In_ PDEVICE_OBJECT DeviceObject 732 ) 733 734 /*++ 735 736 Routine Description: 737 738 This routine is for the fast query call for network file information. 739 740 Arguments: 741 742 FileObject - Supplies the file object used in this operation 743 744 Wait - Indicates if we are allowed to wait for the information 745 746 Buffer - Supplies the output buffer to receive the basic information 747 748 IoStatus - Receives the final status of the operation 749 750 Return Value: 751 752 BOOLEAN - TRUE if the operation succeeded and FALSE if the caller 753 needs to take the long route. 754 755 --*/ 756 757 { 758 BOOLEAN Result = FALSE; 759 TYPE_OF_OPEN TypeOfOpen; 760 761 PFCB Fcb; 762 763 PAGED_CODE(); 764 765 UNREFERENCED_PARAMETER( DeviceObject ); 766 767 ASSERT_FILE_OBJECT( FileObject ); 768 769 FsRtlEnterFileSystem(); 770 771 // 772 // Decode the file object to find the type of open and the data 773 // structures. 774 // 775 776 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 777 778 // 779 // We only support this request on user file or directory objects. 780 // 781 782 if ((TypeOfOpen != UserFileOpen) && 783 ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) { 784 785 FsRtlExitFileSystem(); 786 return FALSE; 787 } 788 789 // 790 // Acquire the file shared to access the Fcb. 791 // 792 793 if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) { 794 795 FsRtlExitFileSystem(); 796 return FALSE; 797 } 798 799 // 800 // Use a try-finally to facilitate cleanup. 801 // 802 803 _SEH2_TRY { 804 805 // 806 // Only deal with 'good' Fcb's. 807 // 808 809 if (CdVerifyFcbOperation( NULL, Fcb )) { 810 811 // 812 // Fill in the input buffer from the Fcb fields. 813 // 814 815 Buffer->CreationTime.QuadPart = 816 Buffer->LastWriteTime.QuadPart = 817 Buffer->ChangeTime.QuadPart = Fcb->CreationTime; 818 819 Buffer->LastAccessTime.QuadPart = 0; 820 821 Buffer->FileAttributes = Fcb->FileAttributes; 822 823 // 824 // Check whether this is a directory. 825 // 826 827 if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 828 829 Buffer->AllocationSize.QuadPart = 830 Buffer->EndOfFile.QuadPart = 0; 831 832 } else { 833 834 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; 835 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; 836 } 837 838 // 839 // Update the IoStatus block with the size of this data. 840 // 841 842 IoStatus->Status = STATUS_SUCCESS; 843 IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION ); 844 845 Result = TRUE; 846 } 847 848 } _SEH2_FINALLY { 849 850 ExReleaseResourceLite( Fcb->Resource ); 851 852 FsRtlExitFileSystem(); 853 } _SEH2_END; 854 855 return Result; 856 } 857 858 859 // 860 // Local support routine 861 // 862 863 VOID 864 CdQueryBasicInfo ( 865 _In_ PIRP_CONTEXT IrpContext, 866 _In_ PFCB Fcb, 867 _Out_ PFILE_BASIC_INFORMATION Buffer, 868 _Inout_ PULONG Length 869 ) 870 871 /*++ 872 873 Description: 874 875 This routine performs the query basic information function for Cdfs 876 877 Arguments: 878 879 Fcb - Supplies the Fcb being queried, it has been verified 880 881 Buffer - Supplies a pointer to the buffer where the information is to 882 be returned 883 884 Length - Supplies the length of the buffer in bytes, and receives the 885 remaining bytes free in the buffer upon return. 886 887 Return Value: 888 889 None 890 891 --*/ 892 893 { 894 PAGED_CODE(); 895 896 UNREFERENCED_PARAMETER( IrpContext ); 897 898 // 899 // We only support creation, last modify and last write times on Cdfs. 900 // 901 902 Buffer->LastWriteTime.QuadPart = 903 Buffer->CreationTime.QuadPart = 904 Buffer->ChangeTime.QuadPart = Fcb->CreationTime; 905 906 Buffer->LastAccessTime.QuadPart = 0; 907 908 Buffer->FileAttributes = Fcb->FileAttributes; 909 910 // 911 // Update the length and status output variables 912 // 913 914 *Length -= sizeof( FILE_BASIC_INFORMATION ); 915 916 return; 917 } 918 919 920 // 921 // Local support routine 922 // 923 924 VOID 925 CdQueryStandardInfo ( 926 _In_ PIRP_CONTEXT IrpContext, 927 _In_ PFCB Fcb, 928 _Out_ PFILE_STANDARD_INFORMATION Buffer, 929 _Inout_ PULONG Length 930 ) 931 /*++ 932 933 Routine Description: 934 935 This routine performs the query standard information function for cdfs. 936 937 Arguments: 938 939 Fcb - Supplies the Fcb being queried, it has been verified 940 941 Buffer - Supplies a pointer to the buffer where the information is to 942 be returned 943 944 Length - Supplies the length of the buffer in bytes, and receives the 945 remaining bytes free in the buffer upon return. 946 947 Return Value: 948 949 None 950 951 --*/ 952 953 { 954 PAGED_CODE(); 955 956 UNREFERENCED_PARAMETER( IrpContext ); 957 958 // 959 // There is only one link and delete is never pending on a Cdrom file. 960 // 961 962 Buffer->NumberOfLinks = 1; 963 Buffer->DeletePending = FALSE; 964 965 // 966 // We get the sizes from the header. Return a size of zero 967 // for all directories. 968 // 969 970 if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 971 972 Buffer->AllocationSize.QuadPart = 973 Buffer->EndOfFile.QuadPart = 0; 974 975 Buffer->Directory = TRUE; 976 977 } else { 978 979 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; 980 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; 981 982 Buffer->Directory = FALSE; 983 } 984 985 // 986 // Update the length and status output variables 987 // 988 989 *Length -= sizeof( FILE_STANDARD_INFORMATION ); 990 991 return; 992 } 993 994 995 // 996 // Local support routine 997 // 998 999 VOID 1000 CdQueryInternalInfo ( 1001 _In_ PIRP_CONTEXT IrpContext, 1002 _In_ PFCB Fcb, 1003 _Out_ PFILE_INTERNAL_INFORMATION Buffer, 1004 _Inout_ PULONG Length 1005 ) 1006 1007 /*++ 1008 1009 Routine Description: 1010 1011 This routine performs the query internal information function for cdfs. 1012 1013 Arguments: 1014 1015 Fcb - Supplies the Fcb being queried, it has been verified 1016 1017 Buffer - Supplies a pointer to the buffer where the information is to 1018 be returned 1019 1020 Length - Supplies the length of the buffer in bytes, and receives the 1021 remaining bytes free in the buffer upon return. 1022 1023 Return Value: 1024 1025 None 1026 1027 --*/ 1028 1029 { 1030 PAGED_CODE(); 1031 1032 UNREFERENCED_PARAMETER( IrpContext ); 1033 1034 // 1035 // Index number is the file Id number in the Fcb. 1036 // 1037 1038 Buffer->IndexNumber = Fcb->FileId; 1039 *Length -= sizeof( FILE_INTERNAL_INFORMATION ); 1040 1041 return; 1042 } 1043 1044 1045 // 1046 // Local support routine 1047 // 1048 1049 VOID 1050 CdQueryEaInfo ( 1051 _In_ PIRP_CONTEXT IrpContext, 1052 _In_ PFCB Fcb, 1053 _Out_ PFILE_EA_INFORMATION Buffer, 1054 _Inout_ PULONG Length 1055 ) 1056 1057 /*++ 1058 1059 Routine Description: 1060 1061 This routine performs the query Ea information function for cdfs. 1062 1063 Arguments: 1064 1065 Fcb - Supplies the Fcb being queried, it has been verified 1066 1067 Buffer - Supplies a pointer to the buffer where the information is to 1068 be returned 1069 1070 Length - Supplies the length of the buffer in bytes, and receives the 1071 remaining bytes free in the buffer upon return. 1072 1073 Return Value: 1074 1075 None 1076 1077 --*/ 1078 1079 { 1080 PAGED_CODE(); 1081 1082 UNREFERENCED_PARAMETER( IrpContext ); 1083 UNREFERENCED_PARAMETER( Fcb ); 1084 1085 // 1086 // No Ea's on Cdfs volumes. 1087 // 1088 1089 Buffer->EaSize = 0; 1090 *Length -= sizeof( FILE_EA_INFORMATION ); 1091 1092 return; 1093 } 1094 1095 1096 // 1097 // Local support routine 1098 // 1099 1100 VOID 1101 CdQueryPositionInfo ( 1102 _In_ PIRP_CONTEXT IrpContext, 1103 _In_ PFILE_OBJECT FileObject, 1104 _Out_ PFILE_POSITION_INFORMATION Buffer, 1105 _Inout_ PULONG Length 1106 ) 1107 1108 /*++ 1109 1110 Routine Description: 1111 1112 This routine performs the query position information function for cdfs. 1113 1114 Arguments: 1115 1116 FileObject - Supplies the File object being queried 1117 1118 Buffer - Supplies a pointer to the buffer where the information is to 1119 be returned 1120 1121 Length - Supplies the length of the buffer in bytes, and receives the 1122 remaining bytes free in the buffer upon return. 1123 1124 Return Value: 1125 1126 None 1127 1128 --*/ 1129 1130 { 1131 PAGED_CODE(); 1132 1133 UNREFERENCED_PARAMETER( IrpContext ); 1134 1135 // 1136 // Get the current position found in the file object. 1137 // 1138 1139 Buffer->CurrentByteOffset = FileObject->CurrentByteOffset; 1140 1141 // 1142 // Update the length and status output variables 1143 // 1144 1145 *Length -= sizeof( FILE_POSITION_INFORMATION ); 1146 1147 return; 1148 } 1149 1150 1151 // 1152 // Local support routine 1153 // 1154 1155 NTSTATUS 1156 CdQueryNameInfo ( 1157 _In_ PIRP_CONTEXT IrpContext, 1158 _In_ PFILE_OBJECT FileObject, 1159 _Out_ PFILE_NAME_INFORMATION Buffer, 1160 _Inout_ PULONG Length 1161 ) 1162 1163 /*++ 1164 1165 Routine Description: 1166 1167 This routine performs the query name information function for cdfs. 1168 1169 Arguments: 1170 1171 FileObject - Supplies the file object containing the name. 1172 1173 Buffer - Supplies a pointer to the buffer where the information is to 1174 be returned 1175 1176 Length - Supplies the length of the buffer in bytes, and receives the 1177 remaining bytes free in the buffer upon return. 1178 1179 Return Value: 1180 1181 NTSTATUS - STATUS_BUFFER_OVERFLOW if the entire name can't be copied. 1182 1183 --*/ 1184 1185 { 1186 NTSTATUS Status = STATUS_SUCCESS; 1187 ULONG LengthToCopy; 1188 1189 PAGED_CODE(); 1190 1191 UNREFERENCED_PARAMETER( IrpContext ); 1192 1193 NT_ASSERT(*Length >= sizeof(ULONG)); 1194 1195 // 1196 // Simply copy the name in the file object to the user's buffer. 1197 // 1198 1199 // 1200 // Place the size of the filename in the user's buffer and reduce the remaining 1201 // size to match. 1202 // 1203 1204 Buffer->FileNameLength = LengthToCopy = FileObject->FileName.Length; 1205 *Length -= sizeof(ULONG); 1206 1207 if (LengthToCopy > *Length) { 1208 1209 LengthToCopy = *Length; 1210 Status = STATUS_BUFFER_OVERFLOW; 1211 } 1212 1213 RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, LengthToCopy ); 1214 1215 // 1216 // Reduce the available bytes by the amount stored into this buffer. In the overflow 1217 // case, this simply drops to zero. The returned filenamelength will indicate to the 1218 // caller how much space is required. 1219 // 1220 1221 *Length -= LengthToCopy; 1222 1223 return Status; 1224 } 1225 1226 1227 // 1228 // Local support routine 1229 // 1230 1231 _Requires_lock_held_(_Global_critical_region_) 1232 NTSTATUS 1233 CdQueryAlternateNameInfo ( 1234 _In_ PIRP_CONTEXT IrpContext, 1235 _In_ PFCB Fcb, 1236 _In_ PCCB Ccb, 1237 _Out_ PFILE_NAME_INFORMATION Buffer, 1238 _Inout_ PULONG Length 1239 ) 1240 1241 /*++ 1242 1243 Routine Description: 1244 1245 This routine performs the query alternate name information function. 1246 We lookup the dirent for this file and then check if there is a 1247 short name. 1248 1249 Arguments: 1250 1251 Fcb - Supplies the Fcb being queried, it has been verified. 1252 1253 Ccb - Ccb for this open handle. 1254 1255 Buffer - Supplies a pointer to the buffer where the information is to 1256 be returned. 1257 1258 Length - Supplies the length of the buffer in bytes, and receives the 1259 remaining bytes free in the buffer upon return. 1260 1261 Return Value: 1262 1263 NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer, 1264 STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name, 1265 STATUS_BUFFER_OVERFLOW otherwise. 1266 1267 --*/ 1268 1269 { 1270 NTSTATUS Status = STATUS_SUCCESS; 1271 1272 DIRENT_ENUM_CONTEXT DirContext = {0}; 1273 DIRENT Dirent = {0}; 1274 1275 PUNICODE_STRING NameToUse; 1276 ULONG DirentOffset; 1277 1278 COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ 1279 FILE_ENUM_CONTEXT FileContext; 1280 1281 PFCB ParentFcb = NULL; 1282 BOOLEAN ReleaseParentFcb = FALSE; 1283 1284 BOOLEAN CleanupFileLookup = FALSE; 1285 BOOLEAN CleanupDirectoryLookup = FALSE; 1286 1287 WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ]; 1288 USHORT ShortNameLength; 1289 1290 PAGED_CODE(); 1291 1292 // 1293 // Initialize the buffer length to zero. 1294 // 1295 1296 Buffer->FileNameLength = 0; 1297 1298 // 1299 // If this is the root or this file was opened using a version number then 1300 // there is no short name. 1301 // 1302 1303 if ((Fcb == Fcb->Vcb->RootIndexFcb) || 1304 FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) { 1305 1306 return STATUS_OBJECT_NAME_NOT_FOUND; 1307 } 1308 1309 // 1310 // Use a try-finally to cleanup the structures. 1311 // 1312 1313 _SEH2_TRY { 1314 1315 ParentFcb = Fcb->ParentFcb; 1316 CdAcquireFileShared( IrpContext, ParentFcb ); 1317 ReleaseParentFcb = TRUE; 1318 1319 CdVerifyOrCreateDirStreamFile( IrpContext, ParentFcb); 1320 1321 if (CdFidIsDirectory( Fcb->FileId)) { 1322 1323 // 1324 // Fcb is for a directory, so we need to dig the dirent from the parent. In 1325 // order to do this we need to get the name of the directory from its pathtable 1326 // entry and then search in the parent for a matching dirent. 1327 // 1328 // This could be optimized somewhat. 1329 // 1330 1331 CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); 1332 CdInitializeFileContext( IrpContext, &FileContext ); 1333 1334 CleanupDirectoryLookup = TRUE; 1335 1336 CdLookupPathEntry( IrpContext, 1337 CdQueryFidPathTableOffset( Fcb->FileId ), 1338 Fcb->Ordinal, 1339 FALSE, 1340 &CompoundPathEntry ); 1341 1342 CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE ); 1343 1344 if (!CdFindDirectory( IrpContext, 1345 ParentFcb, 1346 &CompoundPathEntry.PathEntry.CdCaseDirName, 1347 TRUE, 1348 &FileContext )) { 1349 1350 // 1351 // If we failed to find the child directory by name in the parent 1352 // something is quite wrong with this disc. 1353 // 1354 1355 CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR ); 1356 } 1357 1358 NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName; 1359 DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset; 1360 1361 } else { 1362 1363 // 1364 // Initialize the search dirent structures. 1365 // 1366 1367 CdInitializeDirContext( IrpContext, &DirContext ); 1368 CdInitializeDirent( IrpContext, &Dirent ); 1369 1370 CleanupFileLookup = TRUE; 1371 1372 CdLookupDirent( IrpContext, 1373 ParentFcb, 1374 CdQueryFidDirentOffset( Fcb->FileId ), 1375 &DirContext ); 1376 1377 CdUpdateDirentFromRawDirent( IrpContext, 1378 ParentFcb, 1379 &DirContext, 1380 &Dirent ); 1381 1382 // 1383 // Now update the dirent name. 1384 // 1385 1386 CdUpdateDirentName( IrpContext, &Dirent, TRUE ); 1387 1388 NameToUse = &Dirent.CdCaseFileName.FileName; 1389 DirentOffset = Dirent.DirentOffset; 1390 } 1391 1392 // 1393 // If the name is 8.3 then fail this request. 1394 // 1395 1396 if (CdIs8dot3Name( IrpContext, 1397 *NameToUse )) { 1398 1399 1400 try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND ); 1401 } 1402 1403 CdGenerate8dot3Name( IrpContext, 1404 NameToUse, 1405 DirentOffset, 1406 ShortNameBuffer, 1407 &ShortNameLength ); 1408 1409 // 1410 // We now have the short name. We have left it in Unicode form so copy it directly. 1411 // 1412 1413 Buffer->FileNameLength = ShortNameLength; 1414 1415 if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) { 1416 1417 Buffer->FileNameLength = *Length - sizeof( ULONG ); 1418 Status = STATUS_BUFFER_OVERFLOW; 1419 } 1420 1421 RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength ); 1422 1423 try_exit: NOTHING; 1424 } _SEH2_FINALLY { 1425 1426 if (CleanupFileLookup) { 1427 1428 CdCleanupDirContext( IrpContext, &DirContext ); 1429 CdCleanupDirent( IrpContext, &Dirent );/* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */ 1430 1431 } else if (CleanupDirectoryLookup) { 1432 1433 CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); 1434 CdCleanupFileContext( IrpContext, &FileContext ); 1435 } 1436 1437 if (ReleaseParentFcb) { 1438 1439 CdReleaseFile( IrpContext, ParentFcb ); 1440 } 1441 } _SEH2_END; 1442 1443 // 1444 // Reduce the available bytes by the amount stored into this buffer. 1445 // 1446 1447 if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { 1448 1449 *Length -= sizeof( ULONG ) + Buffer->FileNameLength; 1450 } 1451 1452 return Status; 1453 } 1454 1455 1456 // 1457 // Local support routine 1458 // 1459 1460 VOID 1461 CdQueryNetworkInfo ( 1462 _In_ PIRP_CONTEXT IrpContext, 1463 _In_ PFCB Fcb, 1464 _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer, 1465 _Inout_ PULONG Length 1466 ) 1467 1468 /*++ 1469 1470 Description: 1471 1472 This routine performs the query network open information function for Cdfs 1473 1474 Arguments: 1475 1476 Fcb - Supplies the Fcb being queried, it has been verified 1477 1478 Buffer - Supplies a pointer to the buffer where the information is to 1479 be returned 1480 1481 Length - Supplies the length of the buffer in bytes, and receives the 1482 remaining bytes free in the buffer upon return. 1483 1484 Return Value: 1485 1486 None 1487 1488 --*/ 1489 1490 { 1491 PAGED_CODE(); 1492 1493 UNREFERENCED_PARAMETER( IrpContext ); 1494 1495 // 1496 // We only support creation, last modify and last write times on Cdfs. 1497 // 1498 1499 Buffer->LastWriteTime.QuadPart = 1500 Buffer->CreationTime.QuadPart = 1501 Buffer->ChangeTime.QuadPart = Fcb->CreationTime; 1502 1503 Buffer->LastAccessTime.QuadPart = 0; 1504 1505 Buffer->FileAttributes = Fcb->FileAttributes; 1506 1507 // 1508 // We get the sizes from the header. Return a size of zero 1509 // for all directories. 1510 // 1511 1512 if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 1513 1514 Buffer->AllocationSize.QuadPart = 1515 Buffer->EndOfFile.QuadPart = 0; 1516 1517 } else { 1518 1519 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; 1520 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; 1521 } 1522 1523 // 1524 // Update the length and status output variables 1525 // 1526 1527 *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION ); 1528 1529 return; 1530 } 1531 1532