ConsoleVRDPServer.cpp revision 3918ed075bc7939d7397b643c46b460a4f3b67fc
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VBox Console VRDP Helper class
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
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 * 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.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#endif /* VBOX_WITH_VRDP */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#endif /* !VBOX_WITH_XPCOM */
044af0d1e6474076366759db86f101778c5f20ccvboxsync delete this;
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(QueryInterface) (REFIID riid , void **ppObj)
044af0d1e6474076366759db86f101778c5f20ccvboxsync#endif /* !VBOX_WITH_XPCOM */
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(OnMousePointerShapeChange)(BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot,
044af0d1e6474076366759db86f101778c5f20ccvboxsync STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync m_server->NotifyKeyboardLedsChange (fNumLock, fCapsLock, fScrollLock);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnStateChange)(MachineState_T machineState)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *aDevice, BOOL aAttached,
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync STDMETHOD(OnRuntimeError)(BOOL fatal, INPTR BSTR id, INPTR BSTR message)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* we don't manage window activation here: always agree */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync /* we don't manage window activation here */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#endif /* !VBOX_WITH_XPCOM */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsyncNS_IMPL_THREADSAFE_ISUPPORTS1_CI(VRDPConsoleCallback, IConsoleCallback)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync#endif /* VBOX_WITH_XPCOM */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncvoid dumpPointer (const uint8_t *pu8Shape, uint32_t width, uint32_t height, bool fXorMaskRGB32)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync unsigned i;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (i = 0; i < height; i++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned j;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned k;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (k = 0; k < 8; k++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LOGDUMPPTR(("%d", ((*pu8And) & (1 << (7 - k)))? 1: 0));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t *pu32Xor = (uint32_t *)(pu8Shape + ((((width + 7) / 8) * height + 3) & ~3));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (i = 0; i < height; i++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned j;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (j = 0; j < width; j++)
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++)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync unsigned j;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync for (j = 0; j < width; j++)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync LOGDUMPPTR(("%02X%02X%02X", pu8Xor[2], pu8Xor[1], pu8Xor[0]));
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#define dumpPointer(a, b, c, d) do {} while (0)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync#endif /* DEBUG_sunlover */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncstatic void findTopLeftBorder (const uint8_t *pu8AndMask, const uint8_t *pu8XorMask, uint32_t width, uint32_t height, uint32_t *pxSkip, uint32_t *pySkip)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * Find the top border of the AND mask. First assign to special value.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const uint8_t maskLastByte = (uint8_t)( 0xFF << (cbAndRow * 8 - width) );
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned x;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < height && ySkipAnd == ~(uint32_t)0; y++, pu8And += cbAndRow)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* For each complete byte in the row. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Last byte. */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if ((pu8And[cbAndRow - 1] & maskLastByte) != maskLastByte)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * Find the left border of the AND mask.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* For all bit columns. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < width && xSkipAnd == ~(uint32_t)0; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu8And = pu8AndMask + x/8; /* Currently checking byte. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t mask = 1 << (7 - x%8); /* Currently checking bit in the byte. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = ySkipAnd; y < height; y++, pu8And += cbAndRow)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * Find the XOR mask top border.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < height && ySkipXor == ~(uint32_t)0; y++, pu32Xor += width)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < width; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pu32Xor[x] != 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Find the left border of the XOR mask.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* For all columns. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < width && xSkipXor == ~(uint32_t)0; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pu32Xor = pu32XorStart + x; /* Currently checking dword. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = ySkipXor; y < height; y++, pu32Xor += width)
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.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncstatic void mousePointerGenerateANDMask (uint8_t *pu8DstAndMask, int cbDstAndMask, const uint8_t *pu8SrcAlpha, int w, int h)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < h; y++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Whether alpha channel value is not transparent enough for the pixel to be seen. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Point to next source and dest scans. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncSTDMETHODIMP VRDPConsoleCallback::OnMousePointerShapeChange (BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogSunlover(("VRDPConsoleCallback::OnMousePointerShapeChange: %d, %d, %dx%d, @%d,%d\n", visible, alpha, width, height, xHot, yHot));
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.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * We convert this to RDP color format which consist of
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * one bpp AND mask and 24 BPP (BGR) color XOR image.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * RDP clients expect 8 aligned width and height of
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * pointer (preferably 32x32).
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * They even contain bugs which do not appear for
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * 32x32 pointers but would appear for a 41x32 one.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * So set pointer size to 32x32. This can be done safely
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * because most pointers are 32x32.
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync int cbDstAndMask = (((width + 7) / 8) * height + 3) & ~3;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync mousePointerGenerateANDMask (pu8AndMask, cbDstAndMask, pu8XorMask, width, height);
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 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 findTopLeftBorder (pu8AndMask, pu8XorMask, width, height, &xSkip, &ySkip);
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync /* Must not skip the hot spot. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Compute size and allocate memory for the pointer.
044af0d1e6474076366759db86f101778c5f20ccvboxsync pointer = (VRDPCOLORPOINTER *)RTMemTmpAlloc (sizeof (VRDPCOLORPOINTER) + rdpmasklen + rdpdatalen);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t *maskarray = (uint8_t *)pointer + sizeof (VRDPCOLORPOINTER);
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync /* Copy AND mask. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t *dst = maskarray + (dstheight - 1) * rdpmaskwidth;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t minheight = RT_MIN (height - ySkip, dstheight);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t minwidth = RT_MIN (width - xSkip, dstwidth);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned x, y;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < minheight; y++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < minwidth; x++)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync bool bit = (src[byteIndex] & (1 << (7 - bitIndex))) != 0;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync /* Point src to XOR mask */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (y = 0; y < minheight ; y++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (x = 0; x < minwidth; x++)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dumpPointer ((uint8_t *)pointer + sizeof (*pointer), dstwidth, dstheight, false);
044af0d1e6474076366759db86f101778c5f20ccvboxsync// ConsoleVRDPServer
044af0d1e6474076366759db86f101778c5f20ccvboxsync////////////////////////////////////////////////////////////////////////////////
044af0d1e6474076366759db86f101778c5f20ccvboxsyncPFNVRDPCREATESERVER ConsoleVRDPServer::mpfnVRDPCreateServer = NULL;
044af0d1e6474076366759db86f101778c5f20ccvboxsyncVRDPENTRYPOINTS_1 *ConsoleVRDPServer::mpEntryPoints = NULL;
044af0d1e6474076366759db86f101778c5f20ccvboxsync { VRDP_INTERFACE_VERSION_1, sizeof (VRDPCALLBACKS_1) },
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackQueryProperty (void *pvCallback, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut)
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync server->mConsole->getVRDPServer ()->COMGETTER(Port) (&port);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->getVRDPServer ()->COMGETTER(NetAddress) (bstr.asOutParam());
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* The server expects UTF8. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* More than 64K seems to be an invalid address. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* The value is an empty string. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->machine ()->COMGETTER(MonitorCount)(&cMonitors);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackClientLogon (void *pvCallback, uint32_t u32ClientId, const char *pszUser, const char *pszPassword, const char *pszDomain)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return server->mConsole->VRDPClientLogon (u32ClientId, pszUser, pszPassword, pszDomain);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackClientConnect (void *pvCallback, uint32_t u32ClientId)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackClientDisconnect (void *pvCallback, uint32_t u32ClientId, uint32_t fu32Intercepted)
044af0d1e6474076366759db86f101778c5f20ccvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync server->mConsole->VRDPClientDisconnect (u32ClientId, fu32Intercepted);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackIntercept (void *pvCallback, uint32_t u32ClientId, uint32_t fu32Intercept, void **ppvIntercept)
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync server->mConsole->VRDPInterceptAudio (u32ClientId);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->VRDPInterceptUSB (u32ClientId, ppvIntercept);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->VRDPInterceptClipboard (u32ClientId);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackUSB (void *pvCallback, void *pvIntercept, uint32_t u32ClientId, uint8_t u8Code, const void *pvRet, uint32_t cbRet)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return USBClientResponseCallback (pvIntercept, u32ClientId, u8Code, pvRet, cbRet);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(int) ConsoleVRDPServer::VRDPCallbackClipboard (void *pvCallback, void *pvIntercept, uint32_t u32ClientId, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return ClipboardCallback (pvIntercept, u32ClientId, u32Function, u32Format, pvData, cbData);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(bool) ConsoleVRDPServer::VRDPCallbackFramebufferQuery (void *pvCallback, unsigned uScreenId, VRDPFRAMEBUFFERINFO *pInfo)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync bool fAvailable = false;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync server->mConsole->getDisplay ()->GetFramebuffer (uScreenId, &pfb, &xOrigin, &yOrigin);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* Query framebuffer parameters. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* Now fill the information as requested by the caller. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackFramebufferLock (void *pvCallback, unsigned uScreenId)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackFramebufferUnlock (void *pvCallback, unsigned uScreenId)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncstatic void fixKbdLockStatus (VRDPInputSynch *pInputSynch, IKeyboard *pKeyboard)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync && (pInputSynch->fGuestNumLock != pInputSynch->fClientNumLock))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync && (pInputSynch->fGuestCapsLock != pInputSynch->fClientCapsLock))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackInput (void *pvCallback, int type, const void *pvInput, unsigned cbInput)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync const VRDPINPUTSCANCODE *pInputScancode = (VRDPINPUTSCANCODE *)pvInput;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* Track lock keys. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientNumLock = !server->m_InputSynch.fClientNumLock;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync server->m_InputSynch.fClientCapsLock = !server->m_InputSynch.fClientCapsLock;
a1df400bbe9d64aad400442e56eb637019300a5evboxsync server->m_InputSynch.fClientScrollLock = !server->m_InputSynch.fClientScrollLock;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* Key pressed. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync fixKbdLockStatus (&server->m_InputSynch, pKeyboard);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pKeyboard->PutScancode((LONG)pInputScancode->uScancode);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync const VRDPINPUTPOINT *pInputPoint = (VRDPINPUTPOINT *)pvInput;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_BUTTON1)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_BUTTON2)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_BUTTON3)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_WHEEL_UP)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pInputPoint->uButtons & VRDP_INPUT_POINT_WHEEL_DOWN)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pConsole->getMouse()->PutMouseEventAbsolute (pInputPoint->x + 1, pInputPoint->y + 1, iWheel, mouseButtons);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pConsole->getMouse()->PutMouseEvent (pInputPoint->x - server->m_mousex,
a1df400bbe9d64aad400442e56eb637019300a5evboxsync const VRDPINPUTSYNCH *pInputSynch = (VRDPINPUTSYNCH *)pvInput;
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 /* 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 if (server->m_InputSynch.fClientNumLock != server->m_InputSynch.fGuestNumLock)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync if (server->m_InputSynch.fClientCapsLock != server->m_InputSynch.fGuestCapsLock)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync fixKbdLockStatus (&server->m_InputSynch, pKeyboard);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncDECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackVideoModeHint (void *pvCallback, unsigned cWidth, unsigned cHeight, unsigned cBitsPerPixel, unsigned uScreenId)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ConsoleVRDPServer *server = static_cast <ConsoleVRDPServer *> (pvCallback);
a1df400bbe9d64aad400442e56eb637019300a5evboxsync server->mConsole->getDisplay ()->SetVideoModeHint(cWidth, cHeight, cBitsPerPixel, uScreenId);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncConsoleVRDPServer::ConsoleVRDPServer (Console *console)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync memset (maFramebuffers, 0, sizeof (maFramebuffers));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync unsigned i;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync IVRDPServer *vrdpserver = mConsole->getVRDPServer ();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync HRESULT rc2 = vrdpserver->COMGETTER(Enabled) (&vrdpEnabled);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = mpfnVRDPCreateServer (&mCallbacks.header, this, (VRDPINTERFACEHDR **)&mpEntryPoints, &mhServer);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_USB */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertMsgFailed(("Could not start VRDP server: rc = %Rrc\n", rc));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertMsgFailed(("Could not load the VRDP library\n"));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync LogRel(("VRDP: this version does not include the VRDP server.\n"));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mpEntryPoints->VRDPEnableConnections (mhServer, true);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncvoid ConsoleVRDPServer::DisconnectClient (uint32_t u32ClientId, bool fReconnect)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mpEntryPoints->VRDPDisconnect (mhServer, u32ClientId, fReconnect);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_WITH_VRDP */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncvoid ConsoleVRDPServer::MousePointerUpdate (const VRDPCOLORPOINTER *pPointer)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync mpEntryPoints->VRDPColorPointer (mhServer, pPointer);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_VRDP */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_VRDP */
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 /* Reset the handle to avoid further calls to the server. */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_VRDP */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync#endif /* VBOX_WITH_USB */
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 * It is expected that attaching/detaching is not a frequent operation.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * The thread is always running when the VRDP server is active.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * The thread scans backends and requests the device list every 2 seconds.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * When device list is available, the thread calls the Console to process it.
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncstatic DECLCALLBACK(int) threadRemoteUSB (RTTHREAD self, void *pvUser)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync ConsoleVRDPServer *pOwner = (ConsoleVRDPServer *)pvUser;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync LogFlow(("Console::threadRemoteUSB: start. owner = %p.\n", pOwner));
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync while ((pRemoteUSBBackend = pOwner->usbBackendGetNext (pRemoteUSBBackend)) != NULL)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pOwner->waitRemoteUSBThreadEvent (VRDP_DEVICE_LIST_PERIOD_MS);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync LogFlow(("Console::threadRemoteUSB: iteration. owner = %p.\n", pOwner));
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncvoid ConsoleVRDPServer::notifyRemoteUSBThreadRunning (RTTHREAD thread)
AssertFailed ();
VRDPAuthResult ConsoleVRDPServer::Authenticate (const Guid &uuid, VRDPAuthGuestJudgement guestJudgement,
LogFlow(("ConsoleVRDPServer::Authenticate: uuid = %Ruuid, guestJudgement = %d, pszUser = %s, pszPassword = %s, pszDomain = %s, u32ClientId = %d\n",
if (!mAuthLibrary)
LogRel(("VRDPAUTH: ConsoleVRDPServer::Authenticate: loading external authentication library '%ls'\n", authLibrary.raw()));
if (mAuthLibrary)
mAuthLibrary = 0;
return VRDPAuthAccessDenied;
switch (result)
case VRDPAuthAccessDenied:
case VRDPAuthAccessGranted:
case VRDPAuthDelegateToGuest:
return result;
if (mpfnAuthEntry2)
return rc;
const void *pvData,
LogFlowFunc(("pvCallback = %p, u32ClientId = %d, u32Function = %d, u32Format = 0x%08X, pvData = %p, cbData = %d\n",
switch (u32Function)
(void *)pvData,
cbData);
(void *)pvData,
cbData);
return rc;
void *pvParms,
#ifdef VBOX_WITH_VRDP
switch (u32Function)
NULL,
NULL);
NULL);
return rc;
if (mcClipboardRefs == 0)
rc = HGCMHostRegisterServiceExtension (&mhClipboard, "VBoxSharedClipboard", ClipboardServiceExtension, this);
if (mcClipboardRefs == 0)
#ifdef VBOX_WITH_USB
if (pRemoteUSBBackend)
if (ppvIntercept)
#ifdef VBOX_WITH_USB
if (pRemoteUSBBackend)
if (pRemoteUSBBackend)
#ifdef VBOX_WITH_USB
if (pRemoteUSBBackend)
if (fAdded)
if (pRemoteUSBBackend)
return NULL;
#ifdef VBOX_WITH_USB
if (pRemoteUSBBackend)
if (pRemoteUSBBackend)
#ifdef VBOX_WITH_USB
if (pRemoteUSBBackend)
return pNextRemoteUSBBackend;
#ifdef VBOX_WITH_USB
while (pRemoteUSBBackend)
return pRemoteUSBBackend;
while (pRemoteUSBBackend)
return pRemoteUSBBackend;
#ifdef VBOX_WITH_USB
#ifdef VBOX_WITH_VRDP
#ifdef VBOX_WITH_VRDP
void ConsoleVRDPServer::SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const
#ifdef VBOX_WITH_VRDP
update.x = x;
update.y = y;
update.w = w;
update.h = h;
void ConsoleVRDPServer::SendAudioSamples (void *pvSamples, uint32_t cSamples, VRDPAUDIOFORMAT format) const
#ifdef VBOX_WITH_VRDP
#ifdef VBOX_WITH_VRDP
void ConsoleVRDPServer::SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const
#ifdef VBOX_WITH_VRDP
void ConsoleVRDPServer::QueryInfo (uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const
#ifdef VBOX_WITH_VRDP
#ifdef VBOX_WITH_VRDP
if (!mVRDPLibrary)
struct SymbolEntry
const char *name;
void **ppfn;
LogRel(("VRDPServer::loadLibrary(): failed to load VRDP library! VRDP not available: rc = %Rrc\n", rc));
if (mVRDPLibrary)
return S_OK;
uninit ();
return S_OK;
if (!a##_aName) \
return E_POINTER; \
return S_OK; \
if (!a##_aName) \
return E_POINTER; \
return S_OK; \
if (!a##_aName) \
return E_POINTER; \
if (cbOut == 0) \
return S_OK; \
if (!pchBuffer) \
#_aName \
return E_OUTOFMEMORY; \
return S_OK; \