ConsoleVRDPServer.cpp revision 3918ed075bc7939d7397b643c46b460a4f3b67fc
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/* $Id$ */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/** @file
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VBox Console VRDP Helper class
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * available from http://www.virtualbox.org. This file is free software;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * General Public License (GPL) as published by the Free Software
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync *
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * additional information or have any questions.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync */
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync#include "ConsoleVRDPServer.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "ConsoleImpl.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "DisplayImpl.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "KeyboardImpl.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "MouseImpl.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "Logging.h"
032a52c5b2984e26e84c2961f8f7f98a3954c8f2vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/asm.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync#include <iprt/ldr.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/param.h>
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync#include <iprt/path.h>
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync#include <iprt/alloca.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/err.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#ifdef VBOX_WITH_VRDP
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/VRDPOrders.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#endif /* VBOX_WITH_VRDP */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncclass VRDPConsoleCallback : public IConsoleCallback
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncpublic:
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync VRDPConsoleCallback (ConsoleVRDPServer *server) :
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync m_server(server)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#ifndef VBOX_WITH_XPCOM
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync refcnt = 0;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#endif /* !VBOX_WITH_XPCOM */
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync virtual ~VRDPConsoleCallback() {}
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync NS_DECL_ISUPPORTS
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync#ifndef VBOX_WITH_XPCOM
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync STDMETHOD_(ULONG, AddRef)() {
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync return ::InterlockedIncrement (&refcnt);
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD_(ULONG, Release)()
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync long cnt = ::InterlockedDecrement (&refcnt);
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (cnt == 0)
044af0d1e6474076366759db86f101778c5f20ccvboxsync delete this;
044af0d1e6474076366759db86f101778c5f20ccvboxsync return cnt;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(QueryInterface) (REFIID riid , void **ppObj)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (riid == IID_IUnknown) {
044af0d1e6474076366759db86f101778c5f20ccvboxsync *ppObj = this;
044af0d1e6474076366759db86f101778c5f20ccvboxsync AddRef();
044af0d1e6474076366759db86f101778c5f20ccvboxsync return S_OK;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (riid == IID_IConsoleCallback) {
044af0d1e6474076366759db86f101778c5f20ccvboxsync *ppObj = this;
044af0d1e6474076366759db86f101778c5f20ccvboxsync AddRef();
044af0d1e6474076366759db86f101778c5f20ccvboxsync return S_OK;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync *ppObj = NULL;
044af0d1e6474076366759db86f101778c5f20ccvboxsync return E_NOINTERFACE;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync#endif /* !VBOX_WITH_XPCOM */
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(OnMousePointerShapeChange)(BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot,
044af0d1e6474076366759db86f101778c5f20ccvboxsync ULONG width, ULONG height, BYTE *shape);
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (m_server)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync m_server->NotifyAbsoluteMouse(!!supportsAbsolute);
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (m_server)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync m_server->NotifyKeyboardLedsChange (fNumLock, fCapsLock, fScrollLock);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnStateChange)(MachineState_T machineState)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnAdditionsStateChange)()
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync return S_OK;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnDVDDriveChange)()
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnFloppyDriveChange)()
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return S_OK;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return S_OK;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return S_OK;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
a1df400bbe9d64aad400442e56eb637019300a5evboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return S_OK;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnVRDPServerChange)()
a1df400bbe9d64aad400442e56eb637019300a5evboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return S_OK;
a1df400bbe9d64aad400442e56eb637019300a5evboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnUSBControllerChange)()
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync IVirtualBoxErrorInfo *aError)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnSharedFolderChange) (Scope_T aScope)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnRuntimeError)(BOOL fatal, INPTR BSTR id, INPTR BSTR message)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(OnCanShowWindow)(BOOL *canShow)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (!canShow)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return E_POINTER;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* we don't manage window activation here: always agree */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *canShow = TRUE;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return S_OK;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnShowWindow) (ULONG64 *winId)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync if (!winId)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return E_POINTER;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync /* we don't manage window activation here */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync *winId = 0;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return S_OK;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsyncprivate:
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync ConsoleVRDPServer *m_server;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#ifndef VBOX_WITH_XPCOM
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync long refcnt;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#endif /* !VBOX_WITH_XPCOM */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync};
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#ifdef VBOX_WITH_XPCOM
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#include <nsMemory.h>
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsyncNS_DECL_CLASSINFO(VRDPConsoleCallback)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsyncNS_IMPL_THREADSAFE_ISUPPORTS1_CI(VRDPConsoleCallback, IConsoleCallback)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#endif /* VBOX_WITH_XPCOM */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#ifdef DEBUG_sunlover
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#define LOGDUMPPTR Log
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncvoid dumpPointer (const uint8_t *pu8Shape, uint32_t width, uint32_t height, bool fXorMaskRGB32)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync unsigned i;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const uint8_t *pu8And = pu8Shape;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (i = 0; i < height; i++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned j;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("%p: ", pu8And));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (j = 0; j < (width + 7) / 8; j++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned k;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (k = 0; k < 8; k++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("%d", ((*pu8And) & (1 << (7 - k)))? 1: 0));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu8And++;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("\n"));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (fXorMaskRGB32)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t *pu32Xor = (uint32_t *)(pu8Shape + ((((width + 7) / 8) * height + 3) & ~3));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (i = 0; i < height; i++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned j;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("%p: ", pu32Xor));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (j = 0; j < width; j++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("%08X", *pu32Xor++));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("\n"));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* RDP 24 bit RGB mask. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t *pu8Xor = (uint8_t *)(pu8Shape + ((((width + 7) / 8) * height + 3) & ~3));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (i = 0; i < height; i++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync unsigned j;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("%p: ", pu8Xor));
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync for (j = 0; j < width; j++)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync LOGDUMPPTR(("%02X%02X%02X", pu8Xor[2], pu8Xor[1], pu8Xor[0]));
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pu8Xor += 3;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync LOGDUMPPTR(("\n"));
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync}
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#else
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#define dumpPointer(a, b, c, d) do {} while (0)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#endif /* DEBUG_sunlover */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncstatic void findTopLeftBorder (const uint8_t *pu8AndMask, const uint8_t *pu8XorMask, uint32_t width, uint32_t height, uint32_t *pxSkip, uint32_t *pySkip)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /*
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * Find the top border of the AND mask. First assign to special value.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync uint32_t ySkipAnd = ~0;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync const uint8_t *pu8And = pu8AndMask;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync const uint32_t cbAndRow = (width + 7) / 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const uint8_t maskLastByte = (uint8_t)( 0xFF << (cbAndRow * 8 - width) );
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync Assert(cbAndRow > 0);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned x;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < height && ySkipAnd == ~(uint32_t)0; y++, pu8And += cbAndRow)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* For each complete byte in the row. */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync for (x = 0; x < cbAndRow - 1; x++)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pu8And[x] != 0xFF)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ySkipAnd = y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync break;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (ySkipAnd == ~(uint32_t)0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Last byte. */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if ((pu8And[cbAndRow - 1] & maskLastByte) != maskLastByte)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ySkipAnd = y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (ySkipAnd == ~(uint32_t)0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ySkipAnd = 0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync /*
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * Find the left border of the AND mask.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t xSkipAnd = ~0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* For all bit columns. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < width && xSkipAnd == ~(uint32_t)0; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu8And = pu8AndMask + x/8; /* Currently checking byte. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t mask = 1 << (7 - x%8); /* Currently checking bit in the byte. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = ySkipAnd; y < height; y++, pu8And += cbAndRow)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if ((*pu8And & mask) == 0)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync xSkipAnd = x;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync break;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if (xSkipAnd == ~(uint32_t)0)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync xSkipAnd = 0;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync /*
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * Find the XOR mask top border.
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t ySkipXor = ~0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t *pu32XorStart = (uint32_t *)pu8XorMask;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t *pu32Xor = pu32XorStart;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < height && ySkipXor == ~(uint32_t)0; y++, pu32Xor += width)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < width; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pu32Xor[x] != 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ySkipXor = y;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync break;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (ySkipXor == ~(uint32_t)0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ySkipXor = 0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /*
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Find the left border of the XOR mask.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t xSkipXor = ~(uint32_t)0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* For all columns. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < width && xSkipXor == ~(uint32_t)0; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu32Xor = pu32XorStart + x; /* Currently checking dword. */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = ySkipXor; y < height; y++, pu32Xor += width)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (*pu32Xor != 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync xSkipXor = x;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync break;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (xSkipXor == ~(uint32_t)0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync xSkipXor = 0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync *pxSkip = RT_MIN (xSkipAnd, xSkipXor);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync *pySkip = RT_MIN (ySkipAnd, ySkipXor);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/* Generate an AND mask for alpha pointers here, because
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * guest driver does not do that correctly for Vista pointers.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Similar fix, changing the alpha threshold, could be applied
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * for the guest driver, but then additions reinstall would be
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * necessary, which we try to avoid.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncstatic void mousePointerGenerateANDMask (uint8_t *pu8DstAndMask, int cbDstAndMask, const uint8_t *pu8SrcAlpha, int w, int h)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync memset (pu8DstAndMask, 0xFF, cbDstAndMask);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < h; y++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t bitmask = 0x80;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int x;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < w; x++, bitmask >>= 1)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (bitmask == 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bitmask = 0x80;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Whether alpha channel value is not transparent enough for the pixel to be seen. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pu8SrcAlpha[x * 4 + 3] > 0x7f)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu8DstAndMask[x / 8] &= ~bitmask;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Point to next source and dest scans. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu8SrcAlpha += w * 4;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu8DstAndMask += (w + 7) / 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncSTDMETHODIMP VRDPConsoleCallback::OnMousePointerShapeChange (BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ULONG width, ULONG height, BYTE *shape)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogSunlover(("VRDPConsoleCallback::OnMousePointerShapeChange: %d, %d, %dx%d, @%d,%d\n", visible, alpha, width, height, xHot, yHot));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (m_server)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!shape)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!visible)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync m_server->MousePointerHide ();
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else if (width != 0 && height != 0)
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Pointer consists of 1 bpp AND and 24 BPP XOR masks.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * 'shape' AND mask followed by XOR mask.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * XOR mask contains 32 bit (lsb)BGR0(msb) values.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync *
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * We convert this to RDP color format which consist of
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * one bpp AND mask and 24 BPP (BGR) color XOR image.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync *
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * RDP clients expect 8 aligned width and height of
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * pointer (preferably 32x32).
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync *
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * They even contain bugs which do not appear for
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * 32x32 pointers but would appear for a 41x32 one.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync *
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * So set pointer size to 32x32. This can be done safely
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * because most pointers are 32x32.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync */
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync dumpPointer (shape, width, height, true);
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync int cbDstAndMask = (((width + 7) / 8) * height + 3) & ~3;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync uint8_t *pu8AndMask = shape;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync uint8_t *pu8XorMask = shape + cbDstAndMask;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync if (alpha)
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync {
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync pu8AndMask = (uint8_t *)alloca (cbDstAndMask);
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync mousePointerGenerateANDMask (pu8AndMask, cbDstAndMask, pu8XorMask, width, height);
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync }
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync /* Windows guest alpha pointers are wider than 32 pixels.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * Try to find out the top-left border of the pointer and
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * then copy only meaningful bits. All complete top rows
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * and all complete left columns where (AND == 1 && XOR == 0)
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * are skipped. Hot spot is adjusted.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync */
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync uint32_t ySkip = 0; /* How many rows to skip at the top. */
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync uint32_t xSkip = 0; /* How many columns to skip at the left. */
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync findTopLeftBorder (pu8AndMask, pu8XorMask, width, height, &xSkip, &ySkip);
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync /* Must not skip the hot spot. */
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync xSkip = RT_MIN (xSkip, xHot);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ySkip = RT_MIN (ySkip, yHot);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /*
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Compute size and allocate memory for the pointer.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const uint32_t dstwidth = 32;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync const uint32_t dstheight = 32;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync VRDPCOLORPOINTER *pointer = NULL;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t dstmaskwidth = (dstwidth + 7) / 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t rdpmaskwidth = dstmaskwidth;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync uint32_t rdpmasklen = dstheight * rdpmaskwidth;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync uint32_t rdpdatawidth = dstwidth * 3;
044af0d1e6474076366759db86f101778c5f20ccvboxsync uint32_t rdpdatalen = dstheight * rdpdatawidth;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync pointer = (VRDPCOLORPOINTER *)RTMemTmpAlloc (sizeof (VRDPCOLORPOINTER) + rdpmasklen + rdpdatalen);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pointer)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t *maskarray = (uint8_t *)pointer + sizeof (VRDPCOLORPOINTER);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t *dataarray = maskarray + rdpmasklen;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync memset (maskarray, 0xFF, rdpmasklen);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync memset (dataarray, 0x00, rdpdatalen);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t srcmaskwidth = (width + 7) / 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t srcdatawidth = width * 4;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync /* Copy AND mask. */
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync uint8_t *src = pu8AndMask + ySkip * srcmaskwidth;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t *dst = maskarray + (dstheight - 1) * rdpmaskwidth;
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t minheight = RT_MIN (height - ySkip, dstheight);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t minwidth = RT_MIN (width - xSkip, dstwidth);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned x, y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < minheight; y++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < minwidth; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t byteIndex = (x + xSkip) / 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t bitIndex = (x + xSkip) % 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync bool bit = (src[byteIndex] & (1 << (7 - bitIndex))) != 0;
a1df400bbe9d64aad400442e56eb637019300a5evboxsync
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync if (!bit)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync byteIndex = x / 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bitIndex = x % 8;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dst[byteIndex] &= ~(1 << (7 - bitIndex));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync src += srcmaskwidth;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dst -= rdpmaskwidth;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync }
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync /* Point src to XOR mask */
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync src = pu8XorMask + ySkip * srcdatawidth;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync dst = dataarray + (dstheight - 1) * rdpdatawidth;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < minheight ; y++)
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < minwidth; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync memcpy (dst + x * 3, &src[4 * (x + xSkip)], 3);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync src += srcdatawidth;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dst -= rdpdatawidth;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync pointer->u16HotX = (uint16_t)(xHot - xSkip);
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync pointer->u16HotY = (uint16_t)(yHot - ySkip);
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pointer->u16Width = (uint16_t)dstwidth;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync pointer->u16Height = (uint16_t)dstheight;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pointer->u16MaskLen = (uint16_t)rdpmasklen;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pointer->u16DataLen = (uint16_t)rdpdatalen;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dumpPointer ((uint8_t *)pointer + sizeof (*pointer), dstwidth, dstheight, false);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync m_server->MousePointerUpdate (pointer);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync RTMemTmpFree (pointer);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return S_OK;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync// ConsoleVRDPServer
044af0d1e6474076366759db86f101778c5f20ccvboxsync////////////////////////////////////////////////////////////////////////////////
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync#ifdef VBOX_WITH_VRDP
044af0d1e6474076366759db86f101778c5f20ccvboxsyncRTLDRMOD ConsoleVRDPServer::mVRDPLibrary;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncPFNVRDPCREATESERVER ConsoleVRDPServer::mpfnVRDPCreateServer = NULL;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncVRDPENTRYPOINTS_1 *ConsoleVRDPServer::mpEntryPoints = NULL;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncVRDPCALLBACKS_1 ConsoleVRDPServer::mCallbacks =
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync { VRDP_INTERFACE_VERSION_1, sizeof (VRDPCALLBACKS_1) },
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer::VRDPCallbackQueryProperty,
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer::VRDPCallbackClientLogon,
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer::VRDPCallbackClientConnect,
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer::VRDPCallbackClientDisconnect,
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer::VRDPCallbackIntercept,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackUSB,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackClipboard,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackFramebufferQuery,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackFramebufferLock,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackFramebufferUnlock,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackInput,
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer::VRDPCallbackVideoModeHint
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync};
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackQueryProperty (void *pvCallback, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut)
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync{
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync int rc = VERR_NOT_SUPPORTED;
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync switch (index)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync case VRDP_QP_NETWORK_PORT:
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ULONG port = 0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync server->mConsole->getVRDPServer ()->COMGETTER(Port) (&port);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (port == 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync port = VRDP_DEFAULT_PORT;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (cbBuffer >= sizeof (uint32_t))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync *(uint32_t *)pvBuffer = (uint32_t)port;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = VINF_SUCCESS;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = VINF_BUFFER_OVERFLOW;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *pcbOut = sizeof (uint32_t);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync } break;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync case VRDP_QP_NETWORK_ADDRESS:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync com::Bstr bstr;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->getVRDPServer ()->COMGETTER(NetAddress) (bstr.asOutParam());
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* The server expects UTF8. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync com::Utf8Str address = bstr;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync size_t cbAddress = address.length () + 1;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (cbAddress >= 0x10000)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* More than 64K seems to be an invalid address. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VERR_TOO_MUCH_DATA;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if ((size_t)cbBuffer >= cbAddress)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (cbAddress > 0)
611e5e148a74d4b54cf76c97e4d36acaa816d8c0vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if (address.raw())
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync memcpy (pvBuffer, address.raw(), cbAddress);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync else
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* The value is an empty string. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *(uint8_t *)pvBuffer = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VINF_BUFFER_OVERFLOW;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *pcbOut = (uint32_t)cbAddress;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync } break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync case VRDP_QP_NUMBER_MONITORS:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ULONG cMonitors = 1;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->machine ()->COMGETTER(MonitorCount)(&cMonitors);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (cbBuffer >= sizeof (uint32_t))
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *(uint32_t *)pvBuffer = (uint32_t)cMonitors;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync else
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VINF_BUFFER_OVERFLOW;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *pcbOut = sizeof (uint32_t);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync } break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync default:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return rc;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackClientLogon (void *pvCallback, uint32_t u32ClientId, const char *pszUser, const char *pszPassword, const char *pszDomain)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return server->mConsole->VRDPClientLogon (u32ClientId, pszUser, pszPassword, pszDomain);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackClientConnect (void *pvCallback, uint32_t u32ClientId)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync server->mConsole->VRDPClientConnect (u32ClientId);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackClientDisconnect (void *pvCallback, uint32_t u32ClientId, uint32_t fu32Intercepted)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync server->mConsole->VRDPClientDisconnect (u32ClientId, fu32Intercepted);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync}
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackIntercept (void *pvCallback, uint32_t u32ClientId, uint32_t fu32Intercept, void **ppvIntercept)
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync{
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync LogFlowFunc(("%x\n", fu32Intercept));
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync int rc = VERR_NOT_SUPPORTED;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync switch (fu32Intercept)
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync {
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync case VRDP_CLIENT_INTERCEPT_AUDIO:
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync {
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync server->mConsole->VRDPInterceptAudio (u32ClientId);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync if (ppvIntercept)
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync {
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync *ppvIntercept = server;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync }
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync rc = VINF_SUCCESS;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync } break;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync case VRDP_CLIENT_INTERCEPT_USB:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->VRDPInterceptUSB (u32ClientId, ppvIntercept);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync } break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync case VRDP_CLIENT_INTERCEPT_CLIPBOARD:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->VRDPInterceptClipboard (u32ClientId);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (ppvIntercept)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *ppvIntercept = server;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync } break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync default:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return rc;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackUSB (void *pvCallback, void *pvIntercept, uint32_t u32ClientId, uint8_t u8Code, const void *pvRet, uint32_t cbRet)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#ifdef VBOX_WITH_USB
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return USBClientResponseCallback (pvIntercept, u32ClientId, u8Code, pvRet, cbRet);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#else
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return VERR_NOT_SUPPORTED;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#endif
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackClipboard (void *pvCallback, void *pvIntercept, uint32_t u32ClientId, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return ClipboardCallback (pvIntercept, u32ClientId, u32Function, u32Format, pvData, cbData);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(bool) ConsoleVRDPServer::VRDPCallbackFramebufferQuery (void *pvCallback, unsigned uScreenId, VRDPFRAMEBUFFERINFO *pInfo)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync bool fAvailable = false;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync IFramebuffer *pfb = NULL;
044af0d1e6474076366759db86f101778c5f20ccvboxsync LONG xOrigin = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync LONG yOrigin = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->getDisplay ()->GetFramebuffer (uScreenId, &pfb, &xOrigin, &yOrigin);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (pfb)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->Lock ();
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* Query framebuffer parameters. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ULONG lineSize = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->COMGETTER(BytesPerLine) (&lineSize);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ULONG bitsPerPixel = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->COMGETTER(BitsPerPixel) (&bitsPerPixel);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync BYTE *address = NULL;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->COMGETTER(Address) (&address);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync ULONG height = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->COMGETTER(Height) (&height);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ULONG width = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->COMGETTER(Width) (&width);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* Now fill the information as requested by the caller. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pInfo->pu8Bits = address;
a1df400bbe9d64aad400442e56eb637019300a5evboxsync pInfo->xOrigin = xOrigin;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pInfo->yOrigin = yOrigin;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pInfo->cWidth = width;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pInfo->cHeight = height;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pInfo->cBitsPerPixel = bitsPerPixel;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pInfo->cbLine = lineSize;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfb->Unlock ();
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync fAvailable = true;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (server->maFramebuffers[uScreenId])
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->maFramebuffers[uScreenId]->Release ();
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
a1df400bbe9d64aad400442e56eb637019300a5evboxsync server->maFramebuffers[uScreenId] = pfb;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return fAvailable;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackFramebufferLock (void *pvCallback, unsigned uScreenId)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (server->maFramebuffers[uScreenId])
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->maFramebuffers[uScreenId]->Lock ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
ad27e1d5e48ca41245120c331cc88b50464813cevboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackFramebufferUnlock (void *pvCallback, unsigned uScreenId)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (server->maFramebuffers[uScreenId])
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->maFramebuffers[uScreenId]->Unlock ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncstatic void fixKbdLockStatus (VRDPInputSynch *pInputSynch, IKeyboard *pKeyboard)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if ( pInputSynch->cGuestNumLockAdaptions
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync && (pInputSynch->fGuestNumLock != pInputSynch->fClientNumLock))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pInputSynch->cGuestNumLockAdaptions--;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pKeyboard->PutScancode(0x45);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pKeyboard->PutScancode(0x45 | 0x80);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if ( pInputSynch->cGuestCapsLockAdaptions
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync && (pInputSynch->fGuestCapsLock != pInputSynch->fClientCapsLock))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pInputSynch->cGuestCapsLockAdaptions--;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pKeyboard->PutScancode(0x3a);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pKeyboard->PutScancode(0x3a | 0x80);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackInput (void *pvCallback, int type, const void *pvInput, unsigned cbInput)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync Console *pConsole = server->mConsole;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync switch (type)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync case VRDP_INPUT_SCANCODE:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cbInput == sizeof (VRDPINPUTSCANCODE))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync IKeyboard *pKeyboard = pConsole->getKeyboard ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync const VRDPINPUTSCANCODE *pInputScancode = (VRDPINPUTSCANCODE *)pvInput;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* Track lock keys. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputScancode->uScancode == 0x45)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientNumLock = !server->m_InputSynch.fClientNumLock;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else if (pInputScancode->uScancode == 0x3a)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientCapsLock = !server->m_InputSynch.fClientCapsLock;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else if (pInputScancode->uScancode == 0x46)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
a1df400bbe9d64aad400442e56eb637019300a5evboxsync server->m_InputSynch.fClientScrollLock = !server->m_InputSynch.fClientScrollLock;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else if ((pInputScancode->uScancode & 0x80) == 0)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* Key pressed. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync fixKbdLockStatus (&server->m_InputSynch, pKeyboard);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pKeyboard->PutScancode((LONG)pInputScancode->uScancode);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync case VRDP_INPUT_POINT:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cbInput == sizeof (VRDPINPUTPOINT))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync const VRDPINPUTPOINT *pInputPoint = (VRDPINPUTPOINT *)pvInput;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync int mouseButtons = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int iWheel = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_BUTTON1)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync mouseButtons |= MouseButtonState_LeftButton;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_BUTTON2)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mouseButtons |= MouseButtonState_RightButton;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_BUTTON3)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mouseButtons |= MouseButtonState_MiddleButton;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_WHEEL_UP)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mouseButtons |= MouseButtonState_WheelUp;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync iWheel = -1;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_WHEEL_DOWN)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mouseButtons |= MouseButtonState_WheelDown;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync iWheel = 1;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (server->m_fGuestWantsAbsolute)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pConsole->getMouse()->PutMouseEventAbsolute (pInputPoint->x + 1, pInputPoint->y + 1, iWheel, mouseButtons);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } else
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pConsole->getMouse()->PutMouseEvent (pInputPoint->x - server->m_mousex,
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync pInputPoint->y - server->m_mousey,
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync iWheel, mouseButtons);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_mousex = pInputPoint->x;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_mousey = pInputPoint->y;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync case VRDP_INPUT_CAD:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pConsole->getKeyboard ()->PutCAD();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync case VRDP_INPUT_RESET:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pConsole->Reset();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync case VRDP_INPUT_SYNCH:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cbInput == sizeof (VRDPINPUTSYNCH))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync IKeyboard *pKeyboard = pConsole->getKeyboard ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync const VRDPINPUTSYNCH *pInputSynch = (VRDPINPUTSYNCH *)pvInput;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientNumLock = (pInputSynch->uLockStatus & VRDP_INPUT_SYNCH_NUMLOCK) != 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientCapsLock = (pInputSynch->uLockStatus & VRDP_INPUT_SYNCH_CAPITAL) != 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientScrollLock = (pInputSynch->uLockStatus & VRDP_INPUT_SYNCH_SCROLL) != 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* The client initiated synchronization. Always make the guest to reflect the client state.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Than means, when the guest changes the state itself, it is forced to return to the client
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * state.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (server->m_InputSynch.fClientNumLock != server->m_InputSynch.fGuestNumLock)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.cGuestNumLockAdaptions = 2;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync if (server->m_InputSynch.fClientCapsLock != server->m_InputSynch.fGuestCapsLock)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.cGuestCapsLockAdaptions = 2;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync fixKbdLockStatus (&server->m_InputSynch, pKeyboard);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync default:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackVideoModeHint (void *pvCallback, unsigned cWidth, unsigned cHeight, unsigned cBitsPerPixel, unsigned uScreenId)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync server->mConsole->getDisplay ()->SetVideoModeHint(cWidth, cHeight, cBitsPerPixel, uScreenId);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncConsoleVRDPServer::ConsoleVRDPServer (Console *console)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mConsole = console;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc = RTCritSectInit (&mCritSect);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertRC (rc);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mcClipboardRefs = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mpfnClipboardCallback = NULL;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_USB
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mUSBBackends.pHead = NULL;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mUSBBackends.pTail = NULL;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mUSBBackends.thread = NIL_RTTHREAD;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mUSBBackends.fThreadRunning = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mUSBBackends.event = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_VRDP
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mhServer = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_fGuestWantsAbsolute = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_mousex = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_mousey = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.cGuestNumLockAdaptions = 2;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.cGuestCapsLockAdaptions = 2;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.fGuestNumLock = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.fGuestCapsLock = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.fGuestScrollLock = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.fClientNumLock = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.fClientCapsLock = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync m_InputSynch.fClientScrollLock = false;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync memset (maFramebuffers, 0, sizeof (maFramebuffers));
a1df400bbe9d64aad400442e56eb637019300a5evboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mConsoleCallback = new VRDPConsoleCallback(this);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mConsoleCallback->AddRef();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync console->RegisterCallback(mConsoleCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mAuthLibrary = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncConsoleVRDPServer::~ConsoleVRDPServer ()
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync Stop ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_VRDP
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (mConsoleCallback)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mConsole->UnregisterCallback(mConsoleCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mConsoleCallback->Release();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mConsoleCallback = NULL;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync unsigned i;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync for (i = 0; i < RT_ELEMENTS(maFramebuffers); i++)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (maFramebuffers[i])
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync maFramebuffers[i]->Release ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync maFramebuffers[i] = NULL;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RTCritSectIsInitialized (&mCritSect))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync RTCritSectDelete (&mCritSect);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync memset (&mCritSect, 0, sizeof (mCritSect));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncint ConsoleVRDPServer::Launch (void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync LogFlowMember(("ConsoleVRDPServer::Launch\n"));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_VRDP
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc = VINF_SUCCESS;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync IVRDPServer *vrdpserver = mConsole->getVRDPServer ();
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync Assert(vrdpserver);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync BOOL vrdpEnabled = FALSE;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync HRESULT rc2 = vrdpserver->COMGETTER(Enabled) (&vrdpEnabled);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertComRC(rc2);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (SUCCEEDED (rc2) && vrdpEnabled)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (loadVRDPLibrary ())
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = mpfnVRDPCreateServer (&mCallbacks.header, this, (VRDPINTERFACEHDR **)&mpEntryPoints, &mhServer);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_SUCCESS(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_USB
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync remoteUSBThreadStart ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_USB */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertMsgFailed(("Could not start VRDP server: rc = %Rrc\n", rc));
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertMsgFailed(("Could not load the VRDP library\n"));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = VERR_FILE_NOT_FOUND;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync#else
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc = VERR_NOT_SUPPORTED;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync LogRel(("VRDP: this version does not include the VRDP server.\n"));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncvoid ConsoleVRDPServer::EnableConnections (void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_VRDP
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (mpEntryPoints && mhServer)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mpEntryPoints->VRDPEnableConnections (mhServer, true);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncvoid ConsoleVRDPServer::DisconnectClient (uint32_t u32ClientId, bool fReconnect)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_WITH_VRDP
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (mpEntryPoints && mhServer)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mpEntryPoints->VRDPDisconnect (mhServer, u32ClientId, fReconnect);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncvoid ConsoleVRDPServer::MousePointerUpdate (const VRDPCOLORPOINTER *pPointer)
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync{
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync#ifdef VBOX_WITH_VRDP
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync if (mpEntryPoints && mhServer)
26645f447bb6a819f33492c84e03e364092ec600vboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mpEntryPoints->VRDPColorPointer (mhServer, pPointer);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync }
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_VRDP */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncvoid ConsoleVRDPServer::MousePointerHide (void)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
26645f447bb6a819f33492c84e03e364092ec600vboxsync#ifdef VBOX_WITH_VRDP
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (mpEntryPoints && mhServer)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mpEntryPoints->VRDPHidePointer (mhServer);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync }
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_VRDP */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncvoid ConsoleVRDPServer::Stop (void)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync Assert(VALID_PTR(this)); /** @todo r=bird: there are(/was) some odd cases where this buster was invalid on
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * linux. Just remove this when it's 100% sure that problem has been fixed. */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#ifdef VBOX_WITH_VRDP
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (mhServer)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync HVRDPSERVER hServer = mhServer;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* Reset the handle to avoid further calls to the server. */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mhServer = 0;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (mpEntryPoints && hServer)
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mpEntryPoints->VRDPDestroy (hServer);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync }
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync }
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_VRDP */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#ifdef VBOX_WITH_USB
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync remoteUSBThreadStop ();
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_USB */
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mpfnAuthEntry = NULL;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mpfnAuthEntry2 = NULL;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (mAuthLibrary)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync RTLdrClose(mAuthLibrary);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mAuthLibrary = 0;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync }
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync/* Worker thread for Remote USB. The thread polls the clients for
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * the list of attached USB devices.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * The thread is also responsible for attaching/detaching devices
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * to/from the VM.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync *
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * It is expected that attaching/detaching is not a frequent operation.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync *
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * The thread is always running when the VRDP server is active.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync *
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * The thread scans backends and requests the device list every 2 seconds.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync *
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * When device list is available, the thread calls the Console to process it.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync *
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#define VRDP_DEVICE_LIST_PERIOD_MS (2000)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#ifdef VBOX_WITH_USB
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncstatic DECLCALLBACK(int) threadRemoteUSB (RTTHREAD self, void *pvUser)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync ConsoleVRDPServer *pOwner = (ConsoleVRDPServer *)pvUser;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync LogFlow(("Console::threadRemoteUSB: start. owner = %p.\n", pOwner));
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pOwner->notifyRemoteUSBThreadRunning (self);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync while (pOwner->isRemoteUSBThreadRunning ())
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync RemoteUSBBackend *pRemoteUSBBackend = NULL;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync while ((pRemoteUSBBackend = pOwner->usbBackendGetNext (pRemoteUSBBackend)) != NULL)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync {
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pRemoteUSBBackend->PollRemoteDevices ();
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync }
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pOwner->waitRemoteUSBThreadEvent (VRDP_DEVICE_LIST_PERIOD_MS);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync LogFlow(("Console::threadRemoteUSB: iteration. owner = %p.\n", pOwner));
26645f447bb6a819f33492c84e03e364092ec600vboxsync }
26645f447bb6a819f33492c84e03e364092ec600vboxsync
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync return VINF_SUCCESS;
26645f447bb6a819f33492c84e03e364092ec600vboxsync}
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncvoid ConsoleVRDPServer::notifyRemoteUSBThreadRunning (RTTHREAD thread)
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync mUSBBackends.thread = thread;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync mUSBBackends.fThreadRunning = true;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync int rc = RTThreadUserSignal (thread);
AssertRC (rc);
}
bool ConsoleVRDPServer::isRemoteUSBThreadRunning (void)
{
return mUSBBackends.fThreadRunning;
}
void ConsoleVRDPServer::waitRemoteUSBThreadEvent (unsigned cMillies)
{
int rc = RTSemEventWait (mUSBBackends.event, cMillies);
Assert (RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
NOREF(rc);
}
void ConsoleVRDPServer::remoteUSBThreadStart (void)
{
int rc = RTSemEventCreate (&mUSBBackends.event);
if (RT_FAILURE (rc))
{
AssertFailed ();
mUSBBackends.event = 0;
}
if (RT_SUCCESS (rc))
{
rc = RTThreadCreate (&mUSBBackends.thread, threadRemoteUSB, this, 65536,
RTTHREADTYPE_VRDP_IO, RTTHREADFLAGS_WAITABLE, "remote usb");
}
if (RT_FAILURE (rc))
{
LogRel(("Warning: could not start the remote USB thread, rc = %Rrc!!!\n", rc));
mUSBBackends.thread = NIL_RTTHREAD;
}
else
{
/* Wait until the thread is ready. */
rc = RTThreadUserWait (mUSBBackends.thread, 60000);
AssertRC (rc);
Assert (mUSBBackends.fThreadRunning || RT_FAILURE (rc));
}
}
void ConsoleVRDPServer::remoteUSBThreadStop (void)
{
mUSBBackends.fThreadRunning = false;
if (mUSBBackends.thread != NIL_RTTHREAD)
{
Assert (mUSBBackends.event != 0);
RTSemEventSignal (mUSBBackends.event);
int rc = RTThreadWait (mUSBBackends.thread, 60000, NULL);
AssertRC (rc);
mUSBBackends.thread = NIL_RTTHREAD;
}
if (mUSBBackends.event)
{
RTSemEventDestroy (mUSBBackends.event);
mUSBBackends.event = 0;
}
}
#endif /* VBOX_WITH_USB */
VRDPAuthResult ConsoleVRDPServer::Authenticate (const Guid &uuid, VRDPAuthGuestJudgement guestJudgement,
const char *pszUser, const char *pszPassword, const char *pszDomain,
uint32_t u32ClientId)
{
VRDPAUTHUUID rawuuid;
memcpy (rawuuid, ((Guid &)uuid).ptr (), sizeof (rawuuid));
LogFlow(("ConsoleVRDPServer::Authenticate: uuid = %Ruuid, guestJudgement = %d, pszUser = %s, pszPassword = %s, pszDomain = %s, u32ClientId = %d\n",
rawuuid, guestJudgement, pszUser, pszPassword, pszDomain, u32ClientId));
/*
* Called only from VRDP input thread. So thread safety is not required.
*/
if (!mAuthLibrary)
{
/* Load the external authentication library. */
ComPtr<IMachine> machine;
mConsole->COMGETTER(Machine)(machine.asOutParam());
ComPtr<IVirtualBox> virtualBox;
machine->COMGETTER(Parent)(virtualBox.asOutParam());
ComPtr<ISystemProperties> systemProperties;
virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
Bstr authLibrary;
systemProperties->COMGETTER(RemoteDisplayAuthLibrary)(authLibrary.asOutParam());
Utf8Str filename = authLibrary;
LogRel(("VRDPAUTH: ConsoleVRDPServer::Authenticate: loading external authentication library '%ls'\n", authLibrary.raw()));
int rc = RTLdrLoad (filename.raw(), &mAuthLibrary);
if (RT_FAILURE (rc))
LogRel(("VRDPAUTH: Failed to load external authentication library. Error code: %Rrc\n", rc));
if (RT_SUCCESS (rc))
{
/* Get the entry point. */
mpfnAuthEntry2 = NULL;
int rc2 = RTLdrGetSymbol(mAuthLibrary, "VRDPAuth2", (void**)&mpfnAuthEntry2);
if (RT_FAILURE (rc2))
{
LogRel(("VRDPAUTH: Could not resolve import '%s'. Error code: %Rrc\n", "VRDPAuth2", rc2));
rc = rc2;
}
/* Get the entry point. */
mpfnAuthEntry = NULL;
rc2 = RTLdrGetSymbol(mAuthLibrary, "VRDPAuth", (void**)&mpfnAuthEntry);
if (RT_FAILURE (rc2))
{
LogRel(("VRDPAUTH: Could not resolve import '%s'. Error code: %Rrc\n", "VRDPAuth", rc2));
rc = rc2;
}
if (mpfnAuthEntry2 || mpfnAuthEntry)
{
LogRel(("VRDPAUTH: Using entry point '%s'.\n", mpfnAuthEntry2? "VRDPAuth2": "VRDPAuth"));
rc = VINF_SUCCESS;
}
}
if (RT_FAILURE (rc))
{
mConsole->reportAuthLibraryError (filename.raw(), rc);
mpfnAuthEntry = NULL;
mpfnAuthEntry2 = NULL;
if (mAuthLibrary)
{
RTLdrClose(mAuthLibrary);
mAuthLibrary = 0;
}
return VRDPAuthAccessDenied;
}
}
Assert (mAuthLibrary && (mpfnAuthEntry || mpfnAuthEntry2));
VRDPAuthResult result = mpfnAuthEntry2?
mpfnAuthEntry2 (&rawuuid, guestJudgement, pszUser, pszPassword, pszDomain, true, u32ClientId):
mpfnAuthEntry (&rawuuid, guestJudgement, pszUser, pszPassword, pszDomain);
switch (result)
{
case VRDPAuthAccessDenied:
LogRel(("VRDPAUTH: external authentication module returned 'access denied'\n"));
break;
case VRDPAuthAccessGranted:
LogRel(("VRDPAUTH: external authentication module returned 'access granted'\n"));
break;
case VRDPAuthDelegateToGuest:
LogRel(("VRDPAUTH: external authentication module returned 'delegate request to guest'\n"));
break;
default:
LogRel(("VRDPAUTH: external authentication module returned incorrect return code %d\n", result));
result = VRDPAuthAccessDenied;
}
LogFlow(("ConsoleVRDPServer::Authenticate: result = %d\n", result));
return result;
}
void ConsoleVRDPServer::AuthDisconnect (const Guid &uuid, uint32_t u32ClientId)
{
VRDPAUTHUUID rawuuid;
memcpy (rawuuid, ((Guid &)uuid).ptr (), sizeof (rawuuid));
LogFlow(("ConsoleVRDPServer::AuthDisconnect: uuid = %Ruuid, u32ClientId = %d\n",
rawuuid, u32ClientId));
Assert (mAuthLibrary && (mpfnAuthEntry || mpfnAuthEntry2));
if (mpfnAuthEntry2)
mpfnAuthEntry2 (&rawuuid, VRDPAuthGuestNotAsked, NULL, NULL, NULL, false, u32ClientId);
}
int ConsoleVRDPServer::lockConsoleVRDPServer (void)
{
int rc = RTCritSectEnter (&mCritSect);
AssertRC (rc);
return rc;
}
void ConsoleVRDPServer::unlockConsoleVRDPServer (void)
{
RTCritSectLeave (&mCritSect);
}
DECLCALLBACK(int) ConsoleVRDPServer::ClipboardCallback (void *pvCallback,
uint32_t u32ClientId,
uint32_t u32Function,
uint32_t u32Format,
const void *pvData,
uint32_t cbData)
{
LogFlowFunc(("pvCallback = %p, u32ClientId = %d, u32Function = %d, u32Format = 0x%08X, pvData = %p, cbData = %d\n",
pvCallback, u32ClientId, u32Function, u32Format, pvData, cbData));
int rc = VINF_SUCCESS;
ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvCallback);
NOREF(u32ClientId);
switch (u32Function)
{
case VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE:
{
if (pServer->mpfnClipboardCallback)
{
pServer->mpfnClipboardCallback (VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE,
u32Format,
(void *)pvData,
cbData);
}
} break;
case VRDP_CLIPBOARD_FUNCTION_DATA_READ:
{
if (pServer->mpfnClipboardCallback)
{
pServer->mpfnClipboardCallback (VBOX_CLIPBOARD_EXT_FN_DATA_READ,
u32Format,
(void *)pvData,
cbData);
}
} break;
default:
rc = VERR_NOT_SUPPORTED;
}
return rc;
}
DECLCALLBACK(int) ConsoleVRDPServer::ClipboardServiceExtension (void *pvExtension,
uint32_t u32Function,
void *pvParms,
uint32_t cbParms)
{
LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
pvExtension, u32Function, pvParms, cbParms));
int rc = VINF_SUCCESS;
#ifdef VBOX_WITH_VRDP
ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvExtension);
VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
switch (u32Function)
{
case VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK:
{
pServer->mpfnClipboardCallback = (PFNVRDPCLIPBOARDEXTCALLBACK)pParms->pvData;
} break;
case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
{
/* The guest announces clipboard formats. This must be delivered to all clients. */
if (mpEntryPoints && pServer->mhServer)
{
mpEntryPoints->VRDPClipboard (pServer->mhServer,
VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE,
pParms->u32Format,
NULL,
0,
NULL);
}
} break;
case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
{
/* The clipboard service expects that the pvData buffer will be filled
* with clipboard data. The server returns the data from the client that
* announced the requested format most recently.
*/
if (mpEntryPoints && pServer->mhServer)
{
mpEntryPoints->VRDPClipboard (pServer->mhServer,
VRDP_CLIPBOARD_FUNCTION_DATA_READ,
pParms->u32Format,
pParms->pvData,
pParms->cbData,
&pParms->cbData);
}
} break;
case VBOX_CLIPBOARD_EXT_FN_DATA_WRITE:
{
if (mpEntryPoints && pServer->mhServer)
{
mpEntryPoints->VRDPClipboard (pServer->mhServer,
VRDP_CLIPBOARD_FUNCTION_DATA_WRITE,
pParms->u32Format,
pParms->pvData,
pParms->cbData,
NULL);
}
} break;
default:
rc = VERR_NOT_SUPPORTED;
}
#endif /* VBOX_WITH_VRDP */
return rc;
}
void ConsoleVRDPServer::ClipboardCreate (uint32_t u32ClientId)
{
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
if (mcClipboardRefs == 0)
{
rc = HGCMHostRegisterServiceExtension (&mhClipboard, "VBoxSharedClipboard", ClipboardServiceExtension, this);
if (RT_SUCCESS (rc))
{
mcClipboardRefs++;
}
}
unlockConsoleVRDPServer ();
}
}
void ConsoleVRDPServer::ClipboardDelete (uint32_t u32ClientId)
{
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
mcClipboardRefs--;
if (mcClipboardRefs == 0)
{
HGCMHostUnregisterServiceExtension (mhClipboard);
}
unlockConsoleVRDPServer ();
}
}
/* That is called on INPUT thread of the VRDP server.
* The ConsoleVRDPServer keeps a list of created backend instances.
*/
void ConsoleVRDPServer::USBBackendCreate (uint32_t u32ClientId, void **ppvIntercept)
{
#ifdef VBOX_WITH_USB
LogFlow(("ConsoleVRDPServer::USBBackendCreate: u32ClientId = %d\n", u32ClientId));
/* Create a new instance of the USB backend for the new client. */
RemoteUSBBackend *pRemoteUSBBackend = new RemoteUSBBackend (mConsole, this, u32ClientId);
if (pRemoteUSBBackend)
{
pRemoteUSBBackend->AddRef (); /* 'Release' called in USBBackendDelete. */
/* Append the new instance in the list. */
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
pRemoteUSBBackend->pNext = mUSBBackends.pHead;
if (mUSBBackends.pHead)
{
mUSBBackends.pHead->pPrev = pRemoteUSBBackend;
}
else
{
mUSBBackends.pTail = pRemoteUSBBackend;
}
mUSBBackends.pHead = pRemoteUSBBackend;
unlockConsoleVRDPServer ();
if (ppvIntercept)
{
*ppvIntercept = pRemoteUSBBackend;
}
}
if (RT_FAILURE (rc))
{
pRemoteUSBBackend->Release ();
}
}
#endif /* VBOX_WITH_USB */
}
void ConsoleVRDPServer::USBBackendDelete (uint32_t u32ClientId)
{
#ifdef VBOX_WITH_USB
LogFlow(("ConsoleVRDPServer::USBBackendDelete: u32ClientId = %d\n", u32ClientId));
RemoteUSBBackend *pRemoteUSBBackend = NULL;
/* Find the instance. */
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
pRemoteUSBBackend = usbBackendFind (u32ClientId);
if (pRemoteUSBBackend)
{
/* Notify that it will be deleted. */
pRemoteUSBBackend->NotifyDelete ();
}
unlockConsoleVRDPServer ();
}
if (pRemoteUSBBackend)
{
/* Here the instance has been excluded from the list and can be dereferenced. */
pRemoteUSBBackend->Release ();
}
#endif
}
void *ConsoleVRDPServer::USBBackendRequestPointer (uint32_t u32ClientId, const Guid *pGuid)
{
#ifdef VBOX_WITH_USB
RemoteUSBBackend *pRemoteUSBBackend = NULL;
/* Find the instance. */
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
pRemoteUSBBackend = usbBackendFind (u32ClientId);
if (pRemoteUSBBackend)
{
/* Inform the backend instance that it is referenced by the Guid. */
bool fAdded = pRemoteUSBBackend->addUUID (pGuid);
if (fAdded)
{
/* Reference the instance because its pointer is being taken. */
pRemoteUSBBackend->AddRef (); /* 'Release' is called in USBBackendReleasePointer. */
}
else
{
pRemoteUSBBackend = NULL;
}
}
unlockConsoleVRDPServer ();
}
if (pRemoteUSBBackend)
{
return pRemoteUSBBackend->GetBackendCallbackPointer ();
}
#endif
return NULL;
}
void ConsoleVRDPServer::USBBackendReleasePointer (const Guid *pGuid)
{
#ifdef VBOX_WITH_USB
RemoteUSBBackend *pRemoteUSBBackend = NULL;
/* Find the instance. */
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
pRemoteUSBBackend = usbBackendFindByUUID (pGuid);
if (pRemoteUSBBackend)
{
pRemoteUSBBackend->removeUUID (pGuid);
}
unlockConsoleVRDPServer ();
if (pRemoteUSBBackend)
{
pRemoteUSBBackend->Release ();
}
}
#endif
}
RemoteUSBBackend *ConsoleVRDPServer::usbBackendGetNext (RemoteUSBBackend *pRemoteUSBBackend)
{
LogFlow(("ConsoleVRDPServer::usbBackendGetNext: pBackend = %p\n", pRemoteUSBBackend));
RemoteUSBBackend *pNextRemoteUSBBackend = NULL;
#ifdef VBOX_WITH_USB
int rc = lockConsoleVRDPServer ();
if (RT_SUCCESS (rc))
{
if (pRemoteUSBBackend == NULL)
{
/* The first backend in the list is requested. */
pNextRemoteUSBBackend = mUSBBackends.pHead;
}
else
{
/* Get pointer to the next backend. */
pNextRemoteUSBBackend = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
}
if (pNextRemoteUSBBackend)
{
pNextRemoteUSBBackend->AddRef ();
}
unlockConsoleVRDPServer ();
if (pRemoteUSBBackend)
{
pRemoteUSBBackend->Release ();
}
}
#endif
return pNextRemoteUSBBackend;
}
#ifdef VBOX_WITH_USB
/* Internal method. Called under the ConsoleVRDPServerLock. */
RemoteUSBBackend *ConsoleVRDPServer::usbBackendFind (uint32_t u32ClientId)
{
RemoteUSBBackend *pRemoteUSBBackend = mUSBBackends.pHead;
while (pRemoteUSBBackend)
{
if (pRemoteUSBBackend->ClientId () == u32ClientId)
{
break;
}
pRemoteUSBBackend = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
}
return pRemoteUSBBackend;
}
/* Internal method. Called under the ConsoleVRDPServerLock. */
RemoteUSBBackend *ConsoleVRDPServer::usbBackendFindByUUID (const Guid *pGuid)
{
RemoteUSBBackend *pRemoteUSBBackend = mUSBBackends.pHead;
while (pRemoteUSBBackend)
{
if (pRemoteUSBBackend->findUUID (pGuid))
{
break;
}
pRemoteUSBBackend = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
}
return pRemoteUSBBackend;
}
#endif
/* Internal method. Called by the backend destructor. */
void ConsoleVRDPServer::usbBackendRemoveFromList (RemoteUSBBackend *pRemoteUSBBackend)
{
#ifdef VBOX_WITH_USB
int rc = lockConsoleVRDPServer ();
AssertRC (rc);
/* Exclude the found instance from the list. */
if (pRemoteUSBBackend->pNext)
{
pRemoteUSBBackend->pNext->pPrev = pRemoteUSBBackend->pPrev;
}
else
{
mUSBBackends.pTail = (RemoteUSBBackend *)pRemoteUSBBackend->pPrev;
}
if (pRemoteUSBBackend->pPrev)
{
pRemoteUSBBackend->pPrev->pNext = pRemoteUSBBackend->pNext;
}
else
{
mUSBBackends.pHead = (RemoteUSBBackend *)pRemoteUSBBackend->pNext;
}
pRemoteUSBBackend->pNext = pRemoteUSBBackend->pPrev = NULL;
unlockConsoleVRDPServer ();
#endif
}
void ConsoleVRDPServer::SendUpdate (unsigned uScreenId, void *pvUpdate, uint32_t cbUpdate) const
{
#ifdef VBOX_WITH_VRDP
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPUpdate (mhServer, uScreenId, pvUpdate, cbUpdate);
}
#endif
}
void ConsoleVRDPServer::SendResize (void) const
{
#ifdef VBOX_WITH_VRDP
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPResize (mhServer);
}
#endif
}
void ConsoleVRDPServer::SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const
{
#ifdef VBOX_WITH_VRDP
VRDPORDERHDR update;
update.x = x;
update.y = y;
update.w = w;
update.h = h;
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPUpdate (mhServer, uScreenId, &update, sizeof (update));
}
#endif
}
void ConsoleVRDPServer::SendAudioSamples (void *pvSamples, uint32_t cSamples, VRDPAUDIOFORMAT format) const
{
#ifdef VBOX_WITH_VRDP
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPAudioSamples (mhServer, pvSamples, cSamples, format);
}
#endif
}
void ConsoleVRDPServer::SendAudioVolume (uint16_t left, uint16_t right) const
{
#ifdef VBOX_WITH_VRDP
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPAudioVolume (mhServer, left, right);
}
#endif
}
void ConsoleVRDPServer::SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const
{
#ifdef VBOX_WITH_VRDP
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPUSBRequest (mhServer, u32ClientId, pvParms, cbParms);
}
#endif
}
void ConsoleVRDPServer::QueryInfo (uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const
{
#ifdef VBOX_WITH_VRDP
if (mpEntryPoints && mhServer)
{
mpEntryPoints->VRDPQueryInfo (mhServer, index, pvBuffer, cbBuffer, pcbOut);
}
#endif
}
#ifdef VBOX_WITH_VRDP
/* note: static function now! */
bool ConsoleVRDPServer::loadVRDPLibrary (void)
{
int rc = VINF_SUCCESS;
if (!mVRDPLibrary)
{
rc = SUPR3HardenedLdrLoadAppPriv ("VBoxVRDP", &mVRDPLibrary);
if (RT_SUCCESS(rc))
{
LogFlow(("VRDPServer::loadLibrary(): successfully loaded VRDP library.\n"));
struct SymbolEntry
{
const char *name;
void **ppfn;
};
#define DEFSYMENTRY(a) { #a, (void**)&mpfn##a }
static const struct SymbolEntry symbols[] =
{
DEFSYMENTRY(VRDPCreateServer)
};
#undef DEFSYMENTRY
for (unsigned i = 0; i < RT_ELEMENTS(symbols); i++)
{
rc = RTLdrGetSymbol(mVRDPLibrary, symbols[i].name, symbols[i].ppfn);
AssertMsgRC(rc, ("Error resolving VRDP symbol %s\n", symbols[i].name));
if (RT_FAILURE(rc))
{
break;
}
}
}
else
{
LogRel(("VRDPServer::loadLibrary(): failed to load VRDP library! VRDP not available: rc = %Rrc\n", rc));
mVRDPLibrary = NULL;
}
}
// just to be safe
if (RT_FAILURE(rc))
{
if (mVRDPLibrary)
{
RTLdrClose (mVRDPLibrary);
mVRDPLibrary = NULL;
}
}
return (mVRDPLibrary != NULL);
}
#endif /* VBOX_WITH_VRDP */
/*
* IRemoteDisplayInfo implementation.
*/
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
DEFINE_EMPTY_CTOR_DTOR (RemoteDisplayInfo)
HRESULT RemoteDisplayInfo::FinalConstruct()
{
return S_OK;
}
void RemoteDisplayInfo::FinalRelease()
{
uninit ();
}
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
/**
* Initializes the guest object.
*/
HRESULT RemoteDisplayInfo::init (Console *aParent)
{
LogFlowThisFunc (("aParent=%p\n", aParent));
ComAssertRet (aParent, E_INVALIDARG);
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan (this);
AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
unconst (mParent) = aParent;
return S_OK;
}
/**
* Uninitializes the instance and sets the ready flag to FALSE.
* Called either from FinalRelease() or by the parent when it gets destroyed.
*/
void RemoteDisplayInfo::uninit()
{
LogFlowThisFunc (("\n"));
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan (this);
if (autoUninitSpan.uninitDone())
return;
unconst (mParent).setNull();
}
// IRemoteDisplayInfo properties
/////////////////////////////////////////////////////////////////////////////
#define IMPL_GETTER_BOOL(_aType, _aName, _aIndex) \
STDMETHODIMP RemoteDisplayInfo::COMGETTER(_aName) (_aType *a##_aName) \
{ \
if (!a##_aName) \
return E_POINTER; \
\
AutoCaller autoCaller (this); \
CheckComRCReturnRC (autoCaller.rc()); \
\
/* todo: Not sure if a AutoReadLock would be sufficient. */ \
AutoWriteLock alock (this); \
\
uint32_t value; \
uint32_t cbOut = 0; \
\
mParent->consoleVRDPServer ()->QueryInfo \
(_aIndex, &value, sizeof (value), &cbOut); \
\
*a##_aName = cbOut? !!value: FALSE; \
\
return S_OK; \
}
#define IMPL_GETTER_SCALAR(_aType, _aName, _aIndex) \
STDMETHODIMP RemoteDisplayInfo::COMGETTER(_aName) (_aType *a##_aName) \
{ \
if (!a##_aName) \
return E_POINTER; \
\
AutoCaller autoCaller (this); \
CheckComRCReturnRC (autoCaller.rc()); \
\
/* todo: Not sure if a AutoReadLock would be sufficient. */ \
AutoWriteLock alock (this); \
\
_aType value; \
uint32_t cbOut = 0; \
\
mParent->consoleVRDPServer ()->QueryInfo \
(_aIndex, &value, sizeof (value), &cbOut); \
\
*a##_aName = cbOut? value: 0; \
\
return S_OK; \
}
#define IMPL_GETTER_BSTR(_aType, _aName, _aIndex) \
STDMETHODIMP RemoteDisplayInfo::COMGETTER(_aName) (_aType *a##_aName) \
{ \
if (!a##_aName) \
return E_POINTER; \
\
AutoCaller autoCaller (this); \
CheckComRCReturnRC (autoCaller.rc()); \
\
/* todo: Not sure if a AutoReadLock would be sufficient. */ \
AutoWriteLock alock (this); \
\
uint32_t cbOut = 0; \
\
mParent->consoleVRDPServer ()->QueryInfo \
(_aIndex, NULL, 0, &cbOut); \
\
if (cbOut == 0) \
{ \
Bstr str(""); \
str.cloneTo (a##_aName); \
return S_OK; \
} \
\
char *pchBuffer = (char *)RTMemTmpAlloc (cbOut); \
\
if (!pchBuffer) \
{ \
Log(("RemoteDisplayInfo::" \
#_aName \
": Failed to allocate memory %d bytes\n", cbOut)); \
return E_OUTOFMEMORY; \
} \
\
mParent->consoleVRDPServer ()->QueryInfo \
(_aIndex, pchBuffer, cbOut, &cbOut); \
\
Bstr str(pchBuffer); \
\
str.cloneTo (a##_aName); \
\
RTMemTmpFree (pchBuffer); \
\
return S_OK; \
}
IMPL_GETTER_BOOL (BOOL, Active, VRDP_QI_ACTIVE);
IMPL_GETTER_SCALAR (ULONG, NumberOfClients, VRDP_QI_NUMBER_OF_CLIENTS);
IMPL_GETTER_SCALAR (LONG64, BeginTime, VRDP_QI_BEGIN_TIME);
IMPL_GETTER_SCALAR (LONG64, EndTime, VRDP_QI_END_TIME);
IMPL_GETTER_SCALAR (ULONG64, BytesSent, VRDP_QI_BYTES_SENT);
IMPL_GETTER_SCALAR (ULONG64, BytesSentTotal, VRDP_QI_BYTES_SENT_TOTAL);
IMPL_GETTER_SCALAR (ULONG64, BytesReceived, VRDP_QI_BYTES_RECEIVED);
IMPL_GETTER_SCALAR (ULONG64, BytesReceivedTotal, VRDP_QI_BYTES_RECEIVED_TOTAL);
IMPL_GETTER_BSTR (BSTR, User, VRDP_QI_USER);
IMPL_GETTER_BSTR (BSTR, Domain, VRDP_QI_DOMAIN);
IMPL_GETTER_BSTR (BSTR, ClientName, VRDP_QI_CLIENT_NAME);
IMPL_GETTER_BSTR (BSTR, ClientIP, VRDP_QI_CLIENT_IP);
IMPL_GETTER_SCALAR (ULONG, ClientVersion, VRDP_QI_CLIENT_VERSION);
IMPL_GETTER_SCALAR (ULONG, EncryptionStyle, VRDP_QI_ENCRYPTION_STYLE);
#undef IMPL_GETTER_BSTR
#undef IMPL_GETTER_SCALAR