VirtualBox

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

Last change on this file since 2917 was 2527, checked in by vboxsync, 18 years ago

Check VRDP multiconnection property. A new external authentication prototype for multiconnection.

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