039cd2c4871a00e51af909222a34695d9cec3000vboxsync/** @file
039cd2c4871a00e51af909222a34695d9cec3000vboxsync *
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Shared Folders:
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Handles helper functions.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2011 Oracle Corporation
039cd2c4871a00e51af909222a34695d9cec3000vboxsync *
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * available from http://www.virtualbox.org. This file is free software;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync#include "shflhandle.h"
039cd2c4871a00e51af909222a34695d9cec3000vboxsync#include <iprt/alloc.h>
039cd2c4871a00e51af909222a34695d9cec3000vboxsync#include <iprt/assert.h>
039cd2c4871a00e51af909222a34695d9cec3000vboxsync#include <iprt/critsect.h>
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync/*
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Very basic and primitive handle management. Should be sufficient for our needs.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Handle allocation can be rather slow, but at least lookup is fast.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync *
039cd2c4871a00e51af909222a34695d9cec3000vboxsync */
039cd2c4871a00e51af909222a34695d9cec3000vboxsynctypedef struct
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync uint32_t uFlags;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync uintptr_t pvUserData;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync PSHFLCLIENTDATA pClient;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync} SHFLINTHANDLE, *PSHFLINTHANDLE;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsyncstatic SHFLINTHANDLE *pHandles = NULL;
039cd2c4871a00e51af909222a34695d9cec3000vboxsyncstatic int32_t lastHandleIndex = 0;
efb542e50386467c7bf5e4174935c828e7d6c685vboxsyncstatic RTCRITSECT lock;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsyncint vbsfInitHandleTable()
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles = (SHFLINTHANDLE *)RTMemAllocZ (sizeof (SHFLINTHANDLE) * SHFLHANDLE_MAX);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (pHandles == NULL)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync AssertFailed();
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return VERR_NO_MEMORY;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync /* Never return handle 0 */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles[0].uFlags = SHFL_HF_TYPE_DONTUSE;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync lastHandleIndex = 1;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return RTCritSectInit(&lock);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsyncint vbsfFreeHandleTable()
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (pHandles)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync RTMemFree(pHandles);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles = NULL;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (RTCritSectIsInitialized(&lock))
039cd2c4871a00e51af909222a34695d9cec3000vboxsync RTCritSectDelete(&lock);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return VINF_SUCCESS;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncSHFLHANDLE vbsfAllocHandle(PSHFLCLIENTDATA pClient, uint32_t uType,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync uintptr_t pvUserData)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
039cd2c4871a00e51af909222a34695d9cec3000vboxsync SHFLHANDLE handle;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync Assert((uType & SHFL_HF_TYPE_MASK) != 0 && pvUserData);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync RTCritSectEnter(&lock);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync /* Find next free handle */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if(lastHandleIndex >= SHFLHANDLE_MAX-1)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync lastHandleIndex = 1;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync /* Nice linear search */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync for(handle=lastHandleIndex;handle<SHFLHANDLE_MAX;handle++)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if(pHandles[handle].pvUserData == 0)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
df277f214bcaae98f80456ec998330eaa7460ecavboxsync lastHandleIndex = handle;
df277f214bcaae98f80456ec998330eaa7460ecavboxsync break;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if(handle == SHFLHANDLE_MAX)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync /* Try once more from the start */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync for(handle=1;handle<SHFLHANDLE_MAX;handle++)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if(pHandles[handle].pvUserData == 0)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
df277f214bcaae98f80456ec998330eaa7460ecavboxsync lastHandleIndex = handle;
df277f214bcaae98f80456ec998330eaa7460ecavboxsync break;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if(handle == SHFLHANDLE_MAX)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync { /* Out of handles */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync RTCritSectLeave(&lock);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync AssertFailed();
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return SHFL_HANDLE_NIL;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles[handle].uFlags = (uType & SHFL_HF_TYPE_MASK) | SHFL_HF_VALID;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles[handle].pvUserData = pvUserData;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync pHandles[handle].pClient = pClient;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync lastHandleIndex++;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync RTCritSectLeave(&lock);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return handle;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncstatic int vbsfFreeHandle(PSHFLCLIENTDATA pClient, SHFLHANDLE handle)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync if ( handle < SHFLHANDLE_MAX
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync && (pHandles[handle].uFlags & SHFL_HF_VALID)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync && pHandles[handle].pClient == pClient)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles[handle].uFlags = 0;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandles[handle].pvUserData = 0;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync pHandles[handle].pClient = 0;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return VINF_SUCCESS;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return VERR_INVALID_HANDLE;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncuintptr_t vbsfQueryHandle(PSHFLCLIENTDATA pClient, SHFLHANDLE handle,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync uint32_t uType)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync if ( handle < SHFLHANDLE_MAX
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync && (pHandles[handle].uFlags & SHFL_HF_VALID)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync && pHandles[handle].pClient == pClient)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync Assert((uType & SHFL_HF_TYPE_MASK) != 0);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (pHandles[handle].uFlags & uType)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return pHandles[handle].pvUserData;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return 0;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncSHFLFILEHANDLE *vbsfQueryFileHandle(PSHFLCLIENTDATA pClient, SHFLHANDLE handle)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync return (SHFLFILEHANDLE *)vbsfQueryHandle(pClient, handle,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync SHFL_HF_TYPE_FILE);
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync}
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncSHFLFILEHANDLE *vbsfQueryDirHandle(PSHFLCLIENTDATA pClient, SHFLHANDLE handle)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync return (SHFLFILEHANDLE *)vbsfQueryHandle(pClient, handle,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync SHFL_HF_TYPE_DIR);
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync}
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncuint32_t vbsfQueryHandleType(PSHFLCLIENTDATA pClient, SHFLHANDLE handle)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync if ( handle < SHFLHANDLE_MAX
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync && (pHandles[handle].uFlags & SHFL_HF_VALID)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync && pHandles[handle].pClient == pClient)
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync return pHandles[handle].uFlags & SHFL_HF_TYPE_MASK;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync else
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync return 0;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync}
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncSHFLHANDLE vbsfAllocDirHandle(PSHFLCLIENTDATA pClient)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
039cd2c4871a00e51af909222a34695d9cec3000vboxsync SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)RTMemAllocZ (sizeof (SHFLFILEHANDLE));
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (pHandle)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandle->Header.u32Flags = SHFL_HF_TYPE_DIR;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync return vbsfAllocHandle(pClient, pHandle->Header.u32Flags,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync (uintptr_t)pHandle);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return SHFL_HANDLE_NIL;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncSHFLHANDLE vbsfAllocFileHandle(PSHFLCLIENTDATA pClient)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
039cd2c4871a00e51af909222a34695d9cec3000vboxsync SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)RTMemAllocZ (sizeof (SHFLFILEHANDLE));
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (pHandle)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync pHandle->Header.u32Flags = SHFL_HF_TYPE_FILE;
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync return vbsfAllocHandle(pClient, pHandle->Header.u32Flags,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync (uintptr_t)pHandle);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return SHFL_HANDLE_NIL;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsyncvoid vbsfFreeFileHandle(PSHFLCLIENTDATA pClient, SHFLHANDLE hHandle)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync{
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(pClient,
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync hHandle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync if (pHandle)
039cd2c4871a00e51af909222a34695d9cec3000vboxsync {
c49f08bef6467cf8d9ae457570b8ac833f297e79vboxsync vbsfFreeHandle(pClient, hHandle);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync RTMemFree (pHandle);
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
039cd2c4871a00e51af909222a34695d9cec3000vboxsync else
039cd2c4871a00e51af909222a34695d9cec3000vboxsync AssertFailed();
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync return;
039cd2c4871a00e51af909222a34695d9cec3000vboxsync}