VirtualBox

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

Last change on this file since 498 was 330, checked in by vboxsync, 18 years ago

unbroke OSE

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