[55401] | 1 | /* $Id: VBoxGuestR0LibHGCM.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
|
---|
[1] | 2 | /** @file
|
---|
[68476] | 3 | * VBoxGuestLib - Host-Guest Communication Manager, ring-0 client drivers.
|
---|
[1] | 4 | *
|
---|
[21211] | 5 | * These public functions can be only used by other drivers. They all
|
---|
| 6 | * do an IOCTL to VBoxGuest via IDC.
|
---|
[1] | 7 | */
|
---|
| 8 |
|
---|
| 9 | /*
|
---|
[98103] | 10 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[1] | 11 | *
|
---|
[72627] | 12 | * Permission is hereby granted, free of charge, to any person
|
---|
| 13 | * obtaining a copy of this software and associated documentation
|
---|
| 14 | * files (the "Software"), to deal in the Software without
|
---|
| 15 | * restriction, including without limitation the rights to use,
|
---|
| 16 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
| 17 | * copies of the Software, and to permit persons to whom the
|
---|
| 18 | * Software is furnished to do so, subject to the following
|
---|
| 19 | * conditions:
|
---|
[8155] | 20 | *
|
---|
[72627] | 21 | * The above copyright notice and this permission notice shall be
|
---|
| 22 | * included in all copies or substantial portions of the Software.
|
---|
[26425] | 23 | *
|
---|
[72627] | 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
---|
| 25 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
---|
| 26 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
---|
| 27 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
---|
| 28 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
---|
| 29 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
---|
| 30 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
| 31 | * OTHER DEALINGS IN THE SOFTWARE.
|
---|
[1] | 32 | */
|
---|
| 33 |
|
---|
[69308] | 34 |
|
---|
[68476] | 35 | /*********************************************************************************************************************************
|
---|
| 36 | * Header Files *
|
---|
| 37 | *********************************************************************************************************************************/
|
---|
[68645] | 38 | #include "VBoxGuestR0LibInternal.h"
|
---|
[1] | 39 |
|
---|
| 40 | #include <iprt/assert.h>
|
---|
| 41 | #include <iprt/semaphore.h>
|
---|
[2194] | 42 | #include <iprt/string.h>
|
---|
[76419] | 43 | #include <VBox/err.h>
|
---|
[1] | 44 |
|
---|
[68653] | 45 | #ifdef VBGL_VBOXGUEST
|
---|
| 46 | # error "This file shouldn't be part of the VBoxGuestR0LibBase library that is linked into VBoxGuest. It's client code."
|
---|
| 47 | #endif
|
---|
| 48 |
|
---|
| 49 |
|
---|
| 50 | /*********************************************************************************************************************************
|
---|
| 51 | * Defined Constants And Macros *
|
---|
| 52 | *********************************************************************************************************************************/
|
---|
[58181] | 53 | #define VBGL_HGCM_ASSERT_MSG AssertReleaseMsg
|
---|
[1] | 54 |
|
---|
[69308] | 55 |
|
---|
[68476] | 56 | /*********************************************************************************************************************************
|
---|
| 57 | * Global Variables *
|
---|
| 58 | *********************************************************************************************************************************/
|
---|
[21461] | 59 | /**
|
---|
[68102] | 60 | * Fast heap for HGCM handles data.
|
---|
| 61 | * @{
|
---|
| 62 | */
|
---|
[68476] | 63 | static RTSEMFASTMUTEX g_hMtxHGCMHandleData;
|
---|
| 64 | static struct VBGLHGCMHANDLEDATA g_aHGCMHandleData[64];
|
---|
| 65 | /** @} */
|
---|
[68102] | 66 |
|
---|
| 67 |
|
---|
| 68 | /**
|
---|
[21461] | 69 | * Initializes the HGCM VBGL bits.
|
---|
| 70 | *
|
---|
| 71 | * @return VBox status code.
|
---|
| 72 | */
|
---|
[68654] | 73 | DECLR0VBGL(int) VbglR0HGCMInit(void)
|
---|
[1] | 74 | {
|
---|
[68476] | 75 | AssertReturn(g_hMtxHGCMHandleData == NIL_RTSEMFASTMUTEX, VINF_ALREADY_INITIALIZED);
|
---|
| 76 | return RTSemFastMutexCreate(&g_hMtxHGCMHandleData);
|
---|
[1] | 77 | }
|
---|
| 78 |
|
---|
[21461] | 79 | /**
|
---|
| 80 | * Initializes the HGCM VBGL bits.
|
---|
| 81 | *
|
---|
| 82 | * @return VBox status code.
|
---|
| 83 | */
|
---|
[68654] | 84 | DECLR0VBGL(int) VbglR0HGCMTerminate(void)
|
---|
[1] | 85 | {
|
---|
[68476] | 86 | RTSemFastMutexDestroy(g_hMtxHGCMHandleData);
|
---|
| 87 | g_hMtxHGCMHandleData = NIL_RTSEMFASTMUTEX;
|
---|
[1] | 88 |
|
---|
| 89 | return VINF_SUCCESS;
|
---|
| 90 | }
|
---|
| 91 |
|
---|
[68476] | 92 | DECLINLINE(int) vbglR0HandleHeapEnter(void)
|
---|
[1] | 93 | {
|
---|
[68476] | 94 | int rc = RTSemFastMutexRequest(g_hMtxHGCMHandleData);
|
---|
[1] | 95 |
|
---|
[58181] | 96 | VBGL_HGCM_ASSERT_MSG(RT_SUCCESS(rc), ("Failed to request handle heap mutex, rc = %Rrc\n", rc));
|
---|
[1] | 97 |
|
---|
| 98 | return rc;
|
---|
| 99 | }
|
---|
| 100 |
|
---|
[68476] | 101 | DECLINLINE(void) vbglR0HandleHeapLeave(void)
|
---|
[1] | 102 | {
|
---|
[68476] | 103 | RTSemFastMutexRelease(g_hMtxHGCMHandleData);
|
---|
[1] | 104 | }
|
---|
| 105 |
|
---|
[68476] | 106 | struct VBGLHGCMHANDLEDATA *vbglR0HGCMHandleAlloc(void)
|
---|
[1] | 107 | {
|
---|
[58181] | 108 | struct VBGLHGCMHANDLEDATA *p = NULL;
|
---|
[68476] | 109 | int rc = vbglR0HandleHeapEnter();
|
---|
[58181] | 110 | if (RT_SUCCESS(rc))
|
---|
| 111 | {
|
---|
| 112 | uint32_t i;
|
---|
[1] | 113 |
|
---|
[58181] | 114 | /* Simple linear search in array. This will be called not so often, only connect/disconnect. */
|
---|
| 115 | /** @todo bitmap for faster search and other obvious optimizations. */
|
---|
[68476] | 116 | for (i = 0; i < RT_ELEMENTS(g_aHGCMHandleData); i++)
|
---|
[1] | 117 | {
|
---|
[68476] | 118 | if (!g_aHGCMHandleData[i].fAllocated)
|
---|
[58181] | 119 | {
|
---|
[68476] | 120 | p = &g_aHGCMHandleData[i];
|
---|
[58181] | 121 | p->fAllocated = 1;
|
---|
| 122 | break;
|
---|
| 123 | }
|
---|
[1] | 124 | }
|
---|
| 125 |
|
---|
[68476] | 126 | vbglR0HandleHeapLeave();
|
---|
[1] | 127 |
|
---|
[58181] | 128 | VBGL_HGCM_ASSERT_MSG(p != NULL, ("Not enough HGCM handles.\n"));
|
---|
| 129 | }
|
---|
[1] | 130 | return p;
|
---|
| 131 | }
|
---|
| 132 |
|
---|
[68476] | 133 | void vbglR0HGCMHandleFree(struct VBGLHGCMHANDLEDATA *pHandle)
|
---|
[1] | 134 | {
|
---|
[58181] | 135 | if (pHandle)
|
---|
| 136 | {
|
---|
[68476] | 137 | int rc = vbglR0HandleHeapEnter();
|
---|
[58181] | 138 | if (RT_SUCCESS(rc))
|
---|
| 139 | {
|
---|
| 140 | VBGL_HGCM_ASSERT_MSG(pHandle->fAllocated, ("Freeing not allocated handle.\n"));
|
---|
[719] | 141 |
|
---|
[58181] | 142 | RT_ZERO(*pHandle);
|
---|
[68476] | 143 | vbglR0HandleHeapLeave();
|
---|
[58181] | 144 | }
|
---|
| 145 | }
|
---|
[1] | 146 | }
|
---|
| 147 |
|
---|
[68654] | 148 | DECLR0VBGL(int) VbglR0HGCMConnect(VBGLHGCMHANDLE *pHandle, const char *pszServiceName, HGCMCLIENTID *pidClient)
|
---|
[1] | 149 | {
|
---|
[719] | 150 | int rc;
|
---|
[68476] | 151 | if (pHandle && pszServiceName && pidClient)
|
---|
[1] | 152 | {
|
---|
[68476] | 153 | struct VBGLHGCMHANDLEDATA *pHandleData = vbglR0HGCMHandleAlloc();
|
---|
[58181] | 154 | if (pHandleData)
|
---|
[1] | 155 | {
|
---|
[68550] | 156 | rc = VbglR0IdcOpen(&pHandleData->IdcHandle,
|
---|
| 157 | VBGL_IOC_VERSION /*uReqVersion*/,
|
---|
| 158 | VBGL_IOC_VERSION & UINT32_C(0xffff0000) /*uMinVersion*/,
|
---|
| 159 | NULL /*puSessionVersion*/, NULL /*puDriverVersion*/, NULL /*uDriverRevision*/);
|
---|
[50838] | 160 | if (RT_SUCCESS(rc))
|
---|
[1] | 161 | {
|
---|
[68550] | 162 | VBGLIOCHGCMCONNECT Info;
|
---|
[68476] | 163 | RT_ZERO(Info);
|
---|
[68550] | 164 | VBGLREQHDR_INIT(&Info.Hdr, HGCM_CONNECT);
|
---|
| 165 | Info.u.In.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
|
---|
| 166 | rc = RTStrCopy(Info.u.In.Loc.u.host.achName, sizeof(Info.u.In.Loc.u.host.achName), pszServiceName);
|
---|
[58181] | 167 | if (RT_SUCCESS(rc))
|
---|
| 168 | {
|
---|
[68550] | 169 | rc = VbglR0IdcCall(&pHandleData->IdcHandle, VBGL_IOCTL_HGCM_CONNECT, &Info.Hdr, sizeof(Info));
|
---|
[68476] | 170 | if (RT_SUCCESS(rc))
|
---|
| 171 | {
|
---|
[68550] | 172 | *pidClient = Info.u.Out.idClient;
|
---|
[68476] | 173 | *pHandle = pHandleData;
|
---|
| 174 | return rc;
|
---|
| 175 | }
|
---|
[58181] | 176 | }
|
---|
| 177 |
|
---|
[68550] | 178 | VbglR0IdcClose(&pHandleData->IdcHandle);
|
---|
[1] | 179 | }
|
---|
[50838] | 180 |
|
---|
[68476] | 181 | vbglR0HGCMHandleFree(pHandleData);
|
---|
[1] | 182 | }
|
---|
[58181] | 183 | else
|
---|
| 184 | rc = VERR_NO_MEMORY;
|
---|
[1] | 185 | }
|
---|
[58181] | 186 | else
|
---|
| 187 | rc = VERR_INVALID_PARAMETER;
|
---|
[1] | 188 | return rc;
|
---|
| 189 | }
|
---|
| 190 |
|
---|
[68654] | 191 | DECLR0VBGL(int) VbglR0HGCMDisconnect(VBGLHGCMHANDLE handle, HGCMCLIENTID idClient)
|
---|
[1] | 192 | {
|
---|
[68476] | 193 | int rc;
|
---|
[68550] | 194 | VBGLIOCHGCMDISCONNECT Info;
|
---|
[1] | 195 |
|
---|
[68476] | 196 | RT_ZERO(Info);
|
---|
[68550] | 197 | VBGLREQHDR_INIT(&Info.Hdr, HGCM_DISCONNECT);
|
---|
| 198 | Info.u.In.idClient = idClient;
|
---|
| 199 | rc = VbglR0IdcCall(&handle->IdcHandle, VBGL_IOCTL_HGCM_DISCONNECT, &Info.Hdr, sizeof(Info));
|
---|
[68476] | 200 |
|
---|
[68550] | 201 | VbglR0IdcClose(&handle->IdcHandle);
|
---|
[1] | 202 |
|
---|
[68476] | 203 | vbglR0HGCMHandleFree(handle);
|
---|
[1] | 204 |
|
---|
| 205 | return rc;
|
---|
| 206 | }
|
---|
| 207 |
|
---|
[68654] | 208 | DECLR0VBGL(int) VbglR0HGCMCallRaw(VBGLHGCMHANDLE handle, PVBGLIOCHGCMCALL pData, uint32_t cbData)
|
---|
[1] | 209 | {
|
---|
[68550] | 210 | VBGL_HGCM_ASSERT_MSG(cbData >= sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(HGCMFunctionParameter),
|
---|
[58181] | 211 | ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->cParms,
|
---|
[68550] | 212 | sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(VBGLIOCHGCMCALL)));
|
---|
[1] | 213 |
|
---|
[68550] | 214 | return VbglR0IdcCallRaw(&handle->IdcHandle, VBGL_IOCTL_HGCM_CALL(cbData), &pData->Hdr, cbData);
|
---|
[1] | 215 | }
|
---|
| 216 |
|
---|
[68654] | 217 | DECLR0VBGL(int) VbglR0HGCMCall(VBGLHGCMHANDLE handle, PVBGLIOCHGCMCALL pData, uint32_t cbData)
|
---|
[40483] | 218 | {
|
---|
[68550] | 219 | int rc = VbglR0HGCMCallRaw(handle, pData, cbData);
|
---|
| 220 | if (RT_SUCCESS(rc))
|
---|
| 221 | rc = pData->Hdr.rc;
|
---|
| 222 | return rc;
|
---|
[40483] | 223 | }
|
---|
| 224 |
|
---|
[68654] | 225 | DECLR0VBGL(int) VbglR0HGCMCallUserDataRaw(VBGLHGCMHANDLE handle, PVBGLIOCHGCMCALL pData, uint32_t cbData)
|
---|
[14207] | 226 | {
|
---|
[68550] | 227 | VBGL_HGCM_ASSERT_MSG(cbData >= sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(HGCMFunctionParameter),
|
---|
| 228 | ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->cParms,
|
---|
| 229 | sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(VBGLIOCHGCMCALL)));
|
---|
[14207] | 230 |
|
---|
[68550] | 231 | return VbglR0IdcCallRaw(&handle->IdcHandle, VBGL_IOCTL_HGCM_CALL_WITH_USER_DATA(cbData), &pData->Hdr, cbData);
|
---|
[14207] | 232 | }
|
---|
| 233 |
|
---|
[75547] | 234 |
|
---|
| 235 | DECLR0VBGL(int) VbglR0HGCMFastCall(VBGLHGCMHANDLE hHandle, PVBGLIOCIDCHGCMFASTCALL pCallReq, uint32_t cbCallReq)
|
---|
| 236 | {
|
---|
| 237 | /* pCallReq->Hdr.rc and pCallReq->HgcmCallReq.header.header.rc; are not used by this IDC. */
|
---|
| 238 | return VbglR0IdcCallRaw(&hHandle->IdcHandle, VBGL_IOCTL_IDC_HGCM_FAST_CALL, &pCallReq->Hdr, cbCallReq);
|
---|
| 239 | }
|
---|
| 240 |
|
---|