diff options
Diffstat (limited to 'src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp')
-rw-r--r-- | src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp | 1838 |
1 files changed, 1838 insertions, 0 deletions
diff --git a/src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp b/src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp new file mode 100644 index 00000000..04fe0b1b --- /dev/null +++ b/src/VBox/HostServices/SharedFolders/VBoxSharedFoldersSvc.cpp @@ -0,0 +1,1838 @@ +/* $Id: VBoxSharedFoldersSvc.cpp $ */ +/** @file + * Shared Folders - Host service entry points. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * 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. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS +#include <VBox/shflsvc.h> + +#include "shfl.h" +#include "mappings.h" +#include "shflhandle.h" +#include "vbsf.h" +#include <iprt/alloc.h> +#include <iprt/string.h> +#include <iprt/assert.h> +#include <VBox/AssertGuest.h> +#include <VBox/vmm/ssm.h> +#include <VBox/vmm/pdmifs.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define SHFL_SAVED_STATE_VERSION_FOLDERNAME_UTF16 2 +#define SHFL_SAVED_STATE_VERSION_PRE_AUTO_MOUNT_POINT 3 +#define SHFL_SAVED_STATE_VERSION 4 + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +PVBOXHGCMSVCHELPERS g_pHelpers; +static PPDMLED g_pStatusLed = NULL; + +/** @name Shared folder statistics. + * @{ */ +static STAMPROFILE g_StatQueryMappings; +static STAMPROFILE g_StatQueryMappingsFail; +static STAMPROFILE g_StatQueryMapName; +static STAMPROFILE g_StatCreate; +static STAMPROFILE g_StatCreateFail; +static STAMPROFILE g_StatLookup; +static STAMPROFILE g_StatLookupFail; +static STAMPROFILE g_StatClose; +static STAMPROFILE g_StatCloseFail; +static STAMPROFILE g_StatRead; +static STAMPROFILE g_StatReadFail; +static STAMPROFILE g_StatWrite; +static STAMPROFILE g_StatWriteFail; +static STAMPROFILE g_StatLock; +static STAMPROFILE g_StatLockFail; +static STAMPROFILE g_StatList; +static STAMPROFILE g_StatListFail; +static STAMPROFILE g_StatReadLink; +static STAMPROFILE g_StatReadLinkFail; +static STAMPROFILE g_StatMapFolderOld; +static STAMPROFILE g_StatMapFolder; +static STAMPROFILE g_StatMapFolderFail; +static STAMPROFILE g_StatUnmapFolder; +static STAMPROFILE g_StatUnmapFolderFail; +static STAMPROFILE g_StatInformationFail; +static STAMPROFILE g_StatInformationSetFile; +static STAMPROFILE g_StatInformationSetFileFail; +static STAMPROFILE g_StatInformationSetSize; +static STAMPROFILE g_StatInformationSetSizeFail; +static STAMPROFILE g_StatInformationGetFile; +static STAMPROFILE g_StatInformationGetFileFail; +static STAMPROFILE g_StatInformationGetVolume; +static STAMPROFILE g_StatInformationGetVolumeFail; +static STAMPROFILE g_StatRemove; +static STAMPROFILE g_StatRemoveFail; +static STAMPROFILE g_StatRename; +static STAMPROFILE g_StatRenameFail; +static STAMPROFILE g_StatFlush; +static STAMPROFILE g_StatFlushFail; +static STAMPROFILE g_StatSetUtf8; +static STAMPROFILE g_StatSetFileSize; +static STAMPROFILE g_StatSetFileSizeFail; +static STAMPROFILE g_StatSymlink; +static STAMPROFILE g_StatSymlinkFail; +static STAMPROFILE g_StatSetSymlinks; +static STAMPROFILE g_StatQueryMapInfo; +static STAMPROFILE g_StatWaitForMappingsChanges; +static STAMPROFILE g_StatWaitForMappingsChangesFail; +static STAMPROFILE g_StatCancelMappingsChangesWait; +static STAMPROFILE g_StatUnknown; +static STAMPROFILE g_StatMsgStage1; +/** @} */ + + +/** @page pg_shfl_svc Shared Folders Host Service + * + * Shared Folders map a host file system to guest logical filesystem. + * A mapping represents 'host name'<->'guest name' translation and a root + * identifier to be used to access this mapping. + * Examples: "C:\WINNT"<->"F:", "C:\WINNT\System32"<->"/mnt/host/system32". + * + * Therefore, host name and guest name are strings interpreted + * only by host service and guest client respectively. Host name is + * passed to guest only for informational purpose. Guest may for example + * display the string or construct volume label out of the string. + * + * Root identifiers are unique for whole guest life, + * that is until next guest reset/fresh start. + * 32 bit value incremented for each new mapping is used. + * + * Mapping strings are taken from VM XML configuration on VM startup. + * The service DLL takes mappings during initialization. There is + * also API for changing mappings at runtime. + * + * Current mappings and root identifiers are saved when VM is saved. + * + * Guest may use any of these mappings. Full path information + * about an object on a mapping consists of the root identifier and + * a full path of object. + * + * Guest IFS connects to the service and calls SHFL_FN_QUERY_MAP + * function which returns current mappings. For guest convenience, + * removed mappings also returned with REMOVED flag and new mappings + * are marked with NEW flag. + * + * To access host file system guest just forwards file system calls + * to the service, and specifies full paths or handles for objects. + * + * + */ + + + +static DECLCALLBACK(int) svcUnload (void *) +{ + int rc = VINF_SUCCESS; + + Log(("svcUnload\n")); + vbsfFreeHandleTable(); + + if (g_pHelpers) + HGCMSvcHlpStamDeregister(g_pHelpers, "/HGCM/VBoxSharedFolders/*"); + return rc; +} + +static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient, uint32_t fRequestor, bool fRestoring) +{ + RT_NOREF(u32ClientID, fRequestor, fRestoring); + SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient; + Log(("SharedFolders host service: connected, u32ClientID = %u\n", u32ClientID)); + + pClient->fHasMappingCounts = true; + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient) +{ + RT_NOREF1(u32ClientID); + int rc = VINF_SUCCESS; + SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient; + + Log(("SharedFolders host service: disconnected, u32ClientID = %u\n", u32ClientID)); + + vbsfDisconnect(pClient); + return rc; +} + +/** @note We only save as much state as required to access the shared folder again after restore. + * All I/O requests pending at the time of saving will never be completed or result in errors. + * (file handles no longer valid etc) + * This works as designed at the moment. A full state save would be difficult and not always possible + * as the contents of a shared folder might change in between save and restore. + */ +static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM) +{ +#ifndef UNITTEST /* Read this as not yet tested */ + RT_NOREF1(u32ClientID); + SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient; + + Log(("SharedFolders host service: saving state, u32ClientID = %u\n", u32ClientID)); + + int rc = SSMR3PutU32(pSSM, SHFL_SAVED_STATE_VERSION); + AssertRCReturn(rc, rc); + + rc = SSMR3PutU32(pSSM, SHFL_MAX_MAPPINGS); + AssertRCReturn(rc, rc); + + /* Save client structure length & contents */ + rc = SSMR3PutU32(pSSM, sizeof(*pClient)); + AssertRCReturn(rc, rc); + + rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient)); + AssertRCReturn(rc, rc); + + /* Save all the active mappings. */ + for (int i=0;i<SHFL_MAX_MAPPINGS;i++) + { + /* Mapping are saved in the order of increasing root handle values. */ + MAPPING *pFolderMapping = vbsfMappingGetByRoot(i); + + rc = SSMR3PutU32(pSSM, pFolderMapping? pFolderMapping->cMappings: 0); + AssertRCReturn(rc, rc); + + rc = SSMR3PutBool(pSSM, pFolderMapping? pFolderMapping->fValid: false); + AssertRCReturn(rc, rc); + + if (pFolderMapping && pFolderMapping->fValid) + { + uint32_t len = (uint32_t)strlen(pFolderMapping->pszFolderName); + SSMR3PutU32(pSSM, len); + SSMR3PutStrZ(pSSM, pFolderMapping->pszFolderName); + + len = ShflStringSizeOfBuffer(pFolderMapping->pMapName); + SSMR3PutU32(pSSM, len); + SSMR3PutMem(pSSM, pFolderMapping->pMapName, len); + + SSMR3PutBool(pSSM, pFolderMapping->fHostCaseSensitive); + + SSMR3PutBool(pSSM, pFolderMapping->fGuestCaseSensitive); + + len = ShflStringSizeOfBuffer(pFolderMapping->pAutoMountPoint); + SSMR3PutU32(pSSM, len); + rc = SSMR3PutMem(pSSM, pFolderMapping->pAutoMountPoint, len); + AssertRCReturn(rc, rc); + } + } + +#else + RT_NOREF3(u32ClientID, pvClient, pSSM); +#endif + return VINF_SUCCESS; +} + +static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM, uint32_t uVersion) +{ +#ifndef UNITTEST /* Read this as not yet tested */ + RT_NOREF(u32ClientID, uVersion); + uint32_t nrMappings; + SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient; + uint32_t len, version; + + Log(("SharedFolders host service: loading state, u32ClientID = %u\n", u32ClientID)); + + int rc = SSMR3GetU32(pSSM, &version); + AssertRCReturn(rc, rc); + + if ( version > SHFL_SAVED_STATE_VERSION + || version < SHFL_SAVED_STATE_VERSION_FOLDERNAME_UTF16) + return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; + + rc = SSMR3GetU32(pSSM, &nrMappings); + AssertRCReturn(rc, rc); + if (nrMappings != SHFL_MAX_MAPPINGS) + return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; + + /* Restore the client data (flags + path delimiter + mapping counts (new) at the moment) */ + rc = SSMR3GetU32(pSSM, &len); + AssertRCReturn(rc, rc); + + if (len == RT_UOFFSETOF(SHFLCLIENTDATA, acMappings)) + pClient->fHasMappingCounts = false; + else if (len != sizeof(*pClient)) + return SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, + "Saved SHFLCLIENTDATA size %u differs from current %u!\n", len, sizeof(*pClient)); + + rc = SSMR3GetMem(pSSM, pClient, len); + AssertRCReturn(rc, rc); + + /* We don't actually (fully) restore the state; we simply check if the current state is as we it expect it to be. */ + for (int i=0;i<SHFL_MAX_MAPPINGS;i++) + { + /* Load the saved mapping description and try to find it in the mappings. */ + MAPPING mapping; + RT_ZERO(mapping); + + /* restore the folder mapping counter. */ + rc = SSMR3GetU32(pSSM, &mapping.cMappings); + AssertRCReturn(rc, rc); + + rc = SSMR3GetBool(pSSM, &mapping.fValid); + AssertRCReturn(rc, rc); + + if (mapping.fValid) + { + uint32_t cb; + + /* Load the host path name. */ + rc = SSMR3GetU32(pSSM, &cb); + AssertRCReturn(rc, rc); + + char *pszFolderName; + if (version == SHFL_SAVED_STATE_VERSION_FOLDERNAME_UTF16) + { + AssertReturn(cb > SHFLSTRING_HEADER_SIZE && cb <= UINT16_MAX + SHFLSTRING_HEADER_SIZE && !(cb & 1), + SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, "Bad folder name size: %#x\n", cb)); + PSHFLSTRING pFolderName = (PSHFLSTRING)RTMemAlloc(cb); + AssertReturn(pFolderName != NULL, VERR_NO_MEMORY); + + rc = SSMR3GetMem(pSSM, pFolderName, cb); + AssertRCReturn(rc, rc); + AssertReturn(pFolderName->u16Size < cb && pFolderName->u16Length < pFolderName->u16Size, + SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, + "Bad folder name string: %#x/%#x cb=%#x\n", + pFolderName->u16Size, pFolderName->u16Length, cb)); + + rc = RTUtf16ToUtf8(pFolderName->String.ucs2, &pszFolderName); + RTMemFree(pFolderName); + AssertRCReturn(rc, rc); + } + else + { + pszFolderName = (char *)RTStrAlloc(cb + 1); + AssertReturn(pszFolderName, VERR_NO_MEMORY); + + rc = SSMR3GetStrZ(pSSM, pszFolderName, cb + 1); + AssertRCReturn(rc, rc); + mapping.pszFolderName = pszFolderName; + } + + /* Load the map name. */ + rc = SSMR3GetU32(pSSM, &cb); + AssertRCReturn(rc, rc); + AssertReturn(cb > SHFLSTRING_HEADER_SIZE && cb <= UINT16_MAX + SHFLSTRING_HEADER_SIZE && !(cb & 1), + SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, "Bad map name size: %#x\n", cb)); + + PSHFLSTRING pMapName = (PSHFLSTRING)RTMemAlloc(cb); + AssertReturn(pMapName != NULL, VERR_NO_MEMORY); + + rc = SSMR3GetMem(pSSM, pMapName, cb); + AssertRCReturn(rc, rc); + AssertReturn(pMapName->u16Size < cb && pMapName->u16Length < pMapName->u16Size, + SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, + "Bad map name string: %#x/%#x cb=%#x\n", + pMapName->u16Size, pMapName->u16Length, cb)); + + /* Load case sensitivity config. */ + rc = SSMR3GetBool(pSSM, &mapping.fHostCaseSensitive); + AssertRCReturn(rc, rc); + + rc = SSMR3GetBool(pSSM, &mapping.fGuestCaseSensitive); + AssertRCReturn(rc, rc); + + /* Load the auto mount point. */ + PSHFLSTRING pAutoMountPoint; + if (version > SHFL_SAVED_STATE_VERSION_PRE_AUTO_MOUNT_POINT) + { + rc = SSMR3GetU32(pSSM, &cb); + AssertRCReturn(rc, rc); + AssertReturn(cb > SHFLSTRING_HEADER_SIZE && cb <= UINT16_MAX + SHFLSTRING_HEADER_SIZE && !(cb & 1), + SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, "Bad auto mount point size: %#x\n", cb)); + + pAutoMountPoint = (PSHFLSTRING)RTMemAlloc(cb); + AssertReturn(pAutoMountPoint != NULL, VERR_NO_MEMORY); + + rc = SSMR3GetMem(pSSM, pAutoMountPoint, cb); + AssertRCReturn(rc, rc); + AssertReturn(pAutoMountPoint->u16Size < cb && pAutoMountPoint->u16Length < pAutoMountPoint->u16Size, + SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, + "Bad auto mount point string: %#x/%#x cb=%#x\n", + pAutoMountPoint->u16Size, pAutoMountPoint->u16Length, cb)); + + } + else + { + pAutoMountPoint = ShflStringDupUtf8(""); + AssertReturn(pAutoMountPoint, VERR_NO_MEMORY); + } + + mapping.pszFolderName = pszFolderName; + mapping.pMapName = pMapName; + mapping.pAutoMountPoint = pAutoMountPoint; + + /* 'i' is the root handle of the saved mapping. */ + rc = vbsfMappingLoaded (&mapping, i); + if (RT_FAILURE(rc)) + { + LogRel(("SharedFolders host service: %Rrc loading %d [%ls] -> [%s]\n", + rc, i, pMapName->String.ucs2, pszFolderName)); + } + + RTMemFree(pAutoMountPoint); + RTMemFree(pMapName); + RTStrFree(pszFolderName); + + AssertRCReturn(rc, rc); + } + } + Log(("SharedFolders host service: successfully loaded state\n")); +#else + RT_NOREF(u32ClientID, pvClient, pSSM, uVersion); +#endif + return VINF_SUCCESS; +} + +static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, + uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival) +{ + RT_NOREF(u32ClientID, tsArrival); +#ifndef VBOX_WITHOUT_RELEASE_STATISTICS + uint64_t tsStart; + STAM_GET_TS(tsStart); + STAM_REL_PROFILE_ADD_PERIOD(&g_StatMsgStage1, tsStart - tsArrival); +#endif + Log(("SharedFolders host service: svcCall: u32ClientID = %u, fn = %u, cParms = %u, pparms = %p\n", u32ClientID, u32Function, cParms, paParms)); + + SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient; + + bool fAsynchronousProcessing = false; + +#ifdef LOG_ENABLED + for (uint32_t i = 0; i < cParms; i++) + { + /** @todo parameters other than 32 bit */ + Log((" pparms[%d]: type %u, value %u\n", i, paParms[i].type, paParms[i].u.uint32)); + } +#endif + + int rc = VINF_SUCCESS; + PSTAMPROFILE pStat, pStatFail; + switch (u32Function) + { + case SHFL_FN_QUERY_MAPPINGS: + { + pStat = &g_StatQueryMappings; + pStatFail = &g_StatQueryMappingsFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_QUERY_MAPPINGS\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_QUERY_MAPPINGS) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* numberOfMappings */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* mappings */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + uint32_t fu32Flags = paParms[0].u.uint32; + uint32_t cMappings = paParms[1].u.uint32; + SHFLMAPPING *pMappings = (SHFLMAPPING *)paParms[2].u.pointer.addr; + uint32_t cbMappings = paParms[2].u.pointer.size; + + /* Verify parameters values. */ + if ( (fu32Flags & ~SHFL_MF_MASK) != 0 + || cbMappings / sizeof (SHFLMAPPING) != cMappings + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + if (fu32Flags & SHFL_MF_UTF8) + pClient->fu32Flags |= SHFL_CF_UTF8; + /// @todo r=bird: Someone please explain this amusing code (r63916): + //if (fu32Flags & SHFL_MF_AUTOMOUNT) + // pClient->fu32Flags |= SHFL_MF_AUTOMOUNT; + // + //rc = vbsfMappingsQuery(pClient, pMappings, &cMappings); + + rc = vbsfMappingsQuery(pClient, RT_BOOL(fu32Flags & SHFL_MF_AUTOMOUNT), pMappings, &cMappings); + if (RT_SUCCESS(rc)) + { + /* Report that there are more mappings to get if + * handed in buffer is too small. */ + if (paParms[1].u.uint32 < cMappings) + rc = VINF_BUFFER_OVERFLOW; + + /* Update parameters. */ + paParms[1].u.uint32 = cMappings; + } + } + } + + + } break; + + case SHFL_FN_QUERY_MAP_NAME: + { + pStatFail = pStat = &g_StatQueryMapName; + Log(("SharedFolders host service: svcCall: SHFL_FN_QUERY_MAP_NAME\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_QUERY_MAP_NAME) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* Root. */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* Name. */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLSTRING *pString = (SHFLSTRING *)paParms[1].u.pointer.addr; + + /* Verify parameters values. */ + if (!ShflStringIsValidOut(pString, paParms[1].u.pointer.size)) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfMappingsQueryName(pClient, root, pString); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* None. */ + } + } + } + + } break; + + case SHFL_FN_CREATE: + { + pStat = &g_StatCreate; + pStatFail = &g_StatCreateFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_CREATE\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_CREATE) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* parms */ + ) + { + Log(("SharedFolders host service: Invalid parameters types\n")); + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr; + uint32_t cbPath = paParms[1].u.pointer.size; + SHFLCREATEPARMS *pParms = (SHFLCREATEPARMS *)paParms[2].u.pointer.addr; + uint32_t cbParms = paParms[2].u.pointer.size; + + /* Verify parameters values. */ + if ( !ShflStringIsValidIn(pPath, cbPath, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) + || (cbParms != sizeof (SHFLCREATEPARMS)) + ) + { + AssertMsgFailed (("Invalid parameters cbPath or cbParms (%x, %x - expected >=%x, %x)\n", + cbPath, cbParms, sizeof(SHFLSTRING), sizeof (SHFLCREATEPARMS))); + rc = VERR_INVALID_PARAMETER; + } + else + { + if (pParms->CreateFlags & SHFL_CF_LOOKUP) + { + pStat = &g_StatLookup; + pStatFail = &g_StatLookupFail; + } + + /* Execute the function. */ + rc = vbsfCreate (pClient, root, pPath, cbPath, pParms); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + break; + } + + case SHFL_FN_CLOSE: + { + pStat = &g_StatClose; + pStatFail = &g_StatCloseFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_CLOSE\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_CLOSE) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + + /* Verify parameters values. */ + if (Handle == SHFL_HANDLE_ROOT) + { + rc = VERR_INVALID_PARAMETER; + } + else + if (Handle == SHFL_HANDLE_NIL) + { + AssertMsgFailed(("Invalid handle!\n")); + rc = VERR_INVALID_HANDLE; + } + else + { + /* Execute the function. */ + rc = vbsfClose (pClient, root, Handle); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + break; + + } + + /** Read object content. */ + case SHFL_FN_READ: + pStat = &g_StatRead; + pStatFail = &g_StatReadFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_READ\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_READ) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */ + || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + uint64_t offset = paParms[2].u.uint64; + uint32_t count = paParms[3].u.uint32; + uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr; + + /* Verify parameters values. */ + if ( Handle == SHFL_HANDLE_ROOT + || count > paParms[4].u.pointer.size + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + if (Handle == SHFL_HANDLE_NIL) + { + AssertMsgFailed(("Invalid handle!\n")); + rc = VERR_INVALID_HANDLE; + } + else + { + /* Execute the function. */ + if (g_pStatusLed) + { + Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); + g_pStatusLed->Asserted.s.fReading = g_pStatusLed->Actual.s.fReading = 1; + } + + rc = vbsfRead (pClient, root, Handle, offset, &count, pBuffer); + if (g_pStatusLed) + g_pStatusLed->Actual.s.fReading = 0; + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + paParms[3].u.uint32 = count; + } + else + { + paParms[3].u.uint32 = 0; /* nothing read */ + } + } + } + break; + + /** Write new object content. */ + case SHFL_FN_WRITE: + pStat = &g_StatWrite; + pStatFail = &g_StatWriteFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_WRITE\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_WRITE) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */ + || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + uint64_t offset = paParms[2].u.uint64; + uint32_t count = paParms[3].u.uint32; + uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr; + + /* Verify parameters values. */ + if ( Handle == SHFL_HANDLE_ROOT + || count > paParms[4].u.pointer.size + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + if (Handle == SHFL_HANDLE_NIL) + { + AssertMsgFailed(("Invalid handle!\n")); + rc = VERR_INVALID_HANDLE; + } + else + { + /* Execute the function. */ + if (g_pStatusLed) + { + Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); + g_pStatusLed->Asserted.s.fWriting = g_pStatusLed->Actual.s.fWriting = 1; + } + + rc = vbsfWrite (pClient, root, Handle, offset, &count, pBuffer); + if (g_pStatusLed) + g_pStatusLed->Actual.s.fWriting = 0; + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + paParms[3].u.uint32 = count; + } + else + { + paParms[3].u.uint32 = 0; /* nothing read */ + } + } + } + break; + + /** Lock/unlock a range in the object. */ + case SHFL_FN_LOCK: + pStat = &g_StatLock; + pStatFail = &g_StatLockFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_LOCK\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_LOCK) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_64BIT /* length */ + || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + uint64_t offset = paParms[2].u.uint64; + uint64_t length = paParms[3].u.uint64; + uint32_t flags = paParms[4].u.uint32; + + /* Verify parameters values. */ + if (Handle == SHFL_HANDLE_ROOT) + { + rc = VERR_INVALID_PARAMETER; + } + else + if (Handle == SHFL_HANDLE_NIL) + { + AssertMsgFailed(("Invalid handle!\n")); + rc = VERR_INVALID_HANDLE; + } + else if (flags & SHFL_LOCK_WAIT) + { + /** @todo This should be properly implemented by the shared folders service. + * The service thread must never block. If an operation requires + * blocking, it must be processed by another thread and when it is + * completed, the another thread must call + * + * g_pHelpers->pfnCallComplete (callHandle, rc); + * + * The operation is async. + * fAsynchronousProcessing = true; + */ + + /* Here the operation must be posted to another thread. At the moment it is not implemented. + * Until it is implemented, try to perform the operation without waiting. + */ + flags &= ~SHFL_LOCK_WAIT; + + /* Execute the function. */ + if ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL) + rc = vbsfUnlock(pClient, root, Handle, offset, length, flags); + else + rc = vbsfLock(pClient, root, Handle, offset, length, flags); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + /* none */ + } + } + else + { + /* Execute the function. */ + if ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL) + rc = vbsfUnlock(pClient, root, Handle, offset, length, flags); + else + rc = vbsfLock(pClient, root, Handle, offset, length, flags); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + /* none */ + } + } + } + break; + + /** List object content. */ + case SHFL_FN_LIST: + { + pStat = &g_StatList; + pStatFail = &g_StatListFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_LIST\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_LIST) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* cb */ + || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* pPath */ + || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ + || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* resumePoint */ + || paParms[7].type != VBOX_HGCM_SVC_PARM_32BIT /* cFiles (out) */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + uint32_t flags = paParms[2].u.uint32; + uint32_t length = paParms[3].u.uint32; + SHFLSTRING *pPath = (paParms[4].u.pointer.size == 0) ? 0 : (SHFLSTRING *)paParms[4].u.pointer.addr; + uint8_t *pBuffer = (uint8_t *)paParms[5].u.pointer.addr; + uint32_t resumePoint = paParms[6].u.uint32; + uint32_t cFiles = 0; + + /* Verify parameters values. */ + if ( (length < sizeof (SHFLDIRINFO)) + || length > paParms[5].u.pointer.size + || !ShflStringIsValidOrNullIn(pPath, paParms[4].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + if (g_pStatusLed) + { + Assert(g_pStatusLed->u32Magic == PDMLED_MAGIC); + g_pStatusLed->Asserted.s.fReading = g_pStatusLed->Actual.s.fReading = 1; + } + + /* Execute the function. */ + rc = vbsfDirList (pClient, root, Handle, pPath, flags, &length, pBuffer, &resumePoint, &cFiles); + + if (g_pStatusLed) + g_pStatusLed->Actual.s.fReading = 0; + + if (rc == VERR_NO_MORE_FILES && cFiles != 0) + rc = VINF_SUCCESS; /* Successfully return these files. */ + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + paParms[3].u.uint32 = length; + paParms[6].u.uint32 = resumePoint; + paParms[7].u.uint32 = cFiles; + } + else + { + paParms[3].u.uint32 = 0; /* nothing read */ + paParms[6].u.uint32 = 0; + paParms[7].u.uint32 = cFiles; + } + } + } + break; + } + + /* Read symlink destination */ + case SHFL_FN_READLINK: + { + pStat = &g_StatReadLink; + pStatFail = &g_StatReadLinkFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_READLINK\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_READLINK) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr; + uint32_t cbPath = paParms[1].u.pointer.size; + uint8_t *pBuffer = (uint8_t *)paParms[2].u.pointer.addr; + uint32_t cbBuffer = paParms[2].u.pointer.size; + + /* Verify parameters values. */ + if (!ShflStringIsValidOrNullIn(pPath, paParms[1].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfReadLink (pClient, root, pPath, cbPath, pBuffer, cbBuffer); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + + break; + } + + /* Legacy interface */ + case SHFL_FN_MAP_FOLDER_OLD: + { + pStatFail = pStat = &g_StatMapFolderOld; + Log(("SharedFolders host service: svcCall: SHFL_FN_MAP_FOLDER_OLD\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_MAP_FOLDER_OLD) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* delimiter */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + PSHFLSTRING pszMapName = (PSHFLSTRING)paParms[0].u.pointer.addr; + SHFLROOT root = (SHFLROOT)paParms[1].u.uint32; + RTUTF16 delimiter = (RTUTF16)paParms[2].u.uint32; + + /* Verify parameters values. */ + if (!ShflStringIsValidIn(pszMapName, paParms[0].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfMapFolder (pClient, pszMapName, delimiter, false, &root); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + paParms[1].u.uint32 = root; + } + } + } + break; + } + + case SHFL_FN_MAP_FOLDER: + { + pStat = &g_StatMapFolder; + pStatFail = &g_StatMapFolderFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_MAP_FOLDER\n")); + if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) + Log(("SharedFolders host service: request to map folder '%s'\n", + ((PSHFLSTRING)paParms[0].u.pointer.addr)->String.utf8)); + else + Log(("SharedFolders host service: request to map folder '%ls'\n", + ((PSHFLSTRING)paParms[0].u.pointer.addr)->String.ucs2)); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_MAP_FOLDER) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* delimiter */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* fCaseSensitive */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + PSHFLSTRING pszMapName = (PSHFLSTRING)paParms[0].u.pointer.addr; + SHFLROOT root = (SHFLROOT)paParms[1].u.uint32; + RTUTF16 delimiter = (RTUTF16)paParms[2].u.uint32; + bool fCaseSensitive = !!paParms[3].u.uint32; + + /* Verify parameters values. */ + if (ShflStringIsValidIn(pszMapName, paParms[0].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))) + { + rc = VINF_SUCCESS; + } + else + { + rc = VERR_INVALID_PARAMETER; + + /* Fudge for windows GAs getting the length wrong by one char. */ + if ( !(pClient->fu32Flags & SHFL_CF_UTF8) + && paParms[0].u.pointer.size >= sizeof(SHFLSTRING) + && pszMapName->u16Length >= 2 + && pszMapName->String.ucs2[pszMapName->u16Length / 2 - 1] == 0x0000) + { + pszMapName->u16Length -= 2; + if (ShflStringIsValidIn(pszMapName, paParms[0].u.pointer.size, false /*fUtf8Not16*/)) + rc = VINF_SUCCESS; + else + pszMapName->u16Length += 2; + } + } + + /* Execute the function. */ + if (RT_SUCCESS(rc)) + rc = vbsfMapFolder (pClient, pszMapName, delimiter, fCaseSensitive, &root); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + paParms[1].u.uint32 = root; + } + } + Log(("SharedFolders host service: map operation result %Rrc\n", rc)); + if (RT_SUCCESS(rc)) + Log(("SharedFolders host service: mapped to handle %d\n", paParms[1].u.uint32)); + break; + } + + case SHFL_FN_UNMAP_FOLDER: + { + pStat = &g_StatUnmapFolder; + pStatFail = &g_StatUnmapFolderFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_UNMAP_FOLDER\n")); + Log(("SharedFolders host service: request to unmap folder handle %u\n", + paParms[0].u.uint32)); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_UNMAP_FOLDER) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + + /* Execute the function. */ + rc = vbsfUnmapFolder (pClient, root); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + /* nothing */ + } + } + Log(("SharedFolders host service: unmap operation result %Rrc\n", rc)); + break; + } + + /** Query/set object information. */ + case SHFL_FN_INFORMATION: + { + pStatFail = pStat = &g_StatInformationFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_INFORMATION\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_INFORMATION) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* cb */ + || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + uint32_t flags = paParms[2].u.uint32; + uint32_t length = paParms[3].u.uint32; + uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr; + + /* Verify parameters values. */ + if (length > paParms[4].u.pointer.size) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + if (flags & SHFL_INFO_SET) + { + rc = vbsfSetFSInfo (pClient, root, Handle, flags, &length, pBuffer); + + if (flags & SHFL_INFO_FILE) + { + pStat = &g_StatInformationSetFile; + pStatFail = &g_StatInformationSetFileFail; + } + else if (flags & SHFL_INFO_SIZE) + { + pStat = &g_StatInformationSetSize; + pStatFail = &g_StatInformationSetSizeFail; + } + } + else /* SHFL_INFO_GET */ + { + rc = vbsfQueryFSInfo (pClient, root, Handle, flags, &length, pBuffer); + + if (flags & SHFL_INFO_FILE) + { + pStat = &g_StatInformationGetFile; + pStatFail = &g_StatInformationGetFileFail; + } + else if (flags & SHFL_INFO_VOLUME) + { + pStat = &g_StatInformationGetVolume; + pStatFail = &g_StatInformationGetVolumeFail; + } + } + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + paParms[3].u.uint32 = length; + } + else + { + paParms[3].u.uint32 = 0; /* nothing read */ + } + } + } + break; + } + + /** Remove or rename object */ + case SHFL_FN_REMOVE: + { + pStat = &g_StatRemove; + pStatFail = &g_StatRemoveFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_REMOVE\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_REMOVE) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr; + uint32_t cbPath = paParms[1].u.pointer.size; + uint32_t flags = paParms[2].u.uint32; + + /* Verify parameters values. */ + if (!ShflStringIsValidIn(pPath, cbPath, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfRemove (pClient, root, pPath, cbPath, flags); + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + break; + } + + case SHFL_FN_RENAME: + { + pStat = &g_StatRename; + pStatFail = &g_StatRenameFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_RENAME\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_RENAME) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* src */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* dest */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLSTRING *pSrc = (SHFLSTRING *)paParms[1].u.pointer.addr; + SHFLSTRING *pDest = (SHFLSTRING *)paParms[2].u.pointer.addr; + uint32_t flags = paParms[3].u.uint32; + + /* Verify parameters values. */ + if ( !ShflStringIsValidIn(pSrc, paParms[1].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) + || !ShflStringIsValidIn(pDest, paParms[2].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfRename (pClient, root, pSrc, pDest, flags); + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + break; + } + + case SHFL_FN_FLUSH: + { + pStat = &g_StatFlush; + pStatFail = &g_StatFlushFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_FLUSH\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_FLUSH) + { + rc = VERR_INVALID_PARAMETER; + } + else + if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLHANDLE Handle = paParms[1].u.uint64; + + /* Verify parameters values. */ + if (Handle == SHFL_HANDLE_ROOT) + { + rc = VERR_INVALID_PARAMETER; + } + else + if (Handle == SHFL_HANDLE_NIL) + { + AssertMsgFailed(("Invalid handle!\n")); + rc = VERR_INVALID_HANDLE; + } + else + { + /* Execute the function. */ + + rc = vbsfFlush (pClient, root, Handle); + + if (RT_SUCCESS(rc)) + { + /* Nothing to do */ + } + } + } + } break; + + case SHFL_FN_SET_UTF8: + { + pStatFail = pStat = &g_StatSetUtf8; + + pClient->fu32Flags |= SHFL_CF_UTF8; + rc = VINF_SUCCESS; + break; + } + + case SHFL_FN_SYMLINK: + { + pStat = &g_StatSymlink; + pStatFail = &g_StatSymlinkFail; + Log(("SharedFolders host service: svnCall: SHFL_FN_SYMLINK\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_SYMLINK) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* newPath */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* oldPath */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /* info */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLROOT root = (SHFLROOT)paParms[0].u.uint32; + SHFLSTRING *pNewPath = (SHFLSTRING *)paParms[1].u.pointer.addr; + SHFLSTRING *pOldPath = (SHFLSTRING *)paParms[2].u.pointer.addr; + SHFLFSOBJINFO *pInfo = (SHFLFSOBJINFO *)paParms[3].u.pointer.addr; + uint32_t cbInfo = paParms[3].u.pointer.size; + + /* Verify parameters values. */ + if ( !ShflStringIsValidIn(pNewPath, paParms[1].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) + || !ShflStringIsValidIn(pOldPath, paParms[2].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)) + || (cbInfo != sizeof(SHFLFSOBJINFO)) + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfSymlink (pClient, root, pNewPath, pOldPath, pInfo); + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + } + break; + + case SHFL_FN_SET_SYMLINKS: + { + pStatFail = pStat = &g_StatSetSymlinks; + + pClient->fu32Flags |= SHFL_CF_SYMLINKS; + rc = VINF_SUCCESS; + break; + } + + case SHFL_FN_QUERY_MAP_INFO: + { + pStatFail = pStat = &g_StatQueryMapInfo; + Log(("SharedFolders host service: svnCall: SHFL_FN_QUERY_MAP_INFO\n")); + + /* Validate input: */ + rc = VERR_INVALID_PARAMETER; + ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_QUERY_MAP_INFO); + ASSERT_GUEST_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT); /* root */ + ASSERT_GUEST_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_PTR); /* name */ + PSHFLSTRING pNameBuf = (PSHFLSTRING)paParms[1].u.pointer.addr; + ASSERT_GUEST_BREAK(ShflStringIsValidOut(pNameBuf, paParms[1].u.pointer.size)); + ASSERT_GUEST_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_PTR); /* mountPoint */ + PSHFLSTRING pMntPtBuf = (PSHFLSTRING)paParms[2].u.pointer.addr; + ASSERT_GUEST_BREAK(ShflStringIsValidOut(pMntPtBuf, paParms[2].u.pointer.size)); + ASSERT_GUEST_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_64BIT); /* flags */ + ASSERT_GUEST_BREAK(!(paParms[3].u.uint64 & ~(SHFL_MIQF_DRIVE_LETTER | SHFL_MIQF_PATH))); /* flags */ + ASSERT_GUEST_BREAK(paParms[4].type == VBOX_HGCM_SVC_PARM_32BIT); /* version */ + + /* Execute the function: */ + rc = vbsfMappingsQueryInfo(pClient, paParms[0].u.uint32, pNameBuf, pMntPtBuf, + &paParms[3].u.uint64, &paParms[4].u.uint32); + break; + } + + case SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES: + { + pStat = &g_StatWaitForMappingsChanges; + pStatFail = &g_StatWaitForMappingsChangesFail; + Log(("SharedFolders host service: svnCall: SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES\n")); + + /* Validate input: */ + rc = VERR_INVALID_PARAMETER; + ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_WAIT_FOR_MAPPINGS_CHANGES); + ASSERT_GUEST_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT); /* uFolderMappingsVersion */ + + /* Execute the function: */ + rc = vbsfMappingsWaitForChanges(pClient, callHandle, paParms, g_pHelpers->pfnIsCallRestored(callHandle)); + fAsynchronousProcessing = rc == VINF_HGCM_ASYNC_EXECUTE; + break; + } + + case SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS: + { + pStatFail = pStat = &g_StatCancelMappingsChangesWait; + Log(("SharedFolders host service: svnCall: SHFL_FN_CANCEL_WAIT_FOR_CHANGES\n")); + + /* Validate input: */ + rc = VERR_INVALID_PARAMETER; + ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_CANCEL_MAPPINGS_CHANGES_WAITS); + + /* Execute the function: */ + rc = vbsfMappingsCancelChangesWaits(pClient); + break; + } + + case SHFL_FN_SET_FILE_SIZE: + { + pStat = &g_StatSetFileSize; + pStatFail = &g_StatSetFileSizeFail; + Log(("SharedFolders host service: svcCall: SHFL_FN_SET_FILE_SIZE\n")); + + /* Validate input: */ + ASSERT_GUEST_STMT_BREAK(cParms == SHFL_CPARMS_SET_FILE_SIZE, rc = VERR_WRONG_PARAMETER_COUNT); + ASSERT_GUEST_STMT_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* id32Root */ + ASSERT_GUEST_STMT_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* u64Handle */ + ASSERT_GUEST_STMT_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_64BIT, rc = VERR_WRONG_PARAMETER_TYPE); /* cb64NewSize */ + + /* Execute the function: */ + rc = vbsfSetFileSize(pClient, paParms[0].u.uint32, paParms[1].u.uint64, paParms[2].u.uint64); + break; + } + + default: + { + pStatFail = pStat = &g_StatUnknown; + rc = VERR_NOT_IMPLEMENTED; + break; + } + } + + LogFlow(("SharedFolders host service: svcCall: rc=%Rrc\n", rc)); + + if ( !fAsynchronousProcessing + || RT_FAILURE (rc)) + { + /* Complete the operation if it was unsuccessful or + * it was processed synchronously. + */ + g_pHelpers->pfnCallComplete (callHandle, rc); + } + +#ifndef VBOX_WITHOUT_RELEASE_STATISTICS + /* Statistics: */ + uint64_t cTicks; + STAM_GET_TS(cTicks); + cTicks -= tsStart; + if (RT_SUCCESS(rc)) + STAM_REL_PROFILE_ADD_PERIOD(pStat, cTicks); + else + STAM_REL_PROFILE_ADD_PERIOD(pStatFail, cTicks); +#endif + + LogFlow(("\n")); /* Add a new line to differentiate between calls more easily. */ +} + +/* + * We differentiate between a function handler for the guest (svcCall) and one + * for the host. The guest is not allowed to add or remove mappings for obvious + * security reasons. + */ +static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) +{ + int rc = VINF_SUCCESS; + + Log(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms)); + +#ifdef DEBUG + uint32_t i; + + for (i = 0; i < cParms; i++) + { + /** @todo parameters other than 32 bit */ + Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32)); + } +#endif + + switch (u32Function) + { + case SHFL_FN_ADD_MAPPING: + { + Log(("SharedFolders host service: svcCall: SHFL_FN_ADD_MAPPING\n")); + LogRel(("SharedFolders host service: Adding host mapping\n")); + /* Verify parameter count and types. */ + if ( (cParms != SHFL_CPARMS_ADD_MAPPING) + ) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* host folder path */ + || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* map name */ + || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* fFlags */ + || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /* auto mount point */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLSTRING *pHostPath = (SHFLSTRING *)paParms[0].u.pointer.addr; + SHFLSTRING *pMapName = (SHFLSTRING *)paParms[1].u.pointer.addr; + uint32_t fFlags = paParms[2].u.uint32; + SHFLSTRING *pAutoMountPoint = (SHFLSTRING *)paParms[3].u.pointer.addr; + + /* Verify parameters values. */ + if ( !ShflStringIsValidIn(pHostPath, paParms[0].u.pointer.size, false /*fUtf8Not16*/) + || !ShflStringIsValidIn(pMapName, paParms[1].u.pointer.size, false /*fUtf8Not16*/) + || !ShflStringIsValidIn(pAutoMountPoint, paParms[3].u.pointer.size, false /*fUtf8Not16*/) + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + LogRel((" Host path '%ls', map name '%ls', %s, automount=%s, automntpnt=%s, create_symlinks=%s, missing=%s\n", + pHostPath->String.utf16, pMapName->String.utf16, + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_WRITABLE) ? "writable" : "read-only", + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_AUTOMOUNT) ? "true" : "false", + pAutoMountPoint->String.utf16, + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_CREATE_SYMLINKS) ? "true" : "false", + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_MISSING) ? "true" : "false")); + + char *pszHostPath; + rc = RTUtf16ToUtf8(pHostPath->String.ucs2, &pszHostPath); + if (RT_SUCCESS(rc)) + { + /* Execute the function. */ + rc = vbsfMappingsAdd(pszHostPath, pMapName, + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_WRITABLE), + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_AUTOMOUNT), + pAutoMountPoint, + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_CREATE_SYMLINKS), + RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_MISSING), + /* fPlaceholder = */ false); + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + RTStrFree(pszHostPath); + } + } + } + if (RT_FAILURE(rc)) + LogRel(("SharedFolders host service: Adding host mapping failed with rc=%Rrc\n", rc)); + break; + } + + case SHFL_FN_REMOVE_MAPPING: + { + Log(("SharedFolders host service: svcCall: SHFL_FN_REMOVE_MAPPING\n")); + LogRel(("SharedFolders host service: Removing host mapping '%ls'\n", + ((SHFLSTRING *)paParms[0].u.pointer.addr)->String.ucs2)); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_REMOVE_MAPPING) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* folder name */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + SHFLSTRING *pString = (SHFLSTRING *)paParms[0].u.pointer.addr; + + /* Verify parameters values. */ + if (!ShflStringIsValidIn(pString, paParms[0].u.pointer.size, false /*fUtf8Not16*/)) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = vbsfMappingsRemove (pString); + + if (RT_SUCCESS(rc)) + { + /* Update parameters.*/ + ; /* none */ + } + } + } + if (RT_FAILURE(rc)) + LogRel(("SharedFolders host service: Removing host mapping failed with rc=%Rrc\n", rc)); + break; + } + + case SHFL_FN_SET_STATUS_LED: + { + Log(("SharedFolders host service: svcCall: SHFL_FN_SET_STATUS_LED\n")); + + /* Verify parameter count and types. */ + if (cParms != SHFL_CPARMS_SET_STATUS_LED) + { + rc = VERR_INVALID_PARAMETER; + } + else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* folder name */ + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Fetch parameters. */ + PPDMLED pLed = (PPDMLED)paParms[0].u.pointer.addr; + uint32_t cbLed = paParms[0].u.pointer.size; + + /* Verify parameters values. */ + if ( (cbLed != sizeof (PDMLED)) + ) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + g_pStatusLed = pLed; + rc = VINF_SUCCESS; + } + } + break; + } + + default: + rc = VERR_NOT_IMPLEMENTED; + break; + } + + LogFlow(("SharedFolders host service: svcHostCall ended with rc=%Rrc\n", rc)); + return rc; +} + +extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable) +{ + int rc = VINF_SUCCESS; + + Log(("SharedFolders host service: VBoxHGCMSvcLoad: ptable = %p\n", ptable)); + + if (!VALID_PTR(ptable)) + { + LogRelFunc(("SharedFolders host service: Bad value of ptable (%p)\n", ptable)); + rc = VERR_INVALID_PARAMETER; + } + else + { + Log(("SharedFolders host service: VBoxHGCMSvcLoad: ptable->cbSize = %u, ptable->u32Version = 0x%08X\n", + ptable->cbSize, ptable->u32Version)); + + if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE) + || ptable->u32Version != VBOX_HGCM_SVC_VERSION) + { + LogRelFunc(("SharedFolders host service: Version mismatch while loading: ptable->cbSize = %u (should be %u), ptable->u32Version = 0x%08X (should be 0x%08X)\n", + ptable->cbSize, sizeof (VBOXHGCMSVCFNTABLE), ptable->u32Version, VBOX_HGCM_SVC_VERSION)); + rc = VERR_VERSION_MISMATCH; + } + else + { + g_pHelpers = ptable->pHelpers; + + ptable->cbClient = sizeof (SHFLCLIENTDATA); + + ptable->pfnUnload = svcUnload; + ptable->pfnConnect = svcConnect; + ptable->pfnDisconnect = svcDisconnect; + ptable->pfnCall = svcCall; + ptable->pfnHostCall = svcHostCall; + ptable->pfnSaveState = svcSaveState; + ptable->pfnLoadState = svcLoadState; + ptable->pfnNotify = NULL; + ptable->pvService = NULL; + } + + /* Init handle table */ + rc = vbsfInitHandleTable(); + AssertRC(rc); + + vbsfMappingInit(); + + /* Finally, register statistics if everything went well: */ + if (RT_SUCCESS(rc)) + { + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatQueryMappings, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_QUERY_MAPPINGS successes", "/HGCM/VBoxSharedFolders/FnQueryMappings"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatQueryMappingsFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_QUERY_MAPPINGS failures", "/HGCM/VBoxSharedFolders/FnQueryMappingsFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatQueryMapName, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_QUERY_MAP_NAME", "/HGCM/VBoxSharedFolders/FnQueryMapName"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatCreate, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CREATE/CREATE successes", "/HGCM/VBoxSharedFolders/FnCreate"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatCreateFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CREATE/CREATE failures", "/HGCM/VBoxSharedFolders/FnCreateFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatLookup, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CREATE/LOOKUP successes", "/HGCM/VBoxSharedFolders/FnLookup"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatLookupFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CREATE/LOOKUP failures", "/HGCM/VBoxSharedFolders/FnLookupFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatClose, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CLOSE successes", "/HGCM/VBoxSharedFolders/FnClose"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatCloseFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CLOSE failures", "/HGCM/VBoxSharedFolders/FnCloseFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatRead, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_READ successes", "/HGCM/VBoxSharedFolders/FnRead"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatReadFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_READ failures", "/HGCM/VBoxSharedFolders/FnReadFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatWrite, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_WRITE successes", "/HGCM/VBoxSharedFolders/FnWrite"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatWriteFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_WRITE failures", "/HGCM/VBoxSharedFolders/FnWriteFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatLock, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_LOCK successes", "/HGCM/VBoxSharedFolders/FnLock"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatLockFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_LOCK failures", "/HGCM/VBoxSharedFolders/FnLockFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatList, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_LIST successes", "/HGCM/VBoxSharedFolders/FnList"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatListFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_LIST failures", "/HGCM/VBoxSharedFolders/FnListFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatReadLink, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_READLINK successes", "/HGCM/VBoxSharedFolders/FnReadLink"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatReadLinkFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_READLINK failures", "/HGCM/VBoxSharedFolders/FnReadLinkFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatMapFolderOld, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_MAP_FOLDER_OLD", "/HGCM/VBoxSharedFolders/FnMapFolderOld"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatMapFolder, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_MAP_FOLDER successes", "/HGCM/VBoxSharedFolders/FnMapFolder"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatMapFolderFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_MAP_FOLDER failures", "/HGCM/VBoxSharedFolders/FnMapFolderFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatUnmapFolder, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_UNMAP_FOLDER successes", "/HGCM/VBoxSharedFolders/FnUnmapFolder"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatUnmapFolderFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_UNMAP_FOLDER failures", "/HGCM/VBoxSharedFolders/FnUnmapFolderFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION early failures", "/HGCM/VBoxSharedFolders/FnInformationFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationSetFile, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/SET/FILE successes", "/HGCM/VBoxSharedFolders/FnInformationSetFile"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationSetFileFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/SET/FILE failures", "/HGCM/VBoxSharedFolders/FnInformationSetFileFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationSetSize, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/SET/SIZE successes", "/HGCM/VBoxSharedFolders/FnInformationSetSize"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationSetSizeFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/SET/SIZE failures", "/HGCM/VBoxSharedFolders/FnInformationSetSizeFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationGetFile, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/GET/FILE successes", "/HGCM/VBoxSharedFolders/FnInformationGetFile"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationGetFileFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/GET/FILE failures", "/HGCM/VBoxSharedFolders/FnInformationGetFileFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationGetVolume, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/GET/VOLUME successes", "/HGCM/VBoxSharedFolders/FnInformationGetVolume"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatInformationGetVolumeFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_INFORMATION/GET/VOLUME failures", "/HGCM/VBoxSharedFolders/FnInformationGetVolumeFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatRemove, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_REMOVE successes", "/HGCM/VBoxSharedFolders/FnRemove"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatRemoveFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_REMOVE failures", "/HGCM/VBoxSharedFolders/FnRemoveFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatRename, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_RENAME successes", "/HGCM/VBoxSharedFolders/FnRename"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatRenameFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_RENAME failures", "/HGCM/VBoxSharedFolders/FnRenameFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatFlush, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_FLUSH successes", "/HGCM/VBoxSharedFolders/FnFlush"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatFlushFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_FLUSH failures", "/HGCM/VBoxSharedFolders/FnFlushFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatSetUtf8, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_SET_UTF8", "/HGCM/VBoxSharedFolders/FnSetUtf8"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatSymlink, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_SYMLINK successes", "/HGCM/VBoxSharedFolders/FnSymlink"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatSymlinkFail, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_SYMLINK failures", "/HGCM/VBoxSharedFolders/FnSymlinkFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatSetSymlinks, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_SET_SYMLINKS", "/HGCM/VBoxSharedFolders/FnSetSymlink"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatQueryMapInfo, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_QUERY_MAP_INFO", "/HGCM/VBoxSharedFolders/FnQueryMapInfo"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatWaitForMappingsChanges, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES successes", "/HGCM/VBoxSharedFolders/FnWaitForMappingsChanges"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatWaitForMappingsChangesFail,STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES failures","/HGCM/VBoxSharedFolders/FnWaitForMappingsChangesFail"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatCancelMappingsChangesWait, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS", "/HGCM/VBoxSharedFolders/FnCancelMappingsChangesWaits"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatUnknown, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "SHFL_FN_???", "/HGCM/VBoxSharedFolders/FnUnknown"); + HGCMSvcHlpStamRegister(g_pHelpers, &g_StatMsgStage1, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Time from VMMDev arrival to worker thread.","/HGCM/VBoxSharedFolders/MsgStage1"); + } + } + + return rc; +} + |