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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

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
 * ghiTclo.cpp --
 
21
 *
 
22
 *    Guest-host integration functions.
 
23
 */
 
24
 
 
25
#include "appUtil.h"
 
26
#include "ghIntegration.h"
 
27
#include "ghiTclo.h"
 
28
 
 
29
extern "C" {
 
30
#include "vmware.h"
 
31
#include "vmware/tools/guestrpc.h"
 
32
#include "debug.h"
 
33
#include "dynxdr.h"
 
34
#include "guest_msg_def.h"
 
35
#include "rpcin.h"
 
36
#include "rpcout.h"
 
37
#include "str.h"
 
38
#include "strutil.h"
 
39
#include "unityCommon.h"
 
40
#include "util.h"
 
41
#include "xdrutil.h"
 
42
};
 
43
 
 
44
#include "guestrpc/ghiGetBinaryHandlers.h"
 
45
#include "guestrpc/ghiGetExecInfoHash.h"
 
46
#include "guestrpc/ghiProtocolHandler.h"
 
47
#include "guestrpc/ghiSetFocusedWindow.h"
 
48
#include "guestrpc/ghiSetGuestHandler.h"
 
49
#include "guestrpc/ghiSetOutlookTempFolder.h"
 
50
#include "guestrpc/ghiShellAction.h"
 
51
#include "guestrpc/ghiStartMenu.h"
 
52
#include "guestrpc/ghiTrayIcon.h"
 
53
#include "vmware/guestrpc/capabilities.h"
 
54
 
 
55
static DynBuf gTcloUpdate;
 
56
 
 
57
/*
 
58
 * Overhead of encoding the icon data in a dynbuf - used to make sure we don't
 
59
 * exceed GUEST_MSG_MAX_IN_SIZE when serializing the icons for an app.
 
60
 */
 
61
static const int GHI_ICON_OVERHEAD = 1024;
 
62
 
 
63
 
 
64
/*
 
65
 *----------------------------------------------------------------------------
 
66
 *
 
67
 * GHITcloInit --
 
68
 *
 
69
 *     Initialize the global state (a Dynbuf) used to handle the TCLO parsing
 
70
 *     and dispatch.
 
71
 *
 
72
 * Results:
 
73
 *     None.
 
74
 *
 
75
 * Side effects:
 
76
 *     None.
 
77
 *
 
78
 *----------------------------------------------------------------------------
 
79
 */
 
80
 
 
81
void
 
82
GHITcloInit()
 
83
{
 
84
   DynBuf_Init(&gTcloUpdate);
 
85
}
 
86
 
 
87
 
 
88
/*
 
89
 *----------------------------------------------------------------------------
 
90
 *
 
91
 * GHITcloCleanup --
 
92
 *
 
93
 *     Cleanup the global state (a Dynbuf) used to handle the TCLO parsing
 
94
 *     and dispatch.
 
95
 *
 
96
 * Results:
 
97
 *     None.
 
98
 *
 
99
 * Side effects:
 
100
 *     None.
 
101
 *
 
102
 *----------------------------------------------------------------------------
 
103
 */
 
104
 
 
105
void
 
106
GHITcloCleanup()
 
107
{
 
108
   DynBuf_Destroy(&gTcloUpdate);
 
109
}
 
110
 
 
111
 
 
112
/*
 
113
 *----------------------------------------------------------------------------
 
114
 *
 
115
 * GHITcloGetBinaryInfo --
 
116
 *
 
117
 *     RPC handler for 'unity.get.binary.info'. Get required binary info
 
118
 *     and send it back to the VMX.
 
119
 *
 
120
 * Results:
 
121
 *     TRUE if everything is successful.
 
122
 *     FALSE otherwise.
 
123
 *
 
124
 * Side effects:
 
125
 *     None.
 
126
 *
 
127
 *----------------------------------------------------------------------------
 
128
 */
 
129
 
 
130
gboolean
 
131
GHITcloGetBinaryInfo(RpcInData *data)        // IN/OUT
 
132
{
 
133
   char *binaryPathUtf8;
 
134
   DynBuf *buf = &gTcloUpdate;
 
135
   DynBuf iconDataBuf;
 
136
   unsigned int index = 0;
 
137
   Bool ret = TRUE;
 
138
   std::string friendlyName;
 
139
   std::list<GHIBinaryIconInfo> iconList;
 
140
   char temp[128];   // Used to hold sizes and indices as strings
 
141
   uint32 serializedIconCount = 0;
 
142
 
 
143
   /* Check our arguments. */
 
144
   ASSERT(data);
 
145
   if (!data) {
 
146
      return FALSE;
 
147
   }
 
148
 
 
149
   ASSERT(data->name);
 
150
   ASSERT(data->args);
 
151
 
 
152
   if (!data->name || !data->args) {
 
153
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
154
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
155
   }
 
156
 
 
157
   Debug("%s name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
 
158
 
 
159
   /* Skip the leading space. */
 
160
   index++;
 
161
 
 
162
   /* The binary path provided by the VMX is in UTF8. */
 
163
   binaryPathUtf8 = StrUtil_GetNextToken(&index, data->args, "");
 
164
 
 
165
   if (!binaryPathUtf8) {
 
166
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
167
      ret = RPCIN_SETRETVALS(data,
 
168
                             "Invalid arguments. Expected \"binary_path\"",
 
169
                             FALSE);
 
170
      goto exit;
 
171
   }
 
172
 
 
173
   DynBuf_SetSize(buf, 0);
 
174
 
 
175
   if (!GHI_GetBinaryInfo(binaryPathUtf8, friendlyName, iconList)) {
 
176
      Debug("%s: Could not get binary info.\n", __FUNCTION__);
 
177
      ret = RPCIN_SETRETVALS(data,
 
178
                             "Could not get binary info",
 
179
                             FALSE);
 
180
      goto exit;
 
181
   }
 
182
 
 
183
   /*
 
184
    * Append the name to the output buffer now. If we fail to get the
 
185
    * icons, we still want to return the app name. Then the UI can display
 
186
    * the default icon and correct app name.
 
187
    *
 
188
    * The output buffer should look like this:
 
189
    * <name>\0<icon count>\0<width>\0<height>\0<size>\0<bgraData>\0...
 
190
    *
 
191
    * Note that the icon data is in BGRA format. An alpha channel value of 255 means
 
192
    * "fully opaque", and an alpha channel value of 0 means "fully transparent".
 
193
    */
 
194
 
 
195
   DynBuf_AppendString(buf, friendlyName.c_str());
 
196
 
 
197
   if (iconList.size() <= 0) {
 
198
      Debug("%s: Could not find any icons for path: %s", __FUNCTION__, binaryPathUtf8);
 
199
   }
 
200
 
 
201
   DynBuf_Init(&iconDataBuf);
 
202
   /* Copy icon info to the output buffer. */
 
203
   for (std::list<GHIBinaryIconInfo>::const_iterator it = iconList.begin();
 
204
        it != iconList.end();
 
205
        it++) {
 
206
      /*
 
207
       * XXX: The backdoor has a maximum RPC data size of 64K - don't attempt to send
 
208
       * icons larger than this size.
 
209
       */
 
210
      if ((DynBuf_GetSize(&iconDataBuf) + it->dataBGRA.size()) <
 
211
           GUESTMSG_MAX_IN_SIZE - GHI_ICON_OVERHEAD) {
 
212
         Str_Sprintf(temp, sizeof temp, "%u", it->width);
 
213
         DynBuf_AppendString(&iconDataBuf, temp);
 
214
 
 
215
         Str_Sprintf(temp, sizeof temp, "%u", it->height);
 
216
         DynBuf_AppendString(&iconDataBuf, temp);
 
217
 
 
218
         Str_Sprintf(temp, sizeof temp, "%u", (int32) it->dataBGRA.size());
 
219
         DynBuf_AppendString(&iconDataBuf, temp);
 
220
 
 
221
         DynBuf_Append(&iconDataBuf, &(it->dataBGRA[0]),
 
222
                       it->dataBGRA.size());
 
223
         DynBuf_AppendString(&iconDataBuf, "");
 
224
 
 
225
         serializedIconCount++;
 
226
      }
 
227
   }
 
228
 
 
229
   Str_Sprintf(temp, sizeof temp, "%d", serializedIconCount);
 
230
   DynBuf_AppendString(buf, temp);
 
231
 
 
232
   /* Append the icon data */
 
233
   DynBuf_Append(buf, DynBuf_Get(&iconDataBuf), DynBuf_GetSize(&iconDataBuf));
 
234
   DynBuf_Destroy(&iconDataBuf);
 
235
 
 
236
   /*
 
237
    * Write the final result into the result out parameters and return!
 
238
    */
 
239
   data->result = (char *)DynBuf_Get(buf);
 
240
   data->resultLen = DynBuf_GetSize(buf);
 
241
 
 
242
exit:
 
243
   free(binaryPathUtf8);
 
244
   return ret;
 
245
}
 
246
 
 
247
 
 
248
/*
 
249
 *----------------------------------------------------------------------------
 
250
 *
 
251
 * GHITcloGetBinaryHandlers --
 
252
 *
 
253
 *     RPC handler for 'unity.get.binary.handlers'. Get filetypes supported
 
254
 *     by the binary and send it back to the VMX.
 
255
 *
 
256
 * Results:
 
257
 *     TRUE if everything is successful.
 
258
 *     FALSE otherwise.
 
259
 *
 
260
 * Side effects:
 
261
 *     None.
 
262
 *
 
263
 *----------------------------------------------------------------------------
 
264
 */
 
265
 
 
266
gboolean
 
267
GHITcloGetBinaryHandlers(RpcInData *data)        // IN/OUT
 
268
{
 
269
   char *binaryPathUtf8;
 
270
   XDR xdrs;
 
271
   unsigned int index = 0;
 
272
   Bool ret = TRUE;
 
273
   GHIBinaryHandlersList *handlersList = NULL;
 
274
 
 
275
   /* Check our arguments. */
 
276
   ASSERT(data);
 
277
   if (!data) {
 
278
      return FALSE;
 
279
   }
 
280
 
 
281
   ASSERT(data->name);
 
282
   ASSERT(data->args);
 
283
 
 
284
   if (!data->name || !data->args) {
 
285
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
286
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
287
   }
 
288
 
 
289
   Debug("%s name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
 
290
 
 
291
   /* Skip the leading space. */
 
292
   index++;
 
293
 
 
294
   /* The binary path provided by the VMX is in UTF8. */
 
295
   binaryPathUtf8 = StrUtil_GetNextToken(&index, data->args, "");
 
296
 
 
297
   if (!binaryPathUtf8) {
 
298
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
299
      return RPCIN_SETRETVALS(data, "Invalid arguments. Expected \"binary_path\"", FALSE);
 
300
   }
 
301
 
 
302
   handlersList = (GHIBinaryHandlersList *) Util_SafeCalloc(1, sizeof *handlersList);
 
303
   ASSERT_MEM_ALLOC(DynXdr_Create(&xdrs));
 
304
 
 
305
#if !defined(OPEN_VM_TOOLS)
 
306
   FileTypeList::const_iterator fileTypeIterator;
 
307
   FileTypeList aFileTypeList;
 
308
 
 
309
   aFileTypeList = GHI_GetBinaryHandlers(binaryPathUtf8);
 
310
 
 
311
   /*
 
312
    * Take the list of filetypes handled by this application and convert it into
 
313
    * the XDR based structure that we'll then serialize
 
314
    */
 
315
 
 
316
   int fileTypeCount;
 
317
   for (fileTypeIterator = aFileTypeList.begin(), fileTypeCount = 0;
 
318
        (fileTypeIterator != aFileTypeList.end()) &&
 
319
         (fileTypeCount < GHI_MAX_NUM_BINARY_HANDLERS);
 
320
        ++fileTypeIterator, ++fileTypeCount)
 
321
   {
 
322
      std::string extension = (*fileTypeIterator)->Extension();
 
323
      size_t extensionStringLength = strlen(extension.c_str()) + 1;
 
324
      std::string actionURI = (*fileTypeIterator)->GetActionURIList().front();
 
325
      size_t actionURILength = strlen(actionURI.c_str()) + 1;
 
326
 
 
327
      /*
 
328
       * Copy the handlers suffix/extension string.
 
329
       */
 
330
      GHIBinaryHandlersDetails *aHandler = (GHIBinaryHandlersDetails *)
 
331
                                                XDRUTIL_ARRAYAPPEND(handlersList,
 
332
                                                                    handlers,
 
333
                                                                    1);
 
334
      ASSERT_MEM_ALLOC(aHandler);
 
335
      aHandler->suffix = (char *) Util_SafeCalloc(extensionStringLength,
 
336
                                                  sizeof *aHandler->suffix);
 
337
      Str_Strcpy(aHandler->suffix, extension.c_str(), extensionStringLength);
 
338
 
 
339
      /*
 
340
       * Empty strings for all the other 'type' fields. Note that we cannot leave the
 
341
       * string pointer as NULL, we must encode an empty string for XDR to work.
 
342
       */
 
343
      aHandler->mimetype = (char *) Util_SafeCalloc(1, sizeof *aHandler->mimetype);
 
344
      aHandler->mimetype[0] = '\0';
 
345
      aHandler->UTI = (char *) Util_SafeCalloc(1, sizeof *aHandler->UTI);
 
346
      aHandler->UTI[0] = '\0';
 
347
 
 
348
      /*
 
349
       * Set the Action URI and friendly name for this type
 
350
       */
 
351
      GHIBinaryHandlersActionURIPair *anActionPair = (GHIBinaryHandlersActionURIPair *)
 
352
                                                         XDRUTIL_ARRAYAPPEND(aHandler,
 
353
                                                                             actionURIs,
 
354
                                                                             1);
 
355
      ASSERT_MEM_ALLOC(anActionPair);
 
356
      anActionPair->actionURI = (char *) Util_SafeCalloc(actionURILength,
 
357
                                                         sizeof *anActionPair->actionURI);
 
358
      Str_Strcpy(anActionPair->actionURI, actionURI.c_str(), actionURILength);
 
359
      anActionPair->verb = Util_SafeStrdup("run");
 
360
 
 
361
      std::string friendlyName = (*fileTypeIterator)->FriendlyName();
 
362
      size_t friendlyNameLength = strlen(friendlyName.c_str()) + 1;
 
363
      aHandler->friendlyName = (char *) Util_SafeCalloc(friendlyNameLength,
 
364
                                                        sizeof *aHandler->friendlyName);
 
365
      Str_Strcpy(aHandler->friendlyName, friendlyName.c_str(), friendlyNameLength);
 
366
 
 
367
      /*
 
368
       * Store the list of icon dimensions and URIs.
 
369
       * TODO: Retrieve the list of icons and their dimensions for this filetype.
 
370
       */
 
371
   }
 
372
#endif // OPEN_VM_TOOLS
 
373
 
 
374
   GHIBinaryHandlers message;
 
375
   message.ver = GHI_BINARY_HANDLERS_V1;
 
376
   message.GHIBinaryHandlers_u.handlersV1 = handlersList;
 
377
 
 
378
   ret = xdr_GHIBinaryHandlers(&xdrs, &message);
 
379
   if (ret == FALSE) {
 
380
      Debug("%s: Failed to serialize binary handlers list.\n", __FUNCTION__);
 
381
      ret = RPCIN_SETRETVALS(data, "Failed to serialize binary handlers list.", FALSE);
 
382
      goto exitWithXDRCleanup;
 
383
   }
 
384
 
 
385
   /*
 
386
    * If the serialized data exceeds our maximum message size we have little choice
 
387
    * but to fail the request and log the oversize message.
 
388
    */
 
389
   if (xdr_getpos(&xdrs) > GUESTMSG_MAX_IN_SIZE) {
 
390
      ret = RPCIN_SETRETVALS(data, "Filetype list too large", FALSE);
 
391
      goto exitWithXDRCleanup;
 
392
   }
 
393
 
 
394
   /*
 
395
    * Write the final result into the result out parameters and return!
 
396
    */
 
397
    data->result = reinterpret_cast<char *>(DynXdr_Get(&xdrs));
 
398
    data->resultLen = xdr_getpos(&xdrs);
 
399
    data->freeResult = TRUE;
 
400
    ret = TRUE;
 
401
 
 
402
exitWithXDRCleanup:
 
403
   VMX_XDR_FREE(xdr_GHIBinaryHandlers, &message);
 
404
    /*
 
405
     * Destroy the XDR structure but leave the data buffer alone since it will be
 
406
     * freed by the RpcIn layer.
 
407
     */
 
408
    DynXdr_Destroy(&xdrs, FALSE);
 
409
   free(binaryPathUtf8);
 
410
   return ret;
 
411
}
 
412
 
 
413
 
 
414
/*
 
415
 *----------------------------------------------------------------------------
 
416
 *
 
417
 * GHITcloOpenStartMenu --
 
418
 *
 
419
 *     RPC handler for 'unity.launchmenu.open'. Get the start menu sub-tree
 
420
 *     for a given item, save it in the array so it can be accessed
 
421
 *     later when the VMX needs to iterate over the items. Return the count
 
422
 *     of the items in the sub-tree and a handle to this sub-tree. The handle
 
423
 *     will be used by the VMX to iterate over the sub-items.
 
424
 *
 
425
 * Results:
 
426
 *     TRUE if everything is successful.
 
427
 *     FALSE otherwise.
 
428
 *
 
429
 * Side effects:
 
430
 *     None.
 
431
 *
 
432
 *----------------------------------------------------------------------------
 
433
 */
 
434
 
 
435
gboolean
 
436
GHITcloOpenStartMenu(RpcInData *data)        // IN/OUT
 
437
{
 
438
   char *rootUtf8 = NULL;
 
439
   DynBuf *buf = &gTcloUpdate;
 
440
   uint32 flags = 0;
 
441
   uint32 index = 0;
 
442
   Bool ret = TRUE;
 
443
 
 
444
   /* Check our arguments. */
 
445
   ASSERT(data);
 
446
   if (!data) {
 
447
      return FALSE;
 
448
   }
 
449
 
 
450
   ASSERT(data->name);
 
451
   ASSERT(data->args);
 
452
 
 
453
   if (!data->name || !data->args) {
 
454
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
455
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
456
   }
 
457
 
 
458
   Debug("%s name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
 
459
 
 
460
   /* Skip the leading space. */
 
461
   index++;
 
462
 
 
463
   /* The start menu root provided by the VMX is in UTF8. */
 
464
   rootUtf8 = StrUtil_GetNextToken(&index, data->args, "");
 
465
 
 
466
   if (!rootUtf8) {
 
467
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
468
      ret = RPCIN_SETRETVALS(data,
 
469
                             "Invalid arguments. Expected \"root\"",
 
470
                             FALSE);
 
471
      goto exit;
 
472
   }
 
473
 
 
474
   /*
 
475
    * Skip the NULL after the root, and look for the flags. Old versions of
 
476
    * the VMX don't send this parameter, so it's not an error if it is not
 
477
    * present in the RPC.
 
478
    */
 
479
   if (++index < data->argsSize && sscanf(data->args + index, "%u", &flags) != 1) {
 
480
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
481
      ret = RPCIN_SETRETVALS(data,
 
482
                             "Invalid arguments. Expected flags",
 
483
                             FALSE);
 
484
      goto exit;
 
485
   }
 
486
 
 
487
   DynBuf_SetSize(buf, 0);
 
488
   if (!GHI_OpenStartMenuTree(rootUtf8, flags, buf)) {
 
489
      Debug("%s: Could not open start menu.\n", __FUNCTION__);
 
490
      ret = RPCIN_SETRETVALS(data,
 
491
                             "Could not get start menu count",
 
492
                             FALSE);
 
493
      goto exit;
 
494
   }
 
495
 
 
496
   /*
 
497
    * Write the final result into the result out parameters and return!
 
498
    */
 
499
   data->result = (char *)DynBuf_Get(buf);
 
500
   data->resultLen = DynBuf_GetSize(buf);
 
501
 
 
502
exit:
 
503
   free(rootUtf8);
 
504
   return ret;
 
505
}
 
506
 
 
507
 
 
508
/*
 
509
 *----------------------------------------------------------------------------
 
510
 *
 
511
 * GHITcloGetStartMenuItem --
 
512
 *
 
513
 *     RPC handler for 'unity.launchmenu.next'. Get the start menu item
 
514
 *     at the given index for the tree with a given handle.
 
515
 *     If there's no item at the given index, return FALSE.
 
516
 *
 
517
 * Results:
 
518
 *     TRUE if the item was found.
 
519
 *     FALSE otherwise (i.e. if the VMX provides a wrong handle or if there's
 
520
                        no items left).
 
521
 *
 
522
 * Side effects:
 
523
 *     None.
 
524
 *
 
525
 *----------------------------------------------------------------------------
 
526
 */
 
527
 
 
528
gboolean
 
529
GHITcloGetStartMenuItem(RpcInData *data)        // IN/OUT
 
530
{
 
531
   DynBuf *buf = &gTcloUpdate;
 
532
   uint32 index = 0;
 
533
   Bool ret = TRUE;
 
534
   uint32 itemIndex = 0;
 
535
   uint32 handle = 0;
 
536
 
 
537
   /* Check our arguments. */
 
538
   ASSERT(data);
 
539
   if (!data) {
 
540
      return FALSE;
 
541
   }
 
542
 
 
543
   ASSERT(data->name);
 
544
   ASSERT(data->args);
 
545
 
 
546
   if (!data->name || !data->args) {
 
547
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
548
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
549
   }
 
550
 
 
551
   Debug("%s name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
 
552
 
 
553
   /* Parse the handle of the menu tree that VMX wants. */
 
554
   if (!StrUtil_GetNextUintToken(&handle, &index, data->args, " ")) {
 
555
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
556
      return RPCIN_SETRETVALS(data,
 
557
                              "Invalid arguments. Expected handle index",
 
558
                              FALSE);
 
559
   }
 
560
 
 
561
   /* The index of the menu item to be send back. */
 
562
   if (!StrUtil_GetNextUintToken(&itemIndex, &index, data->args, " ")) {
 
563
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
564
      return RPCIN_SETRETVALS(data,
 
565
                              "Invalid arguments. Expected handle index",
 
566
                              FALSE);
 
567
   }
 
568
 
 
569
   DynBuf_SetSize(buf, 0);
 
570
   if (!GHI_GetStartMenuItem(handle, itemIndex, buf)) {
 
571
      Debug("%s: Could not get start menu item.\n", __FUNCTION__);
 
572
      return RPCIN_SETRETVALS(data,
 
573
                              "Could not get start menu item",
 
574
                              FALSE);
 
575
   }
 
576
 
 
577
   /*
 
578
    * Write the final result into the result out parameters and return!
 
579
    */
 
580
   data->result = (char *)DynBuf_Get(buf);
 
581
   data->resultLen = DynBuf_GetSize(buf);
 
582
 
 
583
   return ret;
 
584
}
 
585
 
 
586
 
 
587
/*
 
588
 *----------------------------------------------------------------------------
 
589
 *
 
590
 * GHITcloCloseStartMenu --
 
591
 *
 
592
 *     RPC handler for 'unity.launchmenu.close'. The VMX is done with this
 
593
 *     particular start menu tree. Free all memory and cleanup.
 
594
 *
 
595
 * Results:
 
596
 *     None.
 
597
 *
 
598
 * Side effects:
 
599
 *     Memory allocated when the start menu tree was opened is finally freed.
 
600
 *
 
601
 *----------------------------------------------------------------------------
 
602
 */
 
603
 
 
604
gboolean
 
605
GHITcloCloseStartMenu(RpcInData *data)        // IN/OUT
 
606
{
 
607
   uint32 index = 0;
 
608
   int32 handle = 0;
 
609
 
 
610
   /* Check our arguments. */
 
611
   ASSERT(data);
 
612
   if (!data) {
 
613
      return FALSE;
 
614
   }
 
615
 
 
616
   ASSERT(data->name);
 
617
   ASSERT(data->args);
 
618
 
 
619
   if (!data->name || !data->args) {
 
620
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
621
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
622
   }
 
623
 
 
624
   Debug("%s name:%s args:'%s'\n", __FUNCTION__, data->name, data->args);
 
625
 
 
626
   /* Parse the handle of the menu tree that VMX wants. */
 
627
   if (!StrUtil_GetNextIntToken(&handle, &index, data->args, " ")) {
 
628
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
629
      return RPCIN_SETRETVALS(data,
 
630
                              "Invalid arguments. Expected handle",
 
631
                              FALSE);
 
632
   }
 
633
 
 
634
   GHI_CloseStartMenuTree(handle);
 
635
 
 
636
   return RPCIN_SETRETVALS(data, "", TRUE);
 
637
}
 
638
 
 
639
 
 
640
/*
 
641
 *----------------------------------------------------------------------------
 
642
 *
 
643
 * GHITcloShellOpen --
 
644
 *
 
645
 *     RPC handler for 'unity.shell.open'. Open the specified file with the
 
646
 *     default shell handler. Note that the file path may be either a URI
 
647
 *     (originated with Tools >= NNNNN), or a regular path (originated with
 
648
 *     Tools < NNNNN).
 
649
 *
 
650
 * Results:
 
651
 *     TRUE if everything is successful.
 
652
 *     FALSE otherwise.
 
653
 *
 
654
 * Side effects:
 
655
 *     None.
 
656
 *
 
657
 *----------------------------------------------------------------------------
 
658
 */
 
659
 
 
660
gboolean
 
661
GHITcloShellOpen(RpcInData *data)    // IN/OUT
 
662
{
 
663
   char *fileUtf8 = NULL;
 
664
   Bool ret = TRUE;
 
665
   unsigned int index = 0;
 
666
 
 
667
   /* Check our arguments. */
 
668
   ASSERT(data);
 
669
   if (!data) {
 
670
      return FALSE;
 
671
   }
 
672
 
 
673
   ASSERT(data->name);
 
674
   ASSERT(data->args);
 
675
 
 
676
   if (!data->name || !data->args) {
 
677
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
678
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
679
   }
 
680
 
 
681
   Debug("%s: name: '%s', args: '%s'\n", __FUNCTION__, data->name, data->args);
 
682
 
 
683
   /* Skip the leading space. */
 
684
   index++;
 
685
 
 
686
   /* The file path provided by the VMX is in UTF8. */
 
687
   fileUtf8 = StrUtil_GetNextToken(&index, data->args, "");
 
688
 
 
689
   if (!fileUtf8) {
 
690
      Debug("%s: Invalid RPC arguments.\n", __FUNCTION__);
 
691
      return RPCIN_SETRETVALS(data,
 
692
                              "Invalid arguments. Expected file_name",
 
693
                              FALSE);
 
694
   }
 
695
 
 
696
   ret = GHI_ShellOpen(fileUtf8);
 
697
   free(fileUtf8);
 
698
 
 
699
   if (!ret) {
 
700
      Debug("%s: Could not perform the requested shell open action.\n", __FUNCTION__);
 
701
      return RPCIN_SETRETVALS(data,
 
702
                              "Could not perform the requested shell open action.",
 
703
                              FALSE);
 
704
   }
 
705
 
 
706
   return RPCIN_SETRETVALS(data, "", TRUE);
 
707
}
 
708
 
 
709
 
 
710
/*
 
711
 *----------------------------------------------------------------------------
 
712
 *
 
713
 * GHITcloShellAction --
 
714
 *
 
715
 *     RPC handler for "ghi.guest.shell.action". The action command has three
 
716
 *     arguments: an action URI, a target URI, and an array of location URIs.
 
717
 *     Action URIs are in the form: "x-vmware-action://<verb>", where <verb> is
 
718
 *     the name of a specific action to perform.
 
719
 *     The target URI is a guest-specific URI that was previously given to the
 
720
 *     host (usually a path to an application to run). Note that this may be
 
721
 *     either a URI (new Tools) or a regular path (old Tools).
 
722
 *     The locations can be files or URLs. Files are typically specified as
 
723
 *     HGFS shared folder locations (see below), but can potentially use the
 
724
 *     "file://<path>" URIs as well.
 
725
 *     Each guest can specify the features it supports using capability flags:
 
726
 *
 
727
 *     Capability                      Description
 
728
 *
 
729
 *     GHI_CAP_CMD_SHELL_ACTION        Guest allows 'ghi.guest.shell.action'.
 
730
 *                                     This encompasses this entire command
 
731
 *                                     and the rest of the capabilities.
 
732
 *
 
733
 *     GHI_CAP_SHELL_ACTION_BROWSE     Guest supports the 'browse' action verb,
 
734
 *                                     used to open a file browser window with
 
735
 *                                     a given set of locations.
 
736
 *
 
737
 *     GHI_CAP_SHELL_ACTION_RUN        Guest supports the 'run' action verb,
 
738
 *                                     used for running applications as well
 
739
 *                                     as opening file or URL locations.
 
740
 *
 
741
 *     GHI_CAP_SHELL_LOCATION_HGFS     Guest supports HGFS share location URIs:
 
742
 *                                     "x-vmware-share://<path>", where <path>
 
743
 *                                     specifies a shared folder name and an
 
744
 *                                     optional path within the shared folder.
 
745
 *
 
746
 * Results:
 
747
 *     TRUE if everything is successful.
 
748
 *     FALSE otherwise.
 
749
 *
 
750
 * Side effects:
 
751
 *     None.
 
752
 *
 
753
 *----------------------------------------------------------------------------
 
754
 */
 
755
 
 
756
gboolean
 
757
GHITcloShellAction(RpcInData *data)    // IN/OUT
 
758
{
 
759
   Bool ret = TRUE;
 
760
   GHIShellAction shellActionMsg;
 
761
   GHIShellActionV1 *shellActionV1Ptr;
 
762
   memset(&shellActionMsg, 0, sizeof shellActionMsg);
 
763
 
 
764
   /* Check our arguments. */
 
765
   ASSERT(data);
 
766
   if (!data) {
 
767
      return FALSE;
 
768
   }
 
769
 
 
770
   ASSERT(data->name);
 
771
   ASSERT(data->args);
 
772
 
 
773
   if (!data->name || !data->args) {
 
774
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
775
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
776
   }
 
777
 
 
778
   /*
 
779
    * Build an XDR Stream from the argument data which begins are args + 1
 
780
    * since there is a space separator between the RPC name and the XDR serialization.
 
781
    */
 
782
   if (!XdrUtil_Deserialize((char *)data->args + 1, data->argsSize - 1,
 
783
                            (void *)xdr_GHIShellAction, &shellActionMsg)) {
 
784
      Debug("%s: Failed to deserialize data\n", __FUNCTION__);
 
785
      ret = RPCIN_SETRETVALS(data,
 
786
                             "Failed to deserialize data.",
 
787
                             FALSE);
 
788
      goto exit;
 
789
   }
 
790
 
 
791
   ASSERT(shellActionMsg.ver == GHI_SHELL_ACTION_V1);
 
792
   if (shellActionMsg.ver != GHI_SHELL_ACTION_V1) {
 
793
      Debug("%s: Unexpected XDR version = %d\n", __FUNCTION__, shellActionMsg.ver);
 
794
      ret = RPCIN_SETRETVALS(data,
 
795
                             "Unexpected XDR version.",
 
796
                             FALSE);
 
797
      goto exit;
 
798
   }
 
799
 
 
800
   shellActionV1Ptr = shellActionMsg.GHIShellAction_u.actionV1;
 
801
   ret = GHI_ShellAction(shellActionV1Ptr->actionURI,
 
802
                         shellActionV1Ptr->targetURI,
 
803
                         (const char **)shellActionV1Ptr->locations.locations_val,
 
804
                         shellActionV1Ptr->locations.locations_len);
 
805
   if (!ret) {
 
806
      Debug("%s: Could not perform the requested shell action.\n", __FUNCTION__);
 
807
      ret = RPCIN_SETRETVALS(data,
 
808
                             "Could not perform the requested shell action.",
 
809
                             FALSE);
 
810
      goto exit;
 
811
   }
 
812
 
 
813
   ret = RPCIN_SETRETVALS(data, "", TRUE);
 
814
 
 
815
exit:
 
816
   VMX_XDR_FREE(xdr_GHIShellAction, &shellActionMsg);
 
817
 
 
818
   return ret;
 
819
}
 
820
 
 
821
 
 
822
/*
 
823
 *----------------------------------------------------------------------------
 
824
 *
 
825
 * GHITcloSetGuestHandler --
 
826
 *
 
827
 *     RPC handler for 'ghi.guest.handler.set'. Changes the nominated handlerType
 
828
 *     to use the VMwareHostOpen proxy app to open files or URLs in the host.
 
829
 *
 
830
 * Results:
 
831
 *     TRUE if everything is successful.
 
832
 *     FALSE otherwise.
 
833
 *
 
834
 * Side effects:
 
835
 *     None.
 
836
 *
 
837
 *----------------------------------------------------------------------------
 
838
 */
 
839
 
 
840
gboolean
 
841
GHITcloSetGuestHandler(RpcInData *data)        // IN/OUT
 
842
{
 
843
   Bool ret = FALSE;
 
844
   XDR xdrs;
 
845
 
 
846
   /* Check our arguments. */
 
847
   ASSERT(data);
 
848
   if (!data) {
 
849
      return FALSE;
 
850
   }
 
851
 
 
852
   ASSERT(data->name);
 
853
   ASSERT(data->args);
 
854
 
 
855
   if (!data->name || !data->args) {
 
856
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
857
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
858
   }
 
859
 
 
860
   Debug("%s name:%s args length: %"FMTSZ"u\n", __FUNCTION__, data->name, data->argsSize);
 
861
 
 
862
   /*
 
863
    * Build an XDR Stream from the argument data which beings are args + 1
 
864
    * since there is a space separator between the RPC name and the XDR serialization.
 
865
    */
 
866
   xdrmem_create(&xdrs, (char *) data->args + 1, data->argsSize - 1, XDR_DECODE);
 
867
 
 
868
   GHISetGuestHandler setGuestHandlerMsg;
 
869
   GHISetGuestHandlerV1 *setGuestHandlerV1Ptr;
 
870
   GHISetGuestHandlerAction *aHandlerAction;
 
871
 
 
872
   memset(&setGuestHandlerMsg, 0, sizeof setGuestHandlerMsg);
 
873
   if (!xdr_GHISetGuestHandler(&xdrs, &setGuestHandlerMsg)) {
 
874
      Debug("%s: Unable to deserialize data\n", __FUNCTION__);
 
875
      ret = RPCIN_SETRETVALS(data, "Unable to deserialize data.", FALSE);
 
876
      goto exitWithXDRCleanup;
 
877
   }
 
878
 
 
879
   ASSERT(setGuestHandlerMsg.ver == GHI_SET_GUEST_HANDLER_V1);
 
880
   setGuestHandlerV1Ptr = setGuestHandlerMsg.GHISetGuestHandler_u.guestHandlerV1;
 
881
   aHandlerAction = setGuestHandlerV1Ptr->actionURIs.actionURIs_val;
 
882
 
 
883
   ret = GHI_SetGuestHandler(setGuestHandlerV1Ptr->suffix,
 
884
                             setGuestHandlerV1Ptr->mimetype,
 
885
                             setGuestHandlerV1Ptr->UTI,
 
886
                             aHandlerAction->actionURI,
 
887
                             aHandlerAction->targetURI);
 
888
 
 
889
   if (ret == FALSE) {
 
890
      Debug("%s: Unable to set guest handler\n", __FUNCTION__);
 
891
      ret = RPCIN_SETRETVALS(data, "Unable to set guest handler", FALSE);
 
892
      goto exitWithXDRCleanup;
 
893
   }
 
894
   /*
 
895
    * Write the final result into the result out parameters and return!
 
896
    */
 
897
    data->result = "";
 
898
    data->resultLen = 0;
 
899
    data->freeResult = FALSE;
 
900
    ret = TRUE;
 
901
 
 
902
exitWithXDRCleanup:
 
903
   VMX_XDR_FREE(xdr_GHISetGuestHandler, &setGuestHandlerMsg);
 
904
   xdr_destroy(&xdrs);
 
905
   return ret;
 
906
}
 
907
 
 
908
 
 
909
/*
 
910
 *----------------------------------------------------------------------------
 
911
 *
 
912
 * GHITcloRestoreDefaultGuestHandler --
 
913
 *
 
914
 *     RPC handler for 'ghi.guest.handler.restoreDefault'. Changes the nominated
 
915
 *     handlerType back to the value in use prior to any changes by tools.
 
916
 *
 
917
 * Results:
 
918
 *     TRUE if everything is successful.
 
919
 *     FALSE otherwise.
 
920
 *
 
921
 * Side effects:
 
922
 *     None.
 
923
 *
 
924
 *----------------------------------------------------------------------------
 
925
 */
 
926
 
 
927
gboolean
 
928
GHITcloRestoreDefaultGuestHandler(RpcInData *data)        // IN/OUT
 
929
{
 
930
   Bool ret = FALSE;
 
931
   XDR xdrs;
 
932
 
 
933
   /* Check our arguments. */
 
934
   ASSERT(data);
 
935
   if (!data) {
 
936
      return FALSE;
 
937
   }
 
938
 
 
939
   ASSERT(data->name);
 
940
   ASSERT(data->args);
 
941
 
 
942
   if (!data->name || !data->args) {
 
943
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
944
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
945
   }
 
946
 
 
947
   Debug("%s name:%s args length: %"FMTSZ"u\n", __FUNCTION__, data->name, data->argsSize);
 
948
 
 
949
   /*
 
950
    * Build an XDR Stream from the argument data which beings are args + 1
 
951
    * since there is a space separator between the RPC name and the XDR serialization.
 
952
    */
 
953
   xdrmem_create(&xdrs, (char *) data->args + 1, data->argsSize - 1, XDR_DECODE);
 
954
 
 
955
   GHIRestoreDefaultGuestHandler restoreMsg;
 
956
   GHIRestoreDefaultGuestHandlerV1 *restoreV1Ptr = NULL;
 
957
 
 
958
   memset(&restoreMsg, 0, sizeof restoreMsg);
 
959
   if (!xdr_GHIRestoreDefaultGuestHandler(&xdrs, &restoreMsg)) {
 
960
      Debug("%s: Unable to deserialize data\n", __FUNCTION__);
 
961
      ret = RPCIN_SETRETVALS(data, "Unable to deserialize data", FALSE);
 
962
      goto exit;
 
963
   }
 
964
 
 
965
   ASSERT(restoreMsg.ver == GHI_SET_GUEST_HANDLER_V1);
 
966
   restoreV1Ptr = restoreMsg.GHIRestoreDefaultGuestHandler_u.defaultHandlerV1;
 
967
 
 
968
   ret = GHI_RestoreDefaultGuestHandler(restoreV1Ptr->suffix,
 
969
                                        restoreV1Ptr->mimetype,
 
970
                                        restoreV1Ptr->UTI);
 
971
   if (ret == FALSE) {
 
972
      Debug("%s: Unable to restore guest handler\n", __FUNCTION__);
 
973
      ret = RPCIN_SETRETVALS(data, "Unable to restore guest handler", FALSE);
 
974
      goto exit;
 
975
   }
 
976
   /*
 
977
    * Write the final result into the result out parameters and return!
 
978
    */
 
979
   data->result = "";
 
980
   data->resultLen = 0;
 
981
   data->freeResult = FALSE;
 
982
   ret = TRUE;
 
983
 
 
984
exit:
 
985
   xdr_destroy(&xdrs);
 
986
   VMX_XDR_FREE(xdr_GHIRestoreDefaultGuestHandler, &restoreMsg);
 
987
   return ret;
 
988
}
 
989
 
 
990
 
 
991
/*
 
992
 *----------------------------------------------------------------------------
 
993
 *
 
994
 * GHILaunchMenuChangeRPC --
 
995
 *
 
996
 *     Informs host that one or more Launch Menu changes have been detected.
 
997
 *
 
998
 * Results:
 
999
 *     TRUE on success
 
1000
 *     FALSE on error
 
1001
 *
 
1002
 * Side effects:
 
1003
 *     None.
 
1004
 *
 
1005
 *----------------------------------------------------------------------------
 
1006
 */
 
1007
 
 
1008
Bool
 
1009
GHILaunchMenuChangeRPC(int numFolderKeys,                // IN
 
1010
                       const char **folderKeysChanged)   // IN
 
1011
{
 
1012
   /* +1 for the space separator */
 
1013
   char request[sizeof GHI_RPC_LAUNCHMENU_CHANGE + 1];
 
1014
   XDR xdrs;
 
1015
   GHIStartMenuChanged startMenuChanged;
 
1016
   GHIStartMenuChangedV1 smcv1;
 
1017
   Bool status;
 
1018
 
 
1019
   /*
 
1020
    * Note: The primary contents of the startMenuChanged - the folder keys,
 
1021
    * are allocated and tracked outside of this function, there's no need to call
 
1022
    * VMX_XDR_FREE here for the XDR contents, in fact if called it will delete memory
 
1023
    * from other parts of the system.
 
1024
    */
 
1025
 
 
1026
   memset(&startMenuChanged, 0, sizeof startMenuChanged);
 
1027
   memset(&smcv1, 0, sizeof smcv1);
 
1028
 
 
1029
   ASSERT_MEM_ALLOC(DynXdr_Create(&xdrs));
 
1030
 
 
1031
   smcv1.keys.keys_len = numFolderKeys;
 
1032
   smcv1.keys.keys_val = (char **) folderKeysChanged;
 
1033
 
 
1034
   startMenuChanged.ver = GHI_STARTMENU_CHANGED_V1;
 
1035
   startMenuChanged.GHIStartMenuChanged_u.ghiStartMenuChangedV1 = &smcv1;
 
1036
 
 
1037
   Str_Sprintf(request,
 
1038
               sizeof request,
 
1039
               "%s ",
 
1040
               GHI_RPC_LAUNCHMENU_CHANGE);
 
1041
 
 
1042
   /* Write preamble and serialized changed folder keys to XDR stream. */
 
1043
   if (!DynXdr_AppendRaw(&xdrs, request, strlen(request)) ||
 
1044
       !xdr_GHIStartMenuChanged(&xdrs, &startMenuChanged)) {
 
1045
      Debug("%s: could not serialize protocol handler info\n", __FUNCTION__);
 
1046
      DynXdr_Destroy(&xdrs, TRUE);
 
1047
      return FALSE;
 
1048
   }
 
1049
 
 
1050
   status = RpcOut_SendOneRaw(DynXdr_Get(&xdrs),
 
1051
                              xdr_getpos(&xdrs),
 
1052
                              NULL,
 
1053
                              NULL);
 
1054
   DynXdr_Destroy(&xdrs, TRUE);
 
1055
 
 
1056
   if (!status) {
 
1057
      Debug("%s: could not send unity launchmenu change\n", __FUNCTION__);
 
1058
   }
 
1059
   return status;
 
1060
}
 
1061
 
 
1062
 
 
1063
/*
 
1064
 *----------------------------------------------------------------------------
 
1065
 *
 
1066
 * GHITcloSetOutlookTempFolder --
 
1067
 *
 
1068
 *    Handler for the 'ghi.guest.outlook.set.tempFolder' RPC.
 
1069
 *
 
1070
 * Results:
 
1071
 *    If the RPC fails, return FALSE. Otherwise, returns TRUE.
 
1072
 *
 
1073
 * Side effects:
 
1074
 *     None.
 
1075
 *
 
1076
 *----------------------------------------------------------------------------
 
1077
 */
 
1078
 
 
1079
gboolean
 
1080
GHITcloSetOutlookTempFolder(RpcInData *data) // IN/OUT: RPC data
 
1081
{
 
1082
   Bool ret = FALSE;
 
1083
   XDR xdrs;
 
1084
 
 
1085
   Debug("%s: Enter.\n", __FUNCTION__);
 
1086
 
 
1087
   /* Check our arguments. */
 
1088
   ASSERT(data);
 
1089
   if (!data) {
 
1090
      return FALSE;
 
1091
   }
 
1092
 
 
1093
   ASSERT(data->name);
 
1094
   ASSERT(data->args);
 
1095
 
 
1096
   if (!data->name || !data->args) {
 
1097
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
1098
      return RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
1099
   }
 
1100
 
 
1101
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
 
1102
         __FUNCTION__, data->name, data->argsSize);
 
1103
 
 
1104
   /*
 
1105
    * Build an XDR stream from the argument data.
 
1106
    *
 
1107
    * Note that the argument data begins with args + 1 since there is a space
 
1108
    * between the RPC name and the XDR serialization.
 
1109
    */
 
1110
   xdrmem_create(&xdrs, (char*) data->args + 1, data->argsSize - 1, XDR_DECODE);
 
1111
 
 
1112
   /* Deserialize the XDR into a GHISetOutlookTempFolder struct. */
 
1113
   GHISetOutlookTempFolder folderMsg;
 
1114
   GHISetOutlookTempFolderV1 *folderV1Ptr = NULL;
 
1115
 
 
1116
   memset(&folderMsg, 0, sizeof folderMsg);
 
1117
   if (!xdr_GHISetOutlookTempFolder(&xdrs, &folderMsg)) {
 
1118
      Debug("%s: Unable to deserialize data\n", __FUNCTION__);
 
1119
      ret = RPCIN_SETRETVALS(data, "Unable to deserialize data", FALSE);
 
1120
      goto exit;
 
1121
   }
 
1122
 
 
1123
   /*
 
1124
    * Get the structure for v1 of the GHISetOutlookTempFolder XDR from the union
 
1125
    * in the GHISetOutlookTempFolder struct.
 
1126
    */
 
1127
   ASSERT(folderMsg.ver == GHI_SET_OUTLOOK_TEMP_FOLDER_V1);
 
1128
   folderV1Ptr = folderMsg.GHISetOutlookTempFolder_u.setOutlookTempFolderV1;
 
1129
 
 
1130
   // Call the platform implementation of our RPC.
 
1131
   ret = GHI_SetOutlookTempFolder(folderV1Ptr->targetURI);
 
1132
   if (ret == FALSE) {
 
1133
      Debug("%s: Failed to set Outlook temporary folder.\n", __FUNCTION__);
 
1134
      ret = RPCIN_SETRETVALS(data, "Failed to set Outlook temporary folder", FALSE);
 
1135
      goto exit;
 
1136
   }
 
1137
 
 
1138
   /*
 
1139
    * We don't have any out parameters, so we write empty values into the
 
1140
    * result fields of the RpcInData structure.
 
1141
    */
 
1142
   RPCIN_SETRETVALS(data, "", FALSE);
 
1143
 
 
1144
   // Set our return value and return to the caller.
 
1145
   ret = TRUE;
 
1146
 
 
1147
exit:
 
1148
   // Destroy the XDR stream.
 
1149
   xdr_destroy(&xdrs);
 
1150
   VMX_XDR_FREE(xdr_GHISetOutlookTempFolder, &folderMsg);
 
1151
   Debug("%s: Exit.\n", __FUNCTION__);
 
1152
   return ret;
 
1153
}
 
1154
 
 
1155
 
 
1156
/*
 
1157
 *----------------------------------------------------------------------------
 
1158
 *
 
1159
 * GHITcloRestoreOutlookTempFolder --
 
1160
 *
 
1161
 *    Handler for the 'ghi.guest.outlook.restore.tempFolder' RPC.
 
1162
 *
 
1163
 * Results:
 
1164
 *    If the RPC fails, return FALSE. Otherwise, returns TRUE.
 
1165
 *
 
1166
 * Side effects:
 
1167
 *     None.
 
1168
 *
 
1169
 *----------------------------------------------------------------------------
 
1170
 */
 
1171
 
 
1172
gboolean
 
1173
GHITcloRestoreOutlookTempFolder(RpcInData *data) // IN/OUT: RPC data
 
1174
{
 
1175
   Bool ret = FALSE;
 
1176
 
 
1177
   Debug("%s: Enter.\n", __FUNCTION__);
 
1178
 
 
1179
   /*
 
1180
    * XXX: This RPC is no longer used/required - the RPC handler is left here
 
1181
    * for compatibility with older hosts.
 
1182
    */
 
1183
 
 
1184
   /*
 
1185
    * We don't have any out parameters, so we write empty values into the
 
1186
    * result fields of the RpcInData structure.
 
1187
    */
 
1188
   RPCIN_SETRETVALS(data, "", FALSE);
 
1189
 
 
1190
   // Set our return value and return to the caller.
 
1191
   ret = TRUE;
 
1192
 
 
1193
   Debug("%s: Exit.\n", __FUNCTION__);
 
1194
   return ret;
 
1195
}
 
1196
 
 
1197
 
 
1198
/*
 
1199
 *-----------------------------------------------------------------------------
 
1200
 *
 
1201
 * GHITcloTrayIconSendEvent --
 
1202
 *
 
1203
 *      Send a mouse or keyboard event to a tray icon.
 
1204
 *
 
1205
 * Results:
 
1206
 *      TRUE on success, FALSE on failure.
 
1207
 *
 
1208
 * Side effects:
 
1209
 *      XXX.
 
1210
 *
 
1211
 *-----------------------------------------------------------------------------
 
1212
 */
 
1213
 
 
1214
gboolean
 
1215
GHITcloTrayIconSendEvent(RpcInData *data) // IN/OUT: XXX
 
1216
{
 
1217
   Bool ret = FALSE;
 
1218
   GHITrayIconEventV1 *v1ptr = NULL;
 
1219
   GHITrayIconEvent eventMsg;
 
1220
 
 
1221
   memset(&eventMsg, 0, sizeof eventMsg);
 
1222
   Debug("%s: Enter.\n", __FUNCTION__);
 
1223
 
 
1224
   /* Check our arguments. */
 
1225
   ASSERT(data);
 
1226
   ASSERT(data->name);
 
1227
   ASSERT(data->argsSize > 0);
 
1228
 
 
1229
   if (!(data && data->name && data->argsSize > 0)) {
 
1230
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
1231
      return FALSE;
 
1232
   }
 
1233
 
 
1234
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
 
1235
         __FUNCTION__, data->name, data->argsSize);
 
1236
 
 
1237
   /*
 
1238
    * Deserialize the XDR data. Note that the data begins with args + 1 since
 
1239
    * there is a space between the RPC name and the XDR serialization.
 
1240
    */
 
1241
   if (!XdrUtil_Deserialize((char *)data->args + 1, data->argsSize - 1,
 
1242
                            (void *)xdr_GHITrayIconEvent, &eventMsg)) {
 
1243
      Debug("%s: Failed to deserialize data\n", __FUNCTION__);
 
1244
      ret = RPCIN_SETRETVALS(data, "Failed to deserialize data.", FALSE);
 
1245
      goto exit;
 
1246
   }
 
1247
   ASSERT(eventMsg.ver == GHI_TRAY_ICON_EVENT_V1);
 
1248
   v1ptr = eventMsg.GHITrayIconEvent_u.trayIconEventV1;
 
1249
 
 
1250
   /* Call the platform implementation of our RPC. */
 
1251
   ret = GHI_TrayIconSendEvent(v1ptr->iconID,
 
1252
                               v1ptr->event,
 
1253
                               v1ptr->x,
 
1254
                               v1ptr->y);
 
1255
 
 
1256
   if (ret == FALSE) {
 
1257
      Debug("%s: RPC failed.\n", __FUNCTION__);
 
1258
      RPCIN_SETRETVALS(data, "RPC failed", FALSE);
 
1259
   } else {
 
1260
      /*
 
1261
       * We don't have any out parameters, so we write empty values into the
 
1262
       * result fields of the RpcInData structure.
 
1263
       */
 
1264
      RPCIN_SETRETVALS(data, "", TRUE);
 
1265
 
 
1266
      /* Set our return value and return to the caller. */
 
1267
      ret = TRUE;
 
1268
   }
 
1269
 
 
1270
exit:
 
1271
   VMX_XDR_FREE(xdr_GHITrayIconEvent, &eventMsg);
 
1272
   Debug("%s: Exit.\n", __FUNCTION__);
 
1273
   return ret;
 
1274
}
 
1275
 
 
1276
 
 
1277
/*
 
1278
 *-----------------------------------------------------------------------------
 
1279
 *
 
1280
 * GHITclOTrayIconStartUpdates --
 
1281
 *
 
1282
 *      Start sending tray icon updates to the VMX.
 
1283
 *
 
1284
 * Results:
 
1285
 *      TRUE on success, FALSE on failure.
 
1286
 *
 
1287
 * Side effects:
 
1288
 *      XXX.
 
1289
 *
 
1290
 *-----------------------------------------------------------------------------
 
1291
 */
 
1292
 
 
1293
gboolean
 
1294
GHITcloTrayIconStartUpdates(RpcInData *data) // IN/OUT: XXX
 
1295
{
 
1296
   Bool ret = FALSE;
 
1297
 
 
1298
   Debug("%s: Enter.\n", __FUNCTION__);
 
1299
 
 
1300
   /* Check our arguments. */
 
1301
   ASSERT(data);
 
1302
   ASSERT(data->name);
 
1303
 
 
1304
   if (!(data && data->name)) {
 
1305
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
1306
      goto exit;
 
1307
   }
 
1308
 
 
1309
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
 
1310
         __FUNCTION__, data->name, data->argsSize);
 
1311
 
 
1312
   if (!GHI_TrayIconStartUpdates()) {
 
1313
      Debug("%s: Failed to start tray icon updates.\n", __FUNCTION__);
 
1314
      RPCIN_SETRETVALS(data, "Failed to start tray icon updates", FALSE);
 
1315
      goto exit;
 
1316
   }
 
1317
 
 
1318
   /*
 
1319
    * Write the result into the RPC out parameters.
 
1320
    */
 
1321
   ret = RPCIN_SETRETVALS(data, "", TRUE);
 
1322
 
 
1323
exit:
 
1324
   Debug("%s: Exit.\n", __FUNCTION__);
 
1325
   return ret;
 
1326
}
 
1327
 
 
1328
 
 
1329
/*
 
1330
 *-----------------------------------------------------------------------------
 
1331
 *
 
1332
 * GHITcloTrayIconStopUpdates --
 
1333
 *
 
1334
 *      Stop sending tray icon updates to the VMX.
 
1335
 *
 
1336
 * Results:
 
1337
 *      TRUE on success, FALSE on failure.
 
1338
 *
 
1339
 * Side effects:
 
1340
 *      XXX.
 
1341
 *
 
1342
 *-----------------------------------------------------------------------------
 
1343
 */
 
1344
 
 
1345
gboolean
 
1346
GHITcloTrayIconStopUpdates(RpcInData *data) // IN/OUT:
 
1347
{
 
1348
   Bool ret = FALSE;
 
1349
 
 
1350
   Debug("%s: Enter.\n", __FUNCTION__);
 
1351
 
 
1352
   /* Check our arguments. */
 
1353
   ASSERT(data);
 
1354
   ASSERT(data->name);
 
1355
 
 
1356
   if (!(data && data->name)) {
 
1357
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
1358
      goto exit;
 
1359
   }
 
1360
 
 
1361
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
 
1362
         __FUNCTION__, data->name, data->argsSize);
 
1363
 
 
1364
   if (!GHI_TrayIconStopUpdates()) {
 
1365
      Debug("%s: Failed to start tray icon updates.\n", __FUNCTION__);
 
1366
      RPCIN_SETRETVALS(data, "Failed to start tray icon updates", FALSE);
 
1367
      goto exit;
 
1368
   }
 
1369
 
 
1370
   /*
 
1371
    * Write the result into the RPC out parameters.
 
1372
    */
 
1373
   ret = RPCIN_SETRETVALS(data, "", TRUE);
 
1374
 
 
1375
exit:
 
1376
   return ret;
 
1377
}
 
1378
 
 
1379
 
 
1380
/*
 
1381
 *-----------------------------------------------------------------------------
 
1382
 *
 
1383
 * GHISendTrayIconUpdateRPC --
 
1384
 *
 
1385
 *      Send the ghi.guest.trayIcon.update RPC to the host.
 
1386
 *
 
1387
 * Results:
 
1388
 *      TRUE if sent, FALSE otherwise.
 
1389
 *
 
1390
 * Side effects:
 
1391
 *      XXX.
 
1392
 *
 
1393
 *-----------------------------------------------------------------------------
 
1394
 */
 
1395
 
 
1396
Bool
 
1397
GHISendTrayIconUpdateRpc(XDR *xdrs) // XXX
 
1398
{
 
1399
   Bool ret = FALSE;
 
1400
   DynBuf outBuf;
 
1401
 
 
1402
   Debug("%s: Enter.\n", __FUNCTION__);
 
1403
 
 
1404
   /* Check our arguments. */
 
1405
   ASSERT(xdrs);
 
1406
   if (NULL == xdrs) {
 
1407
      Debug("%s: Invalid parameter.\n", __FUNCTION__);
 
1408
      goto exit;
 
1409
   }
 
1410
 
 
1411
   /* Append our RPC name and a space to the DynBuf. */
 
1412
   DynBuf_Init(&outBuf);
 
1413
   if (!DynBuf_Append(&outBuf,
 
1414
                      GHI_RPC_TRAY_ICON_UPDATE,
 
1415
                      strlen(GHI_RPC_TRAY_ICON_UPDATE))) {
 
1416
      Debug("%s: Failed to append RPC name to DynBuf.\n", __FUNCTION__);
 
1417
      goto exit;
 
1418
   }
 
1419
 
 
1420
   if (!DynBuf_Append(&outBuf, " ", 1)) {
 
1421
      Debug("%s: Failed to append space to DynBuf.\n", __FUNCTION__);
 
1422
      goto exit;
 
1423
   }
 
1424
 
 
1425
   /* Append the XDR serialized data to the DynBuf. */
 
1426
   if (!DynBuf_Append(&outBuf, DynXdr_Get(xdrs), xdr_getpos(xdrs)) )
 
1427
   {
 
1428
      Debug("%s: Failed to append XDR serialized data to DynBuf.\n",
 
1429
            __FUNCTION__);
 
1430
      goto exit;
 
1431
   }
 
1432
 
 
1433
   if (!RpcOut_SendOneRaw(DynBuf_Get(&outBuf),
 
1434
                          DynBuf_GetSize(&outBuf),
 
1435
                          NULL,
 
1436
                          NULL)) {
 
1437
      Debug("%s: Failed to send RPC to host!\n", __FUNCTION__);
 
1438
      goto exit;
 
1439
   }
 
1440
 
 
1441
   ret = TRUE;
 
1442
 
 
1443
exit:
 
1444
   DynBuf_Destroy(&outBuf);
 
1445
   Debug("%s: Exit.\n", __FUNCTION__);
 
1446
   return ret;
 
1447
}
 
1448
 
 
1449
 
 
1450
/*
 
1451
 *-----------------------------------------------------------------------------
 
1452
 *
 
1453
 * GHITcloSetFocusedWindow --
 
1454
 *
 
1455
 *      Set the specified window to be focused (NULL or zero window ID indicates
 
1456
 *      that no window should be focused).
 
1457
 *
 
1458
 * Results:
 
1459
 *      TRUE on success, FALSE otherwise.
 
1460
 *
 
1461
 * Side effects:
 
1462
 *      XXX.
 
1463
 *
 
1464
 *-----------------------------------------------------------------------------
 
1465
 */
 
1466
 
 
1467
gboolean
 
1468
GHITcloSetFocusedWindow(RpcInData *data)
 
1469
{
 
1470
   Bool ret = FALSE;
 
1471
   XDR xdrs;
 
1472
 
 
1473
   Debug("%s: Enter.\n", __FUNCTION__);
 
1474
 
 
1475
   /* Check our arguments. */
 
1476
   ASSERT(data);
 
1477
   ASSERT(data->name);
 
1478
 
 
1479
   if (!(data && data->name)) {
 
1480
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
1481
      goto exit;
 
1482
   }
 
1483
 
 
1484
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
 
1485
         __FUNCTION__, data->name, data->argsSize);
 
1486
 
 
1487
   /*
 
1488
    * Build an XDR stream from the argument data.
 
1489
    *
 
1490
    * Note that the argument data begins with args + 1 since there is a space
 
1491
    * between the RPC name and the XDR serialization.
 
1492
    */
 
1493
   xdrmem_create(&xdrs, (char*) data->args + 1, data->argsSize - 1, XDR_DECODE);
 
1494
 
 
1495
   GHISetFocusedWindow setFocusedWindowMsg;
 
1496
   GHISetFocusedWindowV1 *setFocusedWindowV1Ptr;
 
1497
 
 
1498
   memset(&setFocusedWindowMsg, 0, sizeof setFocusedWindowMsg);
 
1499
   if (!xdr_GHISetFocusedWindow((XDR *)&xdrs, &setFocusedWindowMsg)) {
 
1500
      goto exitWithXDRCleanup;
 
1501
   }
 
1502
 
 
1503
   ASSERT(setFocusedWindowMsg.ver == GHI_SET_FOCUSED_WINDOW_V1);
 
1504
   if (setFocusedWindowMsg.ver != GHI_SET_FOCUSED_WINDOW_V1) {
 
1505
      Debug("%s: Unexpected XDR version = %d\n", __FUNCTION__, setFocusedWindowMsg.ver);
 
1506
      ret = RPCIN_SETRETVALS(data,
 
1507
                             "Unexpected XDR version.",
 
1508
                             FALSE);
 
1509
      goto exitWithXDRCleanup;
 
1510
   }
 
1511
 
 
1512
   setFocusedWindowV1Ptr = setFocusedWindowMsg.GHISetFocusedWindow_u.setFocusedWindowV1;
 
1513
 
 
1514
   /* Call the platform implementation of our RPC. */
 
1515
   ret = GHI_SetFocusedWindow(setFocusedWindowV1Ptr->windowId);
 
1516
 
 
1517
   /*
 
1518
    * Write the result into the RPC out parameters.
 
1519
    */
 
1520
   ret = RPCIN_SETRETVALS(data, "", TRUE);
 
1521
 
 
1522
exitWithXDRCleanup:
 
1523
   /* Destroy the XDR stream. */
 
1524
   xdr_destroy(&xdrs);
 
1525
   VMX_XDR_FREE(xdr_GHISetFocusedWindow, &setFocusedWindowMsg);
 
1526
exit:
 
1527
   return ret;
 
1528
}
 
1529
 
 
1530
 
 
1531
/*
 
1532
 *-----------------------------------------------------------------------------
 
1533
 *
 
1534
 * GHITcloGetExecInfoHash --
 
1535
 *
 
1536
 *      Get the hash (or timestamp) of information returned by
 
1537
 *      GHITcloGetBinaryInfo.
 
1538
 *
 
1539
 * Results:
 
1540
 *      TRUE on success, FALSE on failure.
 
1541
 *
 
1542
 * Side effects:
 
1543
 *      None.
 
1544
 *
 
1545
 *-----------------------------------------------------------------------------
 
1546
 */
 
1547
 
 
1548
gboolean
 
1549
GHITcloGetExecInfoHash(RpcInData *data) // IN/OUT:
 
1550
{
 
1551
   Bool ret = TRUE;
 
1552
   GHIGetExecInfoHashRequest requestMsg;
 
1553
   GHIGetExecInfoHashReply replyMsg;
 
1554
   XDR xdrs;
 
1555
   GHIGetExecInfoHashRequestV1 *requestV1;
 
1556
   GHIGetExecInfoHashReplyV1 replyV1;
 
1557
   char *execHash = NULL;
 
1558
 
 
1559
   memset(&requestMsg, 0, sizeof requestMsg);
 
1560
   memset(&replyMsg, 0, sizeof replyMsg);
 
1561
 
 
1562
   /* Check our arguments. */
 
1563
   ASSERT(data);
 
1564
   ASSERT(data->name);
 
1565
   ASSERT(data->args);
 
1566
 
 
1567
   if (!(data && data->name && data->args)) {
 
1568
      Debug("%s: Invalid arguments.\n", __FUNCTION__);
 
1569
      ret = RPCIN_SETRETVALS(data, "Invalid arguments.", FALSE);
 
1570
      goto error;
 
1571
   }
 
1572
 
 
1573
   Debug("%s: Got RPC, name: \"%s\", argument length: %"FMTSZ"u.\n",
 
1574
         __FUNCTION__, data->name, data->argsSize);
 
1575
 
 
1576
   /*
 
1577
    * Deserialize the XDR data. Note that the data begins with args + 1 since
 
1578
    * there is a space between the RPC name and the XDR serialization.
 
1579
    */
 
1580
   if (!XdrUtil_Deserialize((char *)data->args + 1, data->argsSize - 1,
 
1581
                            (void *)xdr_GHIGetExecInfoHashRequest, &requestMsg)) {
 
1582
      Debug("%s: Failed to deserialize data\n", __FUNCTION__);
 
1583
      ret = RPCIN_SETRETVALS(data, "Failed to deserialize data.", FALSE);
 
1584
      goto error;
 
1585
   }
 
1586
 
 
1587
   ASSERT(requestMsg.ver == GHI_GET_EXEC_INFO_HASH_V1);
 
1588
   if (requestMsg.ver != GHI_GET_EXEC_INFO_HASH_V1) {
 
1589
      Debug("%s: Unexpected XDR version = %d\n", __FUNCTION__, requestMsg.ver);
 
1590
      ret = RPCIN_SETRETVALS(data, "Unexpected XDR version.", FALSE);
 
1591
      goto exit;
 
1592
   }
 
1593
 
 
1594
   requestV1 = requestMsg.GHIGetExecInfoHashRequest_u.requestV1;
 
1595
 
 
1596
   /*
 
1597
    * Call the platform implementation of the RPC handler.
 
1598
    */
 
1599
   if (!GHI_GetExecInfoHash(requestV1->execPath, &execHash)) {
 
1600
      ret = RPCIN_SETRETVALS(data, "Could not get executable info hash.", FALSE);
 
1601
      goto exit;
 
1602
   }
 
1603
 
 
1604
   replyV1.execHash = execHash;
 
1605
   replyMsg.ver = GHI_GET_EXEC_INFO_HASH_V1;
 
1606
   replyMsg.GHIGetExecInfoHashReply_u.replyV1 = &replyV1;
 
1607
 
 
1608
   /*
 
1609
    * Serialize the result data and return.
 
1610
    */
 
1611
   ASSERT_MEM_ALLOC(DynXdr_Create(&xdrs));
 
1612
 
 
1613
   if (!xdr_GHIGetExecInfoHashReply(&xdrs, &replyMsg)) {
 
1614
      ret = RPCIN_SETRETVALS(data, "Failed to serialize data", FALSE);
 
1615
      DynXdr_Destroy(&xdrs, TRUE);
 
1616
      goto exit;
 
1617
   }
 
1618
 
 
1619
   data->result = reinterpret_cast<char *>(DynXdr_Get(&xdrs));
 
1620
   data->resultLen = xdr_getpos(&xdrs);
 
1621
   data->freeResult = TRUE;
 
1622
 
 
1623
   /*
 
1624
    * Destroy the serialized XDR structure but leave the data buffer alone
 
1625
    * since it will be freed by the RpcIn layer.
 
1626
    */
 
1627
   DynXdr_Destroy(&xdrs, FALSE);
 
1628
 
 
1629
exit:
 
1630
   VMX_XDR_FREE(xdr_GHIGetExecInfoHashRequest, &requestMsg);
 
1631
error:
 
1632
   /* Free the memory allocated in the platform layer for the hash */
 
1633
   free(execHash);
 
1634
   return ret;
 
1635
}