VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestShClPrivate.cpp

Last change on this file was 100651, checked in by vboxsync, 10 months ago

Shared Clipboard: Also give the registered service extension the chance of calling an optional callback. Only used by VRDE so far (and probably never will be used by anything else, historical reasons). bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: GuestShClPrivate.cpp 100651 2023-07-19 11:52:59Z vboxsync $ */
2/** @file
3 * Private Shared Clipboard code.
4 */
5
6/*
7 * Copyright (C) 2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
29#include "LoggingNew.h"
30
31#include "GuestImpl.h"
32#include "AutoCaller.h"
33
34#ifdef VBOX_WITH_SHARED_CLIPBOARD
35# include "ConsoleImpl.h"
36# include "ProgressImpl.h"
37# include "GuestShClPrivate.h"
38
39# include <iprt/semaphore.h>
40# include <iprt/cpp/utils.h>
41
42# include <VMMDev.h>
43
44# include <VBox/GuestHost/SharedClipboard.h>
45# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
46# include <VBox/GuestHost/SharedClipboard-transfers.h>
47# endif
48# include <VBox/HostServices/VBoxClipboardSvc.h>
49# include <VBox/HostServices/VBoxClipboardExt.h>
50# include <VBox/version.h>
51
52
53/*********************************************************************************************************************************
54 * GuestShCl implementation. *
55 ********************************************************************************************************************************/
56
57/** Static (Singleton) instance of the Shared Clipboard management object. */
58GuestShCl* GuestShCl::s_pInstance = NULL;
59
60GuestShCl::GuestShCl(Console *pConsole)
61 : m_pConsole(pConsole)
62 , m_pfnExtCallback(NULL)
63{
64 LogFlowFuncEnter();
65
66 RT_ZERO(m_SvcExtVRDP);
67
68 int vrc = RTCritSectInit(&m_CritSect);
69 if (RT_FAILURE(vrc))
70 throw vrc;
71}
72
73GuestShCl::~GuestShCl(void)
74{
75 uninit();
76}
77
78/**
79 * Uninitializes the Shared Clipboard management object.
80 */
81void GuestShCl::uninit(void)
82{
83 LogFlowFuncEnter();
84
85 if (RTCritSectIsInitialized(&m_CritSect))
86 RTCritSectDelete(&m_CritSect);
87
88 RT_ZERO(m_SvcExtVRDP);
89
90 m_pfnExtCallback = NULL;
91}
92
93/**
94 * Locks the Shared Clipboard management object.
95 *
96 * @returns VBox status code.
97 */
98int GuestShCl::lock(void)
99{
100 int vrc = RTCritSectEnter(&m_CritSect);
101 AssertRC(vrc);
102 return vrc;
103}
104
105/**
106 * Unlocks the Shared Clipboard management object.
107 *
108 * @returns VBox status code.
109 */
110int GuestShCl::unlock(void)
111{
112 int vrc = RTCritSectLeave(&m_CritSect);
113 AssertRC(vrc);
114 return vrc;
115}
116
117/**
118 * Registers a Shared Clipboard service extension.
119 *
120 * @returns VBox status code.
121 * @param pfnExtension Service extension to register.
122 * @param pvExtension User-supplied data pointer. Optional.
123 */
124int GuestShCl::RegisterServiceExtension(PFNHGCMSVCEXT pfnExtension, void *pvExtension)
125{
126 AssertPtrReturn(pfnExtension, VERR_INVALID_POINTER);
127 /* pvExtension is optional. */
128
129 lock();
130
131 LogFlowFunc(("m_pfnExtCallback=%p\n", this->m_pfnExtCallback));
132
133 PSHCLSVCEXT pExt = &this->m_SvcExtVRDP; /* Currently we only have one extension only. */
134
135 Assert(pExt->pfnExt == NULL);
136
137 pExt->pfnExt = pfnExtension;
138 pExt->pvExt = pvExtension;
139 pExt->pfnExtCallback = this->m_pfnExtCallback; /* Assign callback function. Optional and can be NULL. */
140
141 if (pExt->pfnExtCallback)
142 {
143 /* Make sure to also give the extension the ability to use the callback. */
144 SHCLEXTPARMS parms;
145 RT_ZERO(parms);
146
147 parms.u.SetCallback.pfnCallback = pExt->pfnExtCallback;
148
149 /* ignore rc, callback is optional */ pExt->pfnExt(pExt->pvExt,
150 VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK, &parms, sizeof(parms));
151 }
152
153 unlock();
154
155 return VINF_SUCCESS;
156}
157
158/**
159 * Unregisters a Shared Clipboard service extension.
160 *
161 * @returns VBox status code.
162 * @param pfnExtension Service extension to unregister.
163 */
164int GuestShCl::UnregisterServiceExtension(PFNHGCMSVCEXT pfnExtension)
165{
166 AssertPtrReturn(pfnExtension, VERR_INVALID_POINTER);
167
168 lock();
169
170 PSHCLSVCEXT pExt = &this->m_SvcExtVRDP; /* Currently we only have one extension only. */
171
172 AssertReturnStmt(pExt->pfnExt == pfnExtension, unlock(), VERR_INVALID_PARAMETER);
173 AssertPtr(pExt->pfnExt);
174
175 /* Unregister the callback (setting to NULL). */
176 SHCLEXTPARMS parms;
177 RT_ZERO(parms);
178
179 /* ignore rc, callback is optional */ pExt->pfnExt(pExt->pvExt,
180 VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK, &parms, sizeof(parms));
181
182 RT_BZERO(pExt, sizeof(SHCLSVCEXT));
183
184 unlock();
185
186 return VINF_SUCCESS;
187}
188
189/**
190 * Sends a (blocking) message to the host side of the host service.
191 *
192 * @returns VBox status code.
193 * @param u32Function HGCM message ID to send.
194 * @param cParms Number of parameters to send.
195 * @param paParms Array of parameters to send. Must match \c cParms.
196 */
197int GuestShCl::hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const
198{
199 /* Forward the information to the VMM device. */
200 AssertPtr(m_pConsole);
201 VMMDev *pVMMDev = m_pConsole->i_getVMMDev();
202 if (!pVMMDev)
203 return VERR_COM_OBJECT_NOT_FOUND;
204
205 return pVMMDev->hgcmHostCall("VBoxSharedClipboard", u32Function, cParms, paParms);
206}
207
208/**
209 * Reports an error by setting the error info and also informs subscribed listeners.
210 *
211 * @returns VBox status code.
212 * @param pcszId ID (name) of the clipboard. Can be NULL if not being used.
213 * @param vrc Result code (IPRT-style) to report.
214 * @param pcszMsgFmt Error message to report.
215 * @param ... Format string for \a pcszMsgFmt.
216 */
217int GuestShCl::reportError(const char *pcszId, int vrc, const char *pcszMsgFmt, ...)
218{
219 /* pcszId can be NULL. */
220 AssertReturn(pcszMsgFmt && *pcszMsgFmt != '\0', E_INVALIDARG);
221
222 va_list va;
223 va_start(va, pcszMsgFmt);
224
225 Utf8Str strMsg;
226 int const vrc2 = strMsg.printfVNoThrow(pcszMsgFmt, va);
227 if (RT_FAILURE(vrc2))
228 {
229 va_end(va);
230 return vrc2;
231 }
232
233 va_end(va);
234
235 if (pcszId)
236 LogRel(("Shared Clipboard (%s): %s (%Rrc)\n", pcszId, strMsg.c_str(), vrc));
237 else
238 LogRel(("Shared Clipboard: %s (%Rrc)\n", strMsg.c_str(), vrc));
239
240 m_pConsole->i_onClipboardError(pcszId, strMsg.c_str(), vrc);
241
242 return VINF_SUCCESS;
243}
244
245/**
246 * Static main dispatcher function to handle callbacks from the Shared Clipboard host service.
247 *
248 * @returns VBox status code.
249 * @retval VERR_NOT_SUPPORTED if the extension didn't handle the requested function. This will invoke the regular backend then.
250 * @param pvExtension Pointer to service extension.
251 * @param u32Function Callback HGCM message ID.
252 * @param pvParms Pointer to optional data provided for a particular message. Optional.
253 * @param cbParms Size (in bytes) of \a pvParms.
254 */
255/* static */
256DECLCALLBACK(int) GuestShCl::hgcmDispatcher(void *pvExtension, uint32_t u32Function,
257 void *pvParms, uint32_t cbParms)
258{
259 LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
260 pvExtension, u32Function, pvParms, cbParms));
261
262 GuestShCl *pThis = reinterpret_cast<GuestShCl*>(pvExtension);
263 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
264
265 PSHCLEXTPARMS pParms = (PSHCLEXTPARMS)pvParms;
266 /* pParms might be NULL, depending on the message. */
267
268 int vrc;
269
270 switch (u32Function)
271 {
272 case VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK:
273 pThis->m_pfnExtCallback = pParms->u.SetCallback.pfnCallback;
274 vrc = VINF_SUCCESS;
275 break;
276
277 case VBOX_CLIPBOARD_EXT_FN_ERROR:
278 {
279 vrc = pThis->reportError(pParms->u.Error.pszId, pParms->u.Error.rc, pParms->u.Error.pszMsg);
280 break;
281 }
282
283 default:
284 vrc = VERR_NOT_SUPPORTED;
285 break;
286 }
287
288 PSHCLSVCEXT const pExt = &pThis->m_SvcExtVRDP; /* Currently we have one extension only. */
289
290 if (pExt->pfnExt) /* Overwrite rc if we have an extension present. */
291 vrc = pExt->pfnExt(pExt->pvExt, u32Function, pvParms, cbParms);
292
293 LogFlowFuncLeaveRC(vrc);
294 return vrc; /* Goes back to host service. */
295}
296#endif /* VBOX_WITH_SHARED_CLIPBOARD */
297
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use