VirtualBox

source: vbox/trunk/src/VBox/Main/ConsoleVRDPServer.cpp@ 3516

Last change on this file since 3516 was 3278, checked in by vboxsync, 18 years ago

Removed some obsolete VRDP code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.3 KB
Line 
1/** @file
2 *
3 * VBox Console VRDP Helper class
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22#include "ConsoleVRDPServer.h"
23#include "ConsoleImpl.h"
24#include "DisplayImpl.h"
25
26#include "Logging.h"
27
28#include <iprt/asm.h>
29#include <iprt/ldr.h>
30
31#include <VBox/err.h>
32
33
34// ConsoleVRDPServer
35////////////////////////////////////////////////////////////////////////////////
36
37#ifdef VBOX_VRDP
38RTLDRMOD ConsoleVRDPServer::mVRDPLibrary;
39int (VBOXCALL *ConsoleVRDPServer::mpfnVRDPStartServer) (IConsole *pConsole, IVRDPServer *pVRDPServer, HVRDPSERVER *phServer);
40int (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSetFramebuffer) (HVRDPSERVER hServer, IFramebuffer *pFramebuffer, uint32_t fFlags);
41void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSetCallback) (HVRDPSERVER hServer, VRDPSERVERCALLBACK *pcallback, void *pvUser);
42void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPShutdownServer) (HVRDPSERVER hServer);
43void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdateBitmap)(HVRDPSERVER hServer, unsigned uScreenId, unsigned x, unsigned y, unsigned w, unsigned h);
44void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendResize) (HVRDPSERVER hServer);
45void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendAudioSamples)(HVRDPSERVER hserver, void *pvSamples, uint32_t cSamples, VRDPAUDIOFORMAT format);
46void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendAudioVolume) (HVRDPSERVER hserver, uint16_t left, uint16_t right);
47void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUSBRequest) (HVRDPSERVER hserver, uint32_t u32ClientId, void *pvParms, uint32_t cbParms);
48void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdate) (HVRDPSERVER hServer, unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate);
49void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPQueryInfo) (HVRDPSERVER hserver, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
50void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPClipboard) (HVRDPSERVER hserver, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData, uint32_t *pcbActualRead);
51#endif /* VBOX_VRDP */
52
53ConsoleVRDPServer::ConsoleVRDPServer (Console *console)
54{
55 mConsole = console;
56
57 int rc = RTCritSectInit (&mCritSect);
58 AssertRC (rc);
59
60 mcClipboardRefs = 0;
61 mpfnClipboardCallback = NULL;
62
63#ifdef VBOX_WITH_USB
64 mUSBBackends.pHead = NULL;
65 mUSBBackends.pTail = NULL;
66
67 mUSBBackends.thread = NIL_RTTHREAD;
68 mUSBBackends.fThreadRunning = false;
69 mUSBBackends.event = 0;
70#endif
71
72#ifdef VBOX_VRDP
73 mhServer = 0;
74#endif
75
76 mAuthLibrary = 0;
77}
78
79ConsoleVRDPServer::~ConsoleVRDPServer ()
80{
81 Stop ();
82
83 if (RTCritSectIsInitialized (&mCritSect))
84 {
85 RTCritSectDelete (&mCritSect);
86 memset (&mCritSect, 0, sizeof (mCritSect));
87 }
88}
89
90int ConsoleVRDPServer::Launch (void)
91{
92 LogFlowMember(("ConsoleVRDPServer::Launch\n"));
93#ifdef VBOX_VRDP
94 int rc = VINF_SUCCESS;
95 IVRDPServer *vrdpserver = mConsole->getVRDPServer ();
96 Assert(vrdpserver);
97 BOOL vrdpEnabled = FALSE;
98
99 HRESULT rc2 = vrdpserver->COMGETTER(Enabled) (&vrdpEnabled);
100 AssertComRC(rc2);
101
102 if (SUCCEEDED (rc2)
103 && vrdpEnabled
104 && loadVRDPLibrary ())
105 {
106 rc = mpfnVRDPStartServer(mConsole, vrdpserver, &mhServer);
107
108 if (VBOX_SUCCESS(rc))
109 {
110#ifdef VBOX_WITH_USB
111 remoteUSBThreadStart ();
112#endif /* VBOX_WITH_USB */
113 }
114 else
115 AssertMsgFailed(("Could not start VRDP server: rc = %Vrc\n", rc));
116 }
117#else
118 int rc = VERR_NOT_SUPPORTED;
119#endif
120 return rc;
121}
122
123void ConsoleVRDPServer::SetCallback (void)
124{
125#ifdef VBOX_VRDP
126 /* This is called after VM is created and allows the server to accept client connection. */
127 if (mhServer && mpfnVRDPSetCallback)
128 {
129 mpfnVRDPSetCallback (mhServer, mConsole->getVrdpServerCallback (), mConsole);
130 }
131#endif
132}
133
134void ConsoleVRDPServer::Stop (void)
135{
136 Assert(VALID_PTR(this)); /** @todo r=bird: there are(/was) some odd cases where this buster was invalid on
137 * linux. Just remove this when it's 100% sure that problem has been fixed. */
138#ifdef VBOX_VRDP
139 if (mhServer)
140 {
141 HVRDPSERVER hServer = mhServer;
142
143 /* Reset the handle to avoid further calls to the server. */
144 mhServer = 0;
145
146 mpfnVRDPShutdownServer (hServer);
147 }
148#endif
149
150#ifdef VBOX_WITH_USB
151 remoteUSBThreadStop ();
152#endif /* VBOX_WITH_USB */
153
154 mpfnAuthEntry = NULL;
155 mpfnAuthEntry2 = NULL;
156
157 if (mAuthLibrary)
158 {
159 RTLdrClose(mAuthLibrary);
160 mAuthLibrary = 0;
161 }
162}
163
164/* Worker thread for Remote USB. The thread polls the clients for
165 * the list of attached USB devices.
166 * The thread is also responsible for attaching/detaching devices
167 * to/from the VM.
168 *
169 * It is expected that attaching/detaching is not a frequent operation.
170 *
171 * The thread is always running when the VRDP server is active.
172 *
173 * The thread scans backends and requests the device list every 2 seconds.
174 *
175 * When device list is available, the thread calls the Console to process it.
176 *
177 */
178#define VRDP_DEVICE_LIST_PERIOD_MS (2000)
179
180#ifdef VBOX_WITH_USB
181static DECLCALLBACK(int) threadRemoteUSB (RTTHREAD self, void *pvUser)
182{
183 ConsoleVRDPServer *pOwner = (ConsoleVRDPServer *)pvUser;
184
185 LogFlow(("Console::threadRemoteUSB: start. owner = %p.\n", pOwner));
186
187 pOwner->notifyRemoteUSBThreadRunning (self);
188
189 while (pOwner->isRemoteUSBThreadRunning ())
190 {
191 RemoteUSBBackend *pRemoteUSBBackend = NULL;
192
193 while ((pRemoteUSBBackend = pOwner->usbBackendGetNext (pRemoteUSBBackend)) != NULL)
194 {
195 pRemoteUSBBackend->PollRemoteDevices ();
196 }
197
198 pOwner->waitRemoteUSBThreadEvent (VRDP_DEVICE_LIST_PERIOD_MS);
199
200 LogFlow(("Console::threadRemoteUSB: iteration. owner = %p.\n", pOwner));
201 }
202
203 return VINF_SUCCESS;
204}
205
206void ConsoleVRDPServer::notifyRemoteUSBThreadRunning (RTTHREAD thread)
207{
208 mUSBBackends.thread = thread;
209 mUSBBackends.fThreadRunning = true;
210 int rc = RTThreadUserSignal (thread);
211 AssertRC (rc);
212}
213
214bool ConsoleVRDPServer::isRemoteUSBThreadRunning (void)
215{
216 return mUSBBackends.fThreadRunning;
217}
218
219void ConsoleVRDPServer::waitRemoteUSBThreadEvent (unsigned cMillies)
220{
221 int rc = RTSemEventWait (mUSBBackends.event, cMillies);
222 Assert (VBOX_SUCCESS(rc) || rc == VERR_TIMEOUT);
223 NOREF(rc);
224}
225
226void ConsoleVRDPServer::remoteUSBThreadStart (void)
227{
228 int rc = RTSemEventCreate (&mUSBBackends.event);
229
230 if (VBOX_FAILURE (rc))
231 {
232 AssertFailed ();
233 mUSBBackends.event = 0;
234 }
235
236 if (VBOX_SUCCESS (rc))
237 {
238 rc = RTThreadCreate (&mUSBBackends.thread, threadRemoteUSB, this, 65536,
239 RTTHREADTYPE_VRDP_IO, RTTHREADFLAGS_WAITABLE, "remote usb");
240 }
241
242 if (VBOX_FAILURE (rc))
243 {
244 LogRel(("Warning: could not start the remote USB thread, rc = %Vrc!!!\n", rc));
245 mUSBBackends.thread = NIL_RTTHREAD;
246 }
247 else
248 {
249 /* Wait until the thread is ready. */
250 rc = RTThreadUserWait (mUSBBackends.thread, 60000);
251 AssertRC (rc);
252 Assert (mUSBBackends.fThreadRunning || VBOX_FAILURE (rc));
253 }
254}
255
256void ConsoleVRDPServer::remoteUSBThreadStop (void)
257{
258 mUSBBackends.fThreadRunning = false;
259
260 if (mUSBBackends.thread != NIL_RTTHREAD)
261 {
262 Assert (mUSBBackends.event != 0);
263
264 RTSemEventSignal (mUSBBackends.event);
265
266 int rc = RTThreadWait (mUSBBackends.thread, 60000, NULL);
267 AssertRC (rc);
268
269 mUSBBackends.thread = NIL_RTTHREAD;
270 }
271
272 if (mUSBBackends.event)
273 {
274 RTSemEventDestroy (mUSBBackends.event);
275 mUSBBackends.event = 0;
276 }
277}
278#endif /* VBOX_WITH_USB */
279
280VRDPAuthResult ConsoleVRDPServer::Authenticate (const Guid &uuid, VRDPAuthGuestJudgement guestJudgement,
281 const char *pszUser, const char *pszPassword, const char *pszDomain,
282 uint32_t u32ClientId)
283{
284 VRDPAUTHUUID rawuuid;
285
286 memcpy (rawuuid, ((Guid &)uuid).ptr (), sizeof (rawuuid));
287
288 LogFlow(("ConsoleVRDPServer::Authenticate: uuid = %Vuuid, guestJudgement = %d, pszUser = %s, pszPassword = %s, pszDomain = %s, u32ClientId = %d\n",
289 rawuuid, guestJudgement, pszUser, pszPassword, pszDomain, u32ClientId));
290
291 /*
292 * Called only from VRDP input thread. So thread safety is not required.
293 */
294
295 if (!mAuthLibrary)
296 {
297 /* Load the external authentication library. */
298
299 ComPtr<IMachine> machine;
300 mConsole->COMGETTER(Machine)(machine.asOutParam());
301
302 ComPtr<IVirtualBox> virtualBox;
303 machine->COMGETTER(Parent)(virtualBox.asOutParam());
304
305 ComPtr<ISystemProperties> systemProperties;
306 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
307
308 Bstr authLibrary;
309 systemProperties->COMGETTER(RemoteDisplayAuthLibrary)(authLibrary.asOutParam());
310
311 Utf8Str filename = authLibrary;
312
313 LogRel(("VRDPAUTH: ConsoleVRDPServer::Authenticate: loading external authentication library '%ls'\n", authLibrary.raw()));
314
315 int rc = RTLdrLoad (filename.raw(), &mAuthLibrary);
316 if (VBOX_FAILURE (rc))
317 LogRel(("VRDPAUTH: Failed to load external authentication library. Error code: %Vrc\n", rc));
318
319 if (VBOX_SUCCESS (rc))
320 {
321 /* Get the entry point. */
322 mpfnAuthEntry2 = NULL;
323 int rc2 = RTLdrGetSymbol(mAuthLibrary, "VRDPAuth2", (void**)&mpfnAuthEntry2);
324 if (VBOX_FAILURE (rc2))
325 {
326 LogRel(("VRDPAUTH: Could not resolve import '%s'. Error code: %Vrc\n", "VRDPAuth2", rc2));
327 rc = rc2;
328 }
329
330 /* Get the entry point. */
331 mpfnAuthEntry = NULL;
332 rc2 = RTLdrGetSymbol(mAuthLibrary, "VRDPAuth", (void**)&mpfnAuthEntry);
333 if (VBOX_FAILURE (rc2))
334 {
335 LogRel(("VRDPAUTH: Could not resolve import '%s'. Error code: %Vrc\n", "VRDPAuth", rc2));
336 rc = rc2;
337 }
338
339 if (mpfnAuthEntry2 || mpfnAuthEntry)
340 {
341 LogRel(("VRDPAUTH: Using entry point '%s'.\n", mpfnAuthEntry2? "VRDPAuth2": "VRDPAuth"));
342 rc = VINF_SUCCESS;
343 }
344 }
345
346 if (VBOX_FAILURE (rc))
347 {
348 mConsole->reportAuthLibraryError (filename.raw(), rc);
349
350 mpfnAuthEntry = NULL;
351 mpfnAuthEntry2 = NULL;
352
353 if (mAuthLibrary)
354 {
355 RTLdrClose(mAuthLibrary);
356 mAuthLibrary = 0;
357 }
358
359 return VRDPAuthAccessDenied;
360 }
361 }
362
363 Assert (mAuthLibrary && (mpfnAuthEntry || mpfnAuthEntry2));
364
365 VRDPAuthResult result = mpfnAuthEntry?
366 mpfnAuthEntry (&rawuuid, guestJudgement, pszUser, pszPassword, pszDomain):
367 mpfnAuthEntry2 (&rawuuid, guestJudgement, pszUser, pszPassword, pszDomain, true, u32ClientId);
368
369 switch (result)
370 {
371 case VRDPAuthAccessDenied:
372 LogRel(("VRDPAUTH: external authentication module returned 'access denied'\n"));
373 break;
374 case VRDPAuthAccessGranted:
375 LogRel(("VRDPAUTH: external authentication module returned 'access granted'\n"));
376 break;
377 case VRDPAuthDelegateToGuest:
378 LogRel(("VRDPAUTH: external authentication module returned 'delegate request to guest'\n"));
379 break;
380 default:
381 LogRel(("VRDPAUTH: external authentication module returned incorrect return code %d\n", result));
382 result = VRDPAuthAccessDenied;
383 }
384
385 LogFlow(("ConsoleVRDPServer::Authenticate: result = %d\n", result));
386
387 return result;
388}
389
390void ConsoleVRDPServer::AuthDisconnect (const Guid &uuid, uint32_t u32ClientId)
391{
392 VRDPAUTHUUID rawuuid;
393
394 memcpy (rawuuid, ((Guid &)uuid).ptr (), sizeof (rawuuid));
395
396 LogFlow(("ConsoleVRDPServer::AuthDisconnect: uuid = %Vuuid, u32ClientId = %d\n",
397 rawuuid, u32ClientId));
398
399 Assert (mAuthLibrary && (mpfnAuthEntry || mpfnAuthEntry2));
400
401 if (mpfnAuthEntry2)
402 mpfnAuthEntry2 (&rawuuid, VRDPAuthGuestNotAsked, NULL, NULL, NULL, false, u32ClientId);
403}
404
405int ConsoleVRDPServer::lockConsoleVRDPServer (void)
406{
407 int rc = RTCritSectEnter (&mCritSect);
408 AssertRC (rc);
409 return rc;
410}
411
412void ConsoleVRDPServer::unlockConsoleVRDPServer (void)
413{
414 RTCritSectLeave (&mCritSect);
415}
416
417DECLCALLBACK(int) ConsoleVRDPServer::ClipboardCallback (void *pvCallback,
418 uint32_t u32ClientId,
419 uint32_t u32Function,
420 uint32_t u32Format,
421 const void *pvData,
422 uint32_t cbData)
423{
424 LogFlowFunc(("pvCallback = %p, u32ClientId = %d, u32Function = %d, u32Format = 0x%08X, pvData = %p, cbData = %d\n",
425 pvCallback, u32ClientId, u32Function, u32Format, pvData, cbData));
426
427 int rc = VINF_SUCCESS;
428
429 ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvCallback);
430
431 NOREF(u32ClientId);
432
433 switch (u32Function)
434 {
435 case VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE:
436 {
437 if (pServer->mpfnClipboardCallback)
438 {
439 pServer->mpfnClipboardCallback (VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE,
440 u32Format,
441 (void *)pvData,
442 cbData);
443 }
444 } break;
445
446 case VRDP_CLIPBOARD_FUNCTION_DATA_READ:
447 {
448 if (pServer->mpfnClipboardCallback)
449 {
450 pServer->mpfnClipboardCallback (VBOX_CLIPBOARD_EXT_FN_DATA_READ,
451 u32Format,
452 (void *)pvData,
453 cbData);
454 }
455 } break;
456
457 default:
458 rc = VERR_NOT_SUPPORTED;
459 }
460
461 return rc;
462}
463
464DECLCALLBACK(int) ConsoleVRDPServer::ClipboardServiceExtension (void *pvExtension,
465 uint32_t u32Function,
466 void *pvParms,
467 uint32_t cbParms)
468{
469 LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
470 pvExtension, u32Function, pvParms, cbParms));
471
472 int rc = VINF_SUCCESS;
473
474#ifdef VBOX_VRDP
475 ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvExtension);
476
477 VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
478
479 switch (u32Function)
480 {
481 case VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK:
482 {
483 pServer->mpfnClipboardCallback = (PFNVRDPCLIPBOARDEXTCALLBACK)pParms->pvData;
484 } break;
485
486 case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
487 {
488 /* The guest announces clipboard formats. This must be delivered to all clients. */
489 if (mpfnVRDPClipboard)
490 {
491 mpfnVRDPClipboard (pServer->mhServer,
492 VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE,
493 pParms->u32Format,
494 NULL,
495 0,
496 NULL);
497 }
498 } break;
499
500 case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
501 {
502 /* The clipboard service expects that the pvData buffer will be filled
503 * with clipboard data. The server returns the data from the client that
504 * announced the requested format most recently.
505 */
506 if (mpfnVRDPClipboard)
507 {
508 mpfnVRDPClipboard (pServer->mhServer,
509 VRDP_CLIPBOARD_FUNCTION_DATA_READ,
510 pParms->u32Format,
511 pParms->pvData,
512 pParms->cbData,
513 &pParms->cbData);
514 }
515 } break;
516
517 case VBOX_CLIPBOARD_EXT_FN_DATA_WRITE:
518 {
519 if (mpfnVRDPClipboard)
520 {
521 mpfnVRDPClipboard (pServer->mhServer,
522 VRDP_CLIPBOARD_FUNCTION_DATA_WRITE,
523 pParms->u32Format,
524 pParms->pvData,
525 pParms->cbData,
526 NULL);
527 }
528 } break;
529
530 default:
531 rc = VERR_NOT_SUPPORTED;
532 }
533#endif /* VBOX_VRDP */
534
535 return rc;
536}
537
538void ConsoleVRDPServer::ClipboardCreate (uint32_t u32ClientId, PFNVRDPCLIPBOARDCALLBACK *ppfn, void **ppv)
539{
540 int rc = lockConsoleVRDPServer ();
541
542 if (VBOX_SUCCESS (rc))
543 {
544 if (mcClipboardRefs == 0)
545 {
546 rc = HGCMHostRegisterServiceExtension (&mhClipboard, "VBoxSharedClipboard", ClipboardServiceExtension, this);
547
548 if (VBOX_SUCCESS (rc))
549 {
550 mcClipboardRefs++;
551 }
552 }
553
554 if (VBOX_SUCCESS (rc))
555 {
556 *ppfn = ClipboardCallback;
557 *ppv = this;
558 }
559
560 unlockConsoleVRDPServer ();
561 }
562}
563
564void ConsoleVRDPServer::ClipboardDelete (uint32_t u32ClientId)
565{
566 int rc = lockConsoleVRDPServer ();
567
568 if (VBOX_SUCCESS (rc))
569 {
570 mcClipboardRefs--;
571
572 if (mcClipboardRefs == 0)
573 {
574 HGCMHostUnregisterServiceExtension (mhClipboard);
575 }
576
577 unlockConsoleVRDPServer ();
578 }
579}
580
581/* That is called on INPUT thread of the VRDP server.
582 * The ConsoleVRDPServer keeps a list of created backend instances.
583 */
584void ConsoleVRDPServer::USBBackendCreate (uint32_t u32ClientId, PFNVRDPUSBCALLBACK *ppfn, void **ppv)
585{
586#ifdef VBOX_WITH_USB
587 LogFlow(("ConsoleVRDPServer::USBBackendCreate: u32ClientId = %d\n", u32ClientId));
588
589 /* Create a new instance of the USB backend for the new client. */
590 RemoteUSBBackend *pRemoteUSBBackend = new RemoteUSBBackend (mConsole, this, u32ClientId);
591
592 if (pRemoteUSBBackend)
593 {
594 pRemoteUSBBackend->AddRef (); /* 'Release' called in USBBackendDelete. */
595
596 /* Append the new instance in the list. */
597 int rc = lockConsoleVRDPServer ();
598
599 if (VBOX_SUCCESS (rc))
600 {
601 pRemoteUSBBackend->pNext = mUSBBackends.pHead;
602 if (mUSBBackends.pHead)
603 {
604 mUSBBackends.pHead->pPrev = pRemoteUSBBackend;
605 }
606 else
607 {
608 mUSBBackends.pTail = pRemoteUSBBackend;
609 }
610
611 mUSBBackends.pHead = pRemoteUSBBackend;
612
613 unlockConsoleVRDPServer ();
614
615 pRemoteUSBBackend->QueryVRDPCallbackPointer (ppfn, ppv);
616 }
617
618 if (VBOX_FAILURE (rc))
619 {
620 pRemoteUSBBackend->Release ();
621 }
622 }
623#endif
624}
625
626void ConsoleVRDPServer::USBBackendDelete (uint32_t u32ClientId)
627{
628#ifdef VBOX_WITH_USB
629 LogFlow(("ConsoleVRDPServer::USBBackendDelete: u32ClientId = %d\n", u32ClientId));
630
631 RemoteUSBBackend *pRemoteUSBBackend = NULL;
632
633 /* Find the instance. */
634 int rc = lockConsoleVRDPServer ();
635
636 if (VBOX_SUCCESS (rc))
637 {
638 pRemoteUSBBackend = usbBackendFind (u32ClientId);
639
640 if (pRemoteUSBBackend)
641 {
642 /* Notify that it will be deleted. */
643 pRemoteUSBBackend->NotifyDelete ();
644 }
645
646 unlockConsoleVRDPServer ();
647 }
648
649 if (pRemoteUSBBackend)
650 {
651 /* Here the instance has been excluded from the list and can be dereferenced. */
652 pRemoteUSBBackend->Release ();
653 }
654#endif
655}
656
657void *ConsoleVRDPServer::USBBackendRequestPointer (uint32_t u32ClientId, const Guid *pGuid)
658{
659#ifdef VBOX_WITH_USB
660 RemoteUSBBackend *pRemoteUSBBackend = NULL;
661
662 /* Find the instance. */
663 int rc = lockConsoleVRDPServer ();
664
665 if (VBOX_SUCCESS (rc))
666 {
667 pRemoteUSBBackend = usbBackendFind (u32ClientId);
668
669 if (pRemoteUSBBackend)
670 {
671 /* Inform the backend instance that it is referenced by the Guid. */
672 bool fAdded = pRemoteUSBBackend->addUUID (pGuid);
673
674 if (fAdded)
675 {
676 /* Reference the instance because its pointer is being taken. */
677 pRemoteUSBBackend->AddRef (); /* 'Release' is called in USBBackendReleasePointer. */
678 }
679 else
680 {
681 pRemoteUSBBackend = NULL;
682 }
683 }
684
685 unlockConsoleVRDPServer ();
686 }
687
688 if (pRemoteUSBBackend)
689 {
690 return pRemoteUSBBackend->GetBackendCallbackPointer ();
691 }
692
693#endif
694 return NULL;
695}
696
697void ConsoleVRDPServer::USBBackendReleasePointer (const Guid *pGuid)
698{
699#ifdef VBOX_WITH_USB
700 RemoteUSBBackend *pRemoteUSBBackend = NULL;
701
702 /* Find the instance. */
703 int rc = lockConsoleVRDPServer ();
704
705 if (VBOX_SUCCESS (rc))
706 {
707 pRemoteUSBBackend = usbBackendFindByUUID (pGuid);
708
709 if (pRemoteUSBBackend)
710 {
711 pRemoteUSBBackend->removeUUID (pGuid);
712 }
713
714 unlockConsoleVRDPServer ();
715
716 if (pRemoteUSBBackend)
717 {
718 pRemoteUSBBackend->Release ();
719 }
720 }
721#endif
722}
723
724RemoteUSBBackend *ConsoleVRDPServer::usbBackendGetNext (RemoteUSBBackend *pRemoteUSBBackend)
725{
726 LogFlow(("ConsoleVRDPServer::usbBackendGetNext: pBackend = %p\n", pRemoteUSBBackend));
727
728 RemoteUSBBackend *pNextRemoteUSBBackend = NULL;
729#ifdef VBOX_WITH_USB
730
731 int rc = lockConsoleVRDPServer ();
732
733 if (VBOX_SUCCESS (rc))
734 {
735 if (pRemoteUSBBackend == NULL)
736 {
737 /* The first backend in the list is requested. */
738 pNextRemoteUSBBackend = mUSBBackends.pHead;
739 }
740 else
741 {
742 /* Get pointer to the next backend. */
743 pNextRemoteUSBBackend = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
744 }
745
746 if (pNextRemoteUSBBackend)
747 {
748 pNextRemoteUSBBackend->AddRef ();
749 }
750
751 unlockConsoleVRDPServer ();
752
753 if (pRemoteUSBBackend)
754 {
755 pRemoteUSBBackend->Release ();
756 }
757 }
758#endif
759
760 return pNextRemoteUSBBackend;
761}
762
763#ifdef VBOX_WITH_USB
764/* Internal method. Called under the ConsoleVRDPServerLock. */
765RemoteUSBBackend *ConsoleVRDPServer::usbBackendFind (uint32_t u32ClientId)
766{
767 RemoteUSBBackend *pRemoteUSBBackend = mUSBBackends.pHead;
768
769 while (pRemoteUSBBackend)
770 {
771 if (pRemoteUSBBackend->ClientId () == u32ClientId)
772 {
773 break;
774 }
775
776 pRemoteUSBBackend = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
777 }
778
779 return pRemoteUSBBackend;
780}
781
782/* Internal method. Called under the ConsoleVRDPServerLock. */
783RemoteUSBBackend *ConsoleVRDPServer::usbBackendFindByUUID (const Guid *pGuid)
784{
785 RemoteUSBBackend *pRemoteUSBBackend = mUSBBackends.pHead;
786
787 while (pRemoteUSBBackend)
788 {
789 if (pRemoteUSBBackend->findUUID (pGuid))
790 {
791 break;
792 }
793
794 pRemoteUSBBackend = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
795 }
796
797 return pRemoteUSBBackend;
798}
799#endif
800
801/* Internal method. Called by the backend destructor. */
802void ConsoleVRDPServer::usbBackendRemoveFromList (RemoteUSBBackend *pRemoteUSBBackend)
803{
804#ifdef VBOX_WITH_USB
805 int rc = lockConsoleVRDPServer ();
806 AssertRC (rc);
807
808 /* Exclude the found instance from the list. */
809 if (pRemoteUSBBackend->pNext)
810 {
811 pRemoteUSBBackend->pNext->pPrev = pRemoteUSBBackend->pPrev;
812 }
813 else
814 {
815 mUSBBackends.pTail = (RemoteUSBBackend *)pRemoteUSBBackend->pPrev;
816 }
817
818 if (pRemoteUSBBackend->pPrev)
819 {
820 pRemoteUSBBackend->pPrev->pNext = pRemoteUSBBackend->pNext;
821 }
822 else
823 {
824 mUSBBackends.pHead = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
825 }
826
827 pRemoteUSBBackend->pNext = pRemoteUSBBackend->pPrev = NULL;
828
829 unlockConsoleVRDPServer ();
830#endif
831}
832
833
834void ConsoleVRDPServer::SendUpdate (unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate) const
835{
836#ifdef VBOX_VRDP
837 if (mpfnVRDPSendUpdate)
838 mpfnVRDPSendUpdate (mhServer, uScreenId, pvUpdate, cbUpdate);
839#endif
840}
841
842void ConsoleVRDPServer::SendResize (void) const
843{
844#ifdef VBOX_VRDP
845 if (mpfnVRDPSendResize)
846 mpfnVRDPSendResize (mhServer);
847#endif
848}
849
850void ConsoleVRDPServer::SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const
851{
852#ifdef VBOX_VRDP
853 if (mpfnVRDPSendUpdateBitmap)
854 mpfnVRDPSendUpdateBitmap (mhServer, uScreenId, x, y, w, h);
855#endif
856}
857
858void ConsoleVRDPServer::SetFramebuffer (IFramebuffer *framebuffer, uint32_t fFlags) const
859{
860#ifdef VBOX_VRDP
861 if (mpfnVRDPSetFramebuffer)
862 mpfnVRDPSetFramebuffer (mhServer, framebuffer, fFlags);
863#endif
864}
865
866void ConsoleVRDPServer::SendAudioSamples (void *pvSamples, uint32_t cSamples, VRDPAUDIOFORMAT format) const
867{
868#ifdef VBOX_VRDP
869 if (mpfnVRDPSendAudioSamples)
870 mpfnVRDPSendAudioSamples (mhServer, pvSamples, cSamples, format);
871#endif
872}
873
874void ConsoleVRDPServer::SendAudioVolume (uint16_t left, uint16_t right) const
875{
876#ifdef VBOX_VRDP
877 if (mpfnVRDPSendAudioVolume)
878 mpfnVRDPSendAudioVolume (mhServer, left, right);
879#endif
880}
881
882void ConsoleVRDPServer::SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const
883{
884#ifdef VBOX_VRDP
885 if (mpfnVRDPSendUSBRequest)
886 mpfnVRDPSendUSBRequest (mhServer, u32ClientId, pvParms, cbParms);
887#endif
888}
889
890void ConsoleVRDPServer::QueryInfo (uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const
891{
892#ifdef VBOX_VRDP
893 if (mpfnVRDPQueryInfo)
894 mpfnVRDPQueryInfo (mhServer, index, pvBuffer, cbBuffer, pcbOut);
895#endif
896}
897
898#ifdef VBOX_VRDP
899/* note: static function now! */
900bool ConsoleVRDPServer::loadVRDPLibrary (void)
901{
902 int rc = VINF_SUCCESS;
903
904 if (!mVRDPLibrary)
905 {
906 rc = RTLdrLoad("VBoxVRDP", &mVRDPLibrary);
907
908 if (VBOX_SUCCESS(rc))
909 {
910 LogFlow(("VRDPServer::loadLibrary(): successfully loaded VRDP library.\n"));
911
912 struct SymbolEntry
913 {
914 const char *name;
915 void **ppfn;
916 };
917
918 #define DEFSYMENTRY(a) { #a, (void**)&mpfn##a }
919
920 static const struct SymbolEntry symbols[] =
921 {
922 DEFSYMENTRY(VRDPStartServer),
923 DEFSYMENTRY(VRDPSetCallback),
924 DEFSYMENTRY(VRDPShutdownServer),
925 DEFSYMENTRY(VRDPSendUpdate),
926 DEFSYMENTRY(VRDPSendUpdateBitmap),
927 DEFSYMENTRY(VRDPSendResize),
928 DEFSYMENTRY(VRDPSendAudioSamples),
929 DEFSYMENTRY(VRDPSendAudioVolume),
930 DEFSYMENTRY(VRDPSendUSBRequest),
931 DEFSYMENTRY(VRDPQueryInfo),
932 DEFSYMENTRY(VRDPClipboard)
933 };
934
935 #undef DEFSYMENTRY
936
937 for (unsigned i = 0; i < ELEMENTS(symbols); i++)
938 {
939 rc = RTLdrGetSymbol(mVRDPLibrary, symbols[i].name, symbols[i].ppfn);
940
941 AssertMsgRC(rc, ("Error resolving VRDP symbol %s\n", symbols[i].name));
942
943 if (VBOX_FAILURE(rc))
944 {
945 break;
946 }
947 }
948 }
949 else
950 {
951 LogFlow(("VRDPServer::loadLibrary(): failed to load VRDP library! VRDP not available.\n"));
952 mVRDPLibrary = NULL;
953 }
954 }
955
956 // just to be safe
957 if (VBOX_FAILURE(rc))
958 {
959 if (mVRDPLibrary)
960 {
961 RTLdrClose (mVRDPLibrary);
962 mVRDPLibrary = NULL;
963 }
964 }
965
966 return (mVRDPLibrary != NULL);
967}
968#endif /* VBOX_VRDP */
969
970/*
971 * IRemoteDisplayInfo implementation.
972 */
973// constructor / destructor
974/////////////////////////////////////////////////////////////////////////////
975
976HRESULT RemoteDisplayInfo::FinalConstruct()
977{
978 return S_OK;
979}
980
981void RemoteDisplayInfo::FinalRelease()
982{
983 if (isReady())
984 uninit ();
985}
986
987// public methods only for internal purposes
988/////////////////////////////////////////////////////////////////////////////
989
990/**
991 * Initializes the guest object.
992 */
993HRESULT RemoteDisplayInfo::init (Console *aParent)
994{
995 LogFlowMember (("RemoteDisplayInfo::init (%p)\n", aParent));
996
997 ComAssertRet (aParent, E_INVALIDARG);
998
999 AutoLock alock (this);
1000 ComAssertRet (!isReady(), E_UNEXPECTED);
1001
1002 mParent = aParent;
1003
1004 setReady (true);
1005 return S_OK;
1006}
1007
1008/**
1009 * Uninitializes the instance and sets the ready flag to FALSE.
1010 * Called either from FinalRelease() or by the parent when it gets destroyed.
1011 */
1012void RemoteDisplayInfo::uninit()
1013{
1014 LogFlowMember (("RemoteDisplayInfo::uninit()\n"));
1015
1016 AutoLock alock (this);
1017 AssertReturn (isReady(), (void) 0);
1018
1019 mParent.setNull();
1020
1021 setReady (false);
1022}
1023
1024// IRemoteDisplayInfo properties
1025/////////////////////////////////////////////////////////////////////////////
1026
1027#define IMPL_GETTER_BOOL(_aType, _aName, _aIndex) \
1028 STDMETHODIMP RemoteDisplayInfo::COMGETTER(_aName) (_aType *a##_aName) \
1029 { \
1030 if (!a##_aName) \
1031 return E_POINTER; \
1032 \
1033 AutoLock alock (this); \
1034 CHECK_READY(); \
1035 \
1036 uint32_t value; \
1037 uint32_t cbOut = 0; \
1038 \
1039 mParent->consoleVRDPServer ()->QueryInfo \
1040 (_aIndex, &value, sizeof (value), &cbOut); \
1041 \
1042 *a##_aName = cbOut? !!value: FALSE; \
1043 \
1044 return S_OK; \
1045 }
1046
1047#define IMPL_GETTER_SCALAR(_aType, _aName, _aIndex) \
1048 STDMETHODIMP RemoteDisplayInfo::COMGETTER(_aName) (_aType *a##_aName) \
1049 { \
1050 if (!a##_aName) \
1051 return E_POINTER; \
1052 \
1053 AutoLock alock (this); \
1054 CHECK_READY(); \
1055 \
1056 _aType value; \
1057 uint32_t cbOut = 0; \
1058 \
1059 mParent->consoleVRDPServer ()->QueryInfo \
1060 (_aIndex, &value, sizeof (value), &cbOut); \
1061 \
1062 *a##_aName = cbOut? value: 0; \
1063 \
1064 return S_OK; \
1065 }
1066
1067#define IMPL_GETTER_BSTR(_aType, _aName, _aIndex) \
1068 STDMETHODIMP RemoteDisplayInfo::COMGETTER(_aName) (_aType *a##_aName) \
1069 { \
1070 if (!a##_aName) \
1071 return E_POINTER; \
1072 \
1073 AutoLock alock (this); \
1074 CHECK_READY(); \
1075 \
1076 uint32_t cbOut = 0; \
1077 \
1078 mParent->consoleVRDPServer ()->QueryInfo \
1079 (_aIndex, NULL, 0, &cbOut); \
1080 \
1081 if (cbOut == 0) \
1082 { \
1083 Bstr str(""); \
1084 str.cloneTo (a##_aName); \
1085 return S_OK; \
1086 } \
1087 \
1088 char *pchBuffer = (char *)RTMemTmpAlloc (cbOut); \
1089 \
1090 if (!pchBuffer) \
1091 { \
1092 Log(("RemoteDisplayInfo::" \
1093 #_aName \
1094 ": Failed to allocate memory %d bytes\n", cbOut)); \
1095 return E_OUTOFMEMORY; \
1096 } \
1097 \
1098 mParent->consoleVRDPServer ()->QueryInfo \
1099 (_aIndex, pchBuffer, cbOut, &cbOut); \
1100 \
1101 Bstr str(pchBuffer); \
1102 \
1103 str.cloneTo (a##_aName); \
1104 \
1105 RTMemTmpFree (pchBuffer); \
1106 \
1107 return S_OK; \
1108 }
1109
1110IMPL_GETTER_BOOL (BOOL, Active, VRDP_QI_ACTIVE);
1111IMPL_GETTER_SCALAR (ULONG, NumberOfClients, VRDP_QI_NUMBER_OF_CLIENTS);
1112IMPL_GETTER_SCALAR (LONG64, BeginTime, VRDP_QI_BEGIN_TIME);
1113IMPL_GETTER_SCALAR (LONG64, EndTime, VRDP_QI_END_TIME);
1114IMPL_GETTER_SCALAR (ULONG64, BytesSent, VRDP_QI_BYTES_SENT);
1115IMPL_GETTER_SCALAR (ULONG64, BytesSentTotal, VRDP_QI_BYTES_SENT_TOTAL);
1116IMPL_GETTER_SCALAR (ULONG64, BytesReceived, VRDP_QI_BYTES_RECEIVED);
1117IMPL_GETTER_SCALAR (ULONG64, BytesReceivedTotal, VRDP_QI_BYTES_RECEIVED_TOTAL);
1118IMPL_GETTER_BSTR (BSTR, User, VRDP_QI_USER);
1119IMPL_GETTER_BSTR (BSTR, Domain, VRDP_QI_DOMAIN);
1120IMPL_GETTER_BSTR (BSTR, ClientName, VRDP_QI_CLIENT_NAME);
1121IMPL_GETTER_BSTR (BSTR, ClientIP, VRDP_QI_CLIENT_IP);
1122IMPL_GETTER_SCALAR (ULONG, ClientVersion, VRDP_QI_CLIENT_VERSION);
1123IMPL_GETTER_SCALAR (ULONG, EncryptionStyle, VRDP_QI_ENCRYPTION_STYLE);
1124
1125#undef IMPL_GETTER_BSTR
1126#undef IMPL_GETTER_SCALAR
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette