1
/*********************************************************
2
* Copyright (C) 2010 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Unity: Guest window manager integration service.
24
* This file implements parts of the guest-side Unity agent as part of the VMware Tools.
25
* It contains entry points for the GuestRpc (TCLO, RPCI) interface.
27
* UnityWindowTracker updates are sent to the MKS in two ways:
28
* @li @ref UNITY_RPC_GET_UPDATE GuestRpc (host-to-guest).
29
* @li @ref UNITY_RPC_PUSH_UPDATE_CMD GuestRpc (guest-to-host).
31
* @note Looking for the old "unity.get.update" return syntax? See @ref
32
* UNITY_RPC_GET_UPDATE and @ref UnityGetUpdateReturn instead.
39
#include "vmware/tools/plugin.h"
46
#include "guestrpc/unity.h"
47
#include "guestrpc/unityActive.h"
51
#if defined(OPEN_VM_TOOLS)
52
#include "unitylib/unity.h"
55
#endif // OPEN_VM_TOOLS
56
#include "unityDebug.h"
60
#include "unityPlugin.h"
61
#include "unityTclo.h"
63
namespace vmware { namespace tools {
66
* Container used to store and send Unity updates.
69
typedef struct _UnityUpdateChannel {
70
DynBuf updates; ///< See @ref vmtools_unity_uwtGuestRpc.
71
size_t cmdSize; /**< @brief Size of RpcOut command prefix.
72
Used as a convenient offset within #updates when
73
resetting the update buffer. */
75
} UnityTCLOUpdateChannel;
81
static Bool UnityUpdateState(void);
83
/* Sends the unity.window.contents.start RPC to the host. */
84
Bool UnitySendWindowContentsStart(UnityWindowId window,
89
/* Sends the unity.window.contents.chunk RPC to the host. */
90
Bool UnitySendWindowContentsChunk(UnityWindowId window,
95
/* Sends the unity.window.contents.end RPC to the host. */
96
Bool UnitySendWindowContentsEnd(UnityWindowId window);
99
* Callback function used by UnityXdrSendRpc() to encode XDR-serialized
102
typedef Bool(*UnityXdrEncodeFunc)(XDR*,void*);
105
* Helper function used to send an RPC to the host with XDR-serialized
106
* arguments. Calls encodeFn on the XDR* and the provied arg to perform
109
Bool UnityXdrSendRpc(const char *rpcName, UnityXdrEncodeFunc encodeFn, void *arg);
114
* "UnityTcloGetUpdate cannot return the contents of a DynBuf. This will leak
115
* the DynBuf's memory, since nobody at a lower level will ever free it. It's
116
* a crappy interface, but we make due by using a static buffer to hold the
119
* We ideally would not use a static buffer because the maximum size of the
120
* update is unknown. To work around this, make the DynBuf returned in
121
* UnityTcloGetUpdate file-global and recycle it across update requests.
124
static DynBuf gTcloUpdate;
128
*----------------------------------------------------------------------------
132
* Initialize the global state (a Dynbuf) used to handle the TCLO parsing
141
*----------------------------------------------------------------------------
148
* Init our global dynbuf used to send results back.
150
DynBuf_Init(&gTcloUpdate);
156
*----------------------------------------------------------------------------
158
* UnityTcloCleanup --
160
* Cleanup the global state (a Dynbuf) used to handle the TCLO parsing
169
*----------------------------------------------------------------------------
175
DynBuf_Destroy(&gTcloUpdate);
180
*----------------------------------------------------------------------------
184
* RPC handler for 'unity.enter'. Save and disable certain user
185
* settings. Start Unity updates thread and any other platform
186
* specific threads (like a thread that listens for
187
* the desktop switch event on Windows). Note that we first set
188
* the UI settings, and then start the threads. This way the UI
189
* settings take effect before we start sending Unity updates,
190
* so that we never send things like task bar (see bug 166085).
193
* TRUE if helper threads were started.
197
* Certain UI system settings will be disabled.
198
* Unity update thread will be started.
199
* Any other platform specific helper threads will be started as well.
201
*----------------------------------------------------------------------------
205
UnityTcloEnter(RpcInData *data) // IN/OUT
207
/* Check our arguments. */
213
Debug("%s\n", __FUNCTION__);
215
if (!Unity_Enter()) {
216
return RPCIN_SETRETVALS(data, "Could not enter unity", FALSE);
221
return RPCIN_SETRETVALS(data, "", TRUE);
226
*----------------------------------------------------------------------------
230
* RPC handler for 'unity.exit'.
236
* Same as side effects of Unity_Exit().
238
*----------------------------------------------------------------------------
242
UnityTcloExit(RpcInData *data) // IN/OUT
244
/* Check our arguments. */
250
Debug("UnityTcloExit.\n");
255
return RPCIN_SETRETVALS(data, "", TRUE);
260
*----------------------------------------------------------------------------
262
* UnityTcloGetWindowPath --
264
* RPC handler for UNITY_RPC_GET_WINDOW_PATH.
266
* Get the information needed to re-launch a window and retrieve further
267
* information on it. Returns double-NUL-terminated buffer consisting of
268
* NUL-terminated strings "windowPath" and "execPath" strings, the first
269
* uniquely identifying the window and the second uniquely identifying the
270
* window's owning executable.
273
* TRUE if everything is successful.
279
*----------------------------------------------------------------------------
283
UnityTcloGetWindowPath(RpcInData *data) // IN/OUT
285
UnityWindowId window;
286
DynBuf windowPathUtf8;
289
unsigned int index = 0;
292
/* Check our arguments. */
301
if (!data->name || !data->args) {
302
Debug("%s: Invalid arguments.\n", __FUNCTION__);
303
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
306
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
308
/* Parse the command & window id.*/
310
if (!StrUtil_GetNextIntToken((int32*) &window, &index, data->args, " ")) {
311
Debug("UnityTcloGetWindowInfo: Invalid RPC arguments.\n");
312
return RPCIN_SETRETVALS(data,
313
"Invalid arguments. Expected \"windowId\"",
317
Debug("%s: window %d\n", __FUNCTION__, window);
320
* Please note that the Unity_GetWindowPath implementations assume that the
321
* dynbuf passed in does not contain any existing data that needs to be appended to,
322
* so this code should continue to accomodate that assumption.
324
DynBuf_Destroy(&gTcloUpdate);
325
DynBuf_Init(&gTcloUpdate);
326
DynBuf_Init(&windowPathUtf8);
327
DynBuf_Init(&execPathUtf8);
328
if (!Unity_GetWindowPath(window, &windowPathUtf8, &execPathUtf8)) {
329
Debug("%s: Could not get window path.\n", __FUNCTION__);
330
ret = RPCIN_SETRETVALS(data,
331
"Could not get window path",
337
* Construct the buffer holding the result. Note that we need to use gTcloUpdate
338
* here to avoid leaking during the RPC handler.
340
DynBuf_Copy(&windowPathUtf8, &gTcloUpdate);
341
DynBuf_Append(&gTcloUpdate, DynBuf_Get(&execPathUtf8), DynBuf_GetSize(&execPathUtf8));
344
* Write the final result into the result out parameters and return!
346
data->result = (char *)DynBuf_Get(&gTcloUpdate);
347
data->resultLen = DynBuf_GetSize(&gTcloUpdate);
350
DynBuf_Destroy(&windowPathUtf8);
351
DynBuf_Destroy(&execPathUtf8);
357
*----------------------------------------------------------------------------
359
* UnityTcloWindowCommand --
361
* RPC handler for 'unity.window.*' (excluding 'unity.window.settop')
364
* TRUE if everything is successful.
370
*----------------------------------------------------------------------------
374
UnityTcloWindowCommand(RpcInData *data) // IN/OUT
376
UnityWindowId window;
377
unsigned int index = 0;
379
/* Check our arguments. */
388
if (!data->name || !data->args) {
389
Debug("%s: Invalid arguments.\n", __FUNCTION__);
390
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
393
Debug("UnityTcloWindowCommand: name:%s args:'%s'\n", data->name, data->args);
395
/* Parse the command & window id.*/
397
if (!StrUtil_GetNextIntToken((int32*) &window, &index, data->args, " ")) {
398
Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
399
return RPCIN_SETRETVALS(data,
400
"Invalid arguments. Expected \"windowId\"",
405
Debug("%s: %s window %d\n", __FUNCTION__, data->name, window);
407
if (!Unity_WindowCommand(window, data->name)) {
408
return RPCIN_SETRETVALS(data,
409
"Could not execute window command",
412
return RPCIN_SETRETVALS(data, "", TRUE);
418
*----------------------------------------------------------------------------
420
* UnityTcloSetDesktopWorkArea --
422
* RPC handler for 'unity.desktop.work_area.set'.
425
* TRUE if everything is successful.
431
*----------------------------------------------------------------------------
435
UnityTcloSetDesktopWorkArea(RpcInData *data) // IN/OUT
437
Bool success = FALSE;
441
UnityRect *workAreas = NULL;
443
/* Check our arguments. */
452
if (!data->name || !data->args) {
453
Debug("%s: Invalid arguments.\n", __FUNCTION__);
454
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
458
* The argument string will look something like:
459
* <count> [ , <x> <y> <w> <h> ] * count.
462
* 3 , 0 0 640 480 , 640 0 800 600 , 0 480 640 480
465
if (sscanf(data->args, "%u", &count) != 1) {
466
return RPCIN_SETRETVALS(data,
467
"Invalid arguments. Expected \"count\"",
472
workAreas = (UnityRect *)malloc(sizeof *workAreas * count);
474
RPCIN_SETRETVALS(data,
475
"Failed to alloc buffer for work areas",
481
for (argList = data->args, i = 0; i < count; i++) {
482
argList = strchr(argList, ',');
484
RPCIN_SETRETVALS(data,
485
"Expected comma separated display list",
489
argList++; /* Skip past the , */
491
if (sscanf(argList, " %d %d %d %d ",
492
&workAreas[i].x, &workAreas[i].y,
493
&workAreas[i].width, &workAreas[i].height) != 4) {
494
RPCIN_SETRETVALS(data,
495
"Expected x, y, w, h in display entry",
500
if (workAreas[i].x < 0 || workAreas[i].y < 0 ||
501
workAreas[i].width <= 0 || workAreas[i].height <= 0) {
502
RPCIN_SETRETVALS(data, "Invalid argument", FALSE);
507
if (!Unity_SetDesktopWorkAreas(workAreas, count)) {
508
RPCIN_SETRETVALS(data,
509
"Unity_SetDesktopWorkAreas failed",
514
success = RPCIN_SETRETVALS(data, "", TRUE);
523
*----------------------------------------------------------------------------
525
* UnityTcloSetTopWindowGroup --
527
* RPC handler for 'unity.window.settop'.
530
* TRUE if everything is successful.
536
*----------------------------------------------------------------------------
540
UnityTcloSetTopWindowGroup(RpcInData *data) // IN/OUT
542
UnityWindowId window;
543
unsigned int index = 0;
544
unsigned int windowCount = 0;
545
UnityWindowId windows[UNITY_MAX_SETTOP_WINDOW_COUNT];
547
/* Check our arguments. */
556
if (!data->name || !data->args) {
557
Debug("%s: Invalid arguments.\n", __FUNCTION__);
558
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
561
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
563
/* Parse the command & window ids.*/
565
while (StrUtil_GetNextUintToken(&window, &index, data->args, " ")) {
566
windows[windowCount] = window;
568
if (windowCount == UNITY_MAX_SETTOP_WINDOW_COUNT) {
569
Debug("%s: Too many windows.\n", __FUNCTION__);
570
return RPCIN_SETRETVALS(data,
571
"Invalid arguments. Too many windows",
576
if (windowCount == 0) {
577
Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
578
return RPCIN_SETRETVALS(data,
579
"Invalid arguments. Expected at least one windowId",
583
if (!Unity_SetTopWindowGroup(windows, windowCount)) {
584
return RPCIN_SETRETVALS(data,
585
"Could not execute window command",
589
return RPCIN_SETRETVALS(data, "", TRUE);
594
*----------------------------------------------------------------------------
596
* UnityTcloGetUpdate --
598
* RPC handler for 'unity.get.update'. Ask the unity window tracker
599
* to give us an update (either incremental or non-incremental based
600
* on whether the 'incremental' arg is present) and send the result
609
*----------------------------------------------------------------------------
613
UnityTcloGetUpdate(RpcInData *data) // IN/OUT
615
Bool incremental = FALSE;
617
/* Check our arguments. */
626
if (!data->name || !data->args) {
627
Debug("%s: Invalid arguments.\n", __FUNCTION__);
628
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
631
Debug("%s: name:%s args:'%s'", __FUNCTION__, data->name, data->args);
634
* Specify incremental or non-incremetal updates based on whether or
635
* not the client set the "incremental" arg.
637
if (strstr(data->name, "incremental")) {
642
* Call into platform-specific implementation to gather and send updates
643
* back via RPCI. (This is done to ensure all updates are sent to the
644
* Unity server in sequence via the same channel.)
646
Unity_GetUpdate(incremental);
649
* To maintain compatibility, we'll return a successful but empty response.
655
* Give the debugger a crack to do something interesting at this point
657
* XXX Not sure if this is worth keeping around since this routine no
658
* longer returns updates directly.
660
UnityDebug_OnUpdate();
667
*----------------------------------------------------------------------------
669
* UnityTcloConfirmOperation --
671
* RPC handler for 'unity.operation.confirm'.
674
* TRUE if the confirmation could be handled sucessfully.
680
*----------------------------------------------------------------------------
684
UnityTcloConfirmOperation(RpcInData *data) // IN/OUT
686
UnityConfirmOperation unityConfirmOpMsg;
687
UnityConfirmOperationV1 *confirmV1 = NULL;
691
/* Check our arguments. */
700
if (!data->name || !data->args) {
701
Debug("%s: Invalid arguments.\n", __FUNCTION__);
702
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
705
Debug("%s: Enter.\n", __FUNCTION__);
707
memset(&unityConfirmOpMsg, 0, sizeof unityConfirmOpMsg);
710
* Deserialize the XDR data. Note that the data begins with args + 1 since
711
* there is a space between the RPC name and the XDR serialization.
713
if (!XdrUtil_Deserialize(data->args + 1, data->argsSize - 1,
714
(void *)xdr_UnityConfirmOperation, &unityConfirmOpMsg)) {
715
ret = RPCIN_SETRETVALS(data, "Failed to deserialize data", FALSE);
719
confirmV1 = unityConfirmOpMsg.UnityConfirmOperation_u.unityConfirmOpV1;
720
retVal = Unity_ConfirmOperation(confirmV1->details.op,
725
/* Free any memory allocated by XDR - we're done with unityConfirmOpMsg */
726
VMX_XDR_FREE(xdr_UnityConfirmOperation, &unityConfirmOpMsg);
727
ret = RPCIN_SETRETVALS(data, "", retVal);
730
Debug("%s: Exit.\n", __FUNCTION__);
736
*----------------------------------------------------------------------------
738
* UnityTcloSendMouseWheel --
740
* RPC handler for 'unity.sendMouseWheel'.
743
* TRUE on success, FALSE on failure.
748
*----------------------------------------------------------------------------
752
UnityTcloSendMouseWheel(RpcInData *data) // IN/OUT
754
UnityMouseWheel unityMouseWheelMsg;
755
UnityMouseWheelV1 *mouseWheelV1 = NULL;
758
Debug("%s: Enter.\n", __FUNCTION__);
760
memset(&unityMouseWheelMsg, 0, sizeof unityMouseWheelMsg);
763
* Deserialize the XDR data. Note that the data begins with args + 1 since
764
* there is a space between the RPC name and the XDR serialization.
766
if (!XdrUtil_Deserialize(data->args + 1, data->argsSize - 1,
767
(void *)xdr_UnityMouseWheel, &unityMouseWheelMsg)) {
768
ret = RPCIN_SETRETVALS(data, "Failed to deserialize data", FALSE);
772
mouseWheelV1 = unityMouseWheelMsg.UnityMouseWheel_u.mouseWheelV1;
773
retVal = Unity_SendMouseWheel(mouseWheelV1->deltaX,
774
mouseWheelV1->deltaY,
775
mouseWheelV1->deltaZ,
776
mouseWheelV1->modifierFlags);
778
/* Free any memory allocated by XDR - we're done with unityMouseWheelMsg */
779
VMX_XDR_FREE(xdr_UnityMouseWheel, &unityMouseWheelMsg);
780
ret = RPCIN_SETRETVALS(data, "", retVal);
783
Debug("%s: Exit.\n", __FUNCTION__);
789
*----------------------------------------------------------------------------
791
* UnityUpdateCallbackFn --
793
* Callback from the unity window tracker indicating something's
796
* Write the update string into our dynbuf accumlating the update
805
*----------------------------------------------------------------------------
809
UnityUpdateCallbackFn(void *param, // IN: updateChannel
810
UnityUpdate *update) // IN
812
UnityUpdateChannel *updateChannel = reinterpret_cast<UnityUpdateChannel *>(param);
817
char *titleUtf8 = NULL;
818
char *windowPathUtf8 = "";
819
char *execPathUtf8 = "";
821
ASSERT(updateChannel);
822
buf = &updateChannel->updates;
824
switch (update->type) {
826
case UNITY_UPDATE_ADD_WINDOW:
827
if (DynBuf_GetSize(&update->u.addWindow.windowPathUtf8) > 0) {
829
static_cast<char*>(DynBuf_Get(&update->u.addWindow.windowPathUtf8));
831
if (DynBuf_GetSize(&update->u.addWindow.execPathUtf8) > 0) {
833
static_cast<char*>(DynBuf_Get(&update->u.addWindow.execPathUtf8));
836
Str_Sprintf(data, sizeof data, "add %u windowPath=%s execPath=%s",
837
update->u.addWindow.id,
840
DynBuf_AppendString(buf, data);
843
case UNITY_UPDATE_MOVE_WINDOW:
844
Str_Sprintf(data, sizeof data, "move %u %d %d %d %d",
845
update->u.moveWindow.id,
846
update->u.moveWindow.rect.x1,
847
update->u.moveWindow.rect.y1,
848
update->u.moveWindow.rect.x2,
849
update->u.moveWindow.rect.y2);
850
DynBuf_AppendString(buf, data);
853
case UNITY_UPDATE_REMOVE_WINDOW:
854
Str_Sprintf(data, sizeof data, "remove %u", update->u.removeWindow.id);
855
DynBuf_AppendString(buf, data);
858
case UNITY_UPDATE_CHANGE_WINDOW_REGION:
860
* A null region indicates that the region should be deleted.
861
* Make sure we write "region <id> 0" for the reply.
863
region = update->u.changeWindowRegion.region;
865
count = REGION_NUM_RECTS(region);
867
Str_Sprintf(data, sizeof data, "region %u %d",
868
update->u.changeWindowRegion.id, count);
869
DynBuf_AppendString(buf, data);
871
for (i = 0; i < count; i++) {
872
BoxPtr p = REGION_RECTS(region) + i;
873
Str_Sprintf(data, sizeof data, "rect %d %d %d %d",
874
p->x1, p->y1, p->x2, p->y2);
875
DynBuf_AppendString(buf, data);
879
case UNITY_UPDATE_CHANGE_WINDOW_TITLE:
881
reinterpret_cast<char*>(DynBuf_Get(&update->u.changeWindowTitle.titleUtf8));
884
(DynBuf_GetSize(&update->u.changeWindowTitle.titleUtf8) ==
885
strlen(titleUtf8) + 1)) {
886
Str_Sprintf(data, sizeof data, "title %u ",
887
update->u.changeWindowTitle.id);
888
Str_Strncat(data, sizeof data, titleUtf8, sizeof data - strlen(data) - 1);
889
data[sizeof data - 1] = '\0';
891
Str_Sprintf(data, sizeof data, "title %u",
892
update->u.changeWindowTitle.id);
894
DynBuf_AppendString(buf, data);
897
case UNITY_UPDATE_CHANGE_ZORDER:
898
n = Str_Snprintf(data, sizeof data, "zorder %d", update->u.zorder.count);
899
DynBuf_Append(buf, data, n);
900
for (unsigned int zOrderIndex = 0;
901
zOrderIndex < update->u.zorder.count;
903
n = Str_Snprintf(data, sizeof data, " %d", update->u.zorder.ids[zOrderIndex]);
904
DynBuf_Append(buf, data, n);
906
DynBuf_AppendString(buf, ""); // for appending NULL
909
case UNITY_UPDATE_CHANGE_WINDOW_STATE:
910
Str_Sprintf(data, sizeof data, "state %u %u",
911
update->u.changeWindowState.id,
912
update->u.changeWindowState.state);
913
DynBuf_AppendString(buf, data);
916
case UNITY_UPDATE_CHANGE_WINDOW_ATTRIBUTE:
917
Str_Sprintf(data, sizeof data, "attr %u %u %u",
918
update->u.changeWindowAttribute.id,
919
update->u.changeWindowAttribute.attr,
920
update->u.changeWindowAttribute.value);
921
DynBuf_AppendString(buf, data);
924
case UNITY_UPDATE_CHANGE_WINDOW_TYPE:
925
Str_Sprintf(data, sizeof data, "type %u %d",
926
update->u.changeWindowType.id,
927
update->u.changeWindowType.winType);
928
DynBuf_AppendString(buf, data);
931
case UNITY_UPDATE_CHANGE_WINDOW_ICON:
932
Str_Sprintf(data, sizeof data, "icon %u %u",
933
update->u.changeWindowIcon.id,
934
update->u.changeWindowIcon.iconType);
935
DynBuf_AppendString(buf, data);
938
case UNITY_UPDATE_CHANGE_WINDOW_DESKTOP:
939
Str_Sprintf(data, sizeof data, "desktop %u %d",
940
update->u.changeWindowDesktop.id,
941
update->u.changeWindowDesktop.desktopId);
942
DynBuf_AppendString(buf, data);
945
case UNITY_UPDATE_CHANGE_ACTIVE_DESKTOP:
946
Str_Sprintf(data, sizeof data, "activedesktop %d",
947
update->u.changeActiveDesktop.desktopId);
948
DynBuf_AppendString(buf, data);
958
*-----------------------------------------------------------------------------
960
* UnityUpdateChannelInit --
962
* Initialize the state for the update channel.
965
* Pointer to UpdateChannel structure or NULL
968
* RpcOut channel might be open.
969
* Memory for the update buffer might be allocated.
971
*-----------------------------------------------------------------------------
975
UnityUpdateChannelInit()
977
UnityUpdateChannel *updateChannel = NULL;
978
updateChannel = reinterpret_cast<UnityUpdateChannel *>(Util_SafeCalloc(1, sizeof *updateChannel));
980
DynBuf_Init(&updateChannel->updates);
981
DynBuf_AppendString(&updateChannel->updates, UNITY_RPC_PUSH_UPDATE_CMD " ");
983
/* Exclude the null. */
984
updateChannel->cmdSize = DynBuf_GetSize(&updateChannel->updates) - 1;
985
DynBuf_SetSize(&updateChannel->updates, updateChannel->cmdSize);
987
updateChannel->rpcOut = RpcOut_Construct();
988
if (updateChannel->rpcOut == NULL) {
989
Warning("%s: RpcOut_Construct() failed\n", __FUNCTION__);
993
if (!RpcOut_start(updateChannel->rpcOut)) {
994
Warning("%s: RpcOut_start() failed\n", __FUNCTION__);
995
RpcOut_Destruct(updateChannel->rpcOut);
999
return updateChannel;
1002
DynBuf_Destroy(&updateChannel->updates);
1003
vm_free(updateChannel);
1010
*-----------------------------------------------------------------------------
1012
* UnityUpdateChannelCleanup --
1014
* Cleanup the unity update channel.
1020
* RpcOut channel will be closed.
1021
* Memory will be freed.
1023
*-----------------------------------------------------------------------------
1027
UnityUpdateChannelCleanup(UnityUpdateChannel *updateChannel) // IN
1029
if (updateChannel && updateChannel->rpcOut) {
1030
RpcOut_stop(updateChannel->rpcOut);
1031
RpcOut_Destruct(updateChannel->rpcOut);
1032
updateChannel->rpcOut = NULL;
1034
DynBuf_Destroy(&updateChannel->updates); // Avoid double-free by guarding this as well
1035
vm_free(updateChannel);
1042
*-----------------------------------------------------------------------------
1046
* Prints a Unity update via debug output. NUL is represented as '!'.
1054
*-----------------------------------------------------------------------------
1058
DumpUpdate(UnityUpdateChannel *updateChannel) // IN
1063
len = updateChannel->updates.size;
1064
buf = reinterpret_cast<char*>(Util_SafeMalloc(len + 1));
1065
memcpy(buf, updateChannel->updates.data, len);
1067
for (i = 0 ; i < len; i++) {
1068
if (buf[i] == '\0') {
1073
Debug("%s: Sending update: %s\n", __FUNCTION__, buf);
1077
#endif // ifdef VMX86_DEVEL
1081
*-----------------------------------------------------------------------------
1083
* UnitySendUpdates --
1085
* Send a round of unity updates. The caller is responsible
1086
* for gathering updates into updateChannel->updates buffer prior to the
1087
* function call. This function should only be called if there's data
1088
* in the update buffer to avoid sending empty update string to the VMX.
1091
* TRUE if the update was sent,
1092
* FALSE if something went wrong (an invalid RPC channel, for example).
1097
*-----------------------------------------------------------------------------
1101
UnitySendUpdates(void *param) // IN
1103
char const *myReply;
1106
UnityUpdateChannel *updateChannel = reinterpret_cast<UnityUpdateChannel*>(param);
1108
ASSERT(updateChannel);
1109
ASSERT(updateChannel->rpcOut);
1111
/* Send 'tools.unity.push.update <updates>' to the VMX. */
1114
DumpUpdate(updateChannel);
1118
if (!RpcOut_send(updateChannel->rpcOut,
1119
(char *)DynBuf_Get(&updateChannel->updates),
1120
DynBuf_GetSize(&updateChannel->updates),
1121
&myReply, &myRepLen)) {
1124
* We could not send the RPC. If we haven't tried to reopen
1125
* the channel, try to reopen and resend. If we already
1126
* tried to resend, then it's time to give up. I hope that
1127
* trying to resend once is enough.
1132
Debug("%s: could not send rpc. Reopening channel.\n", __FUNCTION__);
1133
RpcOut_stop(updateChannel->rpcOut);
1134
if (!RpcOut_start(updateChannel->rpcOut)) {
1135
Debug("%s: could not reopen rpc channel. Exiting...\n", __FUNCTION__);
1141
Debug("%s: could not resend rpc. Giving up and exiting...\n", __FUNCTION__);
1147
* With the update queue sent, purge the DynBuf by trimming it to the length
1148
* of the command preamble.
1150
DynBuf_SetSize(&updateChannel->updates, updateChannel->cmdSize);
1157
*----------------------------------------------------------------------------
1159
* UnityTcloGetWindowContents --
1161
* RPC handler for 'unity.get.window.contents'. Suck the bits off the
1162
* window and return a .png image over the backdoor.
1165
* TRUE if everything is successful.
1171
*----------------------------------------------------------------------------
1175
UnityTcloGetWindowContents(RpcInData *data) // IN/OUT
1177
unsigned int window;
1178
unsigned int index = 0;
1179
DynBuf *imageData = &gTcloUpdate;
1183
/* Check our arguments. */
1192
if (!data->name || !data->args) {
1193
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1194
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1197
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1200
* Parse the command & window id.
1202
if (!StrUtil_GetNextIntToken((int32*) &window, &index, data->args, " ")) {
1203
Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
1204
return RPCIN_SETRETVALS(data,
1205
"failed: arguments. Expected \"windowId\"",
1209
Debug("%s: window %d\n", __FUNCTION__, window);
1212
* Read the contents of the window, compress it as a .png and
1213
* send the .png back to the vmx as the RPC result.
1215
DynBuf_SetSize(imageData, 0);
1216
if (!Unity_GetWindowContents(window, imageData, &width, &height)) {
1217
return RPCIN_SETRETVALS(data,
1218
"failed: Could not read window contents",
1222
data->result = (char *)DynBuf_Get(imageData);
1223
data->resultLen = DynBuf_GetSize(imageData);
1230
*----------------------------------------------------------------------------
1232
* UnityTcloGetIconData --
1234
* RPC handler for 'unity.get.icon.data'. Suck the bits off the
1235
* window and return a .png image over the backdoor.
1238
* TRUE if everything is successful.
1244
*----------------------------------------------------------------------------
1248
UnityTcloGetIconData(RpcInData *data) // IN/OUT
1250
UnityWindowId window;
1251
UnityIconType iconType;
1252
UnityIconSize iconSize;
1253
unsigned int dataOffset, dataLength;
1256
DynBuf *results = &gTcloUpdate, imageData;
1257
char bitmapData[1024];
1259
/* Check our arguments. */
1268
if (!data->name || !data->args) {
1269
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1270
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1273
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1276
* Parse the arguments.
1278
if ((sscanf(data->args, "%u %u %u %u %u",
1280
(unsigned int*) &iconType,
1284
|| (dataLength > UNITY_MAX_ICON_DATA_CHUNK)) {
1285
Debug("UnityTcloGetIconData: Invalid RPC arguments.\n");
1286
return RPCIN_SETRETVALS(data,
1287
"failed: arguments missing",
1291
Debug("%s: window %u iconType %u" \
1292
" iconSize %u dataOffset %u dataLength %u\n",
1294
window, iconType, iconSize, dataOffset, dataLength);
1297
* Retrieve part/all of the icon in PNG format.
1299
DynBuf_Init(&imageData);
1300
if (!Unity_GetIconData(window, iconType, iconSize,
1301
dataOffset, dataLength, &imageData, &fullLength)) {
1302
return RPCIN_SETRETVALS(data,
1303
"failed: Could not read icon data properly",
1308
DynBuf_SetSize(results, 0);
1309
retLength = DynBuf_GetSize(&imageData);
1310
retLength = MIN(retLength, UNITY_MAX_ICON_DATA_CHUNK);
1311
DynBuf_Append(results, bitmapData, Str_Snprintf(bitmapData,
1314
fullLength, retLength));
1315
DynBuf_Append(results, DynBuf_Get(&imageData), retLength);
1318
* Guarantee that the results have a trailing \0 in case anything does a strlen...
1320
DynBuf_AppendString(results, "");
1321
data->result = (char *)DynBuf_Get(results);
1322
data->resultLen = DynBuf_GetSize(results);
1323
DynBuf_Destroy(&imageData);
1330
*----------------------------------------------------------------------------
1332
* UnityTcloShowTaskbar --
1334
* RPC handler for 'unity.show.taskbar'.
1337
* TRUE if everything is successful.
1343
*----------------------------------------------------------------------------
1347
UnityTcloShowTaskbar(RpcInData *data) // IN/OUT
1350
unsigned int index = 0;
1352
/* Check our arguments. */
1361
if (!data->name || !data->args) {
1362
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1363
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1366
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1368
if (!StrUtil_GetNextUintToken(&command, &index, data->args, " ")) {
1369
Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
1370
return RPCIN_SETRETVALS(data,
1371
"Invalid arguments.",
1375
Debug("%s: command %d\n", __FUNCTION__, command);
1377
Unity_ShowTaskbar((command == 0) ? FALSE : TRUE);
1379
return RPCIN_SETRETVALS(data, "", TRUE);
1384
*----------------------------------------------------------------------------
1386
* UnityTcloMoveResizeWindow --
1388
* RPC handler for 'unity.window.move_resize'.
1391
* TRUE if everything is successful.
1393
* If successful adds null terminated strings for each output coordinates.
1398
*----------------------------------------------------------------------------
1402
UnityTcloMoveResizeWindow(RpcInData *data) // IN/OUT
1404
DynBuf *buf = &gTcloUpdate;
1405
UnityWindowId window;
1406
UnityRect moveResizeRect = {0};
1409
/* Check our arguments. */
1418
if (!data->name || !data->args) {
1419
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1420
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1423
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1425
if (sscanf(data->args, "%u %d %d %d %d",
1429
&moveResizeRect.width,
1430
&moveResizeRect.height) != 5) {
1431
Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
1432
return RPCIN_SETRETVALS(data,
1433
"Invalid arguments.",
1437
if (!Unity_MoveResizeWindow(window, &moveResizeRect)) {
1438
Debug("%s: Could not read window coordinates.\n", __FUNCTION__);
1439
return RPCIN_SETRETVALS(data,
1440
"Could not read window coordinates",
1445
* Send back the new (post move/resize operation) window coordinates.
1448
DynBuf_SetSize(buf, 0);
1449
Str_Sprintf(temp, sizeof temp, "%d %d %d %d", moveResizeRect.x,
1450
moveResizeRect.y, moveResizeRect.width, moveResizeRect.height);
1451
DynBuf_AppendString(buf, temp);
1454
* Write the final result into the result out parameters and return!
1457
data->result = (char *)DynBuf_Get(buf);
1458
data->resultLen = DynBuf_GetSize(buf);
1465
*----------------------------------------------------------------------------
1467
* UnityTcloSetDesktopConfig --
1469
* RPC handler for 'unity.set.desktop.config'. The RPC takes the form of:
1470
* {1,1} {1,2} {2,1} {2,2} 1
1471
* for a 2 x 2 virtual desktop where the upper right {1,2} is the currently
1475
* TRUE if everything is successful.
1479
* Might change virtual desktop configuration in the guest.
1481
*----------------------------------------------------------------------------
1485
UnityTcloSetDesktopConfig(RpcInData *data) // IN/OUT
1487
unsigned int index = 0;
1488
char *desktopStr = NULL;
1490
uint32 initialDesktopIndex = 0;
1491
UnityVirtualDesktopArray desktopConfig;
1493
memset(&desktopConfig, 0, sizeof desktopConfig);
1495
/* Check our arguments. */
1504
if (!data->name || !data->args) {
1505
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1506
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1509
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1511
if (data->argsSize == 0) {
1512
errorMsg = "Invalid arguments: desktop config is expected";
1516
/* Read the virtual desktop configuration. */
1517
while ((desktopStr = StrUtil_GetNextToken(&index, data->args, " ")) != NULL) {
1519
if (sscanf(desktopStr, "{%d,%d}",
1520
&desktopConfig.desktops[desktopConfig.desktopCount].x,
1521
&desktopConfig.desktops[desktopConfig.desktopCount].y) == 2) {
1522
if (desktopConfig.desktopCount >= MAX_VIRT_DESK - 1) {
1523
errorMsg = "Invalid arguments: too many desktops";
1526
desktopConfig.desktopCount++;
1527
} else if (sscanf(desktopStr, "%u", &initialDesktopIndex) == 1) {
1528
if (initialDesktopIndex >= desktopConfig.desktopCount) {
1529
errorMsg = "Invalid arguments: current desktop is out of bounds";
1532
/* All done with arguments at this point - stop processing */
1536
errorMsg = "Invalid arguments: invalid desktop config";
1544
* Call the platform specific function to set the desktop configuration.
1547
if (!Unity_SetDesktopConfig(&desktopConfig)) {
1548
errorMsg = "Could not set desktop configuration";
1552
if (!Unity_SetInitialDesktop(initialDesktopIndex)) {
1553
errorMsg = "Could not set initial desktop";
1557
return RPCIN_SETRETVALS(data,
1562
Debug("%s: %s\n", __FUNCTION__, errorMsg);
1564
return RPCIN_SETRETVALS(data,
1571
*----------------------------------------------------------------------------
1573
* UnityTcloSetDesktopActive --
1575
* RPC handler for 'unity.set.desktop.active'.
1578
* TRUE if everything is successful.
1582
* Might change the active virtual desktop in the guest.
1584
*----------------------------------------------------------------------------
1588
UnityTcloSetDesktopActive(RpcInData *data) // IN/OUT
1590
UnityDesktopId desktopId = 0;
1593
/* Check our arguments. */
1602
if (!data->name || !data->args) {
1603
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1604
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1607
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1609
if (Unity_IsActive() == FALSE) {
1610
errorMsg = "Unity not enabled - cannot change active desktop";
1614
if (sscanf(data->args, " %d", &desktopId) != 1) {
1615
errorMsg = "Invalid arguments: expected \"desktopId\"";
1620
* Call the platform specific function to set the desktop active.
1623
if (!Unity_SetDesktopActive(desktopId)) {
1624
errorMsg = "Could not set active desktop";
1628
return RPCIN_SETRETVALS(data,
1632
Debug("%s: %s\n", __FUNCTION__, errorMsg);
1633
return RPCIN_SETRETVALS(data,
1640
*----------------------------------------------------------------------------
1642
* UnityTcloSetWindowDesktop --
1644
* RPC handler for 'unity.set.window.desktop'.
1647
* TRUE if everything is successful.
1651
* Might change the active virtual desktop in the guest.
1653
*----------------------------------------------------------------------------
1657
UnityTcloSetWindowDesktop(RpcInData *data) // IN/OUT
1659
UnityWindowId windowId;
1660
uint32 desktopId = 0;
1663
/* Check our arguments. */
1672
if (!data->name || !data->args) {
1673
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1674
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1677
Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1679
if (Unity_IsActive() == FALSE) {
1680
errorMsg = "Unity not enabled - cannot set window desktop";
1684
if (sscanf(data->args, " %u %d", &windowId, &desktopId) != 2) {
1685
errorMsg = "Invalid arguments: expected \"windowId desktopId\"";
1690
* Call the platform specific function to move the window to the
1691
* specified desktop.
1694
if (!Unity_SetWindowDesktop(windowId, desktopId)) {
1695
errorMsg = "Could not move the window to the desktop";
1699
return RPCIN_SETRETVALS(data,
1703
Debug("%s: %s\n", __FUNCTION__, errorMsg);
1704
return RPCIN_SETRETVALS(data,
1711
*----------------------------------------------------------------------------
1713
* UnityTcloSetUnityOptions --
1715
* Set the Unity options - must be be called before entering Unity mode.
1718
* TRUE if RPC was succesfully handled.
1724
*----------------------------------------------------------------------------
1728
UnityTcloSetUnityOptions(RpcInData *data)
1731
UnityOptions optionsMsg;
1733
memset(&optionsMsg, 0, sizeof optionsMsg);
1735
/* Check our arguments. */
1744
if (!data->name || !data->args) {
1745
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1746
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1749
Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
1750
__FUNCTION__, data->name, data->argsSize);
1753
* Deserialize the XDR data. Note that the data begins with args + 1 since
1754
* there is a space between the RPC name and the XDR serialization.
1756
if (!XdrUtil_Deserialize((char *)data->args + 1, data->argsSize - 1,
1757
(void *)xdr_UnityOptions, &optionsMsg)) {
1758
Debug("%s: Failed to deserialize data\n", __FUNCTION__);
1759
ret = RPCIN_SETRETVALS(data, "Failed to deserialize data.", FALSE);
1763
Unity_SetUnityOptions(optionsMsg.UnityOptions_u.unityOptionsV1->featureMask);
1765
ret = RPCIN_SETRETVALS(data,
1769
VMX_XDR_FREE(xdr_UnityOptions, &optionsMsg);
1776
*----------------------------------------------------------------------------
1778
* UnityTcloRequestWindowContents --
1780
* Request the window contents for a set of windows.
1783
* TRUE if all the window IDs are valid.
1789
*----------------------------------------------------------------------------
1793
UnityTcloRequestWindowContents(RpcInData *data) // IN
1796
UnityWindowContentsRequest requestMsg;
1797
UnityWindowContentsRequestV1 *requestV1 = NULL;
1798
memset(&requestMsg, 0, sizeof requestMsg);
1800
/* Check our arguments. */
1809
if (!data->name || !data->args) {
1810
Debug("%s: Invalid arguments.\n", __FUNCTION__);
1811
return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1814
Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
1815
__FUNCTION__, data->name, data->argsSize);
1818
* Deserialize the XDR data. Note that the data begins with args + 1 since
1819
* there is a space between the RPC name and the XDR serialization.
1821
if (!XdrUtil_Deserialize((char *)data->args + 1, data->argsSize - 1,
1822
(void *)xdr_UnityWindowContentsRequest, &requestMsg)) {
1823
Debug("%s: Failed to deserialize data\n", __FUNCTION__);
1824
ret = RPCIN_SETRETVALS(data, "Failed to deserialize data.", FALSE);
1828
if (requestMsg.ver != UNITY_WINDOW_CONTENTS_V1) {
1829
Debug("%s: Unexpected XDR version = %d\n", __FUNCTION__, requestMsg.ver);
1833
requestV1 = requestMsg.UnityWindowContentsRequest_u.requestV1;
1836
* Call the platform implementation of the RPC handler.
1838
if (!Unity_RequestWindowContents(requestV1->windowID.windowID_val,
1839
requestV1->windowID.windowID_len)) {
1840
ret = RPCIN_SETRETVALS(data, "Invalid list of windows.", FALSE);
1844
ret = RPCIN_SETRETVALS(data,
1848
VMX_XDR_FREE(xdr_UnityWindowContentsRequest, &requestMsg);
1855
*----------------------------------------------------------------------------
1857
* UnityUpdateState --
1859
* Communicate unity state changes to vmx.
1862
* TRUE if everything is successful.
1868
*----------------------------------------------------------------------------
1872
UnityUpdateState(void)
1876
UnityActiveProto message;
1879
if (DynXdr_Create(&xdrs) == NULL) {
1883
val = Str_Asprintf(NULL, "%s ", UNITY_RPC_UNITY_ACTIVE);
1884
if (!val || !DynXdr_AppendRaw(&xdrs, val, strlen(val))) {
1885
Debug("%s: Failed to create state string.\n", __FUNCTION__);
1889
memset(&message, 0, sizeof message);
1890
message.ver = UNITY_ACTIVE_V1;
1891
message.UnityActiveProto_u.unityActive = Unity_IsActive();
1892
if (!xdr_UnityActiveProto(&xdrs, &message)) {
1893
Debug("%s: Failed to append message content.\n", __FUNCTION__);
1898
if (!RpcOut_SendOneRaw(DynXdr_Get(&xdrs), xdr_getpos(&xdrs), NULL, NULL)) {
1899
Debug("%s: Failed to send Unity state RPC.\n", __FUNCTION__);
1902
Debug("%s: success\n", __FUNCTION__);
1906
DynXdr_Destroy(&xdrs, TRUE);
1912
*----------------------------------------------------------------------------
1914
* UnityXdrRequestOperation --
1916
* XDR encoder function for UnityRequestOperation.
1918
* See UnityXdrSendRpc().
1921
* Returns true if the XDR struct was encoded successfully.
1925
*------------------------------------------------------------------------------
1929
UnityXdrRequestOperation(XDR *xdrs, // IN
1934
return xdr_UnityRequestOperation(xdrs, (UnityRequestOperation *) arg);
1939
*------------------------------------------------------------------------------
1941
* UnitySendRequestMinimizeOperation --
1943
* Send a request for a minimize operation to the host.
1946
* TRUE if everything is successful.
1952
*----------------------------------------------------------------------------
1956
UnitySendRequestMinimizeOperation(UnityWindowId windowId, // IN
1957
uint32 sequence) // IN
1960
UnityRequestOperation msg;
1961
UnityRequestOperationV1 v1;
1962
memset(&msg, 0, sizeof msg);
1963
memset(&v1, 0, sizeof v1);
1965
Debug("%s: Enter.\n", __FUNCTION__);
1967
v1.windowId = windowId;
1968
v1.sequence = sequence;
1969
v1.details.op = MINIMIZE;
1971
msg.ver = UNITY_OP_V1;
1972
msg.UnityRequestOperation_u.unityRequestOpV1 = &v1;
1974
ret = UnityXdrSendRpc(UNITY_RPC_REQUEST_OPERATION,
1975
&UnityXdrRequestOperation,
1978
Debug("%s: Exit.\n", __FUNCTION__);
1984
*----------------------------------------------------------------------------
1986
* UnitySendWindowContents --
1988
* Sends the content of a window to the host, as a PNG encoded image. If the
1989
* image is larger than the maximum size of a GuestMsg, this function breaks
1990
* the image down into a number of chunks, then transfers each of the chunks
1991
* independently. See guest_msg_def.h and unity.x.
1994
* Returns true if the image was transferred successfully.
1999
*------------------------------------------------------------------------------
2003
UnitySendWindowContents(UnityWindowId windowID, // IN
2004
uint32 imageWidth, // IN
2005
uint32 imageHeight, // IN
2006
const char *imageData, // IN
2007
uint32 imageLength) // IN
2010
uint32 count = 0; /* count of chunks sent */
2011
uint32 len = 0; /* length of the next chunk */
2012
const char *readptr = imageData; /* pointer to start of next chunk in imageData */
2014
ASSERT(imageWidth > 0);
2015
ASSERT(imageHeight > 0);
2016
ASSERT(imageLength > 0);
2019
Debug("%s: Enter.\n", __FUNCTION__);
2020
Debug("%s: Sending contents of window 0x%x.\n", __FUNCTION__, windowID);
2021
Debug("%s: Contents are (%u x %u) image, %u bytes.\n", __FUNCTION__,
2022
imageWidth, imageHeight, imageLength);
2024
/* Send the unity.window.contents.start RPC to the host. */
2025
if (!UnitySendWindowContentsStart(windowID,
2032
/* Send the image data. */
2033
while (imageLength > 0) {
2035
* Get the length of the next chunk to send, up to a maximum of
2036
* UNITY_WINDOW_CONTENTS_MAX_CHUNK_SIZE bytes.
2038
len = MIN(UNITY_WINDOW_CONTENTS_MAX_CHUNK_SIZE, imageLength);
2040
Debug("%s: Sending chunk %u at offset 0x%p, size %u.\n", __FUNCTION__,
2041
count, readptr, len);
2043
/* Send the next chunk to the host. */
2044
if (!UnitySendWindowContentsChunk(windowID, count, readptr, len)) {
2053
/* Send the unity.window.contents.end RPC to the host. */
2054
if (!UnitySendWindowContentsEnd(windowID)) {
2066
*------------------------------------------------------------------------------
2068
* UnityXdrEncodeWindowContentsStart --
2070
* XDR encoder function for UnityWindowContentsStart.
2072
* See UnityXdrSendRpc().
2075
* Returns true if the XDR struct was encoded successfully.
2079
*------------------------------------------------------------------------------
2083
UnityXdrEncodeWindowContentsStart(XDR *xdrs,
2088
return xdr_UnityWindowContentsStart(xdrs, (UnityWindowContentsStart *) arg);
2093
*------------------------------------------------------------------------------
2095
* UnitySendWindowContentsStart --
2097
* Sends the unity.window.contents.start RPC to the host.
2100
* Returns true if the RPC was sent successfully.
2105
*------------------------------------------------------------------------------
2109
UnitySendWindowContentsStart(UnityWindowId windowID, // IN
2110
uint32 imageWidth, // IN
2111
uint32 imageHeight, // IN
2112
uint32 imageLength) // IN
2115
UnityWindowContentsStart msg;
2116
UnityWindowContentsStartV1 v1;
2118
memset(&msg, 0, sizeof msg);
2119
memset(&v1, 0, sizeof v1);
2121
Debug("%s: Enter.\n", __FUNCTION__);
2123
v1.windowID = windowID;
2124
v1.imageWidth = imageWidth;
2125
v1.imageHeight = imageHeight;
2126
v1.imageLength = imageLength;
2128
msg.ver = UNITY_WINDOW_CONTENTS_V1;
2129
msg.UnityWindowContentsStart_u.startV1 = &v1;
2131
ret = UnityXdrSendRpc(UNITY_RPC_WINDOW_CONTENTS_START,
2132
&UnityXdrEncodeWindowContentsStart,
2135
Debug("%s: Exit.\n", __FUNCTION__);
2141
*------------------------------------------------------------------------------
2143
* UnityXdrEncodeWindowContentsChunk --
2145
* XDR encoder function for UnityWindowContentsChunk.
2147
* See UnityXdrSendRpc().
2150
* Returns true if the XDR struct was encoded successfully.
2154
*------------------------------------------------------------------------------
2158
UnityXdrEncodeWindowContentsChunk(XDR *xdrs,
2163
return xdr_UnityWindowContentsChunk(xdrs, (UnityWindowContentsChunk *) arg);
2168
*------------------------------------------------------------------------------
2170
* UnitySendWindowContentsChunk --
2172
* Sends a unity.window.contents.chunk RPC to the host.
2175
* Returns true if the RPC was sent successfully.
2180
*------------------------------------------------------------------------------
2184
UnitySendWindowContentsChunk(UnityWindowId windowID,
2190
UnityWindowContentsChunk msg;
2191
UnityWindowContentsChunkV1 v1;
2192
memset(&msg, 0, sizeof msg);
2193
memset(&v1, 0, sizeof v1);
2195
Debug("%s: Enter.\n", __FUNCTION__);
2197
v1.windowID = windowID;
2198
v1.chunkID = chunkID;
2199
v1.data.data_val = (char *) data;
2200
v1.data.data_len = len;
2202
msg.ver = UNITY_WINDOW_CONTENTS_V1;
2203
msg.UnityWindowContentsChunk_u.chunkV1 = &v1;
2205
ret = UnityXdrSendRpc(UNITY_RPC_WINDOW_CONTENTS_CHUNK,
2206
&UnityXdrEncodeWindowContentsChunk,
2209
Debug("%s: Exit.\n", __FUNCTION__);
2215
*------------------------------------------------------------------------------
2217
* UnityXdrEncodeWindowContentsEnd --
2219
* XDR encoder function for UnityWindowContentsEnd.
2222
* Returns true if the XDR struct was encoded successfully.
2226
*------------------------------------------------------------------------------
2230
UnityXdrEncodeWindowContentsEnd(XDR *xdrs,
2235
return xdr_UnityWindowContentsEnd(xdrs, (UnityWindowContentsEnd*) arg);
2240
*------------------------------------------------------------------------------
2242
* UnitySendWindowContentsEnd --
2244
* Sends a unity.window.contents.end RPC to the host.
2247
* Returns true if the RPC was sent successfully.
2252
*------------------------------------------------------------------------------
2256
UnitySendWindowContentsEnd(UnityWindowId windowID)
2259
UnityWindowContentsEnd msg;
2260
UnityWindowContentsEndV1 v1;
2261
memset(&msg, sizeof msg, 0);
2262
memset(&v1, sizeof v1, 0);
2264
Debug("%s: Enter.\n", __FUNCTION__);
2266
v1.windowID = windowID;
2268
msg.ver = UNITY_WINDOW_CONTENTS_V1;
2269
msg.UnityWindowContentsEnd_u.endV1 = &v1;
2271
ret = UnityXdrSendRpc(UNITY_RPC_WINDOW_CONTENTS_END,
2272
&UnityXdrEncodeWindowContentsEnd,
2275
Debug("%s: Exit.\n", __FUNCTION__);
2281
*------------------------------------------------------------------------------
2283
* UnityXdrSendRpc --
2285
* Sends an RPC with XDR-serialized arguments to the host. The provided
2286
* encodeFn will be called to perform XDR encoding of the RPC, with the XDR
2287
* struct and the provided data pointer as its parameters.
2290
* True if the RPC was sent successfully.
2295
*------------------------------------------------------------------------------
2299
UnityXdrSendRpc(const char *rpcName,
2300
UnityXdrEncodeFunc encodeFn,
2305
memset(&xdrs, 0, sizeof xdrs);
2309
Debug("%s: Enter.\n", __FUNCTION__);
2311
if (!DynXdr_Create(&xdrs)) {
2312
Debug("%s: Failed to create DynXdr.\n", __FUNCTION__);
2316
if (!DynXdr_AppendRaw(&xdrs, rpcName, strlen(rpcName))) {
2317
Debug("%s: Failed to append RPC name to DynXdr.\n", __FUNCTION__);
2318
goto dynxdr_destroy;
2321
if (!DynXdr_AppendRaw(&xdrs, " ", 1)) {
2322
Debug("%s: Failed to append space to DynXdr.\n", __FUNCTION__);
2323
goto dynxdr_destroy;
2326
if (!(*encodeFn)(&xdrs, data)) {
2327
Debug("%s: Failed to serialize RPC data.\n", __FUNCTION__);
2328
goto dynxdr_destroy;
2331
if (!RpcOut_SendOneRaw(DynXdr_Get(&xdrs), xdr_getpos(&xdrs), NULL, NULL)) {
2332
Debug("%s: Failed to send RPC.\n", __FUNCTION__);
2333
goto dynxdr_destroy;
2339
DynXdr_Destroy(&xdrs, TRUE);
2342
Debug("%s: Exit.\n", __FUNCTION__);
2348
*----------------------------------------------------------------------------
2350
* UnityBuildUpdates --
2352
* Gather a round of Unity Updates from the Window Tracker. Initialize our
2353
* dynbuf used to hold the updates, call to get the updates into our channel
2354
* and add the terminating NULL. If updates were added to the buffer send them
2358
* TRUE if updates were added to the buffer and succesfully sent to the host.
2361
* DynBuf is updated with serialized form of the updates.
2363
*----------------------------------------------------------------------------
2367
UnityBuildUpdates(void *param, // IN
2371
UnityUpdateChannel *updateChannel = reinterpret_cast<UnityUpdateChannel*>(param);
2373
ASSERT(updateChannel);
2375
DynBuf_SetSize(&updateChannel->updates, updateChannel->cmdSize);
2376
Unity_GetUpdates(flags);
2378
* Write the final '\0' to the DynBuf to signal that we're all out of
2381
DynBuf_AppendString(&updateChannel->updates, "");
2384
* If there are no updates, Unity_GetUpdates appended an empty string, i.e. null.
2387
if (DynBuf_GetSize(&updateChannel->updates) > updateChannel->cmdSize + 1) {
2388
if (!UnitySendUpdates(updateChannel)) {
2397
*------------------------------------------------------------------------------
2399
* UnityShouldShowTaskbar --
2401
* Sends an RPC to retrieve whether the guest should show the taskbar and
2402
* returns the value.
2405
* TRUE if the taskbar should be visible.
2410
*------------------------------------------------------------------------------
2414
UnityShouldShowTaskbar()
2418
Bool showTaskbar = FALSE;
2420
if (!RpcOut_sendOne(&reply, &replyLen, UNITY_RPC_VMX_SHOW_TASKBAR)) {
2421
Debug("%s: could not get the VMX show taskbar setting, assuming FALSE\n",
2423
showTaskbar = FALSE;
2427
if (StrUtil_StrToUint(&value, reply)) {
2428
showTaskbar = (value == 0) ? FALSE : TRUE;
2430
showTaskbar = FALSE;
2436
} /* namespace tools */ } /* namespace vmware */