VBoxGuestR3LibDragAndDrop.cpp revision 99f33ab590a3a65e0cd082dd8d67779efb9cc6c9
/* $Id$ */
/** @file
* VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, Drag & Drop.
*/
/*
* Copyright (C) 2011-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "VBGLR3Internal.h"
#include "VBox/HostServices/DragAndDropSvc.h"
/* Here all the communication with the host over HGCM is handled platform
* neutral. Also the receiving of URIs content (directory trees and files) is
* done here. So the platform code of the guests, should not take care of that.
*
* Todo:
* - Maybe the EOL converting of text mime-types (not fully sure, eventually
* better done on the host side)
*/
/******************************************************************************
* Private internal functions *
******************************************************************************/
{
/** @todo On Windows we also could use the registry to override
* can be used. */
/* Get the users temp directory. Don't use the user's root directory (or
* be kept after the guest OS used it. */
if (RT_FAILURE(rc))
return rc;
/* Append our base drop directory. */
if (RT_FAILURE(rc))
return rc;
/* Create it when necessary. */
if (!RTDirExists(pszDropDir))
{
if (RT_FAILURE(rc))
return rc;
}
/* The actually drop directory consist of the current time stamp and a
* unique number when necessary. */
char pszTime[64];
return VERR_BUFFER_OVERFLOW;
#ifdef RT_OS_WINDOWS
/* Filter out characters not allowed on Windows platforms, put in by
RTTimeSpecToString(). */
/** @todo Use something like RTPathSanitize() when available. Later. */
{ ' ', ' ', '(', ')', '-', '.', '0', '9', 'A', 'Z', 'a', 'z', '_', '_',
0xa0, 0xd7af, '\0' };
#endif
if (RT_FAILURE(rc))
return rc;
/* Create it (only accessible by the current user) */
}
static int vbglR3DnDQueryNextHostMessageType(uint32_t uClientId, uint32_t *puMsg, uint32_t *pcParms, bool fWait)
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* Fetch results */
}
}
return rc;
}
char *pszFormats,
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* Fetch results */
/* A little bit paranoia */
}
}
return rc;
}
{
if (RT_SUCCESS(rc))
return rc;
}
{
if (RT_SUCCESS(rc))
return rc;
}
char *pszDirname,
{
if (RT_SUCCESS(rc))
{
{
/* Fetch results */
/* A little bit paranoia */
}
}
return rc;
}
char *pszFilename,
void *pvData,
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* Fetch results */
/* A little bit paranoia */
}
}
return rc;
}
char *pszFormat,
void **ppvData,
{
/* Make a string list out of the uri data. */
RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
return VINF_SUCCESS;
if (!pvTmpData)
return VERR_NO_MEMORY;
/* Create and query the drop target directory. */
char pszDropDir[RTPATH_MAX];
if (RT_FAILURE(rc))
{
return rc;
}
/* Patch the old drop data with the new drop directory, so the drop target
* can find the files. */
{
/* Query the path component of a file URI. If this hasn't a
* file scheme, null is returned. */
{
if (pszNewUri)
{
}
}
else
}
/* Cleanup the old data and write the new data back to the event. */
/* Lists for holding created files & directories in the case of a
* rollback. */
char pszPathname[RTPATH_MAX];
uint32_t cbPathname = 0;
bool fLoop = true;
do
{
if (RT_SUCCESS(rc))
{
switch(uNextMsg)
{
{
sizeof(pszPathname),
&fMode);
if (RT_SUCCESS(rc))
{
}
break;
}
{
sizeof(pszPathname),
&fMode);
if (RT_SUCCESS(rc))
{
/** @todo r=andy Keep the file open and locked during the actual file transfer. Otherwise this will
* create all sorts of funny races because we don't know if the guest has
* modified the file in between the file data send calls. */
rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* Valid UNIX mode? */
if ( RT_SUCCESS(rc)
&& (fMode & RTFS_UNIX_MASK))
}
}
}
break;
}
{
if (RT_SUCCESS(rc))
rc = VERR_CANCELLED;
/* Break out of the loop. */
}
default:
fLoop = false;
break;
}
}
else
{
if (rc == VERR_NO_DATA)
rc = VINF_SUCCESS;
break;
}
} while (fLoop);
/* Cleanup on failure or if the user has canceled. */
if (RT_FAILURE(rc))
{
/* Remove any stuff created. */
}
return rc;
}
char *pszFormat,
void *pvData,
{
if (RT_SUCCESS(rc))
{
if ( RT_SUCCESS(rc)
|| rc == VERR_BUFFER_OVERFLOW)
{
/* Fetch results */
/* A little bit paranoia */
}
}
return rc;
}
void *pvData,
{
if (RT_SUCCESS(rc))
{
if ( RT_SUCCESS(rc)
|| rc == VERR_BUFFER_OVERFLOW)
{
/* Fetch results */
/* A little bit paranoia */
}
}
return rc;
}
char *pszFormat,
void **ppvData,
{
uint32_t cbDataRecv = 0;
*ppvData,
&cbDataRecv);
while (rc == VERR_BUFFER_OVERFLOW)
{
if (RT_SUCCESS(rc))
{
switch(uNextMsg)
{
{
if (!*ppvData)
{
rc = VERR_NO_MEMORY;
break;
}
&((char*)*ppvData)[cbAllDataRecv],
&cbDataRecv);
break;
}
default:
{
if (RT_SUCCESS(rc))
rc = VERR_CANCELLED;
break;
}
}
}
}
if (RT_SUCCESS(rc))
return rc;
}
char *pszFormat,
void **ppvData,
{
if (RT_SUCCESS(rc))
{
/* Check if this is a uri-event. If so, let VbglR3 do all the actual
* data transfer + file /directory creation internally without letting
* the caller know. */
}
return rc;
}
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* Fetch results */
}
}
return rc;
}
char *pszFormat,
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* Fetch results */
/* A little bit paranoia */
}
}
return rc;
}
/******************************************************************************
* Public functions *
******************************************************************************/
{
/* Initialize header */
/* Initialize parameter */
/* Do request */
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
}
return rc;
}
{
/* Do request */
if (RT_SUCCESS(rc))
return rc;
}
{
true /* fWait */);
if (RT_SUCCESS(rc))
{
switch(uMsg)
{
{
if (!pEvent->pszFormats)
rc = VERR_NO_MEMORY;
if (RT_SUCCESS(rc))
uMsg,
&pEvent->u.a.uDefAction,
&pEvent->u.a.uAllActions,
break;
}
{
break;
}
{
if (!pEvent->pszFormats)
rc = VERR_NO_MEMORY;
if (RT_SUCCESS(rc))
{
{
rc = VERR_NO_MEMORY;
}
}
if (RT_SUCCESS(rc))
break;
}
{
break;
}
#ifdef VBOX_WITH_DRAG_AND_DROP_GH
{
break;
}
{
if (!pEvent->pszFormats)
rc = VERR_NO_MEMORY;
if (RT_SUCCESS(rc))
&pEvent->u.a.uDefAction);
break;
}
#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
default:
break;
}
}
return rc;
}
{
/* Initialize parameter */
/* Do request */
if (RT_SUCCESS(rc))
return rc;
}
{
/* Do request */
if (RT_SUCCESS(rc))
return rc;
}
const char* pcszFormat)
{
/* Initialize parameter */
/* Do request */
if (RT_SUCCESS(rc))
return rc;
}
{
/* Todo: URI support. Currently only data is send over to the host. For URI
* support basically the same as in the H->G case (see
* HostServices/DragAndDrop/dndmanager.h/cpp) has to be done:
* 1. Parse the urilist
* 2. Recursively send "create dir" and "transfer file" msg to the host
* 3. Patch the urilist by removing all base dirnames
* 4. On the host all needs to received and the urilist patched afterwards
* to point to the new location
*/
int rc = VINF_SUCCESS;
{
/* Initialize parameter */
/* Do request */
if (RT_SUCCESS(rc))
{
/* Did the host cancel the event? */
if (rc == VERR_CANCELLED)
break;
}
else
break;
// RTThreadSleep(500);
}
return rc;
}
{
/* Initialize parameter */
/* Do request */
if (RT_SUCCESS(rc))
return rc;
}