vbsf.cpp revision 8e3378edba83d35ebddb0abe82281ee295e34ec4
/** @file
*
* Shared Folders:
* VBox Shared Folders.
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* 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 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.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*/
#include "mappings.h"
#include "vbsf.h"
#include "shflhandle.h"
{
/* Do not strip root. */
char *s = pszFullPath + cbFullPathRoot;
char *delimSecondLast = NULL;
for (;;)
{
cp = RTStrGetCp(s);
{
break;
}
if (cp == RTPATH_DELIMITER)
{
{
}
delimLast = s;
}
s = RTStrNextCp (s);
}
if (cp == 0)
{
if (delimLast + 1 == s)
{
if (delimSecondLast)
{
*delimSecondLast = 0;
}
else if (delimLast)
{
*delimLast = 0;
}
}
else
{
if (delimLast)
{
*delimLast = 0;
}
}
}
}
{
int rc = VERR_FILE_NOT_FOUND;
char szWildCard[4];
cbDirEntry = 4096;
if (pDirEntry == 0)
{
AssertFailed();
return VERR_NO_MEMORY;
}
/** @todo this is quite inefficient, especially for directories with many files */
*(pszStartComponent-1) = 0;
szWildCard[0] = RTPATH_DELIMITER;
szWildCard[2] = 0;
if (VBOX_FAILURE(rc))
goto end;
for(;;)
{
if (rc == VERR_NO_MORE_FILES)
break;
{
AssertFailed();
if (rc != VERR_NO_TRANSLATION)
break;
else
continue;
}
{
rc = VINF_SUCCESS;
break;
}
}
end:
if (VBOX_FAILURE(rc))
if (pDirEntry)
if (hSearch)
return rc;
}
{
int rc = VINF_SUCCESS;
char *pszFullPath = NULL;
/* Query UCS2 root prefix for the path, cbRoot is the length in bytes including trailing (RTUCS2)0. */
{
return VERR_INVALID_PARAMETER;
}
{
int rc;
char *utf8Root;
if (VBOX_SUCCESS (rc))
{
char *utf8FullPath;
if (!utf8FullPath)
{
rc = VERR_NO_MEMORY;
*ppszFullPath = NULL;
}
else
{
if (pcbFullPathRoot)
}
}
else
{
}
}
else
{
/* Client sends us UCS2, so convert it to UTF8. */
Log(("Root %ls path %.*ls\n", pszRoot, pPath->u16Length/sizeof(pPath->String.ucs2[0]), pPath->String.ucs2));
/* Allocate buffer that will be able to contain
* the root prefix and the pPath converted to UTF8.
* Expect a 2 bytes UCS2 to be converted to 8 bytes UTF8
* in worst case.
*/
if (!pszFullPath)
{
rc = VERR_NO_MEMORY;
}
else
{
if (VBOX_FAILURE(rc))
{
AssertFailed();
return rc;
}
char *dst = pszFullPath;
{
cbRoot++;
}
if (pcbFullPathRoot)
{
/* Convert and copy components. */
/* Correct path delimiters */
{
while (*src)
{
*src = RTPATH_DELIMITER;
src++;
}
}
if (*src == RTPATH_DELIMITER)
src++; /* we already appended a delimiter to the first part */
if (VBOX_FAILURE(rc))
{
AssertFailed();
return rc;
}
cb -= l;
dst += l;
}
/* Nul terminate the string */
*dst = 0;
}
}
if (VBOX_SUCCESS (rc))
{
/* When the host file system is case sensitive and the guest expects a case insensitive fs, then problems can occur */
{
char *pszWildCardComponent = NULL;
if (fWildCard)
{
/* strip off the last path component, that contains the wildcard(s) */
while(src > pszFullPath)
{
if (*src == RTPATH_DELIMITER)
break;
src--;
}
if (*src == RTPATH_DELIMITER)
{
bool fHaveWildcards = false;
while(*temp)
{
{
fHaveWildcards = true;
break;
}
temp++;
}
if (fHaveWildcards)
{
*pszWildCardComponent = 0;
}
}
}
/** @todo don't check when creating files or directories; waste of time */
{
/* Find partial path that's valid */
while(src > pszFullPath)
{
if (*src == RTPATH_DELIMITER)
{
*src = 0;
*src = RTPATH_DELIMITER;
if (rc == VINF_SUCCESS)
{
#ifdef DEBUG
*src = 0;
*src = RTPATH_DELIMITER;
#endif
break;
}
}
src--;
}
if ( *src == RTPATH_DELIMITER
&& VBOX_SUCCESS(rc))
{
src++;
for(;;)
{
bool fEndOfString = true;
while(*end)
{
if (*end == RTPATH_DELIMITER)
break;
end++;
}
if (*end == RTPATH_DELIMITER)
{
fEndOfString = false;
*end = 0;
}
else
else
{
/* path component is invalid; try to correct the casing */
if (VBOX_FAILURE(rc))
{
if (!fEndOfString)
*end = RTPATH_DELIMITER;
break;
}
}
if (fEndOfString)
break;
*end = RTPATH_DELIMITER;
}
if (VBOX_FAILURE(rc))
}
else
}
if (pszWildCardComponent)
/* might be a new file so don't fail here! */
rc = VINF_SUCCESS;
}
}
return rc;
}
static void vbsfFreeFullPath (char *pszFullPath)
{
}
static int vbsfOpenFile (SHFLHANDLE *phHandle, const char *pszPath, SHFLCREATEPARMS *pParms, bool fCreate)
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfOpenFile: pszPath = %s, pParms = %p, fCreate = %d\n",
/** @todo r=bird: You should've requested a better RTFileOpen API! This code could certainly have
* benefitted from it. I've done the long overdue adjustment of RTFileOpen so it better reflect
* what a decent OS should be able to do. I've also added some OS specific flags (non-blocking,
* delete sharing), and I'm not picky about adding more if that required. (I'm only picky about
* how they are treated on platforms which doesn't support them.)
* Because of the restrictions in the old version of RTFileOpen this code contains dangerous race
* conditions. File creation is one example where you may easily kill a file just created by
* another user.
*/
/* Open or create a file. */
unsigned fOpen;
{
}
else
{
default:
case SHFL_CF_ACCESS_NONE:
{
/** @todo treat this as read access, but theoretically this could be a no access requested. */
fOpen |= RTFILE_O_READ;
Log(("FLAG: SHFL_CF_ACCESS_NONE\n"));
break;
}
case SHFL_CF_ACCESS_READ:
{
fOpen |= RTFILE_O_READ;
Log(("FLAG: SHFL_CF_ACCESS_READ\n"));
break;
}
case SHFL_CF_ACCESS_WRITE:
{
fOpen |= RTFILE_O_WRITE;
Log(("FLAG: SHFL_CF_ACCESS_WRITE\n"));
break;
}
case SHFL_CF_ACCESS_READWRITE:
{
Log(("FLAG: SHFL_CF_ACCESS_READWRITE\n"));
break;
}
}
/* Sharing mask */
{
default:
case SHFL_CF_ACCESS_DENYNONE:
Log(("FLAG: SHFL_CF_ACCESS_DENYNONE\n"));
break;
case SHFL_CF_ACCESS_DENYREAD:
Log(("FLAG: SHFL_CF_ACCESS_DENYREAD\n"));
break;
case SHFL_CF_ACCESS_DENYWRITE:
Log(("FLAG: SHFL_CF_ACCESS_DENYWRITE\n"));
break;
case SHFL_CF_ACCESS_DENYALL:
Log(("FLAG: SHFL_CF_ACCESS_DENYALL\n"));
break;
}
{
handle = vbsfAllocDirHandle();
}
else
{
}
{
rc = VERR_NO_MEMORY;
}
else
{
/* Must obviously create the directory, before trying to open it. */
{
if (fCreate)
{
/** @todo render supplied attributes.
* bird: The guest should specify this. For windows guests RTFS_DOS_DIRECTORY should suffice. */
if (VBOX_FAILURE(rc))
{
return rc;
}
}
/* Open the directory now */
if (VBOX_SUCCESS(rc))
{
if (VBOX_FAILURE (rc))
{
return rc;
}
}
}
else
{
}
if (VBOX_SUCCESS (rc))
{
}
else
{
}
}
return rc;
}
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfOpenExisting: pszFullPath = %s, pParms = %p\n",
pszFullPath, pParms));
/* Open file. */
if (VBOX_SUCCESS (rc))
{
}
return rc;
}
static int vbsfOpenReplace (const char *pszPath, SHFLCREATEPARMS *pParms, bool bReplace, RTFSOBJINFO *pInfo)
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfOpenReplace: pszPath = %s, pParms = %p, bReplace = %d\n",
{
/* Replace operation is not applicable to a directory. */
}
else
{
// We are loosing an information regarding the cause of failure here
// -- malc
if (!pHandle)
{
AssertFailed();
}
if (VBOX_SUCCESS (rc))
{
/* Set new file attributes */
if (rc != VINF_SUCCESS)
{
return rc;
}
if (bReplace)
{
#if 0
/* @todo */
/* Set new attributes. */
);
#endif
}
}
}
return rc;
}
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfOpenCreate: pszPath = %s, pParms = %p\n",
if (!pHandle)
{
AssertFailed();
}
if (VBOX_SUCCESS (rc))
{
#if 0
{
/* @todo */
);
}
#endif
}
return rc;
}
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfCloseDir: Handle = %08X Search Handle = %08X\n",
{
}
return rc;
}
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfCloseFile: Handle = %08X\n",
return rc;
}
int vbsfCreate (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint32_t cbPath, SHFLCREATEPARMS *pParms)
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfCreate: pClient = %p, pPath = %p, cbPath = %d, pParms = %p\n",
/* Check the client access rights to the root. */
/** @todo */
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPath = NULL;
uint32_t cbFullPathRoot = 0;
if (VBOX_SUCCESS (rc))
{
/* Reset return values in case client forgot to do so. */
/* Query path information. */
/** r=bird: This is likely to create race conditions.
* What is a file now can be a directory when you open it. */
{
Log2(("SHFL_CF_LOOKUP\n"));
/* Client just wants to know if the object exists. */
switch (rc)
{
case VINF_SUCCESS:
{
break;
}
case VERR_FILE_NOT_FOUND:
{
rc = VINF_SUCCESS;
break;
}
case VERR_PATH_NOT_FOUND:
{
rc = VINF_SUCCESS;
break;
}
}
}
else if (rc == VINF_SUCCESS)
{
/* File object exists. */
/* Mark it as a directory in case the caller didn't. */
{
}
{
}
else
{
{
/* Caller wanted a directory but the existing object is not a directory.
* Do not open the object then.
*/
; /* do nothing */
}
else
{
{
{
break;
}
{
/* NIL handle value will tell client that object was not opened.
* Just copy information about the object.
*/
break;
}
{
break;
}
{
break;
}
default:
{
}
}
}
}
}
else
if (rc == VERR_FILE_NOT_FOUND)
{
rc = VINF_SUCCESS;
/* File object does not exist. */
{
{
{
break;
}
case SHFL_CF_ACT_FAIL_IF_NEW:
{
/* NIL handle value will tell client that object was not created. */
break;
}
default:
{
break;
}
}
}
else
{
{
{
break;
}
case SHFL_CF_ACT_FAIL_IF_NEW:
{
/* NIL handle value will tell client that object was not created. */
break;
}
default:
{
}
}
}
}
else
if (rc == VERR_PATH_NOT_FOUND)
{
rc = VINF_SUCCESS;
}
{
rc = vbsfQueryFileInfo(pClient, root, pParms->Handle, SHFL_INFO_GET|SHFL_INFO_FILE, &bufsize, (uint8_t *)&pParms->Info);
}
/* free the path string */
}
return rc;
}
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfClose: pClient = %p, Handle = %RX64\n",
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
if (!pHandle)
return VERR_INVALID_HANDLE;
{
case SHFL_HF_TYPE_DIR:
{
break;
}
case SHFL_HF_TYPE_FILE:
{
break;
}
}
return rc;
}
int vbsfRead (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
unsigned count = 0;
int rc;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
if (*pcbBuffer == 0)
return VINF_SUCCESS; /* @todo correct? */
if (rc != VINF_SUCCESS)
{
return rc;
}
return rc;
}
int vbsfWrite (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
unsigned count = 0;
int rc;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
if (*pcbBuffer == 0)
return VINF_SUCCESS; /* @todo correct? */
if (rc != VINF_SUCCESS)
{
return rc;
}
return rc;
}
{
int rc = VINF_SUCCESS;
if (pHandle == 0)
{
AssertFailed();
return VERR_INVALID_HANDLE;
}
return rc;
}
int vbsfDirList(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, SHFLSTRING *pPath, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer,
{
int rc = VINF_SUCCESS;
bool fUtf8;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
cbDirEntry = 4096;
if (pDirEntry == 0)
{
AssertFailed();
return VERR_NO_MEMORY;
}
cbBufferOrg = *pcbBuffer;
*pcbBuffer = 0;
*pcFiles = 0;
if (pPath)
{
{
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPath = NULL;
if (VBOX_SUCCESS (rc))
{
/* free the path string */
if (VBOX_FAILURE (rc))
goto end;
}
else
goto end;
}
}
while(cbBufferOrg)
{
/* Do we still have a valid last entry for the active search? If so, then return it here */
{
}
else
{
if (rc == VERR_NO_MORE_FILES)
{
*pIndex = 0; /* listing completed */
break;
}
{
AssertFailed();
if (rc != VERR_NO_TRANSLATION)
break;
else
continue;
}
}
if (fUtf8)
else
/* Overestimating, but that's ok */
if (cbBufferOrg < cbNeeded)
{
/* No room, so save this directory entry, or else it's lost forever */
if (*pcFiles == 0)
{
AssertFailed();
return VINF_BUFFER_OVERFLOW; /* Return directly and don't free pDirEntry */
}
return VINF_SUCCESS; /* Return directly and don't free pDirEntry */
}
pSFDEntry->cucShortName = 0;
if (fUtf8)
{
}
else
{
// adjust cbNeeded (it was overestimated before)
}
*pcFiles += 1;
/* Free the saved last entry, that we've just returned */
{
}
if (flags & SHFL_LIST_RETURN_ONE)
break; /* we're done */
}
end:
if (pDirEntry)
return rc;
}
int vbsfQueryFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
int rc = VINF_SUCCESS;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* @todo other options */
*pcbBuffer = 0;
{
}
else
{
}
if (rc == VINF_SUCCESS)
{
*pcbBuffer = sizeof(RTFSOBJINFO);
}
else
AssertFailed();
return rc;
}
int vbsfSetFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
int rc = VINF_SUCCESS;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
*pcbBuffer = 0;
/* Change only the time values that are not zero */
{
);
}
else
{
);
}
if (rc != VINF_SUCCESS)
{
/* temporary hack */
rc = VINF_SUCCESS;
}
{
/* Change file attributes if necessary */
{
if (rc != VINF_SUCCESS)
{
/* silent failure, because this tends to fail with e.g. windows guest & linux host */
rc = VINF_SUCCESS;
}
}
}
if (rc == VINF_SUCCESS)
{
rc = vbsfQueryFileInfo(pClient, root, Handle, SHFL_INFO_GET|SHFL_INFO_FILE, &bufsize, (uint8_t *)pSFDEntry);
if (rc == VINF_SUCCESS)
{
*pcbBuffer = sizeof(RTFSOBJINFO);
}
else
AssertFailed();
}
return rc;
}
int vbsfSetEndOfFile(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
int rc = VINF_SUCCESS;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
*pcbBuffer = 0;
if (flags & SHFL_INFO_SIZE)
{
if (rc != VINF_SUCCESS)
AssertFailed();
}
else
AssertFailed();
if (rc == VINF_SUCCESS)
{
/* Query the new object info and return it */
if (rc == VINF_SUCCESS)
{
*pcbBuffer = sizeof(RTFSOBJINFO);
}
else
AssertFailed();
}
return rc;
}
int vbsfQueryVolumeInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE|SHFL_HF_TYPE_VOLUME);
int rc = VINF_SUCCESS;
char *pszFullPath = NULL;
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* @todo other options */
*pcbBuffer = 0;
if (VBOX_SUCCESS (rc))
{
rc = RTFsQuerySizes(pszFullPath, &pSFDEntry->ullTotalAllocationBytes, &pSFDEntry->ullAvailableAllocationBytes, &pSFDEntry->ulBytesPerAllocationUnit, &pSFDEntry->ulBytesPerSector);
if (rc != VINF_SUCCESS)
goto exit;
if (rc != VINF_SUCCESS)
goto exit;
if (rc != VINF_SUCCESS)
goto exit;
*pcbBuffer = sizeof(SHFLVOLINFO);
}
else AssertFailed();
exit:
/* free the path string */
return rc;
}
int vbsfQueryFSInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE|SHFL_HF_TYPE_VOLUME);
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
if (flags & SHFL_INFO_FILE)
if (flags & SHFL_INFO_VOLUME)
AssertFailed();
return VERR_INVALID_PARAMETER;
}
int vbsfSetFSInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE|SHFL_HF_TYPE_VOLUME);
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
if (flags & SHFL_INFO_FILE)
if (flags & SHFL_INFO_SIZE)
// if (flags & SHFL_INFO_VOLUME)
// return vbsfVolumeInfo(pClient, root, Handle, flags, pcbBuffer, pBuffer);
AssertFailed();
return VERR_INVALID_PARAMETER;
}
int vbsfLock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags)
{
int rc;
if (pHandle == 0)
{
AssertFailed();
return VERR_INVALID_HANDLE;
}
|| (flags & SHFL_LOCK_ENTIRE)
)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Lock type */
switch(flags & SHFL_LOCK_MODE_MASK)
{
case SHFL_LOCK_SHARED:
break;
case SHFL_LOCK_EXCLUSIVE:
break;
default:
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Lock wait type */
if (flags & SHFL_LOCK_WAIT)
else
if (rc != VINF_SUCCESS)
Log(("RTFileUnlock %RTfile %RX64 %RX64 failed with %Rrc\n", pHandle->file.Handle, offset, length, rc));
return rc;
}
int vbsfUnlock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags)
{
int rc;
if (pHandle == 0)
{
return VERR_INVALID_HANDLE;
}
|| (flags & SHFL_LOCK_ENTIRE)
)
{
return VERR_INVALID_PARAMETER;
}
if (rc != VINF_SUCCESS)
Log(("RTFileUnlock %RTfile %RX64 %RTX64 failed with %Rrc\n", pHandle->file.Handle, offset, length, rc));
return rc;
}
int vbsfRemove(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint32_t cbPath, uint32_t flags)
{
int rc = VINF_SUCCESS;
/* Validate input */
|| cbPath == 0
|| pPath == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPath = NULL;
if (VBOX_SUCCESS (rc))
{
if (flags & SHFL_REMOVE_FILE)
else
/* free the path string */
}
return rc;
}
int vbsfRename(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pSrc, SHFLSTRING *pDest, uint32_t flags)
{
int rc = VINF_SUCCESS;
/* Validate input */
|| pSrc == 0
|| pDest == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPathSrc = NULL;
char *pszFullPathDest = NULL;
if (rc != VINF_SUCCESS)
return rc;
if (VBOX_SUCCESS (rc))
{
if (flags & SHFL_RENAME_FILE)
{
rc = RTFileMove(pszFullPathSrc, pszFullPathDest, (flags & SHFL_RENAME_REPLACE_IF_EXISTS) ? RTFILEMOVE_FLAGS_REPLACE : 0);
}
else
{
/* NT ignores the REPLACE flag and simply return and already exists error. */
rc = RTDirRename(pszFullPathSrc, pszFullPathDest, (flags & SHFL_RENAME_REPLACE_IF_EXISTS) ? RTPATHRENAME_FLAGS_REPLACE : 0);
}
/* free the path string */
}
/* free the path string */
return rc;
}
/*
* Clean up our mess by freeing all handles that are still valid.
*
*/
{
for (int i=0;i<SHFLHANDLE_MAX;i++)
{
if (pHandle)
{
Log(("Open handle %08x\n", i));
}
}
return VINF_SUCCESS;
}