VirtualBox

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

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

gcc-4.2 warnings

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