Changeset 78536 in vbox for trunk/src/VBox/Additions/WINNT
- Timestamp:
- May 15, 2019 11:51:30 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/info.cpp
r78533 r78536 563 563 pVBoxFcbX->VolInfo.fsProperties.fCaseSensitive = pReq->VolInfo.fsProperties.fCaseSensitive; 564 564 pVBoxFcbX->VolInfo.fsProperties.fReadOnly = pReq->VolInfo.fsProperties.fReadOnly; 565 /** @todo Use SHFL_FN_QUERY_MAP_INFO to get the correct read-only status of 566 * the share. */ 565 567 pVBoxFcbX->VolInfo.fsProperties.fSupportsUnicode = pReq->VolInfo.fsProperties.fSupportsUnicode; 566 568 pVBoxFcbX->VolInfo.fsProperties.fCompressed = pReq->VolInfo.fsProperties.fCompressed; … … 715 717 { 716 718 /* 717 * NtQueryVolumeInformationFile should've checked the minimum buffer size 718 * but just in case. 719 */ 720 AssertReturnStmt(cbInfo >= sizeof(FILE_FS_SIZE_INFORMATION), 721 pRxContext->InformationToReturn = sizeof(FILE_FS_SIZE_INFORMATION), 722 STATUS_BUFFER_TOO_SMALL); 719 * NtQueryVolumeInformationFile should've checked the buffer size but just in case. 720 */ 721 AssertReturnStmt(cbInfo >= sizeof(*pInfo), pRxContext->InformationToReturn = sizeof(*pInfo), STATUS_BUFFER_TOO_SMALL); 723 722 724 723 /* … … 783 782 { 784 783 /* 785 * NtQueryVolumeInformationFile should've checked the minimum buffer size 786 * but just in case. 787 */ 788 AssertReturnStmt(cbInfo >= sizeof(FILE_FS_SIZE_INFORMATION), 789 pRxContext->InformationToReturn = sizeof(FILE_FS_SIZE_INFORMATION), 790 STATUS_BUFFER_TOO_SMALL); 784 * NtQueryVolumeInformationFile should've checked the buffer size but just in case. 785 */ 786 AssertReturnStmt(cbInfo >= sizeof(*pInfo), pRxContext->InformationToReturn = sizeof(*pInfo), STATUS_BUFFER_TOO_SMALL); 791 787 792 788 /* … … 841 837 } 842 838 843 839 /** 840 * Handles NtQueryVolumeInformationFile / FileFsDeviceInformation 841 */ 842 static NTSTATUS vbsfNtQueryFsDeviceInfo(IN OUT PRX_CONTEXT pRxContext, 843 PFILE_FS_DEVICE_INFORMATION pInfo, 844 ULONG cbInfo, 845 PMRX_NET_ROOT pNetRoot) 846 { 847 /* 848 * NtQueryVolumeInformationFile should've checked the buffer size but just in case. 849 */ 850 AssertReturnStmt(cbInfo >= sizeof(*pInfo), pRxContext->InformationToReturn = sizeof(*pInfo), STATUS_BUFFER_TOO_SMALL); 851 852 /* 853 * Produce the requested data. 854 */ 855 pInfo->DeviceType = pNetRoot->DeviceType; 856 pInfo->Characteristics = FILE_REMOTE_DEVICE; 857 858 Log(("VBOXSF: VBoxMRxQueryVolumeInfo: FileFsFullSizeInformation: DeviceType = %#x\n", pInfo->DeviceType)); 859 Log(("VBOXSF: VBoxMRxQueryVolumeInfo: FileFsFullSizeInformation: Characteristics = %#x (FILE_REMOTE_DEVICE)\n", FILE_REMOTE_DEVICE)); 860 861 /* 862 * Update the return length in the context. 863 */ 864 pRxContext->Info.LengthRemaining = cbInfo - sizeof(*pInfo); 865 pRxContext->InformationToReturn = sizeof(*pInfo); /* whatever */ 866 return STATUS_SUCCESS; 867 } 868 869 /** 870 * Handles NtQueryVolumeInformationFile / FileFsDeviceInformation 871 */ 872 static NTSTATUS vbsfNtQueryFsAttributeInfo(IN OUT PRX_CONTEXT pRxContext, 873 PFILE_FS_ATTRIBUTE_INFORMATION pInfo, 874 ULONG cbInfo, 875 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension, 876 PMRX_VBOX_FOBX pVBoxFobx, 877 PVBSFNTFCBEXT pVBoxFcbX) 878 { 879 static WCHAR const s_wszFsName[] = MRX_VBOX_FILESYS_NAME_U; 880 static ULONG const s_cbFsName = sizeof(s_wszFsName) - sizeof(s_wszFsName[0]); 881 ULONG const cbNeeded = RT_UOFFSETOF(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName) + s_cbFsName; 882 883 /* 884 * NtQueryVolumeInformationFile should've checked the buffer size but just in case. 885 */ 886 AssertReturnStmt(cbInfo >= RT_UOFFSETOF(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName), 887 pRxContext->InformationToReturn = cbNeeded, 888 STATUS_BUFFER_TOO_SMALL); 889 890 /* 891 * Get up-to-date information about filename length and such. 892 */ 893 if (pVBoxFcbX->nsVolInfoUpToDate - RTTimeSystemNanoTS() < RT_NS_100MS /** @todo implement proper volume info TTL */ ) 894 { 895 /* Must fetch the info. */ 896 NTSTATUS Status = vbsfNtUpdateFcbVolInfo(pVBoxFcbX, pNetRootExtension, pVBoxFobx); 897 if (NT_SUCCESS(Status)) 898 { /* likely */ } 899 else 900 return Status; 901 } 902 903 /* 904 * Produce the requested data. 905 * 906 * Note! The MaximumComponentNameLength is documented (1) to be in bytes, but 907 * NTFS and FAT32 both return 255, indicating that it is really a UTF-16 char count. 908 * 909 * Note! Both NTFS and FAT32 seems to be setting Ios.Information and FileSystemNameLength 910 * the number of bytes returned in the STATUS_BUFFER_OVERFLOW case, making it 911 * impossible to guess the length from the returned data. RDR2 forwards information 912 * from the server, and samba returns a fixed FileSystemNameLength. 913 * 914 * (1) https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/ns-ntifs-_file_fs_attribute_information 915 */ 916 pInfo->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; 917 /** @todo Implement FILE_RETURNS_CLEANUP_RESULT_INFO. */ 918 if (pVBoxFcbX->VolInfo.fsProperties.fSupportsUnicode) 919 pInfo->FileSystemAttributes |= FILE_UNICODE_ON_DISK; 920 if (pVBoxFcbX->VolInfo.fsProperties.fReadOnly) 921 pInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME; 922 if (pVBoxFcbX->VolInfo.fsProperties.fFileCompression) 923 pInfo->FileSystemAttributes |= FILE_FILE_COMPRESSION; 924 else if (pVBoxFcbX->VolInfo.fsProperties.fCompressed) 925 pInfo->FileSystemAttributes |= FILE_VOLUME_IS_COMPRESSED; 926 pInfo->MaximumComponentNameLength = pVBoxFcbX->VolInfo.fsProperties.cbMaxComponent 927 ? pVBoxFcbX->VolInfo.fsProperties.cbMaxComponent : 255; 928 ULONG const cbStrCopied = RT_MIN(cbInfo - RT_UOFFSETOF(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName), s_cbFsName); 929 pInfo->FileSystemNameLength = s_cbFsName; 930 if (cbStrCopied > 0) 931 memcpy(pInfo->FileSystemName, MRX_VBOX_FILESYS_NAME_U, cbStrCopied); 932 933 /* 934 * Update the return length in the context. 935 */ 936 pRxContext->Info.LengthRemaining = cbInfo - cbStrCopied - RT_UOFFSETOF(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName); 937 pRxContext->InformationToReturn = cbStrCopied + RT_UOFFSETOF(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName); /* whatever */ 938 return cbInfo >= cbNeeded ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW; 939 } 940 941 /** 942 * Handles NtQueryVolumeInformationFile / FileFsSectorSizeInformation 943 */ 944 static NTSTATUS vbsfNtQueryFsSectorSizeInfo(IN OUT PRX_CONTEXT pRxContext, 945 PFILE_FS_SECTOR_SIZE_INFORMATION pInfo, 946 ULONG cbInfo, 947 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension, 948 PMRX_VBOX_FOBX pVBoxFobx, 949 PVBSFNTFCBEXT pVBoxFcbX) 950 { 951 /* 952 * NtQueryVolumeInformationFile should've checked the buffer size but just in case. 953 */ 954 AssertReturnStmt(cbInfo >= sizeof(*pInfo), pRxContext->InformationToReturn = sizeof(*pInfo), STATUS_BUFFER_TOO_SMALL); 955 956 /* 957 * Get up-to-date sector size info. 958 */ 959 if (pVBoxFcbX->nsVolInfoUpToDate - RTTimeSystemNanoTS() < RT_NS_100MS /** @todo implement proper volume info TTL */ ) 960 { 961 /* Must fetch the info. */ 962 NTSTATUS Status = vbsfNtUpdateFcbVolInfo(pVBoxFcbX, pNetRootExtension, pVBoxFobx); 963 if (NT_SUCCESS(Status)) 964 { /* likely */ } 965 else 966 return Status; 967 } 968 969 /* 970 * Produce the requested data (currently no way to query more than the 971 * basic sector size here, so just repeat it). 972 */ 973 uint32_t const cbSector = pVBoxFcbX->VolInfo.ulBytesPerSector ? pVBoxFcbX->VolInfo.ulBytesPerSector : 512; 974 pInfo->LogicalBytesPerSector = cbSector; 975 pInfo->PhysicalBytesPerSectorForAtomicity = cbSector; 976 pInfo->PhysicalBytesPerSectorForPerformance = cbSector; 977 pInfo->FileSystemEffectivePhysicalBytesPerSectorForAtomicity = cbSector; 978 pInfo->Flags = 0; 979 pInfo->ByteOffsetForSectorAlignment = SSINFO_OFFSET_UNKNOWN; 980 pInfo->ByteOffsetForPartitionAlignment = SSINFO_OFFSET_UNKNOWN; 981 982 /* 983 * Update the return length in the context. 984 */ 985 pRxContext->Info.LengthRemaining = cbInfo - sizeof(*pInfo); 986 pRxContext->InformationToReturn = sizeof(*pInfo); /* whatever */ 987 return STATUS_SUCCESS; 988 } 989 990 991 #include <iprt/mem.h> 844 992 /** 845 993 * Handles NtQueryVolumeInformationFile and similar. 994 * 995 * The RDBSS library does not do a whole lot for these queries. No FCB locking. 996 * 997 * 998 * The IO_STATUS_BLOCK updating differs too, setting of Ios.Information is 999 * limited to cbInitialBuf 1000 * - RxContext->Info.LengthRemaining. 846 1001 */ 847 1002 NTSTATUS VBoxMRxQueryVolumeInfo(IN OUT PRX_CONTEXT RxContext) 848 1003 { 1004 #ifdef LOG_ENABLED 1005 static const char * const s_apszNames[] = 1006 { 1007 "FileFsInvalidZeroEntry", "FileFsVolumeInformation", "FileFsLabelInformation", 1008 "FileFsSizeInformation", "FileFsDeviceInformation", "FileFsAttributeInformation", 1009 "FileFsControlInformation", "FileFsFullSizeInformation", "FileFsObjectIdInformation", 1010 "FileFsDriverPathInformation", "FileFsVolumeFlagsInformation", "FileFsSectorSizeInformation", 1011 "FileFsDataCopyInformation", "FileFsMetadataSizeInformation", "FileFsFullSizeInformationEx", 1012 }; 1013 #endif 1014 849 1015 NTSTATUS Status; 850 1016 … … 854 1020 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot); 855 1021 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx); 856 857 FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;858 PVOID pInfoBuffer = RxContext->Info.Buffer;859 ULONG cbInfoBuffer = RxContext->Info.LengthRemaining;860 ULONG cbToCopy = 0;861 ULONG cbString = 0;862 1022 863 1023 Log(("VBOXSF: MrxQueryVolumeInfo: pInfoBuffer = %p, cbInfoBuffer = %d\n", 864 1024 RxContext->Info.Buffer, RxContext->Info.LengthRemaining)); 865 1025 Log(("VBOXSF: MrxQueryVolumeInfo: vboxFobx = %p, Handle = 0x%RX64\n", 866 pVBoxFobx, pVBoxFobx? pVBoxFobx->hFile: 0)); 867 868 Status = STATUS_INVALID_PARAMETER; 869 870 switch (FsInformationClass) 1026 pVBoxFobx, pVBoxFobx ? pVBoxFobx->hFile : 0)); 1027 1028 /** @todo Consolidate the tail code that updates LengthRemaining. */ 1029 switch (RxContext->Info.FsInformationClass) 871 1030 { 872 1031 case FileFsVolumeInformation: … … 878 1037 return Status; 879 1038 880 case FileFsLabelInformation:881 AssertFailed(/* Only for setting, not for querying. */);882 Status = STATUS_INVALID_INFO_CLASS;883 break;884 885 1039 case FileFsSizeInformation: 886 1040 Log(("VBOXSF: VBoxMRxQueryVolumeInfo: FileFsSizeInformation\n")); … … 900 1054 901 1055 case FileFsDeviceInformation: 902 { 903 PFILE_FS_DEVICE_INFORMATION pInfo = (PFILE_FS_DEVICE_INFORMATION)pInfoBuffer; 904 PMRX_NET_ROOT NetRoot = capFcb->pNetRoot; 905 906 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsDeviceInformation: Type = %d\n", 907 NetRoot->DeviceType)); 908 909 cbToCopy = sizeof(FILE_FS_DEVICE_INFORMATION); 910 911 if (cbInfoBuffer < cbToCopy) 1056 Log(("VBOXSF: VBoxMRxQueryVolumeInfo: FileFsDeviceInformation\n")); 1057 AssertReturn(pVBoxFobx, STATUS_INVALID_PARAMETER); 1058 Status = vbsfNtQueryFsDeviceInfo(RxContext, (PFILE_FS_DEVICE_INFORMATION)RxContext->Info.Buffer, 1059 RxContext->Info.Length, capFcb->pNetRoot); 1060 return Status; 1061 1062 case FileFsAttributeInformation: 1063 Log(("VBOXSF: VBoxMRxQueryVolumeInfo: FileFsAttributeInformation\n")); 1064 AssertReturn(pVBoxFobx, STATUS_INVALID_PARAMETER); 1065 Status = vbsfNtQueryFsAttributeInfo(RxContext, (PFILE_FS_ATTRIBUTE_INFORMATION)RxContext->Info.Buffer, 1066 RxContext->Info.Length, pNetRootExtension, pVBoxFobx, 1067 VBoxMRxGetFcbExtension(capFcb)); 1068 return Status; 1069 1070 case FileFsSectorSizeInformation: 1071 Log(("VBOXSF: VBoxMRxQueryVolumeInfo: FileFsSectorSizeInformation\n")); 1072 AssertReturn(pVBoxFobx, STATUS_INVALID_PARAMETER); 1073 Status = vbsfNtQueryFsSectorSizeInfo(RxContext, (PFILE_FS_SECTOR_SIZE_INFORMATION)RxContext->Info.Buffer, 1074 RxContext->Info.Length, pNetRootExtension, pVBoxFobx, 1075 VBoxMRxGetFcbExtension(capFcb)); 1076 return Status; 1077 1078 case FileFsLabelInformation: 1079 AssertFailed(/* Only for setting, not for querying. */); 1080 RT_FALL_THRU(); 1081 default: 1082 { 1083 Log(("VBOXSF: MrxQueryVolumeInfo: Not supported FS_INFORMATION_CLASS value: %d (%s)!\n", 1084 RxContext->Info.FsInformationClass, 1085 (ULONG)RxContext->Info.FsInformationClass < RT_ELEMENTS(s_apszNames) 1086 ? s_apszNames[RxContext->Info.FsInformationClass] : "??")); 1087 /* Here is a weird issue I couldn't quite figure out. When working directories, I 1088 seem to get semi-random stuff back in the IO_STATUS_BLOCK. Difference between 1089 directories and files seemed to be the IRP_SYNCHRONOUS_API flag. Poking around 1090 a little bit more, the UserIosb seems to be a ring-0 stack address rather than 1091 the usermode one and IopSynchronousApiServiceTail being used for copying it back 1092 to user mode because the handle wasn't synchronous or something. 1093 1094 So, the following is kludge to make the IOS values 0,0 like FAT does it. The 1095 real fix for this escapes me, but this should do the trick... */ 1096 PIRP pIrp = RxContext->CurrentIrp; 1097 if ( pIrp 1098 && (pIrp->Flags & IRP_SYNCHRONOUS_API) 1099 && RTR0MemKernelIsValidAddr(pIrp->UserIosb)) 912 1100 { 913 Status = STATUS_BUFFER_TOO_SMALL; 914 break; 1101 Log9(("VBOXSF: MrxQueryVolumeInfo: IRP_SYNCHRONOUS_API hack: Setting UserIosb (%p) values to zero!\n", \ 1102 pIrp->UserIosb)); 1103 __try 1104 { 1105 pIrp->UserIosb->Status = 0; 1106 pIrp->UserIosb->Information = 0; 1107 } 1108 __except(EXCEPTION_EXECUTE_HANDLER) 1109 { 1110 #ifdef LOG_ENABLED 1111 NTSTATUS rcNt = GetExceptionCode(); 1112 Log(("VBOXSF: MrxQueryVolumeInfo: Oops %#x accessing %p\n", rcNt, pIrp->UserIosb)); 1113 #endif 1114 } 915 1115 } 916 917 pInfo->DeviceType = NetRoot->DeviceType; 918 pInfo->Characteristics = FILE_REMOTE_DEVICE; 919 920 Status = STATUS_SUCCESS; 921 break; 922 } 923 924 case FileFsAttributeInformation: 925 { 926 PFILE_FS_ATTRIBUTE_INFORMATION pInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)pInfoBuffer; 927 928 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation\n")); 929 930 cbToCopy = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName); 931 932 cbString = sizeof(MRX_VBOX_FILESYS_NAME_U); 933 934 if (cbInfoBuffer < cbToCopy) 935 { 936 Status = STATUS_BUFFER_TOO_SMALL; 937 break; 938 } 939 940 pInfo->FileSystemAttributes = 0; /** @todo set unicode, case sensitive etc? */ 941 pInfo->MaximumComponentNameLength = 255; /** @todo should query from the host */ 942 943 if (cbInfoBuffer >= cbToCopy + cbString) 944 { 945 RtlCopyMemory(pInfo->FileSystemName, 946 MRX_VBOX_FILESYS_NAME_U, 947 sizeof(MRX_VBOX_FILESYS_NAME_U)); 948 } 949 else 950 { 951 cbString = cbInfoBuffer - cbToCopy; 952 953 RtlCopyMemory(pInfo->FileSystemName, 954 MRX_VBOX_FILESYS_NAME_U, 955 RT_MIN(cbString, sizeof(MRX_VBOX_FILESYS_NAME_U))); 956 } 957 958 pInfo->FileSystemNameLength = cbString; 959 960 cbToCopy += cbString; 961 962 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsAttributeInformation: FileSystemNameLength %d\n", 963 pInfo->FileSystemNameLength)); 964 965 Status = STATUS_SUCCESS; 966 break; 967 } 968 969 case FileFsControlInformation: 970 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsControlInformation: not supported\n")); 971 Status = STATUS_INVALID_PARAMETER; 972 break; 973 974 case FileFsObjectIdInformation: 975 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsObjectIdInformation: not supported\n")); 976 Status = STATUS_INVALID_PARAMETER; 977 break; 978 979 case FileFsMaximumInformation: 980 Log(("VBOXSF: MrxQueryVolumeInfo: FileFsMaximumInformation: not supported\n")); 981 Status = STATUS_INVALID_PARAMETER; 982 break; 983 984 default: 985 Log(("VBOXSF: MrxQueryVolumeInfo: Not supported FsInformationClass %d!\n", 986 FsInformationClass)); 987 Status = STATUS_INVALID_PARAMETER; 988 break; 989 } 990 991 if (Status == STATUS_SUCCESS) 992 RxContext->Info.LengthRemaining = cbInfoBuffer - cbToCopy; 993 else if (Status == STATUS_BUFFER_TOO_SMALL) 994 { 995 Log(("VBOXSF: MrxQueryVolumeInfo: Insufficient buffer size %d, required %d\n", 996 cbInfoBuffer, cbToCopy)); 997 RxContext->InformationToReturn = cbToCopy; 998 } 999 1000 Log(("VBOXSF: MrxQueryVolumeInfo: cbToCopy = %d, LengthRemaining = %d, Status = 0x%08X\n", 1001 cbToCopy, RxContext->Info.LengthRemaining, Status)); 1002 1003 return Status; 1116 return STATUS_INVALID_PARAMETER; 1117 } 1118 } 1004 1119 } 1005 1120
Note:
See TracChangeset
for help on using the changeset viewer.