VirtualBox

Changeset 78465 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
May 10, 2019 7:11:29 PM (6 years ago)
Author:
vboxsync
Message:

winnt/vboxsf: Converted file & directory removal code to new driver/HGCM interface. bugref:9172

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/SharedFolders/driver/path.cpp

    r78380 r78465  
    695695
    696696/**
    697  * Closes an opened file handle of a MRX_VBOX_FOBX.
     697 * Ensures the FCBx doesn't have dangling pointers to @a pVBoxFobx.
    698698 *
    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.
    702701 */
    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. */
     702DECLINLINE(void) vbsfNtCleanupFcbxTimestampRefsOnClose(PMRX_VBOX_FOBX pVBoxFobx, PVBSFNTFCBEXT pVBoxFcbx)
     703{
    772704    pVBoxFobx->fTimestampsSetByUser          = 0;
    773705    pVBoxFobx->fTimestampsUpdatingSuppressed = 0;
     
    779711    if (pVBoxFcbx->pFobxChangeTime     == pVBoxFobx)
    780712        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 */
     722NTSTATUS 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);
    781791
    782792    /*
     
    794804}
    795805
     806/**
     807 * @note We don't collapse opens, this is called whenever a handle is closed.
     808 */
    796809NTSTATUS VBoxMRxCloseSrvOpen(IN PRX_CONTEXT RxContext)
    797810{
    798     NTSTATUS Status = STATUS_SUCCESS;
    799 
    800811    RxCaptureFcb;
    801812    RxCaptureFobx;
     
    805816    PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen;
    806817
    807     PUNICODE_STRING RemainingName = NULL;
    808818
    809819    Log(("VBOXSF: MRxCloseSrvOpen: capFcb = %p, capFobx = %p, pVBoxFobx = %p, pSrvOpen = %p\n",
    810820          capFcb, capFobx, pVBoxFobx, pSrvOpen));
    811821
    812     RemainingName = pSrvOpen->pAlreadyPrefixedName;
    813 
     822#ifdef LOG_ENABLED
     823    PUNICODE_STRING pRemainingName = pSrvOpen->pAlreadyPrefixedName;
    814824    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
    816827
    817828    if (!pVBoxFobx)
     
    827838    }
    828839
    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     */
    830856    if (pVBoxFobx->hFile != SHFL_HANDLE_NIL)
    831857        vbsfNtCloseFileHandle(pNetRootExtension, pVBoxFobx, VBoxMRxGetFcbExtension(capFcb));
    832858
    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 
    843859    return Status;
    844860}
     
    846862/**
    847863 * 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.
    848867 */
    849868NTSTATUS vbsfNtRemove(IN PRX_CONTEXT RxContext)
    850869{
    851     NTSTATUS Status = STATUS_SUCCESS;
    852 
    853870    RxCaptureFcb;
    854871    RxCaptureFobx;
    855 
    856872    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);
    863876
    864877    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     */
    868903    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    {
    885947        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    {
    889953        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));
    892959    return Status;
    893960}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette