VirtualBox

Changeset 75824 in vbox


Ignore:
Timestamp:
Nov 29, 2018 10:12:53 PM (6 years ago)
Author:
vboxsync
Message:

VBoxGuestControl: Optimizing message handling - part 4. bugref:9313

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/GuestControl.h

    r71517 r75824  
    22/** @file
    33 * Guest Control - Common Guest and Host Code.
     4 *
     5 * @todo r=bird: Just merge this with GuestControlSvc.h!
    46 */
    57
     
    124126#define PATHRENAME_FLAG_NO_SYMLINKS         RT_BIT(1)
    125127/** Mask of valid flags. */
    126 #define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000002)
     128#define PATHRENAME_FLAG_VALID_MASK          UINT32_C(0x00000003)
    127129/** @} */
    128130
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r75801 r75824  
    153153     * Gets the current status of a running process, e.g.
    154154     * new data on stdout/stderr, process terminated etc.
    155      ** Note: Legacy (VBox < 4.3) command.
     155     * @note Legacy (VBox < 4.3) command.
    156156     */
    157157    HOST_EXEC_GET_OUTPUT = 102,
     
    371371    /** Skip message.
    372372     *
    373      * This skips the current message, replying to the sender with
    374      * VERR_NOT_SUPPORTED if appropriate.  No parameters.
     373     * This skips the current message, replying to the main backend as best it can.
     374     * Takes between zero and two parameters.  The first parameter is the 32-bit
     375     * VBox status code to pass onto Main when skipping the command, defaults to
     376     * VERR_NOT_SUPPORTED.  The second parameter is the 32-bit message ID of the
     377     * command to skip, by default whatever is first in the queue is removed.  This
     378     * is also the case if UINT32_MAX is specified.
    375379     *
    376380     * @retval  VINF_SUCCESS on success.
    377381     * @retval  VERR_NOT_FOUND if no message pending.
     382     * @retval  VERR_MISMATCH if the specified message ID didn't match.
    378383     * @retval  VERR_INVALID_CLIENT_ID
    379384     * @retval  VERR_WRONG_PARAMETER_COUNT
     
    615620
    616621/**
    617  * Guest file seeking types. Has to
    618  * match FileSeekType in Main.
     622 * Guest file seeking types. Has to match FileSeekType in Main.
     623 *
     624 * @note This is not compatible with RTFileSeek, which is an unncessary pain.
    619625 */
    620626enum GUEST_FILE_SEEKTYPE
  • trunk/include/VBox/VBoxGuestLib.h

    r75807 r75824  
    752752     *        Use a union for the HGCM stuff then. */
    753753
    754     /** IN: HGCM client ID to use for
    755      *      communication. */
     754    /** IN: HGCM client ID to use for communication. */
    756755    uint32_t uClientID;
    757     /** IN/OUT: Context ID to retrieve
    758      *          or to use. */
     756    /** IN/OUT: Context ID to retrieve or to use. */
    759757    uint32_t uContextID;
    760758    /** IN: Protocol version to use. */
     
    773771VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uType,
    774772                                          void *pvPayload, uint32_t cbPayload);
    775 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient);
     773VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg);
    776774VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId);
    777775VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters);
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp

    r75807 r75824  
    427427 * @return  IPRT status code.
    428428 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
    429  */
    430 VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient)
     429 * @param   rcSkip          The status code to pass back to Main when skipping.
     430 * @param   idMsg           The message ID to skip, pass UINT32_MAX to pass any.
     431 */
     432VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg)
    431433{
    432434    if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
    433435    {
    434         VBGLIOCHGCMCALL Hdr;
    435         VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_SKIP, 0);
    436         return VbglR3HGCMCall(&Hdr, sizeof(Hdr));
     436        struct
     437        {
     438            VBGLIOCHGCMCALL         Hdr;
     439            HGCMFunctionParameter   rcSkip;
     440            HGCMFunctionParameter   idMsg;
     441        } Msg;
     442        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SKIP, 2);
     443        VbglHGCMParmUInt32Set(&Msg.rcSkip, (uint32_t)rcSkip);
     444        VbglHGCMParmUInt32Set(&Msg.idMsg, idMsg);
     445        return VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
    437446    }
    438447
     
    624633                *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
    625634        }
    626         /* Try get the context ID so we can inform the host about this message retrival failure. */
    627         else if (Msg.context.u.value32 != HOST_SESSION_CREATE)
    628             Msg.context.GetUInt32(&pCtx->uContextID);
    629635
    630636    } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
     
    666672
    667673/**
    668  * Retrieves a HOST_SESSION_CLOSE message.
     674 * Retrieves a HOST_PATH_RENAME message.
    669675 */
    670676VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX     pCtx,
     
    698704            Msg.flags.GetUInt32(pfFlags);
    699705        }
     706
    700707    } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
    701708    return rc;
     
    913920        }
    914921    } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
    915     return rc;
     922
     923    if (   rc != VERR_TOO_MUCH_DATA
     924        || g_fVbglR3GuestCtrlHavePeekGetCancel)
     925        return rc;
     926    return VERR_BUFFER_OVERFLOW;
    916927}
    917928
     
    11291140        }
    11301141    } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
    1131     return rc;
     1142
     1143    if (   rc != VERR_TOO_MUCH_DATA
     1144        || g_fVbglR3GuestCtrlHavePeekGetCancel)
     1145        return rc;
     1146    return VERR_BUFFER_OVERFLOW;
    11321147}
    11331148
     
    11671182        }
    11681183    } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
    1169     return rc;
     1184
     1185    if (   rc != VERR_TOO_MUCH_DATA
     1186        || g_fVbglR3GuestCtrlHavePeekGetCancel)
     1187        return rc;
     1188    return VERR_BUFFER_OVERFLOW;
    11701189}
    11711190
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r75807 r75824  
    306306                    if (VbglR3GuestCtrlSupportsOptimizations(g_idControlSvcClient))
    307307                    {
    308                         rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient);
     308                        rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient, VERR_NOT_SUPPORTED, idMsg);
    309309                        VGSvcVerbose(1, "Skipped unexpected message idMsg=%RU32 (%s), cParms=%RU32 (rc=%Rrc)\n",
    310310                                     idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms, rc);
     
    421421        }
    422422    }
    423     /*
    424      * If we cannot retrieve the message, make sure to skip the command.
    425      *
    426      * Note! If we totally failed to get any valid context ID, the host will
    427      *       not see the notification and be stuck till it times out.
    428      */
    429423    else
    430424    {
    431         VGSvcError("Error fetching guest session parameters: %Rrc\n", rc);
    432         VbglR3GuestCtrlSessionNotify(pHostCtx, GUEST_SESSION_NOTIFYTYPE_ERROR, rc);
    433         VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID);
     425        VGSvcError("Error fetching parameters for opening guest session: %Rrc\n", rc);
     426        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
    434427    }
    435428    VGSvcVerbose(3, "Opening a new guest session returned rc=%Rrc\n", rc);
     
    442435    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    443436
    444     uint32_t uSessionID;
     437    uint32_t idSession;
    445438    uint32_t fFlags;
    446     int rc = VbglR3GuestCtrlSessionGetClose(pHostCtx, &fFlags, &uSessionID);
     439    int rc = VbglR3GuestCtrlSessionGetClose(pHostCtx, &fFlags, &idSession);
    447440    if (RT_SUCCESS(rc))
    448441    {
     
    452445        RTListForEach(&g_lstControlSessionThreads, pThread, VBOXSERVICECTRLSESSIONTHREAD, Node)
    453446        {
    454             if (pThread->StartupInfo.uSessionID == uSessionID)
     447            if (pThread->StartupInfo.uSessionID == idSession)
    455448            {
    456449                rc = VGSvcGstCtrlSessionThreadDestroy(pThread, fFlags);
     
    458451            }
    459452        }
    460 #if 0
     453
     454#if 0 /** @todo A bit of a mess here as this message goes to both to this process (master) and the session process. */
    461455        if (RT_FAILURE(rc))
    462456        {
     
    473467        }
    474468#endif
    475         VGSvcVerbose(2, "Closing guest session %RU32 returned rc=%Rrc\n", uSessionID, rc);
     469        VGSvcVerbose(2, "Closing guest session %RU32 returned rc=%Rrc\n", idSession, rc);
    476470    }
    477471    else
    478         VGSvcError("Closing guest session %RU32 failed with rc=%Rrc\n", uSessionID, rc);
     472    {
     473        VGSvcError("Error fetching parameters for closing guest session: %Rrc\n", rc);
     474        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     475    }
    479476    return rc;
    480477}
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r75807 r75824  
    6262
    6363
     64/**
     65 * Helper that grows the scratch buffer.
     66 * @returns Success indicator.
     67 */
     68static bool vgsvcGstCtrlSessionGrowScratchBuf(void **ppvScratchBuf, uint32_t *pcbScratchBuf, uint32_t cbMinBuf)
     69{
     70    uint32_t cbNew = *pcbScratchBuf * 2;
     71    if (   cbNew    <= VMMDEV_MAX_HGCM_DATA_SIZE
     72        && cbMinBuf <= VMMDEV_MAX_HGCM_DATA_SIZE)
     73    {
     74        while (cbMinBuf > cbNew)
     75            cbNew *= 2;
     76        void *pvNew = RTMemRealloc(*ppvScratchBuf, cbNew);
     77        if (pvNew)
     78        {
     79            *ppvScratchBuf = pvNew;
     80            *pcbScratchBuf = cbNew;
     81            return true;
     82        }
     83    }
     84    return false;
     85}
     86
     87
    6488
    6589static int vgsvcGstCtrlSessionFileDestroy(PVBOXSERVICECTRLFILE pFile)
     
    102126    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    103127
    104     char szDir[RTPATH_MAX];
    105     uint32_t fFlags = 0;
    106 
    107     int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx,
    108                                          /* Directory to remove. */
    109                                          szDir, sizeof(szDir),
    110                                          /* Flags of type DIRREMOVE_FLAG_. */
    111                                          &fFlags);
    112     if (RT_SUCCESS(rc))
    113     {
    114         AssertReturn(!(fFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
     128    /*
     129     * Retrieve the message.
     130     */
     131    char        szDir[RTPATH_MAX];
     132    uint32_t    fFlags; /* DIRREMOVE_FLAG_XXX */
     133    int rc = VbglR3GuestCtrlDirGetRemove(pHostCtx, szDir, sizeof(szDir), &fFlags);
     134    if (RT_SUCCESS(rc))
     135    {
     136        /*
     137         * Do some validating before executing the job.
     138         */
    115139        if (!(fFlags & ~DIRREMOVE_FLAG_VALID_MASK))
    116140        {
     
    120144                if (fFlags & DIRREMOVE_FLAG_CONTENT_ONLY)
    121145                    fFlagsRemRec |= RTDIRRMREC_F_CONTENT_ONLY;
    122 
    123146                rc = RTDirRemoveRecursive(szDir, fFlagsRemRec);
     147                VGSvcVerbose(4, "[Dir %s]: rmdir /s (%#x) -> rc=%Rrc\n", szDir, fFlags, rc);
    124148            }
    125             else /* Only delete directory if not empty. */
     149            else
     150            {
     151                /* Only delete directory if not empty. */
    126152                rc = RTDirRemove(szDir);
     153                VGSvcVerbose(4, "[Dir %s]: rmdir (%#x), rc=%Rrc\n", szDir, fFlags, rc);
     154            }
    127155        }
    128156        else
     157        {
     158            VGSvcError("[Dir %s]: Unsupported flags: %#x (all %#x)\n", szDir, (fFlags & ~DIRREMOVE_FLAG_VALID_MASK), fFlags);
    129159            rc = VERR_NOT_SUPPORTED;
    130 
    131         VGSvcVerbose(4, "[Dir %s]: Removing with fFlags=0x%x, rc=%Rrc\n", szDir, fFlags, rc);
    132 
    133         /* Report back in any case. */
     160        }
     161
     162        /*
     163         * Report result back to host.
     164         */
    134165        int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
    135166        if (RT_FAILURE(rc2))
     167        {
    136168            VGSvcError("[Dir %s]: Failed to report removing status, rc=%Rrc\n", szDir, rc2);
    137         if (RT_SUCCESS(rc))
    138             rc = rc2;
    139     }
    140 
    141 #ifdef DEBUG
    142     VGSvcVerbose(4, "Removing directory '%s' returned rc=%Rrc\n", szDir, rc);
    143 #endif
     169            if (RT_SUCCESS(rc))
     170                rc = rc2;
     171        }
     172    }
     173    else
     174    {
     175        VGSvcError("Error fetching parameters for rmdir operation: %Rrc\n", rc);
     176        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     177    }
     178
     179    VGSvcVerbose(6, "Removing directory '%s' returned rc=%Rrc\n", szDir, rc);
    144180    return rc;
    145181}
     
    151187    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    152188
    153     char szFile[RTPATH_MAX];
    154     char szAccess[64];
    155     char szDisposition[64];
    156     char szSharing[64];
     189    /*
     190     * Retrieve the message.
     191     */
     192    char     szFile[RTPATH_MAX];
     193    char     szAccess[64];
     194    char     szDisposition[64];
     195    char     szSharing[64];
    157196    uint32_t uCreationMode = 0;
    158     uint64_t offOpen = 0;
    159     uint32_t uHandle = 0;
    160 
     197    uint64_t offOpen       = 0;
     198    uint32_t uHandle       = 0;
    161199    int rc = VbglR3GuestCtrlFileGetOpen(pHostCtx,
    162200                                        /* File to open. */
     
    179217        if (pFile)
    180218        {
    181             if (!strlen(szFile))
    182                 rc = VERR_INVALID_PARAMETER;
    183 
    184             if (RT_SUCCESS(rc))
     219            pFile->hFile = NIL_RTFILE; /* Not zero or NULL! */
     220            if (szFile[0])
    185221            {
    186222                RTStrCopy(pFile->szName, sizeof(pFile->szName), szFile);
    187223
     224/** @todo
     225 * Implement szSharing!
     226 */
    188227                uint64_t fFlags;
    189228                rc = RTFileModeToFlagsEx(szAccess, szDisposition, NULL /* pszSharing, not used yet */, &fFlags);
    190229                VGSvcVerbose(4, "[File %s] Opening with fFlags=0x%x, rc=%Rrc\n", pFile->szName, fFlags, rc);
    191 
    192230                if (RT_SUCCESS(rc))
     231                {
    193232                    rc = RTFileOpen(&pFile->hFile, pFile->szName, fFlags);
    194                 if (   RT_SUCCESS(rc)
    195                     && offOpen)
    196                 {
    197                     /* Seeking is optional. However, the whole operation
    198                      * will fail if we don't succeed seeking to the wanted position. */
    199                     rc = RTFileSeek(pFile->hFile, (int64_t)offOpen, RTFILE_SEEK_BEGIN, NULL /* Current offset */);
    200                     if (RT_FAILURE(rc))
    201                         VGSvcError("[File %s] Seeking to offset %RU64 failed; rc=%Rrc\n", pFile->szName, offOpen, rc);
     233                    if (RT_SUCCESS(rc))
     234                    {
     235                        /* Seeking is optional. However, the whole operation
     236                         * will fail if we don't succeed seeking to the wanted position. */
     237                        if (offOpen)
     238                            rc = RTFileSeek(pFile->hFile, (int64_t)offOpen, RTFILE_SEEK_BEGIN, NULL /* Current offset */);
     239                        if (RT_SUCCESS(rc))
     240                        {
     241                            /*
     242                             * Succeeded!
     243                             */
     244                            uHandle = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHostCtx->uContextID);
     245                            pFile->uHandle = uHandle;
     246                            RTListAppend(&pSession->lstFiles, &pFile->Node);
     247                            VGSvcVerbose(2, "[File %s] Opened (ID=%RU32)\n", pFile->szName, pFile->uHandle);
     248                        }
     249                        else
     250                            VGSvcError("[File %s] Seeking to offset %RU64 failed: rc=%Rrc\n", pFile->szName, offOpen, rc);
     251                    }
     252                    else
     253                        VGSvcError("[File %s] Opening failed with rc=%Rrc\n", pFile->szName, rc);
    202254                }
    203                 else if (RT_FAILURE(rc))
    204                     VGSvcError("[File %s] Opening failed with rc=%Rrc\n", pFile->szName, rc);
    205255            }
    206 
    207             if (RT_SUCCESS(rc))
     256            else
    208257            {
    209                 uHandle = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHostCtx->uContextID);
    210                 pFile->uHandle = uHandle;
    211 
    212                 RTListAppend(&pSession->lstFiles, &pFile->Node);
    213 
    214                 VGSvcVerbose(2, "[File %s] Opened (ID=%RU32)\n", pFile->szName, pFile->uHandle);
     258                VGSvcError("[File %s] empty filename!\n");
     259                rc = VERR_INVALID_NAME;
    215260            }
    216261
     262            /* clean up if we failed. */
    217263            if (RT_FAILURE(rc))
    218264            {
    219                 if (pFile->hFile)
     265                if (pFile->hFile != NIL_RTFILE)
    220266                    RTFileClose(pFile->hFile);
    221267                RTMemFree(pFile);
     
    225271            rc = VERR_NO_MEMORY;
    226272
    227         /* Report back in any case. */
     273        /*
     274         * Report result back to host.
     275         */
    228276        int rc2 = VbglR3GuestCtrlFileCbOpen(pHostCtx, rc, uHandle);
    229277        if (RT_FAILURE(rc2))
     278        {
    230279            VGSvcError("[File %s]: Failed to report file open status, rc=%Rrc\n", szFile, rc2);
    231         if (RT_SUCCESS(rc))
    232             rc = rc2;
     280            if (RT_SUCCESS(rc))
     281                rc = rc2;
     282        }
     283    }
     284    else
     285    {
     286        VGSvcError("Error fetching parameters for open file operation: %Rrc\n", rc);
     287        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
    233288    }
    234289
     
    244299    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    245300
     301    /*
     302     * Retrieve the message.
     303     */
    246304    uint32_t uHandle = 0;
    247305    int rc = VbglR3GuestCtrlFileGetClose(pHostCtx, &uHandle /* File handle to close */);
     
    252310        {
    253311            VGSvcVerbose(2, "[File %s] Closing (handle=%RU32)\n", pFile ? pFile->szName : "<Not found>", uHandle);
    254 
    255312            rc = vgsvcGstCtrlSessionFileDestroy(pFile);
    256313        }
    257314        else
     315        {
     316            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
    258317            rc = VERR_NOT_FOUND;
    259 
    260         /* Report back in any case. */
     318        }
     319
     320        /*
     321         * Report result back to host.
     322         */
    261323        int rc2 = VbglR3GuestCtrlFileCbClose(pHostCtx, rc);
    262324        if (RT_FAILURE(rc2))
     325        {
    263326            VGSvcError("Failed to report file close status, rc=%Rrc\n", rc2);
    264         if (RT_SUCCESS(rc))
    265             rc = rc2;
    266     }
    267 
     327            if (RT_SUCCESS(rc))
     328                rc = rc2;
     329        }
     330    }
     331    else
     332    {
     333        VGSvcError("Error fetching parameters for close file operation: %Rrc\n", rc);
     334        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     335    }
    268336    return rc;
    269337}
     
    271339
    272340static int vgsvcGstCtrlSessionHandleFileRead(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
    273                                              void *pvScratchBuf, size_t cbScratchBuf)
     341                                             void **ppvScratchBuf, uint32_t *pcbScratchBuf)
    274342{
    275343    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    276344    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    277345
     346    /*
     347     * Retrieve the request.
     348     */
    278349    uint32_t uHandle = 0;
    279350    uint32_t cbToRead;
     
    281352    if (RT_SUCCESS(rc))
    282353    {
    283         void *pvDataRead = pvScratchBuf;
     354        /*
     355         * Locate the file and do the reading.
     356         *
     357         * If the request is larger than our scratch buffer, try grow it - just
     358         * ignore failure as the host better respect our buffer limits.
     359         */
    284360        size_t cbRead = 0;
    285 
    286361        PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
    287362        if (pFile)
    288363        {
    289             if (cbToRead)
    290             {
    291                 if (cbToRead > cbScratchBuf)
    292                 {
    293                     pvDataRead = RTMemAlloc(cbToRead);
    294                     if (!pvDataRead)
    295                         rc = VERR_NO_MEMORY;
    296                 }
    297 
    298                 if (RT_LIKELY(RT_SUCCESS(rc)))
    299                     rc = RTFileRead(pFile->hFile, pvDataRead, cbToRead, &cbRead);
    300             }
    301             else
    302                 rc = VERR_BUFFER_UNDERFLOW;
     364            if (*pcbScratchBuf < cbToRead)
     365                 vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToRead);
     366
     367            rc = RTFileRead(pFile->hFile, *ppvScratchBuf, RT_MIN(cbToRead, *pcbScratchBuf), &cbRead);
     368            VGSvcVerbose(5, "[File %s] Read %zu/%RU32 bytes, rc=%Rrc\n", pFile->szName, cbRead, cbToRead, rc);
    303369        }
    304370        else
     371        {
     372            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
    305373            rc = VERR_NOT_FOUND;
    306 
    307         VGSvcVerbose(4, "[File %s] Read %zu/%RU32 bytes, rc=%Rrc\n", pFile ? pFile->szName : "<Not found>", cbRead, cbToRead, rc);
    308 
    309         /* Report back in any case. */
    310         int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, pvDataRead, (uint32_t)cbRead);
    311         if (   cbToRead > cbScratchBuf
    312             && pvDataRead)
    313             RTMemFree(pvDataRead);
    314 
     374        }
     375
     376        /*
     377         * Report result and data back to the host.
     378         */
     379        int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, *ppvScratchBuf, (uint32_t)cbRead);
    315380        if (RT_FAILURE(rc2))
     381        {
    316382            VGSvcError("Failed to report file read status, rc=%Rrc\n", rc2);
    317         if (RT_SUCCESS(rc))
    318             rc = rc2;
    319     }
    320 
     383            if (RT_SUCCESS(rc))
     384                rc = rc2;
     385        }
     386    }
     387    else
     388    {
     389        VGSvcError("Error fetching parameters for file read operation: %Rrc\n", rc);
     390        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     391    }
    321392    return rc;
    322393}
     
    324395
    325396static int vgsvcGstCtrlSessionHandleFileReadAt(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
    326                                                void *pvScratchBuf, size_t cbScratchBuf)
     397                                               void **ppvScratchBuf, uint32_t *pcbScratchBuf)
    327398{
    328399    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    329400    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    330401
     402    /*
     403     * Retrieve the request.
     404     */
    331405    uint32_t uHandle = 0;
    332406    uint32_t cbToRead;
     
    335409    if (RT_SUCCESS(rc))
    336410    {
    337         void *pvDataRead = pvScratchBuf;
     411        /*
     412         * Locate the file and do the reading.
     413         *
     414         * If the request is larger than our scratch buffer, try grow it - just
     415         * ignore failure as the host better respect our buffer limits.
     416         */
    338417        size_t cbRead = 0;
    339 
    340418        PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
    341419        if (pFile)
    342420        {
    343             if (cbToRead)
    344             {
    345                 if (cbToRead > cbScratchBuf)
    346                 {
    347                     pvDataRead = RTMemAlloc(cbToRead);
    348                     if (!pvDataRead)
    349                         rc = VERR_NO_MEMORY;
    350                 }
    351 
    352                 if (RT_SUCCESS(rc))
    353                     rc = RTFileReadAt(pFile->hFile, (RTFOFF)offReadAt, pvDataRead, cbToRead, &cbRead);
    354 
    355                 VGSvcVerbose(4, "[File %s] Read %zu bytes @ %RU64, rc=%Rrc\n",
    356                              pFile ? pFile->szName : "<Not found>", cbRead, offReadAt, rc);
    357             }
    358             else
    359                 rc = VERR_BUFFER_UNDERFLOW;
     421            if (*pcbScratchBuf < cbToRead)
     422                 vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToRead);
     423
     424            rc = RTFileReadAt(pFile->hFile, (RTFOFF)offReadAt, *ppvScratchBuf, RT_MIN(cbToRead, *pcbScratchBuf), &cbRead);
     425            VGSvcVerbose(5, "[File %s] Read %zu bytes @ %RU64, rc=%Rrc\n", pFile->szName, cbRead, offReadAt, rc);
    360426        }
    361427        else
     428        {
     429            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
    362430            rc = VERR_NOT_FOUND;
    363 
    364         /* Report back in any case. */
    365         int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, pvDataRead, (uint32_t)cbRead);
    366         if (   cbToRead > cbScratchBuf
    367             && pvDataRead)
    368             RTMemFree(pvDataRead);
    369 
     431        }
     432
     433        /*
     434         * Report result and data back to the host.
     435         */
     436        int rc2 = VbglR3GuestCtrlFileCbRead(pHostCtx, rc, *ppvScratchBuf, (uint32_t)cbRead);
    370437        if (RT_FAILURE(rc2))
    371             VGSvcError("Failed to report file read status, rc=%Rrc\n", rc2);
    372         if (RT_SUCCESS(rc))
    373             rc = rc2;
    374     }
    375 
     438        {
     439            VGSvcError("Failed to report file read at status, rc=%Rrc\n", rc2);
     440            if (RT_SUCCESS(rc))
     441                rc = rc2;
     442        }
     443    }
     444    else
     445    {
     446        VGSvcError("Error fetching parameters for file read at operation: %Rrc\n", rc);
     447        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     448    }
    376449    return rc;
    377450}
     
    379452
    380453static int vgsvcGstCtrlSessionHandleFileWrite(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
    381                                               void *pvScratchBuf, size_t cbScratchBuf)
     454                                              void **ppvScratchBuf, uint32_t *pcbScratchBuf)
    382455{
    383456    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    384457    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    385     AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
    386     AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER);
    387 
     458
     459    /*
     460     * Retrieve the request and data to write.
     461     */
    388462    uint32_t uHandle = 0;
    389463    uint32_t cbToWrite;
    390     int rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, pvScratchBuf, (uint32_t)cbScratchBuf, &cbToWrite);
    391     if (RT_SUCCESS(rc))
    392     {
    393         /* Make sure that we only write up to cbScratchBuf bytes. */
    394         if (cbToWrite > (uint32_t)cbScratchBuf)
    395             cbToWrite = (uint32_t)cbScratchBuf;
    396 
     464    int rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite);
     465    if (   rc == VERR_BUFFER_OVERFLOW
     466        && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToWrite))
     467        rc = VbglR3GuestCtrlFileGetWrite(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite);
     468    if (RT_SUCCESS(rc))
     469    {
     470        /*
     471         * Locate the file and do the writing.
     472         */
    397473        size_t cbWritten = 0;
    398474        PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
    399475        if (pFile)
    400476        {
    401             rc = RTFileWrite(pFile->hFile, pvScratchBuf, cbToWrite, &cbWritten);
    402 #ifdef DEBUG
    403             VGSvcVerbose(4, "[File %s] Writing pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n",
    404                          pFile->szName, pvScratchBuf, cbToWrite, cbWritten, rc);
    405 #endif
     477            rc = RTFileWrite(pFile->hFile, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), &cbWritten);
     478            VGSvcVerbose(5, "[File %s] Writing %p LB %RU32 =>  %Rrc, cbWritten=%zu\n",
     479                         pFile->szName, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), rc, cbWritten);
    406480        }
    407481        else
     482        {
     483            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
    408484            rc = VERR_NOT_FOUND;
    409 
    410         /* Report back in any case. */
     485        }
     486
     487        /*
     488         * Report result back to host.
     489         */
    411490        int rc2 = VbglR3GuestCtrlFileCbWrite(pHostCtx, rc, (uint32_t)cbWritten);
    412491        if (RT_FAILURE(rc2))
     492        {
    413493            VGSvcError("Failed to report file write status, rc=%Rrc\n", rc2);
    414         if (RT_SUCCESS(rc))
    415             rc = rc2;
    416     }
    417 
     494            if (RT_SUCCESS(rc))
     495                rc = rc2;
     496        }
     497    }
     498    else
     499    {
     500        VGSvcError("Error fetching parameters for file write operation: %Rrc\n", rc);
     501        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     502    }
    418503    return rc;
    419504}
     
    421506
    422507static int vgsvcGstCtrlSessionHandleFileWriteAt(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
    423                                                 void *pvScratchBuf, size_t cbScratchBuf)
     508                                                void **ppvScratchBuf, uint32_t *pcbScratchBuf)
    424509{
    425510    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    426511    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    427     AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
    428     AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER);
    429 
     512
     513    /*
     514     * Retrieve the request and data to write.
     515     */
    430516    uint32_t uHandle = 0;
    431517    uint32_t cbToWrite;
    432518    uint64_t offWriteAt;
    433 
    434     int rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, pvScratchBuf, (uint32_t)cbScratchBuf, &cbToWrite, &offWriteAt);
    435     if (RT_SUCCESS(rc))
    436     {
     519    int rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite, &offWriteAt);
     520    if (   rc == VERR_BUFFER_OVERFLOW
     521        && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbToWrite))
     522        rc = VbglR3GuestCtrlFileGetWriteAt(pHostCtx, &uHandle, *ppvScratchBuf, *pcbScratchBuf, &cbToWrite, &offWriteAt);
     523    if (RT_SUCCESS(rc))
     524    {
     525        /*
     526         * Locate the file and do the writing.
     527         */
    437528        size_t cbWritten = 0;
    438529        PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
    439530        if (pFile)
    440531        {
    441             rc = RTFileWriteAt(pFile->hFile, (RTFOFF)offWriteAt, pvScratchBuf, cbToWrite, &cbWritten);
    442 #ifdef DEBUG
    443             VGSvcVerbose(4, "[File %s] Writing offWriteAt=%RI64, pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n",
    444                          pFile->szName, offWriteAt, pvScratchBuf, cbToWrite, cbWritten, rc);
    445 #endif
     532            rc = RTFileWriteAt(pFile->hFile, (RTFOFF)offWriteAt, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), &cbWritten);
     533            VGSvcVerbose(5, "[File %s] Writing %p LB %RU32 @ %RU64 =>  %Rrc, cbWritten=%zu\n",
     534                         pFile->szName, *ppvScratchBuf, RT_MIN(cbToWrite, *pcbScratchBuf), offWriteAt, rc, cbWritten);
    446535        }
    447536        else
     537        {
     538            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
    448539            rc = VERR_NOT_FOUND;
    449 
    450         /* Report back in any case. */
     540        }
     541
     542        /*
     543         * Report result back to host.
     544         */
    451545        int rc2 = VbglR3GuestCtrlFileCbWrite(pHostCtx, rc, (uint32_t)cbWritten);
    452546        if (RT_FAILURE(rc2))
     547        {
    453548            VGSvcError("Failed to report file write status, rc=%Rrc\n", rc2);
    454         if (RT_SUCCESS(rc))
    455             rc = rc2;
    456     }
    457 
     549            if (RT_SUCCESS(rc))
     550                rc = rc2;
     551        }
     552    }
     553    else
     554    {
     555        VGSvcError("Error fetching parameters for file write at operation: %Rrc\n", rc);
     556        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     557    }
    458558    return rc;
    459559}
     
    465565    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    466566
     567    /*
     568     * Retrieve the request.
     569     */
    467570    uint32_t uHandle = 0;
    468571    uint32_t uSeekMethod;
     
    472575    {
    473576        uint64_t offActual = 0;
     577
     578        /*
     579         * Validate and convert the seek method to IPRT speak.
     580         */
     581        static const uint8_t s_abMethods[GUEST_FILE_SEEKTYPE_END + 1] =
     582        {
     583            UINT8_MAX, RTFILE_SEEK_BEGIN, UINT8_MAX, UINT8_MAX, RTFILE_SEEK_CURRENT,
     584            UINT8_MAX, UINT8_MAX, UINT8_MAX, GUEST_FILE_SEEKTYPE_END
     585        };
     586        if (   uSeekMethod < RT_ELEMENTS(s_abMethods)
     587            && s_abMethods[uSeekMethod] != UINT8_MAX)
     588        {
     589            /*
     590             * Locate the file and do the seek.
     591             */
     592            PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
     593            if (pFile)
     594            {
     595                rc = RTFileSeek(pFile->hFile, (int64_t)offSeek, s_abMethods[uSeekMethod], &offActual);
     596                VGSvcVerbose(5, "[File %s]: Seeking to offSeek=%RI64, uSeekMethodIPRT=%u, rc=%Rrc\n",
     597                             pFile->szName, offSeek, s_abMethods[uSeekMethod], rc);
     598            }
     599            else
     600            {
     601                VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
     602                rc = VERR_NOT_FOUND;
     603            }
     604        }
     605        else
     606        {
     607            VGSvcError("Invalid seek method: %#x\n", uSeekMethod);
     608            rc = VERR_NOT_SUPPORTED;
     609        }
     610
     611        /*
     612         * Report result back to host.
     613         */
     614        int rc2 = VbglR3GuestCtrlFileCbSeek(pHostCtx, rc, offActual);
     615        if (RT_FAILURE(rc2))
     616        {
     617            VGSvcError("Failed to report file seek status, rc=%Rrc\n", rc2);
     618            if (RT_SUCCESS(rc))
     619                rc = rc2;
     620        }
     621    }
     622    else
     623    {
     624        VGSvcError("Error fetching parameters for file seek operation: %Rrc\n", rc);
     625        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     626    }
     627    return rc;
     628}
     629
     630
     631static int vgsvcGstCtrlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
     632{
     633    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     634    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
     635
     636    /*
     637     * Retrieve the request.
     638     */
     639    uint32_t uHandle = 0;
     640    int rc = VbglR3GuestCtrlFileGetTell(pHostCtx, &uHandle);
     641    if (RT_SUCCESS(rc))
     642    {
     643        /*
     644         * Locate the file and ask for the current position.
     645         */
     646        uint64_t offCurrent = 0;
    474647        PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
    475648        if (pFile)
    476649        {
    477             unsigned uSeekMethodIprt;
    478             switch (uSeekMethod)
    479             {
    480                 case GUEST_FILE_SEEKTYPE_BEGIN:
    481                     uSeekMethodIprt = RTFILE_SEEK_BEGIN;
    482                     break;
    483 
    484                 case GUEST_FILE_SEEKTYPE_CURRENT:
    485                     uSeekMethodIprt = RTFILE_SEEK_CURRENT;
    486                     break;
    487 
    488                 case GUEST_FILE_SEEKTYPE_END:
    489                     uSeekMethodIprt = RTFILE_SEEK_END;
    490                     break;
    491 
    492                 default:
    493                     rc = VERR_NOT_SUPPORTED;
    494                     uSeekMethodIprt = RTFILE_SEEK_BEGIN; /* Shut up MSC */
    495                     break;
    496             }
    497 
     650            offCurrent = RTFileTell(pFile->hFile);
     651            VGSvcVerbose(5, "[File %s]: Telling offCurrent=%RU64\n", pFile->szName, offCurrent);
     652        }
     653        else
     654        {
     655            VGSvcError("File %u (%#x) not found!\n", uHandle, uHandle);
     656            rc = VERR_NOT_FOUND;
     657        }
     658
     659        /*
     660         * Report result back to host.
     661         */
     662        int rc2 = VbglR3GuestCtrlFileCbTell(pHostCtx, rc, offCurrent);
     663        if (RT_FAILURE(rc2))
     664        {
     665            VGSvcError("Failed to report file tell status, rc=%Rrc\n", rc2);
    498666            if (RT_SUCCESS(rc))
    499             {
    500                 rc = RTFileSeek(pFile->hFile, (int64_t)offSeek, uSeekMethodIprt, &offActual);
    501 #ifdef DEBUG
    502                 VGSvcVerbose(4, "[File %s]: Seeking to offSeek=%RI64, uSeekMethodIPRT=%RU16, rc=%Rrc\n",
    503                              pFile->szName, offSeek, uSeekMethodIprt, rc);
    504 #endif
    505             }
    506         }
    507         else
    508             rc = VERR_NOT_FOUND;
    509 
    510         /* Report back in any case. */
    511         int rc2 = VbglR3GuestCtrlFileCbSeek(pHostCtx, rc, offActual);
    512         if (RT_FAILURE(rc2))
    513             VGSvcError("Failed to report file seek status, rc=%Rrc\n", rc2);
    514         if (RT_SUCCESS(rc))
    515             rc = rc2;
    516     }
    517 
    518     return rc;
    519 }
    520 
    521 
    522 static int vgsvcGstCtrlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
     667                rc = rc2;
     668        }
     669    }
     670    else
     671    {
     672        VGSvcError("Error fetching parameters for file tell operation: %Rrc\n", rc);
     673        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     674    }
     675    return rc;
     676}
     677
     678
     679static int vgsvcGstCtrlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
    523680{
    524681    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    525682    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    526683
    527     uint32_t uHandle = 0;
    528     int rc = VbglR3GuestCtrlFileGetTell(pHostCtx, &uHandle);
    529     if (RT_SUCCESS(rc))
    530     {
    531         uint64_t uOffCurrent = 0;
    532         PVBOXSERVICECTRLFILE pFile = vgsvcGstCtrlSessionFileGetLocked(pSession, uHandle);
    533         if (pFile)
    534         {
    535             uOffCurrent = RTFileTell(pFile->hFile);
    536 #ifdef DEBUG
    537             VGSvcVerbose(4, "[File %s]: Telling uOffCurrent=%RU64\n", pFile->szName, uOffCurrent);
    538 #endif
     684    /*
     685     * Retrieve the request.
     686     */
     687    char     szSource[RTPATH_MAX];
     688    char     szDest[RTPATH_MAX];
     689    uint32_t fFlags = 0; /* PATHRENAME_FLAG_XXX */
     690    int rc = VbglR3GuestCtrlPathGetRename(pHostCtx, szSource, sizeof(szSource), szDest, sizeof(szDest), &fFlags);
     691    if (RT_SUCCESS(rc))
     692    {
     693        /*
     694         * Validate the flags (kudos for using the same as IPRT), then do the renaming.
     695         */
     696        AssertCompile(PATHRENAME_FLAG_NO_REPLACE  == RTPATHRENAME_FLAGS_NO_REPLACE);
     697        AssertCompile(PATHRENAME_FLAG_REPLACE     == RTPATHRENAME_FLAGS_REPLACE);
     698        AssertCompile(PATHRENAME_FLAG_NO_SYMLINKS == RTPATHRENAME_FLAGS_NO_SYMLINKS);
     699        AssertCompile(PATHRENAME_FLAG_VALID_MASK  == (RTPATHRENAME_FLAGS_NO_REPLACE | RTPATHRENAME_FLAGS_REPLACE | RTPATHRENAME_FLAGS_NO_SYMLINKS));
     700        if (!(fFlags & ~PATHRENAME_FLAG_VALID_MASK))
     701        {
     702            VGSvcVerbose(4, "Renaming '%s' to '%s', fFlags=%#x, rc=%Rrc\n", szSource, szDest, fFlags, rc);
     703            rc = RTPathRename(szSource, szDest, fFlags);
    539704        }
    540705        else
    541             rc = VERR_NOT_FOUND;
    542 
    543         /* Report back in any case. */
    544         int rc2 = VbglR3GuestCtrlFileCbTell(pHostCtx, rc, uOffCurrent);
    545         if (RT_FAILURE(rc2))
    546             VGSvcError("Failed to report file tell status, rc=%Rrc\n", rc2);
    547         if (RT_SUCCESS(rc))
    548             rc = rc2;
    549     }
    550 
    551     return rc;
    552 }
    553 
    554 
    555 static int vgsvcGstCtrlSessionHandlePathRename(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx)
    556 {
    557     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    558     AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    559 
    560     char szSource[RTPATH_MAX];
    561     char szDest[RTPATH_MAX];
    562     uint32_t fFlags = 0;
    563 
    564     int rc = VbglR3GuestCtrlPathGetRename(pHostCtx,
    565                                           szSource, sizeof(szSource),
    566                                           szDest, sizeof(szDest),
    567                                           /* Flags of type PATHRENAME_FLAG_. */
    568                                           &fFlags);
    569     if (RT_SUCCESS(rc))
    570     {
    571         if (fFlags & ~PATHRENAME_FLAG_VALID_MASK)
     706        {
     707            VGSvcError("Invalid rename flags: %#x\n", fFlags);
    572708            rc = VERR_NOT_SUPPORTED;
    573 
    574         VGSvcVerbose(4, "Renaming '%s' to '%s', fFlags=0x%x, rc=%Rrc\n", szSource, szDest, fFlags, rc);
    575 
    576         if (RT_SUCCESS(rc))
    577         {
    578             unsigned fPathRenameFlags = 0;
    579 
    580             if (fFlags & PATHRENAME_FLAG_NO_REPLACE)
    581                 fPathRenameFlags |= RTPATHRENAME_FLAGS_NO_REPLACE;
    582 
    583             if (fFlags & PATHRENAME_FLAG_REPLACE)
    584                 fPathRenameFlags |= RTPATHRENAME_FLAGS_REPLACE;
    585 
    586             if (fFlags & PATHRENAME_FLAG_NO_SYMLINKS)
    587                 fPathRenameFlags |= RTPATHRENAME_FLAGS_NO_SYMLINKS;
    588 
    589             rc = RTPathRename(szSource, szDest, fPathRenameFlags);
    590         }
    591 
    592         /* Report back in any case. */
     709        }
     710
     711        /*
     712         * Report result back to host.
     713         */
    593714        int rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, rc);
    594715        if (RT_FAILURE(rc2))
     716        {
    595717            VGSvcError("Failed to report renaming status, rc=%Rrc\n", rc2);
    596         if (RT_SUCCESS(rc))
    597             rc = rc2;
    598     }
    599 
    600 #ifdef DEBUG
    601     VGSvcVerbose(4, "Renaming '%s' to '%s' returned rc=%Rrc\n", szSource, szDest, rc);
    602 #endif
     718            if (RT_SUCCESS(rc))
     719                rc = rc2;
     720        }
     721    }
     722    else
     723    {
     724        VGSvcError("Error fetching parameters for rename operation: %Rrc\n", rc);
     725        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     726    }
     727    VGSvcVerbose(5, "Renaming '%s' to '%s' returned rc=%Rrc\n", szSource, szDest, rc);
    603728    return rc;
    604729}
     
    617742    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    618743
     744    /*
     745     * Retrieve the request.
     746     */
    619747    int rc = VbglR3GuestCtrlPathGetUserDocuments(pHostCtx);
    620748    if (RT_SUCCESS(rc))
    621749    {
     750        /*
     751         * Get the path and pass it back to the host..
     752         */
    622753        char szPath[RTPATH_MAX];
    623754        rc = RTPathUserDocuments(szPath, sizeof(szPath));
    624 
    625755#ifdef DEBUG
    626756        VGSvcVerbose(2, "User documents is '%s', rc=%Rrc\n", szPath, rc);
    627757#endif
    628         /* Report back in any case. */
    629         int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */,
    630                                             szPath, (uint32_t)strlen(szPath) + 1 /* Include terminating zero */);
     758
     759        int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, szPath,
     760                                            RT_SUCCESS(rc) ? (uint32_t)strlen(szPath) + 1 /* Include terminating zero */ : 0);
    631761        if (RT_FAILURE(rc2))
     762        {
    632763            VGSvcError("Failed to report user documents, rc=%Rrc\n", rc2);
    633         if (RT_SUCCESS(rc))
    634             rc = rc2;
    635     }
    636 
     764            if (RT_SUCCESS(rc))
     765                rc = rc2;
     766        }
     767    }
     768    else
     769    {
     770        VGSvcError("Error fetching parameters for user documents path request: %Rrc\n", rc);
     771        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     772    }
    637773    return rc;
    638774}
     
    651787    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    652788
     789    /*
     790     * Retrieve the request.
     791     */
    653792    int rc = VbglR3GuestCtrlPathGetUserHome(pHostCtx);
    654793    if (RT_SUCCESS(rc))
    655794    {
     795        /*
     796         * Get the path and pass it back to the host..
     797         */
    656798        char szPath[RTPATH_MAX];
    657799        rc = RTPathUserHome(szPath, sizeof(szPath));
     
    661803#endif
    662804        /* Report back in any case. */
    663         int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */,
    664                                             szPath, (uint32_t)strlen(szPath) + 1 /* Include terminating zero */);
     805        int rc2 = VbglR3GuestCtrlMsgReplyEx(pHostCtx, rc, 0 /* Type */, szPath,
     806                                            RT_SUCCESS(rc) ?(uint32_t)strlen(szPath) + 1 /* Include terminating zero */ : 0);
    665807        if (RT_FAILURE(rc2))
     808        {
    666809            VGSvcError("Failed to report user home, rc=%Rrc\n", rc2);
    667         if (RT_SUCCESS(rc))
    668             rc = rc2;
    669     }
    670 
     810            if (RT_SUCCESS(rc))
     811                rc = rc2;
     812        }
     813    }
     814    else
     815    {
     816        VGSvcError("Error fetching parameters for user home directory path request: %Rrc\n", rc);
     817        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     818    }
    671819    return rc;
    672820}
     
    685833    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    686834
    687     int rc = VINF_SUCCESS;
    688     bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */
    689 
    690     switch (pHostCtx->uProtocol)
    691     {
    692         case 1: /* Guest Additions < 4.3. */
    693             if (pHostCtx->uNumParms != 11)
    694                 rc = VERR_NOT_SUPPORTED;
    695             break;
    696 
    697         case 2: /* Guest Additions >= 4.3. */
    698             if (pHostCtx->uNumParms != 12)
    699                 rc = VERR_NOT_SUPPORTED;
    700             break;
    701 
    702         default:
    703             rc = VERR_NOT_SUPPORTED;
    704             break;
    705     }
    706 
    707     if (RT_SUCCESS(rc))
    708     {
    709         VBOXSERVICECTRLPROCSTARTUPINFO startupInfo;
    710         RT_ZERO(startupInfo);
    711 
    712         /* Initialize maximum environment block size -- needed as input
    713          * parameter to retrieve the stuff from the host. On output this then
    714          * will contain the actual block size. */
    715         startupInfo.cbEnv = sizeof(startupInfo.szEnv);
    716 
    717         rc = VbglR3GuestCtrlProcGetStart(pHostCtx,
     835/** @todo this hardcoded stuff needs redoing.   */
     836
     837    /* Initialize maximum environment block size -- needed as input
     838     * parameter to retrieve the stuff from the host. On output this then
     839     * will contain the actual block size. */
     840    VBOXSERVICECTRLPROCSTARTUPINFO startupInfo;
     841    RT_ZERO(startupInfo);
     842    startupInfo.cbEnv = sizeof(startupInfo.szEnv);
     843
     844    int rc = VbglR3GuestCtrlProcGetStart(pHostCtx,
    718845                                         /* Command */
    719846                                         startupInfo.szCmd,      sizeof(startupInfo.szCmd),
     
    735862                                         /* Process affinity */
    736863                                         startupInfo.uAffinity,  sizeof(startupInfo.uAffinity), &startupInfo.uNumAffinity);
     864    if (RT_SUCCESS(rc))
     865    {
     866        VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
     867                     startupInfo.szCmd, startupInfo.uFlags,
     868                     startupInfo.uNumArgs ? startupInfo.szArgs : "<None>",
     869                     startupInfo.uNumEnvVars ? startupInfo.szEnv : "<None>",
     870                     startupInfo.uTimeLimitMS);
     871
     872        bool fStartAllowed = false; /* Flag indicating whether starting a process is allowed or not. */
     873        rc = VGSvcGstCtrlSessionProcessStartAllowed(pSession, &fStartAllowed);
    737874        if (RT_SUCCESS(rc))
    738875        {
    739             VGSvcVerbose(3, "Request to start process szCmd=%s, fFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
    740                          startupInfo.szCmd, startupInfo.uFlags,
    741                          startupInfo.uNumArgs ? startupInfo.szArgs : "<None>",
    742                          startupInfo.uNumEnvVars ? startupInfo.szEnv : "<None>",
    743                          startupInfo.uTimeLimitMS);
    744 
    745             rc = VGSvcGstCtrlSessionProcessStartAllowed(pSession, &fStartAllowed);
    746             if (RT_SUCCESS(rc))
    747             {
    748                 if (fStartAllowed)
    749                     rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID);
    750                 else
    751                     rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */
    752             }
    753         }
    754     }
    755 
    756     /* In case of an error we need to notify the host to not wait forever for our response. */
    757     if (RT_FAILURE(rc))
    758     {
    759         VGSvcError("Starting process failed with rc=%Rrc, protocol=%RU32, parameters=%RU32\n",
    760                    rc, pHostCtx->uProtocol, pHostCtx->uNumParms);
    761 
    762         /* Don't report back if we didn't supply sufficient buffer for getting
    763          * the actual command -- we don't have the matching context ID. */
    764         if (rc != VERR_TOO_MUCH_DATA)
    765         {
    766             /*
    767              * Note: The context ID can be 0 because we mabye weren't able to fetch the command
    768              *       from the host. The host in case has to deal with that!
    769              */
    770             int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /* PID, invalid */,
    771                                                   PROC_STS_ERROR, rc,
    772                                                   NULL /* pvData */, 0 /* cbData */);
     876            if (fStartAllowed)
     877                rc = VGSvcGstCtrlProcessStart(pSession, &startupInfo, pHostCtx->uContextID);
     878            else
     879                rc = VERR_MAX_PROCS_REACHED; /* Maximum number of processes reached. */
     880        }
     881
     882        /* We're responsible for signaling errors to the host (it will wait for ever otherwise). */
     883        if (RT_FAILURE(rc))
     884        {
     885            VGSvcError("Starting process failed with rc=%Rrc, protocol=%RU32, parameters=%RU32\n",
     886                       rc, pHostCtx->uProtocol, pHostCtx->uNumParms);
     887            int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /*nil-PID*/, PROC_STS_ERROR, rc, NULL /*pvData*/, 0 /*cbData*/);
    773888            if (RT_FAILURE(rc2))
    774889                VGSvcError("Error sending start process status to host, rc=%Rrc\n", rc2);
    775890        }
    776891    }
    777 
     892    else
     893    {
     894        VGSvcError("Failed to retrieve parameters for process start: %Rrc (cParms=%u)\n", rc, pHostCtx->uNumParms);
     895        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     896    }
    778897    return rc;
    779898}
     
    786905 * @param   pSession            The session which is in charge.
    787906 * @param   pHostCtx            The host context to use.
    788  * @param   pvScratchBuf        The scratch buffer.
    789  * @param   cbScratchBuf        The scratch buffer size for retrieving the input
     907 * @param   ppvScratchBuf       The scratch buffer, we may grow it.
     908 * @param   pcbScratchBuf       The scratch buffer size for retrieving the input
    790909 *                              data.
    791910 */
    792911static int vgsvcGstCtrlSessionHandleProcInput(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
    793                                               void *pvScratchBuf, size_t cbScratchBuf)
     912                                              void **ppvScratchBuf, uint32_t *pcbScratchBuf)
    794913{
    795914    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    796915    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    797     AssertPtrReturn(cbScratchBuf, VERR_INVALID_PARAMETER);
    798     AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
    799 
     916
     917    /*
     918     * Retrieve the data from the host.
     919     */
    800920    uint32_t uPID;
    801921    uint32_t fFlags;
    802     uint32_t cbSize;
    803 
    804 #if 0 /* unused */
    805     uint32_t uStatus = INPUT_STS_UNDEFINED; /* Status sent back to the host. */
    806     uint32_t cbWritten = 0; /* Number of bytes written to the guest. */
    807 #endif
    808 
    809     /*
    810      * Ask the host for the input data.
    811      */
    812     int rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags,
    813                                          pvScratchBuf, (uint32_t)cbScratchBuf, &cbSize);
    814     if (RT_FAILURE(rc))
    815         VGSvcError("Failed to retrieve process input command for PID=%RU32, rc=%Rrc\n", uPID, rc);
    816     else if (cbSize > cbScratchBuf)
    817     {
    818         VGSvcError("Too much process input received, rejecting: uPID=%RU32, cbSize=%RU32, cbScratchBuf=%RU32\n",
    819                    uPID, cbSize, cbScratchBuf);
    820         rc = VERR_TOO_MUCH_DATA;
    821     }
    822     else
    823     {
    824         /*
    825          * Is this the last input block we need to deliver? Then let the pipe know ...
    826          */
    827         bool fPendingClose = false;
     922    uint32_t cbInput;
     923    int rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, *ppvScratchBuf, *pcbScratchBuf, &cbInput);
     924    if (   rc == VERR_BUFFER_OVERFLOW
     925        && vgsvcGstCtrlSessionGrowScratchBuf(ppvScratchBuf, pcbScratchBuf, cbInput))
     926        rc = VbglR3GuestCtrlProcGetInput(pHostCtx, &uPID, &fFlags, *ppvScratchBuf, *pcbScratchBuf, &cbInput);
     927    if (RT_SUCCESS(rc))
     928    {
    828929        if (fFlags & INPUT_FLAG_EOF)
    829         {
    830             fPendingClose = true;
    831 #ifdef DEBUG
    832             VGSvcVerbose(4, "Got last process input block for PID=%RU32 (%RU32 bytes) ...\n", uPID, cbSize);
    833 #endif
    834         }
    835 
     930            VGSvcVerbose(4, "Got last process input block for PID=%RU32 (%RU32 bytes) ...\n", uPID, cbInput);
     931
     932        /*
     933         * Locate the process and feed it.
     934         */
    836935        PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
    837936        if (pProcess)
    838937        {
    839             rc = VGSvcGstCtrlProcessHandleInput(pProcess, pHostCtx, fPendingClose, pvScratchBuf, cbSize);
     938            rc = VGSvcGstCtrlProcessHandleInput(pProcess, pHostCtx, RT_BOOL(fFlags & INPUT_FLAG_EOF),
     939                                                *ppvScratchBuf, RT_MIN(cbInput, *pcbScratchBuf));
    840940            if (RT_FAILURE(rc))
    841941                VGSvcError("Error handling input command for PID=%RU32, rc=%Rrc\n", uPID, rc);
     
    843943        }
    844944        else
    845             rc = VERR_NOT_FOUND;
    846     }
    847 
    848 #ifdef DEBUG
    849     VGSvcVerbose(4, "Setting input for PID=%RU32 resulted in rc=%Rrc\n", uPID, rc);
    850 #endif
     945        {
     946            VGSvcError("Could not find PID %u for feeding %u bytes to it.\n", uPID, cbInput);
     947            rc = VERR_PROCESS_NOT_FOUND;
     948            VbglR3GuestCtrlProcCbStatusInput(pHostCtx, uPID, INPUT_STS_ERROR, rc, 0);
     949        }
     950    }
     951    else
     952    {
     953        VGSvcError("Failed to retrieve parameters for process input: %Rrc (scratch %u bytes)\n", rc, *pcbScratchBuf);
     954        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     955    }
     956
     957    VGSvcVerbose(6, "Feeding input to PID=%RU32 resulted in rc=%Rrc\n", uPID, rc);
    851958    return rc;
    852959}
     
    865972    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    866973
     974    /*
     975     * Retrieve the request.
     976     */
    867977    uint32_t uPID;
    868978    uint32_t uHandleID;
    869979    uint32_t fFlags;
    870 
    871980    int rc = VbglR3GuestCtrlProcGetOutput(pHostCtx, &uPID, &uHandleID, &fFlags);
    872981#ifdef DEBUG_andy
     
    876985    if (RT_SUCCESS(rc))
    877986    {
     987        /*
     988         * Locate the process and hand it the output request.
     989         */
    878990        PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
    879991        if (pProcess)
     
    885997        }
    886998        else
    887             rc = VERR_NOT_FOUND;
     999        {
     1000            VGSvcError("Could not find PID %u for draining handle %u (%#x).\n", uPID, uHandleID, uHandleID);
     1001            rc = VERR_PROCESS_NOT_FOUND;
     1002/** @todo r=bird:
     1003 *
     1004 *  No way to report status status code for output requests?
     1005 *
     1006 */
     1007        }
     1008    }
     1009    else
     1010    {
     1011        VGSvcError("Error fetching parameters for process output request: %Rrc\n", rc);
     1012        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
    8881013    }
    8891014
     
    9071032    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    9081033
     1034    /*
     1035     * Retrieve the request.
     1036     */
    9091037    uint32_t uPID;
    9101038    int rc = VbglR3GuestCtrlProcGetTerminate(pHostCtx, &uPID);
    9111039    if (RT_SUCCESS(rc))
    9121040    {
     1041        /*
     1042         * Locate the process and terminate it.
     1043         */
    9131044        PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
    9141045        if (pProcess)
     
    9191050        }
    9201051        else
    921             rc = VERR_NOT_FOUND;
    922     }
    923 
     1052        {
     1053            VGSvcError("Could not find PID %u for termination.\n", uPID);
     1054            rc = VERR_PROCESS_NOT_FOUND;
     1055/** @todo r=bird:
     1056 *
     1057 *  No way to report status status code for output requests?
     1058 *
     1059 */
     1060        }
     1061    }
     1062    else
     1063    {
     1064        VGSvcError("Error fetching parameters for process termination request: %Rrc\n", rc);
     1065        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     1066    }
    9241067#ifdef DEBUG_andy
    9251068    VGSvcVerbose(4, "Terminating PID=%RU32 resulted in rc=%Rrc\n", uPID, rc);
     
    9341077    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    9351078
     1079    /*
     1080     * Retrieve the request.
     1081     */
    9361082    uint32_t uPID;
    937     uint32_t uWaitFlags; uint32_t uTimeoutMS;
    938 
     1083    uint32_t uWaitFlags;
     1084    uint32_t uTimeoutMS;
    9391085    int rc = VbglR3GuestCtrlProcGetWaitFor(pHostCtx, &uPID, &uWaitFlags, &uTimeoutMS);
    9401086    if (RT_SUCCESS(rc))
    9411087    {
     1088        /*
     1089         * Locate the process and the realize that this call makes no sense
     1090         * since we'll notify the host when a process terminates anyway and
     1091         * hopefully don't need any additional encouragement.
     1092         */
    9421093        PVBOXSERVICECTRLPROCESS pProcess = VGSvcGstCtrlSessionRetainProcess(pSession, uPID);
    9431094        if (pProcess)
     
    9491100            rc = VERR_NOT_FOUND;
    9501101    }
    951 
     1102    else
     1103    {
     1104        VGSvcError("Error fetching parameters for process wait request: %Rrc\n", rc);
     1105        VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX);
     1106    }
    9521107    return rc;
    9531108}
     
    9551110
    9561111int VGSvcGstCtrlSessionHandler(PVBOXSERVICECTRLSESSION pSession, uint32_t uMsg, PVBGLR3GUESTCTRLCMDCTX pHostCtx,
    957                                void *pvScratchBuf, size_t cbScratchBuf, volatile bool *pfShutdown)
     1112                               void **ppvScratchBuf, uint32_t *pcbScratchBuf, volatile bool *pfShutdown)
    9581113{
    9591114    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    9601115    AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER);
    961     AssertPtrReturn(pvScratchBuf, VERR_INVALID_POINTER);
     1116    AssertPtrReturn(*ppvScratchBuf, VERR_INVALID_POINTER);
    9621117    AssertPtrReturn(pfShutdown, VERR_INVALID_POINTER);
    9631118
     
    9901145
    9911146        case HOST_EXEC_SET_INPUT:
    992             rc = vgsvcGstCtrlSessionHandleProcInput(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
     1147            rc = vgsvcGstCtrlSessionHandleProcInput(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
    9931148            break;
    9941149
     
    10171172        case HOST_FILE_READ:
    10181173            if (fImpersonated)
    1019                 rc = vgsvcGstCtrlSessionHandleFileRead(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
     1174                rc = vgsvcGstCtrlSessionHandleFileRead(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
    10201175            break;
    10211176
    10221177        case HOST_FILE_READ_AT:
    10231178            if (fImpersonated)
    1024                 rc = vgsvcGstCtrlSessionHandleFileReadAt(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
     1179                rc = vgsvcGstCtrlSessionHandleFileReadAt(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
    10251180            break;
    10261181
    10271182        case HOST_FILE_WRITE:
    10281183            if (fImpersonated)
    1029                 rc = vgsvcGstCtrlSessionHandleFileWrite(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
     1184                rc = vgsvcGstCtrlSessionHandleFileWrite(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
    10301185            break;
    10311186
    10321187        case HOST_FILE_WRITE_AT:
    10331188            if (fImpersonated)
    1034                 rc = vgsvcGstCtrlSessionHandleFileWriteAt(pSession, pHostCtx, pvScratchBuf, cbScratchBuf);
     1189                rc = vgsvcGstCtrlSessionHandleFileWriteAt(pSession, pHostCtx, ppvScratchBuf, pcbScratchBuf);
    10351190            break;
    10361191
     
    10631218            break;
    10641219    }
    1065 
    1066     if (rc == VERR_NOT_SUPPORTED)
    1067     {
     1220    if (RT_SUCCESS(rc))
     1221    { /* likely */ }
     1222    else if (rc != VERR_NOT_SUPPORTED) /* Note: Reply to host must must be sent by above handler. */
     1223        VGSvcError("Error while handling message (uMsg=%RU32, cParms=%RU32), rc=%Rrc\n", uMsg, pHostCtx->uNumParms, rc);
     1224    else
     1225    {
     1226        /* We must skip and notify host here as best we can... */
    10681227        VGSvcVerbose(3, "Unsupported message (uMsg=%RU32, cParms=%RU32) from host, skipping\n", uMsg, pHostCtx->uNumParms);
    1069 
    1070         /*
    1071          * !!! HACK ALERT BEGIN !!!
    1072          * As peeking for the current message by VbglR3GuestCtrlMsgWaitFor() / GUEST_MSG_WAIT only gives us the message type and
    1073          * the number of parameters, but *not* the actual context ID the message is bound to, try to retrieve it here.
    1074          *
    1075          * This is needed in order to reply to the host with the current context ID, without breaking existing clients.
    1076          * Not doing this isn't fatal, but will make host clients wait longer (timing out) for not implemented messages. */
    1077         /** @todo Get rid of this as soon as we have a protocol bump (v4). */
    1078         struct HGCMMsgSkip
    1079         {
    1080             VBGLIOCHGCMCALL hdr;
    1081             /** UInt32: Context ID. */
    1082             HGCMFunctionParameter context;
    1083         };
    1084 
    1085         HGCMMsgSkip Msg;
    1086         VBGL_HGCM_HDR_INIT(&Msg.hdr, pHostCtx->uClientID, GUEST_MSG_WAIT, pHostCtx->uNumParms);
    1087         Msg.context.SetUInt32(0);
    1088 
    1089         /* Retrieve the context ID of the message which is not supported and put it in pHostCtx. */
    1090         int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    1091         if (RT_SUCCESS(rc2))
    1092             Msg.context.GetUInt32(&pHostCtx->uContextID);
    1093 
    1094         /* Now fake a reply to the message. */
    1095         rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, VERR_NOT_SUPPORTED);
    1096         AssertRC(rc2);
    1097 
    1098         /*  !!!                !!!
    1099          *  !!! HACK ALERT END !!!
    1100          *  !!!                !!! */
    1101 
    1102         /* Tell the host service to skip the message. */
    1103         VbglR3GuestCtrlMsgSkipOld(pHostCtx->uClientID);
    1104 
    1105         rc = VINF_SUCCESS;
    1106     }
    1107     /* Note: Other replies must be reported to the host service by the appropriate command handlers above. */
     1228        if (VbglR3GuestCtrlSupportsOptimizations(pHostCtx->uClientID))
     1229            VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, VERR_NOT_SUPPORTED, uMsg);
     1230        else
     1231        {
     1232            /*
     1233             * !!! HACK ALERT BEGIN !!!
     1234             * As peeking for the current message by VbglR3GuestCtrlMsgWaitFor() / GUEST_MSG_WAIT only gives us the message type and
     1235             * the number of parameters, but *not* the actual context ID the message is bound to, try to retrieve it here.
     1236             *
     1237             * This is needed in order to reply to the host with the current context ID, without breaking existing clients.
     1238             * Not doing this isn't fatal, but will make host clients wait longer (timing out) for not implemented messages. */
     1239            /** @todo Get rid of this as soon as we have a protocol bump (v4). */
     1240            struct HGCMMsgSkip
     1241            {
     1242                VBGLIOCHGCMCALL hdr;
     1243                /** UInt32: Context ID. */
     1244                HGCMFunctionParameter context;
     1245            };
     1246
     1247            HGCMMsgSkip Msg;
     1248            VBGL_HGCM_HDR_INIT(&Msg.hdr, pHostCtx->uClientID, GUEST_MSG_WAIT, pHostCtx->uNumParms);
     1249            Msg.context.SetUInt32(0);
     1250
     1251            /* Retrieve the context ID of the message which is not supported and put it in pHostCtx. */
     1252            int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     1253            if (RT_SUCCESS(rc2))
     1254                Msg.context.GetUInt32(&pHostCtx->uContextID);
     1255
     1256            /* Now fake a reply to the message. */
     1257            rc2 = VbglR3GuestCtrlMsgReply(pHostCtx, VERR_NOT_SUPPORTED);
     1258            AssertRC(rc2);
     1259
     1260            /*  !!!                !!!
     1261             *  !!! HACK ALERT END !!!
     1262             *  !!!                !!! */
     1263
     1264            /* Tell the host service to skip the message. */
     1265            VbglR3GuestCtrlMsgSkipOld(pHostCtx->uClientID);
     1266
     1267            rc = VINF_SUCCESS;
     1268        }
     1269    }
    11081270
    11091271    if (RT_FAILURE(rc))
     
    14031565            /*
    14041566             * Allocate a scratch buffer for commands which also send payload data with them.
     1567             * This buffer may grow if the host sends us larger chunks of data.
    14051568             */
    1406             /** @todo Make buffer size configurable via guest properties/argv! */
    14071569            uint32_t cbScratchBuf = _64K;
    1408             Assert(RT_IS_POWER_OF_TWO(cbScratchBuf)); /** @todo r=bird: No idea why this needs to be the case... */
    1409             uint8_t *pvScratchBuf = (uint8_t *)RTMemAlloc(cbScratchBuf);
     1570            void    *pvScratchBuf = RTMemAlloc(cbScratchBuf);
    14101571            if (pvScratchBuf)
    14111572            {
     
    14181579                    VGSvcVerbose(3, "Waiting for host msg ...\n");
    14191580                    uint32_t uMsg = 0;
    1420                     uint32_t cParms = 0;
    1421                     rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &cParms);
     1581                    rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &CtxHost.uNumParms);
    14221582                    if (RT_SUCCESS(rc))
    14231583                    {
    1424                         VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, cParms, rc);
     1584                        VGSvcVerbose(4, "Msg=%RU32 (%RU32 parms) retrieved (%Rrc)\n", uMsg, CtxHost.uNumParms, rc);
    14251585
    14261586                        /*
    1427                          * Set number of parameters for current host context and pass it on to the session handler.
     1587                         * Pass it on to the session handler.
    14281588                         * Note! Only when handling HOST_SESSION_CLOSE is the rc used.
    14291589                         */
    1430                         CtxHost.uNumParms = cParms;
    14311590                        bool fShutdown = false;
    1432                         rc = VGSvcGstCtrlSessionHandler(pSession, uMsg, &CtxHost, pvScratchBuf, cbScratchBuf, &fShutdown);
     1591                        rc = VGSvcGstCtrlSessionHandler(pSession, uMsg, &CtxHost, &pvScratchBuf, &cbScratchBuf, &fShutdown);
    14331592                        if (fShutdown)
    14341593                            break;
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r75806 r75824  
    6262#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
    6363#include <VBox/HostServices/GuestControlSvc.h>
     64#include <VBox/GuestHost/GuestControl.h> /** @todo r=bird: Why two headers??? */
    6465
    6566#include <VBox/log.h>
     
    915916    int clientMsgGet(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    916917    int clientMsgCancel(uint32_t idClient, uint32_t cParms);
    917     int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms);
     918    int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    918919    int clientSessionPrepare(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    919920    int clientSessionCancelPrepared(uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     
    974975        pThis->mClientStateMap[idClient] = ClientState(pThis->mpHelpers, idClient);
    975976    }
    976     catch (std::bad_alloc)
     977    catch (std::bad_alloc &)
    977978    {
    978979        return VERR_NO_MEMORY;
     
    14171418 * @param   hCall       The call handle for completing it.
    14181419 * @param   cParms      Number of parameters.
    1419  */
    1420 int GstCtrlService::clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms)
     1420 * @param   paParms     The parameters.
     1421 */
     1422int GstCtrlService::clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    14211423{
    14221424    /*
    14231425     * Validate the call.
    14241426     */
    1425     ASSERT_GUEST_RETURN(cParms == 0, VERR_WRONG_PARAMETER_COUNT);
     1427    ASSERT_GUEST_RETURN(cParms <= 2, VERR_WRONG_PARAMETER_COUNT);
     1428
     1429    int32_t rcSkip = VERR_NOT_SUPPORTED;
     1430    if (cParms >= 1)
     1431    {
     1432        ASSERT_GUEST_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE);
     1433        rcSkip = (int32_t)paParms[0].u.uint32;
     1434    }
     1435
     1436    uint32_t idMsg = UINT32_MAX;
     1437    if (cParms >= 2)
     1438    {
     1439        ASSERT_GUEST_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE);
     1440        idMsg = paParms[1].u.uint32;
     1441    }
    14261442
    14271443    ClientStateMapIter ItClientState = mClientStateMap.find(idClient);
     
    14341450    if (!rClientState.mHostCmdList.empty())
    14351451    {
    1436         int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS);
    1437         if (RT_SUCCESS(rc))
    1438         {
    1439             /*
    1440              * Remove the command from the queue.
    1441              */
    1442             HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin();
    1443             rClientState.mHostCmdList.pop_front();
    1444 
    1445             /*
    1446              * Compose a reply to the host service.
    1447              */
    1448             VBOXHGCMSVCPARM aReplyParams[4];
    1449             HGCMSvcSetU32(&aReplyParams[0], pFirstCmd->m_idContext);
    1450             HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mMsgType);
    1451             HGCMSvcSetU32(&aReplyParams[2], (uint32_t)VERR_NOT_SUPPORTED);
    1452             HGCMSvcSetPv(&aReplyParams[3], NULL, 0);
    1453             GstCtrlService::hostCallback(GUEST_MSG_REPLY,  RT_ELEMENTS(aReplyParams), aReplyParams);
    1454 
    1455             /*
    1456              * Free the command.
    1457              */
    1458             pFirstCmd->SaneRelease();
    1459         }
    1460         else
    1461             LogFunc(("pfnCallComplete -> %Rrc\n", rc));
    1462         return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     1452        HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin();
     1453        if (   pFirstCmd->mMsgType == idMsg
     1454            || idMsg == UINT32_MAX)
     1455        {
     1456            int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS);
     1457            if (RT_SUCCESS(rc))
     1458            {
     1459                /*
     1460                 * Remove the command from the queue.
     1461                 */
     1462                HostCommand *pFirstCmd = *rClientState.mHostCmdList.begin();
     1463                if (pFirstCmd )
     1464                {
     1465                    rClientState.mHostCmdList.pop_front();
     1466
     1467                    /*
     1468                     * Compose a reply to the host service.
     1469                     */
     1470                    VBOXHGCMSVCPARM aReplyParams[5];
     1471                    HGCMSvcSetU32(&aReplyParams[0], pFirstCmd->m_idContext);
     1472                    switch (pFirstCmd->mMsgType)
     1473                    {
     1474                        case HOST_EXEC_CMD:
     1475                            HGCMSvcSetU32(&aReplyParams[1], 0);              /* pid */
     1476                            HGCMSvcSetU32(&aReplyParams[2], PROC_STS_ERROR); /* status */
     1477                            HGCMSvcSetU32(&aReplyParams[3], rcSkip);         /* flags / whatever */
     1478                            HGCMSvcSetPv(&aReplyParams[4], NULL, 0);         /* data buffer */
     1479                            GstCtrlService::hostCallback(GUEST_EXEC_STATUS, 5, aReplyParams);
     1480                            break;
     1481
     1482                        case HOST_SESSION_CREATE:
     1483                            HGCMSvcSetU32(&aReplyParams[1], GUEST_SESSION_NOTIFYTYPE_ERROR);    /* type */
     1484                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                            /* result */
     1485                            GstCtrlService::hostCallback(GUEST_SESSION_NOTIFY, 3, aReplyParams);
     1486                            break;
     1487
     1488                        case HOST_EXEC_SET_INPUT:
     1489                            HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mParmCount >= 2 ? pFirstCmd->mpParms[1].u.uint32 : 0);
     1490                            HGCMSvcSetU32(&aReplyParams[2], INPUT_STS_ERROR);   /* status */
     1491                            HGCMSvcSetU32(&aReplyParams[3], rcSkip);            /* flags / whatever */
     1492                            HGCMSvcSetU32(&aReplyParams[4], 0);                 /* bytes consumed */
     1493                            GstCtrlService::hostCallback(GUEST_EXEC_INPUT_STATUS, 5, aReplyParams);
     1494                            break;
     1495
     1496                        case HOST_FILE_OPEN:
     1497                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_OPEN); /* type*/
     1498                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                     /* rc */
     1499                            HGCMSvcSetU32(&aReplyParams[3], VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pFirstCmd->m_idContext)); /* handle */
     1500                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
     1501                            break;
     1502                        case HOST_FILE_CLOSE:
     1503                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_ERROR); /* type*/
     1504                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
     1505                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 3, aReplyParams);
     1506                            break;
     1507                        case HOST_FILE_READ:
     1508                        case HOST_FILE_READ_AT:
     1509                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_READ);  /* type */
     1510                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
     1511                            HGCMSvcSetPv(&aReplyParams[3], NULL, 0);                      /* data buffer */
     1512                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
     1513                            break;
     1514                        case HOST_FILE_WRITE:
     1515                        case HOST_FILE_WRITE_AT:
     1516                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_WRITE); /* type */
     1517                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
     1518                            HGCMSvcSetU32(&aReplyParams[3], 0);                           /* bytes written */
     1519                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
     1520                            break;
     1521                        case HOST_FILE_SEEK:
     1522                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_SEEK);  /* type */
     1523                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
     1524                            HGCMSvcSetU64(&aReplyParams[3], 0);                           /* actual */
     1525                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
     1526                            break;
     1527                        case HOST_FILE_TELL:
     1528                            HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_TELL);  /* type */
     1529                            HGCMSvcSetU32(&aReplyParams[2], rcSkip);                      /* rc */
     1530                            HGCMSvcSetU64(&aReplyParams[3], 0);                           /* actual */
     1531                            GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);
     1532                            break;
     1533
     1534                        case HOST_EXEC_GET_OUTPUT: /** @todo This can't be right/work. */
     1535                        case HOST_EXEC_TERMINATE:  /** @todo This can't be right/work. */
     1536                        case HOST_EXEC_WAIT_FOR:   /** @todo This can't be right/work. */
     1537                        case HOST_PATH_USER_DOCUMENTS:
     1538                        case HOST_PATH_USER_HOME:
     1539                        case HOST_PATH_RENAME:
     1540                        case HOST_DIR_REMOVE:
     1541                        default:
     1542                            HGCMSvcSetU32(&aReplyParams[1], pFirstCmd->mMsgType);
     1543                            HGCMSvcSetU32(&aReplyParams[2], (uint32_t)rcSkip);
     1544                            HGCMSvcSetPv(&aReplyParams[3], NULL, 0);
     1545                            GstCtrlService::hostCallback(GUEST_MSG_REPLY, 4, aReplyParams);
     1546                            break;
     1547                    }
     1548
     1549                    /*
     1550                     * Free the command.
     1551                     */
     1552                    pFirstCmd->SaneRelease();
     1553                }
     1554            }
     1555            else
     1556                LogFunc(("pfnCallComplete -> %Rrc\n", rc));
     1557            return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     1558        }
     1559        LogFunc(("Warning: GUEST_MSG_SKIP mismatch! Found %u, caller expected %u!\n", pFirstCmd->mMsgType, idMsg));
     1560        return VERR_MISMATCH;
    14631561    }
    14641562    return VERR_NOT_FOUND;
     
    20182116        case GUEST_MSG_SKIP:
    20192117            LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", idClient));
    2020             rc = pThis->clientMsgSkip(idClient, hCall, cParms);
     2118            rc = pThis->clientMsgSkip(idClient, hCall, cParms, paParms);
    20212119            break;
    20222120        case GUEST_SESSION_PREPARE:
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