VirtualBox

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

Last change on this file since 161 was 1, checked in by vboxsync, 55 years ago

import

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