shflhandle.cpp revision 039cd2c4871a00e51af909222a34695d9cec3000
1N/A/** @file
1N/A *
1N/A * Shared Folders:
1N/A * Handles helper functions.
1N/A */
1N/A
1N/A/*
1N/A * Copyright (C) 2006-2007 innotek GmbH
1N/A *
1N/A * This file is part of VirtualBox Open Source Edition (OSE), as
1N/A * available from http://www.virtualbox.org. This file is free software;
1N/A * you can redistribute it and/or modify it under the terms of the GNU
1N/A * General Public License as published by the Free Software Foundation,
1N/A * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
1N/A * distribution. VirtualBox OSE is distributed in the hope that it will
1N/A * be useful, but WITHOUT ANY WARRANTY of any kind.
1N/A *
1N/A * If you received this file as part of a commercial VirtualBox
1N/A * distribution, then only the terms of your commercial VirtualBox
1N/A * license agreement apply instead of the previous paragraph.
1N/A */
1N/A
1N/A#include "shflhandle.h"
1N/A#include <iprt/alloc.h>
1N/A#include <iprt/assert.h>
1N/A#include <iprt/critsect.h>
1N/A
1N/A
1N/A/*
1N/A * Very basic and primitive handle management. Should be sufficient for our needs.
1N/A * Handle allocation can be rather slow, but at least lookup is fast.
1N/A *
1N/A */
1N/Atypedef struct
1N/A{
1N/A uint32_t uFlags;
1N/A uintptr_t pvUserData;
1N/A} SHFLINTHANDLE, *PSHFLINTHANDLE;
1N/A
1N/Astatic SHFLINTHANDLE *pHandles = NULL;
1N/Astatic int32_t lastHandleIndex = 0;
1N/Astatic RTCRITSECT lock = {0};
1N/A
1N/Aint vbsfInitHandleTable()
1N/A{
1N/A pHandles = (SHFLINTHANDLE *)RTMemAllocZ (sizeof (SHFLINTHANDLE) * SHFLHANDLE_MAX);
1N/A if (pHandles == NULL)
1N/A {
1N/A AssertFailed();
1N/A return VERR_NO_MEMORY;
1N/A }
1N/A
1N/A /* Never return handle 0 */
1N/A pHandles[0].uFlags = SHFL_HF_TYPE_DONTUSE;
1N/A lastHandleIndex = 1;
1N/A
1N/A return RTCritSectInit(&lock);
1N/A}
1N/A
1N/Aint vbsfFreeHandleTable()
1N/A{
1N/A if (pHandles)
1N/A RTMemFree(pHandles);
1N/A
1N/A pHandles = NULL;
1N/A
1N/A if (RTCritSectIsInitialized(&lock))
1N/A RTCritSectDelete(&lock);
1N/A
1N/A return VINF_SUCCESS;
1N/A}
1N/A
1N/ASHFLHANDLE vbsfAllocHandle(uint32_t uType, uintptr_t pvUserData)
1N/A{
1N/A SHFLHANDLE handle;
1N/A
1N/A Assert((uType & SHFL_HF_TYPE_MASK) != 0 && pvUserData);
1N/A
1N/A RTCritSectEnter(&lock);
1N/A
1N/A /* Find next free handle */
1N/A if(lastHandleIndex >= SHFLHANDLE_MAX-1)
1N/A {
1N/A lastHandleIndex = 1;
1N/A }
1N/A
1N/A /* Nice linear search */
1N/A for(handle=lastHandleIndex;handle<SHFLHANDLE_MAX;handle++)
1N/A {
1N/A if(pHandles[handle].pvUserData == 0)
1N/A {
1N/A lastHandleIndex = handle;
1N/A break;
1N/A }
1N/A }
1N/A
1N/A if(handle == SHFLHANDLE_MAX)
1N/A {
1N/A /* Try once more from the start */
1N/A for(handle=1;handle<SHFLHANDLE_MAX;handle++)
1N/A {
1N/A if(pHandles[handle].pvUserData == 0)
1N/A {
1N/A lastHandleIndex = handle;
1N/A break;
1N/A }
1N/A }
1N/A if(handle == SHFLHANDLE_MAX)
1N/A { /* Out of handles */
1N/A RTCritSectLeave(&lock);
1N/A AssertFailed();
1N/A return SHFL_HANDLE_NIL;
1N/A }
1N/A }
1N/A pHandles[handle].uFlags = (uType & SHFL_HF_TYPE_MASK) | SHFL_HF_VALID;
1N/A pHandles[handle].pvUserData = pvUserData;
1N/A
1N/A lastHandleIndex++;
1N/A
1N/A RTCritSectLeave(&lock);
return handle;
}
int vbsfFreeHandle(SHFLHANDLE handle)
{
if (handle < SHFLHANDLE_MAX && (pHandles[handle].uFlags & SHFL_HF_VALID))
{
pHandles[handle].uFlags = 0;
pHandles[handle].pvUserData = 0;
return VINF_SUCCESS;
}
return VERR_INVALID_HANDLE;
}
uintptr_t vbsfQueryHandle(SHFLHANDLE handle, uint32_t uType)
{
if (handle < SHFLHANDLE_MAX && (pHandles[handle].uFlags & SHFL_HF_VALID))
{
Assert((uType & SHFL_HF_TYPE_MASK) != 0);
if (pHandles[handle].uFlags & uType)
return pHandles[handle].pvUserData;
}
return 0;
}
SHFLHANDLE vbsfAllocDirHandle (void)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)RTMemAllocZ (sizeof (SHFLFILEHANDLE));
if (pHandle)
{
pHandle->Header.u32Flags = SHFL_HF_TYPE_DIR;
return vbsfAllocHandle(pHandle->Header.u32Flags, (uintptr_t)pHandle);
}
return SHFL_HANDLE_NIL;
}
SHFLHANDLE vbsfAllocFileHandle (void)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)RTMemAllocZ (sizeof (SHFLFILEHANDLE));
if (pHandle)
{
pHandle->Header.u32Flags = SHFL_HF_TYPE_FILE;
return vbsfAllocHandle(pHandle->Header.u32Flags, (uintptr_t)pHandle);
}
return SHFL_HANDLE_NIL;
}
void vbsfFreeFileHandle (SHFLHANDLE hHandle)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(hHandle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
if (pHandle)
{
vbsfFreeHandle(hHandle);
RTMemFree (pHandle);
}
else
AssertFailed();
return;
}