~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/unity/unityTclo.cpp

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************
2
 
 * Copyright (C) 2010 VMware, Inc. All rights reserved.
3
 
 *
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.
7
 
 *
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.
12
 
 *
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.
16
 
 *
17
 
 *********************************************************/
18
 
 
19
 
/**
20
 
 * @file unityTclo.cpp
21
 
 *
22
 
 *    Unity: Guest window manager integration service.
23
 
 *
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.
26
 
 *
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).
30
 
 *
31
 
 * @note Looking for the old "unity.get.update" return syntax?  See @ref
32
 
 * UNITY_RPC_GET_UPDATE and @ref UnityGetUpdateReturn instead.
33
 
 *
34
 
 * @sa
35
 
 *    @li UnityRpcHG
36
 
 *    @li UnityRpcGH
37
 
 */
38
 
 
39
 
#include "vmware/tools/plugin.h"
40
 
 
41
 
extern "C" {
42
 
   #include "vmware.h"
43
 
   #include "conf.h"
44
 
   #include "debug.h"
45
 
   #include "dynxdr.h"
46
 
   #include "guestrpc/unity.h"
47
 
   #include "guestrpc/unityActive.h"
48
 
   #include "rpcin.h"
49
 
   #include "rpcout.h"
50
 
   #include "strutil.h"
51
 
#if defined(OPEN_VM_TOOLS)
52
 
   #include "unitylib/unity.h"
53
 
#else
54
 
   #include "unity.h"
55
 
#endif // OPEN_VM_TOOLS
56
 
   #include "unityDebug.h"
57
 
   #include "xdrutil.h"
58
 
};
59
 
 
60
 
#include "unityPlugin.h"
61
 
#include "unityTclo.h"
62
 
 
63
 
namespace vmware { namespace tools {
64
 
 
65
 
/**
66
 
 * Container used to store and send Unity updates.
67
 
 */
68
 
 
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. */
74
 
   RpcOut *rpcOut;
75
 
} UnityTCLOUpdateChannel;
76
 
 
77
 
/*
78
 
 * Helper Functions
79
 
 */
80
 
 
81
 
static Bool UnityUpdateState(void);
82
 
 
83
 
/* Sends the unity.window.contents.start RPC to the host. */
84
 
Bool UnitySendWindowContentsStart(UnityWindowId window,
85
 
                                  uint32 width,
86
 
                                  uint32 height,
87
 
                                  uint32 length);
88
 
 
89
 
/* Sends the unity.window.contents.chunk RPC to the host. */
90
 
Bool UnitySendWindowContentsChunk(UnityWindowId window,
91
 
                                  uint32 seq,
92
 
                                  const char *data,
93
 
                                  uint32 length);
94
 
 
95
 
/* Sends the unity.window.contents.end RPC to the host. */
96
 
Bool UnitySendWindowContentsEnd(UnityWindowId window);
97
 
 
98
 
/*
99
 
 * Callback function used by UnityXdrSendRpc() to encode XDR-serialized
100
 
 * arguments.
101
 
 */
102
 
typedef Bool(*UnityXdrEncodeFunc)(XDR*,void*);
103
 
 
104
 
/*
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
107
 
 * XDR encoding.
108
 
 */
109
 
Bool UnityXdrSendRpc(const char *rpcName, UnityXdrEncodeFunc encodeFn, void *arg);
110
 
 
111
 
/*
112
 
 * XXX:
113
 
 * According to Adar:
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
117
 
 *     results."
118
 
 *
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.
122
 
 */
123
 
 
124
 
static DynBuf gTcloUpdate;
125
 
 
126
 
 
127
 
/*
128
 
 *----------------------------------------------------------------------------
129
 
 *
130
 
 * UnityTcloInit --
131
 
 *
132
 
 *     Initialize the global state (a Dynbuf) used to handle the TCLO parsing
133
 
 *     and dispatch.
134
 
 *
135
 
 * Results:
136
 
 *     None.
137
 
 *
138
 
 * Side effects:
139
 
 *     None.
140
 
 *
141
 
 *----------------------------------------------------------------------------
142
 
 */
143
 
 
144
 
void
145
 
UnityTcloInit()
146
 
{
147
 
   /*
148
 
    * Init our global dynbuf used to send results back.
149
 
    */
150
 
   DynBuf_Init(&gTcloUpdate);
151
 
 
152
 
}
153
 
 
154
 
 
155
 
/*
156
 
 *----------------------------------------------------------------------------
157
 
 *
158
 
 * UnityTcloCleanup --
159
 
 *
160
 
 *     Cleanup the global state (a Dynbuf) used to handle the TCLO parsing
161
 
 *     and dispatch.
162
 
 *
163
 
 * Results:
164
 
 *     None.
165
 
 *
166
 
 * Side effects:
167
 
 *     None.
168
 
 *
169
 
 *----------------------------------------------------------------------------
170
 
 */
171
 
 
172
 
void
173
 
UnityTcloCleanup()
174
 
{
175
 
   DynBuf_Destroy(&gTcloUpdate);
176
 
}
177
 
 
178
 
 
179
 
/*
180
 
 *----------------------------------------------------------------------------
181
 
 *
182
 
 * UnityTcloEnter --
183
 
 *
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).
191
 
 *
192
 
 * Results:
193
 
 *     TRUE if helper threads were started.
194
 
 *     FALSE otherwise.
195
 
 *
196
 
 * Side effects:
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.
200
 
 *
201
 
 *----------------------------------------------------------------------------
202
 
 */
203
 
 
204
 
gboolean
205
 
UnityTcloEnter(RpcInData *data)         //  IN/OUT
206
 
{
207
 
   /* Check our arguments. */
208
 
   ASSERT(data);
209
 
   if (!data) {
210
 
      return FALSE;
211
 
   }
212
 
 
213
 
   Debug("%s\n", __FUNCTION__);
214
 
 
215
 
   if (!Unity_Enter()) {
216
 
      return RPCIN_SETRETVALS(data, "Could not enter unity", FALSE);
217
 
   }
218
 
 
219
 
   UnityUpdateState();
220
 
 
221
 
   return RPCIN_SETRETVALS(data, "", TRUE);
222
 
}
223
 
 
224
 
 
225
 
/*
226
 
 *----------------------------------------------------------------------------
227
 
 *
228
 
 * UnityTcloExit --
229
 
 *
230
 
 *     RPC handler for 'unity.exit'.
231
 
 *
232
 
 * Results:
233
 
 *     Always TRUE.
234
 
 *
235
 
 * Side effects:
236
 
 *     Same as side effects of Unity_Exit().
237
 
 *
238
 
 *----------------------------------------------------------------------------
239
 
 */
240
 
 
241
 
gboolean
242
 
UnityTcloExit(RpcInData *data)   // IN/OUT
243
 
{
244
 
   /* Check our arguments. */
245
 
   ASSERT(data);
246
 
   if (!data) {
247
 
      return FALSE;
248
 
   }
249
 
 
250
 
   Debug("UnityTcloExit.\n");
251
 
 
252
 
   Unity_Exit();
253
 
 
254
 
   UnityUpdateState();
255
 
   return RPCIN_SETRETVALS(data, "", TRUE);
256
 
}
257
 
 
258
 
 
259
 
/*
260
 
 *----------------------------------------------------------------------------
261
 
 *
262
 
 * UnityTcloGetWindowPath --
263
 
 *
264
 
 *      RPC handler for UNITY_RPC_GET_WINDOW_PATH.
265
 
 *
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.
271
 
 *
272
 
 * Results:
273
 
 *     TRUE if everything is successful.
274
 
 *     FALSE otherwise.
275
 
 *
276
 
 * Side effects:
277
 
 *     None.
278
 
 *
279
 
 *----------------------------------------------------------------------------
280
 
 */
281
 
 
282
 
gboolean
283
 
UnityTcloGetWindowPath(RpcInData *data)   // IN/OUT
284
 
{
285
 
   UnityWindowId window;
286
 
   DynBuf windowPathUtf8;
287
 
   DynBuf execPathUtf8;
288
 
 
289
 
   unsigned int index = 0;
290
 
   Bool ret = TRUE;
291
 
 
292
 
   /* Check our arguments. */
293
 
   ASSERT(data);
294
 
   if (!data) {
295
 
      return FALSE;
296
 
   }
297
 
 
298
 
   ASSERT(data->name);
299
 
   ASSERT(data->args);
300
 
 
301
 
   if (!data->name || !data->args) {
302
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
303
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
304
 
   }
305
 
 
306
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
307
 
 
308
 
   /* Parse the command & window id.*/
309
 
 
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\"",
314
 
                              FALSE);
315
 
   }
316
 
 
317
 
   Debug("%s: window %d\n", __FUNCTION__, window);
318
 
 
319
 
   /*
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.
323
 
    */
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",
332
 
                             FALSE);
333
 
      goto exit;
334
 
   }
335
 
 
336
 
   /*
337
 
    * Construct the buffer holding the result. Note that we need to use gTcloUpdate
338
 
    * here to avoid leaking during the RPC handler.
339
 
    */
340
 
   DynBuf_Copy(&windowPathUtf8, &gTcloUpdate);
341
 
   DynBuf_Append(&gTcloUpdate, DynBuf_Get(&execPathUtf8), DynBuf_GetSize(&execPathUtf8));
342
 
 
343
 
   /*
344
 
    * Write the final result into the result out parameters and return!
345
 
    */
346
 
   data->result = (char *)DynBuf_Get(&gTcloUpdate);
347
 
   data->resultLen = DynBuf_GetSize(&gTcloUpdate);
348
 
 
349
 
exit:
350
 
   DynBuf_Destroy(&windowPathUtf8);
351
 
   DynBuf_Destroy(&execPathUtf8);
352
 
   return ret;
353
 
}
354
 
 
355
 
 
356
 
/*
357
 
 *----------------------------------------------------------------------------
358
 
 *
359
 
 * UnityTcloWindowCommand --
360
 
 *
361
 
 *     RPC handler for 'unity.window.*' (excluding 'unity.window.settop')
362
 
 *
363
 
 * Results:
364
 
 *     TRUE if everything is successful.
365
 
 *     FALSE otherwise.
366
 
 *
367
 
 * Side effects:
368
 
 *     None.
369
 
 *
370
 
 *----------------------------------------------------------------------------
371
 
 */
372
 
 
373
 
gboolean
374
 
UnityTcloWindowCommand(RpcInData *data)   // IN/OUT
375
 
{
376
 
   UnityWindowId window;
377
 
   unsigned int index = 0;
378
 
 
379
 
   /* Check our arguments. */
380
 
   ASSERT(data);
381
 
   if (!data) {
382
 
      return FALSE;
383
 
   }
384
 
 
385
 
   ASSERT(data->name);
386
 
   ASSERT(data->args);
387
 
 
388
 
   if (!data->name || !data->args) {
389
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
390
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
391
 
   }
392
 
 
393
 
   Debug("UnityTcloWindowCommand: name:%s args:'%s'\n", data->name, data->args);
394
 
 
395
 
   /* Parse the command & window id.*/
396
 
 
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\"",
401
 
                              FALSE);
402
 
 
403
 
   }
404
 
 
405
 
   Debug("%s: %s window %d\n", __FUNCTION__, data->name, window);
406
 
 
407
 
   if (!Unity_WindowCommand(window, data->name)) {
408
 
      return RPCIN_SETRETVALS(data,
409
 
                             "Could not execute window command",
410
 
                             FALSE);
411
 
   } else {
412
 
      return RPCIN_SETRETVALS(data, "", TRUE);
413
 
   }
414
 
}
415
 
 
416
 
 
417
 
/*
418
 
 *----------------------------------------------------------------------------
419
 
 *
420
 
 * UnityTcloSetDesktopWorkArea --
421
 
 *
422
 
 *     RPC handler for 'unity.desktop.work_area.set'.
423
 
 *
424
 
 * Results:
425
 
 *     TRUE if everything is successful.
426
 
 *     FALSE otherwise.
427
 
 *
428
 
 * Side effects:
429
 
 *     None.
430
 
 *
431
 
 *----------------------------------------------------------------------------
432
 
 */
433
 
 
434
 
gboolean
435
 
UnityTcloSetDesktopWorkArea(RpcInData *data)    // IN/OUT
436
 
{
437
 
   Bool success = FALSE;
438
 
   const char *argList;
439
 
   unsigned int count;
440
 
   unsigned int i;
441
 
   UnityRect *workAreas = NULL;
442
 
 
443
 
   /* Check our arguments. */
444
 
   ASSERT(data);
445
 
   if (!data) {
446
 
      return FALSE;
447
 
   }
448
 
 
449
 
   ASSERT(data->name);
450
 
   ASSERT(data->args);
451
 
 
452
 
   if (!data->name || !data->args) {
453
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
454
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
455
 
   }
456
 
 
457
 
   /*
458
 
    * The argument string will look something like:
459
 
    *   <count> [ , <x> <y> <w> <h> ] * count.
460
 
    *
461
 
    * e.g.
462
 
    *    3 , 0 0 640 480 , 640 0 800 600 , 0 480 640 480
463
 
    */
464
 
 
465
 
   if (sscanf(data->args, "%u", &count) != 1) {
466
 
      return RPCIN_SETRETVALS(data,
467
 
                              "Invalid arguments. Expected \"count\"",
468
 
                              FALSE);
469
 
   }
470
 
 
471
 
   if (count != 0) {
472
 
      workAreas = (UnityRect *)malloc(sizeof *workAreas * count);
473
 
      if (!workAreas) {
474
 
         RPCIN_SETRETVALS(data,
475
 
                          "Failed to alloc buffer for work areas",
476
 
                          FALSE);
477
 
         goto out;
478
 
      }
479
 
   }
480
 
 
481
 
   for (argList = data->args, i = 0; i < count; i++) {
482
 
      argList = strchr(argList, ',');
483
 
      if (!argList) {
484
 
         RPCIN_SETRETVALS(data,
485
 
                          "Expected comma separated display list",
486
 
                          FALSE);
487
 
         goto out;
488
 
      }
489
 
      argList++; /* Skip past the , */
490
 
 
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",
496
 
                          FALSE);
497
 
         goto out;
498
 
      }
499
 
 
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);
503
 
         goto out;
504
 
      }
505
 
   }
506
 
 
507
 
   if (!Unity_SetDesktopWorkAreas(workAreas, count)) {
508
 
      RPCIN_SETRETVALS(data,
509
 
                       "Unity_SetDesktopWorkAreas failed",
510
 
                       FALSE);
511
 
      goto out;
512
 
   }
513
 
 
514
 
   success = RPCIN_SETRETVALS(data, "", TRUE);
515
 
 
516
 
out:
517
 
   free(workAreas);
518
 
   return success;
519
 
}
520
 
 
521
 
 
522
 
/*
523
 
 *----------------------------------------------------------------------------
524
 
 *
525
 
 * UnityTcloSetTopWindowGroup --
526
 
 *
527
 
 *     RPC handler for 'unity.window.settop'.
528
 
 *
529
 
 * Results:
530
 
 *     TRUE if everything is successful.
531
 
 *     FALSE otherwise.
532
 
 *
533
 
 * Side effects:
534
 
 *     None.
535
 
 *
536
 
 *----------------------------------------------------------------------------
537
 
 */
538
 
 
539
 
gboolean
540
 
UnityTcloSetTopWindowGroup(RpcInData *data)  // IN/OUT
541
 
{
542
 
   UnityWindowId window;
543
 
   unsigned int index = 0;
544
 
   unsigned int windowCount = 0;
545
 
   UnityWindowId windows[UNITY_MAX_SETTOP_WINDOW_COUNT];
546
 
 
547
 
   /* Check our arguments. */
548
 
   ASSERT(data);
549
 
   if (!data) {
550
 
      return FALSE;
551
 
   }
552
 
 
553
 
   ASSERT(data->name);
554
 
   ASSERT(data->args);
555
 
 
556
 
   if (!data->name || !data->args) {
557
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
558
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
559
 
   }
560
 
 
561
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
562
 
 
563
 
   /* Parse the command & window ids.*/
564
 
 
565
 
   while (StrUtil_GetNextUintToken(&window, &index, data->args, " ")) {
566
 
      windows[windowCount] = window;
567
 
      windowCount++;
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",
572
 
                                 FALSE);
573
 
      }
574
 
   }
575
 
 
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",
580
 
                              FALSE);
581
 
   }
582
 
 
583
 
   if (!Unity_SetTopWindowGroup(windows, windowCount)) {
584
 
      return RPCIN_SETRETVALS(data,
585
 
                              "Could not execute window command",
586
 
                              FALSE);
587
 
   }
588
 
 
589
 
   return RPCIN_SETRETVALS(data, "", TRUE);
590
 
}
591
 
 
592
 
 
593
 
/*
594
 
 *----------------------------------------------------------------------------
595
 
 *
596
 
 * UnityTcloGetUpdate --
597
 
 *
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
601
 
 *     back to the VMX.
602
 
 *
603
 
 * Results:
604
 
 *     None.
605
 
 *
606
 
 * Side effects:
607
 
 *     Clearly.
608
 
 *
609
 
 *----------------------------------------------------------------------------
610
 
 */
611
 
 
612
 
gboolean
613
 
UnityTcloGetUpdate(RpcInData *data)    // IN/OUT
614
 
{
615
 
   Bool incremental = FALSE;
616
 
 
617
 
   /* Check our arguments. */
618
 
   ASSERT(data);
619
 
   if (!data) {
620
 
      return FALSE;
621
 
   }
622
 
 
623
 
   ASSERT(data->name);
624
 
   ASSERT(data->args);
625
 
 
626
 
   if (!data->name || !data->args) {
627
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
628
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
629
 
   }
630
 
 
631
 
   Debug("%s: name:%s args:'%s'", __FUNCTION__, data->name, data->args);
632
 
 
633
 
   /*
634
 
    * Specify incremental or non-incremetal updates based on whether or
635
 
    * not the client set the "incremental" arg.
636
 
    */
637
 
   if (strstr(data->name, "incremental")) {
638
 
      incremental = TRUE;
639
 
   }
640
 
 
641
 
   /*
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.)
645
 
    */
646
 
   Unity_GetUpdate(incremental);
647
 
 
648
 
   /*
649
 
    * To maintain compatibility, we'll return a successful but empty response.
650
 
    */
651
 
   data->result = "";
652
 
   data->resultLen = 0;
653
 
 
654
 
   /*
655
 
    * Give the debugger a crack to do something interesting at this point
656
 
    *
657
 
    * XXX Not sure if this is worth keeping around since this routine no
658
 
    * longer returns updates directly.
659
 
    */
660
 
   UnityDebug_OnUpdate();
661
 
 
662
 
   return TRUE;
663
 
}
664
 
 
665
 
 
666
 
/*
667
 
 *----------------------------------------------------------------------------
668
 
 *
669
 
 * UnityTcloConfirmOperation --
670
 
 *
671
 
 *     RPC handler for 'unity.operation.confirm'.
672
 
 *
673
 
 * Results:
674
 
 *     TRUE if the confirmation could be handled sucessfully.
675
 
 *     FALSE otherwise.
676
 
 *
677
 
 * Side effects:
678
 
 *     None.
679
 
 *
680
 
 *----------------------------------------------------------------------------
681
 
 */
682
 
 
683
 
gboolean
684
 
UnityTcloConfirmOperation(RpcInData *data)   // IN/OUT
685
 
{
686
 
   UnityConfirmOperation unityConfirmOpMsg;
687
 
   UnityConfirmOperationV1 *confirmV1 = NULL;
688
 
   Bool retVal = FALSE;
689
 
   unsigned int ret;
690
 
 
691
 
   /* Check our arguments. */
692
 
   ASSERT(data);
693
 
   if (!data) {
694
 
      return FALSE;
695
 
   }
696
 
 
697
 
   ASSERT(data->name);
698
 
   ASSERT(data->args);
699
 
 
700
 
   if (!data->name || !data->args) {
701
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
702
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
703
 
   }
704
 
 
705
 
   Debug("%s: Enter.\n", __FUNCTION__);
706
 
 
707
 
   memset(&unityConfirmOpMsg, 0, sizeof unityConfirmOpMsg);
708
 
 
709
 
   /*
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.
712
 
    */
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);
716
 
      goto exit;
717
 
   }
718
 
 
719
 
   confirmV1 = unityConfirmOpMsg.UnityConfirmOperation_u.unityConfirmOpV1;
720
 
   retVal = Unity_ConfirmOperation(confirmV1->details.op,
721
 
                                   confirmV1->windowId,
722
 
                                   confirmV1->sequence,
723
 
                                   confirmV1->allow);
724
 
 
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);
728
 
 
729
 
exit:
730
 
   Debug("%s: Exit.\n", __FUNCTION__);
731
 
   return ret;
732
 
}
733
 
 
734
 
 
735
 
/*
736
 
 *----------------------------------------------------------------------------
737
 
 *
738
 
 * UnityTcloSendMouseWheel --
739
 
 *
740
 
 *     RPC handler for 'unity.sendMouseWheel'.
741
 
 *
742
 
 * Results:
743
 
 *     TRUE on success, FALSE on failure.
744
 
 *
745
 
 * Side effects:
746
 
 *     None.
747
 
 *
748
 
 *----------------------------------------------------------------------------
749
 
 */
750
 
 
751
 
gboolean
752
 
UnityTcloSendMouseWheel(RpcInData *data)   // IN/OUT
753
 
{
754
 
   UnityMouseWheel unityMouseWheelMsg;
755
 
   UnityMouseWheelV1 *mouseWheelV1 = NULL;
756
 
   Bool retVal = FALSE;
757
 
   unsigned int ret;
758
 
   Debug("%s: Enter.\n", __FUNCTION__);
759
 
 
760
 
   memset(&unityMouseWheelMsg, 0, sizeof unityMouseWheelMsg);
761
 
 
762
 
   /*
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.
765
 
    */
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);
769
 
      goto exit;
770
 
   }
771
 
 
772
 
   mouseWheelV1 = unityMouseWheelMsg.UnityMouseWheel_u.mouseWheelV1;
773
 
   retVal = Unity_SendMouseWheel(mouseWheelV1->deltaX,
774
 
                                 mouseWheelV1->deltaY,
775
 
                                 mouseWheelV1->deltaZ,
776
 
                                 mouseWheelV1->modifierFlags);
777
 
 
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);
781
 
 
782
 
exit:
783
 
   Debug("%s: Exit.\n", __FUNCTION__);
784
 
   return ret;
785
 
}
786
 
 
787
 
 
788
 
/*
789
 
 *----------------------------------------------------------------------------
790
 
 *
791
 
 * UnityUpdateCallbackFn --
792
 
 *
793
 
 *     Callback from the unity window tracker indicating something's
794
 
 *     changed.
795
 
 *
796
 
 *     Write the update string into our dynbuf accumlating the update
797
 
 *     and return.
798
 
 *
799
 
 * Results:
800
 
 *     None.
801
 
 *
802
 
 * Side effects:
803
 
 *     Clearly.
804
 
 *
805
 
 *----------------------------------------------------------------------------
806
 
 */
807
 
 
808
 
void
809
 
UnityUpdateCallbackFn(void *param,          // IN: updateChannel
810
 
                      UnityUpdate *update)  // IN
811
 
{
812
 
   UnityUpdateChannel *updateChannel = reinterpret_cast<UnityUpdateChannel *>(param);
813
 
   DynBuf *buf = NULL;
814
 
   char data[1024];
815
 
   int i, n, count = 0;
816
 
   RegionPtr region;
817
 
   char *titleUtf8 = NULL;
818
 
   char *windowPathUtf8 = "";
819
 
   char *execPathUtf8 = "";
820
 
 
821
 
   ASSERT(updateChannel);
822
 
   buf = &updateChannel->updates;
823
 
 
824
 
   switch (update->type) {
825
 
 
826
 
   case UNITY_UPDATE_ADD_WINDOW:
827
 
      if (DynBuf_GetSize(&update->u.addWindow.windowPathUtf8) > 0) {
828
 
         windowPathUtf8 =
829
 
            static_cast<char*>(DynBuf_Get(&update->u.addWindow.windowPathUtf8));
830
 
      }
831
 
      if (DynBuf_GetSize(&update->u.addWindow.execPathUtf8) > 0) {
832
 
         execPathUtf8 =
833
 
            static_cast<char*>(DynBuf_Get(&update->u.addWindow.execPathUtf8));
834
 
      }
835
 
 
836
 
      Str_Sprintf(data, sizeof data, "add %u windowPath=%s execPath=%s",
837
 
                  update->u.addWindow.id,
838
 
                  windowPathUtf8,
839
 
                  execPathUtf8);
840
 
      DynBuf_AppendString(buf, data);
841
 
      break;
842
 
 
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);
851
 
      break;
852
 
 
853
 
   case UNITY_UPDATE_REMOVE_WINDOW:
854
 
      Str_Sprintf(data, sizeof data, "remove %u", update->u.removeWindow.id);
855
 
      DynBuf_AppendString(buf, data);
856
 
      break;
857
 
 
858
 
   case UNITY_UPDATE_CHANGE_WINDOW_REGION:
859
 
      /*
860
 
       * A null region indicates that the region should be deleted.
861
 
       * Make sure we write "region <id> 0" for the reply.
862
 
       */
863
 
      region = update->u.changeWindowRegion.region;
864
 
      if (region) {
865
 
         count = REGION_NUM_RECTS(region);
866
 
      }
867
 
      Str_Sprintf(data, sizeof data, "region %u %d",
868
 
                  update->u.changeWindowRegion.id, count);
869
 
      DynBuf_AppendString(buf, data);
870
 
 
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);
876
 
      }
877
 
      break;
878
 
 
879
 
   case UNITY_UPDATE_CHANGE_WINDOW_TITLE:
880
 
      titleUtf8 =
881
 
         reinterpret_cast<char*>(DynBuf_Get(&update->u.changeWindowTitle.titleUtf8));
882
 
 
883
 
      if (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';
890
 
      } else {
891
 
         Str_Sprintf(data, sizeof data, "title %u",
892
 
                     update->u.changeWindowTitle.id);
893
 
      }
894
 
      DynBuf_AppendString(buf, data);
895
 
      break;
896
 
 
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;
902
 
           zOrderIndex++) {
903
 
         n = Str_Snprintf(data, sizeof data, " %d", update->u.zorder.ids[zOrderIndex]);
904
 
         DynBuf_Append(buf, data, n);
905
 
      }
906
 
      DynBuf_AppendString(buf, ""); // for appending NULL
907
 
      break;
908
 
 
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);
914
 
      break;
915
 
 
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);
922
 
      break;
923
 
 
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);
929
 
      break;
930
 
 
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);
936
 
      break;
937
 
 
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);
943
 
      break;
944
 
 
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);
949
 
      break;
950
 
 
951
 
   default:
952
 
      NOT_IMPLEMENTED();
953
 
   }
954
 
}
955
 
 
956
 
 
957
 
/*
958
 
 *-----------------------------------------------------------------------------
959
 
 *
960
 
 * UnityUpdateChannelInit --
961
 
 *
962
 
 *      Initialize the state for the update channel.
963
 
 *
964
 
 * Return value:
965
 
 *      Pointer to UpdateChannel structure or NULL
966
 
 *
967
 
 * Side effects:
968
 
 *      RpcOut channel might be open.
969
 
 *      Memory for the update buffer might be allocated.
970
 
 *
971
 
 *-----------------------------------------------------------------------------
972
 
 */
973
 
 
974
 
UnityUpdateChannel *
975
 
UnityUpdateChannelInit()
976
 
{
977
 
   UnityUpdateChannel *updateChannel = NULL;
978
 
   updateChannel = reinterpret_cast<UnityUpdateChannel *>(Util_SafeCalloc(1, sizeof *updateChannel));
979
 
 
980
 
   DynBuf_Init(&updateChannel->updates);
981
 
   DynBuf_AppendString(&updateChannel->updates, UNITY_RPC_PUSH_UPDATE_CMD " ");
982
 
 
983
 
   /* Exclude the null. */
984
 
   updateChannel->cmdSize = DynBuf_GetSize(&updateChannel->updates) - 1;
985
 
   DynBuf_SetSize(&updateChannel->updates, updateChannel->cmdSize);
986
 
 
987
 
   updateChannel->rpcOut = RpcOut_Construct();
988
 
   if (updateChannel->rpcOut == NULL) {
989
 
      Warning("%s: RpcOut_Construct() failed\n", __FUNCTION__);
990
 
      goto error;
991
 
   }
992
 
 
993
 
   if (!RpcOut_start(updateChannel->rpcOut)) {
994
 
      Warning("%s: RpcOut_start() failed\n", __FUNCTION__);
995
 
      RpcOut_Destruct(updateChannel->rpcOut);
996
 
      goto error;
997
 
   }
998
 
 
999
 
   return updateChannel;
1000
 
 
1001
 
error:
1002
 
   DynBuf_Destroy(&updateChannel->updates);
1003
 
   vm_free(updateChannel);
1004
 
 
1005
 
   return NULL;
1006
 
}
1007
 
 
1008
 
 
1009
 
/*
1010
 
 *-----------------------------------------------------------------------------
1011
 
 *
1012
 
 * UnityUpdateChannelCleanup --
1013
 
 *
1014
 
 *      Cleanup the unity update channel.
1015
 
 *
1016
 
 * Return value:
1017
 
 *      None.
1018
 
 *
1019
 
 * Side effects:
1020
 
 *      RpcOut channel will be closed.
1021
 
 *      Memory will be freed.
1022
 
 *
1023
 
 *-----------------------------------------------------------------------------
1024
 
 */
1025
 
 
1026
 
void
1027
 
UnityUpdateChannelCleanup(UnityUpdateChannel *updateChannel) // IN
1028
 
{
1029
 
   if (updateChannel && updateChannel->rpcOut) {
1030
 
      RpcOut_stop(updateChannel->rpcOut);
1031
 
      RpcOut_Destruct(updateChannel->rpcOut);
1032
 
      updateChannel->rpcOut = NULL;
1033
 
 
1034
 
      DynBuf_Destroy(&updateChannel->updates); // Avoid double-free by guarding this as well
1035
 
      vm_free(updateChannel);
1036
 
   }
1037
 
}
1038
 
 
1039
 
 
1040
 
#ifdef VMX86_DEVEL
1041
 
/*
1042
 
 *-----------------------------------------------------------------------------
1043
 
 *
1044
 
 * DumpUpdate --
1045
 
 *
1046
 
 *      Prints a Unity update via debug output.  NUL is represented as '!'.
1047
 
 *
1048
 
 * Results:
1049
 
 *      None.
1050
 
 *
1051
 
 * Side effects:
1052
 
 *      None.
1053
 
 *
1054
 
 *-----------------------------------------------------------------------------
1055
 
 */
1056
 
 
1057
 
static void
1058
 
DumpUpdate(UnityUpdateChannel *updateChannel)   // IN
1059
 
{
1060
 
   int i, len;
1061
 
   char *buf = NULL;
1062
 
 
1063
 
   len = updateChannel->updates.size;
1064
 
   buf = reinterpret_cast<char*>(Util_SafeMalloc(len + 1));
1065
 
   memcpy(buf, updateChannel->updates.data, len);
1066
 
   buf[len] = '\0';
1067
 
   for (i = 0 ; i < len; i++) {
1068
 
      if (buf[i] == '\0') {
1069
 
         buf[i] = '!';
1070
 
      }
1071
 
   }
1072
 
 
1073
 
   Debug("%s: Sending update: %s\n", __FUNCTION__, buf);
1074
 
 
1075
 
   vm_free(buf);
1076
 
}
1077
 
#endif // ifdef VMX86_DEVEL
1078
 
 
1079
 
 
1080
 
/*
1081
 
 *-----------------------------------------------------------------------------
1082
 
 *
1083
 
 * UnitySendUpdates --
1084
 
 *
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.
1089
 
 *
1090
 
 * Return value:
1091
 
 *      TRUE if the update was sent,
1092
 
 *      FALSE if something went wrong (an invalid RPC channel, for example).
1093
 
 *
1094
 
 * Side effects:
1095
 
 *      None.
1096
 
 *
1097
 
 *-----------------------------------------------------------------------------
1098
 
 */
1099
 
 
1100
 
Bool
1101
 
UnitySendUpdates(void *param) // IN
1102
 
{
1103
 
   char const *myReply;
1104
 
   size_t myRepLen;
1105
 
   Bool retry = FALSE;
1106
 
   UnityUpdateChannel *updateChannel = reinterpret_cast<UnityUpdateChannel*>(param);
1107
 
 
1108
 
   ASSERT(updateChannel);
1109
 
   ASSERT(updateChannel->rpcOut);
1110
 
 
1111
 
   /* Send 'tools.unity.push.update <updates>' to the VMX. */
1112
 
 
1113
 
#ifdef VMX86_DEVEL
1114
 
   DumpUpdate(updateChannel);
1115
 
#endif
1116
 
 
1117
 
retry_send:
1118
 
   if (!RpcOut_send(updateChannel->rpcOut,
1119
 
                    (char *)DynBuf_Get(&updateChannel->updates),
1120
 
                    DynBuf_GetSize(&updateChannel->updates),
1121
 
                    &myReply, &myRepLen)) {
1122
 
 
1123
 
      /*
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.
1128
 
       */
1129
 
 
1130
 
      if (!retry) {
1131
 
         retry = TRUE;
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__);
1136
 
            return FALSE;
1137
 
         }
1138
 
         goto retry_send;
1139
 
 
1140
 
      } else {
1141
 
         Debug("%s: could not resend rpc. Giving up and exiting...\n", __FUNCTION__);
1142
 
         return FALSE;
1143
 
      }
1144
 
   }
1145
 
 
1146
 
   /*
1147
 
    * With the update queue sent, purge the DynBuf by trimming it to the length
1148
 
    * of the command preamble.
1149
 
    */
1150
 
   DynBuf_SetSize(&updateChannel->updates, updateChannel->cmdSize);
1151
 
 
1152
 
   return TRUE;
1153
 
}
1154
 
 
1155
 
 
1156
 
/*
1157
 
 *----------------------------------------------------------------------------
1158
 
 *
1159
 
 * UnityTcloGetWindowContents --
1160
 
 *
1161
 
 *     RPC handler for 'unity.get.window.contents'. Suck the bits off the
1162
 
 *     window and return a .png image over the backdoor.
1163
 
 *
1164
 
 * Results:
1165
 
 *     TRUE if everything is successful.
1166
 
 *     FALSE otherwise.
1167
 
 *
1168
 
 * Side effects:
1169
 
 *     None.
1170
 
 *
1171
 
 *----------------------------------------------------------------------------
1172
 
 */
1173
 
 
1174
 
gboolean
1175
 
UnityTcloGetWindowContents(RpcInData *data)     // IN/OUT
1176
 
{
1177
 
   unsigned int window;
1178
 
   unsigned int index = 0;
1179
 
   DynBuf *imageData = &gTcloUpdate;
1180
 
   uint32 width;
1181
 
   uint32 height;
1182
 
 
1183
 
   /* Check our arguments. */
1184
 
   ASSERT(data);
1185
 
   if (!data) {
1186
 
      return FALSE;
1187
 
   }
1188
 
 
1189
 
   ASSERT(data->name);
1190
 
   ASSERT(data->args);
1191
 
 
1192
 
   if (!data->name || !data->args) {
1193
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1194
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1195
 
   }
1196
 
 
1197
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1198
 
 
1199
 
   /*
1200
 
    * Parse the command & window id.
1201
 
    */
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\"",
1206
 
                              FALSE);
1207
 
 
1208
 
   }
1209
 
   Debug("%s: window %d\n", __FUNCTION__, window);
1210
 
 
1211
 
   /*
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.
1214
 
    */
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",
1219
 
                              FALSE);
1220
 
   }
1221
 
 
1222
 
   data->result = (char *)DynBuf_Get(imageData);
1223
 
   data->resultLen = DynBuf_GetSize(imageData);
1224
 
 
1225
 
   return TRUE;
1226
 
}
1227
 
 
1228
 
 
1229
 
/*
1230
 
 *----------------------------------------------------------------------------
1231
 
 *
1232
 
 * UnityTcloGetIconData --
1233
 
 *
1234
 
 *     RPC handler for 'unity.get.icon.data'. Suck the bits off the
1235
 
 *     window and return a .png image over the backdoor.
1236
 
 *
1237
 
 * Results:
1238
 
 *     TRUE if everything is successful.
1239
 
 *     FALSE otherwise.
1240
 
 *
1241
 
 * Side effects:
1242
 
 *     None.
1243
 
 *
1244
 
 *----------------------------------------------------------------------------
1245
 
 */
1246
 
 
1247
 
gboolean
1248
 
UnityTcloGetIconData(RpcInData *data)  // IN/OUT
1249
 
{
1250
 
   UnityWindowId window;
1251
 
   UnityIconType iconType;
1252
 
   UnityIconSize iconSize;
1253
 
   unsigned int dataOffset, dataLength;
1254
 
   uint32 fullLength;
1255
 
   size_t retLength;
1256
 
   DynBuf *results = &gTcloUpdate, imageData;
1257
 
   char bitmapData[1024];
1258
 
 
1259
 
   /* Check our arguments. */
1260
 
   ASSERT(data);
1261
 
   if (!data) {
1262
 
      return FALSE;
1263
 
   }
1264
 
 
1265
 
   ASSERT(data->name);
1266
 
   ASSERT(data->args);
1267
 
 
1268
 
   if (!data->name || !data->args) {
1269
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1270
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1271
 
   }
1272
 
 
1273
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1274
 
 
1275
 
   /*
1276
 
    * Parse the arguments.
1277
 
    */
1278
 
   if ((sscanf(data->args, "%u %u %u %u %u",
1279
 
               &window,
1280
 
               (unsigned int*) &iconType,
1281
 
               &iconSize,
1282
 
               &dataOffset,
1283
 
               &dataLength) != 5)
1284
 
       || (dataLength > UNITY_MAX_ICON_DATA_CHUNK)) {
1285
 
      Debug("UnityTcloGetIconData: Invalid RPC arguments.\n");
1286
 
      return RPCIN_SETRETVALS(data,
1287
 
                              "failed: arguments missing",
1288
 
                              FALSE);
1289
 
   }
1290
 
 
1291
 
   Debug("%s: window %u iconType %u" \
1292
 
         " iconSize %u dataOffset %u dataLength %u\n",
1293
 
         __FUNCTION__,
1294
 
         window, iconType, iconSize, dataOffset, dataLength);
1295
 
 
1296
 
   /*
1297
 
    * Retrieve part/all of the icon in PNG format.
1298
 
    */
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",
1304
 
                              FALSE);
1305
 
   }
1306
 
 
1307
 
 
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,
1312
 
                                                   sizeof bitmapData,
1313
 
                                                   "%u %" FMTSZ "u ",
1314
 
                                                   fullLength, retLength));
1315
 
   DynBuf_Append(results, DynBuf_Get(&imageData), retLength);
1316
 
 
1317
 
   /*
1318
 
    * Guarantee that the results have a trailing \0 in case anything does a strlen...
1319
 
    */
1320
 
   DynBuf_AppendString(results, "");
1321
 
   data->result = (char *)DynBuf_Get(results);
1322
 
   data->resultLen = DynBuf_GetSize(results);
1323
 
   DynBuf_Destroy(&imageData);
1324
 
 
1325
 
   return TRUE;
1326
 
}
1327
 
 
1328
 
 
1329
 
/*
1330
 
 *----------------------------------------------------------------------------
1331
 
 *
1332
 
 * UnityTcloShowTaskbar --
1333
 
 *
1334
 
 *     RPC handler for 'unity.show.taskbar'.
1335
 
 *
1336
 
 * Results:
1337
 
 *     TRUE if everything is successful.
1338
 
 *     FALSE otherwise.
1339
 
 *
1340
 
 * Side effects:
1341
 
 *     None.
1342
 
 *
1343
 
 *----------------------------------------------------------------------------
1344
 
 */
1345
 
 
1346
 
gboolean
1347
 
UnityTcloShowTaskbar(RpcInData *data)     // IN/OUT
1348
 
{
1349
 
   uint32 command = 0;
1350
 
   unsigned int index = 0;
1351
 
 
1352
 
   /* Check our arguments. */
1353
 
   ASSERT(data);
1354
 
   if (!data) {
1355
 
      return FALSE;
1356
 
   }
1357
 
 
1358
 
   ASSERT(data->name);
1359
 
   ASSERT(data->args);
1360
 
 
1361
 
   if (!data->name || !data->args) {
1362
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1363
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1364
 
   }
1365
 
 
1366
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1367
 
 
1368
 
   if (!StrUtil_GetNextUintToken(&command, &index, data->args, " ")) {
1369
 
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
1370
 
      return RPCIN_SETRETVALS(data,
1371
 
                              "Invalid arguments.",
1372
 
                              FALSE);
1373
 
   }
1374
 
 
1375
 
   Debug("%s: command %d\n", __FUNCTION__, command);
1376
 
 
1377
 
   Unity_ShowTaskbar((command == 0) ? FALSE : TRUE);
1378
 
 
1379
 
   return RPCIN_SETRETVALS(data, "", TRUE);
1380
 
}
1381
 
 
1382
 
 
1383
 
/*
1384
 
 *----------------------------------------------------------------------------
1385
 
 *
1386
 
 * UnityTcloMoveResizeWindow --
1387
 
 *
1388
 
 *     RPC handler for 'unity.window.move_resize'.
1389
 
 *
1390
 
 * Results:
1391
 
 *     TRUE if everything is successful.
1392
 
 *     FALSE otherwise.
1393
 
 *     If successful adds null terminated strings for each output coordinates.
1394
 
 *
1395
 
 * Side effects:
1396
 
 *     None.
1397
 
 *
1398
 
 *----------------------------------------------------------------------------
1399
 
 */
1400
 
 
1401
 
gboolean
1402
 
UnityTcloMoveResizeWindow(RpcInData *data)      // IN/OUT
1403
 
{
1404
 
   DynBuf *buf = &gTcloUpdate;
1405
 
   UnityWindowId window;
1406
 
   UnityRect moveResizeRect = {0};
1407
 
   char temp[1024];
1408
 
 
1409
 
   /* Check our arguments. */
1410
 
   ASSERT(data);
1411
 
   if (!data) {
1412
 
      return FALSE;
1413
 
   }
1414
 
 
1415
 
   ASSERT(data->name);
1416
 
   ASSERT(data->args);
1417
 
 
1418
 
   if (!data->name || !data->args) {
1419
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1420
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1421
 
   }
1422
 
 
1423
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1424
 
 
1425
 
   if (sscanf(data->args, "%u %d %d %d %d",
1426
 
              &window,
1427
 
              &moveResizeRect.x,
1428
 
              &moveResizeRect.y,
1429
 
              &moveResizeRect.width,
1430
 
              &moveResizeRect.height) != 5) {
1431
 
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
1432
 
      return RPCIN_SETRETVALS(data,
1433
 
                              "Invalid arguments.",
1434
 
                              FALSE);
1435
 
   }
1436
 
 
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",
1441
 
                              FALSE);
1442
 
   }
1443
 
 
1444
 
   /*
1445
 
    *  Send back the new (post move/resize operation) window coordinates.
1446
 
    */
1447
 
 
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);
1452
 
 
1453
 
   /*
1454
 
    * Write the final result into the result out parameters and return!
1455
 
    */
1456
 
 
1457
 
   data->result = (char *)DynBuf_Get(buf);
1458
 
   data->resultLen = DynBuf_GetSize(buf);
1459
 
 
1460
 
   return TRUE;
1461
 
}
1462
 
 
1463
 
 
1464
 
/*
1465
 
 *----------------------------------------------------------------------------
1466
 
 *
1467
 
 * UnityTcloSetDesktopConfig --
1468
 
 *
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
1472
 
 *     active desktop.
1473
 
 *
1474
 
 * Results:
1475
 
 *     TRUE if everything is successful.
1476
 
 *     FALSE otherwise.
1477
 
 *
1478
 
 * Side effects:
1479
 
 *     Might change virtual desktop configuration in the guest.
1480
 
 *
1481
 
 *----------------------------------------------------------------------------
1482
 
 */
1483
 
 
1484
 
gboolean
1485
 
UnityTcloSetDesktopConfig(RpcInData *data)      // IN/OUT
1486
 
{
1487
 
   unsigned int index = 0;
1488
 
   char *desktopStr = NULL;
1489
 
   char *errorMsg;
1490
 
   uint32 initialDesktopIndex = 0;
1491
 
   UnityVirtualDesktopArray desktopConfig;
1492
 
 
1493
 
   memset(&desktopConfig, 0, sizeof desktopConfig);
1494
 
 
1495
 
   /* Check our arguments. */
1496
 
   ASSERT(data);
1497
 
   if (!data) {
1498
 
      return FALSE;
1499
 
   }
1500
 
 
1501
 
   ASSERT(data->name);
1502
 
   ASSERT(data->args);
1503
 
 
1504
 
   if (!data->name || !data->args) {
1505
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1506
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1507
 
   }
1508
 
 
1509
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1510
 
 
1511
 
   if (data->argsSize == 0) {
1512
 
      errorMsg = "Invalid arguments: desktop config is expected";
1513
 
      goto error;
1514
 
   }
1515
 
 
1516
 
   /* Read the virtual desktop configuration. */
1517
 
   while ((desktopStr = StrUtil_GetNextToken(&index, data->args, " ")) != NULL) {
1518
 
 
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";
1524
 
            goto error;
1525
 
         }
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";
1530
 
            goto error;
1531
 
         }
1532
 
         /* All done with arguments at this point - stop processing */
1533
 
         free(desktopStr);
1534
 
         break;
1535
 
      } else {
1536
 
         errorMsg = "Invalid arguments: invalid desktop config";
1537
 
         goto error;
1538
 
      }
1539
 
      free(desktopStr);
1540
 
      desktopStr = NULL;
1541
 
   }
1542
 
 
1543
 
   /*
1544
 
    * Call the platform specific function to set the desktop configuration.
1545
 
    */
1546
 
 
1547
 
   if (!Unity_SetDesktopConfig(&desktopConfig)) {
1548
 
      errorMsg = "Could not set desktop configuration";
1549
 
      goto error;
1550
 
   }
1551
 
 
1552
 
   if (!Unity_SetInitialDesktop(initialDesktopIndex)) {
1553
 
      errorMsg = "Could not set initial desktop";
1554
 
      goto error;
1555
 
   }
1556
 
 
1557
 
   return RPCIN_SETRETVALS(data,
1558
 
                           "",
1559
 
                           TRUE);
1560
 
error:
1561
 
   free(desktopStr);
1562
 
   Debug("%s: %s\n", __FUNCTION__, errorMsg);
1563
 
 
1564
 
   return RPCIN_SETRETVALS(data,
1565
 
                           errorMsg,
1566
 
                           FALSE);
1567
 
}
1568
 
 
1569
 
 
1570
 
/*
1571
 
 *----------------------------------------------------------------------------
1572
 
 *
1573
 
 * UnityTcloSetDesktopActive --
1574
 
 *
1575
 
 *     RPC handler for 'unity.set.desktop.active'.
1576
 
 *
1577
 
 * Results:
1578
 
 *     TRUE if everything is successful.
1579
 
 *     FALSE otherwise.
1580
 
 *
1581
 
 * Side effects:
1582
 
 *     Might change the active virtual desktop in the guest.
1583
 
 *
1584
 
 *----------------------------------------------------------------------------
1585
 
 */
1586
 
 
1587
 
gboolean
1588
 
UnityTcloSetDesktopActive(RpcInData *data)      // IN/OUT
1589
 
{
1590
 
   UnityDesktopId desktopId = 0;
1591
 
   char *errorMsg;
1592
 
 
1593
 
   /* Check our arguments. */
1594
 
   ASSERT(data);
1595
 
   if (!data) {
1596
 
      return FALSE;
1597
 
   }
1598
 
 
1599
 
   ASSERT(data->name);
1600
 
   ASSERT(data->args);
1601
 
 
1602
 
   if (!data->name || !data->args) {
1603
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1604
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1605
 
   }
1606
 
 
1607
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1608
 
 
1609
 
   if (Unity_IsActive() == FALSE) {
1610
 
      errorMsg = "Unity not enabled - cannot change active desktop";
1611
 
      goto error;
1612
 
   }
1613
 
 
1614
 
   if (sscanf(data->args, " %d", &desktopId) != 1) {
1615
 
      errorMsg = "Invalid arguments: expected \"desktopId\"";
1616
 
      goto error;
1617
 
   }
1618
 
 
1619
 
   /*
1620
 
    * Call the platform specific function to set the desktop active.
1621
 
    */
1622
 
 
1623
 
   if (!Unity_SetDesktopActive(desktopId)) {
1624
 
      errorMsg = "Could not set active desktop";
1625
 
      goto error;
1626
 
   }
1627
 
 
1628
 
   return RPCIN_SETRETVALS(data,
1629
 
                           "",
1630
 
                           TRUE);
1631
 
error:
1632
 
   Debug("%s: %s\n", __FUNCTION__, errorMsg);
1633
 
   return RPCIN_SETRETVALS(data,
1634
 
                           errorMsg,
1635
 
                           FALSE);
1636
 
}
1637
 
 
1638
 
 
1639
 
/*
1640
 
 *----------------------------------------------------------------------------
1641
 
 *
1642
 
 * UnityTcloSetWindowDesktop --
1643
 
 *
1644
 
 *     RPC handler for 'unity.set.window.desktop'.
1645
 
 *
1646
 
 * Results:
1647
 
 *     TRUE if everything is successful.
1648
 
 *     FALSE otherwise.
1649
 
 *
1650
 
 * Side effects:
1651
 
 *     Might change the active virtual desktop in the guest.
1652
 
 *
1653
 
 *----------------------------------------------------------------------------
1654
 
 */
1655
 
 
1656
 
gboolean
1657
 
UnityTcloSetWindowDesktop(RpcInData *data)   // IN/OUT
1658
 
{
1659
 
   UnityWindowId windowId;
1660
 
   uint32 desktopId = 0;
1661
 
   char *errorMsg;
1662
 
 
1663
 
   /* Check our arguments. */
1664
 
   ASSERT(data);
1665
 
   if (!data) {
1666
 
      return FALSE;
1667
 
   }
1668
 
 
1669
 
   ASSERT(data->name);
1670
 
   ASSERT(data->args);
1671
 
 
1672
 
   if (!data->name || !data->args) {
1673
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1674
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1675
 
   }
1676
 
 
1677
 
   Debug("%s: name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
1678
 
 
1679
 
   if (Unity_IsActive() == FALSE) {
1680
 
      errorMsg = "Unity not enabled - cannot set window desktop";
1681
 
      goto error;
1682
 
   }
1683
 
 
1684
 
   if (sscanf(data->args, " %u %d", &windowId, &desktopId) != 2) {
1685
 
      errorMsg = "Invalid arguments: expected \"windowId desktopId\"";
1686
 
      goto error;
1687
 
   }
1688
 
 
1689
 
   /*
1690
 
    * Call the platform specific function to move the window to the
1691
 
    * specified desktop.
1692
 
    */
1693
 
 
1694
 
   if (!Unity_SetWindowDesktop(windowId, desktopId)) {
1695
 
      errorMsg = "Could not move the window to the desktop";
1696
 
      goto error;
1697
 
   }
1698
 
 
1699
 
   return RPCIN_SETRETVALS(data,
1700
 
                           "",
1701
 
                           TRUE);
1702
 
error:
1703
 
   Debug("%s: %s\n", __FUNCTION__, errorMsg);
1704
 
   return RPCIN_SETRETVALS(data,
1705
 
                           errorMsg,
1706
 
                           FALSE);
1707
 
}
1708
 
 
1709
 
 
1710
 
/*
1711
 
 *----------------------------------------------------------------------------
1712
 
 *
1713
 
 * UnityTcloSetUnityOptions --
1714
 
 *
1715
 
 *     Set the Unity options - must be be called before entering Unity mode.
1716
 
 *
1717
 
 * Results:
1718
 
 *     TRUE if RPC was succesfully handled.
1719
 
 *     FALSE otherwise.
1720
 
 *
1721
 
 * Side effects:
1722
 
 *     None.
1723
 
 *
1724
 
 *----------------------------------------------------------------------------
1725
 
 */
1726
 
 
1727
 
gboolean
1728
 
UnityTcloSetUnityOptions(RpcInData *data)
1729
 
{
1730
 
   Bool ret = TRUE;
1731
 
   UnityOptions optionsMsg;
1732
 
 
1733
 
   memset(&optionsMsg, 0, sizeof optionsMsg);
1734
 
 
1735
 
   /* Check our arguments. */
1736
 
   ASSERT(data);
1737
 
   if (!data) {
1738
 
      return FALSE;
1739
 
   }
1740
 
 
1741
 
   ASSERT(data->name);
1742
 
   ASSERT(data->args);
1743
 
 
1744
 
   if (!data->name || !data->args) {
1745
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1746
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1747
 
   }
1748
 
 
1749
 
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
1750
 
         __FUNCTION__, data->name, data->argsSize);
1751
 
 
1752
 
   /*
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.
1755
 
    */
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);
1760
 
      goto exit;
1761
 
   }
1762
 
 
1763
 
   Unity_SetUnityOptions(optionsMsg.UnityOptions_u.unityOptionsV1->featureMask);
1764
 
 
1765
 
   ret = RPCIN_SETRETVALS(data,
1766
 
                          "",
1767
 
                          TRUE);
1768
 
exit:
1769
 
   VMX_XDR_FREE(xdr_UnityOptions, &optionsMsg);
1770
 
 
1771
 
   return ret;
1772
 
}
1773
 
 
1774
 
 
1775
 
/*
1776
 
 *----------------------------------------------------------------------------
1777
 
 *
1778
 
 * UnityTcloRequestWindowContents --
1779
 
 *
1780
 
 *     Request the window contents for a set of windows.
1781
 
 *
1782
 
 * Results:
1783
 
 *     TRUE if all the window IDs are valid.
1784
 
 *     FALSE otherwise.
1785
 
 *
1786
 
 * Side effects:
1787
 
 *     None.
1788
 
 *
1789
 
 *----------------------------------------------------------------------------
1790
 
 */
1791
 
 
1792
 
gboolean
1793
 
UnityTcloRequestWindowContents(RpcInData *data)    // IN
1794
 
{
1795
 
   Bool ret = TRUE;
1796
 
   UnityWindowContentsRequest requestMsg;
1797
 
   UnityWindowContentsRequestV1 *requestV1 = NULL;
1798
 
   memset(&requestMsg, 0, sizeof requestMsg);
1799
 
 
1800
 
   /* Check our arguments. */
1801
 
   ASSERT(data);
1802
 
   if (!data) {
1803
 
      return FALSE;
1804
 
   }
1805
 
 
1806
 
   ASSERT(data->name);
1807
 
   ASSERT(data->args);
1808
 
 
1809
 
   if (!data->name || !data->args) {
1810
 
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
1811
 
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
1812
 
   }
1813
 
 
1814
 
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
1815
 
         __FUNCTION__, data->name, data->argsSize);
1816
 
 
1817
 
   /*
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.
1820
 
    */
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);
1825
 
      goto exit;
1826
 
   }
1827
 
 
1828
 
   if (requestMsg.ver != UNITY_WINDOW_CONTENTS_V1) {
1829
 
      Debug("%s: Unexpected XDR version = %d\n", __FUNCTION__, requestMsg.ver);
1830
 
      goto exit;
1831
 
   }
1832
 
 
1833
 
   requestV1 = requestMsg.UnityWindowContentsRequest_u.requestV1;
1834
 
 
1835
 
   /*
1836
 
    * Call the platform implementation of the RPC handler.
1837
 
    */
1838
 
   if (!Unity_RequestWindowContents(requestV1->windowID.windowID_val,
1839
 
                                    requestV1->windowID.windowID_len)) {
1840
 
      ret = RPCIN_SETRETVALS(data, "Invalid list of windows.", FALSE);
1841
 
      goto exit;
1842
 
   }
1843
 
 
1844
 
   ret = RPCIN_SETRETVALS(data,
1845
 
                          "",
1846
 
                          TRUE);
1847
 
exit:
1848
 
   VMX_XDR_FREE(xdr_UnityWindowContentsRequest, &requestMsg);
1849
 
 
1850
 
   return ret;
1851
 
}
1852
 
 
1853
 
 
1854
 
/*
1855
 
 *----------------------------------------------------------------------------
1856
 
 *
1857
 
 * UnityUpdateState --
1858
 
 *
1859
 
 *     Communicate unity state changes to vmx.
1860
 
 *
1861
 
 * Results:
1862
 
 *     TRUE if everything is successful.
1863
 
 *     FALSE otherwise.
1864
 
 *
1865
 
 * Side effects:
1866
 
 *     None.
1867
 
 *
1868
 
 *----------------------------------------------------------------------------
1869
 
 */
1870
 
 
1871
 
static Bool
1872
 
UnityUpdateState(void)
1873
 
{
1874
 
   Bool ret = TRUE;
1875
 
   XDR xdrs;
1876
 
   UnityActiveProto message;
1877
 
   char *val;
1878
 
 
1879
 
   if (DynXdr_Create(&xdrs) == NULL) {
1880
 
      return FALSE;
1881
 
   }
1882
 
 
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__);
1886
 
      ret = FALSE;
1887
 
      goto out;
1888
 
   }
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__);
1894
 
      ret = FALSE;
1895
 
      goto out;
1896
 
   }
1897
 
 
1898
 
   if (!RpcOut_SendOneRaw(DynXdr_Get(&xdrs), xdr_getpos(&xdrs), NULL, NULL)) {
1899
 
      Debug("%s: Failed to send Unity state RPC.\n", __FUNCTION__);
1900
 
      ret = FALSE;
1901
 
   } else {
1902
 
      Debug("%s: success\n", __FUNCTION__);
1903
 
   }
1904
 
out:
1905
 
   free(val);
1906
 
   DynXdr_Destroy(&xdrs, TRUE);
1907
 
   return ret;
1908
 
}
1909
 
 
1910
 
 
1911
 
/*
1912
 
 *----------------------------------------------------------------------------
1913
 
 *
1914
 
 * UnityXdrRequestOperation --
1915
 
 *
1916
 
 *    XDR encoder function for UnityRequestOperation.
1917
 
 *
1918
 
 *    See UnityXdrSendRpc().
1919
 
 *
1920
 
 * Results:
1921
 
 *    Returns true if the XDR struct was encoded successfully.
1922
 
 *
1923
 
 * Side-effects:
1924
 
 *    None.
1925
 
 *------------------------------------------------------------------------------
1926
 
 */
1927
 
 
1928
 
Bool
1929
 
UnityXdrRequestOperation(XDR *xdrs,    // IN
1930
 
                         void *arg)    // IN
1931
 
{
1932
 
   ASSERT(xdrs);
1933
 
   ASSERT(arg);
1934
 
   return xdr_UnityRequestOperation(xdrs, (UnityRequestOperation *) arg);
1935
 
}
1936
 
 
1937
 
 
1938
 
/*
1939
 
 *------------------------------------------------------------------------------
1940
 
 *
1941
 
 * UnitySendRequestMinimizeOperation --
1942
 
 *
1943
 
 *     Send a request for a minimize operation to the host.
1944
 
 *
1945
 
 * Results:
1946
 
 *     TRUE if everything is successful.
1947
 
 *     FALSE otherwise.
1948
 
 *
1949
 
 * Side effects:
1950
 
 *     None.
1951
 
 *
1952
 
 *----------------------------------------------------------------------------
1953
 
 */
1954
 
 
1955
 
Bool
1956
 
UnitySendRequestMinimizeOperation(UnityWindowId windowId,   // IN
1957
 
                                  uint32 sequence)          // IN
1958
 
{
1959
 
   Bool ret = FALSE;
1960
 
   UnityRequestOperation msg;
1961
 
   UnityRequestOperationV1 v1;
1962
 
   memset(&msg, 0, sizeof msg);
1963
 
   memset(&v1, 0, sizeof v1);
1964
 
 
1965
 
   Debug("%s: Enter.\n", __FUNCTION__);
1966
 
 
1967
 
   v1.windowId = windowId;
1968
 
   v1.sequence = sequence;
1969
 
   v1.details.op = MINIMIZE;
1970
 
 
1971
 
   msg.ver = UNITY_OP_V1;
1972
 
   msg.UnityRequestOperation_u.unityRequestOpV1 = &v1;
1973
 
 
1974
 
   ret = UnityXdrSendRpc(UNITY_RPC_REQUEST_OPERATION,
1975
 
                         &UnityXdrRequestOperation,
1976
 
                         &msg);
1977
 
 
1978
 
   Debug("%s: Exit.\n", __FUNCTION__);
1979
 
   return ret;
1980
 
}
1981
 
 
1982
 
 
1983
 
/*
1984
 
 *----------------------------------------------------------------------------
1985
 
 *
1986
 
 * UnitySendWindowContents --
1987
 
 *
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.
1992
 
 *
1993
 
 * Results:
1994
 
 *     Returns true if the image was transferred successfully.
1995
 
 *
1996
 
 * Side effects:
1997
 
 *     None.
1998
 
 *
1999
 
 *------------------------------------------------------------------------------
2000
 
 */
2001
 
 
2002
 
Bool
2003
 
UnitySendWindowContents(UnityWindowId windowID, // IN
2004
 
                        uint32 imageWidth,      // IN
2005
 
                        uint32 imageHeight,     // IN
2006
 
                        const char *imageData,  // IN
2007
 
                        uint32 imageLength)     // IN
2008
 
{
2009
 
   Bool ret = FALSE;
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 */
2013
 
 
2014
 
   ASSERT(imageWidth > 0);
2015
 
   ASSERT(imageHeight > 0);
2016
 
   ASSERT(imageLength > 0);
2017
 
   ASSERT(imageData);
2018
 
 
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);
2023
 
 
2024
 
   /* Send the unity.window.contents.start RPC to the host. */
2025
 
   if (!UnitySendWindowContentsStart(windowID,
2026
 
                                     imageWidth,
2027
 
                                     imageHeight,
2028
 
                                     imageLength)) {
2029
 
      goto exit;
2030
 
   }
2031
 
 
2032
 
   /* Send the image data. */
2033
 
   while (imageLength > 0) {
2034
 
      /*
2035
 
       * Get the length of the next chunk to send, up to a maximum of
2036
 
       * UNITY_WINDOW_CONTENTS_MAX_CHUNK_SIZE bytes.
2037
 
       */
2038
 
      len = MIN(UNITY_WINDOW_CONTENTS_MAX_CHUNK_SIZE, imageLength);
2039
 
 
2040
 
      Debug("%s: Sending chunk %u at offset 0x%p, size %u.\n", __FUNCTION__,
2041
 
            count, readptr, len);
2042
 
 
2043
 
      /* Send the next chunk to the host. */
2044
 
      if (!UnitySendWindowContentsChunk(windowID, count, readptr, len)) {
2045
 
         goto exit;
2046
 
      }
2047
 
 
2048
 
      count++;
2049
 
      readptr += len;
2050
 
      imageLength -= len;
2051
 
   }
2052
 
 
2053
 
   /* Send the unity.window.contents.end RPC to the host. */
2054
 
   if (!UnitySendWindowContentsEnd(windowID)) {
2055
 
      goto exit;
2056
 
   }
2057
 
 
2058
 
   ret = TRUE;
2059
 
 
2060
 
exit:
2061
 
   return ret;
2062
 
}
2063
 
 
2064
 
 
2065
 
/*
2066
 
 *------------------------------------------------------------------------------
2067
 
 *
2068
 
 * UnityXdrEncodeWindowContentsStart --
2069
 
 *
2070
 
 *    XDR encoder function for UnityWindowContentsStart.
2071
 
 *
2072
 
 *    See UnityXdrSendRpc().
2073
 
 *
2074
 
 * Results:
2075
 
 *    Returns true if the XDR struct was encoded successfully.
2076
 
 *
2077
 
 * Side effects:
2078
 
 *    None.
2079
 
 *------------------------------------------------------------------------------
2080
 
 */
2081
 
 
2082
 
Bool
2083
 
UnityXdrEncodeWindowContentsStart(XDR *xdrs,
2084
 
                                  void *arg)
2085
 
{
2086
 
   ASSERT(xdrs);
2087
 
   ASSERT(arg);
2088
 
   return xdr_UnityWindowContentsStart(xdrs, (UnityWindowContentsStart *) arg);
2089
 
}
2090
 
 
2091
 
 
2092
 
/*
2093
 
 *------------------------------------------------------------------------------
2094
 
 *
2095
 
 * UnitySendWindowContentsStart --
2096
 
 *
2097
 
 *    Sends the unity.window.contents.start RPC to the host.
2098
 
 *
2099
 
 * Results:
2100
 
 *    Returns true if the RPC was sent successfully.
2101
 
 *
2102
 
 * Side effects:
2103
 
 *    None.
2104
 
 *
2105
 
 *------------------------------------------------------------------------------
2106
 
 */
2107
 
 
2108
 
Bool
2109
 
UnitySendWindowContentsStart(UnityWindowId windowID, // IN
2110
 
                             uint32 imageWidth,      // IN
2111
 
                             uint32 imageHeight,     // IN
2112
 
                             uint32 imageLength)     // IN
2113
 
{
2114
 
   Bool ret = FALSE;
2115
 
   UnityWindowContentsStart msg;
2116
 
   UnityWindowContentsStartV1 v1;
2117
 
 
2118
 
   memset(&msg, 0, sizeof msg);
2119
 
   memset(&v1, 0, sizeof v1);
2120
 
 
2121
 
   Debug("%s: Enter.\n", __FUNCTION__);
2122
 
 
2123
 
   v1.windowID = windowID;
2124
 
   v1.imageWidth  = imageWidth;
2125
 
   v1.imageHeight = imageHeight;
2126
 
   v1.imageLength = imageLength;
2127
 
 
2128
 
   msg.ver = UNITY_WINDOW_CONTENTS_V1;
2129
 
   msg.UnityWindowContentsStart_u.startV1 = &v1;
2130
 
 
2131
 
   ret = UnityXdrSendRpc(UNITY_RPC_WINDOW_CONTENTS_START,
2132
 
                         &UnityXdrEncodeWindowContentsStart,
2133
 
                         &msg);
2134
 
 
2135
 
   Debug("%s: Exit.\n", __FUNCTION__);
2136
 
   return ret;
2137
 
}
2138
 
 
2139
 
 
2140
 
/*
2141
 
 *------------------------------------------------------------------------------
2142
 
 *
2143
 
 * UnityXdrEncodeWindowContentsChunk --
2144
 
 *
2145
 
 *    XDR encoder function for UnityWindowContentsChunk.
2146
 
 *
2147
 
 *    See UnityXdrSendRpc().
2148
 
 *
2149
 
 * Results:
2150
 
 *    Returns true if the XDR struct was encoded successfully.
2151
 
 *
2152
 
 * Side-effects:
2153
 
 *    None.
2154
 
 *------------------------------------------------------------------------------
2155
 
 */
2156
 
 
2157
 
Bool
2158
 
UnityXdrEncodeWindowContentsChunk(XDR *xdrs,
2159
 
                                  void *arg)
2160
 
{
2161
 
   ASSERT(xdrs);
2162
 
   ASSERT(arg);
2163
 
   return xdr_UnityWindowContentsChunk(xdrs, (UnityWindowContentsChunk *) arg);
2164
 
}
2165
 
 
2166
 
 
2167
 
/*
2168
 
 *------------------------------------------------------------------------------
2169
 
 *
2170
 
 * UnitySendWindowContentsChunk --
2171
 
 *
2172
 
 *    Sends a unity.window.contents.chunk RPC to the host.
2173
 
 *
2174
 
 * Results:
2175
 
 *    Returns true if the RPC was sent successfully.
2176
 
 *
2177
 
 * Side effects:
2178
 
 *    None.
2179
 
 *
2180
 
 *------------------------------------------------------------------------------
2181
 
 */
2182
 
 
2183
 
Bool
2184
 
UnitySendWindowContentsChunk(UnityWindowId windowID,
2185
 
                             uint32 chunkID,
2186
 
                             const char *data,
2187
 
                             uint32 len)
2188
 
{
2189
 
   Bool ret = FALSE;
2190
 
   UnityWindowContentsChunk msg;
2191
 
   UnityWindowContentsChunkV1 v1;
2192
 
   memset(&msg, 0, sizeof msg);
2193
 
   memset(&v1, 0, sizeof v1);
2194
 
 
2195
 
   Debug("%s: Enter.\n", __FUNCTION__);
2196
 
 
2197
 
   v1.windowID = windowID;
2198
 
   v1.chunkID = chunkID;
2199
 
   v1.data.data_val = (char *) data;
2200
 
   v1.data.data_len = len;
2201
 
 
2202
 
   msg.ver = UNITY_WINDOW_CONTENTS_V1;
2203
 
   msg.UnityWindowContentsChunk_u.chunkV1 = &v1;
2204
 
 
2205
 
   ret = UnityXdrSendRpc(UNITY_RPC_WINDOW_CONTENTS_CHUNK,
2206
 
                         &UnityXdrEncodeWindowContentsChunk,
2207
 
                         &msg);
2208
 
 
2209
 
   Debug("%s: Exit.\n", __FUNCTION__);
2210
 
   return ret;
2211
 
}
2212
 
 
2213
 
 
2214
 
/*
2215
 
 *------------------------------------------------------------------------------
2216
 
 *
2217
 
 * UnityXdrEncodeWindowContentsEnd --
2218
 
 *
2219
 
 *    XDR encoder function for UnityWindowContentsEnd.
2220
 
 *
2221
 
 * Results:
2222
 
 *    Returns true if the XDR struct was encoded successfully.
2223
 
 *
2224
 
 * Side effects:
2225
 
 *    None.
2226
 
 *------------------------------------------------------------------------------
2227
 
 */
2228
 
 
2229
 
Bool
2230
 
UnityXdrEncodeWindowContentsEnd(XDR *xdrs,
2231
 
                                void *arg)
2232
 
{
2233
 
   ASSERT(xdrs);
2234
 
   ASSERT(arg);
2235
 
   return xdr_UnityWindowContentsEnd(xdrs, (UnityWindowContentsEnd*) arg);
2236
 
}
2237
 
 
2238
 
 
2239
 
/*
2240
 
 *------------------------------------------------------------------------------
2241
 
 *
2242
 
 * UnitySendWindowContentsEnd --
2243
 
 *
2244
 
 *    Sends a unity.window.contents.end RPC to the host.
2245
 
 *
2246
 
 * Results:
2247
 
 *    Returns true if the RPC was sent successfully.
2248
 
 *
2249
 
 * Side effects:
2250
 
 *    None.
2251
 
 *
2252
 
 *------------------------------------------------------------------------------
2253
 
 */
2254
 
 
2255
 
Bool
2256
 
UnitySendWindowContentsEnd(UnityWindowId windowID)
2257
 
{
2258
 
   Bool ret = FALSE;
2259
 
   UnityWindowContentsEnd msg;
2260
 
   UnityWindowContentsEndV1 v1;
2261
 
   memset(&msg, sizeof msg, 0);
2262
 
   memset(&v1, sizeof v1, 0);
2263
 
 
2264
 
   Debug("%s: Enter.\n", __FUNCTION__);
2265
 
 
2266
 
   v1.windowID = windowID;
2267
 
 
2268
 
   msg.ver = UNITY_WINDOW_CONTENTS_V1;
2269
 
   msg.UnityWindowContentsEnd_u.endV1 = &v1;
2270
 
 
2271
 
   ret = UnityXdrSendRpc(UNITY_RPC_WINDOW_CONTENTS_END,
2272
 
                         &UnityXdrEncodeWindowContentsEnd,
2273
 
                         &msg);
2274
 
 
2275
 
   Debug("%s: Exit.\n", __FUNCTION__);
2276
 
   return ret;
2277
 
}
2278
 
 
2279
 
 
2280
 
/*
2281
 
 *------------------------------------------------------------------------------
2282
 
 *
2283
 
 * UnityXdrSendRpc --
2284
 
 *
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.
2288
 
 *
2289
 
 * Returns:
2290
 
 *    True if the RPC was sent successfully.
2291
 
 *
2292
 
 * Side effects:
2293
 
 *    None.
2294
 
 *
2295
 
 *------------------------------------------------------------------------------
2296
 
 */
2297
 
 
2298
 
Bool
2299
 
UnityXdrSendRpc(const char *rpcName,
2300
 
                UnityXdrEncodeFunc encodeFn,
2301
 
                void *data)
2302
 
{
2303
 
   Bool ret = FALSE;
2304
 
   XDR xdrs;
2305
 
   memset(&xdrs, 0, sizeof xdrs);
2306
 
 
2307
 
   ASSERT(rpcName);
2308
 
 
2309
 
   Debug("%s: Enter.\n", __FUNCTION__);
2310
 
 
2311
 
   if (!DynXdr_Create(&xdrs)) {
2312
 
      Debug("%s: Failed to create DynXdr.\n", __FUNCTION__);
2313
 
      goto exit;
2314
 
   }
2315
 
 
2316
 
   if (!DynXdr_AppendRaw(&xdrs, rpcName, strlen(rpcName))) {
2317
 
      Debug("%s: Failed to append RPC name to DynXdr.\n", __FUNCTION__);
2318
 
      goto dynxdr_destroy;
2319
 
   }
2320
 
 
2321
 
   if (!DynXdr_AppendRaw(&xdrs, " ", 1)) {
2322
 
      Debug("%s: Failed to append space to DynXdr.\n", __FUNCTION__);
2323
 
      goto dynxdr_destroy;
2324
 
   }
2325
 
 
2326
 
   if (!(*encodeFn)(&xdrs, data)) {
2327
 
      Debug("%s: Failed to serialize RPC data.\n", __FUNCTION__);
2328
 
      goto dynxdr_destroy;
2329
 
   }
2330
 
 
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;
2334
 
   }
2335
 
 
2336
 
   ret = TRUE;
2337
 
 
2338
 
dynxdr_destroy:
2339
 
   DynXdr_Destroy(&xdrs, TRUE);
2340
 
 
2341
 
exit:
2342
 
   Debug("%s: Exit.\n", __FUNCTION__);
2343
 
   return ret;
2344
 
}
2345
 
 
2346
 
 
2347
 
/*
2348
 
 *----------------------------------------------------------------------------
2349
 
 *
2350
 
 * UnityBuildUpdates --
2351
 
 *
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
2355
 
 *     to the host.
2356
 
 *
2357
 
 * Results:
2358
 
 *     TRUE if updates were added to the buffer and succesfully sent to the host.
2359
 
 *
2360
 
 * Side effects:
2361
 
 *     DynBuf is updated with serialized form of the updates.
2362
 
 *
2363
 
 *----------------------------------------------------------------------------
2364
 
 */
2365
 
 
2366
 
Bool
2367
 
UnityBuildUpdates(void *param,         // IN
2368
 
                  int flags)           // IN
2369
 
{
2370
 
   Bool retVal = TRUE;
2371
 
   UnityUpdateChannel *updateChannel = reinterpret_cast<UnityUpdateChannel*>(param);
2372
 
 
2373
 
   ASSERT(updateChannel);
2374
 
 
2375
 
   DynBuf_SetSize(&updateChannel->updates, updateChannel->cmdSize);
2376
 
   Unity_GetUpdates(flags);
2377
 
   /*
2378
 
    * Write the final '\0' to the DynBuf to signal that we're all out of
2379
 
    * updates.
2380
 
    */
2381
 
   DynBuf_AppendString(&updateChannel->updates, "");
2382
 
 
2383
 
   /*
2384
 
    * If there are no updates, Unity_GetUpdates appended an empty string, i.e. null.
2385
 
    */
2386
 
 
2387
 
   if (DynBuf_GetSize(&updateChannel->updates) > updateChannel->cmdSize + 1) {
2388
 
      if (!UnitySendUpdates(updateChannel)) {
2389
 
         retVal = FALSE;
2390
 
      }
2391
 
   }
2392
 
   return retVal;
2393
 
}
2394
 
 
2395
 
 
2396
 
/*
2397
 
 *------------------------------------------------------------------------------
2398
 
 *
2399
 
 * UnityShouldShowTaskbar --
2400
 
 *
2401
 
 *    Sends an RPC to retrieve whether the guest should show the taskbar and
2402
 
 *    returns the value.
2403
 
 *
2404
 
 * Results:
2405
 
 *    TRUE if the taskbar should be visible.
2406
 
 *
2407
 
 * Side effects:
2408
 
 *    None.
2409
 
 *
2410
 
 *------------------------------------------------------------------------------
2411
 
 */
2412
 
 
2413
 
Bool
2414
 
UnityShouldShowTaskbar()
2415
 
{
2416
 
   char *reply = NULL;
2417
 
   size_t replyLen;
2418
 
   Bool showTaskbar = FALSE;
2419
 
 
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",
2422
 
            __FUNCTION__);
2423
 
      showTaskbar = FALSE;
2424
 
   } else {
2425
 
      uint32 value = 0;
2426
 
 
2427
 
      if (StrUtil_StrToUint(&value, reply)) {
2428
 
         showTaskbar = (value == 0) ? FALSE : TRUE;
2429
 
      } else {
2430
 
         showTaskbar = FALSE;
2431
 
      }
2432
 
   }
2433
 
   return showTaskbar;
2434
 
}
2435
 
 
2436
 
} /* namespace tools */ } /* namespace vmware */