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 RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION)); 903 904 Buffer->LastWriteTime.QuadPart = 905 Buffer->CreationTime.QuadPart = 906 Buffer->ChangeTime.QuadPart = Fcb->CreationTime; 907 908 Buffer->LastAccessTime.QuadPart = 0; 909 910 Buffer->FileAttributes = Fcb->FileAttributes; 911 912 // 913 // Update the length and status output variables 914 // 915 916 *Length -= sizeof( FILE_BASIC_INFORMATION ); 917 918 return; 919 } 920 921 922 // 923 // Local support routine 924 // 925 926 VOID 927 CdQueryStandardInfo ( 928 _In_ PIRP_CONTEXT IrpContext, 929 _In_ PFCB Fcb, 930 _Out_ PFILE_STANDARD_INFORMATION Buffer, 931 _Inout_ PULONG Length 932 ) 933 /*++ 934 935 Routine Description: 936 937 This routine performs the query standard information function for cdfs. 938 939 Arguments: 940 941 Fcb - Supplies the Fcb being queried, it has been verified 942 943 Buffer - Supplies a pointer to the buffer where the information is to 944 be returned 945 946 Length - Supplies the length of the buffer in bytes, and receives the 947 remaining bytes free in the buffer upon return. 948 949 Return Value: 950 951 None 952 953 --*/ 954 955 { 956 PAGED_CODE(); 957 958 UNREFERENCED_PARAMETER( IrpContext ); 959 960 // 961 // There is only one link and delete is never pending on a Cdrom file. 962 // 963 964 Buffer->NumberOfLinks = 1; 965 Buffer->DeletePending = FALSE; 966 967 // 968 // We get the sizes from the header. Return a size of zero 969 // for all directories. 970 // 971 972 if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 973 974 Buffer->AllocationSize.QuadPart = 975 Buffer->EndOfFile.QuadPart = 0; 976 977 Buffer->Directory = TRUE; 978 979 } else { 980 981 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; 982 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; 983 984 Buffer->Directory = FALSE; 985 } 986 987 // 988 // Update the length and status output variables 989 // 990 991 *Length -= sizeof( FILE_STANDARD_INFORMATION ); 992 993 return; 994 } 995 996 997 // 998 // Local support routine 999 // 1000 1001 VOID 1002 CdQueryInternalInfo ( 1003 _In_ PIRP_CONTEXT IrpContext, 1004 _In_ PFCB Fcb, 1005 _Out_ PFILE_INTERNAL_INFORMATION Buffer, 1006 _Inout_ PULONG Length 1007 ) 1008 1009 /*++ 1010 1011 Routine Description: 1012 1013 This routine performs the query internal information function for cdfs. 1014 1015 Arguments: 1016 1017 Fcb - Supplies the Fcb being queried, it has been verified 1018 1019 Buffer - Supplies a pointer to the buffer where the information is to 1020 be returned 1021 1022 Length - Supplies the length of the buffer in bytes, and receives the 1023 remaining bytes free in the buffer upon return. 1024 1025 Return Value: 1026 1027 None 1028 1029 --*/ 1030 1031 { 1032 PAGED_CODE(); 1033 1034 UNREFERENCED_PARAMETER( IrpContext ); 1035 1036 // 1037 // Index number is the file Id number in the Fcb. 1038 // 1039 1040 Buffer->IndexNumber = Fcb->FileId; 1041 *Length -= sizeof( FILE_INTERNAL_INFORMATION ); 1042 1043 return; 1044 } 1045 1046 1047 // 1048 // Local support routine 1049 // 1050 1051 VOID 1052 CdQueryEaInfo ( 1053 _In_ PIRP_CONTEXT IrpContext, 1054 _In_ PFCB Fcb, 1055 _Out_ PFILE_EA_INFORMATION Buffer, 1056 _Inout_ PULONG Length 1057 ) 1058 1059 /*++ 1060 1061 Routine Description: 1062 1063 This routine performs the query Ea information function for cdfs. 1064 1065 Arguments: 1066 1067 Fcb - Supplies the Fcb being queried, it has been verified 1068 1069 Buffer - Supplies a pointer to the buffer where the information is to 1070 be returned 1071 1072 Length - Supplies the length of the buffer in bytes, and receives the 1073 remaining bytes free in the buffer upon return. 1074 1075 Return Value: 1076 1077 None 1078 1079 --*/ 1080 1081 { 1082 PAGED_CODE(); 1083 1084 UNREFERENCED_PARAMETER( IrpContext ); 1085 UNREFERENCED_PARAMETER( Fcb ); 1086 1087 // 1088 // No Ea's on Cdfs volumes. 1089 // 1090 1091 Buffer->EaSize = 0; 1092 *Length -= sizeof( FILE_EA_INFORMATION ); 1093 1094 return; 1095 } 1096 1097 1098 // 1099 // Local support routine 1100 // 1101 1102 VOID 1103 CdQueryPositionInfo ( 1104 _In_ PIRP_CONTEXT IrpContext, 1105 _In_ PFILE_OBJECT FileObject, 1106 _Out_ PFILE_POSITION_INFORMATION Buffer, 1107 _Inout_ PULONG Length 1108 ) 1109 1110 /*++ 1111 1112 Routine Description: 1113 1114 This routine performs the query position information function for cdfs. 1115 1116 Arguments: 1117 1118 FileObject - Supplies the File object being queried 1119 1120 Buffer - Supplies a pointer to the buffer where the information is to 1121 be returned 1122 1123 Length - Supplies the length of the buffer in bytes, and receives the 1124 remaining bytes free in the buffer upon return. 1125 1126 Return Value: 1127 1128 None 1129 1130 --*/ 1131 1132 { 1133 PAGED_CODE(); 1134 1135 UNREFERENCED_PARAMETER( IrpContext ); 1136 1137 // 1138 // Get the current position found in the file object. 1139 // 1140 1141 Buffer->CurrentByteOffset = FileObject->CurrentByteOffset; 1142 1143 // 1144 // Update the length and status output variables 1145 // 1146 1147 *Length -= sizeof( FILE_POSITION_INFORMATION ); 1148 1149 return; 1150 } 1151 1152 1153 // 1154 // Local support routine 1155 // 1156 1157 NTSTATUS 1158 CdQueryNameInfo ( 1159 _In_ PIRP_CONTEXT IrpContext, 1160 _In_ PFILE_OBJECT FileObject, 1161 _Out_ PFILE_NAME_INFORMATION Buffer, 1162 _Inout_ PULONG Length 1163 ) 1164 1165 /*++ 1166 1167 Routine Description: 1168 1169 This routine performs the query name information function for cdfs. 1170 1171 Arguments: 1172 1173 FileObject - Supplies the file object containing the name. 1174 1175 Buffer - Supplies a pointer to the buffer where the information is to 1176 be returned 1177 1178 Length - Supplies the length of the buffer in bytes, and receives the 1179 remaining bytes free in the buffer upon return. 1180 1181 Return Value: 1182 1183 NTSTATUS - STATUS_BUFFER_OVERFLOW if the entire name can't be copied. 1184 1185 --*/ 1186 1187 { 1188 NTSTATUS Status = STATUS_SUCCESS; 1189 ULONG LengthToCopy; 1190 1191 PAGED_CODE(); 1192 1193 UNREFERENCED_PARAMETER( IrpContext ); 1194 1195 NT_ASSERT(*Length >= sizeof(ULONG)); 1196 1197 // 1198 // Simply copy the name in the file object to the user's buffer. 1199 // 1200 1201 // 1202 // Place the size of the filename in the user's buffer and reduce the remaining 1203 // size to match. 1204 // 1205 1206 Buffer->FileNameLength = LengthToCopy = FileObject->FileName.Length; 1207 *Length -= sizeof(ULONG); 1208 1209 if (LengthToCopy > *Length) { 1210 1211 LengthToCopy = *Length; 1212 Status = STATUS_BUFFER_OVERFLOW; 1213 } 1214 1215 RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, LengthToCopy ); 1216 1217 // 1218 // Reduce the available bytes by the amount stored into this buffer. In the overflow 1219 // case, this simply drops to zero. The returned filenamelength will indicate to the 1220 // caller how much space is required. 1221 // 1222 1223 *Length -= LengthToCopy; 1224 1225 return Status; 1226 } 1227 1228 1229 // 1230 // Local support routine 1231 // 1232 1233 _Requires_lock_held_(_Global_critical_region_) 1234 NTSTATUS 1235 CdQueryAlternateNameInfo ( 1236 _In_ PIRP_CONTEXT IrpContext, 1237 _In_ PFCB Fcb, 1238 _In_ PCCB Ccb, 1239 _Out_ PFILE_NAME_INFORMATION Buffer, 1240 _Inout_ PULONG Length 1241 ) 1242 1243 /*++ 1244 1245 Routine Description: 1246 1247 This routine performs the query alternate name information function. 1248 We lookup the dirent for this file and then check if there is a 1249 short name. 1250 1251 Arguments: 1252 1253 Fcb - Supplies the Fcb being queried, it has been verified. 1254 1255 Ccb - Ccb for this open handle. 1256 1257 Buffer - Supplies a pointer to the buffer where the information is to 1258 be returned. 1259 1260 Length - Supplies the length of the buffer in bytes, and receives the 1261 remaining bytes free in the buffer upon return. 1262 1263 Return Value: 1264 1265 NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer, 1266 STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name, 1267 STATUS_BUFFER_OVERFLOW otherwise. 1268 1269 --*/ 1270 1271 { 1272 NTSTATUS Status = STATUS_SUCCESS; 1273 1274 DIRENT_ENUM_CONTEXT DirContext = {0}; 1275 DIRENT Dirent = {0}; 1276 1277 PUNICODE_STRING NameToUse; 1278 ULONG DirentOffset; 1279 1280 COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */ 1281 FILE_ENUM_CONTEXT FileContext; 1282 1283 PFCB ParentFcb = NULL; 1284 BOOLEAN ReleaseParentFcb = FALSE; 1285 1286 BOOLEAN CleanupFileLookup = FALSE; 1287 BOOLEAN CleanupDirectoryLookup = FALSE; 1288 1289 WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ]; 1290 USHORT ShortNameLength; 1291 1292 PAGED_CODE(); 1293 1294 // 1295 // Initialize the buffer length to zero. 1296 // 1297 1298 Buffer->FileNameLength = 0; 1299 1300 // 1301 // If this is the root or this file was opened using a version number then 1302 // there is no short name. 1303 // 1304 1305 if ((Fcb == Fcb->Vcb->RootIndexFcb) || 1306 FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) { 1307 1308 return STATUS_OBJECT_NAME_NOT_FOUND; 1309 } 1310 1311 // 1312 // Use a try-finally to cleanup the structures. 1313 // 1314 1315 _SEH2_TRY { 1316 1317 ParentFcb = Fcb->ParentFcb; 1318 CdAcquireFileShared( IrpContext, ParentFcb ); 1319 ReleaseParentFcb = TRUE; 1320 1321 CdVerifyOrCreateDirStreamFile( IrpContext, ParentFcb); 1322 1323 if (CdFidIsDirectory( Fcb->FileId)) { 1324 1325 // 1326 // Fcb is for a directory, so we need to dig the dirent from the parent. In 1327 // order to do this we need to get the name of the directory from its pathtable 1328 // entry and then search in the parent for a matching dirent. 1329 // 1330 // This could be optimized somewhat. 1331 // 1332 1333 CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry ); 1334 CdInitializeFileContext( IrpContext, &FileContext ); 1335 1336 CleanupDirectoryLookup = TRUE; 1337 1338 CdLookupPathEntry( IrpContext, 1339 CdQueryFidPathTableOffset( Fcb->FileId ), 1340 Fcb->Ordinal, 1341 FALSE, 1342 &CompoundPathEntry ); 1343 1344 CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE ); 1345 1346 if (!CdFindDirectory( IrpContext, 1347 ParentFcb, 1348 &CompoundPathEntry.PathEntry.CdCaseDirName, 1349 TRUE, 1350 &FileContext )) { 1351 1352 // 1353 // If we failed to find the child directory by name in the parent 1354 // something is quite wrong with this disc. 1355 // 1356 1357 CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR ); 1358 } 1359 1360 NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName; 1361 DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset; 1362 1363 } else { 1364 1365 // 1366 // Initialize the search dirent structures. 1367 // 1368 1369 CdInitializeDirContext( IrpContext, &DirContext ); 1370 CdInitializeDirent( IrpContext, &Dirent ); 1371 1372 CleanupFileLookup = TRUE; 1373 1374 CdLookupDirent( IrpContext, 1375 ParentFcb, 1376 CdQueryFidDirentOffset( Fcb->FileId ), 1377 &DirContext ); 1378 1379 CdUpdateDirentFromRawDirent( IrpContext, 1380 ParentFcb, 1381 &DirContext, 1382 &Dirent ); 1383 1384 // 1385 // Now update the dirent name. 1386 // 1387 1388 CdUpdateDirentName( IrpContext, &Dirent, TRUE ); 1389 1390 NameToUse = &Dirent.CdCaseFileName.FileName; 1391 DirentOffset = Dirent.DirentOffset; 1392 } 1393 1394 // 1395 // If the name is 8.3 then fail this request. 1396 // 1397 1398 if (CdIs8dot3Name( IrpContext, 1399 *NameToUse )) { 1400 1401 1402 try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND ); 1403 } 1404 1405 CdGenerate8dot3Name( IrpContext, 1406 NameToUse, 1407 DirentOffset, 1408 ShortNameBuffer, 1409 &ShortNameLength ); 1410 1411 // 1412 // We now have the short name. We have left it in Unicode form so copy it directly. 1413 // 1414 1415 Buffer->FileNameLength = ShortNameLength; 1416 1417 if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) { 1418 1419 Buffer->FileNameLength = *Length - sizeof( ULONG ); 1420 Status = STATUS_BUFFER_OVERFLOW; 1421 } 1422 1423 RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength ); 1424 1425 try_exit: NOTHING; 1426 } _SEH2_FINALLY { 1427 1428 if (CleanupFileLookup) { 1429 1430 CdCleanupDirContext( IrpContext, &DirContext ); 1431 CdCleanupDirent( IrpContext, &Dirent );/* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */ 1432 1433 } else if (CleanupDirectoryLookup) { 1434 1435 CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry ); 1436 CdCleanupFileContext( IrpContext, &FileContext ); 1437 } 1438 1439 if (ReleaseParentFcb) { 1440 1441 CdReleaseFile( IrpContext, ParentFcb ); 1442 } 1443 } _SEH2_END; 1444 1445 // 1446 // Reduce the available bytes by the amount stored into this buffer. 1447 // 1448 1449 if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { 1450 1451 *Length -= sizeof( ULONG ) + Buffer->FileNameLength; 1452 } 1453 1454 return Status; 1455 } 1456 1457 1458 // 1459 // Local support routine 1460 // 1461 1462 VOID 1463 CdQueryNetworkInfo ( 1464 _In_ PIRP_CONTEXT IrpContext, 1465 _In_ PFCB Fcb, 1466 _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer, 1467 _Inout_ PULONG Length 1468 ) 1469 1470 /*++ 1471 1472 Description: 1473 1474 This routine performs the query network open information function for Cdfs 1475 1476 Arguments: 1477 1478 Fcb - Supplies the Fcb being queried, it has been verified 1479 1480 Buffer - Supplies a pointer to the buffer where the information is to 1481 be returned 1482 1483 Length - Supplies the length of the buffer in bytes, and receives the 1484 remaining bytes free in the buffer upon return. 1485 1486 Return Value: 1487 1488 None 1489 1490 --*/ 1491 1492 { 1493 PAGED_CODE(); 1494 1495 UNREFERENCED_PARAMETER( IrpContext ); 1496 1497 // 1498 // We only support creation, last modify and last write times on Cdfs. 1499 // 1500 1501 Buffer->LastWriteTime.QuadPart = 1502 Buffer->CreationTime.QuadPart = 1503 Buffer->ChangeTime.QuadPart = Fcb->CreationTime; 1504 1505 Buffer->LastAccessTime.QuadPart = 0; 1506 1507 Buffer->FileAttributes = Fcb->FileAttributes; 1508 1509 // 1510 // We get the sizes from the header. Return a size of zero 1511 // for all directories. 1512 // 1513 1514 if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) { 1515 1516 Buffer->AllocationSize.QuadPart = 1517 Buffer->EndOfFile.QuadPart = 0; 1518 1519 } else { 1520 1521 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart; 1522 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart; 1523 } 1524 1525 // 1526 // Update the length and status output variables 1527 // 1528 1529 *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION ); 1530 1531 return; 1532 } 1533 1534