VBoxGuestR3LibDragAndDrop.cpp revision 00331fbaff118e6a5077fe96327aca51a70459db
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, Drag & Drop.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copyright (C) 2011-2013 Oracle Corporation
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * available from http://www.virtualbox.org. This file is free software;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * General Public License (GPL) as published by the Free Software
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * The contents of this file may alternatively be used under the terms
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * of the Common Development and Distribution License Version 1.0
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * CDDL are applicable instead of those of the GPL.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * You may elect to license modified versions of this file under the
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * terms and conditions of either the GPL or the CDDL or both.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync/*******************************************************************************
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync* Header Files *
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync*******************************************************************************/
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/* Here all the communication with the host over HGCM is handled platform
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * neutral. Also the receiving of URIs content (directory trees and files) is
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * done here. So the platform code of the guests, should not take care of that.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * - Sending dirs/files in the G->H case
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * - Maybe the EOL converting of text mime-types (not fully sure, eventually
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * better done on the host side)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int vbglR3DnDPathSanitize(char *pszPath, size_t cbPath);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/******************************************************************************
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Private internal functions *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync ******************************************************************************/
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int vbglR3DnDCreateDropDir(char* pszDropDir, size_t cbSize)
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync /** @todo On Windows we also could use the registry to override
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync * this path, on Posix a dotfile and/or a guest property
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync * can be used. */
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync /* Get the users temp directory. Don't use the user's root directory (or
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync * something inside it) because we don't know for how long/if the data will
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync * be kept after the guest OS used it. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Append our base drop directory. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = RTPathAppend(pszDropDir, cbSize, "VirtualBox Dropped Files");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Create it when necessary. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync /* The actually drop directory consist of the current time stamp and a
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * unique number when necessary. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = vbglR3DnDPathSanitize(pszTime, sizeof(pszTime));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Create it (only accessible by the current user) */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return RTDirCreateUniqueNumbered(pszDropDir, cbSize, RTFS_UNIX_IRWXU, 3, '-');
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncstatic int vbglR3DnDQueryNextHostMessageType(uint32_t uClientId, uint32_t *puMsg, uint32_t *pcParms, bool fWait)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Fetch results */
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync rc = Msg.num_parms.GetUInt32(pcParms); AssertRC(rc);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int vbglR3DnDHGProcessActionMessage(uint32_t uClientId,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync AssertPtrReturn(puDefAction, VERR_INVALID_POINTER);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync AssertPtrReturn(puAllActions, VERR_INVALID_POINTER);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync AssertPtrReturn(pcbFormatsRecv, VERR_INVALID_POINTER);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync /* Fetch results */
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync rc = Msg.uDefAction.GetUInt32(puDefAction); AssertRC(rc);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync rc = Msg.uAllActions.GetUInt32(puAllActions); AssertRC(rc);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync rc = Msg.cFormats.GetUInt32(pcbFormatsRecv); AssertRC(rc);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync /* A little bit paranoia */
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync AssertReturn(cbFormats >= *pcbFormatsRecv, VERR_TOO_MUCH_DATA);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int vbglR3DnDHGProcessLeaveMessage(uint32_t uClientId)
1969e98a26e5b56b67fbe3b6bfa007f8f09e86ebvboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_EVT_LEAVE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncstatic int vbglR3DnDHGProcessCancelMessage(uint32_t uClientId)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_EVT_CANCEL;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncstatic int vbglR3DnDHGProcessSendDirMessage(uint32_t uClientId,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync AssertPtrReturn(pcbDirnameRecv, VERR_INVALID_POINTER);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_DIR;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Fetch results */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = Msg.cName.GetUInt32(pcbDirnameRecv); AssertRC(rc);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* A little bit paranoia */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int vbglR3DnDHGProcessSendFileMessage(uint32_t uClientId,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync AssertPtrReturn(pcbFilenameRecv, VERR_INVALID_POINTER);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_FILE;
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Fetch results */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = Msg.cName.GetUInt32(pcbFilenameRecv); AssertRC(rc);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = Msg.cData.GetUInt32(pcbDataRecv); AssertRC(rc);
56970d3a1944c7c073d66266cd52449835221badvboxsync /* A little bit paranoia */
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync AssertReturn(cbFilename >= *pcbFilenameRecv, VERR_TOO_MUCH_DATA);
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsyncstatic int vbglR3DnDHGProcessURIMessages(uint32_t uClientId,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Make a string list out of the uri data. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uint32_t cbTmpData = _1M * 10; /** @todo r=andy 10MB, uh, really?? */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Create and query the (unique) drop target directory. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Patch the old drop data with the new drop directory, so the drop target
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * can find the files. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Query the path component of a file URI. If this hasn't a
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * file scheme, null is returned. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = vbglR3DnDPathSanitize(pszFilePath, strlen(pszFilePath));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /** @todo Use RTPathJoin? */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync char *pszNewUri = RTUriFileCreate(strFullPath.c_str());
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Cleanup the old data and write the new data back to the event. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n";
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *ppvData = RTStrDupN(newData.c_str(), newData.length());
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Lists for holding created files & directories in the case of a
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * rollback. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync bool fLoop = RT_SUCCESS(rc); /* No error occurred yet? */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false /* fWait */);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync rc = vbglR3DnDPathSanitize(pszPathname, sizeof(pszPathname));
0c94a8282c9042b02f022302a3d987746140eab9vboxsync char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname);
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = vbglR3DnDPathSanitize(pszPathname, sizeof(pszPathname));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /** @todo r=andy Keep the file open and locked during the actual file transfer. Otherwise this will
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * create all sorts of funny races because we don't know if the guest has
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * modified the file in between the file data send calls. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync /* Valid UNIX mode? */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync /* Break out of the loop. */
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync } /* while */
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync /* Cleanup on failure or if the user has canceled. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Remove any stuff created. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic int vbglR3DnDHGProcessDataMessageInternal(uint32_t uClientId,
1379dfd407ada5fab15655776896f13b61a951fdvboxsync AssertPtrReturn(pcbFormatRecv, VERR_INVALID_POINTER);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync AssertPtrReturn(pcbDataTotal, VERR_INVALID_POINTER);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_DATA;
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync /* Fetch results */
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync rc = Msg.cData.GetUInt32(pcbDataTotal); AssertRC(rc);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync /* A little bit paranoia */
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA);
4f4cb69bca6bfda8f4d911759d1f3c6f528a173dvboxsync AssertReturn(cbData >= *pcbDataTotal, VERR_TOO_MUCH_DATA);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsyncstatic int vbglR3DnDHGProcessMoreDataMessageInternal(uint32_t uClientId,
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA;
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
a66ec044d2a64d926996cd24da5faadccb070be3vboxsync /* Fetch results */
a66ec044d2a64d926996cd24da5faadccb070be3vboxsync rc = Msg.cData.GetUInt32(pcbDataRecv); AssertRC(rc);
a66ec044d2a64d926996cd24da5faadccb070be3vboxsync /* A little bit paranoia */
a66ec044d2a64d926996cd24da5faadccb070be3vboxsync AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA);
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncstatic int vbglR3DnDHGProcessSendDataMessageLoop(uint32_t uClientId,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc = vbglR3DnDHGProcessDataMessageInternal(uClientId,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync *ppvData = RTMemRealloc(*ppvData, cbAllDataRecv + cbData);
20f21077abf35d7b7b618acb159267933907407fvboxsync rc = vbglR3DnDHGProcessMoreDataMessageInternal(uClientId,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int vbglR3DnDHGProcessSendDataMessage(uint32_t uClientId,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = vbglR3DnDHGProcessSendDataMessageLoop(uClientId,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Check if this is an URI event. If so, let VbglR3 do all the actual
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * data transfer + file /directory creation internally without letting
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * the caller know.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * This keeps the actual (guest OS-)dependent client (like VBoxClient /
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * VBoxTray) small by not having too much redundant code. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (RTStrNICmp(pszFormat, "text/uri-list", *pcbFormatRecv) == 0)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncstatic int vbglR3DnDGHProcessRequestPendingMessage(uint32_t uClientId,
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_GH_REQ_PENDING;
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Fetch results */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int vbglR3DnDGHProcessDroppedMessage(uint32_t uClientId,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync AssertPtrReturn(pcbFormatRecv, VERR_INVALID_POINTER);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_GH_EVT_DROPPED;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* Fetch results */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = Msg.uAction.GetUInt32(puAction); AssertRC(rc);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* A little bit paranoia */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsyncstatic int vbglR3DnDPathSanitize(char *pszPath, size_t cbPath)
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync /* Filter out characters not allowed on Windows platforms, put in by
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync RTTimeSpecToString(). */
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync /** @todo Use something like RTPathSanitize() when available. Later. */
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync { ' ', ' ', '(', ')', '-', '.', '0', '9', 'A', 'Z', 'a', 'z', '_', '_',
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, aCpSet, '_' /* Replacement */);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync/******************************************************************************
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync * Public functions *
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync ******************************************************************************/
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsyncVBGLR3DECL(int) VbglR3DnDConnect(uint32_t *pu32ClientId)
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync AssertPtrReturn(pu32ClientId, VERR_INVALID_POINTER);
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync /* Initialize header */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync Info.u32ClientID = UINT32_MAX; /* try make valgrind shut up. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /* Initialize parameter */
9b1d52365befbce1af8f32d53c2e563ee9169501vboxsync int rc = RTStrCopy(Info.Loc.u.host.achName, sizeof(Info.Loc.u.host.achName), "VBoxDragAndDropSvc");
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* Do request */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CONNECT, &Info, sizeof(Info));
9b1d52365befbce1af8f32d53c2e563ee9169501vboxsyncVBGLR3DECL(int) VbglR3DnDDisconnect(uint32_t u32ClientId)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* Do request */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_DISCONNECT, &Info, sizeof(Info));
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsyncVBGLR3DECL(int) VbglR3DnDProcessNextMessage(uint32_t u32ClientId, CPVBGLR3DNDHGCMEVENT pEvent)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync int rc = vbglR3DnDQueryNextHostMessageType(u32ClientId, &uMsg, &uNumParms,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync true /* fWait */);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = vbglR3DnDHGProcessSendDataMessage(u32ClientId,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = vbglR3DnDGHProcessRequestPendingMessage(u32ClientId,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncVBGLR3DECL(int) VbglR3DnDHGAcknowledgeOperation(uint32_t u32ClientId, uint32_t uAction)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_ACK_OP;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Initialize parameter */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Do request */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncVBGLR3DECL(int) VbglR3DnDHGRequestData(uint32_t u32ClientId, const char* pcszFormat)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync AssertPtrReturn(pcszFormat, VERR_INVALID_PARAMETER);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_REQ_DATA;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Initialize parameter */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync Msg.pFormat.SetPtr((void*)pcszFormat, (uint32_t)strlen(pcszFormat) + 1);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Do request */
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncVBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(uint32_t u32ClientId,
38745c55f37c31ba8b78cc728d2f08ea6eec38d6vboxsync AssertPtrReturn(pcszFormats, VERR_INVALID_POINTER);
56970d3a1944c7c073d66266cd52449835221badvboxsync Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_ACK_PENDING;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Initialize parameter */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Msg.pFormat.SetPtr((void*)pcszFormats, (uint32_t)strlen(pcszFormats) + 1);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Do request */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsyncVBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, void *pvData, uint32_t cbData)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DATA;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uint32_t cbMax = _1M; /** @todo Remove 1 MB limit. */
fdb40b7d2efa84fc6f03b7a695cb4b2e035c30c7vboxsync /* Initialize parameter */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync uint32_t cbToSend = RT_MIN(cbData - cbSent, cbMax);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync Msg.pData.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbToSend);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Do request */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Did the host cancel the event? */
23d8f7aff045c2bade1b168fee79a3e4749e2345vboxsync// RTThreadSleep(500);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncVBGLR3DECL(int) VbglR3DnDGHErrorEvent(uint32_t u32ClientId, int rcOp)
e70bda5438c3582164d26f171a8bc8d3d7da1e12vboxsync Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_EVT_ERROR;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* Initialize parameter */
9540ab73f6cd0c76f44f6bbfe73f89ac145390b8vboxsync /* Do request */
20f21077abf35d7b7b618acb159267933907407fvboxsync int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));