Changeset 78465 in vbox for trunk/src/VBox/Additions
- Timestamp:
- May 10, 2019 7:11:29 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.cpp
r78380 r78465 695 695 696 696 /** 697 * Closes an opened file handle of a MRX_VBOX_FOBX.697 * Ensures the FCBx doesn't have dangling pointers to @a pVBoxFobx. 698 698 * 699 * Updates file attributes if necessary. 700 * 701 * Used by VBoxMRxCloseSrvOpen, vbsfNtRemove and vbsfNtRename. 699 * This isn't strictly speaking needed, as nobody currently dereference these 700 * pointers, however better keeping things neath and tidy. 702 701 */ 703 NTSTATUS vbsfNtCloseFileHandle(PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension, 704 PMRX_VBOX_FOBX pVBoxFobx, 705 PVBSFNTFCBEXT pVBoxFcbx) 706 { 707 if (pVBoxFobx->hFile == SHFL_HANDLE_NIL) 708 { 709 Log(("VBOXSF: vbsfCloseFileHandle: SHFL_HANDLE_NIL\n")); 710 return STATUS_SUCCESS; 711 } 712 713 Log(("VBOXSF: vbsfCloseFileHandle: 0x%RX64, fTimestampsUpdatingSuppressed = %#x, fTimestampsImplicitlyUpdated = %#x\n", 714 pVBoxFobx->hFile, pVBoxFobx->fTimestampsUpdatingSuppressed, pVBoxFobx->fTimestampsImplicitlyUpdated)); 715 716 /* 717 * We allocate a single request buffer for the timestamp updating and the closing 718 * to save time (at the risk of running out of heap, but whatever). 719 */ 720 union MyCloseAndInfoReq 721 { 722 VBOXSFCLOSEREQ Close; 723 VBOXSFOBJINFOREQ Info; 724 } *pReq = (union MyCloseAndInfoReq *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 725 if (pReq) 726 RT_ZERO(*pReq); 727 else 728 return STATUS_INSUFF_SERVER_RESOURCES; 729 730 /* 731 * Restore timestamp that we may implicitly been updated via this handle 732 * after the user explicitly set them or turn off implict updating (the -1 value). 733 * 734 * Note! We ignore the status of this operation. 735 */ 736 Assert(pVBoxFcbx); 737 uint8_t fUpdateTs = pVBoxFobx->fTimestampsUpdatingSuppressed & pVBoxFobx->fTimestampsImplicitlyUpdated; 738 if (fUpdateTs) 739 { 740 /** @todo skip this if the host is windows and fTimestampsUpdatingSuppressed == fTimestampsSetByUser */ 741 /** @todo pass -1 timestamps thru so we can always skip this on windows hosts! */ 742 if ( (fUpdateTs & VBOX_FOBX_F_INFO_LASTACCESS_TIME) 743 && pVBoxFcbx->pFobxLastAccessTime == pVBoxFobx) 744 pReq->Info.ObjInfo.AccessTime = pVBoxFobx->Info.AccessTime; 745 else 746 fUpdateTs &= ~VBOX_FOBX_F_INFO_LASTACCESS_TIME; 747 748 if ( (fUpdateTs & VBOX_FOBX_F_INFO_LASTWRITE_TIME) 749 && pVBoxFcbx->pFobxLastWriteTime == pVBoxFobx) 750 pReq->Info.ObjInfo.ModificationTime = pVBoxFobx->Info.ModificationTime; 751 else 752 fUpdateTs &= ~VBOX_FOBX_F_INFO_LASTWRITE_TIME; 753 754 if ( (fUpdateTs & VBOX_FOBX_F_INFO_CHANGE_TIME) 755 && pVBoxFcbx->pFobxChangeTime == pVBoxFobx) 756 pReq->Info.ObjInfo.ChangeTime = pVBoxFobx->Info.ChangeTime; 757 else 758 fUpdateTs &= ~VBOX_FOBX_F_INFO_CHANGE_TIME; 759 if (fUpdateTs) 760 { 761 Log(("VBOXSF: vbsfCloseFileHandle: Updating timestamp: %#x\n", fUpdateTs)); 762 int vrc = VbglR0SfHostReqSetObjInfo(pNetRootExtension->map.root, &pReq->Info, pVBoxFobx->hFile); 763 if (RT_FAILURE(vrc)) 764 Log(("VBOXSF: vbsfCloseFileHandle: VbglR0SfHostReqSetObjInfo failed for fUpdateTs=%#x: %Rrc\n", fUpdateTs, vrc)); 765 RT_NOREF(vrc); 766 } 767 else 768 Log(("VBOXSF: vbsfCloseFileHandle: no timestamp needing updating\n")); 769 } 770 771 /* This isn't strictly necessary, but best to keep things clean. */ 702 DECLINLINE(void) vbsfNtCleanupFcbxTimestampRefsOnClose(PMRX_VBOX_FOBX pVBoxFobx, PVBSFNTFCBEXT pVBoxFcbx) 703 { 772 704 pVBoxFobx->fTimestampsSetByUser = 0; 773 705 pVBoxFobx->fTimestampsUpdatingSuppressed = 0; … … 779 711 if (pVBoxFcbx->pFobxChangeTime == pVBoxFobx) 780 712 pVBoxFcbx->pFobxChangeTime = NULL; 713 } 714 715 /** 716 * Closes an opened file handle of a MRX_VBOX_FOBX. 717 * 718 * Updates file attributes if necessary. 719 * 720 * Used by VBoxMRxCloseSrvOpen and vbsfNtRename. 721 */ 722 NTSTATUS vbsfNtCloseFileHandle(PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension, 723 PMRX_VBOX_FOBX pVBoxFobx, 724 PVBSFNTFCBEXT pVBoxFcbx) 725 { 726 if (pVBoxFobx->hFile == SHFL_HANDLE_NIL) 727 { 728 Log(("VBOXSF: vbsfCloseFileHandle: SHFL_HANDLE_NIL\n")); 729 return STATUS_SUCCESS; 730 } 731 732 Log(("VBOXSF: vbsfCloseFileHandle: 0x%RX64, fTimestampsUpdatingSuppressed = %#x, fTimestampsImplicitlyUpdated = %#x\n", 733 pVBoxFobx->hFile, pVBoxFobx->fTimestampsUpdatingSuppressed, pVBoxFobx->fTimestampsImplicitlyUpdated)); 734 735 /* 736 * We allocate a single request buffer for the timestamp updating and the closing 737 * to save time (at the risk of running out of heap, but whatever). 738 */ 739 union MyCloseAndInfoReq 740 { 741 VBOXSFCLOSEREQ Close; 742 VBOXSFOBJINFOREQ Info; 743 } *pReq = (union MyCloseAndInfoReq *)VbglR0PhysHeapAlloc(sizeof(*pReq)); 744 if (pReq) 745 RT_ZERO(*pReq); 746 else 747 return STATUS_INSUFF_SERVER_RESOURCES; 748 749 /* 750 * Restore timestamp that we may implicitly been updated via this handle 751 * after the user explicitly set them or turn off implict updating (the -1 value). 752 * 753 * Note! We ignore the status of this operation. 754 */ 755 Assert(pVBoxFcbx); 756 uint8_t fUpdateTs = pVBoxFobx->fTimestampsUpdatingSuppressed & pVBoxFobx->fTimestampsImplicitlyUpdated; 757 if (fUpdateTs) 758 { 759 /** @todo skip this if the host is windows and fTimestampsUpdatingSuppressed == fTimestampsSetByUser */ 760 /** @todo pass -1 timestamps thru so we can always skip this on windows hosts! */ 761 if ( (fUpdateTs & VBOX_FOBX_F_INFO_LASTACCESS_TIME) 762 && pVBoxFcbx->pFobxLastAccessTime == pVBoxFobx) 763 pReq->Info.ObjInfo.AccessTime = pVBoxFobx->Info.AccessTime; 764 else 765 fUpdateTs &= ~VBOX_FOBX_F_INFO_LASTACCESS_TIME; 766 767 if ( (fUpdateTs & VBOX_FOBX_F_INFO_LASTWRITE_TIME) 768 && pVBoxFcbx->pFobxLastWriteTime == pVBoxFobx) 769 pReq->Info.ObjInfo.ModificationTime = pVBoxFobx->Info.ModificationTime; 770 else 771 fUpdateTs &= ~VBOX_FOBX_F_INFO_LASTWRITE_TIME; 772 773 if ( (fUpdateTs & VBOX_FOBX_F_INFO_CHANGE_TIME) 774 && pVBoxFcbx->pFobxChangeTime == pVBoxFobx) 775 pReq->Info.ObjInfo.ChangeTime = pVBoxFobx->Info.ChangeTime; 776 else 777 fUpdateTs &= ~VBOX_FOBX_F_INFO_CHANGE_TIME; 778 if (fUpdateTs) 779 { 780 Log(("VBOXSF: vbsfCloseFileHandle: Updating timestamp: %#x\n", fUpdateTs)); 781 int vrc = VbglR0SfHostReqSetObjInfo(pNetRootExtension->map.root, &pReq->Info, pVBoxFobx->hFile); 782 if (RT_FAILURE(vrc)) 783 Log(("VBOXSF: vbsfCloseFileHandle: VbglR0SfHostReqSetObjInfo failed for fUpdateTs=%#x: %Rrc\n", fUpdateTs, vrc)); 784 RT_NOREF(vrc); 785 } 786 else 787 Log(("VBOXSF: vbsfCloseFileHandle: no timestamp needing updating\n")); 788 } 789 790 vbsfNtCleanupFcbxTimestampRefsOnClose(pVBoxFobx, pVBoxFcbx); 781 791 782 792 /* … … 794 804 } 795 805 806 /** 807 * @note We don't collapse opens, this is called whenever a handle is closed. 808 */ 796 809 NTSTATUS VBoxMRxCloseSrvOpen(IN PRX_CONTEXT RxContext) 797 810 { 798 NTSTATUS Status = STATUS_SUCCESS;799 800 811 RxCaptureFcb; 801 812 RxCaptureFobx; … … 805 816 PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen; 806 817 807 PUNICODE_STRING RemainingName = NULL;808 818 809 819 Log(("VBOXSF: MRxCloseSrvOpen: capFcb = %p, capFobx = %p, pVBoxFobx = %p, pSrvOpen = %p\n", 810 820 capFcb, capFobx, pVBoxFobx, pSrvOpen)); 811 821 812 RemainingName = pSrvOpen->pAlreadyPrefixedName; 813 822 #ifdef LOG_ENABLED 823 PUNICODE_STRING pRemainingName = pSrvOpen->pAlreadyPrefixedName; 814 824 Log(("VBOXSF: MRxCloseSrvOpen: Remaining name = %.*ls, Len = %d\n", 815 RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, RemainingName->Length)); 825 pRemainingName->Length / sizeof(WCHAR), pRemainingName->Buffer, pRemainingName->Length)); 826 #endif 816 827 817 828 if (!pVBoxFobx) … … 827 838 } 828 839 829 /* Close file */ 840 /* 841 * Remove file or directory if delete action is pending and the this is the last open handle. 842 */ 843 NTSTATUS Status = STATUS_SUCCESS; 844 if (capFcb->FcbState & FCB_STATE_DELETE_ON_CLOSE) 845 { 846 Log(("VBOXSF: MRxCloseSrvOpen: Delete on close. Open count = %d\n", 847 capFcb->OpenCount)); 848 849 if (capFcb->OpenCount == 0) 850 Status = vbsfNtRemove(RxContext); 851 } 852 853 /* 854 * Close file if we still have a handle to it. 855 */ 830 856 if (pVBoxFobx->hFile != SHFL_HANDLE_NIL) 831 857 vbsfNtCloseFileHandle(pNetRootExtension, pVBoxFobx, VBoxMRxGetFcbExtension(capFcb)); 832 858 833 if (capFcb->FcbState & FCB_STATE_DELETE_ON_CLOSE)834 {835 Log(("VBOXSF: MRxCloseSrvOpen: Delete on close. Open count = %d\n",836 capFcb->OpenCount));837 838 /* Remove file or directory if delete action is pending. */839 if (capFcb->OpenCount == 0)840 Status = vbsfNtRemove(RxContext);841 }842 843 859 return Status; 844 860 } … … 846 862 /** 847 863 * Worker for vbsfNtSetBasicInfo and VBoxMRxCloseSrvOpen. 864 * 865 * Only called by vbsfNtSetBasicInfo if there is exactly one open handle. And 866 * VBoxMRxCloseSrvOpen calls it when the last handle is being closed. 848 867 */ 849 868 NTSTATUS vbsfNtRemove(IN PRX_CONTEXT RxContext) 850 869 { 851 NTSTATUS Status = STATUS_SUCCESS;852 853 870 RxCaptureFcb; 854 871 RxCaptureFobx; 855 856 872 PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(capFcb->pNetRoot); 857 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx); 858 859 PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext); 860 861 int vrc; 862 PSHFLSTRING ParsedPath = NULL; 873 PMRX_VBOX_FOBX pVBoxFobx = VBoxMRxGetFileObjectExtension(capFobx); 874 PUNICODE_STRING pRemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext); 875 uint16_t cwcRemainingName = pRemainingName->Length / sizeof(WCHAR); 863 876 864 877 Log(("VBOXSF: vbsfNtRemove: Delete %.*ls. open count = %d\n", 865 RemainingName->Length / sizeof(WCHAR), RemainingName->Buffer, capFcb->OpenCount)); 866 867 /* Close file first if not already done. */ 878 cwcRemainingName, pRemainingName->Buffer, capFcb->OpenCount)); 879 Assert(RxIsFcbAcquiredExclusive(capFcb)); 880 881 /* 882 * We allocate a single request buffer for the closing and deletion to save time. 883 */ 884 AssertCompile(sizeof(VBOXSFCLOSEREQ) <= sizeof(VBOXSFREMOVEREQ)); 885 AssertReturn((cwcRemainingName + 1) * sizeof(RTUTF16) < _64K, STATUS_NAME_TOO_LONG); 886 size_t cbReq = RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String) + (cwcRemainingName + 1) * sizeof(RTUTF16); 887 union MyCloseAndRemoveReq 888 { 889 VBOXSFCLOSEREQ Close; 890 VBOXSFREMOVEREQ Remove; 891 } *pReq = (union MyCloseAndRemoveReq *)VbglR0PhysHeapAlloc((uint32_t)cbReq); 892 if (pReq) 893 RT_ZERO(*pReq); 894 else 895 return STATUS_INSUFFICIENT_RESOURCES; 896 /** @todo Create a function that combines closing and removing since that is 897 * usually what NT guests will be doing. Should in theory speed up deletion by 33%. */ 898 899 /* 900 * Close file first if not already done. We dont use vbsfNtCloseFileHandle here 901 * as we got our own request buffer and have no need to update any file info. 902 */ 868 903 if (pVBoxFobx->hFile != SHFL_HANDLE_NIL) 869 vbsfNtCloseFileHandle(pNetRootExtension, pVBoxFobx, VBoxMRxGetFcbExtension(capFcb)); 870 871 Log(("VBOXSF: vbsfNtRemove: RemainingName->Length %d\n", RemainingName->Length)); 872 Status = vbsfNtShflStringFromUnicodeAlloc(&ParsedPath, RemainingName->Buffer, RemainingName->Length); 873 if (Status != STATUS_SUCCESS) 874 return Status; 875 876 /* Call host. */ 877 vrc = VbglR0SfRemove(&g_SfClient, &pNetRootExtension->map, 878 ParsedPath, 879 pVBoxFobx->Info.Attr.fMode & RTFS_DOS_DIRECTORY ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE); 880 881 if (ParsedPath) 882 vbsfNtFreeNonPagedMem(ParsedPath); 883 884 if (vrc == VINF_SUCCESS) 904 { 905 int vrcClose = VbglR0SfHostReqClose(pNetRootExtension->map.root, &pReq->Close, pVBoxFobx->hFile); 906 pVBoxFobx->hFile = SHFL_HANDLE_NIL; 907 if (RT_FAILURE(vrcClose)) 908 Log(("VBOXSF: vbsfNtRemove: Closing the handle failed! vrcClose %Rrc, hFile %#RX64 (probably)\n", 909 vrcClose, pReq->Close.Parms.u64Handle.u.value64)); 910 } 911 912 /* 913 * Try remove the file. The path to the file/whatever string is 914 * embedded in the request buffer, so we have to assemble it ourselves here. 915 */ 916 uint16_t cwcToCopy = pRemainingName->Length / sizeof(WCHAR); 917 AssertMsg(cwcToCopy == cwcRemainingName, ("%#x, was %#x; FCB exclusivity: %d\n", cwcToCopy, cwcRemainingName, RxIsFcbAcquiredExclusive(capFcb))); 918 if (cwcToCopy <= cwcRemainingName) 919 { /* Extremely likely... */ } 920 else 921 { 922 VbglR0PhysHeapFree(pReq); 923 AssertLogRelMsgFailed(("File scheduled for removal was renamed?!?: %#x from %#x; FCB exclusivity: %d\n", 924 cwcToCopy, cwcRemainingName, RxIsFcbAcquiredExclusive(capFcb))); 925 cwcRemainingName = cwcToCopy; 926 AssertReturn((cwcRemainingName + 1) * sizeof(RTUTF16) < _64K, STATUS_NAME_TOO_LONG); 927 cbReq = RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String) + (cwcRemainingName + 1) * sizeof(RTUTF16); 928 pReq = (union MyCloseAndRemoveReq *)VbglR0PhysHeapAlloc((uint32_t)cbReq); 929 if (pReq) 930 RT_ZERO(*pReq); 931 else 932 return STATUS_INSUFFICIENT_RESOURCES; 933 AssertMsgReturnStmt(cwcToCopy == pRemainingName->Length / sizeof(WCHAR), 934 ("%#x, now %#x;\n", cwcToCopy == pRemainingName->Length / sizeof(WCHAR)), 935 VbglR0PhysHeapFree(pReq), STATUS_INTERNAL_ERROR); 936 } 937 938 memcpy(&pReq->Remove.StrPath.String, pRemainingName->Buffer, cwcToCopy * sizeof(RTUTF16)); 939 pReq->Remove.StrPath.String.utf16[cwcToCopy] = '\0'; 940 pReq->Remove.StrPath.u16Length = cwcToCopy * 2; 941 pReq->Remove.StrPath.u16Size = cwcToCopy * 2 + (uint16_t)sizeof(RTUTF16); 942 int vrc = VbglR0SfHostReqRemove(pNetRootExtension->map.root, &pReq->Remove, 943 pVBoxFobx->Info.Attr.fMode & RTFS_DOS_DIRECTORY ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE); 944 NTSTATUS Status; 945 if (RT_SUCCESS(vrc)) 946 { 885 947 SetFlag(capFobx->pSrvOpen->Flags, SRVOPEN_FLAG_FILE_DELETED); 886 887 Status = vbsfNtVBoxStatusToNt(vrc); 888 if (vrc != VINF_SUCCESS) 948 vbsfNtCleanupFcbxTimestampRefsOnClose(pVBoxFobx, VBoxMRxGetFcbExtension(capFcb)); 949 Status = STATUS_SUCCESS; 950 } 951 else 952 { 889 953 Log(("VBOXSF: vbsfNtRemove: VbglR0SfRemove failed with %Rrc\n", vrc)); 890 891 Log(("VBOXSF: vbsfNtRemove: Returned 0x%08X\n", Status)); 954 Status = vbsfNtVBoxStatusToNt(vrc); 955 } 956 VbglR0PhysHeapFree(pReq); 957 958 Log(("VBOXSF: vbsfNtRemove: Returned %#010X (%Rrc)\n", Status, vrc)); 892 959 return Status; 893 960 }
Note:
See TracChangeset
for help on using the changeset viewer.