VirtualBox

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

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

Another attempt to solve the VRDP initialization problem

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